obj-c相关分析 3

1 copy vs mutableCopy

  现在需要说明一下:

只有遵守NSCopying 协议的类才可以发送copy消息, 并且实现 copyWithZone: 方法。
只有遵守 NSMutableCopying 协议的类才可以发送mutableCopy消息, 实现 mutableCopyWithZone: 方法。
不过现在IOS SDK已经有一些的类型遵守了这两个协议,eg:  NSString NSArray等,具体可查看SDK Doc

网上关于这两个方法的说明都比较详细,这里总结一下:

1. 如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。

2. 如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。

3. NSCopyobject()他实际上是浅拷贝,所以需要你需要自己处理需要深拷贝的成员变量(指针变量),还有一点NSCopyObject是对象内存的指针拷贝,因此原对象的retaincount也被复制过来。

4. 对于容器类对象,容器存储的指针都是浅拷贝,所以如果需要深拷贝容器内指针所指向的对象,你需要遍历容器中的指针,分别进行深拷贝。

5.其实copy/mutableCopy,类似于设计模式的clone模式,当你进行深clone或者浅clone,你需要做的就是重载copyWithZone或者mutableCopyWithZone。


NSAutoreleasePool

 在每一个线程中都有一个存放自动释放池堆栈。当您创建一个新的自动释放池时,它被添加到堆栈的顶部。当自动释放池被回收时,它们从堆栈中被删除。当一个对象收到送autorelease消息时,它被添加到当前线程的目前处于栈顶的自动释放池中。如果您释放了一个不是位于堆栈顶部的自动释放池,则这会导致堆栈中所有位于它上面的(未释放的)自动释放池,连同它们包含的所有对象一起被释放。这样就可能会造成程序奔溃。

 一般自动释放池用于下面这种情况:

1. 不是基于Application Kit的程序,比如命令行工具,则没有对自动释放池的内置支持;您必须自己创建它们。

2. 如果你创建了一个新的线程,你必须创建自己的自动释放池,避免内存泄漏。不过如果线程不会发起Cocoa调用,那么也可以不创建自动释放池(不过这种情况基本没遇到过)。

3. 在一些会产生大量临时对象的地方,可以在循环内部创建一个自动释放池,以便在下次迭代之前销毁这些对象。这可以帮助减少应用程序的最大内存占用量。

NSAutoreleasePool与drain , retain , release的关系(在基于引用计数的环境下(一般我们开发的环境都是这个))。

一般NSAutoreleasePool时,我们都只会利用drain,其原理是drain会给自动释放池发送dealloc消息,从而导致自动释放池给它内部所有的对象发生release消息,来清空释放池,和回收对象的内存。

但是如果你给一个NSAutoreleasePool发生retain消息,就会出现异常,如果给NSAutoreleasePool发送release消息,默认是不做任何事情。


3.retain ,release ,autorelease(保证上下文中存在自动释放池)

首先给出下面说明:

  • 当您创建一个对象时,该对象的保留计数为1。

  • 当您向一个对象发送retain消息时,该对象的保留计数加1。

  • 当您向一个对象发送release消息时,该对象的保留计数减1。

    当您向一个对象发送autorelease消息时,该对象的保留计数会在将来的某个阶段减1

这三个方法大家都最为熟悉,没有什么好讲的,

这里需要注意一下是:在将集合类的元素移除集合是,会元素发送release消息。加入时会发生retain消息。其实去看看cocoa2D的容器代码就会发现这个。

同时还需要注意循环引用的问题,一般的解决方法将强引用改为弱引用。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值