ios 内存小结

原创 2015年07月08日 13:46:18

这是 看 书籍  Objective-C 高级编程 ios与os  x多线程和内存管理  一书的随记。

1 arc

首先记录一下几个调试的东西

调试  

1.查看 autoreleasePool 池里面的对象

extern void _objc_autoreleasePoolPrint();

    _objc_autoreleasePoolPrint();

2.通过  clang 可以 查看对应的 汇编代码。其实xcode  的 Product-》Perform Action ->Assemble ""  也就ok了

clang -fobjc-arc -framework Foundation test.m -o test  

3 通过 CFGetRetainCount((__bridge    CFTypeRef)test2));  或者

    extern uintptr_t _objc_rootRetainCount();

    NSLog(@"xxxx %lu",_objc_rootRetainCount(self.array));

可以在 arc 总看到 retaincount 的值。切记 不要依赖这个retaincount 编译器 有很多优化。可能跟你理解的不同。比如 当你 通过一个非 alloc new  copy  mutableCopy 方法获取一个对象的时候 按照道理是 获取的 autorelease 对象。然后在 retain 。编译器 会优化省略 autorelease 过程。


引用计数的思考方式

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

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

不在需要自己持有对象时释放

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


方法名称 以 alloc new copy mutableCopy 开头的方法 必须返回给调用者应当持有的对象。

以init 开头的 更加严格 必须返回 id 类型 或者当前类的 类型 或者 子类父类。这个对象不会注册到 autorelease 池里面去。只是


修饰符

_strong

id 类型 和对象类型 默认的修饰符。即:

id  xx = [[NSObject alloc] init]; 实际上就等于

id _strong obj = [[NSObject alloc] init ];

简单的说 就是当 strong 修饰符修饰的变量 被赋值的时候。 就相等于 retain 了该对象。 当该修饰符 修饰的变量 抛弃原本指向的对象的时候。 就相当于 release了 该对象。当strong 修饰的变量结束了有效区域的时候。也会release

[objc] view plaincopy
  1. MyTest  *test = [[MyTest alloc]init];  
  2. MyTest  *test2 = test;  
  3. MyTest  *test3 = test;  
  4. MyTest  *test4 = test;  
  5. MyTest  *test5 = test;  
  6.   
  7. NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge  
  8.                                                     CFTypeRef)test));  
  9. test5 = nil;  
  10. NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge  
  11.                                                 CFTypeRef)test));  
  12.   
  13. test4 = [[MyTest alloc]init];  
  14. NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge  
  15.                                                 CFTypeRef)test));  

如上代码所示。因为默认修饰符是strong 所以 当test 赋值给strong修饰的变量的时候。 就retain了 test。所以第一个输出是5. 当 执行 test5 = nil 的时候。 因为 被修饰符为 strong 的变量 抛弃的对象会release 所以 变成了4. 同样道理 最后 test retainCount 变成了3;(ps:这里要说的是 之前在有的资料看过 非arc 跟 arc 混编的 复杂情况下 有可能导致的内存泄露。 主要是 对象是非arc 创建的 在 arc中使用的情况。 当时 给出的解决方案。就是 用完之后 设置为 nil 就行了。 想想这里的了解。其实有一定道理。当然现在找不到那个资料了所以 也没法实验总结)

_weak

当2个对象互相引用导致引用环的时候就需要weak了。 简单的说就是赋值的时候 不改变 retainCount的概念。当然还有当对象释放之后 会设置为 nil。这也是 _weak 和 __unsafe_unretain 的主要区别。

这里有个需要注意的。当使用__weak 变量的时候。不是简单的访问。 是会调用一个方法 retainWeakReference (可以重写这个非公开方法 用来调试。但正式开发千万别加逻辑。) 书上说 会加入到 autoreleasePool 里面去。可是访问结束查看 autoreleasePool 。在使用访问 __weak的时候 也确实可以查看到 retainCount 增加了1. 这里可以 猜测 是只是访问的那里新建了一个 autoreleasePool池。访问结束 就 已经释放了。

这样的作用是因为 weak 不持有该对象。当访问过程中。可能被释放掉。 这样就能保证访问过程中都是有效状态。

_unsafe_unretained

我能想到的跟 __weak 的区别就是 释放了对象的时候 不设置为 nil。用这个修饰符的对象 不被arc内存管理 所管理。

_autoreleaseing

autorelease 的本质就是 创建一个NsAutoreleasePool 对象。当一个对象调用 autorelease 的时候。 会去获取当前使用的 最内侧(如果有嵌套的池的话)的NsAutoreleasePool对象。然后调用 NsAutoreleasePool对象的一个 类似数组 的addobject 方法。让 NsAutoreleasePool对象来持有这个 autorelease 对象。 当调用 NsAutoreleasePool 的 drain方法的时候。清除引用。 就释放了 autorelease对象。

