NSManagedObject 自定义访问器方法

发布于 2024-11-10 12:19:05 字数 4154 浏览 3 评论 0原文

我希望有人能给我一些有用的建议,告诉我该怎么做。

我一直在尝试多种方法来对一组具有 client<-->>job 关系的实体进行排序,这些实体基于 ​​client 属性的自定义访问器作为第一个排序描述符,然后作业描述属性作为第二个排序描述符。

我首先尝试使用名为 Client.sortValue 的瞬态属性,并发现瞬态属性不能用作 NSFetchedResultsController 的排序描述符。所以我将属性 Client.sortValue 更改为非瞬态的。

我从不将 sortValue 的值保存到持久存储中。相反,我使用自定义访问器。显然,当运行 fetechedResultsController PerformFetch: 方法时,没有使用自定义访问器方法。当我进行日志记录时会调用它,如下面的代码所示。我可以看到,在自定义访问器中使用断点并查看堆栈跟踪就是这种情况。当运行 PerformFetch 时,我没有看到它在访问器方法上中断,但是当日志记录完成时,它确实在访问器方法上中断。

(奇怪的是,今天早些时候我在某些情况下让它工作,但在其他情况下却不行。它显然是按照我想要的方式排序的,但是在我重构代码以追踪它工作的条件之后,我还没有看到它再次工作。)

我尝试了各种自定义访问器方法,包括以下方法:

- (NSString *) primitiveSortValue {

    NSString *retVal = nil;

    [self willAccessValueForKey:@"lastName"];
    [self willAccessValueForKey:@"firstName"];
    [self willAccessValueForKey:@"company"];

    if (![self.lastName isNullString] ) retVal = [self primitiveValueForKey:@"lastName"]; 
    else if (![self.firstName isNullString] ) retVal = [self primitiveValueForKey:@"firstName"]; 
    else if (![self.company isNullString] ) retVal = [self primitiveValueForKey:@"company"]; 
    else retVal = @"";

    [self didAccessValueForKey:@"lastName"];
    [self didAccessValueForKey:@"firstName"];
    [self didAccessValueForKey:@"company"];


    NSLog(@"Sort Value: %@", retVal);

    return retVal;
}  

在决定覆盖原始访问器方法之前我也尝试过这个方法:

- (NSString *) sortValue {

    NSString *retVal = nil;

    if (![self.lastName isNullString] ) retVal = self.lastName; 
    else if (![self.firstName isNullString] ) retVal = self.firstName; 
    else if (![self.company isNullString] ) retVal = self.company; 
    else retVal = @"";


    NSLog(@"Sort Value: %@", retVal);

    return retVal;
} 

这是我的 fetchedResultsController 方法:

#define CLIENT_SORT_KEY @"clientOfJob.sortValue"
- (NSFetchedResultsController *) fetchedResultsController {
    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Job" inManagedObjectContext:dataInterface.managedObjectContext];

    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:10];

    if (segmentedControl.selectedSegmentIndex == 0) {  // sort by client, then job dscription
        NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:CLIENT_SORT_KEY ascending:YES];
        NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"jobDescription" ascending:YES];

        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];

        NSFetchedResultsController *aFetchedResultsController = 
        [[NSFetchedResultsController alloc] 
         initWithFetchRequest:fetchRequest 
         managedObjectContext:dataInterface.managedObjectContext 
         sectionNameKeyPath:CLIENT_SORT_KEY
         cacheName:nil]; 


        aFetchedResultsController.delegate = self;

        self.fetchedResultsController = aFetchedResultsController;

        [aFetchedResultsController release];
        [fetchRequest release];
        [jobSortDescriptor release];
        [clientSortDescriptor release];
        [sortDescriptors release];        
    }
    else { // sort by job description
        ...        }

    NSError *error = nil;

    if (![fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved Error %@, %@", error, [error userInfo]);
        abort();
    } 

    int i = 0;
    for (id<NSFetchedResultsSectionInfo> sectionItem in [fetchedResultsController sections]){
        NSLog(@"\n***********\nsection %d name %@\n-----------\n",i++, [sectionItem name]);
        int j = 0;
        for (Job *jobItem in [sectionItem objects]) {
            NSLog(@"%d job: %@, client: %@\n",j, jobItem.jobDescription, jobItem.clientOfJob.sortValue);
        }
    }

    return fetchedResultsController;

}

