arc什么 ios
2019-03-27 13:12:00 weixin_34318326 阅读数 3

原文:iOS面试题大全

ARC全称是 Automatic Reference Counting,是Objective-C的内存管理机制。简单地来说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

ARC的使用是为了解决对象retain和release匹配的问题。以前手动管理造成内存泄漏或者重复释放的问题将不复存在。

以前需要手动的通过retain去为对象获取内存,并用release释放内存。所以以前的操作称为MRC (Manual Reference Counting)。

2018-12-05 09:56:00 weixin_33727510 阅读数 8
Objective-C Basics
  1. c

循环引用是指2个或以上对象互相强引用,导致所有对象无法释放的现象。这是内存泄漏的一种情况。举个例子:

* class Father
* 
* @interface Father: NSObject
* @property (strong, nonatomic) Son *son;
* 
* @end
* 
* class Son
* 
* @interface Son: NSObject
* @property (strong, nonatomic) Father *father; 
* 
* @end

上述代码有两个类,分别为爸爸和儿子。爸爸对儿子强引用,儿子对爸爸强引用。这样释放儿子必须先释放爸爸,要释放爸爸必须先释放儿子。如此一来,两个对象都无法释放。

解决方法是将Father中的Son对象属性从strong改为weak。

内存泄漏可以用Xcode中的Debug Memory Graph去检查,同时中Xcode也会在runtime中自动汇报内存泄漏的问题。

ios之ARC
2013-05-17 23:15:11 loganv 阅读数 490

iOS+5+ARC完全指南下载传送门

http://download.csdn.net/detail/loganv/5400019

参考

http://www.cocoachina.com/newbie/tutorial/2013/0407/5945.html

http://www.cocoachina.com/newbie/basic/2012/1016/4927.html

http://blog.csdn.net/zkdemon/article/details/7446385

http://blog.csdn.net/favormm/article/details/7023322

http://www.onevcat.com/2012/06/arc-hand-by-hand/

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226

最直接的arc与非arc项目类的转换

直接在targets->build phases中修改compiler Flags,是否支持arc。添加:-fobjc-arc,就可以让旧项目支持arc。如果想让原来支持arc的不使用arc则添加-fno-objc-arc

或者Edit\Refactor\Convert to Objective-C ARC

想学ios的arc首先要知道ios框架的4个分层

cocoa touch

media

core services

core OS

而arc只适用于第一层也就是cocoa touch,对于其他层的类如quartz,或core foundation就需要手动释放内存


arc编程注意事项

IBOutlet,除了File's Owner连接顶层对象用strong,其他IBOutlet都用weak;

oc对象与core foundation的arc管理转换如下

__bridge_transfer,是给arc管理内存,不要手动释放;用于core foundation转为oc对象

__bridge_retained,解除arc管理内存,需要手动释放;用于oc对象转为core foundation

core foundation ----------> oc,如下(CFBridgingRelease()。函数所做事情和 __bridge_transfer 强制转换完全一样,但更加简洁和清)

- (NSString *)escape:(NSString *)text
{
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)text,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));
}

oc --------> core foundation,如下(同样__bridge_retained也有一个辅助函数:CFBridgingRetain())

NSString *s1 = [[NSString alloc] initWithFormat:@"Hello, %@!", name];
CFStringRef s2 = (__bridge_retained CFStringRef)s1;
// do something with s2
// . . .
CFRelease(s2);

要将Objective-C对象和void *互相转换,你也需要使用__bridge转换,如下:
MyClass *myObject = [[MyClass alloc] init];
[UIView beginAnimations:nil context:(__bridge void *)myObject];
在animation delegate方法中,你再将对象强制转回来:
- (void)animationDidStart:(NSString *)animationID
context:(void *)context
{
MyClass *myObject = (__bridge MyClass *)context;
. . .
}

总结:
• 使用CFBridgingRelease(),从Core Foundation传递所有权给Objective-C;
• 使用CFBridgingRetain(),从Objective-C传递所有权给Core Foundation;
• 使用__brideg,表示临时使用某种类型,不改变对象的所有权。

