Some Objective-C APIs—like target-action—accept method or property names as parameters, then use those names to dynamically call or access the methods or properties. In Swift, you use the #selector and #keyPath expressions to represent those method or property names as selectors or key paths, respectively.
https://developer.apple.com/documentation/swift/using_objective-c_runtime_features_in_swift
一、@objc应用于函数是为了能够让函数表达为 #selector;
In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and you create them using the #selector expression.
import UIKit
class MyViewController: UIViewController {
let myButton = UIButton(frame: CGRect(x: 0, y: 0, 100, height: 50))
override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
let action = #selector(MyViewController.tappedButton)
myButton.addTarget(self, action: action, forControlEvents: .touchUpInside)
}
@objc func tappedButton(_ sender: UIButton?) {
print("tapped button")
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
二、@objc应用于变量是为了能够让变量表达为keypath字符串,进而使用kvc功能。
class Person: NSObject {
@objc var name: String
@objc var friends: [Person] = []
@objc var bestFriend: Person? = nil
init(name: String) {
self.name = name
}
}
let gabrielle = Person(name: "Gabrielle")
let jim = Person(name: "Jim")
let yuanyuan = Person(name: "Yuanyuan")
gabrielle.friends = [jim, yuanyuan]
gabrielle.bestFriend = yuanyuan
#keyPath(Person.name)
// "name"
gabrielle.value(forKey: #keyPath(Person.name))
// "Gabrielle"
#keyPath(Person.bestFriend.name)
// "bestFriend.name"
gabrielle.value(forKeyPath: #keyPath(Person.bestFriend.name))
// "Yuanyuan"
#keyPath(Person.friends.name)
// "friends.name"
gabrielle.value(forKeyPath: #keyPath(Person.friends.name))
三、@objc dynamic应用于变量是为了让变量能够使用kvo机制。
class MyObjectToObserve: NSObject {
@objc dynamic var myDate = NSDate(timeIntervalSince1970: 0) // 1970
func updateDate() {
myDate = myDate.addingTimeInterval(Double(2 << 30)) // Adds about 68 years.
}
}
class MyObserver: NSObject {
@objc var objectToObserve: MyObjectToObserve
var observation: NSKeyValueObservation?
init(object: MyObjectToObserve) {
objectToObserve = object
super.init()
observation = observe(
.objectToObserve.myDate,
options: [.old, .new]
) { object, change in
print("myDate changed from: (change.oldValue!), updated to: (change.newValue!)")
}
}
}
let observed = MyObjectToObserve()
let observer = MyObserver(object: observed)
observed.updateDate() // Triggers the observer's change handler.
// Prints "myDate changed from: 1970-01-01 00:00:00 +0000, updated to: 2038-01-19
Here’s the least you need to remember:
- @objc makes things visible to Objective-C code. You might need this for setting up target/action on buttons and gesture recognizers.
- dynamic opts into dynamic dispatch. You might need this for KVO support or if you‘re doing method swizzling.
- The only way to do dynamic dispatch currently is through the Objective-C runtime, so you must add @objc if you use dynamic.
https://www.cnblogs.com/feng9exe/p/9460336.html