解析:Memory Management with cocos2d

转载地址:http://blog.sina.com.cn/mountlook

Memory Management with cocos2d   cocos2d的内存管理
At this point I need to talk a bit about memory management and the autorelease 
message. 

现在我们需要讨论一下内存管理和自动释放内存消息.
 
Normally, when you create an object in Objective-C, you do so by calling alloc. By 
doing this, you become responsible to release the object when you don’t need it 
anymore. The following is a typical alloc/init and release cycle: 

通常, 在objective-C中创建对象的时候,你会调用alloc方法. 这么做之后, 你就有责任在你不再需要它

的时候释放它所占用的内存. 下面是典型的alloc/init 和release周期.

// allocate a new instance of NSObject 
NSObject* myObject = [[NSObject alloc] init]; 
 
// do something with myObject here … 
 
// release the memory used by myObject 
// if you don’t release it, the object is leaked and the memory used by it is never freed. 
[myObject release]; 

Now, with the autorelease message and the fact that iOS applications always use an 
autorelease pool, you can avoid sending the release message. Here’s the same 
example rewritten using autorelease: 

现在,有了autorelease消息和iOS应用总是使用的自动释放池, 就不再需要发送release消息了.

下面是用autorelease重写的相同的例子.

// allocate a new instance of NSObject 
NSObject* myObject = [[[NSObject alloc] init] autorelease]; 
 
// do something with myObject here … 
 
// no need to call release, in fact you should not send release as it would crash. 

As you can see, this simplifies memory management somewhat in that you no longer 
have to remember to send the release message. The autorelease pool takes care of that 
for you by sending the object a release message at a later time. Creating the object 
gets just a little bit more complex because the autorelease message was added.  

Now consider the following code, which illustrates how you’d allocate a CCNode object if 
you followed the traditional release style: 

可以看到, 这样简化了内存管理工作, 你不再需要惦记着发送release消息了.自动释放池会在随后帮你向

对象发送release消息. 因为需要添加autorelease消息,创建对象的过程变得稍微复杂了一点.

考虑下面的代码, 它说明了按照传统的内存释放周期如何为CCNode对象分配内存.


// allocate a new instance of CCNode 
CCNode* myNode = [[CCNode alloc] init]]; 
 
// do something with myNode … 
 
[myNode release]; 

This is not the preferred way to create cocos2d objects. It’s much easier to use the 
static initializer methods, which return an autorelease object. Contrary to what Apple 
recommends, the use of autorelease is consistently built into the cocos2d engine’s 
design by moving calls like [[[NSObject alloc] init] autorelease] to a static method 
in the class itself. And that’s a good thing—do not fight it! It will make your life 

easier since you don’t have to remember which objects need to be released, which is often 
cause for either crashes due to over-releasing certain objects or memory leaks due to 
not releasing all objects.

不建议用这种方式创建cocos2d对象.使用静态的初始化器方法来返回自动释放内存对象,更加方便.和苹果

推荐的方式不同,通过把[[[NSObject alloc] init] autorelease]调用移动到类自身的静态方法中, 

autorelease的使用被内置在了cocos2d的设计中. 这是很好的做法,不要抵触它.这会让你更加轻松, 因为

你不再需要记住那个对象需要释放.手工释放内存, 常常会要么由于过度释放而导致程序崩溃, 要么由于

忘记释放内存而导致内存泄漏.

In the case of the CCNode class, the static initializer is +(id) node. The following code 
sends the alloc message to self, which is equivalent to using [CCNode alloc] if the 
code is placed in the CCNode implementation. 

在CCNode类中,静态初始化器是+(id) node, 下面的代码发送一个alloc消息给self, 等同于在CCNode类的

实现中的[CCNode alloc].


+(id) node  
{ 
        return [[[self alloc] init] autorelease]; 
} 

It’s just a little more generic to use self in this case, and perfectly legal in case you 
happen to be a C++ programmer now scratching your head. 

Seeing this, we can rewrite the CCNode allocation to use the static initializer and, quite 
unsurprisingly, the code is now very short, concise, and tidy. Just the way I like it: 

这种情况下通常使用self, 这是合法的. 这对于C++程序员来说可能不太容易理解.

看下面的代码,我们使用静态初始化器重写CCNode对象的分配.很明显, 代码变得短小,简明和整洁了. 这

就是我喜欢的方式.

// allocate a new instance of CCNode 
CCNode* myNode = [CCNode node]; 
 
// do something with myNode … 

That’s the beauty of using autorelease objects. You don’t need to remember to send 
them a release message. Each time cocos2d advances to the next frame, the 
autorelease objects that are no longer in use are released automatically. But there’s also 
one caveat. If you use this code and at least one frame later you want to access the 
myNode object, it’ll be gone. Sending any messages to it will cause an EXC_BAD_ACCESS 
crash.  

这就是使用自动释放内存的对象的优雅之处.你不必惦记着给它们发送release消息.每次cocos2d进入到下

一帧, 不再被使用的自动释放内存对象会被自动释放掉.但是有一点需要注意,如果使用这段代码,只要后

面有一个帧企图访问myNode对象, 这时候他已经被释放了,发送任何消息给它将会导致一个

