(WWDC) Swift and Objective-C Interoperability



1306450-a02a26b3521e8b15.png
Xcode automatically generated based on Objective-C code Swift Code


At a Glance

  • Swift and Objective-C interaction
  • Error Handling
  • Empty of the mark
  • Lightweight Generics
  • Kindof Types of
  • to sum up



Swift and Objective-C interaction


When Swift methods exposed to the Objective-C?


NSObject base class
  • Access method control is not privatelevel
class MyController : UIViewController {
  private func refresh() {
    // ...
  }
}
  • Swift did not use characteristics
class MyController : UIViewController {
  func refresh() -> (Int, String)? {
    // ...
    return (status, response)
  }
}


Non NSObject base class
  • In complying NSObjectProtocol agreement marked @objc
class MyController : UIWebViewDelegate {
    func webViewDidStartLoad(v: UIWebView) {
        // ...
    }
}

However, when this happens, Xcode will give a warning.

1306450-2b9d7cc67dcf1467.png


Explicitly marked
  • Mark @IBOutlet, @IBAction, @NSManaged and other property to support the Interface Builder, Core Data
class MyController : UIViewController {
    @IBAction private func refresh() {
        // ...
    }
}
  • Tag dynamicmodifier to support Runtime Objective-C, showing the current value may be updated at runtime KVO
class MyController : UIViewController {
  dynamic private var title: String? {
    get { /* ... */ }
    set { /* ... */ }
  }
}
  • Tag @objcmodifiers, directly exposed to the Objective-C
class MyController : UIViewController {
    @objc private func refresh() {
        // ...
    }
}



Mark @objc, the properties will not be able to use Swift

1306450-23dce0c280c77750.png



Selector conflict



The Objective-C method name discrimination method, rather than a signature method.
So, the same name as the methods defined in Swift if need be exposed to Objective-C, it is possible to encounter an error message.

1306450-2a401a6eb9fb9941.png



For this problem, there are two solutions:

  • Use @objcattribute exposed to Objective-C method rename
1306450-11575a389141230c.png
  • Using the @nonobjcproperty, a method is prohibited exposed to Objective-C
    1306450-e906cabc4a5e936a.png



Function pointer



It is used as a callback function pointer in the C language. However, the C language function pointer can not capture state.

1306450-9d657b28d592cc00.png

self here is not captured in the function pointer in the C language, so they need another place to store the self, for later use.



1306450-ab9de420b3245db4.png

Apple introduced @convention (c) property in the Swift 2.0 to solve this problem.



Error Handling

常见的 Objective-C 错误处理方式 和 Swift 异常。

1306450-48493e0241032315.png


返回类型的差别

Objective-C 中的 id 被翻译为 Swift 中的 AnyObject

1306450-61398a3388bf99bf.png

Objective-C 中的 BOOL 被翻译为 Swift 中的 Void

1306450-6080fe6b2838d759.png


闭包的使用

Objective-C 中的 NSError * 被翻译为 Swift 中的 NSError?

1306450-82d889054adb94a8.png



在 Objective-C 中处理 Swift 方法抛出的错误



定义以下方法和错误类型:

1306450-9fb75319a083001c.png

在 Objective-C 中调用:

1306450-574f998de2a767c8.png



在编译时,Swift 会定义 Objective-C 需要使用的部分:

1306450-c385d29371006f06.png



处理Cocoa中的错误



感谢苹果工程师的辛勤付出,Cocoa中的很多错误类型在Swift中已经可用。

1306450-f4ba262a7969787a.png



已在Swift中可用的比较常见的Cocoa错误类型:

NSCocoaError 
NSURLError 
AVError 
CKErrorCode 
CLError 
GKErrorCode 
HMErrorCode 
POSIXError 
WKErrorCode 
WatchKitErrorCode



为空性标注


请观察 UIView 在 Objective-C 中的定义:

1306450-202193777a5c34f2.png

当被转换为 Swift 1.0 的代码时,结果如下:

1306450-d17e492a90f33d68.png

在转换的过程中,有很多信息是丢失了的。比如:哪些变量可以为nil
庆幸的是,Swift 1.1 中便解决了这个问题。

1306450-92cc36453f8d06da.png



原来,苹果在 Objective-C 中引入了 nullable, nonnull, null_unspecified等修饰符来解决以上问题

