欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

剖析iOS開發(fā)中Cocos2d-x的內(nèi)存管理相關(guān)操作

 更新時(shí)間:2015年10月22日 10:27:25   作者:doctorhsly的專欄  
這篇文章主要介紹了剖析iOS開發(fā)中Cocos2d-x的內(nèi)存管理相關(guān)操作,Cocos2d-x是開發(fā)游戲的利器,需要的朋友可以參考下

一,IOS與圖片內(nèi)存
在IOS上,圖片會(huì)被自動(dòng)縮放到2的N次方大小。比如一張1024*1025的圖片,占用的內(nèi)存與一張1024*2048的圖片是一致的。圖片占用內(nèi)存大小的計(jì)算的公式是;長*寬*4。這樣一張512*512 占用的內(nèi)存就是 512*512*4 = 1M。其他尺寸以此類推。(ps:IOS上支持的最大尺寸為2048*2048)。

二,cocos2d-x 的圖片緩存
Cocos2d-x 在構(gòu)造一個(gè)精靈的時(shí)候會(huì)使用spriteWithFile或者spriteWithSpriteFrameName等 無論用哪種方式,cocos2d-x都會(huì)將這張圖片加載到緩存中。如果是第一次加載這個(gè)圖片,那就會(huì)先將這張圖片加載到緩存,然后從緩存讀取。如果緩存中已經(jīng)存在,則直接從緩存中提取,免除了加載過程。

圖片的緩存主要由以下兩個(gè)類來處理:CCSpriteFrameCache, CCTextureCache

CCSpriteFrameCache加載的是一張拼接過的大圖,每一個(gè)小圖只是大圖中的一個(gè)區(qū)域,這些區(qū)域信息都在plist文件中保存。用的時(shí)候只需要根據(jù)小圖的名稱就可以加載到這個(gè)區(qū)域。

CCTextureCache 是普通的圖片緩存,我們所有直接加載的圖片都會(huì)默認(rèn)放到這個(gè)緩存中,以提高調(diào)用效率。

因此,每次加載一張圖片,或者通過plist加載一張拼接圖時(shí),都會(huì)將整張圖片加載到內(nèi)存中。如果不去釋放,那就會(huì)一直占用著。

三,渲染內(nèi)存
不要以為,計(jì)算內(nèi)存時(shí),只計(jì)算加載到緩存中的內(nèi)存就可以了。以一張1024*1024的圖片為例。

復(fù)制代碼 代碼如下:

CCSprite *pSprite = CCSprite::spriteWithFile("a.png");

調(diào)用上邊這行代碼以后,可以在LEAKS工具中看到,增加了大約4M的內(nèi)存。然后接著調(diào)用
復(fù)制代碼 代碼如下:

addChild(pSprite);

這時(shí),內(nèi)存又增加了4M。也就是,一張圖片,如果需要渲染的話,那它所占用的內(nèi)存將要X2。

再看看通過plist加載的圖片,比如這張大圖尺寸為2048*2048。想要加載其中的一張32*32的小圖片

復(fù)制代碼 代碼如下:

CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("b.plist");

此時(shí)內(nèi)存增加16M (汗)
復(fù)制代碼 代碼如下:

CCSprite *pSpriteFrame = CCSprite::spriteWithSpriteFrameName("b1.png");

b.png 大小為32*32 ,想著也就是增加一點(diǎn)點(diǎn)內(nèi)存,可實(shí)際情況是增加16M內(nèi)存。也就是只要渲染了其中的一部分,那么整張圖片都要一起被加載。

但是情況不是那么的糟糕,這些已經(jīng)渲染的圖片,如果再次加載的話,內(nèi)存是不會(huì)再繼續(xù)升高的,比如又增加了100個(gè)b.plist的另一個(gè)區(qū)域,圖片內(nèi)存還是共增加16+16 = 32M,而不會(huì)繼續(xù)上升。

四,緩存釋放
如果游戲有很多場(chǎng)景,在切換場(chǎng)景的時(shí)候可以把前一個(gè)場(chǎng)景的內(nèi)存全部釋放,防止總內(nèi)存過高.

復(fù)制代碼 代碼如下:

CCTextureCache::sharedTextureCache()->removeAllTextures(); 釋放到目前為止所有加載的圖片

CCTextureCache::sharedTextureCache()->removeUnusedTextures(); 將引用計(jì)數(shù)為1的圖片釋放掉CCTextureCache::sharedTextureCache()->removeTexture(); 單獨(dú)釋放某個(gè)圖片

CCSpriteFrameCache 與 CCTextureCache 釋放的方法差不多。


