iOS 客戶端實(shí)時(shí)搜索匹配時(shí)限制用戶輸入頻率

需求分析:
用戶快速連續(xù)輸入時(shí),如果需要實(shí)時(shí)響應(yīng)用戶輸入。比如實(shí)時(shí)搜索,那么需要快速響應(yīng)輸入內(nèi)容,盡快地完成搜索任務(wù)。在服務(wù)器端,由于性能強(qiáng)大,只要網(wǎng)絡(luò)流暢,實(shí)時(shí)搜索并不是問(wèn)題。國(guó)內(nèi)的百度和國(guó)外的 Google 都能實(shí)時(shí)顯示搜索結(jié)果。但在移動(dòng)客戶端本地搜索時(shí),如果數(shù)據(jù)量大,在低端機(jī)型流暢地響應(yīng)實(shí)時(shí)輸入會(huì)比較困難。

實(shí)現(xiàn)方案:
一個(gè)2000條聯(lián)系人,外加總計(jì)人數(shù)5000左右的群聊成員的數(shù)據(jù)量大小。輸入完成,要流暢地顯示結(jié)果并匹配高亮輸入文案,要求從輸入完成到輸入下一個(gè)字符的不足1秒的時(shí)間內(nèi),完成搜索匹配。如果不能完成搜索,就會(huì)給用戶卡頓的感覺(jué)。其實(shí)不用在輸入文案每次變化都去進(jìn)行搜索,可以等待一定時(shí)間間隔再拿最新的輸入數(shù)據(jù),去進(jìn)行匹配。間隔低于指定時(shí)間間隔就忽略,控制搜索的頻率。在 iOS 端已經(jīng)有 Message Throttle 方案能夠?qū)崿F(xiàn)消息截流限頻。果斷引入,創(chuàng)建一個(gè) MTRule,然后應(yīng)用。

節(jié)流.png

但是實(shí)際使用時(shí)發(fā)現(xiàn),快速輸入時(shí),有兩個(gè)問(wèn)題:

  1. 輸入卡頓
  2. 搜索的結(jié)果出現(xiàn)了大的延遲,有時(shí)甚至接近1分鐘
    這個(gè)是不能忍受的,必須得解決。

輸入卡頓
明顯是輸入的主線程被阻塞。由于原來(lái)的實(shí)現(xiàn)都是在主線程進(jìn)行搜索,必須創(chuàng)建一個(gè)并發(fā)的全局隊(duì)列。然后將搜索封裝到 NSOperation 中,放進(jìn)隊(duì)列里。借助 《NSOperation 的進(jìn)階使用和簡(jiǎn)單探討 》這篇文章的分析,指定 queuePriority 為NSOperationQueuePriorityVeryHigh,以及 qualityOfService 為 NSQualityOfServiceUserInteractive。

然后等待搜索完成,切換回主線程,渲染 UI。

搜索結(jié)果延遲
在搜索任務(wù)里面,打印正在搜索的字符串,發(fā)現(xiàn) Message Throttle 并沒(méi)有起到作用,每一個(gè)字符輸入后,都會(huì)進(jìn)行一次搜索。
看來(lái)得在調(diào)用此函數(shù)前就限制,即提前截流。
但是仍然會(huì)有部分字符串進(jìn)行了多余的搜索,比如:
連續(xù)輸入: z h e n, 按照預(yù)期,只要執(zhí)行搜索: zhen 一次即可。
但實(shí)際上,還可能搜索了 zhe。
想到 NSOperation 有一個(gè) cancel 方法,可以在加入新的搜索任務(wù)前,取消之前的搜索任務(wù)。
高興地添加后,運(yùn)行發(fā)現(xiàn),還是會(huì)有部分多余搜索。詳細(xì)查看 API說(shuō)明,發(fā)現(xiàn):

cancel API.jpg

原來(lái), cancel 方法不會(huì)取消正在執(zhí)行的任務(wù),由于是快速輸入,之前的搜索是來(lái)不及取消的。
仔細(xì)思考,突然腦洞一開,不管用戶輸入多么快,同一時(shí)刻輸入的文字是唯一的。在搜索任務(wù)時(shí),判斷下當(dāng)前最新的輸入內(nèi)容,與分配的搜索任務(wù)的字符串是否一致。如果一致,再進(jìn)行詳細(xì)的搜索匹配。否則,啥也不做。加了后,最終的實(shí)現(xiàn)方案如下圖。


輸入變化時(shí)搜索.png

真正執(zhí)行的多線程任務(wù)函數(shù).png

小結(jié):
使用 Message Throttle ,實(shí)現(xiàn)了限制用戶輸入頻率的效果。使用 NSOperation 和 NSOperationQueue ,將搜索的任務(wù)分配到子線程,不影響交互。同時(shí)在搜索開始判斷當(dāng)前的最新輸入內(nèi)容是否與將要搜索的內(nèi)容一致, 一致再繼續(xù)搜索。
最終,實(shí)現(xiàn)了高頻輸入,絲滑般的體驗(yàn)?;旧显谟脩糨斎胂乱粋€(gè)字符前,能顯示搜索的結(jié)果。當(dāng)然,這也得益于搜索算法的高效。關(guān)于搜索匹配用到的拼音及拼音首字母匹配算法,詳見(jiàn) 《 iOS 字符串搜索匹配拼音或拼音首字母算法實(shí)現(xiàn)》。

有不足之處,歡迎指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容