我有一个实体(TestEntity
),其中包含一个“Transformable”属性,该属性包含一个对象(MyObjectClass
)。初始加载时,可转换保存正确;初始化如下:
TestEntity *test = (TestEntity *)[NSEntityDescription insertNewObjectForEntityForName:ENTITY[<Int>] inManagedObjectContext:temporaryContext];
test.transformableAttr = [[MyObjectClass alloc] initWithObject:obj];
但是,当我获取一个对象(我用NSDictionaryResultType作为字典获取)并更新其“Transformable”属性时,
MyObjectClass *my_obj = ....
dict[@"transformableAttr"] = my_obj
它成功保存,但当我再次获取它时,我获得nil
“Transformable”属性。
现在这只发生在“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;
}
}];
答案 0 :(得分:0)
文档似乎没有提到这个特定情况,但我并不感到惊讶它不起作用。 NSBatchUpdateRequest
被描述为[强调我的]:
请求Core Data在持久存储中批量更新数据,而不将任何数据加载到内存中。
Transformables通过在内存中转换为Data
来实现。如果您的类符合NSCoding
,则编码/解码会在内存中发生,因为SQLite不了解NSCoding
或您的类。
您的原始分配有效,因为Core Data会将transformableAttr
的值转换为内存中的Data
,然后将Data
的字节保存到持久性存储中。在批量更新中,对象没有加载到内存中,因此转换无法运行,因此更新不会像您期望的那样工作。
令人失望的是Core Data并没有让这一点更加清晰。查看Xcode控制台,看看它是否会对此发出警告。如果它没有,请向Apple提交一个错误,因为虽然我不希望这种情况发生,但它也无法以静默方式失败。
如果要使用批量更新,则必须在运行更新之前在代码中转换值。我不能100%确定这是如何运作的,但如果您的价值符合NSCoding
,那么您将从
let transformedData: Data = NSKeyedArchiver.archivedData(withRootObject:transformableAttr)
你所做的就是我不确定的地方。您可以使用transformedData
作为新值。或者您可能必须访问其字节并以某种方式使用它们 - 可能使用withUnsafeBytes(_:)
。您可能遇到麻烦,因为transformableAttr
不是Data
,因此可能会变得混乱。似乎批量更新并非设计为可以与变换一起使用。