2011-08-30 81 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