version cocos2dx-3.7.1
使用SpriteFrame预加载合成的大图,如果没有马上使用,当收到ios的内存警告时就会被移除,后面再获取里面的图片时就会取不到,导致程序崩溃。解决方案为加载大图后,把里面的小图都加到自己定义的一个容器里,使其引用计数加一,避免被移除。
添加到自定义容器代码
void ResourceManager::addSpriteFramesWithFile(const std::string& plist, const std::string& textureFileName)
{
SpriteFrameCache* cache = SpriteFrameCache::getInstance();
cache->addSpriteFramesWithFile(plist, textureFileName);
// ResourceManager的_spriteFrames容器也放一份,增加SpriteFrame引用计数,避免发生内存警告时被cocos引擎移除
FileUtils* fu = FileUtils::getInstance();
std::string fullPath = fu->fullPathForFilename(plist);
ValueMap dict = fu->getValueMapFromFile(fullPath);
ValueMap& framesDict = dict["frames"].asValueMap();
for (auto iter = framesDict.begin(); iter != framesDict.end(); ++iter)
{
std::string spriteFrameName = iter->first;
SpriteFrame* spriteFrame = cache->getSpriteFrameByName(spriteFrameName);
_spriteFrames.insert(spriteFrameName, spriteFrame);
}
}
引擎代码:
void SpriteFrameCache::removeUnusedSpriteFrames()
{
bool removed = false;
std::vector<std::string> toRemoveFrames;
for (auto iter = _spriteFrames.begin(); iter != _spriteFrames.end(); ++iter)
{
SpriteFrame* spriteFrame = iter->second;
if( spriteFrame->getReferenceCount() == 1 ) // 引用计数为1时就移除
{
toRemoveFrames.push_back(iter->first);
spriteFrame->getTexture()->removeSpriteFrameCapInset(spriteFrame);
CCLOG("cocos2d: SpriteFrameCache: removing unused frame: %s", iter->first.c_str());
removed = true;
}
}
_spriteFrames.erase(toRemoveFrames);
// FIXME:. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache
if( removed )
{
_loadedFileNames->clear();
}
}