如何检测对特定属性的更改NSManagedObject?在我的核心数据数据模型中,我有一个Product代表待售产品的实体.该Product实体有几个属性:price,sku,weight,numberInStock,等每当price一个属性Product的变化,我需要执行冗长的计算.因此,我想知道任何更改的price属性,[编辑]即使该更改来自合并另一个线程上保存的上下文.这样做的好方法是什么?我的商店里有成千上万的物品; 显然,向每个人发送一条消息是不可行的. ProductProductaddObserver
我一直用NSManagedObjectContextObjectsDidChangeNotification检测的变化,但它只是通知我是一个管理对象发生了变化,而不是其该对象的属性发生变化.每当a发生任何变化时,我都可以重做计算Product,但只要不相关的属性发生变化,就会导致无用的重新计算.我正在考虑创建一个Price实体(只包含一个price属性)并使用Product和之间的一对一关系Price.这样,我可以检测到Price对象的更改,以便开始计算.这对我来说似乎过于愚蠢.有没有更好的办法?
更新:
@railwayparade指出我可以使用该changedValues方法NSManagedObject确定每个更新对象的哪些属性已更改.我完全错过了这个方法,如果没有在后台线程上进行更改并将其合并到主线程的上下文中,它将完全解决我的问题.(见下一段.)
我完全错过了关于NSManagedObjectContextObjectsDidChangeNotification工作方式的微妙之处.据我所知,当另一个线程上保存的托管对象上下文合并到主线程上的上下文(使用a mergeChangesFromContextDidSaveNotification:)时,结果NSManagedObjectContextObjectsDidChangeNotification 只包含有关当前位于主线程的托管对象上下文中的对象的更改信息.如果更改的对象不在主线程的上下文中,则它不会成为通知的一部分.这很有道理,但不是我所期待的.因此,为了获得更详细的更改信息,我想使用一对一关系而不是属性实际上需要检查后台线程NSManagedObjectContextDidSaveNotification,而不是主线程NSManagedObjectContextObjectsDidChangeNotification.当然,简单地使用changedValues方法会更聪明NSManagedObject正如@railwayparade帮助指出的那样.但是,我仍然存在这样的问题:主线程上合并的更改通知不一定包含后台线程上所做的所有更改.
我有一些代码循环遍历NSManagedObjects数组,并在找到存储在实例变量中的某条记录时停止.我能够设法查看它们是否是同一记录(不是等效记录,特定记录)的唯一方法是比较objectID的URIRepresentations.这肯定不是最好的方法.我正在做:
if ([[[obj1 objectID] URIRepresentation] isEqualTo: [[_obj2 objectID] URIRepresentation]]) {
NSLog(@"Match");
}
Run Code Online (Sandbox Code Playgroud)
以下代码永远不会匹配,即使我NSLog的objectIDs,并看到它们实际上是完全相同的.
if ([[obj1 objectID] isEqualTo: [_obj2 objectID]]) {
NSLog(@"Match");
}
Run Code Online (Sandbox Code Playgroud) 我正在Swift中创建一个NSManagedObject子类,当我创建一个类型为Int,Float或Double的可选属性时,我得到一个错误(也许是其他我没试过的).
@NSManaged var number: Float? //error:Property cannot be marked @NSManaged because its type cannot be represented in Objective-C
@NSManaged var anotherNumber: Float //no error
@NSManaged var array: NSArray? //no error
@NSManaged var anotherArray: Array<String>? //no error
Run Code Online (Sandbox Code Playgroud)
Objective-C中可以表示哪些可选类型?当我使用Swift数组或字符串时(以及当我没有使用Optional Int或Double时),为什么不出现错误?
我的CoreData模型有一个Xcode生成的NSManagedObject类.
@objc(SomeClass) class SomeClass : NSManagedObject { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
它在名为"SomeClass.swift"的文件中定义.我想扩展这个类,所以我创建了'SomeClassExtension.swift'.我像这样定义扩展:
extension SomeClass {
class func typeMethod1() {}
func instanceMethod2() {}
}
Run Code Online (Sandbox Code Playgroud)
这些扩展方法可以在此定义文件中使用,但它们在其外部不可见.是什么导致了这个问题?
我有一个自定义NSManagedObject子类,比方说Person.我也UIView注册了-addObserver:forKeyPath:options:context:观察a的各种属性Person,其中一些像"名称"一样持久,而其他属性只是与Core Data无关的KVO兼容的访问器,如"喝酒".
@interface Person : NSManagedObject
{
BOOL drinking;
}
@property (nonatomic, retain) NSString* name;
@property (nonatomic, readonly) BOOL drinking;
@end
@implementation Person
@dynamic name;
...
- (void) getDrunk {
[self willChangeValueForKey: @"drinking"];
drinking = YES;
[self didChangeValueForKey: @"drinking"];
}
...
@end
Run Code Online (Sandbox Code Playgroud)
一切正常.每当我发送-getDrunk或设置name属性时,视图都会收到通知.我是一个快乐的人,除非我阅读以下NSManagedObject文件:
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
Run Code Online (Sandbox Code Playgroud)
事实1.如果接收器为键值提供键值观察变化通知的自动支持,则为YES,否则为NO.
事实2. NSManagedObject的默认实现为建模属性返回NO,为未建模属性返回YES.
现在我正在努力解析文档中的上述两个事实.检查事实2很简单,类人确实为@"name"返回NO,为@"drink"返回YES.但是,当名称发生变化时,视图如何得到通知?KVO文档清楚地说,
使用自动观察器通知时,没有必要通过调用willChangeValueForKey:和didChangeValueForKey来对属性进行更改:当通过键值编码和符合键值编码的方法改变属性时.
因此,如果Person从+automaticallyNotifiesObserversForKey:@"name" 返回NO ,那么我似乎必须手动将名称设置器包装will/didChangeValueForKey:为KVO才能工作.但是,KVO工作正常.我错过了什么?是什么在点NSManagedObject的覆盖+automaticallyNotifiesObserversForKey:和记录它,如果它似乎没有改变标准的志愿行为? …
我的NSManagedObjectModel返回nil,尽管路径正确.
NSString *modelKey = [NSString stringWithFormat:@"/%@/Model", name];
NSString *modelPath = [((Configuration *)[Configuration shared]) stringEntry:modelKey];
NSURL *modelURL = nil;
if ( ! [modelPath contains:@"://"] ) {
modelPath = PathForBundleResource( modelPath );
modelURL = [NSURL fileURLWithPath:modelPath];
}
NSManagedObjectModel *m = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Run Code Online (Sandbox Code Playgroud)
NSString*PathForBundleResource(NSString*relativePath)
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
return [resourcePath stringByAppendingPathComponent:relativePath];
Run Code Online (Sandbox Code Playgroud)
我重置了模拟器,做了一个干净的构建,但没有任何帮助.
我是iPhone编程的新手(特别是核心数据).
非常感谢任何帮助.
编辑:我编辑了有关xcdatamodeld文件的原始帖子.它最初没有正确连接,但现在它仍然存在同样的问题.
编辑2:显然,xcdatamodel的名称在链接后对xcdatamodel的名称有一些变化.它现在正在运作.感觉很蠢.不知道如何删除这个问题.
我正在使用Core Data,并希望将auto_increment ID设置为唯一的字段之一.是否可以使用核心数据在iOS中设置auto_increment?任何人都可以帮我一个如何实现这个的小例子?
下面是我在数据库中插入记录的代码.在第一个字段"id"中,我想将其设置为auto_increment而不是手动插入它.
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:@selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *newObj = [NSEntityDescription insertNewObjectForEntityForName:@"Users" inManagedObjectContext:context];
[newObj setValue:[NSNumber numberWithInt:userId] forKey:@"id"];
[newObj setValue:theFileName forKey:@"Name"];
Run Code Online (Sandbox Code Playgroud) 我有两个实体,每个实体都在自己的UITableView部分显示.
我已启用编辑功能,允许用户通过向右滑动来删除行.这适用于第一个实体,但是当我尝试删除第二个实体中的对象时,我收到此错误:
An NSManagedObjectContext cannot delete objects in other contexts
Run Code Online (Sandbox Code Playgroud)
我得到了错误所说的内容,但我看不出它在这里是如何适用的.我使用对上下文的保留引用来创建,获取和删除数据库中的所有对象,因此我确信只有一个上下文.我也没有使用多线程.知道会发生什么吗?
使用CoreData我创建了一个实体,然后将其子类化为自己的文件,其中包含@propertys,然后在.m文件中包含@dynamic部分.
当我希望某些东西具有某个值时,如果它从未被设置过,我总是使用惰性实例化,如下所示:
- (NSString *)preview {
if ([self.body length] < 200) {
_preview = self.body;
}
else {
_preview = [self.body substringWithRange:NSMakeRange(0, 200)];
}
return _preview;
}
Run Code Online (Sandbox Code Playgroud)
但是如何使用@dynamic属性执行此操作?如果我做同样的事情,它说_preview是一个未声明的属性,但它在.h文件中.懒惰实例化它我做什么不同?
我开始尝试使用swift 3和Xcode 8 beta的Core数据.当我尝试从核心数据模型生成NSManagedObject子类并在编辑器菜单中创建NSManagedObject子类...选项时,Xcode 8 beta生成三个文件,其中一个是_COREDATA_DATAMODELNAME_ + CoreDataModel.swift,其中包含以下内容:
import Foundation
import CoreData
___COREDATA_DATAMODEL_MANAGEDOBJECTCLASSES_IMPLEMENTATIONS___
Run Code Online (Sandbox Code Playgroud)
此外,此文件的内容显示两个警告:
Expressions are not allowed at the top level.
Use of unresolved identifier '___COREDATA_DATAMODEL_MANAGEDOBJECTCLASSES_IMPLEMENTATIONS___'
Run Code Online (Sandbox Code Playgroud)
有没有人面临同样的问题?这个新文件的含义是什么?
谢谢
nsmanagedobject ×10
core-data ×7
ios ×3
iphone ×3
objective-c ×3
swift ×2
cocoa ×1
optional ×1
swift3 ×1
visibility ×1
xcode5 ×1
xcode8 ×1