Swift3、4中的@objc、@objcMembers和dynamic

栏目: Objective-C · 发布时间: 7年前

内容简介:Objective-C 对象是基于运行时的,方法或属性使用动态派发 ,在运行调用时再决定实际调用的具体实现。而 Swift 为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift 类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以直接使用。Objective-C 中所有类都继承自Swift4 后继承自

Objective-C 对象是基于运行时的,方法或属性使用动态派发 ,在运行调用时再决定实际调用的具体实现。而 Swift 为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift 类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以直接使用。

Objective-C 中所有类都继承自 NSObject ,Swift 中的类如果要供 Objective-C 调用,必须也继承自 NSObject

@objc

  1. @objc 修饰符的根本目的是用来暴露接口给 Objective-C 的运行时(类、协议、属性和方法等)

  2. 添加 @objc 修饰符并不意味着这个方法或者属性会采用 Objective-C 的方式变成动态派发,Swift 依然可能会将其优化为静态调用

  3. @objc 修饰符的隐式添加:

    • Swift 3 中继承自 NSObject 的类,不需要手动添加 @objc ,编译器会给所有的非 private 的类和成员加上 @objcprivate 接口想要暴露给 Objective-C 需要 @objc 的修饰

      button.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
      @objc private func backButtonTapped() { }
      func backButtonTapped() { }
      复制代码
    • Swift 4 中继承自 NSObject 的类的隐式 @objc 自动添加,只会发生在以下四种情况:

      • 重写了父类的 Objective-C 方法
      • 实现了一个 Objective-C 的协议
      • @IBAction@IBOutlet 关键字的修饰
      • @NSManaged 关键字的修饰
  4. 使用 @objc 可以修改 Swift 接口暴露到 Objective-C 后的名字

    @objc(Squirrel)
    class Белка: NSObject {
        @objc(color)
        var цвет: Цвет = .Красный
    
        @objc(hideNuts:inTree:)
        func прячьОрехи(количество: Int, вДереве дерево: Дерево) { }
    }
    复制代码

@objcMembers

Swift4 后继承自 NSObject 的类不再隐式添加 @objc 关键字,但在某些情况下非常依赖 Objective-C 的运行时(如 XCTest),所以在 Swift4 中提供了 @objcMembers 关键字,对类和子类、扩展和子类扩展重新启用 @objc 推断。

@objcMembers
class MyClass : NSObject {
  func foo() { }             // implicitly @objc

  func bar() -> (Int, Int)   // not @objc, because tuple returns
      // aren't representable in Objective-C
}

extension MyClass {
  func baz() { }   // implicitly @objc
}

class MySubClass : MyClass {
  func wibble() { }   // implicitly @objc
}

extension MySubClass {
  func wobble() { }   // implicitly @objc
}
复制代码

使用 @objc@nonobjc 可以指定开启或关闭某一 extension 中的所有方法的 @objc 推断。

class SwiftClass { }

@objc extension SwiftClass {
  func foo() { }            // implicitly @objc
  func bar() -> (Int, Int)  // error: tuple type (Int, Int) not
      // expressible in @objc. add @nonobjc or move this method to fix the issue
}

@objcMembers
class MyClass : NSObject {
  func wibble() { }    // implicitly @objc
}

@nonobjc extension MyClass {
  func wobble() { }    // not @objc, despite @objcMembers
}
复制代码

dynamic

当前 Swift 的动态性依赖于 Objective-C,Swift3 中 dynamic 就隐式包含了 @objc 的意思,但考虑到以后版本的 Swift 语言和运行时将会自支持 dynamic 而不再依赖于 Objective-C,所以在 Swift4 中将 dynamic@objc 含义进行了抽离。

class MyClass {
  dynamic func foo() { }       // error: 'dynamic' method must be '@objc'
  @objc dynamic func bar() { } // okay
}
复制代码

参考: Limiting @objc inference


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Inside Larry's and Sergey's Brain

Inside Larry's and Sergey's Brain

Richard Brandt / Portfolio / 17 Sep 2009 / USD 24.95

You’ve used their products. You’ve heard about their skyrocketing wealth and “don’t be evil” business motto. But how much do you really know about Google’s founders, Larry Page and Sergey Brin? Inside......一起来看看 《Inside Larry's and Sergey's Brain》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器