@autoreleasepool {}在ARC下还能用

1.ARC下用 @autoreleasepool {}主要还是为了避免内存峰值。简单点的说在{}中存放的对象会在稍后的某个时刻释放掉

(1)在自动释放池@autoreleasepool{}中alloc一个对象后(如p1),仍然需要用[p1 autorelease];只是这个语句和[p1 release];不同,后者表示把p1的retainCount-1,而前者仅仅表示把p1放到自动释放池中返回一个self,自动释放池结束销毁时,统一对里面的对象引用计数retainCount-1。

(2)@autoreleasepool{}可以随意创建,也可以嵌套使用。

(3)不管这个对象是在自动释放池内还是外创建的,只要在自动释放池内写一个[p1 autorelease];p1就会被放到自动释放池中。注意autorelease是一个方法,且只有在自动释放池中使用才有效。

(4)如果把一个对象重复加到自动释放池如[p1 autorelease];[p1 autorelease];,那么会出错。原因是:加载几次,届时自动释放池就会用[p1 release];释放几次,但是由于这两个加载的对象其实是一个对象同样地址,所以第一次自动释放正确,第二次自动释放时发现已经被释放了,所以p1就变成了野指针。

(5)以下是自动释放池嵌套的使用规则和注意点。

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {

  Person *p1=[[Person alloc]init];
  @autoreleasepool {
    @autoreleasepool {
      [p1 autorelease];
    }//在执行到此处时,p1被自动释放
  }

  //以下代码有错误
  @autoreleasepool {
    [p1 autorelease];//此时p1被加入进来
    @autoreleasepool {
      [p1 autorelease];//被重复加载进来,但仍然同一个
    }//此处,p1被自动释放了,所以第一次加进来的那个也被释放了,因为是同一个对象
  }//所以此处在调用[p1 release];时就出现报错:野指针

  return 0;
}

(6)@autoreleasepool的应用:如果需要在方法中创建对象,并把这个对象作为返回值,那么可以在这个方法中使用[*** autorelease];把它加入到自动释放池中,否则,直接用[*** release];来匹配alloc的话,在该方法中就已经把这个对象alloc和release了一遍相当于释放了,那么所谓的返回对象返回的时一个野指针(没有指向任何对象)。当然,调用这个方法的代码页需要写在自动释放池作用域内才生效。

(7)接上面。返回对象的那个方法中,创建对象不建议直接用类名,而是用self,否则如果存在子类调用会崩溃。如Car *car1=[[self alloc]init];

(8)其实诸如NSString *str1=[NSString stringWithFormat:@"%@",@"hello"];也是调用了一个方法,并且返回了一个字符串对象。比照(6)和(7)我们得知这个stringWithFormat应该也是顺便返回了一个autorelease。

(9)在ARC机制中,我们用@property声明的成员变量,建议用strong代替之前手动管理内存时的retain,虽然后者仍然可以使用。因为我们在ARC中内存管理就是看是否有强指针指向对象,如有就不回收,如没有就回收。所以强指针是strong,相反是weak。而基本数据类型我们还是习惯用assign。

(10)虽然Xcode提供了非ARC转换成ARC的,很少有把整个非ARC转换成ARC的。如果我们导入第三方库时,需要非ARC和ARC共存,即我们系统默认是ARC,我们需要让系统不要去管这个非ARC的第三方库,如下设置:双击响应的.m文件,输入-fno-objc-arc回车即可。

(11)顺便,当出现两个类循环引用的话(也就是A要包含B,B要包含A,即A对象要作为B的变量,B对象要作为A的变量),只需要把一方的strong改成weak,并且在响应的.h文件中把#import ".h"改成Class ***。如果因为改成Class ***而无法使用那个类的方法的话,只需要在它的.m文件中#import“.h”文件即可,这个因为不是在.h文件中导入所以不冲突。

注意:利用webview加载gif图时,左右来回滑动导致内存暴涨,用了

@autoreleasepool {

for (UIView *subview in self.welcomeScr.subviews) {

if ([[subview class]isSubclassOfClass:[UIWebView class]]) {

[subview removeFromSuperview];

}

}

NSInteger index= self.welcomeScr.contentOffset.x/ScreenW;

NSInteger count = index+1;

NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%ld",index+1] ofType:@"gif"];

NSData *gifData = [NSData dataWithContentsOfFile:path];

UIWebView *webView = [self createWebViewWithFrame:CGRectMake(ScreenW * index  ,0,ScreenW,ScreenH)];

[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];

[self.welcomeScr addSubview:webView];

}

