2013-08-23 49 views
3

對於EntityA與EntityB具有多對一關係的核心數據模型,我想創建一個EntityA對象列表,它們按EntityB的名稱排序相關。通常情況下做到這一點我會成立這樣的讀取請求:nsfetchedresultscontroller中段名關鍵路徑的無關係值

if (_fetchedResultsController != nil) { 
    return _fetchedResultsController; 
} 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

然後我會成立了我的請求的值(在這種情況下,它是由種名稱排序廠家的名單有些植物已經沒有種設置。 。)

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Plant" inManagedObjectContext:self.managedObjectContext]; 
NSSortDescriptor *sortDescriptorOne = [[NSSortDescriptor alloc] initWithKey:@"species.name" ascending:YES]; 
NSString *sectionKeyPath = @"species.name"; 

然後我完成它與平常的東西:

[fetchRequest setEntity:entity]; 

// Set the batch size to a suitable number. 
[fetchRequest setFetchBatchSize:20]; 

NSArray *sortDescriptors = @[sortDescriptorOne]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
managedObjectContext:self.managedObjectContext 
sectionNameKeyPath:sectionKeyPath 
cacheName:@"plantsCache"]; 

aFetchedResultsController.delegate = self; 
self.fetchedResultsController = aFetchedResultsController; 

[NSFetchedResultsController deleteCacheWithName:@"plantsCache"]; 
NSError *error = nil; 
if (![self.fetchedResultsController performFetch:&error]) { 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 

return _fetchedResultsController; 

但結果我得到的是不適合我的工作,因爲關係是可選的。所以EntityA與EntityB有一些關係,有些則沒有。當EntityA的關係值爲零時,結果控制器似乎不知道該怎麼做。

任何建議,我可以做些什麼來繼續使用關係的價值,但允許一些對象爲零的部分?

+0

實體A是植物和實體B是物種?那麼一對多的關係是從EntityB到EntityA,而不是像你的第一句話那樣呢? - 與物種無關的植物究竟發生了什麼?他們沒有提取,沒有顯示,...? –

+0

你是對的我把它倒過來了。我的意思是EntityA(工廠)與EntityB(物種)有着多對一的關係。與任何物種無關的植物出現在空白(未命名)部分,核心數據向控制檯投訴。這種行爲實際上是我想要的。但是如果我從詳細視圖返回列表視圖,添加了一個沒有物種的工廠,那麼列表將不會顯示額外的工廠項目,直到再次調用fetchedresultscontroller。最好我不想在viewWillAppear上重新填充結果控件。 – jedipixel

+0

也許可以通過向工廠實體添加一個方法(或瞬態屬性)'sectionName'並將其用作'sectionNameKeyPath'來解決未命名的部分問題(和投訴)。該方法應該返回'self.species.name'或一個空字符串。 - 我目前無法測試,所以我不知道這是否有幫助。 –

回答

3

設置一個短暫的財產Plant這樣的:

-(NSString*)speciesName { 
    return self.species ? self.species.name : @""; 
} 

您現在可以使用speciesNamesectionNameKeyPath

+0

這也需要在覈心數據模型或實體的類文件? – jedipixel

+0

需要在模型中。在模型編輯器中將其標記爲「瞬態」。 – Mundi

+0

好的,謝謝!這有很大幫助。 – jedipixel

0

用Swift 3.0進入這個版本。有兩個實體EntityA和EntityB,其中EntityA通常屬於(具有指向)某個EntityB的實體,但也可能是非獨佔的。

Swift修復是爲EntityA添加一個擴展,如果檢測到一個空條件,它將返回一個空字符串。

extension Note { 
    var bookTitleOrNil : String { 
     if let bookTitle = self.book?.title { 
      return bookTitle 
     } 
     return "" 
    } 
} 

然後替換在建立之後的fetchRequestController(FRC):

let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.managedObjectContext, sectionNameKeyPath: "book.title", cacheName: nil) 

對於使用新的擴展爲sectionNameKeyPath:

let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.managedObjectContext, sectionNameKeyPath: "bookTitleOrNil", cacheName: nil) 

然後,生成用於不同段頭時,我用了以下內容:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
    let useIndexPath = IndexPath(row: 0, section: section) // Get first item in section (all notes in a section point to same book) 
    let note = frc.object(at: useIndexPath) 
    if let bookTitle = note.book?.title { 
     return bookTitle 
    } else { 
     return "Unlinked" 
    } 
} 

因此,這些筆記首先按照它們所屬的書籍排序,如章節標題所示(儘管不屬於任何書籍的筆記出現在「未鏈接」標題下的第一個排序)。

此外,在設置FRC的fetchRequest中的排序時,需要設置主要排序描述符以使用book.title,然後進行任何其他排序,例如註釋的標題。

let sortDescriptor1 = NSSortDescriptor(key: "book.title", ascending: true) 
let sortDescriptor2 = NSSortDescriptor(key: "title", ascending: true) 
fetchRequest.sortDescriptors = [sortDescriptor1, sortDescriptor2] 

當然,人們也可以設計,使創建並避免了零的情況下這樣一個音符時,音符總是屬於一本書額外的檢查應用程序。