1. 程式人生 > >【玩轉cocos2d-x之二十六】資料結構CCDictionary

【玩轉cocos2d-x之二十六】資料結構CCDictionary

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。

1.2.鍵(key)

uthash支援4種標準型別的鍵:整型,字串,指標和結構體,不過到了CCDictionary就只支援整型和字串型了。

  1. enum CCDictType  
  2. {  
  3.     kCCDictUnknown = 0,  
  4.     kCCDictStr,  
  5.     kCCDictInt  
  6. };  

2.CCDictElement

在瞭解CCDictionary之前還要看一下CCDictElement,很明顯,CCDictElement是CCDictionary的一個元素,包含了一個key-value。key支援整型和字串,使用的時候要注意在同一個CCDictionary中key型別必須要一致,value可以不一致。

3.API

3.1.建立

  1. //建立一個CCDictionary
  2. static CCDictionary* create();  
  3. //用一個已存在的CCDictionary來建立一個新的CCDictionary
  4. static CCDictionary* createWithDictionary(CCDictionary* srcDict);  
  5. //用一個plist來建立CCDictionary
  6. static CCDictionary* createWithContentsOfFile(constchar *pFileName);  
  7. //返回一個非autorelease物件的CCDictionary,它訥訥感夠確保在新執行緒中使用
  8. //但是你必須手動管理它的生命週期,當你不再需要它的時候,必須呼叫CC_SAFE_RELEASE
  9. static CCDictionary* createWithContentsOfFileThreadSafe(constchar *pFileName);  

3.2.查詢

  1. //返回指定字串型別key的value,如果CCDictionary的key是整型,會出現斷言
  2. CCObject* objectForKey(const std::string& key);  
  3. //返回指定整型key的value,如果CCDictionary的key是字串型,會出現斷言
  4. CCObject* objectForKey(intptr_t key);  
  5. //返回指定字串型別key的CCString,這裡假定value是CCString型,如果不是或者未找到,則返回空串
  6. const CCString* valueForKey(const std::string& key);  
  7. //返回指定整型型別key的CCString,這裡假定value是CCString型,如果不是或者未找到,則返回空串
  8. const CCString* valueForKey(intptr_t key);  

3.3.增加

  1. //插入一個key-value,如果是第一次呼叫,那麼CCDictionary的key型別會被確定為字串型,之後就不能插入整型key
  2. //如果已存在該key,則舊key-value會被釋放和移除,被新的替代
  3. void setObject(CCObject* pObject, const std::string& key);  
  4. //插入一個key-value,如果是第一次呼叫,那麼CCDictionary的key型別會被確定為整型,之後就不能插入字串型key
  5. //如果已存在該key,則舊key-value會被釋放和移除,被新的替代
  6. void setObject(CCObject* pObject, intptr_t key);  

3.4.移除

  1. //移除指定key
  2. void removeObjectForKey(const std::string& key);  
  3. void removeObjectForKey(intptr_t key);  
  4. //移除一個CCArray中keys
  5. void removeObjectsForKeys(CCArray* pKeyArray);  
  6. //通過元素來移除value
  7. void removeObjectForElememt(CCDictElement* pElement);  
  8. //移除所有的key-value
  9. void removeAllObjects();  

3.5.其他

  1. //返回一個隨機元素,這個使用得注意,因為value可以不一樣,所以返回型別每次都可能不同,在型別轉換的時候要非常小心    
  2. CCObject* randomObject();  
  3. //返回一個包含所有key的CCArray
  4. CCArray* allKeys();  
  5. //返回指定value的所有key,因為value是可以相同的,內部使用==比較兩個value是否相同 
  6. CCArray* allKeysForObject(CCObject* object);  
  7. //返回元素個數
  8. unsigned int count();  
  9. //把CCDictionary寫到一個plist中,寫入的value要求是字串型
  10. bool writeToFile(constchar *fullPath);  

4.示例

  1. // Create a dictionary, return an autorelease object.
  2. CCDictionary* pDict = CCDictionary::create();  
  3. // Insert objects to dictionary
  4. CCString* pValue1 = CCString::create("100");  
  5. CCString* pValue2 = CCString::create("120");  
  6. CCInteger* pValue3 = CCInteger::create(200);  
  7. pDict->setObject(pValue1, "key1");  
  8. pDict->setObject(pValue2, "key2");  
  9. pDict->setObject(pValue3, "key3");  
  10. // Get the object for key
  11. CCString* pStr1 = (CCString*)pDict->objectForKey("key1");  
  12. CCLog("{ key1: %s }", pStr1->getCString());  
  13. CCInteger* pInteger = (CCInteger*)pDict->objectForKey("key3");  
  14. CCLog("{ key3: %d }", pInteger->getValue());  
  15. CCString* pStr3=static_cast<CCString*>(pDict->randomObject());//這裡有問題了,因為value有不同型別,所以隨機返回時型別處理要小心
  16. CCLog("{ random key: %s }",pStr3->getCString());              //如果返回的是整型pValue3,那麼會出現斷言
  17. if(pDict->writeToFile("pdic.plist"))                          //整型的value無法寫入,會提示This type cannot appear in property list
  18.     CCLog("Write to file success!");  
Resource/pdic.plist
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"/>
  3. <plistversion="1.0">
  4.     <dict>
  5.         <key>key1</key>
  6.         <string>100</string>
  7.         <key>key2</key>
  8.         <string>120</string>
  9.         <key>key3</key>          <!key3對應整型資料無法寫入/>
  10.     </dict>
  11. </plist>

5.CCDICT_FOREACH

5.1.概況

巨集定義,用於遍歷CCDictionary的value。

  1. #define CCDICT_FOREACH(__dict__, __el__) \
  2.     CCDictElement* pTmp##__dict__##__el__ = NULL; \  
  3.     if (__dict__) \  
  4.     HASH_ITER(hh, (__dict__)->m_pElements, __el__, pTmp##__dict__##__el__)  

5.2.示例

  1. CCDictElement* pElement;  
  2. CCDICT_FOREACH(dict, pElement)  
  3. {  
  4.     constchar*key = pElement->getStrKey();  
  5.     // You certainly know the type of value, so we assume that it's a CCSprite.
  6.     CCSprite* pSprite = (CCSprite*)pElement->getObject();  
  7.     // ......
  8. }