返回

Swift系列三十 - 从OC到Swift(二)

IOS

一、协议

1.1. 只能被class继承的协议

示例代码:

@objc protocol MyProtocol {
    func myMethod()
}

class MyClass: NSObject, MyProtocol {
    func myMethod() {
        print("Hello, world!")
    }
}

let myObject = MyClass()
myObject.myMethod() // 输出:Hello, world!

被@objc修饰的协议,还可以暴露给OC去遵守实现。

1.2. 可选协议

正常情况下,Swift中的协议是必须遵守的,否则会报错。但是,我们可以使用@optional来声明一个可选协议,这样,在遵守该协议时就可以选择性地实现协议中的方法。

示例代码:

@objc optional protocol MyOptionalProtocol {
    func myOptionalMethod()
}

class MyClass: NSObject, MyOptionalProtocol {
    func myOptionalMethod() {
        print("Hello, world!")
    }
}

let myObject = MyClass()
myObject.myOptionalMethod?() // 输出:Hello, world!

二、关联对象

关联对象是Objective-C中的一种机制,允许向对象添加额外的属性,而不会修改对象的接口。关联对象可以用于存储私有数据、实现委托模式等。

在Swift中,关联对象可以通过objc_setAssociatedObject()objc_getAssociatedObject()函数来使用。

示例代码:

class MyClass {
    var associatedObject: Any?

    func setAssociatedObject(object: Any?) {
        objc_setAssociatedObject(self, &kMyAssociatedObjectKey, object, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }

    func getAssociatedObject() -> Any? {
        return objc_getAssociatedObject(self, &kMyAssociatedObjectKey)
    }
}

let myObject = MyClass()
myObject.setAssociatedObject(object: "Hello, world!")
let associatedObject = myObject.getAssociatedObject() as? String
print(associatedObject) // 输出:Hello, world!

三、KVO

KVO(Key-Value Observing)是一种机制,允许对象观察其他对象的属性的变化。当被观察对象的属性发生变化时,观察对象将收到通知。

在Swift中,KVO可以通过addObserver(_:forKeyPath:options:context:)方法来实现。

示例代码:

class MyClass {
    @objc dynamic var myProperty: Int = 0
}

class ObserverClass {
    var myObject: MyClass

    init(myObject: MyClass) {
        self.myObject = myObject
        myObject.addObserver(self, forKeyPath: "myProperty", options: [.new, .old], context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "myProperty" {
            let oldValue = change?[.oldKey] as? Int
            let newValue = change?[.newKey] as? Int
            print("Old value: \(oldValue), new value: \(newValue)")
        }
    }
}

let myObject = MyClass()
let observer = ObserverClass(myObject: myObject)
myObject.myProperty = 10

输出:

Old value: nil, new value: 10