前言
Typealias 是 Swift 中的一种特性,它允许给现有类型定义一个新的别名。用 Typealias 命名的类型不是一个新类型,它只是特定类型的语义抽象。这个功能可以使我们的代码更具可读性,更易于维护。今天来讲讲这个关键字的一些使用场景。
1. 更好的语义
可以使用 typealias 来让一个类型具有语义,使代码更有可读性,一个非常典型的例子就是 TimeInterval 类型,很多人可能还不知道,其实 TimeInterval 并不是一个新的类型,而是 Double 类型的别名,我们点开 TimeInterval 的声明文件就可以看到了:
public typealias TimeInterval = Double
用 TimeInterval 作为 Double 的别名,就让 Double 类型有了时间间隔语义。再举个例子,Kingfisher 中有个场景是把 Int 类型命名为了 CancelToken,用来记录取消任务的 token,这种做法的目的也是让类型具有语义。
public typealias CancelToken = Int
2. 降低代码复杂度,提高可读性
可以使用 typealias 来为闭包类型、函数类型等定义别名,使代码更易于理解和维护。比如有些闭包类型比较长,每次写很不方便,就可以把它定义一个别名,比如。
typealias CompletionHandler = (_ success: Bool) -> String
// 堆代码 duidaima.com
func doSomething(completion: CompletionHandler) {
// 执行一些操作
completion(true)
}
doSomething { success in
if success {
return "操作成功"
} else {
return "操作失败"
}
}
还有一些嵌套类型的情况,导致外界访问时类型名非常长,这时候也可以用 typealias 解决,比如下边这个例子:
struct MyStruct {
struct NestedStruct {
struct SuperNestedStruct {
typealias NestedType = Int
}
}
}
let value: MyStruct.NestedStruct.SuperNestedStruct.NestedType = 5
print(value) // 输出 "5"
typealias MyType = MyStruct.NestedStruct.SuperNestedStruct.NestedType
let newValue: MyType = 10
print(newValue) // 输出 "10"
3. 跨平台开发
使用 typealias 可以在不同平台之间提供不同的实现,从而简化跨平台开发的代码。比如你要开发一个框架,既支持 iOS 又支持 macOS,那么平台的差异会导致类型不同,比如颜色的类型,在 iOS 中为 UIColor,在 macOS 中为 NSColor,这时候为了简化开发流程就可以使用来简化。
#if os(macOS)
typealias Color = NSColor
#elseif os(iOS) || os(tvOS) || os(watchOS)
typealias Color = UIColor
#endif
let textColor: Color = .red
其他的控件比如 NSView、UIView,也是一样的道理。
4. 泛型类型的简化
当使用泛型类型时,可以使用 typealias 来为泛型类型定义一个更具表达力的别名,这种用法其实和第一种类似,也是提高了原类型的语义。
typealias KeyValue = Dictionary<String, Any>
func processDictionary(dict: KeyValue) {
// 处理字典
}
let dict: KeyValue = ["name": "John", "age": 30]
processDictionary(dict: dict)
5. 简化元组
元组中如果数量过多,也会导致类型非常长,这时候除了减少元素数量之外,也可以使用 typealias 为复杂元组类型定义一个更有意义的别名,从而提高代码的可读性。以 Alamofire 为例,在做身份验证时有一段使用 typealias 为元组类型定义别名的场景:
typealias ChallengeEvaluation = (disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?, error: AFError?)
open func urlSession(_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
eventMonitor?.urlSession(session, task: task, didReceive: challenge)
let evaluation: ChallengeEvaluation
switch challenge.protectionSpace.authenticationMethod {
case NSURLAuthenticationMethodHTTPBasic, NSURLAuthenticationMethodHTTPDigest, NSURLAuthenticationMethodNTLM,
NSURLAuthenticationMethodNegotiate:
evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
#if !(os(Linux) || os(Windows))
case NSURLAuthenticationMethodServerTrust:
evaluation = attemptServerTrustAuthentication(with: challenge)
case NSURLAuthenticationMethodClientCertificate:
evaluation = attemptCredentialAuthentication(for: challenge, belongingTo: task)
#endif
default:
evaluation = (.performDefaultHandling, nil, nil)
}
if let error = evaluation.error {
stateProvider?.request(for: task)?.didFailTask(task, earlyWithError: error)
}
completionHandler(evaluation.disposition, evaluation.credential)
}
它将一个元组类型 (disposition: URLSession.AuthChallengeDisposition, credential: URLCredential?, error: AFError?) 定义为 ChallengeEvaluation,以提高这个类型的可读性和可维护性。