@autorelease中只能写oc代码,core foundation需要CFAutorelease();

常用不支持arc第三方库,也可以编译成静态.a文件,添加到项目中去;


ios面试或笔试时,常常会被问delegate是应该用weak,还是strong;

最给力的回答,大多数用weak,如果是用strong,则会造成retain回还,当两个对象互相retain时,会导致两个对象都无法被释放,这也是内存泄漏的常见原因之一,而weak指针可以避免retain回还。


以上只是arc的初级应用,高级应用后续研究zhong......

比如block 与arc;

@autoreleaseepool,__autoreleasing,多线程与arc;

第三方库如cocos2d与arc

等....


IOS ARC
2013-01-09 20:03:00 iteye_7514 阅读数 4

原文连接:点击打开链接

ARC指南:http://download.csdn.net/detail/zkdemon/4213790

ARC是iOS5推出的新功能,全称叫ARC(AutomaticReferenceCounting)。简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

该机能在iOS5/MacOSX10.7开始导入,利用Xcode4.2 可以使用该机能。简单地理解ARC,就是通过指定的语法,让编译器(LLVM 3.0)在编译代码时,自动生成实例的引用计数管理部分代码。有一点,ARC并不是GC,它只是一种代码静态分析(Static Analyzer)工具。

通过一小段代码,我们看看使用ARC前后的变化点。

@interfaceNonARCObject:NSObject{

NSString*name;

}

-(id)initWithName:(NSString*)name;

@end

@implementationNonARCObject

-(id)initWithName:(NSString*)newName{

self=[superinit];

if(self){

name=[newNameretain];

}

returnself;

}

-(void)dealloc{

[namerelease];

[Superdealloc];

}

@end

@interfaceARCObject:NSObject{

NSString*name;

}

-(id)initWithName:(NSString*)name;

@end

@implementationARCObject

-(id)initWithName:(NSString*)newName{

self=[superinit];

if(self){

name=newName;

}

returnself;

}

@end

我们之前使用Objective-C中内存管理规则时,往往采用下面的准则

生成对象时,使用autorelease

对象代入时,先autorelease后再retain

对象在函数中返回时,使用return[[objectretain]autorelease];

而使用ARC后,我们可以不需要这样做了,甚至连最基础的release都不需要了。

使用ARC有什么好处呢?

看到上面的例子,大家就知道了,以后写Objective-C的代码变得简单多了,因为我们不需要担心烦人的内存管理,担心内存泄露了

代码的总量变少了,看上去清爽了不少,也节省了劳动力

代码高速化,由于使用编译器管理引用计数,减少了低效代码的可能性

记住一堆新的ARC规则—关键字及特性等需要一定的学习周期

一些旧的代码,第三方代码使用的时候比较麻烦;修改代码需要工数,要么修改编译开关

关于第二点,由于XCode4.2中缺省ARC就是ON的状态,所以编译旧代码的时候往往有"AutomaticReferenceCountingIssue"的错误信息。



这个时候,可以将项目编译设置中的“Objectice-CAutoReferenceCounteting”设为NO。如下所示。



如果只想对某个.m文件不适应ARC,可以只针对该类文件加上-fno-objc-arc编译FLAGS,如下图。


retain,release,autorelease,dealloc由编译器自动插入,不能在代码中调用

dealloc虽然可以被重载,但是不能调用[superdealloc]

由于ARC并不是GC,并需要一些规则让编译器支持代码插入,所以必须清楚清楚了这些规则后,才能写出健壮的代码。

ObjectiveC中的对象,有强参照(Strongreference)和弱参照(Weakreference)之分,当需要保持其他对象的时候,需要retain以确保对象引用计数加1。对象的持有者(owner)只要存在,那么该对象的强参照就一直存在。

对象处理的基本规则是

只要对象的持有者存在(对象被强参照),那么就可以使用该对象

对象失去了持有者后,即被破弃

强参照(Strongreference)



(s1)

