2011-08-30 77 views
0

该计划的一个组成部分采用文本从一个的UITextField,它复制到一个可变的字符串,然后执行试图改变一个不可改变的对象随机抛出

 sharedManager.ce_name=name.text 


    [sharedManager.ce_name replaceOccurrencesOfString:@" " withString:@"%20" 
    options:NSLiteralSearch range:NSMakeRange(0, [sharedManager.ce_name length])]; 

在这一点上它总是给我“试图改变一个不可改变的对象“ - 这是不是随机

我第一次得到这个错误我把它改成

sharedManager.ce_name=(NSMutableString *)name.text 

这仍然给了我试图改变一个不可改变的对象错误,但我t会随机发生 - 奇怪的权利?

然后我把它改为

NSMutableString *mutable_name = [NSMutableString stringWithString:name.text]; 

    sharedManager.ce_name=mutable_name; 

它尚未失败对我做这种方式,但我相信,我还没有找到解决方案。

我的问题:

1)莫非是事实,这是第一次修正后随机做它表明我有一些根深蒂固的内存管理问题?

2)为什么C风格的演员不修复它?

3)我目前的修补程序会工作吗?

感谢您的时间:)

回答

4

这里的问题是您使用铸造的方式。当你投射一个指针时,它就开始处理那个位置上的内存,就像它是代表该类型的数据块一样。所以如果我有一个指向Car类的指针:Car * mycar;并且我将它转换为Person对象:(Person *)mycar;程序将尝试访问内存,就像它一样指向一个Person对象。然而,除了旧电视连续剧以外,汽车不是一个人,所以当它尝试访问这个成员或调用函数时,它会尝试去一个内存位置,该位置包含除期望值之外的内容,并且未定义事情发生(通常是崩溃)。

NSMutableString和NSString在这方面是不兼容的,所以从一个铸造到另一个会导致可怕的时代。你的修正([NSMutableString stringWithString:])是正确的解决方案。

+0

非凡!谢谢你解决我的问题。然而,我最欣赏的事情是,你解释了铸造的真实性。我从来没有想过这样:) –

2
  1. 如果它是随机这样做,就意味着name.text有时一个可变的字符串,有时一个不变的字符串。

  2. 像这样的对象之间的投射不会改变对象的类别。它不会让你的不可变对象变化。

  3. 这“修复”可能是做的最好的方式(在从我可以在代码中看到至少你是显示)

2

如果没有至少看到所涉及的变量的声明,很难说,但最终的解决方案,创建一个新的可变字符串可能是正确的解决方案。至于你的问题,

  1. 本身不是内存管理,但它可能覆盖它不应该有的地方。
  2. 强制转换不能改变对象的基本类型。你有(可能是)一个NSString,并且世界上所有的投射都不能把它变成一个NSMutableString。
  3. 就像我说的,可能,但我们需要看到更多的代码来确保。这当然是一个更好的解决方案。
+0

所以等待, 如果 sharedManager.ce_name 是NSMutable字符串,则: sharedManager.ce_name =(*的NSMutableString)name.text 不会让sharedManager.ce_name保持一个不变的字符串? –

+0

ce_name必须是可变的,否则它不应该让你编译。名称是一个UITextField,对吗?然后name.text是一个NSString,不可变,所以通过将它转换为一个可变字符串,你只是告诉obj-c查看所有错误的方法。我的猜测是,如果且仅当文本中实际存在空格时才会出错,否则它不会尝试更改它,以免发生错误。 – Kevin