值得注意的是釋放的時(shí)機(jī),一般在切換場(chǎng)景的時(shí)候釋放資源,如果從A場(chǎng)景切換到B場(chǎng)景,調(diào)用的函數(shù)順序?yàn)锽::init()---->A::exit()---->B::onEnter() 可如果使用了切換效果,比如CTransitionJumpZoom::transitionWithDuration這樣的函數(shù),則函數(shù)的調(diào)用順序變?yōu)锽::init()---->B::onEnter()---->A::exit() 而且第二種方式會(huì)有一瞬間將兩個(gè)場(chǎng)景的資源疊加在一起,如果不采取過度,很可能會(huì)因?yàn)閮?nèi)存吃緊而崩潰。

有時(shí)強(qiáng)制釋放全部資源時(shí),會(huì)使某個(gè)正在執(zhí)行的動(dòng)畫失去引用而彈出異常,可以調(diào)用CCActionManager::sharedManager()->removeAllActions();來解決。

五、內(nèi)存管理
1.概述
cocos2d-x最初移植自cocos2d的objective C版本。因此,在內(nèi)存管理上,使用了和NSObject類似的引用計(jì)數(shù)器方法,相關(guān)接口放置在CCObject類中。

2.引用計(jì)數(shù)器——手動(dòng)管理內(nèi)存
CCObject的及其子類的對(duì)象在創(chuàng)建時(shí),引用計(jì)數(shù)自動(dòng)設(shè)置為1。之后每次調(diào)用retain,引用計(jì)數(shù)+1。每次調(diào)用release,引用計(jì)數(shù)-1;若引用計(jì)數(shù)=0,則直接delete this。
相關(guān)接口如下:
 

復(fù)制代碼 代碼如下:

//引用次數(shù)+1
virtual void CCObject::retain(void);
//引用次數(shù)-1;若引用計(jì)數(shù)器=0,則delete this;
virtual void CCObject::release(void);
//helper方法,快速判斷當(dāng)前對(duì)象只有唯一引用
bool CCObject::isSingleRefrence(void);
//返回引用次數(shù)
unsigned int CCObject::retainCount(void);

原則1:誰生成(new、copy)誰負(fù)責(zé)release。
例子:
復(fù)制代碼 代碼如下:

CCObject *obj=new CCObject;
...
obj->release();

retain是在指針傳遞和賦值時(shí)使用的,他的含義是表示擁有。這經(jīng)常用在指針賦值上。
原則2:誰retain,誰負(fù)責(zé)release。
例子:

復(fù)制代碼 代碼如下:

obj->retain();
...
obj->release();

原則3:傳遞賦值時(shí),需要先retain形參,后release原指針,最后賦值。(注意,因?yàn)檫@里沒有使用自賦值檢查,所以這組順序不能錯(cuò)。)
例子:

復(fù)制代碼 代碼如下:

void CCNode::setGrid(CCGridBase* pGrid)
{
            CC_SAFE_RETAIN(pGrid);
            CC_SAFE_RELEASE(m_pGrid);
            m_pGrid = pGrid;
}

 
3.自動(dòng)釋放池——自動(dòng)管理內(nèi)存
 
原則4:對(duì)于使用autorelease的對(duì)象,不必管它,每幀結(jié)束后會(huì)自動(dòng)釋放。

相關(guān)接口:

復(fù)制代碼 代碼如下:

CCObject* CCObject::autorelease(void);
 

例子:
復(fù)制代碼 代碼如下:

CCObject *obj=new CCOjbect;
obj->autorelease();
...

完全手動(dòng)管理內(nèi)存,很繁瑣,cocos2d-x提供了自動(dòng)釋放池CCPoolManager。將對(duì)象置于自動(dòng)釋放池中,每幀繪制結(jié)束,就自動(dòng)release池中的對(duì)象。

 
4.CCNode節(jié)點(diǎn)管理

cocos2d-x使用節(jié)點(diǎn)組成一棵樹,渲染的時(shí)候要遍歷這棵樹。CCNode是所有節(jié)點(diǎn)類的父類,他內(nèi)部使用了一個(gè)CCArray對(duì)象管理他的所有子節(jié)點(diǎn),當(dāng)對(duì)象被添加為子節(jié)點(diǎn)時(shí),實(shí)際上是被添加到CCArray對(duì)象中,同時(shí)會(huì)調(diào)用這個(gè)對(duì)象的retain方法。同理,從CCArray中移除時(shí),也會(huì)調(diào)用release方法。
 
相關(guān)接口:

復(fù)制代碼 代碼如下:

virtual void addChild(CCNode * child);
virtual void addChild(CCNode * child, int zOrder);
virtual void addChild(CCNode * child, int zOrder, int tag);
virtual void removeChild(CCNode* child, bool cleanup);
void removeChildByTag(int tag, bool cleanup);
virtual void removeAllChildrenWithCleanup(bool cleanup);

