“无法覆盖已标记为不可用的'init'”可防止覆盖空init

时间:2015-09-23 20:48:51

标签: ios swift swift2

我有一种情况,我试图覆盖NSError,为我提供一个错误的实例,我将重新使用它。

我的代码一直工作,直到我更新Xcode并转换为Swift 2。

public class NAUnexpectedResponseTypeError: NSError {
    public convenience init() {
        let messasge = "The object fetched by AFNetworking was not of an expected type."
        self.init(
            domain: "MyDomain",
            code: 6782,
            userInfo: [NSLocalizedDescriptionKey: messasge]
        )
    }
}

编译器说Cannot override 'init' which has been marked unavailable。通过这样做,我能够破解它:

public class NAUnexpectedResponseTypeError: NSError {
    public class func error() -> NSError {
        let message = "The object fetched by AFNetworking was not of an expected type."
        return NAUnexpectedResponseTypeError(
            domain: "MyDomain",
            code: 6782,
            userInfo: [NSLocalizedDescriptionKey: message]
        )
    }
}

所以,我的问题是:

  1. 有没有办法在这样的情况下添加空的init方法?
  2. 如果是1,那是不是出于某种原因?
  3. 使用类方法解决此问题的方法是否适当?
  4. 编辑:

    我提出了另一种解决方法,我更喜欢使用类方法的解决方法。我仍然不高兴我不能覆盖空的init方法。

    public class NAUnexpectedResponseTypeError: NSError {
        public convenience init(message: String?) {
            var errorMessage: String
            if let message = message {
                errorMessage = message
            } else {
                errorMessage = "The object fetched by AFNetworking was not of an expected type."
            }
            self.init(
                domain: "MyDomain",
                code: 6782,
                userInfo: [NSLocalizedDescriptionKey: errorMessage]
            )
        }
    }
    

2 个答案:

答案 0 :(得分:3)

由于NSError是不可变的,因此没有理由创建相同数据的多个实例。只需创建一个单一的常量实例:

let NAUnexpectedResponseTypeError = NSError(domain: "MyDomain",
    code: 6782,
    userInfo: [NSLocalizedDescriptionKey: "The object fetched by AFNetworking was not of an expected type."]
)

如果你的情况不是常数,那么扩展而不是子类NSError几乎总是更好。例如:

extension NSError {
    class func MyError(code code:code, message: String) -> NSError {
        return NSError(domain: "MyDomain", 
                       code: code,
                       userInfo: [NSLocalizedDescriptionKey: message])
   }
}

这种扩展(作为一个类别)在ObjC中有很长的历史,是一个很好的模式带给Swift(如果你不能轻易使用enum ErrorTypes,哪个更好Swift )。

在很多情况下,我发现为此设置顶级功能更容易,而不是扩展NSError。例如:

private func makeError(code code:code, message: String) -> NSError {
    return NSError(domain: "MyDomain", 
                   code: code,
                   userInfo: [NSLocalizedDescriptionKey: message])
}

(当我必须使用NSError时,我个人在Swift中一直使用这些功能。在ObjC中,我通常使用NSError上的类别。不知道为什么我改变了,但感觉更自然。)

答案 1 :(得分:3)

你不能覆盖空的init,它被标记为不可用,因此你不应该对它做任何事情。

你确实有另一种解决方法

public class NAUnexpectedResponseTypeError: NSError {

    public convenience init(message: String = "The object fetched by AFNetworking was not of an expected type.") {
            self.init(
                domain: "MyDomain",
                code: 6782,
                userInfo: [NSLocalizedDescriptionKey: message]
        )
    }
}

我没有测试它,但它应该可以工作。

由于您使用的是swift 2.0,为什么不让您的实例符合错误类型而不是子类化NSError?它会更清洁,更具惯用性。