Отмена из UISearchBar, когда пользователь нажимает на представление

Кто-нибудь знает, как отменить (отказаться от первого ответчика) из UISearchBar, когда вы нажимаете под текстовое поле поиска и над клавиатурой? Может кто-нибудь помочь опубликовать код для решения этой проблемы?

Спасибо

Ответы на вопрос(6)

Решение Вопроса

iphonedevbook, пример кода проекта 04, должен был использовать одну большую прозрачную кнопку, которая лежит за всеми другими элементами управления, которая ничего не делает, кроме как подает в отставку всех первых респондентов, если нажать. То есть если пользователь нажимает в любом месте, где нетt более важный элемент управления - интуитивное поведение - строка поиска и клавиатура исчезают.

 Amagrammer18 авг. 2009 г., 15:40
По сути, это то же самое, что и мое предложение выше. Это может быть немного проще для реализации.
 Bryan C18 авг. 2009 г., 17:21
Спасибо, Хауке! Создание прозрачной кнопки и обработка события касания для отставки первого респондента сделали свое дело.
 Bryan C18 авг. 2009 г., 17:28
У меня есть еще один вопрос:скажем, у меня есть представление, содержащее mkmapview за этой прозрачной кнопкой. Как я могу активировать карту после того, как панель поиска исчезла?
 Amit Hagin20 февр. 2012 г., 13:32
Я думаю этоэто больше не актуально - но для других, кто заинтересован: вы можете обнаружить нажатие на карту с помощью UITapGestureRecognizer, и тогда вы не сможетевообще не нужно использовать кнопку: UITapGestureRecognizer * taprec = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector (handleTap)]; [Карта addGestureRecognizer: taprec];

лемы, с которыми я столкнулся, используя их решения:

1) Если естьЧто-нибудь еще на экране, нажав это выиграетВ результате вызывается resignFirstResponder. Например, если пользователь нажимает кнопку, а не пространство вокруг кнопки, кнопка будет использовать событие. Бо СкоттОднако решение s решает эту проблему.

2) Прикосновение к строке поиска приведет к вызову resignFirstResponder. Очевидно, ты нене хочу, чтобы клавиатура исчезала при нажатии UISearchBar. Небольшое изменение, описанное ниже, решает эту проблему.

В итоге я настроил свой взгляд следующим образом. Родительское представление имеет двух дочерних элементов - UISearchBar и подпредставление, которое содержит остальные мои элементы пользовательского интерфейса. Подвид занимает весь экран под UISearchBar. Тогда я использовал Бо СкоттаТочный код для добавления и удаления распознавателя жестов, но вместо добавления его в self.view я добавил его в подпредставление:

IBOutlet UIView *gestureRecognizer;

...

-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    cancelGesture = [UITapGestureRecognizer new];
    [cancelGesture addTarget:self action:@selector(backgroundTouch:)];
    [gestureRecognizer addGestureRecognizer:cancelGesture];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    if (cancelGesture) {
        [gestureRecognizer removeGestureRecognizer:cancelGesture];
        [cancelGesture release];
        cancelGesture = nil;
    }
}

[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];
 mikeho06 мар. 2016 г., 06:34
Этот код имеет смысл, еслиself этоUIView, Но большую часть времени,self на самом делеUIViewControllerтак что это действительно должно быть[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.searchBar action:@selector(resignFirstResponder)]];

UIGestureRecognizer* cancelGesture;

- (void) backgroundTouched:(id)sender {
    [self.view endEditing:YES];
}

#pragma mark - UISearchBarDelegate

-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    cancelGesture = [UITapGestureRecognizer new];
    [cancelGesture addTarget:self action:@selector(backgroundTouched:)];
    [self.view addGestureRecognizer:cancelGesture];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    if (cancelGesture) {
        [self.view removeGestureRecognizer:cancelGesture];
        [cancelGesture release];
        cancelGesture = nil;
    }
}

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

Есть несколько предостережений, которые вы можете обойти: если вы нажмете что-нибудь, кроме клавиатуры или панели поиска,s текстовое поле, распознаватель ловит щелчок - поэтому, если вы используете кнопку очистки, отмены, области действия или результатов, которые они выиграли 'правильно ответить.

В моем конкретном сценарии у меня был UITableView, который покрывал открытую область представления, поэтому я прикрепил к нему распознаватель жестов вместо основного представления контроллеров представления, изолируя область, на которую будет реагировать жест.

Предположим, что ваш объект контроллера имеет ссылку на объект UISearchBar * theSearchBar, и что вы назначаете его при создании объекта UISearchBar.

Затем вам нужно обнаружить, что касающееся представление было затронуто. Точка зрения, которая тронутазнает», но вам нужно передать эту информацию в контроллер. К сожалению, Apple неЭто простой способ сделать это, но этоЭто тоже не сложно.

Мое решение состоит в том, чтобы заменить стандартный UIView, который объект UIViewController обычно создает, на UIControl, а затем заставить UIViewController реагировать на сенсорные события.

MainController.m

- (void) loadView {
    UIControl *control = [[UIControl alloc] initWithFrame: <desired frame="">];
[control addTarget: self action: @selector(touchUpInside) 
             forControlEvents: UIControlEventTouchUpInside];
       // or touch down events, or whatever you like
    self.view = control;
    [control release];
}

