Pregunta

I'm developing an iOS 4 application.

I have a class with a NSMutableDictionary property:

@interface CardHelper : NSObject <NSXMLParserDelegate>{
    ...

    NSMutableDictionary* cards;

    ...
}

@property (nonatomic, readonly) NSMutableDictionary* cards;

- (id)initWithXMLFile:(NSString *)xmlFileName andLanguage:(NSString *)language;
...

I create that NSMutableDictionary here:

...
#define kNumCards 22
...

- (id)initWithXMLFile:(NSString *)xmlFileName andLanguage:(NSString *)language
{
    if (self = [super init])
    {
        userLanguage = [NSString stringWithString:language];

        cards = [NSMutableDictionary dictionaryWithCapacity: kNumCards];

        [self parseXMLFile:[self GetResourcePathFor:xmlFileName OfType:@"xml"]];

        return self;
    }
    else
        return nil;
}

And I add elements on it here:

- (void) parser:(NSXMLParser *)parser
  didEndElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qName
{
    NSLog(@"DidEndElement: %@", elementName);
    if ([elementName isEqualToString:@"card"])
    {
        [cards setObject:currentCard forKey:currentCard.Number];
        [currentCard release];
        currentCard = nil;

        return;
    }

    ...
}

CardHelper object is created on a class called ViewController (the main view controller for my app). From this view controller I show another one:

- (IBAction)oneCardCliked:(id)sender
{
    oneViewController = [[OneCardViewController alloc] init];
    oneViewController.cardHelper = cardHelper;

    [self presentModalViewController:oneViewController animated:YES];
}

CardHelper defined in ViewController:

@interface ViewController : UIViewController {
    ...
    CardHelper* cardHelper;
    ...
}
...

I pass cardHelper to OneCardViewController to use there.

But, on OneCardViewController I try to get a card from cards, I get that cards has converted from NSMutableDictionary to NSCFString.

OneCardViewController interface:

@interface OneCardViewController : UIViewController {
    CardHelper* cardHelper;
    ...
}

@property (nonatomic, retain) CardHelper* cardHelper;

I get the exception here:

- (void) setUpTarotGame
{
    int arcaneNumber;
    arcaneNumber = [cardHelper GenerateArcaneNumber];
    NSString* number = [NSString stringWithFormat:@"%d", arcaneNumber];
    if (cardHelper == nil) {
        NSLog(@"cardHelper nil");
        return;
    }
    if (cardHelper.cards == nil)
    {
        NSLog(@"cards nil");
        return;
    }
    else
        NSLog(@"cards count = %d", [cardHelper.cards count]);
    currentCard = [cardHelper.cards objectForKey:number];

    [self setCardImageWithArcane:arcaneNumber];
}

The exception is thrown in this line:

currentCard = [cardHelper.cards objectForKey:number];

Do you know why?

¿Fue útil?

Solución

It's not being converted, it's being dealloced and the memory is being used for something else.

In your init method you are not retaining these objects :

userLanguage = [NSString stringWithString:language];
cards = [NSMutableDictionary dictionaryWithCapacity: kNumCards];

Try

userLanguage = [language copy];
cards = [NSMutableDictionary alloc] initWithCapacity:kNumCards];

instead.

Otros consejos

You are not retaining objects, they are being deallocated and the pointers are not pointing to new objects that are re-using the same memory.

Consider using ARC (Automatic Retain Counting) for you project. With ARC the compiler takes care of retain counts so you don't have to, in fact aren't allowed to. There is a refactoring that will convert a current project.

Your programming life should be much happier with ARC. :-)

cards = [NSMutableDictionary dictionaryWithCapacity: kNumCards]; 

This creates an autoreleased object. By the time you call it again, it has been released and assigned to something else, a string in this case.

You have to retain the dictionary or create a non-autoreleased one:

cards = [[NSMutableDictionary alloc] initWithCapacity:kNumCards]; 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top