2013-02-23 143 views
5

將新的Core Data模型版本添加到我的應用後,我執行了輕量級遷移,顯然已成功完成。遷移後的文件加載正常,但在第一次嘗試通過特定關係訪問屬性時,該應用程序崩潰,出現NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'。這種關係在遷移之前運行良好。我從其他帖子瞭解到,4294967295確實是-1,但我可以在我的應用/數據中識別出36個項目的唯一情況是數據模型中有36個實體(作爲參考,正在獲取的關係有58個項目在其表格中)。核心數據遷移後的NSRangeException

問題:

我的問題是:根據我得到的錯誤,我已經做了以下的故障排除,有沒有一種模式的變化,可以通過輕量級遷移,但腐敗一路上的數據,導致着名的例外?我將嘗試將幾個版本的遷移劃分爲更小的塊,以便隔離或避免該問題,但能夠專注於可能存在錯誤的特定模式更改會很好。

失敗:

用下面的代碼中的「爲MyObject」時發生該故障:

[[self object2] text]; 

的Object2的關係是一對一,非可選兩種方式和既不向前也不數據模型之間反比關係發生了變化。 text屬性可能不相關,因爲發生錯誤時,awakeFromFetch未在object2中到達。如果在上述語句之前將[self object2]分配給變量,則分配成功並報告data: <fault>

數據庫:

在sqlite3的數據庫來看,我注意到以下幾點:

  1. 正向和反向關係的指數值似乎是在每個表是正確的。
  2. object2表具有兩個反向關係列,而不是遷移前的列(前ZMYOBJECT和其他Z2_MYOBJECT,對於所有行都爲空)。沒有其他關係被添加來解釋這一欄。
  3. Z_PRIMARYKEY表中,遷移後的所有條目顯示-1Z_MAX,而在遷移之前,它們對於空表顯示爲零,對於已填充的表顯示爲最大行數。手動更新Z_MAX到合適的值沒有幫助例外。所有Z_SUPER值都是正確的。

我設置了一個映射模型來查看是否有任何東西看起來與自動映射有關,但一切看起來都很好。

總體架構更改

在數據模型的源代碼版本,有共有十四實體,其中只有四個已經填充了數據(應用程序仍處於開發階段)。 7個是頂級實體,7個是三個頂級實體的子實體。

在目標版本的數據模型中,添加了22個實體,一些頂級實體和一些子實體,有幾十個關係,其中一些添加到現有實體中。

某些屬性和關係已從現有實體中刪除,而其他屬性已添加。沒有更改數據類型或關係設置,沒有重命名屬性或關係,也不需要特殊映射。

更新(2/25/12):當我開始研究一個新的中間模型時,我記得我已經將一些實體的類從NSManagedObject更改爲NSManagedObject子類,但是沒有生成類文件。我沒有懷疑這會導致問題,並且實際上,創建所有類文件對異常沒有幫助。我只是想指出,作爲模型之間的另一個變化。

結論:

這是胡亂猜測,但如果36單位數是不是巧合,似乎在「爲MyObject」試圖在「對象2」故障它沒有一個有效的參考對於表並且試圖加載表號-1,導致異常。然而,簡單的[self object2]賦值成功的事實並不符合該結論。

任何想法?

回答

2

通過多次增量遷移工作,我能夠確定是什麼導致了問題和解決方案。

問題:

一個現有實體的數據在當前的模型沒有子實體。如果我創建了一個簡單地添加一個子實體的新模型,它不包含任何屬性或關係,並且沒有其他更改,那麼NSRangeException,Z_MAX觀察和我的問題中記錄的相反關係的翻倍都會發生。

解決方案是:

觀察以下對上面的情況是「成功的」輕量遷移失敗後,我創建映射模型。由於唯一的變化是一個額外的實體,除了一個實體映射外,其他所有實體都是直接的。問題是如何處理單個附加實體。

默認情況下,沒有任何屬性或關係的添加實體顯示所有父級屬性的屬性和關係映射。所有映射默認情況下都有空的值表達式,我認爲這意味着它只會在遷移期間跳過它們。顯然,這不是真的。通過刪除實體映射中的所有屬性和關係映射,然後關閉推斷映射,遷移成功進行。

我仍然必須解決所有剩餘的實體,並將嘗試使用此方法批量執行其餘所有計劃的屬性和關係。

+0

你是如何選擇你的映射模型的?關閉自動遷移後? – 2013-07-03 09:12:58

+0

