- delegate
- Associated Object
- Lock
- Toll-Free Bridging 和 Unmanaged
--
delegate
OC中使用delegate时候,我们用weak
修饰。一是在这个delegate实际的对象被释放时,会被重置为nil。另一个是,能够避免因为delegate不存在时候访问导致的崩溃问题。
swift中,由于protocol
可以被struct
enum
等非class
类型继承,如果设置delegate
时候使用weak
修饰。则该protocol
只能被class
继承,声明的时候需要加上关键字@objc
,或者class
,指明这个协议只能被class
继承。
@objc protocol MyProtocol {
func saySomething()
}
protocol MyProtocolNew : class {
func doSomething()
}
--
Associated Object
// 一: OC中通过runtime绑定类型给category添加属性
@implementation Student (Category)
static char *mySchool = "mySchool";
- (void)setSchool:(NSString *)school {
objc_setAssociatedObject(self, mySchool, school, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)school {
return objc_getAssociatedObject(self, mySchool);
}
@end
// 二 : swift
import ObjectiveC.runtime
//Fish 类
class Fish: NSObject {
}
//添加属性
var key : Void?
extension Fish {
var breed : String? {
set {
objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get {
return objc_getAssociatedObject(self, &key) as! String?
}
}
}
--
Lock
多线程编程中,为了安全的访问同一个资源。OC中通常用@synchronized
修饰一个变量。它实质上是调用了objc_sync
中的objc_sync_enter
和objc_sync_exit
方法,并且加入了一些异常判断。所以虽然swift中已经没有了@synchronized
,我们可以直接调用方法objc_sync_enter & objc_sync_exit
。
let obj = String()
objc_sync_enter(obj)
//do something
objc_sync_exit(obj)
//可以自己写个全局的方法,就能直接像OC一样调用方法了
func synchronized(_ lock: AnyObject, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
--
Toll-Free Bridging 和 Unmanaged
swift对Core Foundation
框架的内存管理进行了一些列的简化,降低了使用CF框架的难度。
-
对Cocoa中的Toll-Free Foundation的处理。Cocoa中大部分
NS
开头的类在CF
中都有对应的存在。在OC中ARC负责的只是NSObject的自动引用计数,因此对于CF对象无法进行内存管理。把对象在NS和CF之间转换的时候,需要向编译器说明是否转移内存的管理权。对于不涉及内存管理的转换情况,在转换的时候加上__bridge
说明,表示内存管理权不变。NSURL *fileURL = [NSURL URLWithString:@"SomeURL"]; SystemSoundID theSoundID; OSStatus error = AudioServicesCreateSystemSoundID( (__bridge CFURLRef)fileURL, &theSoundID);
swfit中,这样的转换,可以省略__bridge
import AudioToolbox
let fileURL = NSURL(string: "SomeURL")
var theSoundID: SystemSoundID = 0
AudioServicesCreateSystemSoundID(fileURL!, &theSoundID)
- OC中,不能处理CF类型的创建和释放。对于CF的API,如果名字中含有
Create
Copy
Retain
,使用完成后,需要我们调用CFRealease
是释放。但是在Swift中,不用显式的释放带有这些关键字的内容了。就是说Swift时代,CF也纳入了ARC的管理阵营。原理就是在合适的地方,系统自己给加上了CF_RETURNS_RETAINED
和CF_RETURNS_NOT_RETAINED
这样的标注。
但是有⼀点例外,那就是对于⾮系统的 CF API (⽐如你⾃⼰写的或者是第三⽅的),因为并没有强制机制要求它们⼀定遵照 Cocoa 的命名规范,所以贸然进⾏⾃动内存管理是不可⾏的。如果你没有明确地使⽤上⾯的标注来指明内存管理的⽅式的话,将这些返回 CF 对象的 API 导⼊ Swift 时,它们的类型会被对对应为 Unmanaged<T> 。