实际上在arc 中 。编译器有很多优化。让原本是autorelease 的对象 根本就不加入到 NSAutoreleasePool中去。

pd:这里需要注意的是 指针变量 默认的修饰符 是 autoreleaseing  比如 id *xx。 是 autoreleaseing的 而 id xx 是 strong的。

属性

属性 修饰符
assign __unsafe_unretained
copy __strong(是retain的复制的新对象)
retain __strong
strong __strong
unsafe_unretained __unsafe_unretained
weak __weak
这里 感觉没有太多的东西需要了解。 只要了解了修饰符 就会知道属性的这些含义了。  需要注意的是 有人喜欢在类里面的方法里面对属性复制的时候 用 下划线开头的变量。这里不建议这样做。 除了 初始化方法 delloc方法,以及 set get 方法内部。 其他地方 对属性赋值的时候 尽量用属性访问。这是为了维护好属性的 copy  strong 等。

另外这里测试的时候 发现 如果在方法里面 有个 __weak属性  每次使用 属性都会导致retainCount +1. 查看汇编代码 有个

_objc_retainAutoreleasedReturnValue 方法被调用了。完全不知道为什么。。

看了下 _objc_autoreleasedReturnValue 函数 返回 注册到 autoreleasepool 里面的对象。 但是 跟 autorelease 函数又不同。 如果 _objc_autoreleasedReturnValue 方法之后 会立即调用 _objc_retainAutoreleasedReturnValue  就不将对象注册到 autoreleasepool 中。而是直接传递到方法或者函数的调用方。 _objc_retainAutoreleasedReturnValue 和 objc_retain 函数不同。 这个作用 就是 上面说到的。 对于不是 new alloc copy mutablecopy 开头的方法。按道理返回的对象是 autorelease 然后在retain 。这个机制就优化了这里的代码

IOS 内存限制

110down vote I did some testing with the utility Split wrote (link is in his answer). I don't ...
  • yy405145590
  • yy405145590
  • 2015年07月07日 20:11
  • 1791

《IOS_C语言》程序存储区划分、动态申请内存、内存操作函数

一:程序存储区划分 1、栈区:(最低地址内存空间)一般的基本数据类型,包括数组类型、结构体类型、int\short\char····等类型,甚至是const int a=6,也是栈区的,并不是常量,也...
  • baidu_30907803
  • baidu_30907803
  • 2015年08月31日 17:07
  • 532

iOS开发-18个性能优化/内存优化常用方法(很常用)

1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数),它避免了最常见的由于我们忘记释放内存所造成的内存泄露。它自动为你管理retain和rel...
  • Zhai19931004
  • Zhai19931004
  • 2016年05月09日 14:59
  • 3579

ios获取内存信息

#import "sysSystemInfo.h" #import #import #import #import #import #import -(void) logMemoryIn...
  • wzq9706
  • wzq9706
  • 2013年09月05日 10:23
  • 5192

定位IOS内存暴增

最近做项目,突然遇到内存暴增。用到了Instruments,定位到了问题所在。先上图 根据内存百分比,一步一步定位到内存增长最大的函数处。...
  • yqmfly
  • yqmfly
  • 2015年04月16日 17:34
  • 1969

ios webView内存爆涨的解决方法

之前因为项目里h5页面不多,所以webView虽然占很多内存,但是没引起我的注意。后来面试的时候,人家问我:用webView有啥弊端?我说不知道,直接用啊!后来了解了一下js javascritc...
  • gaoyuqiang30
  • gaoyuqiang30
  • 2016年10月26日 17:25
  • 1037

iOS经典讲解之使用instruments检测内存

这里是原文 入门 为了节省大家的时间,提供一个演示的Demo给大家。代码传送门.   下载后解压然后用xcode打开。   编译运行APP后 然后在搜索框内输入任意词汇,点击结果你会看到...
  • Loving_iOS
  • Loving_iOS
  • 2016年02月26日 15:01
  • 7818

iOS单个app最大内存占用限制

device: (crash amount/total amount/percentage of total) iPad1: 127MB/256MB/49% iPad2: 275MB/512MB/...
  • fishmai
  • fishmai
  • 2017年07月08日 17:29
  • 1750

[iOS]UIWebView内存消耗过多解决方法

在iOS开发时,使用UIWebView 来加载显示一个网页是比较常见的情况. 用过UIWebView 的人可能知道当应用使用多个UIWebView 来加载网页时,内存使用增加特别厉害.最近刚好遇到这个...
  • kongu
  • kongu
  • 2015年07月14日 15:24
  • 9276

iOS可用内存限制

iPad1最大可占到110M左右,如果冲到120M就有可能被杀掉。  iPad2可以占用到300M以上,这个不太稳定,可能冲到350就被杀掉了。  可以在收到内存警告的时...
  • speedge
  • speedge
  • 2015年09月21日 15:27
  • 543
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ios 内存小结
举报原因:
原因补充:

(最多只允许输入30个字)