混用Swift和objc - 使用Cocoa
source link: https://rhetty.github.io/2017/04/10/%E6%B7%B7%E7%94%A8Swift%E5%92%8Cobjc-%E4%BD%BF%E7%94%A8Cocoa/
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.
能够在 objc 和 Swift 之间相互转换的类型称作bridged
类型,比如 Swift 中的String
可以作为NSString
传给 objc。
Foundation
Foundation 框架为程序提供了基础的功能。
Bridged 类型
详见表格
这些类型和它们对应的类型功能一样,在 Swift 中,可变性用var
和let
控制,所以不用两种类型。objc 的引用类型与它们所对应的 Swift 的值类型基本上相差NS
前缀。
在 Swift 与 objc 相互导入时,导入器会替换相关的 bridged 类型。
Renamed 类型
Swift 的 Foundation 重命名了一些类和协议,包括相关的枚举类型和常量。
一般,类都去掉了NS
前缀,也有一些特例:
- objc 特有的类或与 objc runtime 相关的类:
NSObject
,NSAutoreleasePool
,NSException
,NSProxy
- 平台特有的类:
NSBackgroundActivity
,NSUserNotification
,NSXPCConnection
- 有等价值类型的类,如 Bridged 类型所述:
NSString
,NSDictionary
,NSURL
- 没有等价类型的类,但在不久的将来会有的:
NSAttributedString
,NSRegularExpression
,NSPredicate
Foundation 框架中有很多枚举和常量,当 Swift 导入这些类型时,会把它们作为相关类的嵌套类型。如NSJSONReadingOptions
会导入为JSONSerialization.ReadingOptions
。
Strings
在 Swift 中要创建NSString
,可以用as
转型String
,也可以用字符串常量来创建。
Numbers
NSNumber
可以桥接 Swift 的数值类型,包括Int
, Double
, Bool
。
把数值类型转型为NSNumber
时,要用as?
操作符。
objc 平台相关的整形类型,如
NSUInteger
、NSInteger
,都与Int
对应。
Arrays
当桥接一个参数化的NSArray
对象时,其中的元素也会被桥接。如果没有参数化,就会桥接为类型[Any]
的数组。
可以直接用字面值定义一个NSArray
对象:
集合的桥接与数组类似,如果NSSet
没有明确参数化类型,就会桥接为Set<AnyHashable>
。
Dictionaries
为定义参数化类型的NSDictionary
桥接为[AnyHashable: Any]
。
Core Foundation
CF 类型会被导入为 Swift 类。还会提供内存管理注解,这样 Swift 就能自动管理 CF 对象的内存,包括你自己实例化的 CF 对象。In Swift, you can use each pair of toll-free bridged Foundation and Core Foundation types interchangeably. You can also bridge some toll-free bridged Core Foundation types to Swift standard library types if you cast to a bridging Foundation type first.
Remapped Types
Swift 导入 CF 类型时,编译器会重新映射这些类型的名字。从每个类型名最后移除Ref
,因为所有 Swift 类都是引用类型。
CFTypeRed
类型会重新映射为AnyObject
类型。
Memory Managed Objects
从注解过的API中返回的 CF 对象会被 Swift 自动管理内存,不需要自己调用CFRetain
, CFRelease
, CFAutorelease
。
如果你想要在你自己的 C 方法或 objc 方法中返回 CF 对象,可以用CF_RETURNS_RETAINED
、CF_RETURNS_NOT_RETAINED
宏来注解,就能自动插入内存管理语句。也可以用CF_IMPLICIT_BRIDGING_ENABLED
、CF_IMPLICIT_BRIDGING_DISABLED
宏,来包裹 C 方法声明,遵循 CF 所有权策略和命名策略,从而根据命名推断出内存管理。
Unmanaged Objects
当 Swift 导入的 API 没有注解,就不能自动管理返回的 CF 对象的内存。Swift 会将返回的 CF 对象包裹在Unmanaged<Instance>
结构中。所有间接返回的 CF 对象也是 unmanaged。如下是未注解的 C 方法:
Swift 这么导入:
当你从一个未注解的 API 收到一个非托管的对象时,要马上把它转化成一个内存管理对象。Unmanaged<Instance>
结构体提供两个方法来转化成内存管理对象——takeUnretainedValue()
和takeRetainedValue()
。这两个方法都返回原始的、解包的对象类型。
当然也可以用retain()
、release()
、autorelease()
方法来管理非托管对象,但这些方法不推荐。
Unified Logging
标准日志系统提供 API 来替代NSLog
方法。
Swift 中,可以用顶级的os_log(_:dso:log:type:_:)
方法与标准日志系统交互,在模块 os 的子模块 log 中。
用NSString
或printf
格式的字符串来格式化日志消息。
也可以明确日志的层级,如 Info、Debug、Error。
要对特定的子系统记录日志,可以创建OSLog
对象,明确子系统和分类,作为参数传给os_log
方法。
Cocoa Structures
把 Swift 代码转换回 objc 代码时,Cocoa 和 Foundation 中内置的结构体会转换为NSValue
实例。As a result, you can use an Objective-C structure from Swift in Cocoa APIs that accept only instances of reference types. This is true even though the instance’s defining type is bridged to Swift as a structure type.
下面的结构体会桥接为NSValue
:
- CATransform3D
- CLLocationCoordinate2D
- CGAffineTransform
- CGPoint
- CGRect
- CGSize
- CGVector
- CMTimeMapping
- CMTimeRange
- CMTime
- MKCoordinateSpan
- NSRange
- SCNMatrix4
- SCNVector3
- SCNVector4
- UIEdgeInsets
- UIOffset
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK