从类中访问实例变量

时间:2012-07-14 21:39:29

标签: objective-c class instance-variables

我创建了一个具有静态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]);它在该行崩溃并给出以下错误。

Crash error

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

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

鉴于这种“安全”容器,基本思想保持不变:正常的初始化程序添加到容器中,例如myGlobal.insert(self);dealloc方法将其删除,例如myGlobal.erase(self);

答案 2 :(得分: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

您的问题必须来自其他方面。要么你没有保留全局数组。或者您没有正确存储您的“财产”(例如,您没有保留它)。或者其他什么。

答案 3 :(得分:0)

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

相关问题