级别: ★☆☆☆☆
标签:「iOS」「Swift 5.1 」「扩展」
作者: 沐灵洛
审校: QiShare团队
扩展:在不需要访问源码的情况下,为现有的类,结构,枚举或协议类型添加了新功能。和Objective-C
的分类很类似,不同的是Swift的扩展没有名称。
Swift的扩展具备的能力:
注意:扩展可以给一个类型添加新的功能,但是不能覆盖现有功能。
Extension
语法声明扩展需要使用Extension
关键字:
extension SomeType { // 可添加扩展的功能 } 复制代码
扩展可以扩展现有类型以使其采用一个或多个协议。
extension SomeType: SomeProtocol, AnotherProtocol { // 可添加协议要求的实现 } 复制代码
注意:如果定义扩展为现有类型添加新的功能,则此新功能在所有该类型已存在的实例上都是可用的,即使实例在定义扩展之前被创建。
扩展可以添加实例计算属性和类计算属性。下例向Swift的内置Double
类型添加了五个计算实例属性作为距离单位:
extension Double { var km: Double { return self * 1_000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1_000.0 } var ft: Double { return self / 3.28084 } } let oneInch = 25.4.mm print("一英寸是 \(oneInch) 米") // Prints "一英寸是 0.0254 米" let threeFeet = 3.ft print("三英尺是 \(threeFeet) 米") // Prints "三英尺是 0.914399970739201 米" let aMarathon = 42.km + 195.m print("马拉松长 \(aMarathon) 米") // Prints "马拉松长 42195.0 米" 复制代码
注意:扩展可以添加新的计算属性,但是不能添加存储属性,也不能为现有属性添加属性观察者。
扩展可以为现有类型添加初始化方法。
扩展也可以为一个Class
类型添加新的便利初始化方法,但是不能为一个Class
类型添加新的指定初始化方法或反初始化方法。指定初始化方法或反初始化方法必须由原始的类实现。
如果使用扩展为值类型添加一个初始化方法,该值类型为其所有存储属性提供了默认值,并且没有自定义的初始化方法,则我们可以在该值类型扩展中的初始化方法里调用默认的初始化方法或调用按成员生成的初始化方法。若值类型原始实现时,提供了自定义的初始化方法,则在该值类型扩展中的初始化方法里调用其自定义的初始化方法。
注:若想自定义的值类型既能调用默认初始化又能调用成员初始化还要能调用自定义的初始化,则这个自定义的初始化方法必须写在extension
中。
如果使用扩展为声明在其他模块的结构体添加初始化方法,则新的初始化方法不能访问self
属性,直到该结构体从其定义的模块中调用了初始化方法。
struct Size { var width = 0.0, height = 0.0 } struct Point { var x = 0.0, y = 0.0 } struct Rect { var origin = Point() var size = Size() init(origi:Point,siz:Size) { origin = origi size = siz } } extension Rect { init(center:Point,size:Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origi: Point(x: originX, y: originY), siz: size) //! `Rect`原始定义中未自定义初始化方法则此处应该使用默认初始化方法或者成员初始化方法:`self.init(origin: Point(x: originX, y: originY), size: size)` } } 复制代码
扩展为现有类型添加实例方法和类方法。
extension Int { func repetitions(task: () -> Void) { for _ in 0..<self { task() } } } //调用 输出三次`Hello!` 3.repetitions { print("Hello!") } 复制代码
值类型扩展中可以添加使用mutating
修饰的实例方法,允许修改实例本身。
extension Int { mutating func square() { self = self * self } } var someInt = 3 someInt.square() // someInt : 9 复制代码
扩展可以为现有类型添加新的下标。
//倒序输出一个整型数 extension Int { subscript(digitIndex:Int)->Int { var baseNum = 1 for _ in 0..<digitIndex { baseNum *= 10 } assert(baseNum <= self, "整数的索引越界了") return (self/baseNum)%10 } } print(123456[5]) // 1 复制代码
扩展可为现有类,结构体,枚举添加新的嵌套类型。
extension Int { enum Status : String,CaseIterable { case NoAuth = "NoAuth" case RequestError = "RequestError" case None = "None" } var netStatus : String { switch self { case 401: return Status.NoAuth.rawValue case let x where x >= 500 : return Status.RequestError.rawValue default: return Status.None.rawValue } } } print(401.netStatus) //!< NoAuth print(500.netStatus) //!< RequestError print(402.netStatus) //!< None 复制代码
参考资料: swift 5.1官方编程指南
了解更多iOS及相关新技术,请关注我们的公众号:
关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)
推荐文章:
Swift 5.1 (18) - 嵌套类型 Swift 5.1 (17) - 类型转换与模式匹配 浅谈编译过程
深入理解HTTPS 浅谈 GPU 及 “App渲染流程”
iOS 查看及导出项目运行日志
Flutter Platform Channel 使用与源码分析
开发没切图怎么办?矢量图标(iconFont)上手指南
DarkMode、WKWebView、苹果登录是否必须适配?
奇舞团安卓团队——aTaller
奇舞周刊