firstName作为”natsu”字符串对象的最初持有者,是该NSString类型对象的Strongreference。

(s2)

这里将firstName代入到aName中,即aName也成为了@”natsu”字符串对象的持有者,对于该对象,aName也是Strongreference。

(s3)

这里,改变firstName的内容。生成新的字符串对象”maki”。这时候firstName成为”maki”的持有者,而@”natsu”的持有者只有aName。每个字符串对象都有各自的持有者,所以它们都在内存中都存在。

(s4)

追加新的变量otherName,它将成为@”maki”对象的另一个持有者。即NSString类型对象的Strongreference。

(s5)

将otherName代入到aName,这时,aName将成为@”maki”字符串对象的持有者。而对象@”natsu”已经没有持有者了,该对象将被破弃。

弱参照(Weakreference)

接下来我们来看看弱参照(Weakreference)的使用方式。


(w1)

与强参照方式同样,firstName作为字符串对象@”natsu”的持有者存在。即是该NSString类型对象的Strongreference。

(w2)

使用关键字__weak,声明弱参照weakName变量,将firstName代入。这时weakName虽然参照@”natsu”,但仍是Weakreference。即weakName虽然能看到@”natsu”,但不是其持有者。

(w3)

firstName指向了新的对象@”maki”,成为其持有者,而对象@”natsu”因为没有了持有者,即被破弃。同时weakName变量将被自动代入nil。

ARC中关于对象的引用参照,主要有下面几关键字。使用strong,weak,autoreleasing限定的变量会被隐式初始化为nil。

__strong

变量声明缺省都带有__strong关键字,如果变量什么关键字都不写,那么缺省就是强参照。

__weak

上面已经看到了,这是弱参照的关键字。该概念是新特性,从iOS5/MacOSX10.7开始导入。由于该类型不影响对象的生命周期,所以如果对象之前就没有持有者,那么会出现刚创建就被破弃的问题,比如下面的代码。

NSString__weak*string=[[NSStringalloc]initWithFormat:@"FirstName:%@",[selffirstName]];

NSLog(@"string:%@",string);//此时string为空

如果编译设定OS版本DeploymentTarget设定为这比这低的版本,那么编译时将报错(Thecurrentdeployment targetdoesnotsupportautomated__weak references),这个时候,我们可以使用下面的__unsafe_unretained。

弱参照还有一个特征,即当参数对象失去所有者之后,变量会被自动付上nil(Zeroing)。

__unsafe_unretained

该关键字与__weak一样,也是弱参照,与__weak的区别只是是否执行nil赋值(Zeroing)。但是这样,需要注意变量所指的对象已经被破弃了,地址还还存在,但内存中对象已经没有了。如果还是访问该对象,将引起「BAD_ACCESS」错误。

__autoreleasing

该关键字使对像延迟释放。比如你想传一个未初始化的对像引用到一个方法当中,在此方法中实例化此对像,那么这种情况可以使用__autoreleasing。他被经常用于函数有值参数返回时的处理,比如下面的例子。

-(void)generateErrorInVariable:(__autoreleasingNSError**)paramError{

....

*paramError=[[NSErroralloc]initWithDomain:@"MyApp"code:1userInfo:errorDictionary];

}

....

{

NSError*error=nil;

[selfgenerateErrorInVariable:&error];

NSLog(@"Error=%@",error);

}

又如函数的返回值是在函数中申请的,那么希望释放是在调用端时,往往有下面的代码。

-(NSString*)stringTest

{

NSString*retStr=[NSStringstringWithString:@"test"];

return[[retStrretain]autorelease];

}

//使用ARC

-(NSString*)stringTest

{

__autoreleasingNSString*retStr=[NSStringalloc]initWithString:@"test"];

returnretStr;

}

即当方法的参数是id*,且希望方法返回时对象被autoreleased,那么使用该关键字。

基本的ARC使用规则

代码中不能使用retain,release,retain,autorelease

不重载dealloc(如果是释放对象内存以外的处理,是可以重载该函数的,但是不能调用[superdealloc])

