2011-06-03 41 views
27

我想顯示一些默認內容,當用戶點擊搜索欄,但在任何文本輸入之前。UISearchDisplayController - 如何預先載入searchResultTableView

我有一個解決方案使用的setText工作:

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

    [searchDisplayController.searchBar setText:@" "]; 

} 

這工作,但它不是優雅,並在搜索欄的提示文本消失。

有沒有更好的方式將數據預加載到UISearchDisplayController的SearchResultTableView中,而無需在自定義控制器中自己實現整個UISearch功能?

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

+0

3班輪!當然,這是大約40行和很多閱讀,直到我找出了那個UISearchDisplayController發生了什麼。好問題,我喜歡學習iOS這樣的小挑戰。 – 2012-03-01 18:38:29

+0

看到這個鏈接 http://stackoverflow.com/a/21344947/747719 這是一個回車的解決方案。 – kapukinz 2014-01-25 00:33:14

回答

-1

爲什麼不看看Xcode中的TableSearch項目?它或多或少地解決你需要的東西。它在開頭顯示一個表格,並在搜索字段被點擊時顯示出來。在幫助中檢查Xcode 4中的文檔和API參考中的TableSearch。

另請參閱this它幾乎可以滿足您對UISearchBar和UITableView的需求。相反,我更喜歡這種方法。調整它。

爲了進一步滿足您的需求,我建議使用兩個數據源。其中一個包含所有內容(這是您將在一開始顯示的內容),一個包含過濾的搜索結果。現在繼續並清空第一個數據源,並用第二個數據源的內容填充以存儲&以顯示先前搜索的結果。繼續這種方式。在您的任務的TableSearch代碼中使用此方法。

9

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

在除擁有的UISearchBar視圖控制器的viewDidLoad中:

[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),它將加載並在那裏,坐在frame = CGRectZero的內存中。你給它一個適當的框架,然後將它添加到searchBar,et瞧的超級視圖。

我通過顯示searchView的超級視圖和tableView 的超級視圖正確加載tableView - 它們具有相同的超級視圖來驗證這是正確的。所以,我回去把tableView添加到superview中,並且確實顯示出來了。對我來說,它顯示變暗了(也許上面的另一個視圖?alpha設置較低?),但仍然可以點擊。我沒有更進一步,但是這絕對讓你的tableView顯示沒有任何用戶交互。

享受,

達明

+0

這不適合我。我已經將我的搜索欄放置在故事板中。我不想再次定位它。當我點擊搜索欄時,數據未加載。 – coolcool1994 2013-10-09 03:14:33

+0

這不是一個簡單的問題 - 如果你通讀「這是發生了什麼」,你會看到爲什麼添加子視圖是必要的。我還沒有在ios6或7中驗證過行爲 - 現在可能有更好的方法來做到這一點。祝你好運! – 2013-10-10 20:28:11

+0

在iOS 8中,您需要執行self.view.superview addSubview ...而不是使用搜索欄。然後你需要用狀態欄調整tabview的大小,如下所示:CGRect testFrame = CGRectMake(0,self.notesSearchBar.frame.size.height + [UIApplication sharedApplication] .statusBarFrame.size.height,self.notesSearchBar.frame。 size.width,self.view.frame.size.height - self.notesSearchBar.frame.size.height); – coolcool1994 2016-05-28 02:08:00

-1

這裏有一個方法來預先填充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; 
} 
提供正確的數據源

//希望這會有所幫助。

謝謝

+0

沒有爲我工作..我有我的數據源都準備好了.. – 2012-07-10 08:45:43

1

我有解決方案。插入這三個方法。你必須預先在tableview中加載數據才能工作。我的代碼工作在我的代碼中,只要您已經預裝了數據並且您正在使用搜索顯示控制器,它就必須爲您工作。針對iOS 7

- (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; 
} 
+0

這是一個很好的解決方案。也許還應該有一個 [self.searchDisplayController.searchResultsTableView removeFromSuperview];在searchDisplayControllerWillEndSearch – MacMark 2013-12-27 17:44:37

4

工作液:

// 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; 
    } 
} 
+0

這一個顯示第二個滯後,我可以看到重疊視圖來了,並走開。有什麼可以避免的? – Sategroup 2015-09-13 08:09:09

8

我發現了一個較好地解決了這個問題,它似乎在iOS 6和7完美地工作儘管它仍然是一個黑客,它比上述更簡潔,更有前途。其他解決方案不能一致地工作,並阻止一些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:方法中執行某些操作來解決此問題。但是這對我沒有意義,因爲當你取消搜索時,它需要真正隱藏你的結果表,你可能需要在這種情況下運行代碼。我給這部分的解決辦法是子類(注意:你很可能使用一種方法攪和類別,讓無處不在的工作,如果需要在您的項目):

// 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委託方法和不斷變化的零或空字符串到空格字符串@「」防止在空搜索欄上發生的正常隱藏/調暗。如果你正在使用這第二個代碼,那麼你可以修改第一個比特來傳遞一個零而不是@「」,因爲這第二個比特會爲你做所需的轉換到@「」。

在我自己的項目,我需要處理的情況是用戶不鍵入一個空格,所以不是@」「上面我用了一個定義令牌:

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

,然後在內部處理它通過將它回到零字符串:

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

Enjoy! :)

+0

這對我正在嘗試做的事情非常有效。 – gplocke 2014-08-03 19:12:08

1

這個工作在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); 
} 

不過,我不喜歡這樣的黑客,通過我自己的實現(用的UISearchBar UITableView中)取代了searchDisplayController。

1

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

默認情況下,只要UISearchBar中沒有文本,所顯示的表就會是您的原始表格視圖(從現在開始稱爲originalTableView)。根據dimsBackgroundDuringPresentation的值,這可能有也可能沒有黑色透視層。

一旦用戶輸入任何文本到的UISearchBar,新表視圖的內容將被顯示(I將把這個作爲searchTableView)。

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

解決方案1:複雜的實現,平滑的動畫

對於平滑的動畫:

  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() 
    } 
} 

在這個虛構的例子中,數據被顯示爲a,b,c當用戶沒有集中在的UISearchBar,但一旦使用者輕按的UISearchBar顯示爲A,B,C

解決方案2:快速實施,波濤洶涌的動畫

無需實現在這兩個originalTableView和searchTableView搜索控制器的邏輯,你可以使用這個解決方案簡單地顯示searchTableView即使它被隱藏默認。

很可能,您已經實施了UISearchResultsUpdating協議。通過在該方法中簡單地調用tableView.hidden = false,您應該獲得您之後的行爲;儘管它的動畫不如恆星。

// here tableView refers to searchTableView 

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