之后,内存有些变小,但是减下来的内存只有1~2MB,没有比增长的多,更没有完全释放掉

webview的内存释放方法还需要研究。。。。。。。

时间: 2024-10-24 09:12:24

@autoreleasepool {}在ARC下还能用的相关文章

Objective-C中,ARC下的 strong和weak指针原理解释

Objective-C中,ARC下的 strong和weak指针原理解释 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除

八.OC基础加强--1.autorelease的用法 2.ARC下内存管理 3.分类(category)4.block的学习

1.autorelease的用法   1.自动释放池及autorelease介绍 (1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的. (2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中 . 2.为什么会有autorelease? OC的内存管理机制中比较重要的一条规律是:谁申请,谁释放. 但有些情况下,开发者并不能确定某些对象何时释放.这时候就需要自动释放池. 它的好处是: (1)不需要再关心对象释放的时间 : (2)不需要再关

ARC下的内存管理

1.ARC下单对象内存管理 局部变量释放对象随之被释放 int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = [[Person alloc] init]; } // 执行到这一行局部变量p释放 // 由于没有强指针指向对象, 所以对象也释放 return 0; } 清空指针对象随之被释放 int main(int argc, const char * argv[]) { @autoreleasepool

arc下dealloc得处理

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/css/cuteeditor.css); dealloc 中的每一行都会有一个错误. 我们不再被允许调用 [release] 了, 也不允许调用 [super dealloc]. 因为我们在 dealloc 不再做任何操作了, 所以我们可以直接把这个方法删除掉. 唯一一个留着 dealloc 方法的原因就是

__block在arc和非arc下含义一样吗?

Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block). 比如这样一个Block类型: typedef void (^MyBlockType)(int); @property (copy) MyBlockType myBlock; if (self.myBlock) { //此时,走到这里,self.myBlock可能被另一个线程改为空,造成crash //注意:a

iOS: ARC和非ARC下使用Block属性的问题

1. Block的声明和线程安全 Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC下返回Block). 另一个需要注意的问题是关于线程安全,在声明Block属性时需要确认“在调用Block时另一个线程有没有可能去修改Block?”这个问题,如果确定不会有这种情况发生的话,那么Block属性声明可以用nonatomic.如果不肯定的话(通常情况是这样的),那么你首先需要声明Blo

(知其所以然 主题2)从底层分析OC中ARC和非ARC下深复制和浅复制

今天,在坊间听到有人在争论OC中关于NSString的深浅复制,听了下,感觉很有必要来一个分析总结,让我们从底层去了解OC中深浅复制的运作机制. 所谓copy就是在原有对象的基础上产生一个副本对象,遵循最关键的两点原则: 1. 改变原对象的属性和行为不会对副本对象产生任何影响 2. 改变副本对象的属性和行为不会对原对象产生任何影响 在理解了这一层之后,我们一起来研究下deep copy 和 shallow copy,因为苹果是一个非常注重性能的公司,所以拷贝在底层实现没那么简单: 以NSStri

ARC下查看对象的引用计数

网上各种文章.问答给出的结论都是"ARC下无法打印对象的引用计数值". 确实,ARC禁止直接查看Objective-C对象的引用计数,但是Objective-C对象不是还可以转化为Core Foundation对象么?于是动手做了一个小实验: id obj = [[NSObject alloc]init]; printf("retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(obj))); 需要注意

iOS开发高级面试题-ARC下dealloc的作用

在MRC时代,我们需要在 dealloc中做很多,比如释放对象,等等; 如今我们已经进入ARC时代,对于普通对象的释放,系统已经帮我们做好了; 那是否可以高枕无忧了呢?在ARC下我们应该做什么? 观点: ARC下,系统可以帮我们释放该对象,及其包含的对象; 但是却无法释放不属于该对象的一些东西,如: 1.通知的观察者 由于通知中心是系统的一个单例,你在注册通知的观察者时,实际上是在通知中心注册的, 这时,即使ARC下系统帮我们释放了对象,但是在通知中心的观察还是没有移除,那么当有 该通知时,依然