autorelease的使用和注意

1.当我们创建一个对象时,(1)Person *p = [[Person alloc] init],就需要在下方执行一次(2)[p release],而[p release]一般放在最后,如果紧跟(1)的话,当创建完对象,对象就会被销毁,成为僵尸对象,假设,Person中有age属性,则再执行(3)p.age = 10;无疑会报错(野指针错误),如果放在程序的最后面的话,则p.age 正常执行。所以我们会担心(2)的乱放会造成许多错误。

例如:



解决方法是使用autorelease方法,其返回值是对象本身,autorelease会将对象放在一个自动释放池中,当自动释放池被销毁时,会对池子里面的所有对象做一次release操作所以代码:(1)Person *p = [[Person alloc] init],(4) [p autorelease].

 (1)(4)-> Person *p = [[[Person alloc] init]autorelease];

 

整体代码如下:



图示如下:



自动释放池销毁后:


注意:autorelease只是把对象扔到自动释放池里面(延迟了对象被销毁的时间),并不可以改变对象的计数器。改变计数器只有retain和release两种方法。缺点是:不能精确控制对象被销毁的时间,内存处理效率低(适用于占用内存比较小的对象,对象里面包含的属性主要是基本数据类型)。且autoreleasepool的存在是以栈结构存在的,栈结构的特点就是先进后出。当一个对象调用autorelease方法时,会将当前对象放到栈顶的释放池中。

 



autorelease和release不能同时适用。下面就是一个错误的使用:

autoreleasepool{

      Car *c = [[[Car alloc] init] autorelease];

 

      [c release];

     

}//野指针错误(message send to deallocted instance),当执行到这行代码时 c的计数器已经为0,但是释放池销毁,里面的对象需要再做一次release操作。(//或者 Car *c =[ [[[Car alloc] init] autorelease]autorelease];也是一个野指针错误)

 

 

2.ios 5.0版本以前:

自动是释放池的创建

NSAutoreleasePool*pool = [[NSAutoreleasePool alloc] init];

//对象代码区

[pool  release];//销毁池子

或者[pool drain]//已经被淘汰

 

 ios 5.0以后版本:

@autoreleasepool {

           //

           //

}

 

3.

1)Car *c = [[[Car alloc] init] autorelease];

如果要直接使用这句来创建对象的话,对于开发者,会觉得很浪费时间。所以如何优化这句代码呢?在开发过程中,我们会使用类方法,返回一个autorelease的对象。类方法返回对象类型(id)或(instancetype)。所以类方法如下:

 

+(instancetype)car{

 

      return [[[Car alloc] init] autorelease];

}

 

创建对象时就可以

//返回一个调用autorelease方法的Car对象c

Car *c = [Carcar];

 

如果我们想要一个直接返回对速度赋初值的Car对象

 

则可以这样:

//这只是个类方法并不是构造方法

+(instancetype)car{

Car * c = [[[Caralloc] init] autorelease];

c.speed = 100;

 

      return c ;

}

 

 

NSSting *str =@”1233”;

NSSting *str=[NSStringstringWithFormat:@”ha %d”,age ];

 

 

注意:系统自带方法里面如果没有包含alloc new 或者copy,说明返回的对象都是autorelease的。

规范:类方法的方法名一般以类名开头。类名相同的时候一般加前缀。

 

2)在开发过程中,如果父类有一个类方法可以快速创建一个调用autorelease方法的对象,在写类方法时,里面创建对象时我们要用self([[[self alloc] init] autorelease]),这样的话子类就不用重写这个方法来获取一个autorelease的对象。谁调用这个类方法,self则代表的就是谁。



  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用运行时API可以定位内存泄露,具体可以通过以下步骤实现: 1. 在 Xcode 中选择 Product -> Scheme -> Edit Scheme,然后在左侧选择 Run,接着在 Arguments Passed On Launch 中添加环境变量:MallocStackLoggingNoCompact,并将其值设为 1。 2. 在代码中添加以下代码: ``` #import <objc/runtime.h> void checkMemoryLeak() { unsigned int count = 0; Class *classes = objc_copyClassList(&count); for (unsigned int i = 0; i < count; i++) { Class cls = classes[i]; if (class_respondsToSelector(cls, @selector(doesNotRecognizeSelector:))) { // This class has no method implementations of its own. continue; } unsigned int methodCount = 0; Method *methods = class_copyMethodList(cls, &methodCount); for (unsigned int j = 0; j < methodCount; j++) { Method method = methods[j]; SEL selector = method_getName(method); if (selector == @selector(alloc) || selector == @selector(new)) { // Skip alloc and new methods to avoid false positives. continue; } NSString *methodName = NSStringFromSelector(selector); if ([methodName hasPrefix:@"init"]) { // Skip init methods to avoid false positives. continue; } IMP imp = method_getImplementation(method); if (imp == NULL) { // Skip methods with no implementation. continue; } if (strstr(methodName.UTF8String, "copy") != NULL || strstr(methodName.UTF8String, "mutableCopy") != NULL) { // Skip copy and mutableCopy methods to avoid false positives. continue; } if (strstr(methodName.UTF8String, "retain") != NULL) { // Skip retain methods to avoid false positives. continue; } if (strstr(methodName.UTF8String, "release") != NULL || strstr(methodName.UTF8String, "autorelease") != NULL) { // Skip release and autorelease methods to avoid false positives. continue; } // Call the method with a nil argument to create an object without retaining it. ((id (*)(id, SEL, ...))method_invoke)(cls, selector, nil); } free(methods); } free(classes); } ``` 3. 在代码中调用 checkMemoryLeak 函数,这个函数会递归遍历所有类及其方法,并在不保留对象的情况下调用方法,从而创建对象并触发内存分配。如果有内存泄漏,可以通过 Instruments 工具捕获堆栈信息并进行分析。 需要注意的是,这个方法只是一种定位内存泄漏的手段,具体的问题还需要根据具体情况进行分析和解决。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值