我们知道NSFetchRequest的propertiesToFetch可以限制我们想要的属性,它可以减少内存的占用空间。 如果我们这样做:
request.propertiesToFetch = [NSArray arrayWithObjects:@"nID", nil];
和
NSString *strID = [NSString stringWithFormat:@"%@", aPerson.nID];
cell.textLabel.text = strID;
然后调试输出(而不是触发故障):
CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK, t0.ZNID FROM ZPERSON t0 ORDER BY t0.ZNID
然而,当我向NSManagedObject Person的子类添加一个新的未建模属性时,发生了一件奇怪的事情。 就像这样:
@interface Person (Ex)
@property (nonatomic, retain) NSString *strTempName;
@end
@implementation Person (Ex)
@dynamic strTempName;
-(void)setStrTempName:(NSString *)strTempName
{
[self setPrimitiveValue:strTempName forKey:@"strTempName"];
}
-(NSString*)strTempName
{
return [self primitiveValueForKey:@"strTempName"];
}
这是访问新的未建模属性的地方:
NSString *strTT = aPerson.strTempName;
然后调试输出:
2013-05-06 10:43:07.789 TestCoreData[988:c07] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZBISFORTEST, t0.ZBISINTRASH, t0.ZNID, t0.ZSTRNAME, t0.ZSTROK, t0.ZSTROK2, t0.ZSTRTEST1, t0.ZSTRTEST2, t0.ZADEPART, t0.ZAMIDDLETHUMNAIL, t0.ZANORMALPIC, t0.ZASMALLTHUMNAIL FROM ZPERSON t0 WHERE t0.Z_PK = ?
2013-05-06 10:43:07.790 TestCoreData[988:c07] CoreData: annotation: sql connection fetch time: 0.0010s
2013-05-06 10:43:07.791 TestCoreData[988:c07] CoreData: annotation: total fetch execution time: 0.0018s for 1 rows.
2013-05-06 10:43:07.792 TestCoreData[988:c07] CoreData: annotation: fault fulfilled from database for : 0x898a030 <x-coredata://CAD35D43-F6B2-4463-B59B-C9A3CD488935/Person/p51846>
从上面的输出消息中,我们可以找到unmodeled属性而不是SELECT t0.Z_ENT,t0.Z_PK,t0.ZNID,SELECT生成所有属性句子并触发故障!
但是,我已经阅读了一些有关未建模属性(here is link)的消息:
因为未建模的属性只是自定义的属性 NSManagedObject子类而不是实体,故障对象知道 他们没什么。故障对象从数据模型初始化 这样他们响应的所有密钥都必须在数据模型中。这个 意味着故障不能可靠地响应未建模的请求 属性。
为什么奇怪的事情会发生?
提前感谢。
@Anonymous,
选择1): 应用程序崩溃,调试输出显示:
2013-05-06 14:03:05.665 TestCoreData[1794:c07] -[Person strTempName]: unrecognized selector sent to instance 0x6ba77b0
2013-05-06 14:03:30.395 TestCoreData[1794:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person strTempName]: unrecognized selector sent to instance 0x6ba77b0'
选择2): 首先,像willAccessValueForKey等方法是发送KVO更改通知,就像NSManagedObject.h中的注释一样:
- (void)willAccessValueForKey:(NSString *)key; // read notification
- (void)didAccessValueForKey:(NSString *)key; // read notification (together with willAccessValueForKey used to maintain inverse relationships, to fire faults, etc.)
其次,在选择2)代码后,我的应用程序中仍然存在奇怪的事情(触发故障)。
也感谢你的回复。
答案 0 :(得分:0)
出现问题:
第一:这是正确的,@动态是错误的。访问者在您的代码中。没有任何动态。
第二:原始访问器用于建模属性。你有一个“伊塔尔财产”。只需按照在其他任何地方使用它的方式使用它。 (但是添加... access ...和...... change ......方法。)
更改后,重新检查是否触发故障。
+++ 在-didAccessValueForKey :( NSManagedObject)的文档中,您将找到正确实现的示例:
- (NSString *)firstName
{
[self willAccessValueForKey:@"firstName"];
NSString *rtn = firstName;
[self didAccessValueForKey:@"firstName"];
return rtn;
}
答案 1 :(得分:0)
return [self primitiveValueForKey:@"strTempName"];
这是错误的。 primitiveValueForKey
用于访问建模属性。由于你的属性没有建模,你得到了所有奇怪的行为 - 核心数据触发错误,因为它正在寻找属性,当它找不到它时,它会引发异常。
你想要达到什么目的?也许你正在寻找一个瞬态属性,或者你应该像在任何其他对象中一样合成属性?
答案 2 :(得分:-1)
我认为你的编码太多了。 @dynamic为您生成getter和setter。你有两个选择。
1)删除setter / getter调用。
2)修改你的getter / setter以警告系统你正在改变值:
-(void)setStrTempName:(NSString *)strTempName
{
[self willChangeValueForKey:@"strTempName"];
[self setPrimitiveValue:strTempName forKey:@"strTempName"];
[self didChangeValueForKey:@"strTempName"];
}
-(NSString*)strTempName
{
[self willAccessValueForKey:@"strTempName"];
NSString *tmp = [self primitiveValueForKey:@"strTempName"];
[self didAccessValueForKey:@"strTempName"];
return tmp;
}