1.TableView と Search Bar and Search Display を使うための下準備をする
1.プロジェクトからシングルビューをつくり、ストーリーボード上の ViewController に TableView と Search Bar and Search Display を配置する。
2.配置した2つの View(TableView と Search Bar and Search Display)を ViewController.mへそれぞれ接続する。
3.プロトコルを追加。
//ViewController.h(m)
———————————————-
@interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
//searchBar を接続(ストーリーボードからドラッグして行う)。
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
//TableView を接続(ストーリーボードからドラッグして行う)。
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
———————————————-
2.テーブルビューのセルにデータを表示させる
以下の記述をファイルに追加する。
//ViewController.h(m)
———————————————-
@interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
//searchBar を接続
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
//TableView を接続
@property (weak, nonatomic) IBOutlet UITableView *tableView;
/**
* さきほど記述した場所の下に追記する。テーブルに表示する情報が入ります
*/
@property (nonatomic, strong) NSArray *dataSourceiPhone;
@property (nonatomic, strong) NSArray *dataSourceAndroid;
@end
———————————————-
これを追記したタイミングで「”Assigning to ‘id<~>‘ from incompatible type ‘~’ “」のようなエラーが出る場合は、プロトコロルがきちんと実装できているか確認する。
//これも記述
———————————————-
– (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// デリゲートメソッドをこのクラスで実装する
self.tableView.delegate = self;
self.tableView.dataSource = self;
// テーブルに表示したいデータソースをセット
self.dataSourceiPhone = @[@”iPhone 4″, @”iPhone 4S”, @”iPhone 5″, @”iPhone 5c”, @”iPhone 5s”];
self.dataSourceAndroid = @[@”Nexus”, @”Galaxy”, @”Xperia”];
}
———————————————-
//これもまるまる追記
———————————————-
@implementation ViewController
(略)
//ここから下を全部追記
#pragma mark – TableViewDataSource delegate methods
/**
* テーブルに表示するデータ件数を返します(実装必須)
*
* @param tableView テーブルビュー
* @param section 対象セクション番号
*
* @return データ件数
*/
– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger dataCount;
switch (section) {
case 0:
dataCount = self.dataSourceiPhone.count;
break;
case 1:
dataCount = self.dataSourceAndroid.count;
break;
default:
break;
}
return dataCount;
}
/**
* テーブルに表示するセクション(区切り)の件数を返します(任意実装)
*
* @param テーブルビュー
*
* @return セクション件数
*/
– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
/**
* テーブルに表示するセルを返します(実装必須)
*
* @param tableView テーブルビュー
* @param indexPath セクション番号・行番号の組み合わせ
*
* @return セル
*/
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @”Cell”;
// 再利用できるセルがあれば再利用する
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// 再利用できない場合は新規で作成
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
switch (indexPath.section) {
case 0:
cell.textLabel.text = self.dataSourceiPhone[indexPath.row];
break;
case 1:
cell.textLabel.text = self.dataSourceAndroid[indexPath.row];
break;
default:
break;
}
return cell;
}
@end
———————————————-
セルにデータが表示てきていることを確認する。
3.検索バーをタップした時のTableViewControllerに検索結果を表示する準備をする
//検索結果を格納するNSArrayをプロパティで宣言する
———————————————-
@interface ViewController ()
@property (nonatomic, strong) NSArray *dataSourceiPhone;
@property (nonatomic, strong) NSArray *dataSourceAndroid;
//ここを追記
//検索結果を格納する配列
@property (nonatomic, strong) NSArray *dataSourceSearchResultsiPhone;
@property (nonatomic, strong) NSArray *dataSourceSearchResultsAndroid;
@end
———————————————-
結果を表示するViewControllerはStoryboardで 「Search Bar and Search Display」を紐づけした時に自動で参照が追加されて Self(UIViewController)にsearchDisplayController として紐づけられている。
//numberOfRowsInSectionを変更
———————————————-
– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger dataCount;
// ここのsearchDisplayControllerはStoryboardで紐付けされたsearchBarに自動で紐づけられている
//検索キーワードが入力されているか判定
if (tableView == self.searchDisplayController.searchResultsTableView) {
// 検索中のテーブルビューはこちらで処理
//セクションが複数ある場合はセクションごとに
switch (section) {
case 0:
dataCount = self.dataSourceSearchResultsiPhone.count;
break;
case 1:
dataCount = self.dataSourceSearchResultsAndroid.count;
break;
default:
break;
}
} else {
// 通常時のテーブルビューはこちらで処理
switch (section) {
case 0:
dataCount = self.dataSourceiPhone.count;
//もし、検索前のセルにデータを表示したくない場合はデータの数を0にする
//dataCount = 0;
break;
case 1:
dataCount = self.dataSourceAndroid.count;
break;
default:
break;
}
}
NSLog(@”%ld”, (long)dataCount);
return dataCount;
}
———————————————-
//cellForRowAtIndexPathを変更
———————————————-
– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @”Cell”;
// 再利用できるセルがあれば再利用する
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// 再利用できない場合は新規で作成
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// ここのsearchDisplayControllerはStoryboardで紐付けされたsearchBarに自動で紐づけられている
//検索キーワードが入力されているか判定
if (tableView == self.searchDisplayController.searchResultsTableView) {
// 検索中のテーブルビューはこちらで処理
//セクションが複数ある場合はセクションごとに
switch (indexPath.section) {
case 0:
cell.textLabel.text = self.dataSourceSearchResultsiPhone[indexPath.row];
break;
case 1:
cell.textLabel.text = self.dataSourceSearchResultsAndroid[indexPath.row];
break;
default:
break;
}
} else {
// 通常時のテーブルビューはこちらで処理
switch (indexPath.section) {
case 0: // iOS
cell.textLabel.text = self.dataSourceiPhone[indexPath.row];
break;
case 1: // Android
cell.textLabel.text = self.dataSourceAndroid[indexPath.row];
break;
default:
break;
}
}
return cell;
}
———————————————-
4.データを絞り込む
———————————————-
// 検索バーに入力された文字列を引数に、絞り込みをかけます
– (void)filterContainsWithSearchText:(NSString *)searchText
{
//CONTAINS右辺値が含まれているか,cは大文字小文字の区別なしオプション
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”SELF contains[c] %@”, searchText];
self.dataSourceSearchResultsiPhone = [self.dataSourceiPhone filteredArrayUsingPredicate:predicate];
self.dataSourceSearchResultsAndroid = [self.dataSourceAndroid filteredArrayUsingPredicate:predicate];
}
———————————————-
//検索バーの文字を編集する度に呼ばれるデリゲートメソッド
———————————————-
– (BOOL)searchDisplayController:controller shouldReloadTableForSearchString:(NSString *)searchString
{
// 検索バーに入力された文字列を引数に、絞り込みをかけます
[self filterContainsWithSearchText:searchString];
// YESを返すとテーブルビューがリロードされます。
// リロードすることでdataSourceSearchResultsiPhoneとdataSourceSearchResultsAndroidからテーブルビューを表示します
return YES;
}
———————————————-
//セルが選択されたら
———————————————-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@”セルが選択されました”);
}
———————————————-
↑これで、1度目のタップでうまく反応しない場合は、didSelectRowAtIndexPath が didDeselectRowAtIndexPath になっていないか確認すること。