Objective-C中的嵌套工厂方法

时间:2010-03-21 21:43:01

标签: iphone objective-c xcode macos

使用嵌套工厂方法处理内存管理的最佳方法是什么,例如在以下示例中?

@interface MyClass : NSObject {
    int _arg;
}

+ (MyClass *) SpecialCase1;
+ (MyClass *) SpecialCase2;
+ (MyClass *) myClassWithArg:(int)arg;
- (id) initWithArg:(int)arg;

@property (nonatomic, assign) int arg;

@end

@implementation MyClass

@synthesize arg = _arg;

+ (MyClass *) SpecialCase1
{
    return [MyClass myClassWithArg:1];
}

+ (MyClass *) SpecialCase2
{
    return [MyClass myClassWithArg:2];
}

+ (MyClass *) myClassWithArg:(int)arg
{
    MyClass *instance = [[[MyClass alloc] initWithArg:arg] autorelease];

    return instance;
}

- (id) initWithArg:(int)arg
{
    self = [super init];
    if (nil != self) {
        self.arg = arg;
    }

    return self;
}

@end

这里的问题(我认为)是在SpecialCaseN方法返回其调用者之前刷新自动释放池[编辑:显然不是 - 请参阅下面的注释]。因此,SpecialCaseN的最终调用者不能依赖于保留的结果。 (我在尝试将[MyClass SpecialCase1]的结果分配给另一个对象的属性时,得到“[MyClass copyWithZone:]:无法识别的选择器发送到实例0x100110250”。)

想要使用SpecialCaseN工厂方法的原因是在我的实际项目中,初始化实例需要多个参数,我有一个预定义的“模型”实例列表,我希望能够创建容易。

我确信有比这更好的方法。

[编辑:每个请求添加@interface。]

2 个答案:

答案 0 :(得分:2)

为什么你认为自动释放池正在被刷新?

自动释放池不会在cocoa-touch中刷新,除非您将其刷新,或者将控制权返回给事件循环。

来自iPhone Memory Management Guide

  

自动应用套件   在一个开头创建一个池   事件循环(或事件循环迭代),   例如鼠标按下事件,和   最后发布它,所以你的代码   通常不必担心   它们。

答案 1 :(得分:1)

错误完全描述了问题:调用copyWithZone并且它未在MyClass中实现。查看它所分配的属性的属性或实现(看它是否正在复制)。此外,如果将MyClass的实例用作NSDictionary的键,则将调用copyWithZone。以下是implementing copyWithZone的一些信息。