属性和ARC

时间:2013-09-04 13:40:01

标签: ios objective-c cocos2d-iphone automatic-ref-counting

我正在使用ARC和Cocos2d 2.0作为静态库(它不使用ARC并且被编译为单独的目标)。我翻译了一个旧项目(没有ARC),我想知道以这种方式声明属性是否存在一些潜在的保留周期问题:

@interface PlayerData : NSObject <NSCoding> {
}


//Is ok to save this as if the game gets paused you may want to save this.
@property (readwrite, nonatomic) int numberOfHits;
@property (readwrite, nonatomic) bool everBeenHitInCurrentLevel;
@property (readwrite, nonatomic) int hitsForOneHearth;

我注意到我的各种场景会随着时间的推移积累内存。我还在CCLayer方法的发布方法(MyScene:CCLayer)中添加了一个CCLOG调用,它永远不会被调用。这就是我如何创建场景(我使用&#34替换; [CCDirector sharedDirector] replaceScene &#34;方法

+ (id) sceneWithLevelName:(LevelName)name
{
    CCScene *scene = [CCScene node];        
    ShooterScene * shooterLayer = [[self alloc] initWithId:name];
    [scene addChild:shooterLayer];


    return scene;    
}

编辑:当我意识到我愚蠢地没有包含对象的示例并仅使用原始数据类型时,我将在此处粘贴一些元素片段:CharacterSelection,ShooterScene和PlanetSelectionMenu:

//ShooterScene
@interface ShooterScene : CCLayer {
    HudLayer * hudLayer;
    ....
}

@property(readwrite, nonatomic) CCSpriteBatchNode* backgroundAndEnemiesBatchNode;
@property(readwrite, nonatomic) ShipEntity* playerShip;
... etc..


Please note that I do not declare member variables for properties like playerShip and backgroundAndEnemiesBatchNode beause, as far as I can understand, should suffice the property declaration (but please correct me if I am wrong or if the approach may cause issues). 

//CharacterSelectionScene
@interface CharacterSelectionScene : CCLayer {
    int currentlySelectedCharacterSpriteTag;
    CCSprite * lights;
    CCLayer * spritesLayer;    
    ...
}

//PlanetSelectionMenu
#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface PlanetSelectionMenu : CCLayer {
    CCLayer * backgroundLayer; // Added background images here
    CCLayer * alwaysPresentItems;
}

+ (id) scene;

@end

请注意,每次我从 PlanetSelectionMenu 转到 CharacterSelectionScene - 反之亦然 - 记忆会增加。但是在这种情况下,我没有使用过任何属性,只是&#34;只是&#34;向图层和batchnodes添加了对象(CCSprites)。

编辑2:这是我在分配时通过Menu-&gt; CharacterSelection-&gt; PlanetSelectionScene等看到的内容。看起来平均而言LiveBytes是4MB,因为我当时只看到一个场景然后我假设没有保留周期。那为什么我会收到那些讨厌的LOW内存消息呢?

enter image description here

1 个答案:

答案 0 :(得分:6)

虽然默认属性属性现在是strong,但它不能是那些导致保留周期的属性,因为它们是基本类型,默认为assign

引入保留周期的其他三种常见方法会浮现在脑海中:

  • 您是否在任何地方(@protocol s)实施委托模式。你的代表在必要时总是弱参考吗?
    -(id) initWithDelegate:(id) target
    {
        ...
        _target = target;   //_target should be a weak reference
        ...
    }
  • 您的任何子节点是否引用了他们的父母?
    -(id) initWithParent:(CCNode*) parentNode
    {
        ...
        _parent = parentNode; //_parent should be a weak reference.
        ...
    }
  • 执行任何块参考self
   ^{[self callSomeMethod];}

应使用对self的弱引用:

   __weak typeof(self) selfReference = self;
   ^{[selfReference callSomeMethod];}

我通常发现使用ARC查找泄漏的最佳方法是不使用Leaks工具,而是使用Allocations工具。由于我的所有场景在其符号中都倾向于使用“场景”一词,因此我会按照场景进行过滤。

由于您使用replaceScene,因此您应该一次只有一个场景(转换期间除外),因此您只应在对象摘要中看到一个对象。

enter image description here

如果你确实有一个徘徊的场景,我通常会发现最好看一下这些物体保留历史。从这里开始,我将每个保留与相应的释放配对,直到我发现保留并且不释放我的场景的罪魁祸首。更常见的是,这不是一个明显的保留周期,有一个块,或一个被声明为强而不是弱的属性。

enter image description here