奇数泛型;升级到iOS 12.2(Xcode 10.2)后Swift 4.2中的可选行为
我们刚刚将Xcode更新为10.2(因此iOS 12.2 SDK),并开始看到与奇数泛型;升级到iOS 12.2(Xcode 10.2)后Swift 4.2中的可选行为,swift,generics,optional,Swift,Generics,Optional,我们刚刚将Xcode更新为10.2(因此iOS 12.2 SDK),并开始看到与Swift泛型和Optionals相关的奇怪行为。我们将Swift版本保持在4.2,因此没有Swift 5更新。唯一的变化是从Xcode 10.1更新到Xcode 10.2 下面是一个示例代码,说明了这些奇怪之处。注释显示了版本之间的更改。理想情况下,不应该有任何变化 class Phone<T> {} extension Phone { class func create(initial: T
Swift泛型
和Optionals
相关的奇怪行为。我们将Swift版本保持在4.2,因此没有Swift 5更新。唯一的变化是从Xcode 10.1更新到Xcode 10.2
下面是一个示例代码,说明了这些奇怪之处。注释显示了版本之间的更改。理想情况下,不应该有任何变化
class Phone<T> {}
extension Phone {
class func create(initial: T? = nil) -> Phone<T> {
if let _ = initial { print("Regular: Unwrapping worked.") }
return Phone()
}
}
extension Phone where T == Void {
class func create(initial: T? = nil) -> Phone<T> {
if let _ = initial { print("T == Void: Unwrapping worked.") }
return Phone()
}
}
var phone: Phone<Int?> = Phone()
var phone2: Phone<Int?> = Phone()
var phone3: Phone<Int?> = Phone()
// unwrapping works iOS 12.1, doesn't work in 12.2
phone = Phone.create(initial: Optional(nil))
// unwrapping works iOS 12.1, doesn't work in 12.2
phone2 = Phone.create(initial: Optional<Int?>(nil))
// doesn't compile in iOS 12.1, unwrapping works in iOS 12.2
phone3 = Phone.create(initial: Optional<Int>(nil))
// doesn't compile in iOS 12.1, unwrapping doesn't work in 12.2 (uses the T == Void function)
let phone4 = Phone.create(initial: Optional(nil))
class电话{}
分机{
类func create(初始值:T?=nil)->Phone{
如果让uz=initial{print(“常规:展开工作”)}
回电
}
}
T==Void的分机{
类func create(初始值:T?=nil)->Phone{
如果让{print('T==Void:Unwrapping worked.)}
回电
}
}
var phone:phone=phone()
var phone2:Phone=Phone()
var phone3:Phone=Phone()
//在iOS 12.1中展开有效,但在12.2中不起作用
phone=phone.create(首字母:可选(无))
//在iOS 12.1中展开有效,但在12.2中不起作用
phone2=Phone.create(首字母:可选(无))
//不在iOS 12.1中编译,在iOS 12.2中展开工作
phone3=Phone.create(首字母:可选(无))
//在iOS 12.1中无法编译,在12.2中无法展开(使用t==Void函数)
让phone4=Phone.create(初始值:可选(无))
我们已经阅读了Xcode 10.2的发行说明,但没有发现关于可选或泛型的任何变化。很难理解是什么导致了不同版本之间行为的变化
特别有趣的是,phone2
和phone3
的行为方式不同。上面的代码示例中几乎没有奇怪的事情发生,因此问题是是否有人知道是什么导致了此版本中的行为更改?这是因为这意味着Optional(nil)
现在被编译器视为nil as Optional
。以前使用Optional(nil)
,您会得到一个包装的nil
值,例如Int???。一些(nil)
,但是现在您只得到nil
因此,以下几点:
let phone: Phone<Int?> = Phone.create(initial: Optional(nil))
现在您正在向参数传递一个Int???.some(nil)
,展开成功
然而,我想问你为什么要首先处理双重包装的期权——我强烈建议你避免使用它们,除非绝对必要。我记得gereric optinals在4.2中改变了:不知道这是否是相对的,但我想我提到了……这太棒了@Hamish,非常感谢。我看到SE-0213在Swift 5中实现,为什么您认为我在完整的Swift 4.2代码库中看到了这一点?是时候使用苹果雷达了,还是我遗漏了什么?(我完全同意代码中的可选处理非常糟糕,这不是它应该采用的设计方式)。@Guven值得注意的是,SE-0213是在Swift 5编译器中实现的,而Swift 5编译器。似乎SE-0213的主要实现不考虑编译器正在运行的兼容模式,因此即使在SWIFT 4.2或4模式中也总是有效的。考虑到它可以巧妙地改变代码的行为,IMO认为这是错误的决定,并且应该通过版本检查来保护它。不幸的是,现在Swift 5已经发布,现在改变有点太晚了。
let phone: Phone<Int?> = Phone.create(initial: nil as Optional)
let phone: Phone<Int?> = Phone.create(initial: nil)
let phone: Phone<Int?> = Phone.create(initial: Optional.init(nil))