如何将 NSCFString 转换 到的 nsstring转换成int

NSCFString !!!通常遇到这个东西造成崩溃都是由于NSString类型实用不当。应仔细检查
NSCFString !!!通常遇到这个东西造成崩溃都是由于NSString类型实用不当。应仔细检查
[摘要:objc’s category and class cluster http://www.j2megame.org/index.php/content/view/.html objective-c有一个feature,能够给已有的类增加方式,而无需转变类名。传统的说话大概须要经过继续或组开完成]
objc’s category and class cluster&
http://www.j2megame.org/index.php/content/view/.htmlobjective-c有一个feature,可以给已有的类添加方法,而无需改变类名。传统的语言可能需要通过继承或者组合实现,但是obj-c只需要用这个feature就好,这就是category。Category:举个例子,NSString是一个常用的类,NSString是原生支持unicode,比如NSString* str = @”感谢国家”; 要获得string的length,在大部分语言中获得的是字节数(比如python),如果文字编码是utf-8,那么得到的是12(4*3)。但是 NSString是原生支持unicode,所以当使用str.length时,获得的长度是4。有这一特性很好,但这里不是讨论的重点,假设我们需要给NSString增加一个获得字节长度的方法,假设方法名为:byteLengthWithEncoding,使用category可以给NSString类增加如下代码:@interface NSString (StringLength)- (NSUInteger) byteLengthWithEncoding:(NSStringEncoding)@end&@implementation NSString (StringLength)- (NSUInteger) byteLengthWithEncoding:(NSStringEncoding)encoding {&&&&if&(self == nil) {&&&&&&&&return&0;&&&&}&&&&const&char* byte = [self cStringUsingEncoding:encoding];&&&&return&strlen(byte);}@end开始表明我们要扩展的类是NSString,并且把这个方法归到(StringLength)的分组中。这个category组名称随便你命名。然后增加了一个方法名:byteLengthWithEncoding;接下来在implementation中实现这个方法,我们使用了NSString原生的方法cStringUsingEncoding,获得char*的指针,然后使用c里面的函数strlen来获得字节数。来测试一下:int&main(int&argc,&char* argv[]){&&&&NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];&&&&NSString* str = @"感谢国家";&&&&NSLog(@"str's length is : %d", [str length]);&&&&NSLog(@"str's byte length is: %d", [str byteLengthWithEncoding:NSUTF8StringEncoding]);&&&&[pool drain];&&&&return&0;}编译gcc -framework Foundation main.m -o test得到运行结果:2010-08-18 21:24:03.605 test[271:903] str's length is : 4
21:24:03.608 test[271:903] str's byte length is: 12一切都如预期运行,可以感受到category的威力了吧~category用于给一个类增加类方法如此好用,但是对于category有两点要注意的:如果使用category给类增加的方法和原来类的方法同名,则原来的类方法被覆盖,且你将访问不到原来的方法。使用category只能增加类方法,不能增加类变量(ivar)对于第二点,如果我们要增加类方法,同时也要增加类变量,该怎么办?嗯,你可能想到了使用类继承。好,那就来写个类继承NSString,不过我们先不增加类变量,然后给这个类增加上面的那个类方法byteLengthWithEncoding,我们的实现大概是这样:@interface NSStringWithByteLength: NSString {}- (NSUInteger) byteLengthWithEncoding:(NSStringEncoding)@end&@implementation NSStringWithByteLength- (NSUInteger) byteLengthWithEncoding:(NSStringEncoding)encoding {&&&&if&(self == nil) {&&&&&&&&return&0;&&&&}&&&&const&char* byte = [self cStringUsingEncoding:encoding];&&&&return&strlen(byte);}@end&int&main(int&argc,&char* argv[]){&&&&NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];&&&&NSStringWithByteLength* str = (NSStringWithByteLength*)[NSString stringWithString:@"感谢国家"];&&&&NSLog(@"str's length is : %d", [str length]);&&&&NSLog(@"str's byte length is: %d", [str byteLengthWithEncoding:NSUTF8StringEncoding]);&&&&[pool drain];&&&&return&0;}代码有问题的是main函数的第二行,我们强行将返回NSString*的指针转成NSStringWithByteLength类指针,这样应该在调用 类方法byteLengthWithEncoding时出问题。urh,先不管它,gcc编译,输出,运行到输出[str length]时,运行正常,输出4;下一行,调用byteLengthWithEncoding时果然crash了,看出错提示:-[NSCFString byteLengthWithEncoding:]: unrecognized selector sent to instance 0x说的是NSCFString类没有byteLengthWithEncoding方法,wait a minute,哪里来的NSCFString这个类?Class Cluster:原因在于NSString是个class cluster,一个类簇。什么是一个类簇?简单的来说,NSString是个“工厂类”,然后它在外层提供了很多方法接口,但是这些方法的实现是由具体 的内部类来实现的。当使用NSString生成一个对象时,初始化方法会判断哪个“自己内部的类”最适合生成这个对象,然后这个“工厂”就会生成这个具体 的类对象返回给你。这种又外层类提供统一抽象的接口,然后具体实现让隐藏的,具体的内部类来实现,在设计模式中称为“抽象工厂”模式。这里有一篇老外写的,更详细的介绍objective-c class cluster的文章。回过头来看上面的代码,实际上在使用[NSString stringWithString:]的方法时,返回的就是NSCFString* 这个具体类的指针,当然这个类没有后面我们指定的类方法 byteLengthWithEncoding,自然调用时也就出错了。其实即使不是返回NSCFString的指针,上面的代码也有问题,假设是返回NSString的指针,直接使用 (NSStringByteWithLength)去进行强制转换也有问题,毕竟NSStringByteWithLength是子类。这样一来,可能想 到正确的写法应该是将第main函数的第2行初始对象是换为:NSString* str = [[NSStringWithByteLength alloc] initWithBytes:"感谢国家"&&&&length:12 encoding:NSUTF8StringEncoding];这里我们换了一个初始化string的方法,用了NSString原有的initWithBytes的方法。因为 NSStringWithByteLength继承了NSString,即使NSString是个类簇,由于我们没有在 NSStringWithByteLength里重写alloc和init的方法,这么接下来的alloc和initWithBytes的方法调用应该都 是还是NSString里的方法吧,按我们之前关于类簇的分析,这里返回的可能仍然是NSCFString*的类型,然后我们将返回值赋给 NSString,由于NSString*是NSCFString的父类,这种赋值应该没问题。ok,接下来就make & run 。又crash了~ 看报错的信息:-[NSStringWithByteLength initWithBytes:length:encoding:]: unrecognized selector sent to instance 0x好像是说NSStringWithByteLength没有initWithBytes的方法调用。没错,我们是没有在 NSStringWithByteLength中定义这个方法,但是按我们之前的期望,第一步[NSStringWithByteLength alloc] 这里应该调用的是NSString的alloc,然后返回一个对象后再次调用NSString的initWithBytes方法,看起来和直接使用 [[NSString alloc] initWithBytes: length: encoding] 没什么区别啊,为什么这里就说没有initWithBytes这方法了呢?为什么[[NSString alloc] initWithBytes:length:encoding] 调用时没有问题,而用我们自己的 NSStringWithByteLength的派生类调用就出了问题呢?其实又是NSString这个类簇在底下搞鬼,把[[NSString alloc] initWithBytes:length:encoding]拆开看,相当于:id someClass = [NSString alloc];[someClass initWithBytes:length:encoding];先看第一行,我们把这someClass的class打出来看看:[someClass className],又出来个新玩意:NSPlaceholderString。先不管它,不过这里我们至少知道了,这里alloc返回的一个 NSPlaceholderString类型的指针。然后我们再看,把第一行改为:id someClass = [NSStringWithByteLength alloc]按照我们之前的分析,由于这里仍然调用的是NSString的alloc方法,那么返回的someClass的className应该仍然是 NSPlaceholderString才对,但是把这个打印出来,返回的居然是:NSStringWithByteLength,没错,还是我们自己的 类的指针。这是怎么回事?如果是在alloc这一步已经返回不同的类型指针的话,那么刚才的报错提示没有 initWithBytes:length:encoding的方法的提示就不难理解了,因为NSPlaceholderString这个类里定义了这个 方法,而我们自己的NSStringWithByteLength的类没有这个方法。但是同样调用的是NSString的alloc,为啥两次返回不同 呢?Under the hood接下来就是见证奇迹的时刻,NSString alloc时有个中间层,就是我们上面看到的NSPlaceholderString,alloc的对象先统一为这个类对象之后,在后面调用 NSPlaceholderString的类方法时,比如initWithBytes:length:encoding 才返回具体的类,即在NSPlaceholderString这一层做个“代理工厂”,根据调用的不同init方法再返回具体的类,比如 NSCFString。那么为什么我们自己的类调用alloc时,就不返回NSPlaceholderString这个类对象了呢?关键就在于NSString alloc方法的实现。NSString的alloc方法实现类似这样(这里只写简单的逻辑,Cocoa实际的代码实现未必和这个相同,不过逻辑应该是类 似的):@class&NSPlaceholderS&@interface NSString:(NSObject)+ (id)@ end&@implementation NSString+(id) alloc {&&&&if&([self isEquals:[NSString&class]]) {&&&&&&&&return&[NSPlaceholderString alloc];&&&&}&&&&else&&&&&&&&return&[super alloc];}@end&@interface NSPlaceholderString:(NSString)@end关键就在于alloc的实现,可以发现,当只用NSString调用alloc的时候,由于self == [NSString class],所以这时返回的是NSPlaceholderString的类对象;而使用其他类(比如派生类)调用alloc时,返回的是super的 alloc,这里也就是[NSObject alloc],而NSObject的alloc方法返回的是调用类的类对象,所以在我们用我们自己的NSStringWithByteLength类调用 时,返回的就是NSStringWithByteLength类的类对象了。综述只扩展类方法的时候,Category已经足够好用了,而上面也解释了Class Cluster和NSString alloc的“怪异”实现。可见继承一个“class cluster”类型的类是多么不容易,如果不熟悉,可能处处是陷阱。所以在有的书上就提出这样的建议:最好不要继承NSString这样的“类簇”类, 同样的还有NSArray,NSDictionary,NSNumber等等。在apple的文档中也提到,建议使用“组合”或者“catogery”来 实现这种扩展,如果你没有非要继承这种“类簇”类的理由的话。转自:
感谢关注 Ithao123精品文库频道,是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 IThao123!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
Hadoop是一个由Apache基金会所开发的分布式系统基础架构。
用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
Swift是Apple在WWDC2014所发布的一门编程语言,用来撰写OS X和iOS应用程序[1]。在设计Swift时.就有意和Objective-C共存,Objective-C是Apple操作系统在导入Swift前使用的编程语言
Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来使得编程更加简单、灵活和有趣。界面则基于广受人民群众爱戴的Cocoa和Cocoa Touch框架,展示了软件开发的新方向。
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
IThao123周刊4076人阅读
一.Toll-free bridging介绍
Toll-free bridging,简称为TFB,是一种允许某些ObjC类与其对应的CoreFoundation类之间可以互换使用的机制。比如 NSString与CFString是桥接(bridged)的, 这意味着可以将任意NSString当做CFString使用,也可以将任意的CFString当做NSString使用。如下:
NSString ocString = [[[NSString]] stringWithString:@&pants&];
CFIndex length = CFStringGetLength((CFStringRef)ocString);
CFStringRef cfString = CFStringCreateWithCString(NULL,&pants&,kCFStringEncodingASCII);
NSUInteger length = [(NSString *)cfString length];
大部分(但不是全部)同时在Cocoa和CoreFoundation中存在的类是以这种方式桥接的,除NSString之外,还有NSArray与CFArray,NSDictionary与CFDictionary等。
中列出了可以toll-free bridged的类和non toll-free bridged的类。
二.从CoreFoundation类桥接到ObjC类
从CoreFoundation类桥接(bridge)到Objective-C类(即CFString可以当做NSString处理)的方法很简单。每个桥接类(bridged class)实际上是一个类簇(),这意味着公共类(public class)是抽象的,核心功能由私有子类(private subclasses)实现。CoreFoundation类的内存结构(memory layout)与其中一个私有子类相同,而这个子类仅仅作为CoreFoundation类的Objective-C对应类存在,其他Objective-C私有子类可能以其他方式独立存在,但因为所有私有子类都有相同的公共接口,所以从外界看来,它们看起来一样而且以相同的方式工作。
具体来说,NSString是一个抽象类,每当你创建一个NSString实例,实际上是创建的NSString的一个私有子类实例。其中一个私有子类就是NSCFString,其是CFString类的在ObjC中的对应类。CFString中的第一个元素就是isa指针,指向NSCFString类,所以其可以作为一个Objective-C对象工作。
NSCFString实现了作为NSString需要的所有方法,实现这些方法有两种方式,一种是作为桩函数(stub)实现,仅仅通过它调用CoreFoundation中的对应函数;另一种方法是实现与CoreFoundation中函数相同的方法。在实际代码中,这两种方法共同存在。
从这个方向看,桥接机制很简单,就像不存在一样。CFString只是NSCFString类的一个实例,而NSCFString是NSString的子类,实现了作为NSString的所有方法,很多的实现只是直接调用CoreFoundation的实现。
三.从ObjC类桥接到CoreFoundation类
这个方向的桥接就会很复杂,这是因为一个TFB Objective-C类的实例可能是其任意一个子类的实例,还可能是应用程序自定义的子类,但这些可能为任意子类的实例需要在CoreFoundation函数中透明使用,即你可以在任意一个NSString实例(很可能不是NSCFString)上使用CFStringGetLength获得字符串的长度。实际上如果这是NSString实例恰好是NSCFString,则直接调用CoreFoundation的函数,如果不是则直接向其发送-length消息,以Objective-C的方式处理。
这是怎么实现的呢,现在来看下函数的实现
CFIndex CFStringGetLength(CFStringRef str) {
CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFIndex, str, &length&);
__CFAssertIsString(str);
return __CFStrLength(str);
第一行的宏可以处理Objective-C对象,其实现如下:
// Invoke an ObjC method, return the result
#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) \
if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \
{rettype (*func)(const void *, SEL) = (void *)__CFSendObjCM \
static SEL s = NULL; if (!s) s = sel_registerName(sel); \
return func((const void *)obj, s);}
首先看第一行if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)),只是gcc的分支预测标识,表示我们希望CF_IS_OBJC(typeID, obj)返回false。而CF_IS_OBJC做了什么呢?
CF_INLINE int CF_IS_OBJC(CFTypeID typeID, const void *obj) {
return (((CFRuntimeBase *)obj)-&_isa != __CFISAForTypeID(typeID) && ((CFRuntimeBase *)obj)-&_isa & (void *)0xFFF);
这部分代码检查obj是否为Objective-C对象,首先检查其isa指针是否指向了特定的CF类型,如果不是则检查isa指针是否大于0xFFF,如果大于,则说明此对象为Objective-C对象。
而如何根据typeID(__kCFStringTypeID)找到其对应的类(NSCFString)呢,来看__CFISAForTypeID的实现。
extern struct objc_class *__CFRuntimeObjCClassTable[];
CF_INLINE void *__CFISAForTypeID(CFTypeID typeID) {
return (void *)(__CFRuntimeObjCClassTable[typeID]);
__CFISAForTypeID只是以typeID为索引在__CFRuntimeObjCClassTable中查找。__CFRuntimeObjCClassTable是一个CFType与ObjC类的匹配表,在CoreFoundation初始化时,所有桥接类在此表中赋值,而其他项赋值为哑值(NSCFType)。所以以__kCFStringTypeID为索引在此表中可找到NSCFString。如果对象的isa不是指向NSCFString,则说明其不是CFString。
如果经CF_IS_OBJC判断对象不是CF类型,则其为其他Objective-C对象,这时会走Objecitive-C的消息机制,通过__CFSendObjCMsg函数向对象发送-length消息,__CFSendObjCMsg实际上是objc_msgSend_rtp()。
简单来将,处理TFB类的每个CoreFoundation函数首先检查传递的对象是否真正的CoreFoundation类型(特定的CoreFoundation类型,如CFStringGetLength则需要对象是CFString,而不能是其它CoreFoundation对象),如果是纯Objective-C类型,则简单的调用Objective-C类的消息处理。如果是CoreFoundation类型,则以CoreFoundation通常的方式处理。
这种实现有个有趣的后果,如果我们对一个CFArray使用CFStringGetLength函数会有什么效果呢?isa检查为检测到CFArray不是一个真正的CFString,所以会走向Objective-C分支,最终我们得到一个错误
-[NSCFArray length]: unrecognized selector sent to instance 0x
以上的代码是中的,在最近的中实现有变化,不过原理相同。CF635中的实现
#define __CFRuntimeClassTableSize 1024
extern uintptr_t __CFRuntimeObjCClassTable[];
CF_INLINE uintptr_t __CFISAForTypeID(CFTypeID typeID) {
return (typeID & __CFRuntimeClassTableSize) ? __CFRuntimeObjCClassTable[typeID] : 0;
CF_INLINE Boolean CF_IS_OBJC(CFTypeID typeID, const void *obj) {
if (CF_IS_TAGGED_OBJ(obj))
uintptr_t cfisa = ((CFRuntimeBase *)obj)-&_
if (cfisa == 0)
// Temporarily disabled
#if __LP64__
if (cfisa & 0xUL) {
CFLog(kCFLogLevelWarning, CFSTR(&*** Warning: CF tested pointer %p for objectness and found its isa pointer to be bogus (%p)&), obj, cfisa);
if (cfisa & 0x1000UL) {
CFLog(kCFLogLevelWarning, CFSTR(&*** Warning: CF tested pointer %p for objectness and found its isa pointer to be bogus (%p)&), obj, cfisa);
if (cfisa == (uintptr_t)__CFConstantStringClassReferencePtr)
uintptr_t type_isa = (uintptr_t)(typeID & __CFRuntimeClassTableSize ? __CFRuntimeObjCClassTable[typeID] : 0);
if (cfisa == type_isa)
四.基本行为的桥接
以上描述的是显式的桥接的工作方式,对于TFB还有更有趣的一方面,所有对象都共享的基本行为实际上是对所有类桥接的,实质上NSObject可以桥接到CFType。一个最普遍的例子,可以对任意Objective-C对象使用CFRetain,也可以对任意CoreFoundation对象使用retain方法,与其他桥接相同,如果你在Objective-C代码中重写了retain方法,则CFRetain会调用你重写的retain方法。这种桥接行为不仅适合于内存管理方法,对任意的CFType函数(如CFCopyDescription),任意的NSObject方法(如performSelector:withObject:afterDelay:)都适用。
CoreFoundation对象桥接到ObjC对象时,因为任何CoreFoundation对象的首字段(isa)都指向一个ObjC类,对于桥接类isa指向其在ObjC中的对应类,对于非桥接类isa指向一个特殊的__NSCFType(__CFRuntimeObjCClassTable表中的默认值),所有这些类都是NSObject的子类,所以它们继承了NSObject类的所有行为。对于映射到对应CoreFoundation类的方法,则是直接调用CoreFoundation侧的实现。
当ObjC类桥接到CoreFoundation时,和上面描述的机制相同,CFRetain以及其他CFType函数首先检查此对象是否真正的CoreFundation对象(应该是仅检测是否CoreFundation对象,而不是桥接类中检测是否特定的CoreFundation对象)或者是其他Objecitive-C类。如果是CF对象,则调用CoreFoundation的实现,如果不是,则使用消息模式让Objective-C侧处理。
五.ARC与Toll-free bridging
ARC只能管理Objective-C类型,对于Objective-C对象我们不用手动进行retain/release/autorelease的操作,ARC会自动为我们完成。但对于CoreFoundation对象则仍然需要我们手动管理。因为存在所有权(ownership)不明确的问题,所以ARC禁止Objecitive-C对象指针与其它指针类型进行标准cast转换,对CoreFoundation对象指针也是如此。下面一行代码,则手动内存管理时是很典型的转换,但在ARC下却不能编译。
id obj = (id)CFDictionaryGetValue(cfDict, key);
为了使其在ARC环境下可编译,需要使用特殊的casting标注告诉ARC关于所有权(ownership)的语义。这些标注为__bridge,__bridge_transfer和__bridge_retained。
最简单的是__bridge,这是没有所有权影响的直接转换。ARC接收此值,像通常那样处理。
id obj = (__bridge id)CFDictionaryGetValue(cfDict, key);
另外两个casting标注分别向ARC系统转移所有权和从ARC系统获取所有权,在以下情况下使用。以下面代码为例
NSString *value = (NSString *)CFPreferencesCopyAppValue(CFSTR(&someKey&), CFSTR(&pany.someapp&));
[self useValue: value];
[value release];
在使用ARC时,如果使用__bridge,则代码需修改为
NSString *value = (__bridge NSString *)CFPreferencesCopyAppValue(CFSTR(&someKey&), CFSTR(&pany.someapp&));
[self useValue: value];
CFPreferencesCopyAppValue操作需要一个与之匹配的release操作,在初始化value时,ARC系统使用了retain,当value不再使用时,ARC系统会自动对value release,以与之前的retain操作配对。但并没有与CFPreferencesCopyAppValue操作配对的release,所以此对象泄漏。
__bridge_transfer可以用来解决这个问题,__bridge_transfer在将指针值传递给ARC时,同时传递了所有权(transfers ownership)。当__bridge_transfer用来标注cast时,它告诉此对象已经被retain过了,不需要再次retain。既然ARC获取到了所有权,那么它仍然会在使用完毕后release。代码如下:
NSString *value = (__bridge_transfer NSString *)CFPreferencesCopyAppValue(CFSTR(&someKey&), CFSTR(&pany.someapp&));
[self useValue: value];
Toll-free bridging可以在两个方向进行,当从ObjC对象向CoreFundation桥接时代码如下:
CFStringRef value = (__bridge CFStringRef)[self someString];
UseCFStringValue(value);
这种情况下,ARC不会管理value的声明周期,所以在赋值操作完成之后,UseCFStringValue使用value之前,此对象就会被立即释放,这样在UseCFStringValue使用该对象时就会因访问已释放的对象而crash。通过使用__bridge_retained可以让ARC将所有权转出,既然ARC已将所有权转出,所以其不会再释放此对象,这时UseCFStringValue就可以安全使用了,使用完毕后由CoreFundation负责释放,如下
CFStringRef value = (__bridge_retained CFStringRef)[self someString];
UseCFStringValue(value);
CFRelease(value);
这些cast标注不仅可用于toll-free bridging,当需要将Objecitve-C对象指针不当做ObjC对象存储时都可以使用,可以使用此方式将ObjC对象指针与void *或其他指针任意转换。如下:
NSDictionary *contextDict = [NSDictionary dictionary...];
[NSApp beginSheet: sheetWindow
modalForWindow: mainWindow
modalDelegate: self
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: (__bridge_retained void *)contextDict];
- (void)sheetDidEnd: (NSWindow *)sheet returnCode: (NSInteger)code contextInfo: (void *)contextInfo
NSDictionary *contextDict = (__bridge_transfer NSDictionary *)contextI
if(code == NSRunStoppedResponse)
__bridge仅仅在ARC和non-ARC之间转移指针,并不转移所有权。
__bridge_transfer将一个non-Objective-C指针移动到Objective-C指针,并转移所有权,这样ARC会代替你release它.
__bridge_retained将一个Objective-C指针指针移动到一个non-Objective-C指针,同样转移所有权,这样ARC将不会release它,编程者负责后续使用CFRelease或其他函数释放。
六.创建桥接类
不是所有的CoreFoundation类是可以桥接的,从上述讨论的TFB的实现方式可见,做到双向桥接需要CoreFoundation类的每个函数都要首先判断该对象是否真正的CF对象,若不是CF对象,则以Objective-C对象处理。因为CoreFoundation类由苹果控制,所以若其本身未实现此功能,我们没有办法手动添加,所以不能创建双向桥接的TFB类。
但由于任何CoreFoundation的首字段都是isa,我们可以把其当做objective-C对象处理,所以单向的桥接时可以实现的。我们可以在Objective-C侧创建新的类以匹配CoreFoundation中的类。在中讨论了如何创建新的TollFreeBridged类,在中收集了开发者创建的TollFreeBridged类。
本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接。
本文永久链接: //toll-free-bridging/
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:325053次
积分:3525
积分:3525
排名:第6811名
原创:21篇
转载:126篇
评论:33条
(1)(1)(1)(1)(1)(1)(2)(2)(1)(1)(1)(2)(7)(1)(6)(1)(1)(1)(2)(2)(1)(5)(2)(5)(1)(8)(8)(2)(1)(5)(16)(2)(28)(1)(7)(6)(15)

我要回帖

更多关于 nsdate转换成nsstring 的文章

 

随机推荐