![1306450-a02a26b3521e8b15.png](https://upload-images.jianshu.io/upload_images/1306450-a02a26b3521e8b15.png)
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
private
level
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](https://upload-images.jianshu.io/upload_images/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
dynamic
modifier 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
@objc
modifiers, 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](https://upload-images.jianshu.io/upload_images/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](https://upload-images.jianshu.io/upload_images/1306450-2a401a6eb9fb9941.png)
For this problem, there are two solutions:
- Use
@objc
attribute exposed to Objective-C method rename
![1306450-11575a389141230c.png](https://upload-images.jianshu.io/upload_images/1306450-11575a389141230c.png)
- Using the
@nonobjc
property, a method is prohibited exposed to Objective-C
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](https://upload-images.jianshu.io/upload_images/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](https://upload-images.jianshu.io/upload_images/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](https://upload-images.jianshu.io/upload_images/1306450-48493e0241032315.png)
返回类型的差别
Objective-C 中的 id
被翻译为 Swift 中的 AnyObject
![1306450-61398a3388bf99bf.png](https://upload-images.jianshu.io/upload_images/1306450-61398a3388bf99bf.png)
Objective-C 中的 BOOL
被翻译为 Swift 中的 Void
![1306450-6080fe6b2838d759.png](https://upload-images.jianshu.io/upload_images/1306450-6080fe6b2838d759.png)
闭包的使用
Objective-C 中的 NSError *
被翻译为 Swift 中的 NSError?
![1306450-82d889054adb94a8.png](https://upload-images.jianshu.io/upload_images/1306450-82d889054adb94a8.png)
在 Objective-C 中处理 Swift 方法抛出的错误
定义以下方法和错误类型:
![1306450-9fb75319a083001c.png](https://upload-images.jianshu.io/upload_images/1306450-9fb75319a083001c.png)
在 Objective-C 中调用:
![1306450-574f998de2a767c8.png](https://upload-images.jianshu.io/upload_images/1306450-574f998de2a767c8.png)
在编译时,Swift 会定义 Objective-C 需要使用的部分:
![1306450-c385d29371006f06.png](https://upload-images.jianshu.io/upload_images/1306450-c385d29371006f06.png)
处理Cocoa中的错误
感谢苹果工程师的辛勤付出,Cocoa中的很多错误类型在Swift中已经可用。
![1306450-f4ba262a7969787a.png](https://upload-images.jianshu.io/upload_images/1306450-f4ba262a7969787a.png)
已在Swift中可用的比较常见的Cocoa错误类型:
NSCocoaError
NSURLError
AVError
CKErrorCode
CLError
GKErrorCode
HMErrorCode
POSIXError
WKErrorCode
WatchKitErrorCode
为空性标注
请观察 UIView 在 Objective-C 中的定义:
![1306450-202193777a5c34f2.png](https://upload-images.jianshu.io/upload_images/1306450-202193777a5c34f2.png)
当被转换为 Swift 1.0 的代码时,结果如下:
![1306450-d17e492a90f33d68.png](https://upload-images.jianshu.io/upload_images/1306450-d17e492a90f33d68.png)
在转换的过程中,有很多信息是丢失了的。比如:哪些变量可以为nil
?
庆幸的是,Swift 1.1 中便解决了这个问题。
![1306450-92cc36453f8d06da.png](https://upload-images.jianshu.io/upload_images/1306450-92cc36453f8d06da.png)
原来,苹果在 Objective-C 中引入了 nullable
, nonnull
, null_unspecified
等修饰符来解决以上问题
![1306450-f02bdae9e1f7aeef.png](https://upload-images.jianshu.io/upload_images/1306450-f02bdae9e1f7aeef.png)
标明 Objective-C/C 指针是否可以为nil
,可以:
- 更好地表达 API 的意图
- 改善编译器的静态检查
- 提高 API 在 Swift 中的易用性
很快,在苹果的 SDK 中遍布了这些修饰符。
编译器可以抛出相关的警告,便于开发者及时发现这些问题。
![1306450-84d4f61ef67f72fc.png](https://upload-images.jianshu.io/upload_images/1306450-84d4f61ef67f72fc.png)
更新后的 SDK 代码:
![1306450-be379e03f3dadbda.png](https://upload-images.jianshu.io/upload_images/1306450-be379e03f3dadbda.png)
可以发现,苹果使用 NS_ASSUME_NONNULL_BEGIN
和 NS_ASSUME_NONNULL_END
,假设标记区域为 nonnull
。
审计区域对一些指针做出了假设:
- 单个层级的指针被假设为
nonnull
- NSError** 每个指针层级都是
nullable
然后对 nullable
和 null_unspecified
的情况进行单独标记
C 指针
![1306450-d7ee774bf16ba489.png](https://upload-images.jianshu.io/upload_images/1306450-d7ee774bf16ba489.png)
- 以双下划线为前缀的为空性修饰符可以随处使用
- 为空性修饰符放在指针符号后
这里有一个细节值得注意:
![1306450-dfca0eba9bb7c09d.png](https://upload-images.jianshu.io/upload_images/1306450-dfca0eba9bb7c09d.png)
外层指针为 __nullable
,*values 可以为 null。如果 numValues 为0, 你就可以传入 null。
![1306450-b4f8b638aabc801a.png](https://upload-images.jianshu.io/upload_images/1306450-b4f8b638aabc801a.png)
内层指针为 __nonnull
,**values 不可以为 null。你必须传入一个非 null 的数组,用于创建 CFArray。
最后,为空性修饰符已经遍布苹果的 SDK ,建议你也使用它们来改善你的 Objective-C API。
轻量级泛型
以下 Objective-C 中的数组没有标明元素类型,对应的 Swift 代码也没有标明元素类型。
![1306450-7356d1eaf7047c6b.png](https://upload-images.jianshu.io/upload_images/1306450-7356d1eaf7047c6b.png)
如果使用带有类型的集合,可以
- 提高 API 的表达力
- 使集合更易用
- 改善编译器的静态检查
![1306450-46fc1e89b3113c65.png](https://upload-images.jianshu.io/upload_images/1306450-46fc1e89b3113c65.png)
![1306450-824f73499d17b49a.png](https://upload-images.jianshu.io/upload_images/1306450-824f73499d17b49a.png)
![1306450-2a64a3e2d107213d.png](https://upload-images.jianshu.io/upload_images/1306450-2a64a3e2d107213d.png)
![1306450-f3a6ba6ffa2569c2.png](https://upload-images.jianshu.io/upload_images/1306450-f3a6ba6ffa2569c2.png)
使用方法:
- 在 < > 中指定参数类型
- 参数类型可以在这个类中尽情使用
![1306450-0b12e4f6bf2339c7.png](https://upload-images.jianshu.io/upload_images/1306450-0b12e4f6bf2339c7.png)
在 Categories 和 Extensions 中也可以使用
![1306450-d8175cd83994f0fd.png](https://upload-images.jianshu.io/upload_images/1306450-d8175cd83994f0fd.png)
这个特性支持向后兼容:
- 不需要改变运行时
- 对代码生成无任何影响
如果你不需要类型时,也可以很容易地去除它。
![1306450-d73ac9c2aa4a3a46.png](https://upload-images.jianshu.io/upload_images/1306450-d73ac9c2aa4a3a46.png)
Kindof 类型
来观察一个问题:
![1306450-9846f5a414d69445.png](https://upload-images.jianshu.io/upload_images/1306450-9846f5a414d69445.png)
编译器并不知道 view.subviews[0] 是一个 Button。
id
是很弱的API协议
![1306450-1b907465dad44334.png](https://upload-images.jianshu.io/upload_images/1306450-1b907465dad44334.png)
以上代码可以将 NSApp
定义为 id
类型。
![1306450-e8fcf793f561c4fe.png](https://upload-images.jianshu.io/upload_images/1306450-e8fcf793f561c4fe.png)
以上代码可以将 NSApp
定义为 __kindof UIApplication *
类型。
使用__kindof
可以很方便地转换父类和子类。
![1306450-686c64def2955b6c.png](https://upload-images.jianshu.io/upload_images/1306450-686c64def2955b6c.png)
还可以允许向子类发送消息
![1306450-638faafae24ea448.png](https://upload-images.jianshu.io/upload_images/1306450-638faafae24ea448.png)
__kindof
其实是更实用的id
类型
![1306450-6b838332367ca277.png](https://upload-images.jianshu.io/upload_images/1306450-6b838332367ca277.png)
![1306450-cb8493aa87ab03eb.png](https://upload-images.jianshu.io/upload_images/1306450-cb8493aa87ab03eb.png)
![1306450-d743ef501a35ee8b.png](https://upload-images.jianshu.io/upload_images/1306450-d743ef501a35ee8b.png)
什么时候在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](https://upload-images.jianshu.io/upload_images/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