Xcode ARC的引入

很多引用的类库暂时还不支持.麻烦的是对大多数第三方库需要加禁用arc的编译flag

如果你的项目使用的是 ARC 模式,则为非 ARC 模式的代码文件加入 -fno-objc-arc 标签。

添加标签的方法:

  1. 打开:你的target -> Build Phases -> Compile Sources.
  2. 双击对应的 *.m 文件
  3. 在弹出窗口中输入上面提到的标签 -fobjc-arc / -fno-objc-arc
  4. 点击 done 保存


虽然objective-c 2.0支持垃圾收集器(Garbage Collection,简称GC),但是垃圾收集器只能在MAC程序上开启,ios上没办法用。就算在MAC应用程序上可以用,GC也会有性能上的损耗。 
现在LLVM3.0多了一个给力的新东西,叫Automatic Reference Counting。


ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只不过是在代码编译时为你自动在合适的位置插入release或autorelease,就如同之前MRC时你所做的那样。


使用Xcode自带的转换ARC工具
165  
166 选择要转换的文件
167  
168 这个小工具是Edit->Refactor下的Convert to Objective-C ARC


SURL *fileURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
184 if (fileURL != nil) {
185   SystemSoundID theSoundID;
186   OSStatus error = AudioServicesCreateSystemSoundID((CFURLRef)fileURL, &theSoundID);
187   if (error == kAudioServicesNoError) {
188       soundID = theSoundID;
189     }
190 }
191  
192 这里代码尝试把一个NSURL指针强制转换为一个CFURLRef指针。这里涉及到一些Core Services特别是Core Foundation(CF)的东西,AudioServicesCreateSystemSoundID()函数接受CFURLRef为参数,这是一个CF的概念,但是我们在较高的抽象层级上所建立的是NSURL对象。在Cocoa框架中,有很多顶层对象对底层的抽象,而在使用中我们往往可以不加区别地对这两种对象进行同样的对待,这类对象即为可以”自由桥接”的对象(toll-free bridged)。NSURL和CFURLRef就是一对好基友好例子,在这里其实CFURLRef和NSURL是可以进行替换的。
193  
194 通常来说为了代码在底层级上的正确,在iOS开发中对基于C的API的调用所传入的参数一般都是CF对象,而Objective-C的API调用都是传入NSObject对象。因此在采用自由桥接来调用C API的时候就需要进行转换。但是在使用ARC编译的时候,因为内存管理的原因,编译器需要知道对这些桥接对象要实行什么样的操作。如果一个NSURL对象替代了CFURLRef,那么在作用区域外,应该由谁来决定内存释放和对象销毁呢?为了解决这个问题,引入了bridge,bridge_transfer和__bridge_retained三个关键字。关于选取哪个关键字做转换,需要由实际的代码行为来决定。如果对于自由桥接机制感兴趣,大家可以自己找找的相关内容,比如适用类型、内部机制和一个简介~之后我也会对这个问题做进一步说明
195  
196 回到demo,我们现在在上面的代码中(CFURLRef)前加上__bridge进行转换。


为了方便查找,再此列出一些在转换时可能出现的问题,当然在我们使用ARC时也需要注意避免代码中出现这些问题:
211  
212 “Cast … requires a bridged cast”
213 这是我们在demo中遇到的问题,不再赘述
214  
215 Receiver type ‘X’ for instance message is a forward declaration
216 这往往是引用的问题。ARC要求完整的前向引用,也就是说在MRC时代可能只需要在.h中申明@class就可以,但是在ARC中如果调用某个子类中未覆盖的父类中的方法的话,必须对父类.h引用,否则无法编译。
217  
218 Switch case is in protected scope
219 现在switch语句必须加上{}了,ARC需要知道局部变量的作用域,加上{}后switch语法更加严格,否则遇到没有break的分支的话内存管理会出现问题。
220  
221 A name is referenced outside the NSAutoreleasePool scope that it was declared in…
222 这是由于写了自己的autoreleasepool,而在转换时在原来的pool中申明的变量在新的@autoreleasepool中作用域将被局限。解决方法是把变量申明拿到pool的申请之前。
223  
224 ARC forbids Objective-C objects in structs or unions
225 可以说ARC所引入的最严格的限制是不能在C结构体中放OC对象了..因此类似下面这样的代码是不可用的
226  
227 1
228 2
229 3
230 4
231  
232 typedef struct {
233   UIImage *selectedImage;
234   UIImage *disabledImage;
235 } ButtonImages;
236  
237 这个问题只有乖乖想办法了..改变原来的结构什么的..

