2012-04-27 5 views
0

Le projet est pour ios 5.0. J'ai mis le compte de référence automatique, de toute façon je ne suis pas capable de compiler le code si j'écris une déclaration de retenue.objectif c commutateur conserver erreur

J'ai écrit un commutateur dans une fonction, parce que je ne veux pas créer si et beaucoup d'autres branches.

Ma partie de code, il est relatif simple et semble correcte, mais semble seulement être:

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]; 

lors de l'exécution, je reçu ce message: *** - [MyClass retain]: message envoyé à l'instance désallouées 0x6e78580 et il affichera le XCode comme ligne de rupture sur la ligne [userDefaults setObject de la branche de cas.

Quelque part, j'ai vu une compilation lors de la compilation du commutateur, il va créer une classe. Mais je ne suis pas sûr dans quel langage: Java, C#, ou Obj-C et parce que j'ai quitté ma classe et j'exécute la classe switch, elle libérera la variable userDefaults et c'est la raison pour laquelle l'objet userDefaults est désalloué. Maintenant, je ne suis pas sûr de savoir comment écrire ce changement pour travailler et ressemble à professionnel. Je ne voudrais pas créer dans chaque cas la variable userDefaults et vider là. La seule solution est d'écrire ce commutateur à if-else?

que cela fonctionne:

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]; 

pourquoi?

  • ne sais pas pourquoi il ne fonctionnait, mais qu'il est écrasé à nouveau. J'ai déplacé la variable dans le code:

    interrupteur (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; 
    } 
    

Ce sombré à nouveau et je suis venu ici pour vérifier les réponses :)

j'ai vu la suggestion ci-dessous:

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

cet accident à la même ligne:

[[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"]; 
  • ce qui est faux? Je ne peux pas le croire. *** - [MyClass retenir]: message envoyé à l'instance désallouées 0x6b532c0

le MyClass est un UIViewContoller. Je fais une sélection de la langue et j'appuie sur certains boutons pour naviguer sur l'écran 1 ou 2 et je reviens et referai la sélection de la langue et il va planter, mais pas toujours. Mais quand il s'écrase toujours sur la même ligne et toujours le même message d'erreur.

ce qui a le

userDefaults setObject 

avec navigations?

---------------------------------------------- -----

Got le vrai problème: que facile de trouver la solution

-------------------------- -------------------------

J'ai écrit le: userDefaults setObject Aussi j'ai écrit: ceci est un projet ARC et il échoue chez MyClass conserver, ce qui ne peut pas être mon code.

Le code est une sélection de langue avec une feuille d'action. Si je fais une recherche que je vais avoir le lien suivant: EXC_BAD_ACCESS invoking a block

  • de là, je vois que je devrais avoir une copie produite quelque part au lieu d'un retenir. La question est pourquoi est-il nécessaire de conserver à setObject? Eh bien, parce qu'il a été ajouté un écouteur de changement ...

// [[NSUserDefaults standardUserDefaults] addObserver: auto forKeyPath: @ options "langue": contexte NSKeyValueObservingOptionNew: NULL];

le code supprimé et le contenu de la fonction de rappel déplacé après le code du commutateur, il résout le problème - pas besoin retain faire un rappel :)

J'ai voté avec tous jusqu'à signe, qui a essayé de aide-moi et accepte la solution qui était le plus "beau" code.

Merci

+0

Le deuxième code fonctionne? – Krishnabhadra

+0

il a été travaillé une fois, et s'est écrasé constamment, que je me suis déplacé à l'intérieur de la déclaration, crash nouveau –

+0

enregistrer vos opérations de comptage ref dans les instruments et attendre l'erreur – justin

Répondre

1

Pas une réponse à votre question, mais que diriez-vous amerrissage forcé le switch et l'utilisation:

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

réponse partielle:

Dans des déclarations de commutation cas Objective-C, si vous déclarez un Ivar dans un cas, vous devez entourer le cas avec des accolades, comme vous l'avez fait dans votre deuxième exemple (bien que les exemples que j'ai vus mettent l'instruction break à l'intérieur des accolades). Vos instructions de requête ne déclarent pas de variable, mais peut-être que NSUserDefaults crée un objet là-bas, ce qui rend les accolades obligatoires. (Edit: Comme Starbugs notes dans sa réponse ci-dessous, vous sont instanciation d'un objet lorsque vous écrivez @ « Langue ».)

Donc, si votre deuxième exemple fonctionne, pourquoi ne pas aller avec elle? Comment ça a l'air non professionnel? D'autant plus que les accolades supplémentaires pour les boîtiers de connexion sont standard pour Objective-C.

+0

Je ne pense pas que les accolades supplémentaires pour les commutateurs de cas sont standard pour Objective-C ... d'où vient cette information? – starbugs

+0

J'ai été présenté pour la première fois par 'Beginning iPhone 3 Development' d'Apress, par Mark et LaMarche. Cela a toujours été vrai. Si je déclare un objet dans une instruction switch-case sans accolades, il ne sera pas compilé. – Wienke

+0

Cela s'applique également à la déclaration de variables scalaires et d'objets. – Wienke

2

Ce problème n'est pas spécifique à Objective-C, mais à C/C++ en général. Vous pouvez jeter un oeil à this answer.

Le problème avec votre premier code est que le compilateur Objective-C fait un peu de magie liée à l'instanciation de NSString s qui cause le plus probablement le problème décrit dans la question liée ci-dessus. En bref: vous devez placer des accolades autour de chaque instruction case qui instancie une variable locale et @"something" fait exactement cela.

Questions connexes