在Swift中舱污,@objc
屬性具有多重作用,主要用于將Swift代碼與Objective-C代碼進(jìn)行互操作粱栖。以下是@objc
的主要用途:
-
暴露給Objective-C:
@objc
屬性可以將Swift類话浇、屬性、方法暴露給Objective-C代碼闹究。這對(duì)于需要調(diào)用Swift代碼或在Swift中使用Objective-C庫的情況非常有用幔崖。@objc class MyClass: NSObject { @objc var myProperty: String = "Hello, World!" @objc func myMethod() { print(myProperty) } }
-
支持KVO(鍵值觀察):
在Swift中,如果你想對(duì)一個(gè)屬性進(jìn)行鍵值觀察(Key-Value Observing, KVO)跋核,該屬性必須被標(biāo)記為@objc dynamic
岖瑰。@objc
部分使屬性可以被Objective-C看到,而dynamic
部分則啟用了動(dòng)態(tài)派發(fā)砂代,允許KVO機(jī)制正常工作蹋订。class MyObservableClass: NSObject { @objc dynamic var observedProperty: String = "Initial Value" }
-
用于選擇器(Selectors):
當(dāng)需要將Swift方法傳遞給Objective-C API(如定時(shí)器、通知中心或UI控件的目標(biāo)-動(dòng)作機(jī)制)時(shí)刻伊,需要用到選擇器(Selector)露戒。這時(shí),方法必須被標(biāo)記為@objc
捶箱。class MyClass: NSObject { @objc func handleButtonTap() { print("Button tapped!") } func setup() { let selector = #selector(handleButtonTap) // 將selector傳遞給Objective-C API } }
-
與Objective-C的協(xié)議互操作:
如果Swift類需要遵循一個(gè)Objective-C定義的協(xié)議智什,并且該協(xié)議中的方法需要在Swift中實(shí)現(xiàn),那么這些方法必須被標(biāo)記為@objc
丁屎。@objc protocol MyProtocol { @objc func doSomething() } class MyClass: NSObject, MyProtocol { @objc func doSomething() { print("Doing something!") } }
-
在Swift的枚舉上使用:
如果你希望將Swift枚舉暴露給Objective-C荠锭,你可以使用@objc
標(biāo)記枚舉,并且枚舉必須是遵循RawRepresentable
或CaseIterable
協(xié)議的整型(如Int
晨川、String
等)枚舉证九。@objc enum MyEnum: Int, CaseIterable { case case1 case case2 }
需要注意的是,@objc
標(biāo)記會(huì)增加二進(jìn)制大小并可能影響性能共虑,因?yàn)樗婕暗脚cObjective-C運(yùn)行時(shí)的交互愧怜。因此,除非確實(shí)需要妈拌,否則應(yīng)盡量避免在Swift代碼中使用@objc
拥坛。
當(dāng)需要將Swift方法傳遞給Objective-C API時(shí),需要用到選擇器(Selector)尘分。這時(shí)猜惋,方法必須被標(biāo)記為@objc。
解釋:
在iOS和macOS開發(fā)中培愁,Swift和Objective-C是兩種主要的編程語言著摔,它們可以互相調(diào)用和集成。然而竭钝,由于這兩種語言在底層實(shí)現(xiàn)和運(yùn)行時(shí)機(jī)制上有所不同梨撞,因此在進(jìn)行互操作時(shí),需要遵循一些特定的規(guī)則香罐。
當(dāng)你需要將一個(gè)Swift方法傳遞給一個(gè)Objective-C API時(shí)卧波,這個(gè)API通常期望接收一個(gè)選擇器(Selector)。選擇器是Objective-C中的一個(gè)概念庇茫,它代表了一個(gè)可以被執(zhí)行的方法的引用港粱。與直接調(diào)用方法不同,選擇器允許你在運(yùn)行時(shí)動(dòng)態(tài)地決定要調(diào)用哪個(gè)方法旦签。
由于Swift在編譯時(shí)會(huì)進(jìn)行更多的類型檢查和優(yōu)化查坪,而Objective-C則依賴于運(yùn)行時(shí)系統(tǒng)來解析方法調(diào)用,因此Swift編譯器需要知道哪些方法可能會(huì)被Objective-C代碼以這種方式調(diào)用宁炫。這就是@objc
屬性的作用偿曙。
當(dāng)你將一個(gè)Swift方法標(biāo)記為@objc
時(shí),你告訴Swift編譯器這個(gè)方法需要在Objective-C的運(yùn)行時(shí)系統(tǒng)中注冊(cè)羔巢。這樣望忆,當(dāng)Objective-C代碼通過選擇器引用該方法時(shí),運(yùn)行時(shí)系統(tǒng)能夠找到并調(diào)用它竿秆。
例如启摄,假設(shè)你有一個(gè)Swift類,它有一個(gè)方法需要被傳遞給Objective-C的UIButton
的addTarget(_:action:for:)
方法幽钢。這個(gè)方法需要接收一個(gè)選擇器作為參數(shù)歉备,該選擇器指向要執(zhí)行的方法。
class MyClass: NSObject {
// 這個(gè)方法需要被Objective-C代碼調(diào)用匪燕,因此它被標(biāo)記為@objc
@objc func buttonTapped() {
print("Button was tapped!")
}
func setupButton() {
let button = UIButton(type: .system)
// 創(chuàng)建一個(gè)選擇器蕾羊,指向buttonTapped方法
let selector = #selector(buttonTapped)
// 將按鈕的點(diǎn)擊事件與目標(biāo)(self)和選擇器關(guān)聯(lián)起來
button.addTarget(self, action: selector, for: .touchUpInside)
}
}
在這個(gè)例子中,buttonTapped
方法被標(biāo)記為@objc
谎懦,這樣它就可以在Objective-C的運(yùn)行時(shí)系統(tǒng)中被找到和調(diào)用肚豺。然后,我們使用#selector
宏來創(chuàng)建一個(gè)指向這個(gè)方法的選擇器界拦,并將其傳遞給UIButton
的addTarget(_:action:for:)
方法吸申。
總之,當(dāng)你需要將Swift方法傳遞給Objective-C API(特別是那些期望接收選擇器的API)時(shí)享甸,你需要確保該方法被標(biāo)記為@objc
截碴,以便Objective-C的運(yùn)行時(shí)系統(tǒng)能夠找到并調(diào)用它。
UIButton
是Objective-C中定義的類蛉威,那addTarget(_:action:for:)
就是Objective-C API