2012-12-08 78 views
4

我正在篩選NSArray與NSPredicate和使用過濾數組爲我的UITableView。 當用戶在UITextField中輸入文本時,我正在使用此篩選。所以每當UITextField中的文本發生變化,我都會調用我的過濾器函數。篩選巨大的NSArray

它看起來像這樣:

NSArray *hugeArray = ...; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", input]; 
_resultArray = [hugeArray filteredArrayUsingPredicate:predicate]; 
[_myTableView reloadData]; 

當我使用的NSArray有很多對象的輸入變得非常緩慢(在UI完整的輸入變得緩慢)。 有沒有可能獲得更好的性能或在後臺運行過濾的命令?

不應阻塞在UITextField中寫入內容。當輸入後很短的時間內刷新UITableView時,它可能會正常。

+0

上的NSSet

NSSet *hugeSet = [NSSet setWithArray:hugeArray] NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", input]; NSSet *filteredSet = [hugeSet filteredSetUsingPredicate: predicate]; 

更多信息,我建議你使用NSOperationqueue處理過濾器。如果用戶在過濾時插入另一個字符串,則中止舊的字符串。 – Vinh

回答

12

NSPredicate重點在於靈活性而不是速度。對於內存中的NSArray(即不是核心數據關係),只需使用循環即可獲得更好的性能。

如果仍然太慢,那麼有幾種方法:

  • 合併您的要求。請參閱Is there a simple way (in Cocoa/iOS) to queue a method call to run once in the next run loop?您可以創建一個凝聚式蹦牀,以便每隔幾百毫秒只更新一次您的列表。這樣,如果用戶鍵入的速度非常快,則不會重新過濾每個單個chaacter的列表。

  • 更聰明的過濾。如果您只是過濾了「bo」,而您現在想過濾「bob」,那麼您知道它是前一個列表的子集。您不必重新過濾所有內容。爲此寫一個好的算法需要一點工作,但可以顯着提高性能。

  • NSOperationQueue(比GCD更易於取消,但GCD也可以)上執行您的過濾,並讓UI使用KVO來注意過濾數組何時更改。

  • 在過濾時跟蹤實際更改(增加/刪除)。如果您可以提供幫助,您不應該在桌面視圖上致電reloadData。您應該執行插入和刪除(insertRowsAtIndexPaths:)。這避免了不斷攪動你的細胞,而且它通常看起來更好。此外,代碼更復雜,但是改進可能會非常顯着。

+0

感謝提示。我會嘗試一下。 – Sebastian

0

我認爲在後臺運行它是解決方案。在另一個隊列上執行查詢,然後重新加載主隊列上的表。使用GCD它看起來像這樣...

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", input]; 
     _resultArray = [hugeArray filteredArrayUsingPredicate:predicate]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       [_myTableView reloadData]; 
      }); 
    }); 
+0

這需要謹慎操作。如果在每次擊鍵時都完成此操作,則會出現大問題。每個新的擊鍵都應該啓動後臺搜索,但只能在停止當前後臺搜索之後進行。如果用戶更新文本並開始新的搜索,則無法完成當前搜索。 – rmaddy

+0

您應該過濾到臨時數組中,並在主線程上分配'_resultArray'的新值,因爲在後臺線程仍在運行時,表視圖可能會訪問其數據源。 –

+0

@rmaddy,如果這是一個非常長的操作,則爲true。我不知道停止過濾的方法,是嗎? – combinatorial

1

如果你仍然想使用一個謂語,如果對象順序並不重要(意爲對象的指數並不重要),你可以將你的NSArrayNSSet過濾一組數據(使用NSPredicate)比數組快得多。 VS NSArray的NSDictionary的VS在Apple Documentation