另外,在MRC时代一个常做的事情是在dealloc里把指向自己的delegate设成nil(否则就等着EXC_BAD_ACCESS吧 :P),而现在一般delegate都是weak的,因此在self被销毁后这个指针自动被置成nil了,你不用再为之担心,好棒啊..

通过加载xib得到的用户界面,在其从xib文件加载时,就已经是view hierarchy的一部分了,而view hierarchy中的指向都是strong的。因此outlet所指向的UI对象不应当再被hold一次了。将这些outlet写为weak的最显而易见的好处是你就不用再viewDidUnload方法中再将这些outlet设为nil了(否则就算view被摧毁了,但是由于这些UI对象还在被outlet指针指向而无法释放,代码简洁了很多啊..)。


自由桥接的细节
349  
350 MainViewController现在剩下的问题都是桥接转换问题了~有关桥接的部分有三处:
351  
352 (NSString *)CFURLCreateStringByAddingPercentEscapes(…):CFStringRef至NSString *
353 (CFStringRef)text:NSString *至CFStringRef
354 (CFStringRef)@“!‘();:@&=+$,/?%#[]”:NSString 至CFStringRef
355 编译器对前两个进行了报错,最后一个是常量转换不涉及内存管理。
356  
357 关于toll-free bridged,如果不进行细究,NSString和CFStringRef是一样的东西,新建一个CFStringRef可以这么做:
358  
359 1
360  
361 CFStringRef s1 = [[NSString alloc] initWithFormat:@"Hello, %@!",name];
362  
363 然后,这里alloc了而s1是一个CF指针,要释放的话,需要这样:
364  
365 1
366  
367 CFRelease(s1);
368  
369 相似地可以用CFStringRef来转成一个NSString对象(MRC):
370  
371 1
372 2
373 3
374 4
375 5
376  
377 CFStringRef s2 = CFStringCreateWithCString(kCFAllocatorDefault,bytes, kCFStringEncodingMacRoman);
378 NSString *s3 = (NSString *)s2;
379  
380 // release the object when you're done  
381 [s3 release];
382  
383 在ARC中,编译器需要知道这些指针应该由谁来负责释放,如果把一个NSObject看做是CF对象的话,那么ARC就不再负责它的释放工作(记住ARC是only for NSObject的)。对于不需要改变持有者的对象,直接用简单的bridge就可以了,比如之前在SoundEffect.m做的转换。在这里对于(CFStringRef)text这个转换,ARC已经负责了text这个NSObject的内存管理,因此这里我们需要一个简单的bridge。而对于CFURLCreateStringByAddingPercentEscapes方法,方法中的create暗示了这个方法将形成一个新的对象,如果我们不需要NSString转换,那么为了避免内存的问题,我们需要使用CFRelease来释放它。而这里我们需要一个NSString,因此我们需要告诉编译器接手它的内存管理工作。这里我们使用bridge_transfer关键字,将内存管理权由CF object移交给NSObject(或者说ARC)。如果这里我们只用bridge的话,内存管理的负责人没有改变,那么这里就会出现一个内存泄露。另外有时候会看到CFBridgingRelease(),这其实就是transfer cast的内联写法..是一样的东西。总之,需要记住的原则是,当在涉及CF层的东西时,如果函数名中有含有Create, Copy, 或者Retain之一,就表示返回的对象的retainCount+1了,对于这样的对象,最安全的做法是将其放在CFBridgingRelease()里,来平衡retain和release。
384  
385 还有一种bridge方式,__bridge_retained。顾名思义,这种转换将在转换时将retainCount加1。和CFBridgingRelease()相似,也有一个内联方法CFBridgingRetain()来负责和CFRelease()进行平衡。
386  
387 需要注意的是,并非所有的CF对象都是自由桥接的,比如Core Graphics中的所有对象都不是自由桥接的(如CGImage和UIImage,CGColor和UIColor)。另外也不是只有自由桥接对象才能用bridge来桥接,一个很好的特例是void (指向任意对象的指针,类似id),对于void 和任意对象的转换,一般使用_bridge。(这在将ARC运用在Cocos2D中很有用)

