0

Swift中的@objc、@objcMembers关键字探讨

 2 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzkwMDIxNDA3NA%3D%3D&mid=2247483745&idx=1&sn=8f1db6e0a109754ed73bd3438f64285e&chksm=c0463d34f731b4222e8c238448d19e71f801b25d459b57be673305bcee2ae9cd5aa09a120f01&token=912344454&lang=zh_CN
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Swift中的@objc、@objcMembers关键字探讨

原创 剑老师 一个老码农 2021-03-02 13:01 发表于

收录于合集
#iOS开发 14 个
#Swift 9 个

我们说Objective-c是一门动态语言,决策会尽可能的推迟到运行时。而Swit是一门静态语言,也就是说Swift的对象类型、调用的方法都是在编译期就确定的,这也是为什么swift比oc性能高的原因。但是在Swift中所有继承自NSObject的类,仍然保留了Objective-c的动态性。如果想要使用它的动态性就需要加上@objc关键字,本篇文章就来讲一下,哪些情况需要用到@objc。

  1. Protocol如果是optional(非必须实现)的,必须加上@objc

  2. 利用#selector调用的方法,被调用的方法须加上@objc

  3. 使用kvc时

  4. NSPredicate筛选

  5. oc与swift混合开发,swift方法/属性需要被oc调用的,要加上@objc

  6. swift的枚举需要被oc使用的

  • Protocol如果是optional(非必须实现)的,必须加上@objc

如下,便是一段Swift的Protocol代码,如果这样写,此Protocol中的几个方法,都必须实现

protocol PlayerDelegate: class {    func playerReadyToPlay(player: CustomMediaPlayer, totalTime: Double)    func playerCacheProgress(player: CustomMediaPlayer, progress: Float)    func playerPlayProgress(player: CustomMediaPlayer, currentTime: Double)}

如果里面某些方法是非必须实现的,则需要在方法前加上@objc optional,在protocol前也需要加上@objc

@objc protocol PlayerDelegate: class {    @objc optional func playerReadyToPlay(player: CustomMediaPlayer, totalTime: Double)    @objc optional func playerCacheProgress(player: CustomMediaPlayer, progress: Float)    func playerPlayProgress(player: CustomMediaPlayer, currentTime: Double)}
  • 利用#selector调用的方法

在Swift中#selector,相当于oc中的@selector,而@selector会在运行时进行方法调用。所以在Swift中使用#selector调用方法,需要在方法前加上@objc。拿button调用方法举例:

button.addTarget(self, action: #selector(click), for: .touchUpInside)@objc private func click() {}

swift中button调用方法

  • 使用kvc时

kvc其实也是利用了oc的运行时特性,所以使用kvc也需要在属性前加上@objc,如下代码:

class People: NSObject {    @objc var name = ""    var age = 10    }///使用valueforkey获取name值let people = People()people.name = "张三"people.age = 15let name = people.value(forKey: "name")print(name)people.setValue("王麻子", forKey: "name")

使用valueforkey获取name值,或利用setvalue:forkey赋值,name前需加@objc

  • NSPredicate筛选

NSPredicate是利用对象属性的key进行筛选的属性,要加上@objc,实际上NSPredicate也是利用了对象的oc对象的kvc特性,如下代码:

///people类class People: NSObject {    @objc var name = ""    @objc var age = 0    }override func viewDidLoad() {    super.viewDidLoad()    let array = NSMutableArray()            let people1 = People()    people1.name = "张三"    people1.age = 15    array.add(people1)    let people2 = People()    people2.name = "李四"    people2.age = 18    array.add(people2)    ///找到age等于15的人,并打印名字            let predicate = NSPredicate(format: "age == %d", 15)    if let result = array.filtered(using: predicate) as? [People], result.count > 0 {        let people = result.first        print(people?.name)    }    }
  • oc与swift混合开发,swift方法/属性需要被oc调用的

oc与swift混合开发,swift方法/属性需要被oc调用的,属性或方法前需要加上@objc。

class People: NSObject {    @objc var name = ""    @objc func playGame() {        print("玩游戏")    }}

Swift类中的属性和方法加上@objc

People *people = [[People alloc] init];people.name = @"111";[people playGame];

oc中调用Swift

注:类前不需要加,只要是继承自NSObject的类,被oc调用时,系统会默认为被调用的类加为@objc。

  • oc与swift混合开发,swift的枚举需要被oc使用的

Swift的枚举被oc使用时,必须在enum前加上@objc,且Swift的枚举必须是Int类型,否则无法被oc使用

@objc enum PeopleSex: Int {    case female = 0    case male = 1}

Swift的枚举,必须是Int类型,才能被oc调用

  • @objc与@objcMembers的区别

在Swift中,继承自NSObject的类如果有比较多的属性或方法都需要加上@objc的话,会多比较多的代码。那么可以利用@objcMembers减少代码。被@objcMembers修饰的类,会默认为类、子类、类扩展和子类扩展的所有属性和方法都加上@objc。当然如果想让某一个扩展关闭@objc,则可以用@nonobjc进行修饰。

@objcMembersclass People: NSObject {    var name = ""    var age = 10    func playGame() {        print("玩游戏")    }}

我是剑老师,欢迎关注“App程序猿”

图片


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK