在storyboard中的静态UITableView中拖入 UISearchBar and Search Display Controller出现的奇怪问题

最近学习过程中想模拟一下新浪微博“发现”界面。

我在storyboard中拖入一个UITableViewController,设置这个UITableViewController的TableView为Static Cells,然后添加了两个Section,每个Section两行Cell。

接下来往这个TableView中拖入了一个UISearchBar and Search Display Controller,storyboard中的结构如下图:

然后在UITableViewController对应的WBDiscoverTableViewController.m中实现相关的协议方法。代码如下:

#import
"WBDiscoverTableViewController.h"

@interface
WBDiscoverTableViewController ()

@property (weak,
nonatomic)
IBOutlet
UISearchBar *mySearchbar;

@property (nonatomic,
strong)
NSArray *results;

@property (weak,
nonatomic)
IBOutlet
UITableViewCell *hotTopicsCell1;

@property (weak,
nonatomic)
IBOutlet
UITableViewCell *hotTopicsCell2;

@property (weak,
nonatomic)
IBOutlet
UITableViewCell *nearbyPeopleCell;

@property (weak,
nonatomic)
IBOutlet
UITableViewCell *nearbyWeiboCell;

@end

@implementation WBDiscoverTableViewController

- (void)viewDidLoad {

[super
viewDidLoad];

static
NSString *cellID =
@"resultCell";

[self.searchDisplayController.searchResultsTableView
registerClass:[UITableViewCell
class]
forCellReuseIdentifier:cellID];

}

- (void)viewWillAppear:(BOOL)animated
{

}

- (void)searchWithString
{

switch (self.mySearchbar.selectedScopeButtonIndex)
{

case
0:

//搜用户

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsUsersWithString:self.mySearchbar.text
AndCount:20
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

case
1:

//搜学校

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsSchoolsWithString:self.mySearchbar.text
AndCount:20
AndType:0
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

case
2:

//搜公司

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsCompaniesWithString:self.mySearchbar.text
AndCount:20
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

default:

break;

}

}

#pragma mark UISearchBarDelegate

- (void)searchBarSearchButtonClicked:(UISearchBar
*)searchBar {

[self
searchWithString];

}

#pragma mark UISearchDisplayDelegate

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController
*)controller {

NSLog(@"WillBeginSearch....");

}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {

NSLog(@"DidBeginSearch....");

}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {

NSLog(@"WillEndSearch....");

}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController
*)controller {

NSLog(@"DidEndSearch....");

}

- (BOOL)searchDisplayController:(UISearchDisplayController
*)controller shouldReloadTableForSearchString:(NSString *)searchString {

[self
searchWithString];

return
NO;

}

- (BOOL)searchDisplayController:(UISearchDisplayController
*)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {

[self
searchWithString];

return
NO;

}

#pragma mark - Table view data source

//由于这个控制器既是原来的WBDiscoverTableViewController,又是UISearchDisplayController的searchContentsController。

//WBDiscoverTableViewController的tableView和searchResultsTableView的delegat都指向这个对象(self),

//所以需要在回调中区别到底是哪个tableView

- (NSInteger)numberOfSectionsInTableView:(UITableView
*)tableView {

if (tableView ==
self.tableView)
{

return
2;

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView){

return
1;

} else

return
0;

}

- (NSInteger)tableView:(UITableView
*)tableView numberOfRowsInSection:(NSInteger)section {

if (tableView ==
self.tableView)
{

return
2;

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView)
{

return
self.results.count;

} else

return
0;

}

