iOS 5:某些引用未被保留

时间:2011-11-17 01:26:52

标签: objective-c ios5

我现在看到一些有趣的行为,我正在使用iOS 5和Xcode 4.2。我有一个包含UIImage变量和NSString变量的单例类,但由于某种原因,即使我正在使用属性,也永远不会保留UIImage变量。我在其他项目中使用了相同的代码用于单例,它总是运行良好,但在iOS 5中看起来很糟糕。顺便说一下,我不使用ARC。

以下是头文件的示例:

@interface MYSingleton : NSObject {

    NSString *aString;
    UIImage *anImage;
}

@property (nonatomic, retain) NSString *aString;
@property (nonatomic, retain) UIImage *anImage;

+ (MYSingleton *) instance;

@end

这是相应的实现文件:

@implementation MYSingleton

static MYSingleton *instance = nil;

@synthesize aString, anImage;

- (void) dealloc {
    [aString release];
    [anImage release];
    [super dealloc];
}

+ (MYSingleton *) instance {
    @synchronized(self) {
        if (instance == nil) {
            [[MYSingleton alloc] init]; // assignment not done here
        }
    }

    return instance;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (instance == nil) {
            instance = [super allocWithZone:zone];
            return instance; 
        }
    }

    return nil; 
}

- (id)copyWithZone:(NSZone *)zone {
    return self;    
}

- (id)retain {
    return self;    
}

- (unsigned)retainCount {
    return UINT_MAX;  
}

- (void)release {
    // do nothing    
}

- (id)autorelease {
    return self;
}

@end

根据大众需求,以下是我为UIImage变量赋值的方法:

- (void)imagePickerController:(UIImagePickerController  *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    id image = [info objectForKey:UIImagePickerControllerOriginalImage];

    MYSingleton *m = [MYSingleton instance];
    m.anImage = image
}

我还注意到iOS 5中可能存在相关差异,但我创建了一个类别。此类别适用于UIDevice。我添加了一个将平台作为字符串返回的方法。我将字符串缓存在我在类别实现文件顶部声明的静态变量中。第一次调用该方法时,静态变量为nil,因此计算该值并将其存储在静态变量中。在后续调用该方法时,将返回缓存的变量。这在iOS 4中运行良好,但是在5次多次调用此方法时会抛出EXEC_BAD_ACCESS错误(除非我单步执行代码)。

任何帮助都非常感激。

1 个答案:

答案 0 :(得分:1)

首先,那个单身人士是一堆废话(是的,我知道这是来自文档 - 仍然是一堆废话)。如果你想实现一个单例,只需执行:

@implementation MYSingleton
+ (id)sharedInstance
{
     static MYSingleton *instance = nil;
     static dispatch_once_t once;
     dispatch_once(&once, ^{
          instance = [[self alloc] init]; 
     });
     return instance;
}
... etc ...
@end

所有其余的都是浪费打字。

其次,您不会显示与崩溃事物相关的代码。但最好的猜测是,你有正在执行的代码:

anImage = [... some random method that returns an image....];

当你的意思是:

self.anImage = [ ... ];

也就是说,您没有使用设置器,并且不保留图像。也许这是你最近介绍的一个变化。可能由于缓存,图像在先前版本中是单例。

很难说没有看到更多代码。