0

在一个小型 RTS 项目中,我有一个按钮列表,每个按钮都有一个分配给它们的建筑对象。有些建筑物非常通用,但有些则非常特殊,因此我将其中一些建筑物作为子类。

当我制作一个按钮列表时,它们每个都有一个 PEHouse 对象,一切正常。

但是一旦其中一个 PEHouse 是子类的 PEHouse,它就会立即发布,我不明白为什么。

按钮具有以下属性:

@property (nonatomic, strong) PEHouse *linkedHouse;

房子有这些价值观:

@interface PEHouse : NSObject {
    NSString *title;
}
@property (nonatomic) BOOL is_locked;

我的塔有这个设置:

#import "PEHouse.h"

@interface PETower : PEHouse <NSObject>

-(void)secondAction;
+ (PETower*)createTower;

@end

当我生成这样的常规对象列表时:

DLog(@"Building menu");
    if ([key isEqualToString:@"button_income"]) {
        [GMBuildMenu buttonFromBuilding:[PEHouse newSawmill] withIndex:1 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newQuarry] withIndex:2 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newIronMine] withIndex:3 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newMiscShop] withIndex:4 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newWeaponsShop] withIndex:5 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newArmorShop] withIndex:6 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newBazaar] withIndex:7 inDict:dict];
        [GMBuildMenu buttonFromBuilding:[PEHouse newTreasury] withIndex:8 inDict:dict];
        return YES;
    }

一切正常。当我只生成一个这样的子集构建按钮时:

 if ([key isEqualToString:@"button_military"]) {
        [GMBuildMenu buttonFromBuilding:[PEHouse newTower] withIndex:1 inDict:dict];
}

该对象在...后立即释放

有谁知道为什么会发生这种差异?

更新

代码如下所示:

+(OpenGLButton*)buttonFromBuilding:(PEHouse*)house withIndex:(int)index inDict:(NSMutableDictionary*)dict {
    OpenGLButton *new = [GMButtonMenu addButtonToMenu:dict withLabel:house.button_art andShowname:house.title];
    new.linkedHouse = house;
    CGRect buttonFrame = CGRectMake(20, ((30)*index), (28*[GMButtonMenu globalGUIScale]), (28*[GMButtonMenu globalGUIScale]));
    new.location = buttonFrame;
    new.index = index;
    new.details = house.desc;
    return new;
}

在 PEHouse 我们发现:

+ (PETower *)newTower {
    PETower *new = [PETower createTower];
    return new;
}


+ (PEHouse *)newSawmill {
    PEHouse *new = [PEHouse createDefault];
    new.title = @"Sawmill";

    new.is_large = YES;
    return new;
}
4

3 回答 3

1

首先,[GMBuildMenu buttonFromBuilding:...] 类方法的签名是什么?根据您的代码,它看起来像:

+(void)buttonFromBuilding:(PEHouse *)house withIndex:(int)index inDict:(NSDictionary *)dict 

但是,按照惯例,这样命名的方法应该返回一个按钮:

+(UIButton *)buttonFromBuilding:(PEHouse *)house withIndex:(int)index inDict:(NSDictionary *)dict

知道你的方法对 PEHouse 对象做了什么会很有趣。它强烈拥有它吗?

于 2012-12-30T16:03:07.957 回答
0

我认为这是 ARC 遵循的惯例的问题。

ARC 所做的是释放来自newalloc、或的所有内容retain,并将工厂方法视为自动发布的。copymutableCopy

我怀疑让一个类方法返回一个OpenGLButton实例会使 ARC 在你的方法末尾插入一个自动释放调用,做类似的事情

+(OpenGLButton*)buttonFromBuilding:(PEHouse*)house withIndex:(int)index inDict:(NSMutableDictionary*)dict {
    OpenGLButton *new = [GMButtonMenu addButtonToMenu:dict withLabel:house.button_art andShowname:house.title];
    // ...
    return [new autorelease];
}

然后,由于您没有将返回值分配给任何东西,因此一旦超出范围,它就会被释放。

于 2012-12-30T16:12:56.900 回答
0

+[GMBuildMenu buttonFromBuilding:withIndex:inDict:]返回新创建的按钮,但您不会将该引用存储在任何地方。由于您说您的大多数按钮不会立即被释放,我推断该方法必须在某处存储对新创建按钮的引用。

查看方法,我看到了这一行:

OpenGLButton *new = [GMButtonMenu addButtonToMenu:dict withLabel:house.button_art andShowname:house.title];

其他行都没有buttonFromBuilding:withIndex:inDict:存储new在任何地方,所以我推断+[GMButtonMenu addButtonToMenu:withLabel:andShowname:]在某处存储了对新按钮的引用。

我猜它将按钮存储在第一个参数中。您正在通过dict该论点。

调查塔按钮意外释放的这些可能原因:

  1. dict调用时为 nil [GMBuildMenu buttonFromBuilding:[PEHouse newTower] withIndex:1 inDict:dict]

  2. dict不是 nil,而是在[GMBuildMenu buttonFromBuilding:[PEHouse newTower] withIndex:1 inDict:dict]返回后不久被释放。

于 2012-12-30T22:28:43.610 回答