簡體   English   中英

UISearchDisplayController - 如何預加載 searchResultTableView

[英]UISearchDisplayController - how to preload searchResultTableView

我想在用戶點擊搜索欄時顯示一些默認內容,但在輸入任何文本之前。

我有一個使用 settext 的解決方案:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {

   [searchDisplayController.searchBar setText:@" "];

}

這可行,但它並不優雅,並且搜索欄中的提示文本消失了。

有沒有更好的方法將數據預加載到 UISearchDisplayController 中的 SearchResultTableView 中,而不必自己在自定義 controller 中實現整個 UISearch 功能?

要獲得所需效果的演示,請查看 Safari 的搜索框,如果點擊它,搜索界面將打開並顯示以前的搜索。

好的,我有。 用一些數據預加載你的 dataSource 並執行以下 hack(沒有違法),你會得到 tableView 顯示。 請注意,可能需要進行一些清理工作,但這會顯示您的默認數據。

在視圖 controller 的 viewDidLoad 中,擁有 UISearchBar:

[super viewDidLoad];
[self.searchDisplayController.searchResultsTableView reloadData];
// whatever you named your search bar - mine is property named searchBar
CGRect testFrame = CGRectMake(0, 20, self.searchBar.frame.size.width, 100);
self.searchDisplayController.searchResultsTableView.frame = testFrame;
[self.searchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];

這是正在發生的事情:
在您開始編輯之前,UISearchBar 不想顯示 searchResultsTableView。 如果您觸摸tableView(例如reloadData),它將加載並在那里,坐在memory 與frame = CGRectZero。 您給它一個適當的框架,然后將其添加到 searchBar 的超級視圖中,等等。

我通過在正確加載 tableView顯示 searchBar 的超級視圖和 tableView 的超級視圖來驗證這是正確的——它們具有相同的超級視圖。 所以,我把 go 回來,提早將 tableView 添加到 superview 中,果然它出現了。 對我來說,它顯示為暗淡(可能上面的另一個視圖?alpha 設置較低?),但仍然可以點擊。 我沒有進一步 go ,但這絕對可以讓你在沒有任何用戶交互的情況下顯示你的 tableView。

享受,

達米安

我為這個問題找到了一個更好的解決方案,它似乎在 iOS 6 和 7 上完美運行。雖然它仍然是一個 hack,但它比上述更清潔和面向未來的 hack。 其他解決方案無法始終如一地工作,並阻止某些 UISearchDisplayDelegate 方法觸發。 此外,我遇到了復雜的嵌入問題,我無法用上述方法解決。 其他解決方案的主要問題是它們嚴重混淆了 UISearchDisplayController 的內部:我的解決方案基於 UISearchDisplayContoller 是 UISearchbarDelegate 的觀察,並且可以通過在搜索中模擬按鍵來觸發結果表的自動消光和顯示場地! 所以:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller 
{
    if ([controller respondsToSelector: @selector(searchBar:textDidChange:)])
        [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "];
}

這段代碼通過檢查它是否響應 UISearchbarDelegate 方法來防止崩潰,並發送空格 @" " 以欺騙 UISearchDisplayController 認為用戶輸入了一個字母。

現在,如果用戶鍵入內容然后將其刪除,表格將再次變暗。 其他解決方案嘗試通過在 searchDisplayController:didHideSearchResultsTableView: 方法中執行某些操作來解決此問題。 但這對我來說沒有意義,因為當您取消搜索時,它肯定需要真正隱藏您的結果表,並且在這種情況下您可能需要運行代碼。 我對此部分的解決方案是子類化(請注意,如果您的項目需要,您可能可以使用 Method Swizzled Category 使其在任何地方都可以工作):

// privately declare protocol to suppress compiler warning
@interface UISearchDisplayController (Super) <UISearchBarDelegate>
@end

// subclass to change behavior
@interface GMSearchDisplayController : UISearchDisplayController
@end

@implementation GMSearchDisplayController

- (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString
{
    if (searchString.length == 0)
        searchString = @" ";
    if ([super respondsToSelector: @selector(searchBar:textDidChange:)])
        [super searchBar: searchBar textDidChange: searchString];
}

@end

此代碼通過攔截 textDidChange 委托方法並將 nil 或空字符串更改為空格字符串 @" " 來防止在空搜索欄上發生的正常隱藏/變暗。 如果您正在使用第二位代碼,那么您可以修改第一位以傳遞 nil 而不是 @" ",因為第二位將為您進行所需的到 @" " 的轉換。

在我自己的項目中,我需要處理用戶輸入空格的情況,所以我使用了一個定義的標記,而不是上面的 @" ":

// arbitrary token used internally
#define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_"

然后通過將其轉換回 nil 字符串在內部處理它:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL])
        searchString = nil;
}

享受: :)

iOS 7 的工作解決方案:

// When the tableView is hidden, put it back
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
    [self.searchDisplayController.searchResultsTableView reloadData];
    controller.searchResultsTableView.hidden = NO;

    // Also, remove the dark overlay
    for (UIView *v in [[controller.searchResultsTableView superview] subviews]) {
        // This is somewhat hacky..
        if (v.alpha < 1) {
            [v setHidden:YES];
        }
    }
}

