OC系统库包含相当多的collection类,其中各种数组、字典、set。CoreFoundation框架也定义了一套C语言的API,操作这些collection及数据结构。Foundation中的NSArray和CoreFoundation中的CFArray是等价的。两种创建数组的方式可能有区别,“无缝桥接”技术可以在两个类型之间转换。
比如,使用Foundation框架中的字典对象时会遇到一个问题,键的语义是“拷贝”,值得语义是“保留”。CoreFoundation框架中的字典类型叫做CFDictionary。可变字典为CFMutableDictionary。通过下列方法指定键和值的内存管理语义。
第二个参数定义了字典的初始大小。
最后两个参数定义了很多回调函数,指示key和value在各种情况下应该执行的操作。两个参数都是结构体指针。
前面说过,在向NSMutableDictionary中加数键和值时,如果用作键的对象不支持拷贝操作,编译器会报错,“所属对象的类不支持NSCopying协议,因为copyWithZone:方法未实现”。可以直接在CoreFoundation创建字典~~
总结:
1.无缝桥接技术,可以在Foundation框架中的OC对象和CoreFoundation框架中的C语言数据结构之间来回转换。
2.CoreFoundation创建collection,可以指定很多回调函数,表示在各种情况下的操作,然后无缝桥接转换成OC对象使用。
CFArray要通过CFArrayRef来引用,而这是指向struct__CFArray的指针。CFArrayGetCount这种函数可以操作此struct,来获取数组大小。
-(void)demo1{
NSArray *anArray = @[@1,@2,@3,@4,@5];
CFArrayRef aCFArray = (__bridge CFArrayRef)anArray;
NSLog(@"Size of array = %li", CFArrayGetCount(aCFArray));
}
__brifge的意思是,ARC依然有这个OC对象的所有权。而__bridge_retained意思是ARC将交出对象的所有权。若用后者,上面代码的后面要加上CFRelease释放内存。返现转换通过__bridge_transfer来实现,想把CFArrayRef转换为NSArray*令ARC获得对象所有权。
比如,使用Foundation框架中的字典对象时会遇到一个问题,键的语义是“拷贝”,值得语义是“保留”。CoreFoundation框架中的字典类型叫做CFDictionary。可变字典为CFMutableDictionary。通过下列方法指定键和值的内存管理语义。
-(void)demo2{
CFMutableDictionaryRef CFDictionaryCreateMutable(
CFAllocatorRef allocator,
CFIndex capacity,
const CFDictionaryKeyCallBacks *keyCallBcaks,
const CFDictionaryValueCallBacks *valueCallBacks
);
}
首个参数表示使用的内存分配器,通常传入NULL表示采用默认分配器。
第二个参数定义了字典的初始大小。
最后两个参数定义了很多回调函数,指示key和value在各种情况下应该执行的操作。两个参数都是结构体指针。
-(void)demo3{
struct CFDictionaryKeyCallBacks{
CFIndex version;
CFDictionaryRetainCallBack retain;
CFDictionaryReleaseCallBack release;
CFDictionaryCopyDescriptionCallBack copyDescription;
CFDictionaryEqualCallBack equal;
CFDictionaryHashCallBack hash;
};
struct CFDictionaryValueCallBacks{
CFIndex version;
CFDictionaryRetainCallBack retain;
CFDictionaryReleaseCallBack release;
CFDictionaryCopyDescriptionCallBack copyDescription;
CFDictionaryEqualCallBack equal;
};
}
如果字典中加入了新的键和值,机会调用retain函数
-(void)demo4{
typedef const void* (*CFDictionaryRetainCallBack)(
CFAllocatorRef allocator,
const void *value
);
}
retain是个函数指针,所指向的函数接受两个参数,传入的value表示即将加入字典的键或者值,返回的void*表示加入字典中的最终值。
const void *CustomCallback(CFAllocatorRef allocator, const void *value) {
return value;
}
这么写只是把即将加入字典的值原样返回,用它充当retain回调函数创建字典,就不会“保留”键和值了。下面是完整的字典创建过程。
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
const void *EOCRetainCallback(CFAllocatorRef allocator, const void *value) {
return CFRetain(value);
}
void EOCReleaseCallback(CFAllocatorRef allocator, const void *value) {
CFRelease(value);
}
CFDictionaryKeyCallBacks keyCallbacks = {
0,
EOCRetainCallback,
EOCReleaseCallback,
NULL,
CFEqual,
CFHash
};
CFDictionaryValueCallBacks valueCallbacks = {
0,
EOCRetainCallback,
EOCReleaseCallback,
NULL,
CFEqual
};
-(void)demo5{
CFMutableDictionaryRef aCFDictionary = CFDictionaryCreateMutable(NULL, 0, &keyCallbacks, &valueCallbacks);
NSMutableDictionary *anNSDuctionary = (__bridge_transfer NSMutableDictionary *)aCFDictionary;
}
设置回调函数时,CFDictionaryCopyDescriptionCallBack被设置为null,默认实现就很好。equal和hash回调函数分别是CFEqual和CFHash,这个这和NSMutableDictionary的默认实现相同,CFEqual最终会调用NSObject的isEqual:方法,CFHash会调用hash方法。
前面说过,在向NSMutableDictionary中加数键和值时,如果用作键的对象不支持拷贝操作,编译器会报错,“所属对象的类不支持NSCopying协议,因为copyWithZone:方法未实现”。可以直接在CoreFoundation创建字典~~
总结:
1.无缝桥接技术,可以在Foundation框架中的OC对象和CoreFoundation框架中的C语言数据结构之间来回转换。
2.CoreFoundation创建collection,可以指定很多回调函数,表示在各种情况下的操作,然后无缝桥接转换成OC对象使用。