NSBatchUpdateRequest 不保存 Transformable 属性
NSBatchUpdateRequest not saving Transformable attribute
我有一个实体 (TestEntity
),它包含一个包含对象 (MyObjectClass
) 的 "Transformable" 属性。在初始加载时,可变形正确保存;初始化如下:
TestEntity *test = (TestEntity *)[NSEntityDescription insertNewObjectForEntityForName:ENTITY[<Int>] inManagedObjectContext:temporaryContext];
test.transformableAttr = [[MyObjectClass alloc] initWithObject:obj];
但是,当我获取对象(我使用 NSDictionaryResultType 作为字典获取)并更新其 "Transformable" 属性时,
MyObjectClass *my_obj = ....
dict[@"transformableAttr"] = my_obj
它保存成功,但是当我再次获取它时,我得到 "Transformable" 属性的 nil
。
现在这只发生在 "NSBatchUpdateRequest" 上,因为当我使用 MOC 保存时
TestEntity *test = ....
test.transformableAttr = updated_object
保存成功,再次获取时我可以访问更新后的属性。
谁能解释一下?这是否意味着 NSBatchUpdateRequest 不可转换?
我的 NSBatchUpdateRequest 代码:
[context performBlock:^{
NSError *requestError = nil;
NSBatchUpdateRequest *batchRequest = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:entity];
batchRequest.resultType = NSUpdatedObjectIDsResultType;
batchRequest.propertiesToUpdate = properties;
NSBatchUpdateResult *result = nil;
SET_IF_NOT_NIL(batchRequest.predicate, predicate)
@try {
result = (NSBatchUpdateResult *)[context executeRequest:batchRequest error:&requestError];
if (requestError != nil){
// @throw
}
if ([result.result respondsToSelector:@selector(count)]){
__block NSInteger counter = [result.result count];
if (counter > 0){
[managedObjectContext performBlock:^{
for(NSManagedObjectID *objectID in result.result){
NSError *faultError = nil;
NSManagedObject *object = [managedObjectContext existingObjectWithID:objectID error:&faultError];
if (object && faultError == nil) {
[managedObjectContext refreshObject:object mergeChanges:YES];
}
counter--;
if (counter <= 0) {
// complete
}
else{
// Wait.
}
}
}];
}
else{
// No Changes
}
}
else {
// No Changes
}
}
@catch (NSException *exception) {
@throw;
}
}];
文档似乎没有提到这个特定的场景,但我对它不起作用并不感到惊讶。 NSBatchUpdateRequest
被描述为 [强调我的]:
A request to Core Data to do a batch update of data in a persistent store without loading any data into memory.
Transformables 通过在内存中转换 to/from Data
来工作。如果你的 class 符合 NSCoding
,coding/decoding 发生在内存中,因为 SQLite 不知道 NSCoding
或你的 classes.
你最初的分配是有效的,因为 Core Data 在内存中将 transformableAttr
的值转换为 Data
,然后将 Data
的字节保存到持久存储中。在批量更新中,对象未加载到内存中,因此无法进行转换 运行,因此更新无法如您所愿。
令人失望的是 Core Data 没有使这一点更清楚。查看 Xcode 控制台,看看它是否警告您。如果没有,请向 Apple 提交错误,因为虽然我不希望它起作用,但静默失败也不利于它。
如果您想使用批量更新,则必须在 运行 更新之前在代码中转换您的值。我不是 100% 确定这将如何工作,但如果您的值符合 NSCoding
,您将从
开始
let transformedData: Data = NSKeyedArchiver.archivedData(withRootObject:transformableAttr)
然后你做的是我不确定的地方。您可以使用 transformedData
作为新值。或者您可能必须访问它的字节并以某种方式使用它们——也许使用 withUnsafeBytes(_:)
。你可能 运行 会遇到麻烦,因为 transformableAttr
不是 Data
,所以它可能会变得混乱。似乎批量更新不适用于可变形对象。
我有一个实体 (TestEntity
),它包含一个包含对象 (MyObjectClass
) 的 "Transformable" 属性。在初始加载时,可变形正确保存;初始化如下:
TestEntity *test = (TestEntity *)[NSEntityDescription insertNewObjectForEntityForName:ENTITY[<Int>] inManagedObjectContext:temporaryContext];
test.transformableAttr = [[MyObjectClass alloc] initWithObject:obj];
但是,当我获取对象(我使用 NSDictionaryResultType 作为字典获取)并更新其 "Transformable" 属性时,
MyObjectClass *my_obj = ....
dict[@"transformableAttr"] = my_obj
它保存成功,但是当我再次获取它时,我得到 "Transformable" 属性的 nil
。
现在这只发生在 "NSBatchUpdateRequest" 上,因为当我使用 MOC 保存时
TestEntity *test = ....
test.transformableAttr = updated_object
保存成功,再次获取时我可以访问更新后的属性。
谁能解释一下?这是否意味着 NSBatchUpdateRequest 不可转换?
我的 NSBatchUpdateRequest 代码:
[context performBlock:^{
NSError *requestError = nil;
NSBatchUpdateRequest *batchRequest = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:entity];
batchRequest.resultType = NSUpdatedObjectIDsResultType;
batchRequest.propertiesToUpdate = properties;
NSBatchUpdateResult *result = nil;
SET_IF_NOT_NIL(batchRequest.predicate, predicate)
@try {
result = (NSBatchUpdateResult *)[context executeRequest:batchRequest error:&requestError];
if (requestError != nil){
// @throw
}
if ([result.result respondsToSelector:@selector(count)]){
__block NSInteger counter = [result.result count];
if (counter > 0){
[managedObjectContext performBlock:^{
for(NSManagedObjectID *objectID in result.result){
NSError *faultError = nil;
NSManagedObject *object = [managedObjectContext existingObjectWithID:objectID error:&faultError];
if (object && faultError == nil) {
[managedObjectContext refreshObject:object mergeChanges:YES];
}
counter--;
if (counter <= 0) {
// complete
}
else{
// Wait.
}
}
}];
}
else{
// No Changes
}
}
else {
// No Changes
}
}
@catch (NSException *exception) {
@throw;
}
}];
文档似乎没有提到这个特定的场景,但我对它不起作用并不感到惊讶。 NSBatchUpdateRequest
被描述为 [强调我的]:
A request to Core Data to do a batch update of data in a persistent store without loading any data into memory.
Transformables 通过在内存中转换 to/from Data
来工作。如果你的 class 符合 NSCoding
,coding/decoding 发生在内存中,因为 SQLite 不知道 NSCoding
或你的 classes.
你最初的分配是有效的,因为 Core Data 在内存中将 transformableAttr
的值转换为 Data
,然后将 Data
的字节保存到持久存储中。在批量更新中,对象未加载到内存中,因此无法进行转换 运行,因此更新无法如您所愿。
令人失望的是 Core Data 没有使这一点更清楚。查看 Xcode 控制台,看看它是否警告您。如果没有,请向 Apple 提交错误,因为虽然我不希望它起作用,但静默失败也不利于它。
如果您想使用批量更新,则必须在 运行 更新之前在代码中转换您的值。我不是 100% 确定这将如何工作,但如果您的值符合 NSCoding
,您将从
let transformedData: Data = NSKeyedArchiver.archivedData(withRootObject:transformableAttr)
然后你做的是我不确定的地方。您可以使用 transformedData
作为新值。或者您可能必须访问它的字节并以某种方式使用它们——也许使用 withUnsafeBytes(_:)
。你可能 运行 会遇到麻烦,因为 transformableAttr
不是 Data
,所以它可能会变得混乱。似乎批量更新不适用于可变形对象。