25

tableviewアプリケーションでデバイスのリストを表示するための があります。viewWillAppear が呼び出されたら、self.searchDisplayController.searchBar as a subview to a headerView. 次に、を割り当てself.tableView.tableHeaderView = headerViewます。次のようになります。 ここに画像の説明を入力

テーブルビューを下にスクロールして、ヘッダービューが表示されないようにしてから、セルをタップして他のビューコントローラーに移動します。このtableViewに戻ってheaderViewまでスクロールすると、searchBarが非表示になりますが、非表示領域をタップするとsearchDisplayControllerがアクティブになり、キャンセルボタンが機能しません。これは iOS 7 でのみ発生します。なぜこうなった? ここに画像の説明を入力
注: tableViewController に戻ったときに、headerView がビューの外にある場合にのみ発生します。

4

9 に答える 9

18

私はちょうど同じ問題を抱えていました。検索終了状態で UISearchDisplayController のデリゲート メソッドにデバッグすると、searchBar は UITableView ではなく、UIView のサブビューになります。以下のコードを参照してください。

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    //My Solution: remove the searchBar away from current super view,
    //then add it as subview again to the tableView
    UISearchBar *searchBar = controller.searchBar;
    UIView *superView = searchBar.superview;
    if (![superView isKindOfClass:[UITableView class]]) {
        NSLog(@"Error here");
        [searchBar removeFromSuperview];
        [self.tableView addSubview:searchBar];
    }
    NSLog(@"%@", NSStringFromClass([superView class]));
}

私の解決策は、searchBar を現在のスーパー ビューから削除し、サブビューとして再度 tableView に追加することです。私はすでにテストに成功しました。その助けを願っています!

よろしく

于 2014-01-03T17:06:40.293 に答える
5

私はまったく同じ問題を抱えています。検索バーはまだそこにあり、タッチ イベントを受け取ることができます。ただし、レンダリングされません。UISearchDisplayController を使用しないと問題なくレンダリングされるため、問題は UISearchDisplaycontroller にあると思います。私はそれを置き換えるためにカスタム SearchDisplaycontroller を書くことになりました。それは非常に基本的で、必要なことだけを行います。

通常の UISearchDisplayController と同じ方法で使用しますが、self.searchDisplayController は何も返しません。カスタム検索表示コントローラーを参照するには、別のポインターを使用する必要があります。

大きな醜い回避策のように見えますが、私のために働いた唯一のものです。代替案を聞きたいと思っています。

@protocol SearchDisplayDelegate;

@interface SearchDisplayController : NSObject<UISearchBarDelegate>

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;

@property(nonatomic,assign)                           id<SearchDisplayDelegate> delegate;

@property(nonatomic,getter=isActive)  BOOL            active;  // configure the view controller for searching. default is NO. animated is NO
- (void)setActive:(BOOL)visible animated:(BOOL)animated;       // animate the view controller for searching

@property(nonatomic,readonly)                         UISearchBar                *searchBar;
@property(nonatomic,readonly)                         UIViewController           *searchContentsController; // the view we are searching (often a UITableViewController)
@property(nonatomic,readonly)                         UITableView                *searchResultsTableView;   // will return non-nil. create if requested
@property(nonatomic,assign)                           id<UITableViewDataSource>   searchResultsDataSource;  // default is nil. delegate can provide
@property(nonatomic,assign)                           id<UITableViewDelegate>     searchResultsDelegate;

@end


@protocol SearchDisplayDelegate <NSObject>
// implement the protocols you need
@optional
@end

実装

@implementation SearchDisplayController {
    UISearchBar *_searchBar;
    UIViewController *_viewController;
    UITableView *_searchResultsTableView;
    UIView *_overLay;
}

- (void)dealloc {
    [_searchBar release];
    [_searchResultsTableView release];
    [_overLay release];
    [super dealloc];
}

- (UIViewController *)searchContentsController {
    return _viewController;
}

- (UITableView *)searchResultsTableView {
    return _searchResultsTableView;
}

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController {
    self = [super init];
    if (self) {
        _searchBar = [searchBar retain];
        _searchBar.delegate = self;
        _viewController = viewController;
        _searchResultsTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(_searchBar.frame), _viewController.view.frame.size.width, _viewController.view.frame.size.height - CGRectGetMaxY(_searchBar.frame))];
        _overLay = [[UIView alloc]initWithFrame:_searchResultsTableView.frame];
        _overLay.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(overLayTapped)];
        [_overLay addGestureRecognizer:tap];
        [tap release];
    }
    return self;
}
- (void)setSearchResultsDataSource:(id<UITableViewDataSource>)searchResultsDataSource {
    _searchResultsTableView.dataSource = searchResultsDataSource;
}

- (void)setSearchResultsDelegate:(id<UITableViewDelegate>)searchResultsDelegate {
    _searchResultsTableView.delegate = searchResultsDelegate;
}

- (void)overLayTapped {
    [self setActive:NO animated:YES];
    [_searchBar resignFirstResponder];
    _searchBar.text = nil;
    _searchBar.showsCancelButton = NO;
}

- (void)setActive:(BOOL)visible animated:(BOOL)animated {
    UIView *viewToAdd = nil;
    if (!_searchBar.text.length) {
        viewToAdd = _overLay;
    } else {
        viewToAdd = _searchResultsTableView;
    }
    float a = 0;
    if (visible) {
        [_viewController.view addSubview:viewToAdd];
        a = 1.0;
    }
    if ([_viewController.view respondsToSelector:@selectore(scrollEnabled)]) {
        ((UIScrollView *)_viewController.view).scrollEnabled = !visible;
    }

    if (animated) {
        [UIView animateWithDuration:0.2 animations:^{
            _overLay.alpha = a;
            _searchResultsTableView.alpha = a;
        }];
    } else {
        _overLay.alpha = a;
        _searchResultsTableView.alpha = a;
    }
}