-(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView {
    [self.searchDisplayController.searchResultsTableView reloadData];
    if (self.searchDisplayController.active == YES) {
        tableView.hidden = NO;
    }
}

我有解決辦法。 插入這三種方法。您必須在表格視圖中預加載數據才能使其正常工作。 我的代碼中有這些代碼,因此只要您已經預加載了數據並且您正在使用搜索顯示 controller,它就必須為您工作。

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height);
    self.searchDisplayController.searchResultsTableView.frame = testFrame;
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];

//    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
    controller.searchResultsTableView.hidden = NO;
}

-(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
    CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height);
    self.searchDisplayController.searchResultsTableView.frame = testFrame;
    [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];

    //    [self.view addSubview:self.searchDisplayController.searchResultsTableView];
    controller.searchResultsTableView.hidden = NO;
}


-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
    controller.searchResultsTableView.hidden = YES;
}

這適用於 iOS 8:

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
{
  self.searchDisplayController.searchResultsTableView.hidden = NO;
}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller
{
    self.searchDisplayController.searchResultsTableView.hidden = NO;
    [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview];

    CGRect frame = self.searchDisplayController.searchResultsTableView.frame;
    self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height);
}

但是,我不喜歡這種 hack,並用我自己的實現(UISearchBar 和 UITableView)替換了 searchDisplayController。

我使用 UISearchController 在 iOS 9 中測試了以下內容。

默認情況下,當 UISearchBar 中沒有文本時,顯示的表格將是您的原始表格視圖(以下稱為originalTableView )。 根據dimsBackgroundDuringPresentation的值,這可能有也可能沒有黑色透視層。

一旦用戶在 UISearchBar 中輸入任何文本,就會顯示新表格視圖的內容(我將其稱為searchTableView )。

請注意,在這兩種解決方案中,我都以類似於 Apple 在本示例中的方式實現 UISearchController ; 即,有兩個獨立的 UITableViewController 負責顯示數據。

解決方案一:實現復雜,更流暢 animation

對於更平滑的 animation:

  1. 實現 UISearchControllerDelegate 的 willPresentSearchController 和 willDismissSearchController 方法。
  2. 在 willPresent 中,更新您 originalTableView 的數據以准備顯示您想要的任何零文本數據,然后調用reloadData()
  3. 在 willDismiss 中,恢復流程以顯示原始內容並調用reloadData()

例子:

// here tableView refers to originalTableView

extension ViewController: UISearchControllerDelegate {
    func willPresentSearchController(searchController: UISearchController) {
        data = ["A", "B", "C"]
        tableView.reloadData()
    }

    func willDismissSearchController(searchController: UISearchController) {
        data = ["a", "b", "c"]
        tableView.reloadData()
    }
}

在這個虛構的示例中,當用戶沒有將注意力集中在 UISearchBar 上時,數據顯示為a,b,c ,但是一旦用戶點擊 UISearchBar,就會顯示為A,B,C

解決方案 2:快速實施,斷斷續續 animation

無需在 originalTableView 和 searchTableView 中實現搜索 controller 的邏輯,您可以使用此解決方案來簡單地顯示 searchTableView,即使它默認隱藏。

很可能,您已經在實現 UISearchResultsUpdating 協議。 通過在該方法中簡單地調用tableView.hidden = false ,你應該得到你所追求的行為; 盡管 animation 的性能不如恆星。

// here tableView refers to searchTableView

extension SearchViewController: UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        tableView.hidden = false
        filterData(text: searchController.searchBar.text!)
        tableView.reloadData()
    }
}

為什么不看看 Xcode 自帶的 TableSearch 項目呢? 它或多或少地解決了您的需求。 它在開頭顯示一個表格,並在點擊搜索字段時將其隱藏。 在幫助下檢查文檔中的 TableSearch 和 Xcode 4 中的 API 參考。

也看看這個它幾乎可以滿足您使用 UISearchBar 和 UITableView 的需求。 我更喜歡這種方法。 調整它。

為了進一步滿足您的需求,我建議使用兩個數據源。 一個包含所有內容(這是您在開始時要顯示的內容),一個用於保存過濾后的搜索結果。 現在前面的 go 並清空第一個數據源並用第二個數據源的內容填充它以存儲和暗淡顯示先前搜索的結果。 以這種方式進行。 在 TableSearch 代碼中為您的任務使用此方法。

這是一種預填充 searchController 的方法。

// 1. 用戶輸入文本后立即保存以前的搜索結果

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    // save searchString

    return YES;
}

// 2. 啟動時加載上一個搜索字符串

- (void)viewDidLoad 
{
    // create data source for table view
    // searchData may be a NSMutableArray property defined in your interface

    self.searchData = // search your master list for searchString

    // or create your own list using any search criteria you want

    // or you may act depending on user preference
    if(!showPreviousSearch)
    {
        // [searchData removeAllObjects];
    }
}

// 3. 詢問時提供正確的數據源

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        ...
    }

    NSMutableArray *dataSource = nil;
    if (tableView == [[self searchDisplayController] searchResultsTableView])
    {
        dataSource = self.searchData;
    }
    else
    {
        dataSource = self.masterData;
    }

    ...

    return cell;
}

// 希望這可以幫助。

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM