2010-02-25 55 views
5

我的iPhone應用程序總是崩潰,我已經在過去的一週血腥範圍縮小到這一行:Objective-C正確地複製一個NSArray?

NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error]; 

我從上面獲得正確的結果,但訪問之後應用程序崩潰(EXC_BAD_ACCESS)。 我該如何複製fetchResults的內容,以便我可以玩弄它?

我已經試過

NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]]; 

但不會崩潰的應用程序的唯一事情就是

NSArray *retVal = [[NSArray alloc] initWithArray:nil]; 

有人能幫助我嗎?我想我需要Obj-C內存管理的一課。

編輯: 這裏有崩潰的代碼比較完整的例子:

NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error]; 
[request release]; 
NSMutableArray *retVal = [NSMutableArray arrayWithCapacity:0]; 
for(Job *job in fetchResults){ 
    //NSLog(@"dev: %@",job.lastmod_device); 
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
          [job.jobkey copy], @"entitykey", 
          [NSNumber numberWithInt:[job.lastmod_device timeIntervalSince1970]], @"job_lastmod_device", 
          [NSNumber numberWithInt:[job.lastmod_server timeIntervalSince1970]], @"job_lastmod_server", 
          [NSNumber numberWithInt:[job.customer.lastmod_device timeIntervalSince1970]], @"customer_lastmod_device", 
          [NSNumber numberWithInt:[job.customer.lastmod_server timeIntervalSince1970]], @"customer_lastmod_server", 
          [NSNumber numberWithInt:[job.productionschedule_lastmod_device timeIntervalSince1970]], @"productionschedule_lastmod_device", 
          [NSNumber numberWithInt:[job.productionschedule_lastmod_server timeIntervalSince1970]], @"productionschedule_lastmod_server", nil]; 
    //NSLog(@"dict: %@", dict); 
    [retVal addObject:dict]; 
} 
return retVal; 

而且調用此方法的代碼:

NSArray *arr2 = [self retrieveJobs]; 

(就是這樣,我從來沒有使用變量)

編輯2: 即使只是用空的for循環遍歷所提取的結果,而對fetchResults對象也不做任何其他處理,從而導致應用程序崩潰。這怎麼可能?

+0

請出示你在那裏訪問的結果。 – 2010-02-25 23:46:35

+0

查看上面的修改 – kbanman 2010-02-26 11:43:05

回答

2

NSArray *retVal = [fetchResults retain]應該爲你保持一切。它沒有複製,但我希望這不是你想要做的。你的第一次嘗試應該複印一份。但是,如果你不小心,它們都容易泄漏(你的第二個例子泄漏保證)。你確定你沒有在程序中做其他事情,導致這部分代碼失敗?

這裏是做一個真正的副本,如果這就是你想要的一些選項:

NSArray *retVal = [fetchResults copy]; 
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults]; 

這兩項收益留存陣列給你。

1

您確定抓取請求正在返回數據嗎?根據文檔:

滿足從接收方獲取的請求所指定的標準以及與接收方的持久存儲協調器相關聯的持久性存儲區的對象數組。如果發生錯誤,則返回nil。如果沒有對象符合請求指定的條件,則返回一個空數組。

此外,你可以顯示代碼訪問數組?它是否與執行提取請求的方法相同?

19

你正在顛簸;這些行代碼...

NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]]; 

後兩個是簡單的泄漏。第一種是製作副本的一種方式,但是retVal = [fetchResults copy];是製作副本的更好方法。

但是,當然,你根本不需要副本。這不是問題。你繼續說,唯一不會崩潰的是一個空的結果集。

這表明兩件事之一;要麼你的結果集已損壞(不太可能),要麼你正在錯誤地訪問結果集(可能)。

「顛簸」是,您提出了一個關於崩潰的問題,而不包括崩潰的回溯或崩潰的位置。添加這些,你很可能會在短時間內得到答案。我們都是這樣做的,即使經過20多年的Objective-C,我仍然需要面對現實,退後一步,思考事情以擺脫顛簸。 )

1
NSArray *retVal = [[NSArray alloc] initWithArray:fetchResults]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults copy]]; 
NSArray *retVal = [[NSArray alloc] initWithArray:[fetchResults retain]]; 

確定fetchResults包含結果嗎? 因爲可能有「fetchResults」對象本身釋放並指向一些垃圾位置。這就是爲什麼你會崩潰。檢查並通知fetchResults是否是有效的對象。

0

要得到沒有參考原件的真實副本,您需要執行DEEP副本。一種方法是歸檔數組並將其解壓縮回NSArray。

Collections with IOS

相關問題