闪电阅读之二:可选的字符串陷阱

前几天,我试图建立一个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)类的日志所困扰,则可以开始使用其他方法之一。


感谢您的光临! 并且,像往常一样,帮助传播信息。 ❤️👏