- (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

if (tableView ==
self.tableView)
{

if (indexPath.section
== 0 && indexPath.row
== 0) {

return
self.hotTopicsCell1;

} else
if (indexPath.section
== 0 && indexPath.row
== 1) {

return
self.hotTopicsCell2;

} else
if (indexPath.section
== 1 && indexPath.row
== 0) {

return
self.nearbyPeopleCell;

} else {

return
self.nearbyWeiboCell;

}

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView)
{

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"resultCell"];

id result =
self.results[indexPath.row];

if ([result
isMemberOfClass:[WBSearchSuggestionsOfUsers
class]]) {

WBSearchSuggestionsOfUsers * suggestion = result;

cell.textLabel.text
= suggestion.nickName;

cell.detailTextLabel.text
= suggestion.followersCount;

} else
if ([result
isMemberOfClass:[WBSearchSuggestionsOfSchools
class]]) {

WBSearchSuggestionsOfSchools *suggestion = result;

cell.textLabel.text
= suggestion.schoolName;

cell.detailTextLabel.text
= suggestion.location;

} else {

WBSearchSuggestionsOfCompanies *suggestion = result;

cell.textLabel.text
= suggestion.suggestion;

}

return cell;

} else

return
nil;

}

- (CGFloat)tableView:(UITableView
*)tableView heightForHeaderInSection:(NSInteger)section {

return
10;

}

- (void)tableView:(UITableView
*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

//    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

UIViewController *vc = [[UIViewController
alloc]init];

vc.view.backgroundColor
= [UIColor
whiteColor];

[self.navigationController
pushViewController:vc
animated:YES];

}

@end

当我在UISearchBar中输入关键字进行搜索,如果返回结果的数量(self.results.count)大于2的时候,程序就会崩溃,错误原因:reason:
‘*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]’。

看起来是数组访问越界了,也就是说数组中只有两个对象,但是却访问了index为2的对象,于是程序就崩溃了。检查了代码,并没有什么异常,最后想到是不是静态TableView导致的问题呢?

于是决定将TableView修改为动态的,并修改WBDiscoverTableViewController.m中的代码:

#import
"WBDiscoverTableViewController.h"

@interface
WBDiscoverTableViewController ()

@property (weak,
nonatomic)
IBOutlet
UISearchBar *mySearchbar;

@property (nonatomic,
strong)
NSArray *results;

@end

@implementation WBDiscoverTableViewController

- (void)viewDidLoad {

[super
viewDidLoad];

[self.searchDisplayController.searchResultsTableView
registerNib:[UINib
nibWithNibName:@"WBsearchSuggestionCell"
bundle:[NSBundle
mainBundle]]
forCellReuseIdentifier:@"WBsearchSuggestionCell"];

[self.tableView
registerNib:[UINib
nibWithNibName:@"hotTopicsCell1"
bundle:[NSBundle
mainBundle]]
forCellReuseIdentifier:@"hotTopicsCell1"];

[self.tableView
registerNib:[UINib
nibWithNibName:@"hotTopicsCell2"
bundle:[NSBundle
mainBundle]]
forCellReuseIdentifier:@"hotTopicsCell2"];

[self.tableView
registerNib:[UINib
nibWithNibName:@"nearbyPeopleCell"
bundle:[NSBundle
mainBundle]]
forCellReuseIdentifier:@"nearbyPeopleCell"];

[self.tableView
registerNib:[UINib
nibWithNibName:@"nearbyWeiboCell"
bundle:[NSBundle
mainBundle]]
forCellReuseIdentifier:@"nearbyWeiboCell"];

}

- (void)searchWithString
{

switch (self.mySearchbar.selectedScopeButtonIndex)
{

case
0:

//搜用户

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsUsersWithString:self.mySearchbar.text
AndCount:20
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

case
1:

//搜学校

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsSchoolsWithString:self.mySearchbar.text
AndCount:20
AndType:0
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

case
2:

//搜公司

if ([[NSUserDefaults
standardUserDefaults]
objectForKey:@"accessToken"])
{

[[WBWeiboAPI
shareWeiboApi]
searchSuggestionsCompaniesWithString:self.mySearchbar.text
AndCount:20
CompletionCallBack:^(id
obj) {

self.results
= obj;

dispatch_async(dispatch_get_main_queue(),
^{

NSLog(@"self.results.count
:%ld", self.results.count);

[self.searchDisplayController.searchResultsTableView
reloadData];

});

}];

}

break;

default:

break;

}

}

#pragma mark UISearchBarDelegate

- (void)searchBarSearchButtonClicked:(UISearchBar
*)searchBar {

[self
searchWithString];

}

#pragma mark UISearchDisplayDelegate

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController
*)controller {

NSLog(@"WillBeginSearch....");

}

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {

NSLog(@"DidBeginSearch....");

}

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {

NSLog(@"WillEndSearch....");

}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController
*)controller {

NSLog(@"DidEndSearch....");

}