1306450-f02bdae9e1f7aeef.png



标明 Objective-C/C 指针是否可以为nil,可以:

  • 更好地表达 API 的意图
  • 改善编译器的静态检查
  • 提高 API 在 Swift 中的易用性



很快,在苹果的 SDK 中遍布了这些修饰符。
编译器可以抛出相关的警告,便于开发者及时发现这些问题。

1306450-84d4f61ef67f72fc.png



更新后的 SDK 代码:

1306450-be379e03f3dadbda.png



可以发现,苹果使用 NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END,假设标记区域为 nonnull

审计区域对一些指针做出了假设:

  • 单个层级的指针被假设为 nonnull
  • NSError** 每个指针层级都是 nullable

然后对 nullablenull_unspecified 的情况进行单独标记



C 指针
1306450-d7ee774bf16ba489.png
  • 以双下划线为前缀的为空性修饰符可以随处使用
  • 为空性修饰符放在指针符号后



这里有一个细节值得注意:

1306450-dfca0eba9bb7c09d.png

外层指针为 __nullable,*values 可以为 null。如果 numValues 为0, 你就可以传入 null。

1306450-b4f8b638aabc801a.png

内层指针为 __nonnull,**values 不可以为 null。你必须传入一个非 null 的数组,用于创建 CFArray。



最后,为空性修饰符已经遍布苹果的 SDK ,建议你也使用它们来改善你的 Objective-C API。



轻量级泛型



以下 Objective-C 中的数组没有标明元素类型,对应的 Swift 代码也没有标明元素类型。

1306450-7356d1eaf7047c6b.png



如果使用带有类型的集合,可以

  • 提高 API 的表达力
  • 使集合更易用
  • 改善编译器的静态检查
1306450-46fc1e89b3113c65.png
1306450-824f73499d17b49a.png
1306450-2a64a3e2d107213d.png
1306450-f3a6ba6ffa2569c2.png



使用方法:

  • 在 < > 中指定参数类型
  • 参数类型可以在这个类中尽情使用
1306450-0b12e4f6bf2339c7.png

在 Categories 和 Extensions 中也可以使用

1306450-d8175cd83994f0fd.png



这个特性支持向后兼容:

  • 不需要改变运行时
  • 对代码生成无任何影响


如果你不需要类型时,也可以很容易地去除它。

1306450-d73ac9c2aa4a3a46.png



Kindof 类型



来观察一个问题:

1306450-9846f5a414d69445.png

编译器并不知道 view.subviews[0] 是一个 Button。


id 是很弱的API协议



1306450-1b907465dad44334.png

以上代码可以将 NSApp 定义为 id 类型。



1306450-e8fcf793f561c4fe.png

以上代码可以将 NSApp 定义为 __kindof UIApplication * 类型。



使用__kindof 可以很方便地转换父类和子类。

1306450-686c64def2955b6c.png



还可以允许向子类发送消息

1306450-638faafae24ea448.png



__kindof其实是更实用的id类型

1306450-6b838332367ca277.png
使用 id 约束返回值
1306450-cb8493aa87ab03eb.png
使用 __kindof 约束返回值
1306450-d743ef501a35ee8b.png
使用 __kindof 约束集合的元素类型


什么时候在API中使用 id



多数惯用情况下,id 可以被更准确的类型替代:

  • 返回 self 的方法可以使用 instancetype
  • 多数集合使用场景可以对元素类型进行约束
  • __kindof X * It can be used to express a subclass of class X
  • For compliance SomeProtocol protocol type, use id <SomeProtocol>



You only need to indicate when to use any type of object id. such as:

1306450-250c1bcb5444ee95.png



to sum up



Swift and Objective-C co-evolved to better collaborate

  • Xcode allows you to switch between these two languages ​​at ease in



Let your Objective-C code with the times

  • Objective-C can enhance the expressive power of the new features of the API
  • With a stronger type of security check, you can quickly discover the problem
  • Let your Objective-C code in a more elegant interface Swift





References:
Swift in Objective-C and Interoperability




Reproduced, please indicate the source , thank you ~

Reproduced in: https: //www.jianshu.com/p/70cbad6eee3a

Guess you like

Origin blog.csdn.net/weixin_33836874/article/details/91327781