Подтвердить что ты не робот

IOS8 Не удается скрыть кнопку отмены на панели поиска в UISearchController

Моя цель - не допустить появления кнопки отмены в строке поиска в UISearchController. Я начал с Поиск Apple Table с кодом примера UISearchController и спрятал кнопку отмены, как показано в нижеприведенной ссылке. Однако, когда пользователь вступает в текстовое поле, кнопка отмены все еще появляется. Любая помощь?

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

    ...
4b9b3361

Ответ 1

Я думаю, что есть три способа достичь этого:

  • Переопределить searchDisplayControllerDidBeginSearch и использовать следующий код:

searchController.searchBar.showsCancelButton = false

  1. Подкласс UISearchBar и переопределить layoutSubviews для изменения этого var, когда система пытается его нарисовать.

  2. Зарегистрируйтесь для уведомления клавиатуры UIKeyboardWillShowNotification и примените код в точке 1.

Конечно, вы всегда можете реализовать свою панель поиска.

Ответ 2

Для iOS 8 и UISearchController используйте этот метод делегата из UISearchControllerDelegate:

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

Не забудьте указать себя как делегата: searchController.delegate = self

Ответ 3

Просто подкласс UISearchController и UISearchBar.

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

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

Ответ 4

Следующие подпроекты проекта github UISearchBar, которые представлены как решение 2:

https://github.com/mechaman/CustomSearchControllerSwift

Кроме того, он также подклассифицирует UISearchController, чтобы включить отображение строки поиска в местах, отличных от заголовка tableView!

Надеюсь, что это поможет.

Ответ 5

Это было самое простое решение, которое я мог придумать в 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 против его создания внутри хранимого свойства.

Ответ 6

TL; DR: Подкласс UISearchBar и переопределение setShowsCancelButton: и setShowsCancelButton:animated: скрывает кнопку отмены.

РЕШЕНИЕ

Я установил active в NO, если строка поиска не является первым ответчиком (клавиатура не активна и не отображается), так как это фактически команда отмены.

FJSearchBar

Маркировка searchController.searchBar.showsCancelButton = NO, похоже, не работает в iOS 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

Некоторые примечания:

  • Я положил строку поиска и BOOL как частные переменные вместо свойств, потому что
    • Они более легкие, чем частные.
    • Им не нужно видеть или изменять внешний мир.
  • Мы проверяем, является ли searchBar первым ответчиком. Если это не так, мы фактически деактивируем контроллер поиска, потому что текст пуст, и мы больше не ищем. Если вы уверены, что действительно, вы также можете убедиться, что searchText.length == 0.
  • searchBar:textDidChange: вызывается перед searchBarShouldBeginEditing:, поэтому мы обработали его в этом порядке.
  • Я обновляю результаты поиска каждый раз, когда текст изменяется, но вы можете переместить [self.searchResultsUpdater updateSearchResultsForSearchController:self]; в searchBarSearchButtonClicked:, если вы хотите, чтобы поиск выполнялся после нажатия пользователем кнопки поиска.

Ответ 7

Использовать UISearchControllerDelegate.

func willPresentSearchController(_ searchController: UISearchController) {

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

Ответ 8

Просто подклассифицируйте свой UISearchController и выполните следующие действия:

class CustomSearchController: UISearchController {

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

Это было самое простое решение, которое я мог придумать, чтобы решить проблему с мигающей кнопкой отмены.