LoginSignup
6
5

More than 5 years have passed since last update.

UISearchBarのクリアボタン表示を制御する

Last updated at Posted at 2015-02-01

検索バーのクリアボタン表示制御は通常できません。検索バーにキーワードが入力されていれば、フォーカスが外れていても、クリアボタンが常に表示されている状態になっています。
その動作を変更したい場合、例えば検索バーにフォーカスがあたっている場合のみクリアボタンを表示したい場合、UISearchBarのtextFieldを探してクリアボタンの表示モードを変更する必要があります。

iOS SDKのバージョンによっては、UISearchBar.subviewsを検索すれば見つかる場合もあるようですが、iOS 7/8では、もう一段下の階層にtextFieldが追加されているため、再帰的に検索すると見つけることができます。

ということで、クリアボタンを制御するには、以下のようにUISearchBarのカテゴリを作成すれば実現することができます。毎回検索バーのクリアボタンを検索するのは面倒なので、最初にアクセスしたときのみ検索しオブジェクトにキャッシュさせておけばいいでしょう。

// UISearchBar+ConfigHacking.h
#import <UIKit/UIKit.h>

@interface UISearchBar (ConfigHacking)

/*!
    @abstract UISeachBarのsubviewを再帰的に検索して、TextFieldのclearButtonModeを変更/取得する
    @todo UISearchBarの構造が変更された場合、対応する必要がある
 */
@property (nonatomic, readwrite) UITextFieldViewMode textFieldClearButtonMode;

@end

// UISearchBar+ConfigHacking.m
#import "UISearchBar+ConfigHacking.h"

#import <objc/runtime.h>

static const NSUInteger MaxRecursiveDepth = 3;

#pragma mark -

@implementation UISearchBar (ConfigHacking)

- (UITextField *)retrieveTextFieldInView:(UIView *)view depth:(NSUInteger)depth {
    if (depth >= MaxRecursiveDepth) {
        return nil;
    }
    for (UIView *subview in view.subviews) {
        if ([subview isKindOfClass:[UITextField class]]) {
            return (UITextField *)subview;
        }
        UITextField *textField = [self retrieveTextFieldInView:subview depth:depth+1];
        if (textField) {
            return textField;
        }
    }
    return nil;
}

- (UITextField *)ch_searchField {
    UITextField *textField = objc_getAssociatedObject(self, _cmd);
    if (textField) {
        return textField;
    }

    @synchronized(self) {
        textField = [self retrieveTextFieldInView:self depth:1];
        objc_setAssociatedObject(self, _cmd, textField, OBJC_ASSOCIATION_ASSIGN);
    }
    return textField;
}

- (UITextFieldViewMode)textFieldClearButtonMode {
    UITextField *searchField = [self ch_searchField];
    if (searchField) {
        return searchField.clearButtonMode;
    }
    return UITextFieldViewModeAlways;
}

- (void)setTextFieldClearButtonMode:(UITextFieldViewMode)textFieldClearButtonMode {
    UITextField *searchField = [self ch_searchField];
    if (searchField) {
        searchField.clearButtonMode = textFieldClearButtonMode;
    }
}

@end

このカテゴリを使えば、検索バーにフォーカスがあたっている時のみクリアボタンを表示したい場合、textFieldClearButtonModeUITextFieldViewModeWhilteEditingを設定すれば変更できます。

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)];
self.searchBar.textFieldClearButtonMode = UITextFieldViewModeWhileEditing;

Storyboardに追加した検索バーのクリアボタン表示モードを変更したい場合は、 User defined runtime attributes を使って変更すればよいでしょう。

  • Key Path: textFieldClearButtonMode
  • Type: Number
  • Value: 1
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5