不能使用NSAllocateObject,NSDeallocateObject

不能在C结构体中使用对象指针

id与void*间的如果cast时需要用特定的方法(__bridge关键字)

不能使用NSAutoReleasePool、而需要@autoreleasepool块

不能使用“new”开始的属性名称(如果使用会有下面的编译错误”Property’ssynthesizedgetter followsCocoanamingconventionforreturning‘owned’objects”)

-------------------------------------------------------------------- 华丽的分割线 --------------------------------------------------------------------

ARC工作原理是在编译程序的时候由xCode将内存操作的代码(如:retain,release和autorelease)自动添加到需要的位置。

ARC只能在iOS4和iOS5上使用,weakrefrences只能在iOS5上使用,并且只能是工程在ARC管理内存的时候才能用。
老版本的工程是可以转换成使用ARC的工程,转换规则包括:

1.去掉所有的retain,release,autorelease

2.把NSAutoRelease替换成@autoreleasepool{}块

3.把assign的属性变为weak

使用ARC的一些强制规定

1.不能直接调用dealloc方法,不能调用retain,release,autorelease,reraubCount方法,包括@selector(retain)的方式也不行

2.截图租户事故宣布dealloc方法来管理一些资源,但不能用来释放实例变量,也不能在dealloc方法里面去掉[superdealloc]方法,在ARC下父类的dealloc同样由编译器来自动完成

3.CoreFoundation类型的对象任然可以用CFRetain,CFRelease这些方法

4.不能在使用NSAllocateObject和NSDeallocateObject对象

5.不能在c结构体中使用对象指针,如果有类似功能可以创建一个Objective-c类来管理这些对象

6.在id和void*之间没有简便的转换方法,同样在Objective-c和coreFoundation类型之间的转换都需要使用编译器制定的转换函数

7.不能再使用NSAutoreleasePool对象,ARC提供了@autoreleasepool块来代替它,这样更加有效率

8.不能使用内存存储区(不能再使用NSZone)

9.不能以new为开头给一个属性命名

10.声明outlet时一般应当使用weak,除了对StoryBoard这样nib中间的顶层对象要用strong

11.weak相当于老版本的assign,strong相当于retain

对工程中的单个文件制定不使用ARC的方法:在targets的buildphases选项下CompileSources下选择要不使用arc编译的文件,双击它,输入-fno-objc-arc即可


属性值关键字所有权strong__strong有weak__weak无unsafe_unretained__unsafe_unretained无copy__strong有assign__unsafe_unretained无retain__strong有

strong

该属性值对应__strong关键字,即该属性所声明的变量将成为对象的持有者。

weak

该属性对应__weak关键字,与__weak定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被破弃之后,对象将被自动赋值nil。

并且,delegate和Outlet应该用weak属性来声明。同时,如上一回介绍的iOS5之前的版本是没有__weak关键字的,所以weak属性是不能使用的。这种情况我们使用unsafe_unretained。

unsafe_unretained

等效于__unsafe_unretaind关键字声明的变量;像上面说明的,iOS5之前的系统用该属性代替weak来使用。

copy

与strong的区别是声明变量是拷贝对象的持有者。

assign

一般ScalarVarible用该属性声明,比如,int,BOOL。

retain

该属性与strong一致;只是可读性更强一些。

读写相关的属性(readwrite,readonly)

读写相关的属性有readwrite和readonly两种,如果使用ARC之后,我么需要注意一下readonly属性的使用。

比如下面的变量声明。

@property(nonatomic,readonly)NSString*name;

一般声明为readonly的变量按理说应该不需要持有所有权了,但是在ARC有效的情况下,将出现下面的错误信息:

“ARCforbidssynthesizingapropertyofanObjective-Cobjectwithunspecifiedownershiporstorageattribute如果定义了ARC有效,那么必须要有所有者属性的定义;所以我们的代码改成这样,就OK了

@property(nonatomic,strong,readonly)NSString*name;

不过有一点,ScalarVarible的变量缺省都有assign的属性定义,所以不需要给他们单独的明示声明了。

