当前位置: 首页 > 科技观察

iOS备选内存管理

时间:2023-03-20 20:03:03 科技观察

OS内存管理是一个老生常谈的问题。我们写iOS的时候,无时无刻不涉及到内存管理。从一开始的MRR(manualretain-release)到后来的ARC(AutomaticReferenceCounting),包括CoreFoundation在内的内存管理都遵循引用计数的基本原则。大家一定对基本的内存管理不陌生。这里主要说一点,其他的就不多说了。官方文档有这段话——你拥有你创建的任何对象你使用名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法创建对象(例如,alloc、newObject或mutableCopy).大意是,如果你一开始使用alloc/new/copy/mutableCopy方法创建了一个对象,那么你将拥有这个对象(retain)。不用的时候需要手动释放一次。举个例子,假设有一个方法[STObjectnewObject],我们应该这样使用,如果绝对不release,会导致Object被泄露。STObject*object=[STObjectnewObject];//dosomething[objectrelease];在这种情况下,我们也可以想象,如果我们要实现以new开头的方法,需要如下代码-(instancetype)newObject{return[[[selfclass]alloc]init];}+(UIButton*)copyButton{return[[UIButtonbuttonWithType:UIButtonTypeCustom]retain];}则出现以下问题:MRR下实现了一个newObject方法,遵循约定的原则,返回值会retain+1,然后在ARC下调用这个方法创建一个对象。MRR下实现了一个newObject方法。该方法不遵守约定原则,返回autorelease的对象,然后在ARC下调用该方法创建对象。ARC下实现了一个newObject方法,然后在MRR下调用newObject方法创建一个对象。使用后在releaseARC下实现一个newObject方法,然后在MRR下调用newObject方法创建对象。在没有release的情况下使用后,我们可以自己写上面的实验代码,然后进行测试。最终测试结果如下:场景一和场景三运行正常。场景2崩溃。场景4产生内存泄漏。为什么场景2会崩溃?这是因为在ARC下,如果我们的编译器看到你创建了一个对象,其方法是以alloc/new/copy/mutableCopy开头的,它会在used***中插入一个release操作,因为返回的对象是autorelease,它又被释放了,所以导致了野指针。场景4中泄漏的原因是一样的。当ARC下的编译器发现方法以new开头时,release语句就不会插入到方法的末尾。场景4在使用过程中,newObject并没有被释放,所以会出现leak。.如果我们只使用MRR或者ARC,一般不会出现这种问题。这种问题一般是ARC/MRR混合的时候一些不规范的写法导致的,所以在写代码的过程中,一定要遵守规范。如果我们自己写alloc/new/copy/mutableCopy开头的方法,一定不要忘记返回MRR下的retained对象。同样,我们在使用alloc/new/copy/mutableCopy等方法创建对象时,一定不要忘记用完后Release。如果我们有一段MRR代码,提供了一个以new开头的方法,但是不符合规范,那么我们在ARC下怎么办呢?根据上面的结论,我们正常的使用肯定会导致这里出现野指针。如果可以更改代码,当然应该更改代码以符合规范。如果源代码无法更改,我们只能修改用户。这是一个方法:SELselector=NSSelectorFromString(@"copyObject");STObject*object=(STObject*)[STObjectperformSelector:selector];你可以试试看,然后想想为什么。iOS的内存管理远不止于此,本文提到的实际编码过程很少遇到,只是作为知识的补充~