在切換場(chǎng)景時(shí),系統(tǒng)會(huì)遍歷整棵樹的節(jié)點(diǎn),進(jìn)行release。

5.靜態(tài)工廠

cocos2d-x中存在大量的靜態(tài)工廠方法,這些方法中,全都對(duì)this指針調(diào)用了autorelease函數(shù)。如CCSprite中的這些方法:

復(fù)制代碼 代碼如下:

static CCSprite* spriteWithTexture(CCTexture2D *pTexture);
static CCSprite* spriteWithTexture(CCTexture2D *pTexture, const CCRect& rect);
static CCSprite* spriteWithTexture(CCTexture2D *pTexture, const CCRect& rect, const CCPoint& offset);
static CCSprite* spriteWithSpriteFrame(CCSpriteFrame *pSpriteFrame);
static CCSprite* spriteWithSpriteFrameName(const char *pszSpriteFrameName);
static CCSprite* spriteWithFile(const char *pszFileName);
static CCSprite* spriteWithFile(const char *pszFileName, const CCRect& rect);
static CCSprite* spriteWithBatchNode(CCSpriteBatchNode *batchNode, const CCRect& rect);
 

這些方法內(nèi)部實(shí)現(xiàn)了:內(nèi)存分配、初始化、設(shè)置autorelease。用靜態(tài)工廠來生成對(duì)象,可以簡(jiǎn)化代碼,是官方建議的方法。

6.cache機(jī)制類

cocos2d-x中存在一些cache類,這些都是單例類的管理器。

復(fù)制代碼 代碼如下:

CCAnimationCache
CCSpriteFrameCache
CCTextureCache

這些cache內(nèi)部也使用了ratain和release方法,防止這些資源被釋放掉。
使用這些cache,我們可以保存預(yù)加載的一些資源,在方便的時(shí)候調(diào)用它,去綁定給一些對(duì)象。注意,這些cache在場(chǎng)景切換時(shí),不會(huì)自動(dòng)刪除,需要手動(dòng)調(diào)用purgeXXXX方法,進(jìn)行清理。

相關(guān)文章

  • MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法

    MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法

    最近發(fā)現(xiàn)了一個(gè)問題,unity一打開就黑屏,通過查找相關(guān)的資料終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于在MacOS系統(tǒng)下Unity啟動(dòng)黑屏的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2018-01-01
  • 快速上手IOS UIBezierPath(貝塞爾曲線)

    快速上手IOS UIBezierPath(貝塞爾曲線)

    本文主要介紹了IOS 貝塞爾曲線(UIBezierPath)的基礎(chǔ)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • 在Swift中使用JSONModel 實(shí)例代碼

    在Swift中使用JSONModel 實(shí)例代碼

    本文主要介紹在Swift中使用JSONModel,這里給大家提供代碼實(shí)例做參考,希望能幫助有需要的小伙伴
    2016-07-07
  • iOS圖片拉伸的方法

    iOS圖片拉伸的方法

    這篇文章主要為大家詳細(xì)介紹了iOS圖片拉伸的相關(guān)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • iOS10全新推送功能實(shí)現(xiàn)代碼

    iOS10全新推送功能實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了iOS10全新推送功能實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • IOS開發(fā)用戶登錄注冊(cè)模塊所遇到的問題

    IOS開發(fā)用戶登錄注冊(cè)模塊所遇到的問題

    最近和另外一位同事負(fù)責(zé)公司登錄和用戶中心模塊的開發(fā)工作。通過本文給大家分享IOS開發(fā)用戶登錄注冊(cè)模塊所遇到的問題,感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • iOS圖片模糊效果的實(shí)現(xiàn)方法

    iOS圖片模糊效果的實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了iOS圖片模糊效果的三種實(shí)現(xiàn)方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • IOS安裝包比Android容量大的原因

    IOS安裝包比Android容量大的原因

    這篇文章主要介紹了為什么IOS安裝包比Android容量大的原因,如果你是一個(gè)IOS或者安卓開發(fā)者,學(xué)習(xí)下相關(guān)知識(shí)吧。
    2018-02-02
  • 輕松搞定iOS遠(yuǎn)程消息推送

    輕松搞定iOS遠(yuǎn)程消息推送

    這篇文章主要幫助大家輕松搞定iOS遠(yuǎn)程消息推送,討論遠(yuǎn)程推送的流程與配置過程,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 關(guān)于iOS 11下app圖標(biāo)變空白問題的解決方法

    關(guān)于iOS 11下app圖標(biāo)變空白問題的解決方法

    升級(jí)到iOS11系統(tǒng)下自己的項(xiàng)目桌面app圖標(biāo)不見了,通過查找相關(guān)的資料終于找到了解決方法,下面這篇文章主要給大家介紹了關(guān)于iOS 11下app圖標(biāo)變空白問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2017-12-12

最新評(píng)論