gpt4 book ai didi

iphone - 即使定义了依赖键,我是否也必须手动更新 transient 属性?

转载 作者:行者123 更新时间:2023-12-03 20:09:36 26 4
gpt4 key购买 nike

我开始使用 transient 属性 a little while ago ,并认为我非常了解它们,但这个属性的行为与我想象的不同。它在数据模型中定义为未定义类型的 transient 属性,因此声明为属性:

@property (nonatomic, readonly) NSSet * manufacturers;

此属性被声明为依赖于此对象上的另一个 1:M 关系:

+ (NSSet *) keyPathsForValuesAffectingManufacturers
{
return [NSSet setWithObject:@"lines"];
}

我已经为这个 transient 属性实现了一个相当标准的 getter:

- (NSSet *) manufacturers
{
[self willAccessValueForKey:@"manufacturers"];
NSSet *mfrs = [self primitiveManufacturers];
[self didAccessValueForKey:@"manufacturers"];

if (mfrs == nil)
{
NSMutableSet *working = [NSMutableSet set];

/* rebuild the set of manufacturers into 'working' here */

mfrs = working;
[self setPrimitiveManufacturers:mfrs];
}

return mfrs;
}

不起作用的部分是,当从 lines 关系中添加/删除对象时,manufacturers 的缓存原始值似乎不会被清除在这个物体上。当您添加/删除行时,肯定会调用manufacturers访问器,但是[selfprimitiveManufacturers]仍然返回旧的缓存值(这显然是非零),因此代码没有调用重建当前的制造商集,并且我最终得到了过时的返回值。

我是否误解了缓存 transient 属性值的工作原理?或者,当通过某种 KVO 回调更改行时,我是否应该手动使缓存值无效,以便下次访问 manufacturers 时执行“if”内的更新代码?

非常感谢任何帮助。

编辑:我知道我基本上是在模拟与此 transient 属性的 1:M 关系(即 transient 关系,因为需要更好的词) ,而且我还知道 documentation 警告不要使用 setPrimitiveValue:forKey: 来建立关系:

You should typically use this method only to modify attributes (usually transient), not relationships. If you try to set a to-many relationship to a new NSMutableSet object, it will (eventually) fail. In the unusual event that you need to modify a relationship using this method, you first get the existing set using primitiveValueForKey: (ensure the method does not return nil), create a mutable copy, and then modify the copy

但是,由于我没有在真实 1:M 关系上设置原始值,而只是在模拟 transient 关系上设置原始值,因此我假设此警告不适用于我的用例。

编辑 #2: 因为我只是尝试跟踪何时从 lines 集中添加或删除对象(这是 的预期值的唯一方法>制造商可以改变),而不是试图跟踪lines集中已有的对象的属性更新,我认为我不应该需要像这样重量级的东西: https://github.com/mbrugger/CoreDataDependentProperties

解决方案:根据下面的答案,我实现了以下解决方案,以在更新 lines 时清空 manufacturers 设置。任何人都可以看到这方面的任何问题,或者建议任何更有效的实现方法吗?此操作必须快速,这一点很重要,因为它是在主线程中完成的,并且会明显延迟与更新完成同时发生的 UI 更新。

- (void) awakeFromFetch
{
[super awakeFromFetch];
[self addObserver:self forKeyPath:@"lines" options:0 context:nil];
}


- (void) awakeFromInsert
{
[super awakeFromInsert];
[self addObserver:self forKeyPath:@"lines" options:0 context:nil];
}


- (void) didTurnIntoFault
{
[self removeObserver:self forKeyPath:@"lines"];
[super didTurnIntoFault];
}


- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([object isEqual:self] && [keyPath isEqualToString:@"lines"])
{
[self setPrimitiveManufacturer:nil];
}
else
{
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}

最佳答案

keyPathsForValuesAffectingManufacturers 并不意味着当线路发生变化时,制造商的值会被删除,而是意味着当线路发生变化时,观察制造商的对象应该得到通知,因为线路变化会自动改变制造商,而不会触发通知。当一个属性基于另一个属性获取其值时使用此属性。针对您的情况,换线时需要更换厂家。

关于iphone - 即使定义了依赖键,我是否也必须手动更新 transient 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4578401/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com