iOS ARC
2016-01-25 17:11:00 weixin_34310369 阅读数 2

内存管理

  • 引用计数:Objective-C Python
  • 垃圾收集:C#,Java等
  • 区别

内存管理的基本规则

  • 自己生成的对象,自己持有
  • 非自己生成的对象,自己也能持有
  • 不再需要自己持有的对象要释放
  • 非自己持有的对象无法释放

自己生成的对象,自己持有

使用以下名称开头的方法名意味着自己生成的对象只能自己持有

  • alloc
  • new
  • copy
  • mutableCopy

非自己生成的对象,自己也能持有

通过retain方法,非自己生成的对象跟用alloc/new/copy/mutableCopy方法生成并持有的对象一样,成为自己持有

不再需要自己持有的对象要释放

自己持有的对象,一旦不在需要,持有者有义务释放该对象,使用release方法
使用autorelease推迟对象的释(一般用于返回对象的方法)

非自己持有的对象无法释放

alloc/retain/release/dealloc实现

  • alloc -> callAlloc ->class_createInstance -> calloc
  • retain -> sidetable_retain(SideTable refcnts ++)
  • release -> sidetable_release(objc_msgSend)(this, SEL_dealloc))
  • dealloc -> _object_dispose(objc_destructInstance)

autorelease实现

  • _objc_autoreleasePoolPush-> ... -> _objc_autoreleasePoolPop
  • 在每个runloop开始前,系统会创建一个autoreleasepool,在结束之前drain释放
    每一个线程都有一个runloop,每个autoreleasepool对应着一个线程
    (使用block枚举时,自动添加autorelease)

什么时候手动添加autoreleasepool

  • 编写的程序不是基于UI框架的
  • 循坏中创建了大量的临时对象
  • 创建一个辅助线程

ARC规则

修饰符

  • __strong
  • __weak
  • __unsafe_unretained
  • __autoreleasing

__strong修饰符

  • 默认修饰符,表示强引用

__weak修饰符

  • __strong容易发生循坏引用,特别是“父-子”关系的对象
  • __weak提供若引用,超出作用域会自动设置为nil,避免循坏引用
  • 检查附有__weak修饰符的变量是否为nil,判断被赋值的对象是否被废弃

__unsafe_unretained

  • 和__weak的区别是不会设置nil,会造成空指针
  • 在iOS4兼容

__autoreleasing

  • 在ARC有效时,@autoreleaspool代替NSAutoreleasPoll类,__autoreleasing修饰的变量代替autorelea方法
  • 访问__weak修饰的变量必须访问注册到autoreleasepool的对象
  • id的指针或者对象的指针在没有显示的指定时会被附加上__autoreleasing修饰符(例如:NSError *error)

规则

  • 不能使用retain/release/retainCount/autorelease
  • 不能使用NSAllocateObject/NSDeallocateObject
  • 遵守内存管理的方法命名规则
  • 不要显示调用dealloc
  • 使用@autoreleasepool块代替NSAutoreleasePool
  • 不能使用区域
  • 对象型变量不能作为C语言结构体的成员
  • 显示转换"id"和“void *”

显示转换"id"和“void *”

  • 通过"__bridge"转换,id和“void *”就能相互转换
  • __bridge_retained 使要转换赋值变量也持有所赋值的对象
  • __bridge_transfer 被转换的变量所持有的对象在该变量被赋值给转换目标变量后随之释放

ARC的实现

__strong修饰符

  • objc_storeStrong -> objc_retain,objc_release(prev) -> objc_release(obj)

__weak修饰符

  • objc_initWeak-> storeWeak -> objc_destroyWeak -> objc_release

__autoreleasing

  • objc_autoreleasePoolPush -> ... -> objc_autorelease -> objc_autoreleasePoolPop

引用计数

  • retainCount -> refcnts

IOS ARC

阅读数 565

arc ios

阅读数 1

iOS ARC与非ARC

阅读数 294

iOS ARC

阅读数 866

没有更多推荐了,返回首页