Singleton issues


#1

When implementing the ImageCache class in this chapter i experienced the following error at the point of touching the “Use” button on the Camera view:

*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** +[ImageCache<0x6220> init]: cannot init a class object.’

I double checked my code a few times and it was definitely like for like with the book. While debugging i established that the error was being raised by the sharedImageCache method at the point when it executes:

Anyway i decided to dig around a bit and try to work out what the issue was as the error message didn’t really make sense to me, the code looked fine to me based on my limited knowledge.

I found the following source of information in Apple’s documentation: developer.apple.com/mac/library/ … jects.html

At the bottom of the page it details how to implement a singleton class so i copied the method used there which gave me the following code in ImageCache:

[code]#import “ImageCache.h”

@implementation ImageCache

static ImageCache *sharedImageCache = nil;

#pragma mark Singleton stuff

+(ImageCache *)sharedImageCache
{
if (sharedImageCache == nil) {
sharedImageCache = [[super allocWithZone:NULL] init];
}
return sharedImageCache;
}

+(id)allocWithZone:(NSZone *)zone
{
return [[self sharedImageCache] retain];
}

-(id) retain
{
return self;
}

-(NSUInteger)retainCount
{
return NSUIntegerMax; // denotes and object can’t be released
}

-(void)release
{
// do nowt
}

-(id)autorelease
{
return self;
}

-(id)init
{
[super init];
dictionary = [[NSMutableDictionary alloc] init];
return self;
}
[/code]

After making these changes my program works and i’m able to take and assign pictures to Possession objects successfully. It took me a few days to get to this point so i’m relieved.

I just don’t fully understand why the original code as in the book didn’t work? Has there been a change for iOS 4.0 that makes the code invalid?

Thanks for any help with this.


#2

Not an issue with 4.0, that exception is saying you sent the message init to the class ImageCache - instead of an instance of ImageCache.

Without seeing the code, I can’t tell where it was happening.


#3

Sorry here’s the full ImageCache code that causes the error, i’ve retyped it a couple of times so I must be making the same mistake repeatedly but not realising. I bet its something really simple and i’ll feel dumb haha

[code]//
// ImageCache.h
// Homepwner
//

#import <UIKit/UIKit.h>

@interface ImageCache : NSObject
{
NSMutableDictionary *dictionary;
}
+(ImageCache *)sharedImageCache;
-(void)setImage:(UIImage *)i forKey:(NSString *)s;
-(UIImage *)imageForKey:(NSString *)s;
-(void)deleteImageForKey:(NSString *)s;
@end
[/code]

[code]//
// ImageCache.m
// Homepwner
//

#import “ImageCache.h”

static ImageCache *sharedImageCache;

@implementation ImageCache

#pragma mark Singleton stuff

+(ImageCache *)sharedImageCache
{
if (!sharedImageCache) {
sharedImageCache = [[ImageCache alloc] init]; <<----- EXCEPTION RAISED BY THIS LINE
}
return sharedImageCache;
}

+(id)allocWithZone:(NSZone *)zone
{
if (!sharedImageCache) {
sharedImageCache = [super allocWithZone:zone];
return sharedImageCache;
} else {
return nil;
}
}

-(void)release
{
// op
}

-(id)init
{
[super init];
dictionary = [[NSMutableDictionary alloc] init];
return self;
}

#pragma mark Accessing the cache

-(void)setImage:(UIImage *)i forKey:(NSString *)s
{
[dictionary setObject:i forKey:s];
}

-(UIImage *)imageForKey:(NSString *)s
{
return [dictionary objectForKey:s];
}

-(void)deleteImageForKey:(NSString *)s
{
[dictionary removeObjectForKey:s];
}

@end
[/code]

Thanks for helping


#4

I’ve just retyped again and now its working haha, how frustrating…i’ve no idea what mistake i was making though? Maybe it was in the allocWithZone method. Who knows?

Anyway sometimes i suppose it just helps talking about it with someone and the issue gets sorted. Still, frustrating that i can’t recreate the issue now and understand my mistake.

Thanks


#5

Hi,

It’s obviously all ok now but if you’d had

sharedImageCache = [[ImageCache init] alloc];

you’d have got the same error on that line - easily done and hard to spot.

Gareth


#6

yeah maybe that was it, i rewrote it a few times so must have made the same mistake repeatedly, never mind…thanks for responses anyway