- (void) viewDidLoad {
    [super viewDidLoad];
    theSearchBar = [[UISearchBar alloc] initWithFrame: <desired frame="">];

    // insert code to finish customizing the search bar

    [self.view addSubview: theSearchBar];
}

- (void) touchUpInside {
    if [theSearchBar isFirstResponder] {
        // grab any data you need from the search bar
        [theSearchBar resignFirstResponder];
    }
}
</desired></desired>

MainController.h

@interface MainController : UIViewController
{
    UISearchBar *theSearchBar;
}

Разъяснение:

Есть только один объект - пустьВызываем класс MainController, который является подклассом UIViewController. Все перечисленные выше методы реализованы в MainController. theSearchBar объявлен как UISearchBar * в файле .h.

Вы определяете свой вид и контроллер с помощью Interface Builder? Если это так, я предлагаю вам узнать, как НЕ использовать его - как только вы попадаете в уловки, которые мы обсуждаем здесь, это становится скорее помехой, чем помощью - я нене используй это вообще, никогда.

 Amagrammer17 авг. 2009 г., 22:29
Не глобально, а в файле MainController.h (или как вы его называете). Я добавлю немного выше, чтобы показать вам, что я имею в виду; однако, если вы действительно неЯ не думаю, что вам нужно читать документацию более подробно.
 Amagrammer18 авг. 2009 г., 00:50
Это связано с тем, как вы назначаете self.view в loadView. Мне нужно перепроверить синтаксис - пожалуйста, дайте мне немного, чтобы сделать это.
 Bryan C17 авг. 2009 г., 21:01
Спасибо за более подробную информацию. Я пытался очень внимательно следить за вашим обновлением, но теперь яполучаю ошибку: error: 'панель поиска' undeclared (первое использование в этой функции). К вашему сведению, searchBar - это имя UISearchBar * searchBar, объявленного в моем событии viewDidLoad. Нужно ли объявлять searchBar глобально?
 Bryan C17 авг. 2009 г., 23:46
Мы уже сделали все, что вы упомянули. Теперь, когда я собираю и запускаю, он говорит о загрузке более ста тысяч кадров стека. Отладчик ломается до некоторой сборки машины, и симулятор отображает черный экран. Когда я закомментирую вашу подпрограмму loadView выше, она работает нормально. Пожалуйста, порекомендуйте.
 Bryan C18 авг. 2009 г., 04:44
Я пытался, но все еще получаю исключение. Я'м с использованием iphone SDK 3.0.
 Amagrammer17 авг. 2009 г., 19:54
Вы имеете в виду, чтобы вызвать resignFirstResponder? У вас уже есть, если вы сохранили его в качестве ссылки, когда вы создали его.
 Bryan C17 авг. 2009 г., 20:08
Я немного смущен. Предполагается, что приведенный выше код находится в отдельном контроллере представления от того, где я создал панель поиска? Кроме того, почему вы создаете UIControl вместо UISearchBar в вашей подпрограмме loadView?
 Amagrammer22 авг. 2009 г., 03:28
Я предпочитаю не размещать мою электронную почту здесь. Неужели было бы так плохо размещать только те методы, которые задействованы?
 Amagrammer18 авг. 2009 г., 01:11
Duh. Я сделал глупую ошибку. viewDidLoad не имеет параметров - это 'только те, у которых есть viewDidAppear и т. д.анимированный» в качестве параметра. Попробуйте исправить, как показано выше.
 Amagrammer17 авг. 2009 г., 20:35
Да, вы в замешательстве, и, вероятно, потому что я нене достаточно кода для вас. Я отредактирую свой ответ.
 Bryan C17 авг. 2009 г., 18:53
Как получить ссылку на строку поиска из события touchUpInside? У меня есть touchUpInside в классе viewcontroller, содержащем панель поиска.
 Bryan C18 авг. 2009 г., 13:41
Могу ли я отправить вам свой код по электронной почте?
 Amagrammer18 авг. 2009 г., 05:24
Хорошо, на данный момент мне нужно увидеть ваш реальный код. Иначе нетЯ не могу сделать.

@Gia Dang 'ответ самый простой, но я нет подклассUIView, толькоUIViewControllerтак что мой звонокнемного разные. Кроме того, так как я нене знаю накладные расходы для фактического вызоваresignFirstResponderЯ предпочитаю проверить в первую очередь. Это's больше кода, но так как все это делается в основном потоке (который может замедлить пользовательский интерфейс), яЯ предпочитаю проверить первым.

@implementation MyController : UIViewController {
@private
    UISearchController *_uiSearchController;
}

- (void)viewDidLoad {
    // add tap on view to resign the responder if we're in the middle of typing in the search
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboardIfNeeded)];
    [self.}

- (void)closeKeyboardIfNeeded {
    if (![_uiSearchController.searchBar isFirstResponder]) {
        return;
    }
    [_uiSearchController.searchBar resignFirstResponder];
}

@end

Что касается других ответов, будьте осторожны с постоянным воссозданием объектов. Всегда есть хит производительности, будь тоs само создание или сборка мусора черезARCи эти вещи замедлят ваш основной поток. В зависимости от того, что выЭто также может оказать существенное влияние на производительность.

Ваш ответ на вопрос