取消 NSJSONSerialization - 键入时搜索,请求重叠

Posted

技术标签:

【中文标题】取消 NSJSONSerialization - 键入时搜索,请求重叠【英文标题】:Cancelling NSJSONSerialization - Search as you type, requests overlapping 【发布时间】:2013-04-09 13:58:18 【问题描述】:

与 iPhone Facebook 应用程序搜索功能类似,我在您将功能输入到我的应用程序时实现搜索,尽管在将数据解码为 JSON 格式时遇到问题。

基本上发生的情况是因为某些搜索比其他搜索花费的时间更长,它们以不同的时间间隔返回,这会在数据显示在屏幕上时导致一些小的视觉问题。

我在每次解码后使用 NSJSONSerialization 为关键字“industry”设置了一个 NSLOG

2013-04-09 23:38:18.941 Project Name [42836:1d03] http://fooWebAddress/json/?method=search&limit=10&q=indus
2013-04-09 23:38:19.776 Project Name [42836:3e07] http://fooWebAddress/json/?method=search&limit=10&q=indu
2013-04-09 23:38:20.352 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=indust
2013-04-09 23:38:21.814 Project Name [42836:4e03] http://fooWebAddress/json/?method=search&limit=10&q=industr
2013-04-09 23:38:23.434 Project Name [42836:8803] http://fooWebAddress/json/?method=search&limit=10&q=ind
2013-04-09 23:38:24.070 Project Name [42836:7503] http://fooWebAddress/json/?method=search&limit=10&q=industry

如您所见,一切都乱了套。

有没有人有办法停止前一个连接的 NSJSONSerialization。 或者可能有任何其他方式来解决这个问题?


升级到 NSJSONSerialization...

    NSURLRequest (initwithURL) NSOperationQueue NSURLConnection(异步) NSJSON序列化

提前致谢。

【问题讨论】:

您是否取消了之前的操作(如果是,如何取消)? 等到用户停止输入,然后只调用网络服务。在两者之间是用户连续输入,使用以下代码取消先前调用网络服务的请求。 [NSObject cancelPerformSelectorsWithTarget:self]; [self performSelector:@selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; 【参考方案1】:

当用户开始输入更多文本时,您可以取消之前的连接并忽略您从他们那里收到的任何进一步的委托回调。然后对当前文本发出新请求。

您可以通过维护某种lastRequestlastOperation 引用来做到这一点。当用户开始输入时,调用[self.lastRequestOrOperation cancel] 并忽略来自该请求的任何进一步通知,并在您拥有的任何回调中使用if (request != self.lastRequest) return; 之类的检查。

但是,如果用户继续输入一段时间,您会不断取消请求,并且他们可能在停止输入之前看不到任何结果。

更好的解决方案是添加排序,以便每个请求与递增的序列 ID 相关联。然后,您仅在响应序列高于您收到的最后一个响应序列时解析结果并更新 UI。如果您收到之前的任何带外响应,您只需忽略它们。

【讨论】:

【参考方案2】:

这是一个比取消NSJSONSerialization 复杂得多的问题。我的建议是使用NSFetchedResultsController 来填充显示搜索结果的表格视图。使用搜索词作为附加到NSFetchedResultsControllerNSFetchRequest 中的谓词变量之一。然后,当您使用 NSJSONSerialization 解析结果时,将结果与与该请求关联的搜索词一起存储。一旦搜索词更改(您可以检测到用户何时键入更多字符),重新创建NSFetchedResultsController 并重新加载您的表格视图。此外,如果您使用 performSelector:withObject:afterDelay 启动它,您还可以尝试取消调用以解析先前的结果。请注意,这不能总是依赖,因为呼叫可能在您尝试取消时已启动。

【讨论】:

【参考方案3】:

有点基本,但您始终可以维护一个子类 NSURLRequests 的字典(子类以提供标签)。

开始请求 - 将请求添加到带有标签 = array.count - 1 的字典,带有键匹配标签 连接返回 - 请求是不是最近的请求,如果是,解析json Parse JSON - 请求是最近的请求,如果是,显示结果,如果不是,仅在没有显示以前的结果时显示 请求处理 - 从字典中删除键

最近的请求 = 字典是否包含具有更高键值的对象

【讨论】:

【参考方案4】:

目前你正在做的是,你输入每个字符并调用网络服务。为什么要为您键入的每个字母调用网络服务。如果用户连续输入,则会增加负载,因此只有在用户停止特定时间间隔时才调用 Web 服务。然后将该字符串传递给调用 web-service 或您正在调用的任何方法。

[NSObject cancelPerformSelectorsWithTarget:self]; // This will cancel your all req which is going to make when user typing without stopping 
[self performSelector:@selector(sendSearchRequest) withObject:searchText afterDelay:0.1f]; // This will pass the string to call a web-service method, on which user hold for some time.

【讨论】:

以上是关于取消 NSJSONSerialization - 键入时搜索,请求重叠的主要内容,如果未能解决你的问题,请参考以下文章

NSJSONSerialization 没有返回错误

NSJSONSerialization - 无法将数据转换为字符串

Swift 2 - NSJSONSerialization.JSONObjectWithData 处理错误 [重复]

使用 NSJSONSerialization 解析 twitter 搜索 json 数据

使用 NSDictionary 访问 NSJSONSerialization 数据

NSJSONSerialization生成NSCFString *和NSTaggedPointerString *