Swift5.0的类扩展(extension)

625 阅读3分钟

简单认识

扩展的作用:为现有的类、结构体、枚举类型、协议添加新功能。与 OC 中的Category类似,不同的是,Swift 的扩展没有名字。关键字extension

如:

extension String {

    // 删除空格和换行符 ,返回新字符串 
    func trimmed() -> String {

        self.trimmingCharacters(in: .whitespacesAndNewlines)

    }
    
    // 删除空格和换行符(修改自身)
    mutating func trim() {

        self = self.trimmed()

    }  

}  

如果您要返回一个新值而不是就地更改它,则应该使用诸如eding的词尾

可以使用扩展向类型添加属性。但有一个规则:它们只能是计算属性,而不是存储属性。原因是添加新的存储属性会影响数据类型的实际大小。

extension String {
    var lines: [String] {

        self.components(separatedBy: .newlines)

    } 
}
 

如果我们在扩展中,实现自定义初始值设定项,那么 Swift将不会禁用自动成员初始值设定项。

extension Book {

    init(title: String, pageCount: Int) {

        self.title = title

        self.pageCount = pageCount

        self.readingHours = pageCount / 50

    }

}

符合类型可以根据需要,添加自己的sayHello()方法,但如果他们不需要 ,他们始终可以依赖我们的协议扩展中提供的方法。

它还拥有不需要访问被扩展类型源代码就能完成扩展的能力(即逆向建模)

Swift 中的扩展的作用

1、添加计算实例属性、计算类型属性; 2、定义实例方法、类方法; 3、提供新初始化器; 4、定义下标; 5、定义和使用新内嵌类型; 6、使现有的类型遵循某协议 7、扩展现有的协议 8、划分代码区域

  • 添加计算实例属性、计算类型属性
extension Double {
    var km: Double { return self * 1_000.0 }
    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

扩展可以添加新的计算属性,但不能添加存储属性,或向现有的属性 添加属性观察者。

  • 定义实例方法、类方法
Int类型添加方法repetitions
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}

3.repetitions {
    print("Hello!")
}
extension Int {
    // 平方
    mutating func square() {
        self = self * self
    }
}
var someInt = 3
someInt.square()
// someInt 现在是 9
  • 提供新初始化器
extension UIView {
    convenience init(_ ID: String){
    	super.init()
        // ...
    }
}

extension Rect {
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

通过扩展提供一个新的构造器,要确保每个通过该构造器创建的实例 都是初始化完整的。

  • 定义下标 为已有的类型添加新的下标
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}
  • 定义和使用新内嵌类型 为已有的类、结构体、枚举类型添加新的内嵌类型
extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
}
  • 使现有的类遵循某协议 如果一个类已经实现了协议的所有要求,但是还没遵守该协议,可以通过扩展来让它遵守这个协议。
protocol TestProtocol {
    func test()
}
class TestClass {
    func test() {
        print("test")
    }
}

extension TestClass : TestProtocol {

}

// 使已有的类型遵循一个或多个协议 
extension MineController: UITableViewDelegate, UITableViewDataSource {
    // implementation of protocol requirements goes here

}
  • 扩展协议 1.给一个协议提供默认实现,也间接实现“可选协议”的效果 2.给协议扩充“协议中从未声明过的方法”
protocol TestProtocol {
    func test1()
}
extension TestProtocol {
    func test1() { 
        print("TestProtocol test1")
    }
    func test2() {
        print("TestProtocol test2") 
    }
}

class TestClass : TestProtocol {

} 

var cls = TestClass()
cls.test1() // TestProtocol test1 
cls.test2() // TestProtocol test2 
var cls2: TestProtocol = TestClass() 
cls2.test1() // TestProtocol test1 
cls2.test2() // TestProtocol test2
  • where
// 只给遵守myProtocol协议的UIView添加了拓展
// 强大的协议拓展  可以给协议添加默认实现   面向协议编程的基础
extension HomeHeaderViewDelegate where Self: UIView {
    
}