- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
使用 Xcode 10,但没有迁移到 Swift 4.2,所以我的项目仍在使用 Swift 4.1 运行。
假设我在 Dictionary
上有以下扩展:
extension Dictionary where Key: ExpressibleByStringLiteral {
func find<T>(key: Key) -> T? {
return self[key] as? T
}
}
我使用此函数以类型安全的方式访问 hashmap 中的值,例如:
let dict: [String: Any] = ["foo": "bar"]
let foo: String? = dict.find(key: "foo") // prints "bar"
当我希望从我的 find
函数返回 Any
类型时,我的问题浮出水面,例如:
let bar: Any? = dict.find(key: "bar")
Xcode 10 之前,如果在散列映射中找不到键,这个函数过去常常向我返回简单明了的 nil
。
但是,在 Xcode 10 之后,它返回 Optional.some(nil)
。
我明白,任何类型都可以像下面这样初始化:
let foo: Any = Optional<String>.none
我想在我的情况下也会发生类似的事情。有没有人知道如何解决它并仍然从 find
函数返回 nil
?
最佳答案
这是由于有意更改 (#13910),编译器现在更保守地解包一个被转换为通用占位符类型的可选值。现在,您获得的结果与您在非通用上下文中获得的结果更加一致(有关进一步讨论,请参阅 SR-8704)。
例如:
// note the constraint `where Key : ExpressibleByStringLiteral` is needlessly restrictive.
extension Dictionary where Key : ExpressibleByStringLiteral {
func find<T>(key: Key) -> T? {
return self[key] as? T
}
}
let dict: [String: Any] = ["foo": "bar"]
let genericBar: Any? = dict.find(key: "bar")
print(genericBar as Any) // in Swift 4.1: nil, in Swift 4.2: Optional(nil)
// `T` in the above example is inferred to be `Any`.
// Let's therefore substitute `as? T` with `as? Any`.
let nonGenericBar = dict["bar"] as? Any
print(nonGenericBar as Any) // in both versions: Optional(nil)
如您所见,无论是否使用通用占位符来执行转换,您现在都会得到 Optional(nil)
,从而使行为更加一致。
为什么您最终得到 Optional(nil)
的原因是因为您正在执行有条件地转换可选值。条件转换本身会产生一个可选值以指示成功或失败,并将生成的可选值放入成功案例中会为您提供双重包装的可选值。并且由于您正在转换为 Any
,它可以表示 Optional
值,因此不需要进行解包以“适合”结果类型中的值。
如果您希望将生成的可选项展平为单独包装的可选项,您可以合并 nil
:
extension Dictionary {
func find<T>(key: Key) -> T? {
return (self[key] as? T?) ?? nil
}
}
或者在转换之前解包值,例如使用guard
:
extension Dictionary {
func find<T>(key: Key) -> T? {
guard let value = self[key] else { return nil }
return value as? T
}
}
或者,我的首选方法是使用 flatMap(_:)
:
extension Dictionary {
func find<T>(key: Key) -> T? {
return self[key].flatMap { $0 as? T }
}
}
综上所述,我经常发现 [String: Any]
的用法是一种代码味道,强烈表明应该使用更强大的类型。除非键真的可以是任意字符串(而不是一组固定的静态已知键),并且值真的可以是特定键的任何类型——几乎当然,您可以使用更好的类型来对数据建模。
关于swift - iOS 12 SDK 通用函数返回 Optional.some(nil),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446097/
有没有办法在 .swift 文件(编译成 .swift 模块)中声明函数,如下所示: 你好.swift func hello_world() { println("hello world")
我正在尝试使用 xmpp_messenger_ios 和 XMPPFramework 在 iOS 上执行 MUC 这是加入房间的代码。 func createOrJoinRoomOnXMPP()
我想在我的应用程序上创建一个 3D Touch 快捷方式,我已经完成了有关快捷方式本身的所有操作,它显示正确,带有文本和图标。 当我运行这个快捷方式时,我的应用程序崩溃了,因为 AppDelegate
我的代码如下: let assetTag = Expression("asset_tag") let query2 = mdm.select(mdm[assetTag],os, mac, lastRe
我的 swift 代码如下所示 Family.arrayTuple:[(String,String)]? = [] Family.arrayTupleStorage:String? Family.ar
这是我的 JSON,当我读取 ord 和 uniq 数据时出现错误 let response2 : [String: Any] = ["Response":["status":"SUCCESS","
我想将 swift 扩展文件移动到 swift 包中。但是,将文件移动到 swift 包后,我遇到了这种错误: "Type 'NSAttributedString' has no member 'ma
使用CocoaPods,我们可以设置以下配置: pod 'SourceModel', :configurations => ['Debug'] 有什么方法可以用 Swift Package Manag
我正在 Xcode 中开发一个 swift 项目。我将其称为主要项目。我大部分都在工作。我在日期选择器、日期范围和日期数学方面遇到了麻烦,因此我开始了另一个名为 StarEndDate 的项目,其中只
这是 ObjectiveC 代码: CCSprite *progress = [CCSprite spriteWithImageNamed:@"progress.png"]; mProgressBar
我正在创建一个命令行工具,在 Xcode 中使用 Swift。我想使用一个类似于 grunt 的配置文件确实如此,但我希望它是像 Swift 包管理器的 package.swift 文件那样的快速代码
我假设这意味着使用系统上安装的任何 swift 运行脚本:#!/usr/bin/swift 如何指定脚本适用的解释器版本? 最佳答案 Cato可用于此: #!/usr/bin/env cato 1.2
代码说完全没问题,没有错误,但是当我去运行模拟器的时候,会出现这样的字样: (Swift.LazyMapCollection (_base:[ ] 我正在尝试创建一个显示报价的报价应用。 这是导入
是否可以在运行 Swift(例如 Perfect、Vapor、Kitura 等)的服务器上使用 RealmSwift 并使用它来存储数据? (我正在考虑尝试将其作为另一种解决方案的替代方案,例如 no
我刚开始学习编程,正在尝试完成 Swift 编程书中的实验。 它要求““编写一个函数,通过比较两个 Rank 值的原始值来比较它们。” enum Rank: Int { case Ace = 1 ca
在您将此问题标记为重复之前,我检查了 this question 它对我不起作用。 如何修复这个错误: error: SWIFT_VERSION '5.0' is unsupported, suppo
从 Xcode 9.3 开始,我在我的模型中使用“Swift.ImplicitlyUnwrappedOptional.some”包裹了我的字符串变量 我不知道这是怎么发生的,但它毁了我的应用程序! 我
这个问题在这里已经有了答案: How to include .swift file from other .swift file in an immediate mode? (2 个答案) 关闭 6
我正在使用 Swift Package Manager 创建一个应用程序,我需要知道构建项目的配置,即 Debug 或 Release。我试图避免使用 .xcodeproj 文件。请有人让我知道这是否
有一个带有函数定义的文件bar.swift: func bar() { println("bar") } 以及一个以立即模式运行的脚本foo.swift: #!/usr/bin/xcrun s
我是一名优秀的程序员,十分优秀!