当 KVO 从模型设置器触发时,防止递归地重新输入observeValueForKeypath

发布于 2024-09-14 13:15:54 字数 1178 浏览 6 评论 0原文

我有一大批模型会自我观察变化。当 setter 被触发时,模型中的观察者被调用,在该模型中,我调用 Web 服务器并更新 Web 服务器中的信息,以便它正确地拥有应有的数据。

然而,在我对网络服务器的调用中,我可以得到一个错误,从连接断开、服务器重置等到服务器说不允许更新(例如,另一个用户更改的某些其他参数阻止了更新)。

哦,断开连接的数据存储的乐趣...

有什么方法可以更新自我(即模型)而不重新触发 KVO 操作?

当我返回响应时,我可以关闭观察者,但是在执行后台服务器请求时,可能会对同一对象执行另一个用户操作。这将中断另一个调用。

请参阅此处的帖子,了解我想要做什么的解释首先获得观察结果以及完整模型的代码示例。

我打电话的部分将在观察员中如下:

-(void)observeValueForKeyPath:(NSString *)keyPath
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context {

  if ([keyPath isEqual:@"firstName"]) {

    if !([serverCall value:[change objectForKey:NSKeyValueChangeNewKey] 
                    forKey:@"firstName"]) {

        // Notify the user of the problem and somehow do a 
        // [self setFirstName:[change objectForKey:NSKeyValueChangeOldKey]]
        // without firing off a KVO which would only loop this process
    }
  }

  if ([keyPath isEqual:@"lastName"]) {
    // Do whatever I need to do
  }
}

你们似乎总是提出一些好的建议,我总是感谢你们提出的任何建议。

I have a whole host of models that watch themselves for changes. When a setter is triggered, the observer in the model is called and within that model I make a call to a web server and update information in the web server so it correctly has the data it should.

However, in my call to the web server I can get back an error for anything from connection being dropped, server reset etc to the server saying the update wasn't allowed (e.g. some other parameter changed by another user prevented the update).

Oh the joys of a disconnected data store...

Is there any way that I can update self (i.e. the model) without it re-triggering a KVO action?

I could turn off the observer when I get back the response, but another user action to the same object is possible while the background server request is being performed. This would then break the other call.

See the post here for an explanation of what I was trying to do to get the observation happening in the first place and a code example of the full model.

The portion where I am making the call would be in the observer as follows:

-(void)observeValueForKeyPath:(NSString *)keyPath
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context {

  if ([keyPath isEqual:@"firstName"]) {

    if !([serverCall value:[change objectForKey:NSKeyValueChangeNewKey] 
                    forKey:@"firstName"]) {

        // Notify the user of the problem and somehow do a 
        // [self setFirstName:[change objectForKey:NSKeyValueChangeOldKey]]
        // without firing off a KVO which would only loop this process
    }
  }

  if ([keyPath isEqual:@"lastName"]) {
    // Do whatever I need to do
  }
}

You guys always seem to come through on some good advice and I am always grateful for any suggestions you may have.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘亓 2024-09-21 13:15:54

好吧,我最终采取了不同的策略。我没有依赖对象模型来发布更新,而是将所有内容提升一级并让控制器处理更新。

本质上,该过程如下: 根据

  1. 需要在模型中创建对象
  2. 在控制器中设置一个设置器,该设置器在方法变量中保存对象设置的当前状态
  3. 将新设置传递到服务器,但仅限于在两次更新之间更改的设置现有的和新的设置(所有增量值)
  4. 如果调用通过,则更新模型,或者如果失败,则通知用户并且不执行任何操作。

结果是每个控制器中的代码多一点,但是通过动态比较当前的值与新值,并且仅将已更改的值传递给服务器,我完成了相同的最终结果。

这使我能够根据更改的数量传递多个值之一,而无需一遍又一遍地调用通用服务器 API 方法来对 setter 和 getter 进行硬编码。

最终效果是,我保留了所有 KVC/KVO 通知,而不必担心绕过它或不对某些呼叫进行 KVC/KVO 更新,而不会对其他呼叫进行 KVC/KVO 更新。

Well I ended up taking a different tack. Instead of relying on the object model to post the updates, I took everything up one level and let the controller handle the updates.

Essentially the process was as follows:

  1. Create the objects in the model when required
  2. Have a setter in the controller that held in a method variable the current state of the object settings
  3. Passed the new settings up to the server, but only those that changed between the existing and the new settings (all the delta values)
  4. If the call passed, update the model or, if it failed, notify the user and do nothing more

It worked out being a little more code in each controller, but by dynamically comparing the current values with the new values and only passing up the ones that had changed to the server I accomplished the same net result.

This allows me to pass up one of more values based upon how many changed without having to hard-code setters and getters with a call to a common server-API method over and over again.

The net effect was that I keep all my KVC/KVO notification without worrying about bypassing it or not doing KVC/KVO updates on some calls and not on others.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文