@JoãoNunes一旦禁用了自動遷移,只要源和目標散列匹配,它就會自動選擇您的映射模型。只要您在創建映射模型後尚未修改數據模型,它們就應該匹配。不幸的是,有時他們不這樣做,正如這裏所說:(http://stackoverflow.com/questions/10894383/core-data-mapping-model-version-hashes-not-matching-to-source-model-version-hash )。打開核心數據遷移調試模式可以幫助解決未選擇映射模型的問題。 – 2013-07-03 15:56:28

+0

感謝您的提示。我爲遷移添加了調試,但仍然存在問題。我在這裏創建了一個問題:http://stackoverflow.com/questions/17464414/core-data-mapping-model-not-working-with-correct-hashes – 2013-07-04 07:50:55

1

當我遇到此問題時,您的帖子很有幫助。謝謝。 [您是否報告過該錯誤?]

下面是一些更多的實驗結果,但是,唉,不是一個很好的解決方案。

  • 我的模式更改類似地添加了一個沒有附加屬性或關係的實體子類型。錯誤信息與您的一樣,除了邊界是[0 .. 19]。這確實對應於20個實體類型,驗證了你的假設。與您的情況一樣,遷移完成後嘗試訪問實體屬性時發生錯誤。

  • 將虛擬屬性和虛擬自我關係添加到新的實體類型並不能避免遷移後的崩潰。 (不過,我沒有新的實體類型爲唯一架構變化試驗,因爲我之前推該模式改變Alpha版測試人員)

  • 我觀察Z2_MYOBJECT柱和Z_PRIMARYKEY.Z_MAX = -1症狀爲其他成功遷移後模式更改,所以這些可能根本就沒有問題。 -1值被適當的最大值懶惰地替換。額外的列可能在遷移過程中使用。

  • 在我的情況下,新實體的超類型具有有序的多對多關係。在整個數據存儲僅包含一個對象實例(該實體類型的實例沒有外出關係鏈接)的非常簡單的情況下,模式遷移成功。它確實有額外的Z2_MYOBJECT列和Z_PRIMARYKEY.Z_MAX = -1值,但從那裏添加對象時,生成的數據存儲工作正常。

  • 我試着創建一個映射模型,但沒有成功讓Core Data應用它。關閉推斷的映射只是讓Core Data根本無法遷移。 它有一個竅門嗎?我是否必須編寫自定義遷移代碼來調用映射模型?這是Xcode 4.6.2,所以舊的bug早已消失。

  • 當使用GIT中向後或向前滾動碼&數據模型進行實驗,這似乎是必要的:(1)關閉&重新打開Xcode項目和(2)做一個乾淨的構建。否則Xcode可能會崩潰和/或離開混淆狀態。

  • 爲了實驗向後滾動,則必須刪除.momd/目錄或目標的iOS模擬器/設備的整個應用程序(或部署通過iTunes或TestFlight應用程序),因爲通過重新部署的Xcode不會刪除過時的文件(如.mom.omo數據模型定義),然後讓應用程序執行實際部署的應用程序無法做到的輕量級遷移。

  • 關於用於添加的實體類型的實體映射,請注意,當Core Data應用映射模型時,它將實體從舊數據存儲複製到新實體。它沒有修改表格。除非要刪除它們,否則不希望它「跳過」屬性(包括繼承的屬性)。

  • 但是,由於架構更改添加了一個實體類型,該實體沒有要遷移的實例,因此其自定義映射模型規則無關緊要。

因此我不知道別的東西造成的死機停下來,像吃剩的實驗.mom文件或自定義的遷移代碼。你的解決方法是否成立?

經過2天的試驗,我決定我的阿爾法測試人員必須在這次沒有數據遷移的情況下生活。幸運的是,這沒有生產客戶。但它並沒有讓我對Core Data有信心。

+0

感謝您的補充信息。在解決了這裏提到的問題之後,根據我的回答,我遇到了另一個引起我注意的反覆出現的問題:(http:// stackoverflow。COM /問題/ 10894383 /核心數據映射模型版本哈希值 - 不匹配 - 源模型版本哈希)。提供給這個問題的答案並沒有解決我的問題,所以我增加了一個賞金,但沒有得到任何迴應。我沒有報告錯誤,因爲我希望上個月在本地Cocoa會議上參加核心數據會議,看看專家是否知道解決方案。不幸的是,我無法參加。 – 2013-05-22 18:02:15

+0

通常,您不需要編寫自定義遷移代碼,但有幾件事情可能會阻止映射模型正常工作。我在上面的評論中提到了一個關聯的問題。您需要檢查映射模型中的哈希值與源數據文件和活動模型版本中的哈希值。查看這個問題的答案,以獲取有關啓用Core Data調試的詳細信息,如果尚未這樣做:http://stackoverflow.com/questions/12835950/debug-core-data-migration-to-compare-hash-values – 2013-05-22 18:07:34

1

在自動輕量級遷移後訪問特定實體的任何實例時,在添加核心數據模型版本後,我擁有相同類型的NSRangeException。在我的情況下,範圍也與我的模型中的實體數量相對應。

我使用File > New > File...,然後選擇Core Data > Mapping Model,生成了Xcode 4.6(4H127)的映射模型。這導致崩潰至(d)演變成-[NSSymbolicExpression length]: unrecognized selector sent to instance...

解決方案

在我的情況的問題是我造成初始崩潰的實體有一個名爲size關係,這是蘋果的Predicate Programming Guide上市的保留字。映射模型的檢查發現,保留字已在值表達式被資本化的關係:

FUNCTION($manager, "destinationInstancesForEntityMappingNamed:sourceInstances:" , "PNSizeOptionToPNSizeOption", $source.SIZE)

我發現Core Data Model Versioning and Data Migration Programming Guide解決方案:

自定義值表達式保留字:如果使用自定義值 表達式,則必須使用#(例如$ source。#size)轉義保留字,例如SIZE,FIRST和最後的 。

不幸的是,Xcode的算法生成映射模型不承認的保留字,我不得不在關係映射檢查器更改到$source.#size表達的關鍵路徑。這解決了這個問題。我假設核心數據的推斷映射模型在輕量級遷移期間遇到了類似的問題。

這種類型的碰撞可能還有其他原因,所以此解決方案可能不適用,但可能需要檢查模型中的屬性名稱與Predicate Programming Guide中的保留字列表。