- (BOOL)searchDisplayController:(UISearchDisplayController
*)controller shouldReloadTableForSearchString:(NSString *)searchString {

[self
searchWithString];

return
NO;

}

- (BOOL)searchDisplayController:(UISearchDisplayController
*)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {

[self
searchWithString];

return
NO;

}

#pragma mark - Table view data source

//由于这个控制器既是原来的WBDiscoverTableViewController,又是UISearchDisplayController的searchContentsController。

//WBDiscoverTableViewController的tableView和searchResultsTableView的delegat都指向这个对象(self),

//所以需要在回调中区别到底是哪个tableView

- (NSInteger)numberOfSectionsInTableView:(UITableView
*)tableView {

if (tableView ==
self.tableView)
{

return
2;

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView){

return
1;

} else

return
0;

}

- (NSInteger)tableView:(UITableView
*)tableView numberOfRowsInSection:(NSInteger)section {

if (tableView ==
self.tableView)
{

return
2;

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView)
{

return
self.results.count;

} else

return
0;

}

- (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

if (tableView ==
self.tableView)
{

if (indexPath.section
== 0 && indexPath.row
== 0) {

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"hotTopicsCell1"
forIndexPath:indexPath];

return cell;

} else
if (indexPath.section
== 0 && indexPath.row
== 1) {

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"hotTopicsCell2"
forIndexPath:indexPath];

return cell;

} else
if (indexPath.section
== 1 && indexPath.row
== 0) {

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"nearbyPeopleCell"
forIndexPath:indexPath];

return cell;

} else {

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"nearbyWeiboCell"
forIndexPath:indexPath];

return cell;

}

} else
if (tableView ==
self.searchDisplayController.searchResultsTableView)
{

WBsearchSuggestionCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"WBsearchSuggestionCell"
forIndexPath:indexPath];

id result =
self.results[indexPath.row];

if ([result
isMemberOfClass:[WBSearchSuggestionsOfUsers
class]]) {

WBSearchSuggestionsOfUsers * suggestion = result;

cell.suggestion.text
= suggestion.nickName;

} else
if ([result
isMemberOfClass:[WBSearchSuggestionsOfSchools
class]]) {

WBSearchSuggestionsOfSchools *suggestion = result;

cell.suggestion.text
= suggestion.schoolName;

} else {

WBSearchSuggestionsOfCompanies *suggestion = result;

cell.suggestion.text
= suggestion.suggestion;

}

return cell;

} else

return
nil;

}

- (CGFloat)tableView:(UITableView
*)tableView heightForHeaderInSection:(NSInteger)section {

return
10;

}

- (void)tableView:(UITableView
*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

[tableView deselectRowAtIndexPath:indexPath
animated:YES];

UIViewController *vc = [[UIViewController
alloc]init];

vc.view.backgroundColor
= [UIColor
whiteColor];

[self.navigationController
pushViewController:vc
animated:YES];

}

@end

测试,问题解决了!

但是仍然心存疑问,为什么静态TableView会影响UISearchBar and Search Display Controller中 searchResultsTableView的cell?

时间: 2024-10-03 03:05:30

在storyboard中的静态UITableView中拖入 UISearchBar and Search Display Controller出现的奇怪问题的相关文章

StoryBoard中segue的使用

StoryBoard中segue的使用 点击button跳转到下一个页面, 条件是textField里有值时才能实现跳转功能, 否则不跳转, 这个功能的实现就需要用到segue 首先在storyboard中viewController中拖入一个imageView textField UIButton, 在ViewController中拉入一条segue选择modal到下一个页面, 关联方法到ViewController中 在segue中添加标识    输入内容不为空得时候, 进行页面间跳转  

iOS中 xib自定义View在storyboard中的使用

