简体   繁体   English

升级到iOS 12.2(Xcode 10.2)后,Swift 4.2中的奇数泛型和可选行为

[英]Odd Generics & Optional Behavior in Swift 4.2 after upgrading to iOS 12.2 (Xcode 10.2)

We have just updated Xcode to 10.2 (hence iOS 12.2 SDK) and started seeing odd behavior with respect to the behavior of Swift Generics and Optionals . 我们刚刚将Xcode更新为10.2(因此是iOS 12.2 SDK),并开始看到有关Swift GenericsOptionals行为的奇怪行为。 We have kept the Swift version at 4.2, so no Swift 5 update. 我们将Swift版本保持在4.2,因此没有Swift 5更新。 The only change was updating to Xcode 10.2 from Xcode 10.1. 唯一的变化是从Xcode 10.1更新到Xcode 10.2。

Here is a sample code that illustrates the oddities. 这是一个示例代码,用于说明奇怪之处。 The comments show what has changed between versions. 评论显示版本之间发生了哪些变化。 Ideally, there shouldn't be any changes. 理想情况下,不应该有任何变化。

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))

We have gone through the release notes of Xcode 10.2 but haven't spotted any changes around Optionals or Generics. 我们已经阅读了Xcode 10.2的发行说明,但没有发现Optionals或Generics的任何变化。 It is really hard to understand what is causing this change in behavior between versions. 很难理解导致版本之间行为发生这种变化的原因。

It is especially very interesting how phone2 and phone3 behave differently. phone2phone3表现方式特别有趣。 There are few odd things happening in the code sample above, so the question is if anyone knows what might have caused the behavioral changes in this release? 上面的代码示例中发生了一些奇怪的事情,所以问题是,是否有人知道在此版本中可能导致行为更改的原因是什么?

This is due to SE-0213: Literal initialization via coercion which means that Optional(nil) is now treated as nil as Optional by the compiler. 这是由于SE-0213:通过强制进行文字初始化,这意味着编译器现在将Optional(nil)视为nil as Optional Previously with Optional(nil) , you'd get a wrapped nil value eg Int??.some(nil) , however now you get just nil . 以前使用Optional(nil) ,你会得到一个包裹的 nil值,例如Int??.some(nil) ,但现在你得到的只是nil

So for the following: 所以对于以下内容:

let phone: Phone<Int?> = Phone.create(initial: Optional(nil))

the compiler is treating it as: 编译器将其视为:

let phone: Phone<Int?> = Phone.create(initial: nil as Optional)

which is equivalent to: 这相当于:

let phone: Phone<Int?> = Phone.create(initial: nil)

Because you've specified the generic parameter T to be Int? 因为您已将通用参数T指定为Int? , the initial: parameter takes an Int?? initial:参数需要一个Int?? . Therefore by passing nil you're passing Int??.none , and therefore the unwrapping fails. 因此,通过传递nil你传递Int??.none ,因此解包失败。

One way to restore the old behaviour is to specify .init explicitly in order to force the compiler to call the initialiser: 恢复旧行为的一种方法是明确指定.init以强制编译器调用初始化器:

let phone: Phone<Int?> = Phone.create(initial: Optional.init(nil))

Now you're passing an Int??.some(nil) to the parameter and the unwrapping succeeds. 现在你传递一个Int??.some(nil)到参数并且解包成功。

However I would question why you're dealing with doubly wrapped optionals in the first place – I would strongly encourage avoiding them unless absolutely necessary. 但是我会问你为什么要首先处理双重包装的选项 - 除非绝对必要,否则我强烈建议你避免使用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 objc [29733]:Swift类的Swift类扩展和类别不允许在ios 12.2上运行+ load方法xcode 10.2 - objc[29733]: Swift class extensions and categories on Swift classes are not allowed to have +load methods xcode 10.2 running on ios 12.2 无法在新的Xcode 10.2(iOS 12.2)中构建Alamofire框架 - Unable to build Alamofire framework in new Xcode 10.2 (iOS 12.2) 从Xcode 9.4升级到Xcode 11并将Swift 3.0升级到Swift 4.2后在iOS应用中使用Realm时指针损坏 - Corrupt pointer when using Realm in iOS app after upgrading from Xcode 9.4 to Xcode 11 and Swift 3.0 to Swift 4.2 当键盘为numberPad,phonePad或decimalPad(iOS 12.2,Xcode 10.2)时,应用程序崩溃 - App crashes when keyboard is numberPad, phonePad or decimalPad (iOS 12.2, Xcode 10.2) Xcode 10.2中的Realm Swift-错误:Swift 5.0编译器无法导入使用Swift 4.2编译的模块 - Realm Swift in Xcode 10.2 - ERROR: Module compiled with Swift 4.2 cannot be imported by the Swift 5.0 compiler 在Xcode 10.2上的Swift4.2中插入NSManagedObject后,我立即收到Xcode构建错误。 - I am getting Xcode build errors as soon as I insert NSManagedObject in Swift4.2 on Xcode 10.2 自定义类不会自动显示 - Swift 3 iOS 10.2 Xcode 8 - Custom class not automatically showing up - Swift 3 iOS 10.2 Xcode 8 Xcode 10.2 iOS Swift (+ React Native) 项目编译错误 - Xcode 10.2 iOS Swift (+ React Native) project compilation error 更新到Xcode 10.2 / Swift 5后无法构建macOS项目 - Can't build macOS project after updating to Xcode 10.2/Swift 5 更新到Xcode 10.2 beta 3后启动应用程序时出现Swift错误 - Swift error while starting app, after update to Xcode 10.2 beta 3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM