0

我创建了一个具有静态 NSMutableArray 的类,我希望在覆盖期间用该类的每个实例填充该数组,init因此我不必做任何比我需要的更多的编码。

我应该指出该数组完美地工作,我只是无法存储正确的数据。

这有意义吗?如果是这样,我该怎么做?

虽然我试过这样做

_instance = self;

[[MyClass getStack] addObject:_instance];

似乎我无法访问该属性的实例,并且登录后我得到的只是:

2012-07-14 22:37:58.223 Application[4497:1bb03] <MyClass: 0x92cfc70>

编辑更多代码:

我的 .h 文件:

@interface MyClass : NSObject

+ (NSMutableArray *)getStack;

我的 .m 文件:

@interface MyClass ()

@end

static NSMutableArray *stack;

@implementation MyClass

使用崩溃图像编辑

记录数组属性时NSLog(@"%@", [[[MyClass stack] objectAtIndex:0] adam]);,它在该行崩溃并给我以下错误。

崩溃错误

4

4 回答 4

1

凯文格兰特的回答很好,但有一个问题。NSArray 保留它包含的对象。因此,当您向数组添加实例时,对象实际上不会被释放,因为数组将保持对它的强引用。当然,通常 NSArray 保留它的孩子是有意义的,这样它就不会持有一个不再有效的指针,指向从它下面释放出来的对象。在这种情况下,您要在对象被释放之前手动将其从数组中删除,实际上您希望阻止数组保留它包含的对象。

一种方法是将每个实例包装在一个 NSValue 中。NSValue 有一个名为 的方法-valueWithNonretainedObject:,它听起来像。它创建一个包含一个对象但不保留该对象的 NSValue 实例。现在,当您将 NSValue 实例添加到数组时,数组会保留 NSValue 实例,而不是包含的对象,并且不会阻止实例被释放。这是代码中的示例:

static NSMutableArray *instanceArray = nil;

@implementation MyClass

+ (void)addInstance:(MyClass *)instance
{
    if (!instanceArray) instanceArray = [[NSMutableArray alloc] init];
    NSValue *value = [NSValue valueWithNonretainedObject:instance];
    [instanceArray addObject:value];
}

+ (void)removeInstance:(MyClass *)instance
{
    NSValue *valueToRemove = nil;
    for (NSValue *value in instanceArray) 
    {
        if ([value nonretainedObjectValue] == instance) 
        {
            valueToRemove = value;
            break;
        }
    }
    if (valueToRemove != nil) [instanceArray removeObject:valueToRemove];
}

- (id)init
{
    self = [super init];
    if (self != nil)
    {
        [[self class] addInstance:self];
    }
 }

 - (void)dealloc
 {
      [[self class] removeInstance:self];
      [super dealloc];
 }

 @end
于 2012-07-14T21:59:14.023 回答
0

编辑:正如已经正确指出的那样,Objective-C 容器存在过度保留问题。此外,不能保证有可用的自动释放池,因此必须明确分配。

解决这些问题的一种方法是使用根本不保留的容器,例如动态重新分配的数组或(如果是 Objective-C++)std::set< YourClass* >包含指向当前实例的指针的容器。

给定这样一个“安全”容器,基本思想保持不变:普通初始化程序添加到容器,例如myGlobal.insert(self);,而dealloc方法删除它,例如myGlobal.erase(self);

于 2012-07-14T21:42:58.220 回答
0

init将其中的每个实例添加到全局数组中很容易:

static NSMutableArray *stack = nil;

@implementation MyClass
+ (void)initialize {
    if (stack == nil)
        stack = [[NSMutableArray alloc] init];
}

+ (id)init {
    self = [super init];
    if (self) {
        [stack addObject:self];
    }
    return self;
}
@end

你的问题一定来自别的东西。要么你没有保留全局数组。或者您没有正确存储您的“财产”(例如,您没有保留它)。或者其他的东西。

于 2012-07-15T09:21:12.463 回答
0

事实证明,问题出在我创建的实例属性的名称上,例如,我为“size”创建了一个 int,为“layer”创建了一个 CALayer,但这些都被标准属性覆盖了。为了克服它,我只是将类名添加为每个属性的前缀。此外,由于格式为 %@ 而不是 %i,日志在上面崩溃了。感谢大家的帮助!

于 2012-07-15T12:06:50.880 回答