web-dev-qa-db-ja.com

iOS8はUISearchControllerの検索バーのキャンセルボタンを非表示にできません

私の目標は、キャンセルボタンがUISearchControllerの検索バーに表示されないようにすることです。私は ISearchControllerサンプルコードを使用したAppleのテーブル検索 から始め、以下のコードの抜粋にあるようにキャンセルボタンを非表示にしました。ただし、ユーザーがテキストフィールドをタップしても、キャンセルボタンは表示されます。何か助けは?

override func viewDidLoad() {
    super.viewDidLoad()

    resultsTableController = ResultsTableController()

    searchController = UISearchController(searchResultsController: resultsTableController)
    searchController.searchResultsUpdater = self
    searchController.searchBar.sizeToFit()
    tableView.tableHeaderView = searchController.searchBar

    searchController.searchBar.delegate = self

    //Hide cancel button - added by me
    searchController.searchBar.showsCancelButton = false

    ...
22
dguastaf

それを実現するには3つの方法があると思います。

  1. searchDisplayControllerDidBeginSearchをオーバーライドし、次のコードを使用します。

searchController.searchBar.showsCancelButton = false

  1. UISearchBarをサブクラス化し、layoutSubviewsをオーバーライドして、システムがそれを描画しようとしたときにそのvarを変更します。

  2. キーボード通知に登録IKeyboardWillShowNotificationでコードを適用1。

もちろん、いつでも検索バーを実装できます。

21
nunofmendes

IOS 8およびUISearchControllerの場合、UISearchControllerDelegateから次のデリゲートメソッドを使用します。

func didPresentSearchController(searchController: UISearchController) {
  searchController.searchBar.showsCancelButton = false
}

自分を代理人として設定することを忘れないでください:searchController.delegate = self

17
Andrew Robinson

単にUISearchControllerUISearchBarをサブクラス化します。

class NoCancelButtonSearchController: UISearchController {
    let noCancelButtonSearchBar = NoCancelButtonSearchBar()
    override var searchBar: UISearchBar { return noCancelButtonSearchBar }
}

class NoCancelButtonSearchBar: UISearchBar {
    override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) { /* void */ }
}
15
ma11hew28

次のgithubプロジェクトは、ソリューション2として提示されるUISearchBarをサブクラス化します。

https://github.com/mechaman/CustomSearchControllerSwift

さらに、UISearchControllerをサブクラス化して、検索バーをtableViewヘッダー以外の場所に配置できるようにします。

お役に立てれば。

3
user2253546

これは、Swiftで思いついた最も簡単なソリューションでした。

カスタム検索コントローラー:

class CustomSearchController: UISearchController {

    var _searchBar: CustomSearchBar

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        self._searchBar = CustomSearchBar()
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    override init(searchResultsController: UIViewController?) {
        self._searchBar = CustomSearchBar()
        super.init(searchResultsController: searchResultsController)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var searchBar: UISearchBar {
        return self._searchBar
    }
}

カスタム検索バー:

class CustomSearchBar: UISearchBar {
    override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
        // do nothing
    }
}

これの最も重要な部分は、_searchBarオブジェクトをinitに1回挿入するか、格納されたプロパティ内に作成するか。

2
Eric Conner

UISearchControllerをサブクラス化し、以下を実行するだけです。

class CustomSearchController: UISearchController {

   override func viewDidLayoutSubviews() {
       super.viewDidLayoutSubviews()
       searchBar.showsCancelButton = false
   }
}

これは、キャンセルボタンの点滅の問題を解決するために思いついた最も簡単な解決策でした。

2
mc_plectrum

Swift:

以下は、viewDidLoadの下に追加された私にとっては機能しました。そのボタンが欲しくないからです。

let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField
searchBarStyle?.clearButtonMode = .never

ストーリーボードにsearchBarのIDを必ず追加してください。 enter image description here

1
CristianMoisei

TL; DRUISearchBarをサブクラス化し、setShowsCancelButton:およびsetShowsCancelButton:animated:をオーバーライドすると、キャンセルボタンが非表示になります。

解決

検索バーが最初のレスポンダーではない場合(キーボードがアクティブで表示されていない場合)は、activeNOに設定します。これは、実質的にcancelコマンド。

FJSearchBar

マーキングsearchController.searchBar.showsCancelButton = NOiOS 8では機能しないようです。私はテストしていませんiOS 9

FJSearchBar.h

空ですが、完全にするためにここに配置されています。

@import UIKit;

@interface FJSearchBar : UISearchBar

@end

FJSearchBar.m

#import "FJSearchBar.h"

@implementation FJSearchBar

- (void)setShowsCancelButton:(BOOL)showsCancelButton {
    // do nothing
}

- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
    // do nothing
}

@end

FJSearchController

ここで、実際の変更を行います。 UISearchBarDelegateを独自のカテゴリに分割しました。これは、IMHOのカテゴリにより、クラスがよりクリーンになり、保守が容易になるためです。デリゲートをメインクラスのインターフェイス/実装内に保持したい場合は、それを歓迎します。

FJSearchController.h

@import UIKit;

@interface FJSearchController : UISearchController

@end

@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>

@end

FJSearchController.m

#import "FJSearchController.h"
#import "FJSearchBar.h"

@implementation FJSearchController {
@private
    FJSearchBar *_searchBar;
    BOOL _clearedOutside;
}

- (UISearchBar *)searchBar {
    if (_searchBar == nil) {
        // if you're not hiding the cancel button, simply uncomment the line below and delete the FJSearchBar alloc/init
        // _searchBar = [[UISearchBar alloc] init];
        _searchBar = [[FJSearchBar alloc] init];
        _searchBar.delegate = self;
    }
    return _searchBar;
}

@end

@implementation FJSearchController (UISearchBarDelegate)

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // if we cleared from outside then we should not allow any new editing
    BOOL shouldAllowEditing = !_clearedOutside;
    _clearedOutside = NO;
    return shouldAllowEditing;
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // hide the keyboard since the user will no longer add any more input
    [searchBar resignFirstResponder];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (![searchBar isFirstResponder]) {
        // the user cleared the search while not in typing mode, so we should deactivate searching
        self.active = NO;
        _clearedOutside = YES;
        return;
    }
    // update the search results
    [self.searchResultsUpdater updateSearchResultsForSearchController:self];
}

@end

注意すべきいくつかの部分:

  1. 検索バーとBOOLをプロパティの代わりにプライベート変数として使用しました。
    • プライベートプロパティよりも軽量です。
    • 彼らは外の世界から見られたり修正されたりする必要はありません。
  2. searchBarが最初のレスポンダーであるかどうかを確認します。そうでない場合は、テキストが空で検索を行わないため、実際には検索コントローラーを非アクティブ化します。 本当に確認したい場合は、searchText.length == 0を確認することもできます。
  3. searchBar:textDidChange:searchBarShouldBeginEditing:の前に呼び出されるため、この順序で処理しました。
  4. テキストが変わるたびに検索結果を更新しますが、ユーザーがを押した後にのみ検索を実行したい場合は、[self.searchResultsUpdater updateSearchResultsForSearchController:self];searchBarSearchButtonClicked:に移動することをお勧めします検索ボタン。
1
mikeho

UISearchControllerDelegateを使用します。

func willPresentSearchController(_ searchController: UISearchController) {

        searchController.searchBar.setValue("", forKey:"_cancelButtonText")
    }
0
A.G