TexturePacker 導出的圖片信息*.plist 就是CCDictionary格式。可以把它想象成類似讀xml格式的文件,不過這個不是讀xml,而是讀*.plist。並把數據讀到CCDictionary 的數據結構中,不用深究其原理。只要知道下面的接口,可以讀出數據就可以了。
原文地址:http://blog.csdn.net/jackystudio/article/details/16958587
CCDictionary在cocos2d-x中被大量的應用,比如CCTexureCache,CCSpriteFramCache等等。
1.實現原理
1.1.uthash
CCDictionary是使用uthash實現的,而過時的CCMutableDictionary則是使用STL實現,就效率而言CCDictionary至少提升了兩倍,而且CCDictionary並沒有使用C++模版,因此也很容易綁定到腳本。
uthash是一個C/C++的哈希表實現,它以宏定義的方式實現了哈希表,不僅加快了運行速度,而且與key類型無關。它的github地址是https://github.com/troydhanson/uthash。cocos2d-x的頭文件在\cocos2d-x-2.2.0\cocos2dx\support\data_support\uthash.h。
如果想在C++中直接使用也很簡單,userguide在這裏:http://troydhanson.github.io/uthash/userguide.html。可以很方便地進行增加,刪除,查找,計數,迭代,排序等操作。
1.2.鍵(key)
uthash支持4種標準類型的鍵:整型,字符串,指針和結構體,不過到了CCDictionary就只支持整型和字符串型了。
- enum CCDictType
- {
- kCCDictUnknown = 0,
- kCCDictStr,
- kCCDictInt
- };
2.CCDictElement
在瞭解CCDictionary之前還要看一下CCDictElement,很明顯,CCDictElement是CCDictionary的一個元素,包含了一個key-value。key支持整型和字符串,使用的時候要注意在同一個CCDictionary中key類型必須要一致,value可以不一致。
3.API
3.1.創建
- //創建一個CCDictionary
- static CCDictionary* create();
- //用一個已存在的CCDictionary來創建一個新的CCDictionary
- static CCDictionary* createWithDictionary(CCDictionary* srcDict);
- //用一個plist來創建CCDictionary
- static CCDictionary* createWithContentsOfFile(const char *pFileName);
- //返回一個非autorelease對象的CCDictionary,它訥訥感夠確保在新線程中使用
- //但是你必須手動管理它的生命週期,當你不再需要它的時候,必須調用CC_SAFE_RELEASE
- static CCDictionary* createWithContentsOfFileThreadSafe(const char *pFileName);
3.2.查找
- //返回指定字符串類型key的value,如果CCDictionary的key是整型,會出現斷言
- CCObject* objectForKey(const std::string& key);
- //返回指定整型key的value,如果CCDictionary的key是字符串型,會出現斷言
- CCObject* objectForKey(intptr_t key);
- //返回指定字符串類型key的CCString,這裏假定value是CCString型,如果不是或者未找到,則返回空串
- const CCString* valueForKey(const std::string& key);
- //返回指定整型類型key的CCString,這裏假定value是CCString型,如果不是或者未找到,則返回空串
- const CCString* valueForKey(intptr_t key);
3.3.增加
- //插入一個key-value,如果是第一次調用,那麼CCDictionary的key類型會被確定爲字符串型,之後就不能插入整型key
- //如果已存在該key,則舊key-value會被釋放和移除,被新的替代
- void setObject(CCObject* pObject, const std::string& key);
- //插入一個key-value,如果是第一次調用,那麼CCDictionary的key類型會被確定爲整型,之後就不能插入字符串型key
- //如果已存在該key,則舊key-value會被釋放和移除,被新的替代
- void setObject(CCObject* pObject, intptr_t key);
3.4.移除
- //移除指定key
- void removeObjectForKey(const std::string& key);
- void removeObjectForKey(intptr_t key);
- //移除一個CCArray中keys
- void removeObjectsForKeys(CCArray* pKeyArray);
- //通過元素來移除value
- void removeObjectForElememt(CCDictElement* pElement);
- //移除所有的key-value
- void removeAllObjects();
3.5.其他
- //返回一個隨機元素,這個使用得注意,因爲value可以不一樣,所以返回類型每次都可能不同,在類型轉換的時候要非常小心
- CCObject* randomObject();
- //返回一個包含所有key的CCArray
- CCArray* allKeys();
- //返回指定value的所有key,因爲value是可以相同的,內部使用==比較兩個value是否相同
- CCArray* allKeysForObject(CCObject* object);
- //返回元素個數
- unsigned int count();
- //把CCDictionary寫到一個plist中,寫入的value要求是字符串型
- bool writeToFile(const char *fullPath);
4.示例
- // Create a dictionary, return an autorelease object.
- CCDictionary* pDict = CCDictionary::create();
- // Insert objects to dictionary
- CCString* pValue1 = CCString::create("100");
- CCString* pValue2 = CCString::create("120");
- CCInteger* pValue3 = CCInteger::create(200);
- pDict->setObject(pValue1, "key1");
- pDict->setObject(pValue2, "key2");
- pDict->setObject(pValue3, "key3");
- // Get the object for key
- CCString* pStr1 = (CCString*)pDict->objectForKey("key1");
- CCLog("{ key1: %s }", pStr1->getCString());
- CCInteger* pInteger = (CCInteger*)pDict->objectForKey("key3");
- CCLog("{ key3: %d }", pInteger->getValue());
- CCString* pStr3=static_cast<CCString*>(pDict->randomObject());//這裏有問題了,因爲value有不同類型,所以隨機返回時類型處理要小心
- CCLog("{ random key: %s }",pStr3->getCString()); //如果返回的是整型pValue3,那麼會出現斷言
- if(pDict->writeToFile("pdic.plist")) //整型的value無法寫入,會提示This type cannot appear in property list
- CCLog("Write to file success!");
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"/>
- <plist version="1.0">
- <dict>
- <key>key1</key>
- <string>100</string>
- <key>key2</key>
- <string>120</string>
- <key>key3</key> <!key3對應整型數據無法寫入/>
- </dict>
- </plist>
5.CCDICT_FOREACH
5.1.概況
宏定義,用於遍歷CCDictionary的value。
- #define CCDICT_FOREACH(__dict__, __el__) \
- CCDictElement* pTmp##__dict__##__el__ = NULL; \
- if (__dict__) \
- HASH_ITER(hh, (__dict__)->m_pElements, __el__, pTmp##__dict__##__el__)
5.2.示例
- CCDictElement* pElement;
- CCDICT_FOREACH(dict, pElement)
- {
- const char*key = pElement->getStrKey();
- // You certainly know the type of value, so we assume that it's a CCSprite.