0

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

我在一个函数中写了一个开关,因为我不想创建 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]: message sent to deallocated instance 0x6e78580 并且它将在某些情况下分支的 [userDefaults setObject 行将 XCode 显示为断线。

我在某处看到编译 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];

为什么?

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

    开关(选定行){

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

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

4

3 回答 3

2

这个问题不是 Objective-C 特有的,而是一般的 C/C++ 所特有的。您可能想看看这个答案

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

于 2012-04-27T13:02:38.447 回答
1

不是你的问题的答案,但如何放弃switch和使用:

NSArray * languages = [NSArray arrayWithObjects: @"English", @"German", @"French",
                                                 @"Italian", @"Spanish", nil];
NSString * selectedLanguage = [languages objectAtIndex: selectedRow];
[[NSUserDefaults standardUserDefaults] setObject: selectedLanguage forKey:@"language"];
于 2012-04-27T12:43:11.650 回答
1

部分答案:

在 Objective-C 的 switch-case 语句中,如果在 case 中声明 ivar,则必须用大括号将 case 括起来,就像在第二个示例中所做的那样(尽管我看到的示例将break语句放在大括号内)。

您的 case 语句没有声明变量,但也许 NSUserDefaults 在那里有效地创建了一个对象,从而使大括号成为强制性的。(编辑:正如starbugs 在下面的回答中指出的那样,当您编写@“Language”时,您正在实例化一个对象。)

因此,如果您的第二个示例有效,为什么不使用它呢?怎么看不专业?特别是考虑到用于大小写切换的额外大括号是 Objective-C 的标准。

于 2012-04-27T12:37:35.950 回答