4

在 Swift 编程语言中,强制要求

“指定的初始化程序必须确保其类引入的所有属性在委托给超类初始化程序之前都已初始化。” 来自另一个 S/O 的报价来源

否则会显示类似以下的错误

属性“self.baz”未在 super.init 调用中初始化

我想在 Swift 中实现以下 Objective-C 代码:

@interface FooBar : NSObject

@property (nonatomic, readonly) NSString *baz;

@end

@implementataion FooBar

@synthesize baz = _baz;

- (instancetype)initWithString:(NSString *)string {
    self = [super init];
    if (self) {
        _baz = [self parseString:string];
    }
    return self;
}

- (NSString *)parseString:(NSString *)string {
    // Perform something on the original string
    return ...;
}

@end

以下实现会引发如上所述的编译器错误:

class FooBar: NSObject {
    let baz: NSString?

    init(string: NSString?) {
        super.init()
        baz = parseString(string)
    }

    private func parseString(string: NSString?) -> NSString? {
        // Perform something on the original string
        return ...;
    }
}

如果我执行以下操作,我会收到一条错误消息

在 super.init 初始化 self 之前在方法调用“parseString”中使用 self

class FooBar: NSObject {
    let baz: NSString?

    init(string: NSString?) {
        baz = parseString(string)
        super.init()
    }

    private func parseString(string: NSString?) -> NSString? {
        // Perform something on the original string
        return string;
    }
}

所以我目前的解决方案是使用私有类方法:

class FooBar: NSObject {
    let baz: NSString?

    init(string: NSString?) {
        baz = FooBar.parseString(string)
        super.init()
    }

    private class func parseString(string: NSString?) -> NSString? {
        // Perform something on the original string
        return ...;
    }
}

我的问题是是否有更好的方法来实现相同的目标,还是私有类方法是最好的方法?

4

1 回答 1

2

正如您正确提到的,编译器抱怨“在 super.init 初始化 self 之前在方法调用 'parseString' 中使用 self”。原因是编译器必须确保self在它完成初始化之前你不会访问任何东西。因为编译器不想(甚至不能)在初始化完成之前检查每个传出的方法调用,所以它只是不允许在完成之前使用任何 self 。

幸运的是,您的方法parseString不想更改或访问任何属性。因此,您可以并且应该将其设为非实例函数。如果它与 的实例无关FooBar,为什么它只能在 的实例上可用FooBar

你可以简单地把它变成一个staticorclass函数,就像你已经做的那样,这非常好。

但我会更进一步,将其完全移出FooBar. 有几个选项:

  • 创建一个Helper您将其定义为的class function
  • 创建一个Helper您将其定义为的类instance function并在您的类中创建一个Helper实例,FooBar或者创建一个全局实例并将该实例也传递给 init。
于 2015-12-27T13:12:47.837 回答