I hope someone can give me some helpful suggestions on what to do about this.

I have been trying several ways to sort a set of entities that have the relationship client<-->>job based on a custom accessor for a property of client as the first sort descriptor, and then the job description property as the second sort descriptor.

I first tried to use a transient property, called Client.sortValue, and discovered that transient properties can't be used as sort descriptors with the NSFetchedResultsController. So I changed the property Client.sortValue to be non-transient.

I never save a value for sortValue to the persistent store. Instead, I use a custom accessor. Apparently, the custom accessor method is not being used when the fetechedResultsController performFetch: method is run. It is called when I do logging, as shown in the code below. I can see that this is the case using a break point in the custom accessor and viewing the stack trace. I don't see it break on the accessor method when the performFetch is run, but it does break on the accessor method when the logging is done.

(Strangely, I had it working earlier today under some circumstances, but not others. It was obviously being sorted the way I wanted it to be, but after I refactored my code to track down the conditions where it worked, I have not seen it work again.)

I have tried various custom accessor methods, including the following:

- (NSString *) primitiveSortValue {

    NSString *retVal = nil;

    [self willAccessValueForKey:@"lastName"];
    [self willAccessValueForKey:@"firstName"];
    [self willAccessValueForKey:@"company"];

    if (![self.lastName isNullString] ) retVal = [self primitiveValueForKey:@"lastName"]; 
    else if (![self.firstName isNullString] ) retVal = [self primitiveValueForKey:@"firstName"]; 
    else if (![self.company isNullString] ) retVal = [self primitiveValueForKey:@"company"]; 
    else retVal = @"";

    [self didAccessValueForKey:@"lastName"];
    [self didAccessValueForKey:@"firstName"];
    [self didAccessValueForKey:@"company"];


    NSLog(@"Sort Value: %@", retVal);

    return retVal;
}  

I also tried this one before deciding to override the primitive accessor method:

- (NSString *) sortValue {

    NSString *retVal = nil;

    if (![self.lastName isNullString] ) retVal = self.lastName; 
    else if (![self.firstName isNullString] ) retVal = self.firstName; 
    else if (![self.company isNullString] ) retVal = self.company; 
    else retVal = @"";


    NSLog(@"Sort Value: %@", retVal);

    return retVal;
} 

Here is my fetchedResultsController method:

#define CLIENT_SORT_KEY @"clientOfJob.sortValue"
- (NSFetchedResultsController *) fetchedResultsController {
    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Job" inManagedObjectContext:dataInterface.managedObjectContext];

    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:10];

    if (segmentedControl.selectedSegmentIndex == 0) {  // sort by client, then job dscription
        NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:CLIENT_SORT_KEY ascending:YES];
        NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"jobDescription" ascending:YES];

        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
        [fetchRequest setSortDescriptors:sortDescriptors];

        NSFetchedResultsController *aFetchedResultsController = 
        [[NSFetchedResultsController alloc] 
         initWithFetchRequest:fetchRequest 
         managedObjectContext:dataInterface.managedObjectContext 
         sectionNameKeyPath:CLIENT_SORT_KEY
         cacheName:nil]; 


        aFetchedResultsController.delegate = self;

        self.fetchedResultsController = aFetchedResultsController;

        [aFetchedResultsController release];
        [fetchRequest release];
        [jobSortDescriptor release];
        [clientSortDescriptor release];
        [sortDescriptors release];        
    }
    else { // sort by job description
        ...        }

    NSError *error = nil;

    if (![fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved Error %@, %@", error, [error userInfo]);
        abort();
    } 

    int i = 0;
    for (id<NSFetchedResultsSectionInfo> sectionItem in [fetchedResultsController sections]){
        NSLog(@"\n***********\nsection %d name %@\n-----------\n",i++, [sectionItem name]);
        int j = 0;
        for (Job *jobItem in [sectionItem objects]) {
            NSLog(@"%d job: %@, client: %@\n",j, jobItem.jobDescription, jobItem.clientOfJob.sortValue);
        }
    }

    return fetchedResultsController;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文