我的类有一个NSURL从字符串初始化的类型属性.该字符串在编译时已知.
要使类正常运行,必须在初始化(不是更晚)时将其设置为其预期值,因此将它定义为可选(隐式展开或其他方式)没有意义:
class TestClass: NSObject {
private let myURL:NSURL
...
Run Code Online (Sandbox Code Playgroud)
假设NSURL(string:)(返回NSURL?)如果传递了编译时已知的有效URL字符串,则永远不会失败,我可以这样做:
override init() {
myURL = NSURL(string: "http://www.google.com")!
super.init()
}
Run Code Online (Sandbox Code Playgroud)
但是,我在某种程度上对强制解包感到不舒服,并希望以某种方式保护URL初始化.如果我试试这个:
guard myURL = NSURL(string: "http://www.google.com") else {
fatalError()
}
Run Code Online (Sandbox Code Playgroud)
可选类型'NSURL?'的值 没有打开; 你的意思是用'!' 要么 '?'?
(注意:没有办法在上面的代码中添加!或?修复错误的任何地方.条件解包只发生guard let... guard var...,并且myURL已经定义)
我明白为什么失败:即使成功调用NSURL(string:)的返回(有效的)NSURL 包裹内的可选NSURL?,所以我还需要以某种方式分配给前解开它myURL(这是不可选的,因此不转让兼容原样).
我可以通过使用中间变量解决这个问题:
guard let theURL = NSURL(string: "http://www.google.com") else {
fatalError()
}
myURL = theURL
Run Code Online (Sandbox Code Playgroud)
......但这显然不是优雅的.
我该怎么办?
更新另一种不使用的guard方法是使用a switch作为Optionalenum的选项映射:
init?() {
switch URL(string: "http://www.google.com") {
case .none:
myURL = NSURL()
return nil
case let .some(url):
myURL = url
}
}
Run Code Online (Sandbox Code Playgroud)
虽然你仍然得到一个url局部变量.
原始答案
您可以将初始化程序声明为可用的初始化程序,并nil在url字符串解析失败时返回,而不是抛出致命错误.这将使客户端更清楚您的类初始化程序可能在某些时候失败.但你仍然不会摆脱guard它.
init?() {
guard let url = URL(string: "http:www.google.com") else {
// need to set a dummy value due to a limitation of the Swift compiler
myURL = URL()
return nil
}
myURL = url
}
Run Code Online (Sandbox Code Playgroud)
这在调用者方面增加了一点复杂性,因为它需要检查对象创建是否成功,但是如果对象初始化程序可能无法构造对象,则它是推荐的模式.您还需要放弃NSObject继承,因为您无法init使用可用的版本(init?)覆盖它.
您可以在Swift博客,Apple的文档或此SO问题上找到有关可用初始化程序的更多详细信息.
| 归档时间: |
|
| 查看次数: |
2899 次 |
| 最近记录: |