3

对于 EntityA 与 EntityB 具有多对一关系的核心数据模型,我想创建一个 EntityA 对象列表,按与之相关的 EntityB 的名称排序。通常要做到这一点,我会像这样设置获取请求:

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 的关系的值为 nil 时,结果控制器似乎不知道该怎么做。

有什么建议我可以做些什么来继续使用关系的值制作部分但允许某些对象为零?

4

2 回答 2

3

像这样设置瞬态属性Plant

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

您现在可以speciesName用作sectionNameKeyPath.

于 2013-08-23T10:01:03.800 回答
0

使用 Swift 3.0 遇到了这个问题。有两个实体 EntityA 和 EntityB,其中 EntityA 通常属于(具有指向)某个 EntityB 的指针,但也可能是无主的。

Swift 修复是向 EntityA 添加一个扩展,如果检测到 nil 条件,则返回一个空字符串。

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]

当然,人们也可以设计应用程序,以便在创建便笺时通过额外检查使便笺始终属于一本书,从而避免出现 nil 情况。

于 2017-04-07T04:14:33.210 回答