ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

内存管理,ARC

内存管理,ARC 2. Core Foundations memory allocation policy is that you need to release values returned by functions with “Copy” or “Create” or alloc in their name;这是指在corefoundation.framework中。而NSString等是在foundation.framework中。3.不是alloc出来的对象不要执行 autorelease!!!alloc方法将分配的内存初始化为0BOOL类型变量被初始化为NOint为0float为0.0指针为nil所有的基地都属于我们了。4.Cocoa过去没有垃圾回收机制iPhone现在也没有。所以必须自己通过-retain, -release and -autorelease这些命令使用引用计数reference counting技术来管理内存。Objective-C的内存管理机制与.Net/Java那种全自动的垃圾回收机制不同它本质上还是C语言中的手动管理方式只不过加了一些自动方法。为什么iOS中没有GC• GC消耗CPU时间耗电。• GC执行后会停掉运行时库◦ GC执行频率高损失性能耗内存影响UI动画处理效果5.可以不为应用程序委托AppDelegate提供dealloc方法因为它永远不会被调用。iPhone OS在应用程序拆卸tear-down期间会恢复所有应用程序内存。从技术上讲视图控制器存在泄漏问题。但是在实践中这不是问题。6. 在objc 中出现了EXE_BAD_ACCESS经常是因为访问了被释放了的对象。在dealloc时要把[super dealloc]放到 dealloc的最后调用否则可能会出现问题可能是因为释放了NSObject导致继承该类的其它数据成员没有宿主导致错误。7.内存使用经验1使用尽量少使用或使用小尺寸的UIView层对于iPad一个像素需要4Byte来算一个层的大小就是 4x1024x768 ~ 3M字节, 10个层就是 10x3M 30M2尽量使用图片pattern而不是一张大的图片与在界面上放一个大底图相比最佳方案是设计出一个小的pattern图然后用这个方案显示成底图。UIImage *smallImage [[UIImage alloc] initWithContentsOfFile:path];backgroundView.backgroundColor [UIColor colorWithPatternImage:smallImage];[smallImage release];3使用 NSAutoreleasePool 的时候也尽量建议局部使用比如下面的循环。循环中大量生成的自动释放autorelease对象可以考虑使用autorelease pool封装。代码范例for(UIView *subview in bigView.subviews) { // 使用autorelease pool自动释放对象池 NSAutoreleasePool *pool [[NSAutoreleasePool alloc] init]; UIImageView *imageView (UIImageView *)subview; // subview处理代码 ....... // 销毁自动释放对象 [pool drain]; }4iOS4.0的multi-tasking特性发布后程序可以被调入后台运行苹果工程师的意见是进入后台运行时你的应用应该释放掉能释放的对象尽量保持在16M左右这样别的程序运行时才不容易把你的应用挤掉。(5)生成对象时使用autorelease;对象代入时先autorelease后再retain,Failed Self 的原则;对象在函数中返回时使用return [[object retain] autorelease];8.数组和字典的内存管理当NSMutableArray被release时它将自动release所有索引位置上的对象. 应该同样适用于NSArray及其它容器.测试NSMutableArray addObject会对添加进的对象发送retain消息;NSMutableDictionary setObject也会对添加的对象发送retain消息;当使用AppKit时,Cocoa定期自动创建和销毁自动释放池.通常是在一个事件循环后执行这些操作.objective-c基础教程中讲,实际上,在编写iPhone程序时,苹果公司建议你不要在自己的代码中使用autorelease方法,同时还要避免使用那些创建了自动释放对象的便利函数.9.ios6.0内存警告的兼容处理 viewDidUnload 屏蔽http://www.cocoachina.com/bbs/simple/?t125949.html判断self.view是否显示在屏幕上if (self.view.window){} //在iOS程序里面window是程序视图层次体系的最高层。view要直接或间接加到这个window上才能被看到。即它的window属性值不为nil。模拟内存警告在ios6模拟器中当前页didReceiveMemoryWarning被调用前一页didReceiveMemoryWarning被调用此时前一页self.view.window为nil这里如果置前一页的self.viewnil再返回前一页时前一页loadview被调用。在ios5模拟器中当前didReceiveMemoryWarning被调用前一页的didReceiveMemoryWarning、viewDidUnload被调用。再返回前一页会调用前一页的loadview。结论在ios5中会自动销毁非当前页的viewController.view。ios6中要手动销毁非当前页的viewController.view且不会调用viewDidUnload。只有viewController.view被销毁了viewController的loadviewviewDidLoad才会被依次调用。在调用loadView前self.view会被重新创建它的内容就是空的了。所以基于原ios5的viewDidUnload代码在ios6中处理代码修改如下-(void)didReceiveMemoryWarning{[super didReceiveMemoryWarning];if([[[UIDevice currentDevice] systemVersion] floatValue] 6.0){if ([self.view window] nil)//非当前视图{[self viewDidUnload];/*下面self.view nil;目的是再次进入时能够重新加载此操作不能调用两次如果调用两次会导致此页面在下面时也会被调用loadview且要销毁所有的子view在loadview时重新创建这涉及到保存一些view中的数据防止丢失。*/self.view nil;}}}如果不主动执行[self viewDidUnload]或相关函数则必须要在loadView和viewDidLoad中对一些成员的创建做空建判断。空建即为空是才创建。但[self.view addSubview:xxx];要在空建判断外添加因为此时self.view内容是空的。参考 http://www.cnblogs.com/thefeelingofsimple/archive/2012/12/03/2799145.html10.9.ARChttp://onevcat.com/2012/06/arc-hand-by-hand/http://www.yifeiyang.net/development-of-the-iphone-simply-1/在Building Setting中Apple LLVM compiler 3.1 language 中 “Objectice-C Auto Reference Counteting” 项设置是否启用ARC。如果只想对某个.m文件不适应ARC可以只针对该文件加上 -fno-objc-arc 编译FLAGS。而启用arc使用 -fobjc-arc编译选项。ARC的一个基本规则即是只要某个对象被任一strong指针指向那么它将不会被销毁。如果对象没有被任何strong指针指向那么就将被销毁。成员对象指针和局部指针默认就是strong的即ARC中默认的指针类型就是strong。当对象被销毁后在ARC机制作用下所有指向这个对象的weak指针将被置为nil。这个特性相当有用使用ARC以后不论是strong还是weak类型的指针都不再会指向一个dealloced的对象不会出现EXCBADACCESS错误从根源上解决了意外释放导致的crash。strong和retain相似weak比assign更聪明一些。Objective-C内存ARC规则retain, release, autorelease, dealloc由编译器自动插入不能在代码中调用不能使用retain/release/retainCount/autorelease可以重写dealloc但不能调用[super dealloc]不要显式调用dealloc使用autoreleasepool块代替NSAutoreleasePool引用关键字ARC中关于对象的引用参照主要有下面几关键字。使用strong, weak, autoreleasing限定的变量会被隐式初始化为nil。__strong 强参照变量声明缺省都带有__strong关键字。__weak 弱参照该类型不影响对象的生命周期如果对象之前就没有持有者那么会出现刚创建就被破弃的情况。弱参照还有一个特征即当参数对象失去所有者之后变量会被自动付上nil (Zeroing)。__unsafe_unretained 即MRC的assign__autoreleasing 该关键字使对像延迟释放。用在函数返回新对象或函数的参数会接管新对象。可以理解为暂只保存对象内存不检查强弱情况待有指针接管后再检查判断。- (void)generateErrorInVariable:(__autoreleasing NSError **)paramError{ .... *paramError [[NSErroralloc] initWithDomain:MyAppcode:1 userInfo:errorDictionary]; }void)generateErrorInVariable:(__autoreleasing NSError **)paramError{ .... *paramError [[NSErroralloc] initWithDomain:MyAppcode:1 userInfo:errorDictionary]; }NSError*errornil; [selfgenerateErrorInVariable:error]; NSLog(Error %, error);*errornil; [selfgenerateErrorInVariable:error]; NSLog(Error %, error);-(NSString*)stringTest{ __autoreleasing NSString *retStr [NSStringalloc] initWithString:test];returnretStr; }NSString*)stringTest{ __autoreleasing NSString *retStr [NSStringalloc] initWithString:test];returnretStr; }即当方法的参数是id*或希望方法返回时对象被autoreleased那么使用该关键字。伴随ARC的导入还有一系列函数的定义也被严格定义了那就是以 init 开头的函数。init 函数作为alloc生成对象的初期化函数需要按原样直接传递对象给调用段所以下面的声明是OK的。-(id)initWithObject:(id)obj;而下面的是NG的。-(void)initWithObject;不过声明为 -(void) initialize; 是没有问题的。只能将ARC用在objective-c对象上(也即继承自NSObject的对象)但是如果涉及到较为底层的东西比如Core Foundation中的malloc()或者free()等ARC就鞭长莫及了这时候还是需要自己手动进行内存管理。另外为了确保ARC能正确的工作有些语法规则也会因为ARC而变得稍微严格一些。ARC确实可以在适当的地方为代码添加retain或者release但是这并不意味着你可以完全忘记内存管理因为你必须在合适的地方把strong指针手动设置到nil否则app很可能会oom。简单说还是那句话你必须时刻清醒谁持有了哪些对象而这些持有者在什么时候应该变为指向nil。使用ARC之后由于内存问题造成的crash基本就是过去式了OOM除外。iOS 5.1 Xcode 4.3版本中ARC 有效时的属性(property) 定义的时候如果不明确指定所有权关键字那么缺省的就是 strong。但是在 Xcode4.2 中即使 strong 也要显示指定。property也可以用strong或weak来标记简单地把原来写retain和assign的地方替换成strong或者weak就可以了。代码示例__weak NSString *weakName self.textField.text;首先ARC是LLVM3.0编译器的特性而老的工程默认编译器可能是GCC或者LLVM-GCC因此第一步就是确认编译器是否正确。在Project设置面板选择target在Build Settings中将Compiler for C/C/Objective-C选为Apple LLVM compiler 3.0或以上。为了确保之后转换的顺利最好把Treat Warnings as Errors和 Run Static Analyzer都打开确保在改变编译器后代码依旧没有警告或者内存问题。Build Settings页面把Objective-C Automatic Reference Counting改成YES(如果找不到的话请看一看搜索栏前面的小标签是不是调成All了..这个选项在Basic里是不出现的)这样工程就将在所有源代码中启用ARC了。Edit-Refactor下的Convert to Objective-C ARC点击后会让选择要转换哪几个文件。readonly的property声明要显示声明strongproperty (nonatomic, strong, readonly)NSString*name;NSString*name;对于强引用的成员view在出现内存警告时要在unload中置为nil
返回列表