import UIKit
假如你正在写一个不涉及 UI 的框架,但你需要你的框架响应 iOS app 生命周期的一些通知,比如 app 完成加载、进入后台、内存不足等。而这些通知的 name
定义于 UIKit 的 UIApplication 中,如 UIKit.UIApplication.didFinishLaunchingNotification
等,因此我们需要引入 UIKit
,一个听上去涉及 UI 的模块:
import UIKit
// ...
// ...
notificationCenter.addObserver(
forName: UIApplication.didFinishLaunchingNotification
// ...
) {
// ...
}
// ...
// ...
如此,在引入 UIKit.UIApplication
的同时,我们也引入了 UIView
、UIViewController
等等的噪声。
import
参考苹果关于 import 的文档,我们实际上可以缩小 import
的效果,引入模块下的一个具体的 symbol,如 class
、var
、func
等:
import-kind → typealias | struct | class | enum | protocol | let | var | func
import class UIKit.UIApplication
// 其余仍不变
这样的话我们就不必引入 UIKit
中的其他成分了。虽然我的 Xcode 的代码补全还是乐此不疲的给我提供 UIView
等选项,但编译是不能通过的,会提示域中没有响应的 symbol。
关于 Swift Namespace
之前写过一篇关于 Swift Namespace 的文章:
孙一萌:关于 Swift Namespacezhuanlan.zhihu.com里面提到了 Module 本身也是一个 Namespace,因此 import Module
实际上就是导入 Namespace;而上述的导入 Module 下的一个 Symbol,就是导入了一个更小的 Namespace。
但 Swift 没有实际的 Namespace 对象,也没有办法显式地声明 Namespace,没有办法显式地引用一个 Namespace,这是非常严重的缺陷。经常有 Module 中存在一个与 Module 同名的 Symbol,导入后我们就没办法显式地引用 Module。
假设有一个库叫做 Cache
,它定义了一个类型叫 Cache
。我们 import Cache
之后,当前域中的、之后的所有 Cache
都指向 Cache.Cache
(即模块下的同名类型),我们再也没法引用 Cache
模块了。
如果Cache
定义了一个 Object
类型,我们当前模块里也定义有一个 Object
(这名字确实很普遍)。按规矩,我们可以用 Cache.Object
来拿到彼方的 Object
,然而,Xcode 会报错,告诉你 Cache
类型下没有 Object
(或者总之类似的报错内容),因为 Object
确实不在 Cache.Cache
下。
目前好像只有用一些奇技淫巧来绕开这个问题,比如在另一个域中导入 Cache
,然后做一些 typealias
的工作。
同时也发现 Swift 论坛已经有人开了一个相关的 pitch 了:
Pitch: Fully qualified name syntaxforums.swift.org