目标c开关保留错误

时间:2012-04-27 09:16:44

标签: objective-c design-patterns ios5

该项目适用于ios 5.0。我设置了自动引用计数,无论如何,如果我写一个retain语句,我就无法编译代码。

我在一个函数中写了一个开关,因为我不想创建if和很多if else分支。

我的代码部分相对简单,似乎正确,但似乎只是:

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

在运行时我收到此消息: *** - [MyClass retain]:发送到解除分配的实例0x6e78580的消息  它会将XCode显示为某些案例分支的[userDefaults setObject行]的分隔线。

在某些地方,我在编译Switch时看到了编译,它将创建一个类。但我不确定使用哪种语言:Java,C#或Obj-C,因为我离开了我的类并且我正在执行switch类,它将释放userDefaults变量,这就是为什么取消分配userDefaults对象的原因。现在我不知道如何编写这个开关来工作,看起来像专业。我不想在每种情况下创建userDefaults变量并在那里刷新。唯一的解决方案是将此开关写入if-else?

这是有效的:

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

为什么?

  • 不确定为什么它确实有效,但它再次崩溃了。 我已经在代码中移动了变量:

    开关(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;
    }
    

再次坠毁,我来到这里检查答案:)

我看到了下面的建议:

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

这次崩溃在同一条线上:

[[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"];
  • 出了什么问题?不敢相信。 *** - [MyClass retain]:消息发送到解除分配的实例0x6b532c0

MyClass是一个UIViewContoller。我做了一个语言选择并按下一些按钮来导航1或2屏幕,我回来再次进行语言选择,它会崩溃,但并非总是如此。但是当它崩溃时总是在同一行并且总是出现相同的错误信息。

有什么
userDefaults setObject 

导航?

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

遇到了真正的问题:比轻松找到解决方案

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

我写了:userDefaults setObject 我还写道:这是一个ARC项目,它在MyClass保留时失败,这不能是我的代码。

代码是带有操作表的语言选择。 如果我进行搜索,我会有下一个链接: EXC_BAD_ACCESS invoking a block

  • 从那里我看到我应该在某处生成副本而不是保留。 问题是为什么需要在setObject中保留? 好吧,因为它增加了一个改变听众......

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

删除了代码并且在切换代码之后移动了回调内容它解决了问题 - 不需要保留来执行回调:)

我已经投票支持所有人,并试图帮助我,并接受了最“漂亮”代码的解决方案。

由于

3 个答案:

答案 0 :(得分:2)

此问题并非特定于Objective-C,而是特定于C / C ++。您可能需要查看this answer

你的第一个代码的问题是Objective-C编译器做了一些与NSString的实例化相关的魔术,这很可能导致上面链接的问题中描述的问题。简而言之:你需要在实例化局部变量的每个case语句周围加上大括号,而@"something"正是这样做的。

答案 1 :(得分:1)

部分答案:

在Objective-C switch-case语句中,如果你在一个case中声明一个ivar,你必须用大括号括起case,就像你在第二个例子中所做的那样(虽然我看过的例子是{{1}大括号内的语句。)

你的case语句没有声明变量,但NSUserDefaults可能在那里有效地创建了一个对象,使得括号成为必需的。 (编辑:正如starbugs在下面的回答中所说,当你写@“语言”时,你 实例化一个对象。)

所以,如果你的第二个例子有效,为什么不配合呢?它看起来如何不专业?特别是考虑到用于开关的额外支架是Objective-C的标准配置。

答案 2 :(得分:1)

不是您问题的答案,而是如何放弃switch并使用:

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