无法在 NSValueTransformer 中调用transformedValue

Posted

技术标签:

【中文标题】无法在 NSValueTransformer 中调用transformedValue【英文标题】:Cannot make transformedValue called in NSValueTransformer 【发布时间】:2014-08-25 07:36:34 【问题描述】:

有我对NSValueTransformer的实现

+ (Class)transformedValueClass 
    return [NSData class];


+ (BOOL)allowsReverseTransformation 
    return YES;


- (id)transformedValue:(id)value 
    // some implementation, there is breakpoint


- (id)reverseTransformedValue:(id)value 
    // some implementation, there is breakpoint

我在运行时注册它

 EncryptionTransformer *transformer = [[EncryptionTransformer alloc] init];
 [NSValueTransformer setValueTransformer:transformer forName:@"EncryptionTransformer"];

我将我的字段标记为可转换

我的 MO 中有一个属性

@property (nonatomic, strong) NSData *someData;

@dynamic someData;

我做错了什么? transformedValue 未被调用。

【问题讨论】:

如果您尝试评论“注册运行时部分”有什么不同吗?你把那部分放在哪里了?除了使用断点,您可以简单地在两种方法的开头做一个日志吗?你看到了什么? 您的设置看起来正确。您提供给我们的信息量让我想像这种行为的几个选项 - 1)您没有为 someData 设置任何内容。 2) 不确定,但可以在-[NSManagedObjectContext save:] 上调用值转换器 3) 您的属性类型是 NSData。因此,我假设您正在将 NSData 转换为 NSData,我从未尝试过,但 CoreData 在将 NSData 转换为 NSData 时可能会跳过转换。 4) 就像 flexaddicted 所说的 - 尝试不使用“运行时”部分 @PetroKorienev 我试过在没有运行时的情况下这样做 - 没有效果,我应该尝试检查 3-d 案例。但是我需要将 NSData 转换为 NSData,我不知道该怎么做才能逃避这种行为 【参考方案1】:

我在上面的评论中对您的问题做了一些假设。我在测试示例中复制了您的设置并发现以下内容:

    您的设置是正确的 - 无需在运行时设置值转换器,例如 EncryptionTransformer *transformer = [[EncryptionTransformer alloc] init]; [NSValueTransformer setValueTransformer:transformer forName:@"EncryptionTransformer"]; 实际值转换器的转换方法-(id)transformedValue:-[NSManagedObjectContext save:]之后调用 此外,如果您的 NSManagedObjectContext 没有直接连接到持久存储协调器(在 MagicalRecord 或 RestKit 等框架中提供的流行方法 out-of-box-(id)transformedValue: 不会在 -[NSManagedObjectContext save:] 之后调用。它仅在 -[NSManagedObjectContext save:] 之后在直接连接到持久存储协调器的上下文中调用。 对于-(id)reverseTransformedValue:(id)value,类似的规则是正确的 - 它仅在从持久存储协调器获取后调用

简单代码(我使用你的设置):

char *data = "abc";
NSManagedObjectContext *moc =
[(TCDAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
Event *event = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Event class]) inManagedObjectContext:moc];
event.timeStamp = [NSDate date];
event.myData = [NSData dataWithBytes:data length:4];   // no call to -(id)transformedValue:
[moc save:nil];   // called -(id)transformedValue:

【讨论】:

哇,谢谢,我只在子上下文中调用,不需要在父上下文中调用。我认为有问题。我是否以错误的方式理解嵌套上下文?我该如何解决?以及为什么他们只在父上下文中使用 Transformer。 实际上不是。这里的关键点是使用保存到数据库调用转换器。看,您保存了子项-> 更改传播给父项。通过这种方式,更改通过上下文传播到根上下文(直接连接到持久存储协调器)。当您保存根上下文时,更改将提交到数据库。这就是真正执行转换的时刻。因此,在数据库中,您的数据已加密,在内存(托管对象上下文)中 - 已解密。不确定,你想达到什么目标,但我认为这是理想的情况 所以当我调用 save: 在我的子上下文中,更改不会提交到数据库?并且没有任何理由调用 save: on child context? 我明白了,保存在子上下文中只会在父上下文上同步。好的,谢谢。 cocoanetics.com/2012/07/multi-context-coredata 以便更好地理解嵌套上下文 - 但它超出了这个问题的范围,如果不清楚,最好创建一个新的。

以上是关于无法在 NSValueTransformer 中调用transformedValue的主要内容,如果未能解决你的问题,请参考以下文章

使用 swift 在 xcode 6 中自定义 NSValueTransformer

NSValueTransformer,如何使用?

如何将上下文对象传递给 NSValueTransformer

在哪里为 Swift 中的核心数据实现 NSValueTransformer

iOS 核心数据加密使用 NSValueTransformer

用于核心数据中 C 结构的 NSValueTransformer