我正在尝试为NSURL编写一个初始化器,它可能会在失败时抛出。
我非常希望它看起来像这样。
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。
救命我找不到更好的方法。
更新
事实证明,初始化器中的自赋值适用于结构和枚举,但不适用于类。我理想代码的基础是一个结构。
不能像Objective-C那样在Swift中重新定义类(引用类型)的self
。当init
运行时,对象已经被分配。在init
中,您只需要初始化分配的对象,而不是返回不同的对象(而是nil)。此外,如果init?
失败,它会立即传播,您无法捕获nil状态。
查看"Failable Initializers"博客文章你可能认为你可以。但如果仔细观察,这篇文章只显示值类型的初始化。即Int
是struct
,而Color
是enum
。
我认为其基本原理是,在值类型中,self
是实际值,而在引用类型中,self
是指向未完全初始化的对象的特殊事物。
一种解决方法是使用@price ringo建议的工厂方法。
另一种变通方法——在这种情况下可能特别合适——是以将CCD_ 12封装在自己的CCD_。特别合适,因为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 ...
}
取决于哪一个更合适。
您是否考虑过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
}
}
}