(http://www.oschina.net/code/snippet_196012_24966)

二、开启ARC后需要遵循的原则 
3、不能使用id<–>void *的类型转换,因为编译器不知道这个void *是否需要retained。 
4、不能使用NSAutoreleasedPool,要用@autoreleasepool {„„}来代替。 

在新旧技术更替的更年期应注意:现在ARC还under NDA,没有任何开源框架可以公开支持ARC的,如果想使用此特性,在选取开源框架时应该尽量选择使用CF库较少的框架,否则手动爆开源框架的菊花会很痛苦。

【iOS中的自由桥接
http://www.cnblogs.com/crazypebble/p/3381260.html】】
http://wenku.baidu.com/link?url=-eEFmXc76ar9IolULQjtPXCB3qYBwZRSb0vL0rfT7SmHXYH5hHBCGyVCQYIE-JWyhgvNRzdaLnv6woNdH5dYYMJbDzDudtoEmmXox_OKh7O
http://blog.sina.com.cn/s/blog_4c4c79950100t3uy.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "Xcode中的Edit菜单中的To Objective-C ARC"是一个选项,它可以将项目从手动管理内存转换为自动引用计数(ARC)模式。在ARC模式下,编译器会自动插入内存管理代码,从而减少了程序员需要手动管理内存的工作量,使代码更加简洁和易于维护。 ### 回答2: Xcode的Edit中的"Convert to Objective-C ARC"是一个功能,用于将项目中的手动引用计数(Manual Reference Counting,简称MRC)代码转换为自动引用计数(Automatic Reference Counting,简称ARC)代码。 在早期的iOS开发中,开发者需要手动管理内存,使用retain、release和autorelease等方法来管理对象的内存生命周期。这种方式需要开发者花费大量的时间和精力来确保内存管理的正确性,容易出现内存泄露和野指针等问题。 ARC的出现极大地简化了内存管理的过程,开发者不再需要手动管理引用计数,编译器会自动在合适的时候插入retain、release和autorelease等代码。这样可以大大减少内存管理相关的bug,并提高开发效率。 "Convert to Objective-C ARC"功能可以帮助开发者将项目中的MRC代码转换为ARC代码。使用该功能,开发者可以选择要转换的文件或者整个工程,Xcode会自动检测代码中的引用计数,然后自动插入正确的ARC相关代码。在转换完成后,开发者可以更加方便地进行内存管理,减少人为的错误。 总之,Xcode的Edit中的"Convert to Objective-C ARC"功能是为了帮助开发者将手动管理引用计数的代码转换为自动管理引用计数的代码,简化内存管理过程,提高开发效率。 ### 回答3: Xcode中的Edit功能包括了许多实用的工具和选项,其中之一就是"Convert to Objective-C ARC"(转换为Objective-C自动引用计数)。 Objective-C ARC是一种自动内存管理机制,它可以自动处理内存管理,减少了开发者手动管理内存的工作量。这种机制通过跟踪对象的引用计数,并自动释放不再需要的对象来实现。在ARC下,开发者无需手动调用retain、release,以及autorelease等方法来管理内存。 "Convert to Objective-C ARC"是一个非常有用的功能,它可以将项目中使用手动引用计数(MRC)的代码转换为使用自动引用计数(ARC)的代码。这个功能简化了开发者的工作,提高了代码的可维护性和性能。转换后的代码可以通过简单地点击几个按钮完成自动迁移,不需要手动修改大量的代码。 使用"Convert to Objective-C ARC"功能的步骤如下: 1. 在Xcode中打开需要转换的工程。 2. 点击Xcode菜单栏的"Edit"选项。 3. 在下拉菜单中选择"Convert"。 4. 在弹出的菜单中选择"To Objective-C ARC"。 5. Xcode将会自动对项目中的源代码进行分析,找出需要进行转换的部分。 6. 在转换窗口中,选择需要转换的文件和目标。 7. 点击"Finish"按钮开始进行转换。 在转换过程中,Xcode会自动对代码进行检查和修改,将使用MRC的代码转换为ARC的代码。转换完成后,开发者可以自行检查转换的结果,并进行必要的手动修复。 总之,"Convert to Objective-C ARC"是Xcode中强大的编辑工具之一,它能够帮助开发者轻松地将使用手动引用计数的代码转换为使用自动引用计数的代码,提高开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值