1,创建UIView 的SubClass 命名为MyView 2, new一个名为MyView的xib p1 3,配置xib的属性 p2 4,为View 添加背景色,添加一个按钮并定制按钮约束,这里我添加的约束为垂直居中,Button与View等宽,Button左边起点位置为0. p3 5,设置xib中的File’s owner = MyView, 拖拽view 到关联的代码中命名为contentView p4 6, 在storyboard 中对ViewController 添加一个View,之

Storyboard中segue使用总结

简介         场景转换在应用中是非常常见的,让用户在一个视图控制器内操作,能够实例化并显示另一个视图控制器,需要创建一个在两者之间相连的segue(转 场).比如导航控制器里面,某个场景中的操作可以触发转场去加载并显示另一个场景,转场可以将下一个控制器自动推入导航栈. 说明         Xcode6之前Storyboard里面的几种segue区别及视图切换:push.modal.popover.replace和custom可参考:http://www.2cto.com/kf/2012

Django中使用静态资源/文件

Django中常需要引用js,css,小图像文件,一般我们把这一类文件称为静态文件,放置在static文件夹中,接下来,对Django中配置静态文件进行下傻瓜式的步骤介绍 在工程目录下新建static文件夹 修改settings.py,添加 STATIC_URL = '/static/' STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, '..', 'static')) STATICFILES_DIRS = ( os.path.join(B

在容器中部署静态网站----Nginx

在容器中部署静态网站----Nginx 步骤: 1.创建映射端口的交互式容器 docker run -p 80 --name web -i -t daocloud.io/ubuntu /bin/bash 2.安装Nginx apt-get install -y nginx 3.安装文本编辑器vim apt-get install -y vim 4.创建静态页面 mkdir -p /var/www/html cd /var/www/html vim index.html 使用i切换到插入模式 在i

Signal处理中的函数可重入问题

1. Signal信号简介 信号是软件层次上模拟的中断,它是一种异步通信的处理机制.信号的异步性意味着,应用程序不用等待事件的发生,当信号发生时应用程序自动陷入到对应的信号处理函数中.产生信号的事件对进程而言是随机出现的.信号的响应方式有忽略.捕捉.执行默认动作三种. 2. 线程安全 线程安全函数:在C语言中局部变量是在栈中分配的,任何未使用静态数据或其他共享资源的函数都是线程安全的.使用全局变量的函数是非线程安全的.使用静态数据或其他共享资源的函数,必须通过加锁的方式来使函数实现线程安全. 线

在iOS中创建静态库

如果你作为iOS开发者已经有一段时间,可能会有一套属于自己的类和工具函数,它们在你的大多数项目中被重用. 重用代码的最简单方法是简单的 拷贝/粘贴 源文件.然而,这种方法很快就会成为维护时的噩梦.因为每个app都有自己的一份代码副本,你很难在修复bug或者升级时保证所有副本的同步. 这就是静态库要拯救你的.一个静态库是若干个类,函数,定义和资源的包装,你可以将其打包并很容易的在项目之间共享. 在本教程中,你将用两种方法亲手创建你自己的通用静态库. 为了获得最佳效果,你应该熟悉Objective-

c#中如何在一个panel中放入窗体

? 1 2 3 4 5 6 7 Form2 f2 = new Form2();       //实例化窗体FORM2              f2.TopLevel = false;    //设置为非顶级窗体              f2.FormBorderStyle = FormBorderStyle.None;            //设置窗体为非边框样式              f2.Dock = System.Windows.Forms.DockStyle.Fill;   /

C#基础——全局静态类中的静态类变量的设置

前言 今天在设计一个系统用户管理界面的时候,出现了一个问题: 由于要在不同窗体之间传递数据,所以想到了要设置全局变量,比如一个用户有属性,ID,UserName,UserPwd和UserPower,为了简便,设定了一个Manager的类,管理这四个属性.然后设置了一个静态类,ModuleParas,有一个静态类变量manager. 结果出现了可访问性不一致的问题. 代码 1 public class Manager 2 { 3 public int ID; 4 public string Use