闪电阅读之二:可选的字符串陷阱
前几天,我试图建立一个URL。 检查以下代码块:
初始化?(userId: String? ){
后卫userId!= nil else {return nil}
self.path =“ / user / \(userId)” self.url.appendPathComponent(self.path)
}
看起来合法吧?
假设我们将23940
作为userId
传递给此初始化程序。 根据Swift版本,路径值为:
Swift 2.x路径=“ / user / 23940”
Swift 3.x路径=“ / user / Optional(” 23940“)”
Swift 4.x路径=“ / user / Optional(” 23940“)”
微妙,但令人心碎。
首先,如果您正在处理由于某种原因仍使用Swift 2.x的超老项目,并计划进行迁移,请提防此问题。
其次,我们可以在此处使用Guard-let代替Guard-check语句来解决此问题。 但是,到处都有保护语句并不方便,尤其是当您只想打印内容时。
我创建了以下结构来克服此问题:
公共结构Printable :CustomStringConvertible {
公众让价值:T?
public init(_ value:T?){
self.value =值
}
公共变量描述:字符串{
如果让值=值{
返回字符串(描述:值)
}其他{
返回“(空)”
}
}
}
注意 :是的,我们也可以打印“ nil”而不是“(null)”,但是我认为后者更具表现力。 您始终可以选择其中一个。
只要有可选选项,只需将它们包装在一个Printable
结构中,如下所示。
self.path =“ / user / \((Printable(userId)))” //“ / user / 23940”
print(Printable(userId))//“ 23940”
或者,在更复杂的示例中:
struct用户:CustomStringConvertible {让id:字符串
让firstName:字符串?
让lastName:字符串?
var说明:字符串{
var string = id
字符串+ =“,\(Printable(firstName))”
字符串+ =“,\(Printable(lastName))”
返回字符串
}
}
让user1 =用户(
id:“ 23940”,
firstName:“Göksel”,
lastName:“Köksal”
)
让user2 =用户(
id:“ 23941”,
firstName:“Sıla”,
lastName:无
)
打印(用户1)
打印(user2)
没有Printable
结构,这些对象将在下面打印;
“ 23940,可选(”Göksel“),可选(”Köksal“)”
“ 23941,可选(”Sıla“),无”
使用Printable
,它可以打印;
“ 23940,Göksel,Köksal”
“ 23941,Sıla,(空)”
后者似乎更清洁。
全局“描述”功能
func describe (__ value:Optional )->字符串 {
切换值{
案例.some(让包裹):
返回字符串(描述:包装)
案例.none:
返回“(空)”
}
}
可选扩展
扩展名可选{
var stringValue:字符串 {
切换自我{
案例.some(让包裹):
返回字符串(描述:包装)
案例.none:
返回“(空)”
}
}
}
图片来源:AlpAvanoğlu
比较方式
var url1:URL? = URL(字符串:“ www.google.com”)
var url2:URL? =无
//`Printable`结构: print(Printable(url1))//打印“ www.google.com”
print(Printable(url2))//打印“(null)”
//`describe`全局函数: print(describe(url1))//打印“ www.google.com”
print(describe(url2))//打印“(null)”
//在`Optional`上的`stringValue`扩展名: print(url1.stringValue)//打印“ www.google.com”
print(url2.stringValue)//打印“(null)”
如果您在控制台上被诸如Optional(www.google.com)
类的日志所困扰,则可以开始使用其他方法之一。
感谢您的光临! 并且,像往常一样,帮助传播信息。 ❤️👏