简体   繁体   English

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

[英]Parameterless Failable initializer for an NSObject subclass

I'd like to provide a failable initializer to an NSObject subclass for the initialization without parameters. 我想为NSObject子类提供一个可用的初始化程序,用于初始化而不带参数。 My overall goal is to return nil this class is initialized on an OS version less than 8.0. 我的总体目标是返回nil这个类在小于8.0的OS版本上初始化。

My attempt at this is below: 我的尝试如下:

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

    }
}

However this code results in the following compiler error. 但是,此代码会导致以下编译器错误。

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

Is it possible to override init() to provide a failable implementation in a subclass? 是否可以覆盖init()以在子类中提供可用的实现? Or is there a better way to achieve this goal? 或者有更好的方法来实现这一目标吗?

As you are subclassing NSObject, you cannot have a failable no-parameter initialiser as NSObject's no parameter initialiser is not failable. 由于你是NSObject的子类,你不能有一个可用的无参数初始化器,因为NSObject的无参数初始化器是不可用的。

You could create a class factory method that returns an instance or nil depending on the iOS version 您可以创建一个类工厂方法,该方法根据iOS版本返回实例或nil

Given that: 鉴于:

You can override a failable initializer with a nonfailable initializer but not the other way around. 您可以使用不可用的初始化程序覆盖可用的初始化程序,但不能反过来。

and

A failable initializer can also delegate to a nonfailable initializer. 可用的初始化程序也可以委托给不可用的初始化程序。 Use this approach if you need to add a potential failure state to an existing initialization process that does not otherwise fail. 如果您需要将潜在的故障状态添加到现有的初始化过程中,否则请使用此方法,否则该过程将失败。

(excerpts from Failable Initializers ) (摘自Failable Initializers

and taking into account that NSObject does not have a parameterless failable initializer, then no, you cannot override a non failable initializer with a failable initializer. 并且考虑到NSObject没有无参数的可用初始化器,那么不,你不能用可用的初始化器覆盖不可用的初始化器。

The only option I see is to create an initializer with a dummy parameter, like: 我看到的唯一选择是使用伪参数创建初始化程序,如:

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

and then using it as: 然后将其用作:

var myObj = MyObject(true)

or 要么

var myObj = MyObject(false)

More interestingly, assigning a default value to the dummy parameter seems to do the job pretty well: 更有趣的是, 为dummy参数分配一个默认值似乎很好地完成了这项工作:

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

var myObj = MyObject()

If you don't want to pass a 'dummy' argument, you could pass an inout error. 如果您不想传递'dummy'参数,则可以传递inout错误。 That way, you can avoid polluting the code with dummy parameters and know more about why initialization failed (if it matters). 这样,您可以避免使用虚拟参数污染代码,并了解更多有关初始化失败的原因(如果重要)。

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()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM