在Swift类的指定初始值设定项中调用实例方法

时间:2015-12-27 12:57:25

标签: objective-c swift designated-initializer code-migration

在Swift编程语言中,必须

  

“指定的初始化程序必须确保在委托一个超类初始化程序之前初始化其类引入的所有属性。”source of quote from another 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 ...;
    }
}

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

1 个答案:

答案 0 :(得分:2)

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

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

您可以简单地将它设为staticclass功能,这非常好。

但我会更进一步将其完全移出FooBar。有几种选择:

  • 创建一个类Helper,您可以将其定义为class function
  • 创建一个类Helper,您可以在其中将其定义为instance function并在类Helper中创建一个FooBar实例,或创建一个全局实例并在init中传递该实例同样。