Core Data自定义访问器甚至不会被调用

时间:2012-02-18 06:22:43

标签: cocoa-touch core-data override accessor

我有一个我试图在运行时设置的Core Data属性,其值来自另一个属性。然而,奇怪的是,我构建的自定义访问器似乎从未被调用过。

属性seasonNameVisible只能从带有搜索字段的谓词的谓词中调用,如下所示:

// Add our search predicates
for (NSString *term in searchTerms) {
    NSPredicate *searchTermPredicate = [NSPredicate predicateWithFormat:@"(episodeName contains[cd] %@) OR (fromSeason.seasonNameVisible contains[cd] %@) OR (fromSeason.fromSeries.seriesName contains[cd] %@)", term, term, term];
    [subPredicates addObject:searchTermPredicate];
}

如果我将该属性更改为seasonName,那么谓词的那一部分会很好地返回结果,所以我不怀疑谓词或任何其他搜索代码。

我的计划是在运行时从seasonNameVisible派生seasonName NSString。所以,我使用原始访问器修改了Season NSManagedObject子类以覆盖访问器和setter。但据我所知,我的访问者永远不会被调用。

这是标题/界面:

//
//  Season.h
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Episode, Series;

@interface Season : NSManagedObject

@property (nonatomic, retain) NSNumber * seasonIndex;
@property (nonatomic, retain) NSString * seasonName;
@property (nonatomic, retain) NSString * seasonNameVisible;
@property (nonatomic, retain) NSSet *episodes;
@property (nonatomic, retain) Series *fromSeries;

@property (nonatomic, retain) NSString * primitiveSeasonName;
@property (nonatomic, retain) NSString * primitiveSeasonNameVisible;
@end

@interface Season (CoreDataGeneratedAccessors)

- (void)addEpisodesObject:(Episode *)value;
- (void)removeEpisodesObject:(Episode *)value;
- (void)addEpisodes:(NSSet *)values;
- (void)removeEpisodes:(NSSet *)values;

@end

// my additions
@interface Season (PrimitiveAccessors)
- (NSString *)primitiveSeasonName;
- (NSString *)primitiveSeasonNameVisible;
@end

......和实施:

//
//  Season.m
//

#import "Season.h"
#import "Episode.h"
#import "Series.h"


@implementation Season

@dynamic seasonIndex;
@dynamic seasonName;
@dynamic seasonNameVisible;
@dynamic episodes;
@dynamic fromSeries;

// my additions
@dynamic primitiveSeasonName;
@dynamic primitiveSeasonNameVisible;

- (NSString *)seasonNameVisible
{
    NSString *visible;
    [self willAccessValueForKey:@"seasonNameVisible"];
    visible = [self primitiveValueForKey:@"seasonNameVisible"];
    [self didAccessValueForKey:@"seasonNameVisible"];

    if (visible != nil) {
        return visible;
    } else {
        [self willAccessValueForKey:@"seasonName"];
        visible = [[self primitiveValueForKey:@"seasonName"] substringFromIndex:2];
        [self didAccessValueForKey:@"seasonName"];
        [self setSeasonNameVisible:visible];
        return visible;
    }
}

- (void)setSeasonNameVisible:(NSString *)seasonNameVisible 
{
    [self willChangeValueForKey:@"seasonNameVisible"];
    [self setPrimitiveValue:seasonNameVisible forKey:@"seasonNameVisible"];
    [self didChangeValueForKey:@"seasonNameVisible"];
}

@end

我已经阅读了Apple的文档,并在StackOverflow上寻找有关自定义访问器方法的帮助,我认为我的代码是正确的(这是我第一次尝试使用原始访问器,或覆盖NSManagedObject方法,所以我有点超出我的通常深度),但即使我在它上面放置一个断点,它似乎永远不会被调用。

1 个答案:

答案 0 :(得分:1)

您要求根据延迟加载的属性获取核心数据。我不认为这会起作用。您可能需要在设置季节名称时设置seasonNameVisible,或者更有意义的是,将季节名称的存储分离为任何前缀(您要移除以提供可见名称)以及任何真实的名称名称。

在评论中的其他信息之后,我会建议如下:

  • 将您的赛季分为两个属性,即赛季号(int)和赛季名称
  • 按季节编号
  • 对您的获取请求进行排序
  • section name key path是对象上的一个新的只读属性,它返回一个由数字和名称组成的字符串

在更改与FRC一起使用的获取请求时,您在注释中看到的错误是正常的。从模拟器中删除应用程序并重新构建它将消失,或在开发时使用nil缓存。 FRC永久地存储其缓存(例如,在运行之间),因此任何更改都会使其失真。

部分名称密钥路径可以是您喜欢的任何密钥路径或属性名称,只要排序相同即可。来自NSFetchedResultsController的文档:

  

sectionNameKeyPath

     

返回节名称的结果对象的键路径。传递nil表示控制器应生成单个部分。   部分名称用于预先计算部分信息。   如果此密钥路径与fetchRequest中第一个排序描述符指定的密钥路径不同,则它们必须生成相同的相对排序。例如,fetchRequest中的第一个排序描述符可能指定持久属性的键; sectionNameKeyPath可能指定从持久属性派生的瞬态属性的键

因此,您有一个Season对象,其中包含两个持久属性seasonNumberseasonName。您按季节编号对获取请求进行排序。您的部分名称密钥路径(对于可能在剧集中具有season关系的抓取)将为@"season.seasonSectionName",实现如下 - 您的托管对象模型中没有任何更改,只是更改您的Season对象:

Season.h:

@property(nonatomic,readonly) NSString *seasonSectionName;

Season.m:

-(NSString*)seasonSectionName
{
    return [NSString stringWithFormat:@"%d - %@",self.seasonNumber,self.seasonName];
}

你真正在做的就是用另一个房产来装饰季节数。