我在Core Data中创建了一个瞬态属性,它保存非瞬态加密属性formula
的解密字符串formulaEnc
。
我已经定义了一个局部变量NSString *tmpFormula
来缓存解密的公式,以避免每次访问托管对象时解密该值。
这是我添加到托管对象的自定义访问者:
- (NSString*)formula
{
[self willAccessValueForKey:@"formula"];
NSString *tmpFormula = [self primitiveValueForKey:@"formula"];
[self didAccessValueForKey:@"formula"];
[self willAccessValueForKey:@"formulaEnc"];
NSString *formulaEnc = [self primitiveValueForKey:@"formulaEnc"];
[self didAccessValueForKey:@"formulaEnc"];
if(!tmpFormula && formulaEnc) {
NSLog(@"Decryption started.");
NSData *encryptedData = [NSData dataFromBase64String:self.formulaEnc];
NSError *decryptionError;
NSString *password = @"password";
NSData *decryptedData = [RNDecryptor
decryptData:encryptedData
withPassword:password
error:&decryptionError];
if (decryptionError) NSLog(@"Decryption
failed with error: %@",decryptionError);
NSString *decryptedString = [[NSString alloc]
initWithData:decryptedData encoding:NSUTF8StringEncoding];
tmpFormula = decryptedString;
[self setPrimitiveValue:tmpFormula forKey:@"formula"];
}
return tmpFormula;
}
我将所有托管对象存储在NSArray
中以将其缓存在内存中。但是,即使对象被缓存,每当我读取托管对象时,访问访问者formula
(请参阅上面的代码片段)并再次进行解密。
BTW:这就是我在主代码中创建NSArray
托管对象的方法:
- (NSArray*)allFigures
{ if (!_allFigures) {
NSLog(@"Recalculating allFigures.");
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Figure"];
request.sortDescriptors = @[[NSSortDescriptor
sortDescriptorWithKey:@"order" ascending:YES ]];
request.returnsObjectsAsFaults = NO;
NSError *fetchError;
NSArray *result = [self.managedDocument.managedObjectContext
executeFetchRequest:request error:&fetchError];
_allFigures = result;
}
return _allFigures;
}
这是前一个代码段的调用方式:
NSArray *figures = [self figuresForCategory:category
inManagedObjectContext:self.managedDocument.managedObjectContext];
[self calculateValuesForFigures:figures withCompletion:
^(NSDictionary *values, NSArray *figures) {
dispatch_async(dispatch_get_main_queue(), ^{
self.figures = figures;
});
}];
- (NSArray *)figuresForCategory:(NSString*)category
inManagedObjectContext:(NSManagedObjectContext*)context
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"xyz CONTAINS[cd] %@ ",category];
return [self.allFigures filteredArrayUsingPredicate:predicate];
}
- (void)calculateValuesForFigures:(NSArray*)figures
withCompletion:(void(^)(NSDictionary* valueDict,
NSArray* figures))completionBlock;
{
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext =
self.managedDocument.managedObjectContext;
[backgroundContext performBlock:^{
NSArray *figuresInBackgroundContext =
[self managedObjectsInArray:figures passedToContext:backgroundContext];
// …
调试代码时,第一个代码段中的局部变量tmpFormula
为nil
,但其值应该与缓存的值相同。
为什么我的缓存不起作用的任何想法或想法?
正如我发现的那样 - 感谢您的帮助,我的托管对象因未知方法而出现故障。 -willTurnIntoFault
(调试器中的命令bt
)的回溯产生:
thread #24: tid = 0x8f50b, 0x000b7eb4 Demo`-[Figure willTurnIntoFault](self=0x17f18610, _cmd=0x3432fe08) + 20 at Figure.m:104, queue = 'NSManagedObjectContext Queue, stop reason = breakpoint 6.1
frame #0: 0x000b7eb4 Demo`-[Figure willTurnIntoFault](self=0x17f18610, _cmd=0x3432fe08) + 20 at Figure.m:104
frame #1: 0x2d8fd6ea CoreData`-[NSFaultHandler turnObject:intoFaultWithContext:] + 66
frame #2: 0x2d9648f8 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) _disposeObjects:count:notifyParent:] + 320
frame #3: 0x2d964c16 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) _dispose:] + 682
frame #4: 0x2d95f8d2 CoreData`-[NSManagedObjectContext _dealloc__] + 402
frame #5: 0x2d95fb2e CoreData`internalBlockToDeallocNSManagedObjectContext + 70
frame #6: 0x38818e7a libdispatch.dylib`_dispatch_queue_drain + 374
frame #7: 0x38815f92 libdispatch.dylib`_dispatch_queue_invoke + 42
frame #8: 0x38819744 libdispatch.dylib`_dispatch_root_queue_drain + 76
frame #9: 0x388199c4 libdispatch.dylib`_dispatch_worker_thread2 + 56
frame #10: 0x38943dfe libsystem_pthread.dylib`_pthread_wqthread + 298
如何找到'-willTurnIntoFault'的来电者?
答案 0 :(得分:1)
您的瞬态属性代码看起来很不错。 tmpFormula
应该是
一个局部变量,可以稍微简化一下:
- (NSString*)formula
{
NSString *tmpFormula;
[self willAccessValueForKey:@"formula"];
tmpFormula = [self primitiveValueForKey:@"formula"];
[self didAccessValueForKey:@"formula"];
if (tmpFormula == nil) {
NSString *formulaEnc = self.formulaEnc;
NSLog(@"Decryption started.");
// ... decrypt ...
tmpFormula = decryptedString;
self.formula = tmpFormula;
}
return tmpFormula;
}
这个问题也与解密无关。
问题在于托管对象 只能存在于创建它们的托管对象上下文中。
您似乎在背景MOC上创建对象并将它们放入全局
用于缓存的数组。但是一旦背景MOC被释放,所有对象都会被释放
会自动变为故障,您无法再访问其属性。
(您将获得nil
或可能是运行时异常)。
所以这种缓存是行不通的。