Search code examples
objective-cdesign-patternsios5

objective c switch retain statement


The project is for iOS 5.0. I have set the automatic reference counting, anyhow I am not able to compile the code if I write a retain statement.

I wrote a switch in a function, because I don't want to create if and a lot of if else branches.

My code portion it is relative simple and seems correct, but only seems to be:

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];

switch (selectedRow) {
        
    case 0://English
        [userDefaults setObject:@"English" forKey:@"language"];
        break;
    case 1:// Deutsch 
        [userDefaults setObject:@"German" forKey:@"language"];   
        break;
    case 2://Français
        [userDefaults setObject:@"French" forKey:@"language"];         
        break;
    case 3://Italiano
        [userDefaults setObject:@"Italian" forKey:@"language"];       
        break;
    case 4://Español
        [userDefaults setObject:@"Spanish" forKey:@"language"];
        break;
        
    default:
        break;
}
// flush:
[userDefaults synchronize];

at runtime I got this message: *** -[MyClass retain]: message sent to deallocated instance 0x6e78580 and it will shown the XCode as the breakline at some case branch's [userDefaults setObject line.

Somewhere I saw a compile when compile the Switch it will create a class. But I am not sure in which language: Java, C#, or Obj-C and because I left my class and I am executing the switch class it will dealloc the userDefaults variable and that is the reason why is deallocated the userDefaults object. Now I am not sure how to write this switch to get working and looks like professional. I wouldn't like to create in each case the userDefaults variable and flush there. The only one solution is to write this switch to if-else?

this is working:

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    
    switch (selectedRow) {
            
        case 0://English
        {
            [userDefaults setObject:@"English" forKey:@"language"];
        }
            break;
        case 1:// Deutsch 
        {
            [userDefaults setObject:@"German" forKey:@"language"];   
        }
            break;
        case 2://Français
        {
            [userDefaults setObject:@"French" forKey:@"language"];         
        }
            break;
        case 3://Italiano
        {
            [userDefaults setObject:@"Italian" forKey:@"language"];       
        }
            break;
        case 4://Español
        {
            [userDefaults setObject:@"Spanish" forKey:@"language"];
        }
            break;
            
        default:
            break;
    }
    // flush:
    [userDefaults synchronize];

why?

  • not sure why It does worked, but than it crashed again. I have moved the variable inside the code:

    switch (selectedRow) {

          case 0://English
          {
              NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
              [userDefaults setObject:@"English" forKey:@"language"];
              // flush:
              [userDefaults synchronize];
          }
              break;
          case 1:// Deutsch 
          {
              NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
              [userDefaults setObject:@"German" forKey:@"language"]; 
              // flush:
              [userDefaults synchronize];  
          }
              break;
          case 2://Français
          {
              NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
              [userDefaults setObject:@"French" forKey:@"language"]; 
              // flush:
              [userDefaults synchronize];        
          }
              break;
          case 3://Italiano
          {
              NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
              [userDefaults setObject:@"Italian" forKey:@"language"];   
              // flush:
              [userDefaults synchronize];    
          }
              break;
          case 4://Español
          {
              NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
              [userDefaults setObject:@"Spanish" forKey:@"language"];
              // flush:
              [userDefaults synchronize];
          }
              break;
    
          default:
              break;
      }
    

This crashed again and I came here to check the answers

I saw the suggestion below:

NSArray * languages = [NSArray arrayWithObjects: @"English", @"German", @"French",@"Italian", @"Spanish", nil];
    NSString * selectedLanguage = [languages objectAtIndex: selectedRow];
    [[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"];

this crash at the same line:

[[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"];
  • what is wrong? can't believe it. *** -[MyClass retain]: message sent to deallocated instance 0x6b532c0

the MyClass is a UIViewContoller. I do a language selection and press some buttons to navigate 1 or 2 screen and I am coming back and do the language selection again and it will crash, but not always. But when it crashing it always at the same line and always the same error message.

What has the

userDefaults setObject 

with navigations?

#--------------------------------------------------- Got the real problem: than easy to find the solution #---------------------------------------------------

I wrote the: userDefaults setObject Also I wrote : this is an ARC project and it fails at MyClass retain, which can't be my code .

The code is a language selection with an action sheet. If I do a search I will have the next link: EXC_BAD_ACCESS invoking a block

  • from there I see I should have a copy generated somewhere instead of a retain. The question is is why is needed the retain at setObject? Well, because it was added a change listener...

//[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"language" options:NSKeyValueObservingOptionNew context:NULL];

the code removed and the content of the callback moved after the switch code it solves the problem - not needed a retain to do a callback


Solution

  • Not an answer to your question, but how about ditching the switch and using:

    NSArray * languages = [NSArray arrayWithObjects: @"English", @"German", @"French",
                                                     @"Italian", @"Spanish", nil];
    NSString * selectedLanguage = [languages objectAtIndex: selectedRow];
    [[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"];