- (void)setActive:(BOOL)active {
    [self setActive:active animated:YES];
}

#pragma mark - UISearchBar delegate protocols

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [self setActive:YES animated:YES];
    searchBar.showsCancelButton = YES;
    [_searchResultsTableView reloadData];
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {

}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [_searchResultsTableView reloadData];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self overLayTapped];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (searchText.length) {
        [_overLay removeFromSuperview];
        [_viewController.view addSubview:_searchResultsTableView];
    } else {
        [_searchResultsTableView removeFromSuperview];
        [_viewController.view addSubview:_overLay];
    }
        [_searchResultsTableView reloadData];
}

@end

更新:これをプログラム的に使用する方法について

ivar を宣言する

SearchDisplayController *mySearchDisplayController;

プログラムで初期化する

mySearchDisplayController = [[SearchDisplayController alloc]initWithSearchBar:mySearchBar contentsController:self];

テーブルビューに検索バーを追加する

self.tableView.headerView = mySearchBar;

self.searchDisplayController ではなく、カスタム クラスへの参照として mySearchDisplayController を使用します。

于 2013-09-30T04:35:24.440 に答える
2

デバッガーを使用して、UISearchBar が最初は tableHeaderView の子ビューであることがわかりましたが、それが消えると、tableView 自体の子になります。これはおそらく UISearchDisplayController によって何らかの形で行われました...したがって、次のハックを実行して、UISearchBar をヘッダービューに戻すだけでした:

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  if(!self.searchDisplayController.isActive && self.searchBar.superview != self.tableView.tableHeaderView) {
    [self.tableView.tableHeaderView addSubview:self.searchBar];
  }
}

iOS 7でも6でも問題なく動作するようです:)

(searchDisplayController がアクティブでないことを確認する必要があります。アクティブでない場合、検索中に検索バーが消えます)

于 2013-11-14T16:35:55.323 に答える
1

同じ問題があり、UISearchDisplayController を作成した後に次の行を呼び出して修正できました

[self performSelector:@selector(setSearchDisplayController:) withObject:displayController];

私の viewDidLoad 関数は次のようになります。

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44)];
searchBar.placeholder = NSLocalizedString(@"Search", @"Search");

UISearchDisplayController *displayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
displayController.delegate = self;
displayController.searchResultsDataSource = self;
displayController.searchResultsDelegate = self;

[self performSelector:@selector(setSearchDisplayController:) withObject:displayController];

self.tableView.contentOffset = CGPointMake(0, 44);
self.tableView.tableHeaderView = searchBar;

この回答のおかげで: https://stackoverflow.com/a/17324921/1070393

于 2013-11-20T12:38:10.800 に答える
1

UITableViewの上でUISearchBarを使用し、IBOutletを作成し、ファイルの所有者とそれらをUISearchbarに接続します

例 - .h ファイル

#import <UIKit/UIKit.h>

@interface LocationViewController : UIViewController<UISearchBarDelegate>
{

   BOOL IsSearchOn;

}

@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;

@property (strong, nonatomic) IBOutlet UITableView *TBVLocation;

.m ファイル

#pragma mark -


#pragma mark UISearchBar Delegate Methods



-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

{

    [self.searchResult removeAllObjects];

     if(searchText.length == 0)
      {
           IsSearchOn=NO;
        // [filteredTableData removeAllObjects];
           [self.searchBar resignFirstResponder];
        // [self .tblView reloadData];


     }
   else
     {
       IsSearchOn=YES;

       if(searchText != nil && ![searchText isEqualToString:@""])
       {

        /*            NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@", searchText];

        self.searchResult = [NSMutableArray arrayWithArray: [searchArray filteredArrayUsingPredicate:resultPredicate]];*/
        for(int i=0;i<[[arrCountryList valueForKey:@"country_name"] count];i++)
        {


            NSRange titleRange =    [[[[arrCountryList valueForKey:@"country_name"] objectAtIndex:i] lowercaseString] rangeOfString:[searchText lowercaseString]];

            if(titleRange.location != NSNotFound)
                [self.searchResult addObject:[arrCountryList objectAtIndex:i]];

        }

        [TBVLocation reloadData];
    }
   }

 }



- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar

 {


 [searchBar resignFirstResponder];


 }


-(void)searchBarCancelButtonClicked:(UISearchBar *) searchBar


{


  [searchBar resignFirstResponder];

  IsSearchOn=NO;

  searchBar.text = nil;

  [TBVLocation reloadData];



}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar

{

  [searchBar resignFirstResponder];
  return YES;
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
   searchBar.showsCancelButton = YES;
   searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
   // IsSearchOn=YES;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar

{
    IsSearchOn=NO;
    searchBar.showsCancelButton = NO;
   [TBVLocation reloadData];
   [searchBar resignFirstResponder];
}

それは魅力のように機能します。

于 2014-07-02T07:59:26.787 に答える
0

私は同じ問題を抱えていて、このスレッドで提案されている解決策のいくつかをテストしましたが、問題は解決しませんでした。以前、UISearchBar を追加して構成しました

 - (void)viewDidLoad

コード内のViewControllerのメソッド。

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:searchBarView.frame];
searchBar.delegate = self;
searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
ect...

この問題を解決したのは、InterfaceBuilder に UISearchbar を追加し、ViewController にアウトレットを作成し、この UISearchBar を UISearchDisplayController に追加したことです。

self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar(<--outlet) contentsController:self];

これが一部の人々にも役立つことを願っています

于 2014-06-16T08:24:02.923 に答える