我有一个我试图在运行时设置的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方法,所以我有点超出我的通常深度),但即使我在它上面放置一个断点,它似乎永远不会被调用。
答案 0 :(得分:1)
您要求根据延迟加载的属性获取核心数据。我不认为这会起作用。您可能需要在设置季节名称时设置seasonNameVisible,或者更有意义的是,将季节名称的存储分离为任何前缀(您要移除以提供可见名称)以及任何真实的名称名称。
在评论中的其他信息之后,我会建议如下:
在更改与FRC一起使用的获取请求时,您在注释中看到的错误是正常的。从模拟器中删除应用程序并重新构建它将消失,或在开发时使用nil缓存。 FRC永久地存储其缓存(例如,在运行之间),因此任何更改都会使其失真。
部分名称密钥路径可以是您喜欢的任何密钥路径或属性名称,只要排序相同即可。来自NSFetchedResultsController的文档:
sectionNameKeyPath
返回节名称的结果对象的键路径。传递nil表示控制器应生成单个部分。 部分名称用于预先计算部分信息。 如果此密钥路径与fetchRequest中第一个排序描述符指定的密钥路径不同,则它们必须生成相同的相对排序。例如,fetchRequest中的第一个排序描述符可能指定持久属性的键; sectionNameKeyPath可能指定从持久属性派生的瞬态属性的键。
因此,您有一个Season
对象,其中包含两个持久属性seasonNumber
和seasonName
。您按季节编号对获取请求进行排序。您的部分名称密钥路径(对于可能在剧集中具有season
关系的抓取)将为@"season.seasonSectionName"
,实现如下 - 您的托管对象模型中没有任何更改,只是更改您的Season对象:
Season.h:
@property(nonatomic,readonly) NSString *seasonSectionName;
Season.m:
-(NSString*)seasonSectionName
{
return [NSString stringWithFormat:@"%d - %@",self.seasonNumber,self.seasonName];
}
你真正在做的就是用另一个房产来装饰季节数。