NSObject子类的无参数Failable初始值设定项

时间:2014-11-09 22:03:08

标签: ios swift

我想为NSObject子类提供一个可用的初始化程序,以便在没有参数的情况下进行初始化。我的总体目标是返回nil这个类在小于8.0的OS版本上初始化。

我的尝试如下:

class MyObject: NSObject {
    override init?() {
        super.init()
        if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
            return nil
        }

    }
}

但是,此代码会导致以下编译器错误。

Failable initializer 'init()' cannot override a non-failable initializer

是否可以覆盖init()以在子类中提供可用的实现?或者有更好的方法来实现这一目标吗?

3 个答案:

答案 0 :(得分:4)

由于你是NSObject的子类,你不能拥有一个可用的无参数初始化器,因为NSObject没有参数初始化器是不可用的。

您可以创建一个类工厂方法,该方法根据iOS版本

返回实例或nil

答案 1 :(得分:4)

鉴于:

  

您可以使用不可用的初始化程序覆盖可用的初始化程序,但不能反过来。

  

可用的初始化程序也可以委托给不可用的初始化程序。如果您需要将潜在的故障状态添加到现有的初始化过程中,请使用此方法,否则将无法失败。

(摘自Failable Initializers

并且考虑到NSObject没有无参数的可用初始值设定项,那么不能,您不能使用可用的初始化程序覆盖不可用的初始值设定项。

我看到的唯一选择是使用虚拟参数创建初始化程序,例如:

class MyObject: NSObject {
    init?(_ ignore: Bool) {
        super.init()
        if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
            return nil
        }
    }
}

然后将其用作:

var myObj = MyObject(true)

var myObj = MyObject(false)

更有趣的是,为虚拟参数分配默认值似乎很好地完成了这项工作:

class MyObject: NSObject {
    init?(_ ignore: Bool = false) {
        super.init()
        if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
            return nil
        }
    }
}

var myObj = MyObject()

答案 2 :(得分:0)

如果您不想传递'dummy'参数,则可以传递inout错误。这样,您就可以避免使用虚拟参数污染代码,并且更多地了解初始化失败的原因(如果重要的话)。

final class FailableFoo: NSObject {
    let foo: String

    enum FailableFooInitializationError: LocalizedError {
        case somethingWentWrong
    }

    required init?(error: inout Error?) {
        foo = "Foo"
        let somethingWentWrong = true
        if somethingWentWrong {
            error = FailableFooInitializationError.somethingWentWrong
            return nil
        } else {
            super.init()
        }
    }
}

final class Bar: NSObject {
    let foo: FailibleFoo?

    override init() {
        var fooInitializationError: Error? = nil
        foo = FailableFoo(error: &fooInitializationError)
        if let fooInitializationError = fooInitializationError {
            // handle init error
        }
        super.init()
    }
}