菜鸟教程小白 发表于 2022-12-13 08:23:58

ios - KVO 和 Core Data - 自观察托管对象


                                            <p><p>我认为这个问题很简单也很常见,但我仍然不明白为什么它不起作用。让我暴露上下文:</p>

<p>假设我有一个不错的核心数据模型,其中包含一个名为 Document 的实体。该文档有类型、日期、编号和版本...例如,类型:<strong>D</strong>,日期:<strong>17-10-2015</strong>,编号:<strong >24</strong> 和版本 <strong>3</strong>。
本文档具有使用这四个值计算的标识符:<strong>D20151017-24-R03</strong>。</p>

<p>这样的文档会很多,我必须通过它的 Identifier 来搜索它们,而且我也会使用很多 <code>NSFetchedResultsController</code>。所以暂时的可能性就出来了。 </p>

<p>这就是我所做的。先注册观察四个相关属性:</p>

<pre><code>- (instancetype)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context {
    self = ;

    if (self) {
      ;
      ;
      ;
      ;
    }

    return self;
}
</code></pre>

<p>然后,在释放时注销:</p>

<pre><code>- (void)dealloc {
    ;
    ;
    ;
    ;
}
</code></pre>

<p>最后,管理通知:</p>

<pre><code>- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == KVODocumentIdContext) {
      ;
    }
    else {
      ;
    }
}
</code></pre>

<p>就在这里<code>updateDocumentId</code>:</p>

<pre><code>- (void) updateDocumentId {
    NSString * prefix = ;
    NSString * date = ;
    NSString * number = ];
    NSString * version = ?@&#34;&#34;:];

    self.documentId = ;
}
</code></pre>

<p>对我来说,这应该是完美的......但是......它没有......</p>

<p>我有一个很好的:</p>

<pre><code>failed: caught &#34;NSInternalInconsistencyException&#34;, &#34;&lt;MBSDocument: 0x7fd9dbb45f40&gt; (entity: MBSDocument; id: 0x7fd9dbb3cd00 &lt;x-coredata:///MBSDocument/tB55CB581-AEC0-4211-A78A-7C48377BACC2612&gt; ; data:
...
An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: date
Observed object: &lt;MBSDocument: 0x7fd9dbb45f40&gt; (entity: MBSDocument; id: 0x7fd9dbb3cd00 &lt;x-coredata:///MBSDocument/tB55CB581-AEC0-4211-A78A-7C48377BACC2612&gt; ; data:
...
</code></pre>

<p>我尝试了很多方法,其中包括在 <code>observeValueForKeyPath:ofObject:change:context:</code> 中删除对 <code>super</code> 的调用,或者在 <code>init 中注册</code> 等。但没有任何效果。好吧,我们将不胜感激。</p>

<p>提前致谢。</p>

<p><strong>编辑:</strong>这是定义上下文的方式:</p>

<pre><code>static void * KVODocumentIdContext = &amp;KVODocumentIdContext;
</code></pre>

<p><strong>编辑2:</strong>文档类继承自<code>NSManagedObject</code>。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>第一件事:我不会覆盖 initWithEntity:</p>

<p>这是苹果官方 NSManagedObject 类 API 文档的节选:</p>

<p>“您也不鼓励重写 initWithEntity:insertIntoManagedObjectContext: 或 dealloc。更改 initWithEntity:insertIntoManagedObjectContext: 方法中的值不会被上下文注意到,如果您不小心,这些更改可能不会被保存。大多数初始化应在其中一种唤醒…方法中执行自定义。”</p>

<p>因此,您可能应该在 awakeFromInsert: 或 awakeFromFetch: 中添加这些 KVO 观察结果:(然后在 didTurnIntoFault 中删除这些观察者)您的子类的重写方法,也许您可​​以免除添加和删除观察者的所有这些开销,具体取决于什么会影响您的计算属性。</p>

<p>如果影响计算属性的键路径不是很多关系,那么你不妨编写你的 documentID 计算属性 getter 访问器并实现类方法 +(NSSet *)keYPathsForValiesAffectingDocumentID,它返回一个包含键路径的 NSSet,如果更改将导致使用新值重新计算计算机属性。 </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - KVO 和 Core Data - 自观察托管对象,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/30975997/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/30975997/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - KVO 和 Core Data - 自观察托管对象