EXC_BAD_ACCESS异常.

Simply adding the CCNode* myNode variable as a member to your class doesn’t mean 
that the memory used by the object is automatically retained. If you want an autorelease 
object to stick around into the next and future frames, you do need to retain it and 
subsequently release it if you don’t explicitly add it as a child node.  

仅仅把CCNode* myNode变量添加到类的成员变量中,并不意味着这个对象所使用的内存会被自动地保留. 

如果你希望在后面的帧中保留自动释放内存对象,你必须保留对这个对象的引用,然后相应地释放它, 除非

显式地加入到类的子节点中

There’s an even better way to use autorelease objects and keep them around without 
explicitly calling retain. Usually you’ll create CCNode objects and add them to the scene 
hierarchy by adding the nodes as children to another CCNode derived object. You can 
even get rid of the member variable if you want to, by relying on cocos2d to store the 
object for you. 

下面介绍一种比较好的方式,不需要显示调用retain方法也可以保持自动释放内存对象.通常创建了CCNode

对象后,作为子节点添加到另一个CCNode子类的对象,这样就可以把这些CCNode对象加入到场景层次中.如

果你愿意甚至可以删除这些成员变量,依赖cocos2d来为你存储对象.

// creating an autorelease instance of CCNode 
-(void) init 
{ 
        myNode = [CCNode node]; 
        myNode.tag = 123; 
 
        // adding the node as children to self (assuming self is derived from CCNode) 
        [self addChild:myNode]; 
} 
 
-(void) update:(ccTime)delta 
{ 
        // later access and use the myNode object again 
        CCNode* myNode = [self getChildByTag:123]; 
 
        // do something with myNode 
}

The magic is that addChild adds the object to a collection, in this case a CCArray that’s 
similar to the NSMutableArray of the iPhone SDK, but faster. The CCArray and the 
NSMutableArray and any other iPhone SDK collection automatically send a retain 
message to any object added to them, and send a release message to any object 
removed from the collection. Thus the object stays around and remains valid and can be 
accessed at a later time, yet it will automatically be released after it has been removed 
from the collection. 

内幕在于, addChild把对象添加到容器中, 例子中使用的是CCArray, 和iPhone SDK提供的

NSMutableArray相似, 但是更快. CCArray,NSMutableArray和其它iPhone SDK的容器自动发送一个retain

消息给加入其中的所有对象, 当它们从容器中移除时再给它们发送一条release消息.这样对象可以一直保

持有效以便随后的访问, 同时,当它们从容器中移除时也可以被自动释放掉.


What you should keep in mind is that managing memory for cocos2d objects is best 
done as I described here. You may run into other developers who say that autorelease is 
bad or slow and shouldn’t be used. Don’t give in to them.  

需要牢记的是,我在这里讨论的关于cocos2d的管理内存的方法是最好的. 你可能会遇到其他开发人员说自

动释放内存不好或者缓慢而不应该使用.别听他们的.

NOTE: The Apple developer documentation recommends reducing the number of autorelease 
objects. Most cocos2d objects, however, are created as autorelease objects. It makes memory 
management much easier, as I’ve shown.  

提示:苹果开发者文档建议减少使用自动释放内存的对象的数量.然而,大多数cocos2d对象,都是作为自动

释放内存对象创建的.这让内存管理更加容易,就像上面展示的那样.

If you start using alloc/init and release for every cocos2d object, you’ll get yourself 

into a lot of pain for little to no benefit. That isn’t to say that you’ll never use 

alloc/init; it does have its uses and is sometimes even required. But for cocos2d objects, 

you should rely on using the static autorelease initializers. 

如果你在每一个cocos2d对象上使用alloc/init和release方法, 你会陷入到很多毫无益处的痛苦中.也并

不是说永远不要使用alloc/init, 它有它的作用,有时候甚至是必需的.但是对于cocos2d对象, 你应该使

用静态自动释放内存初始化器.

Autorelease objects have only one caveat, and that’s that their memory is in use until the 

game advances by one frame. This means if you create a lot of throw-away autorelease objects 

every frame, you might be wasting memory. But that’s actually a rare occurrence. 

自动释放内存对象只有一点需要注意.它们的内存会一直被占用, 直到游戏进入到下一帧.这就意味着如果

你在每一帧中创建了大量舍弃式自动释放内存的对象, 会非常浪费内存.但是这实际上很少发生.

This concludes my quick primer on cocos2d memory management. Memory 
management in the Objective-C world is governed by simple rules: 
> If you own (alloc, copy, or retain) an object, you must release it later 
> If you send autorelease to an object, you must not release it 

以上是我对cocos2d内存管理的快速入门.在Objective-C的世界,内存管理遵循两条简单的规则:

>如果你拥有(alloc, copy或者retain)一个对象, 你必须在随后释放它.

>如果你发送了autorelease消息给一个对象, 你不必释放它.

For a more in-depth discussion of memory management, refer to Apple’s Memory 
Management Programming Guide 
(http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Memor
yMgmt/MemoryMgmt.html). 

更深入的关于内存管理的讨论,请参阅苹果的内存管理编程指南(Apple’’s Memory Management Programming Guide):

(http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Memor yMgmt/MemoryMgmt.html).


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值