我正在尝试为NSURL编写初始化程序,这可能会导致失败。
我非常希望它看起来像this。
extension NSURL {
convenience init?(string: String, throwOnNil: Bool) throws {
if let URL = NSURL(string: string) {
self = URL
} else if throwOnNil {
throw MyURLError(string: string)
} else {
return nil
}
}
}
但不再支持该语法: error: cannot assign to value: 'self' is immutable
。
该语法仅适用于struct和enum。
这是我唯一提出的问题
extension NSURL {
convenience init?(string: String, throwOnNil: Bool) throws {
if throwOnNil && NSURL(string: string) == nil {
throw MyURLError(string: string)
}
self.init(string: string)
}
}
两次构建URL。
帮助! 必须有一种我找不到的更好的方法。
更新
事实证明,初始化程序中的自我赋值适用于结构和枚举,但不适用于类。我基于理想代码的例子是一个结构。
答案 0 :(得分:2)
您不能像在Objective-C中那样在Swift中重新定义self
类(引用类型)。当init
运行时,该对象已经被分配。在init
中,您只是初始化已分配的对象,而不是返回不同的对象(但是为零)。此外,如果init?
失败,这会立即传播,你就无法捕捉到零状态。
Int
为struct
,Color
为enum
。
我认为基本原理是值类型self
是实际值,而引用类型self
是指向未完全初始化的对象的特殊事物。
一种解决方法是使用@ price-ringo建议的工厂方法。
另一种解决方法 - 在这种情况下可能特别合适 - 是
将NSURL
包装在自己的URL
结构中。特别适合,因为一个URL
应该是Swift中的值类型...示例:
struct URL {
let url : NSURL?
init(string: String) throws {
if let url = NSURL(string: string) {
self.url = url
// or extract the values and push to struct in an even more Swifty
// way
}
else {
throw URLError()
}
}
// define methods which wrap url ...
}
取决于哪一个更合适。
答案 1 :(得分:1)
您是否考虑过NSURL
上的工厂方法?它可以帮助你完成大部分工作。
extension NSURL {
static func initialize(string: String, throwOnNil: Bool) throws -> NSURL? {
if let URL = NSURL(string: string) {
return URL
} else if throwOnNil {
throw MyURLError(string: string)
} else {
return nil
}
}
}