为什么我的应用程序在调用UISearchBar的textDidChange时崩溃?



我有一个UITableView,它可以显示音乐库中的所有歌曲,效果很好。然而,当我开始在搜索栏中键入以缩小搜索结果时,应用程序会立即崩溃。就像我一按键盘上的一个字母,它就会崩溃。我试过重新设计我的textDidChange:方法,但不管怎样,它总是崩溃。我不知道我做错了什么,有人能帮忙吗?谢谢

标题:


@interface PTTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>
@property (strong,nonatomic)UITableView* tableView;
@property (strong,nonatomic)UISearchBar* searchBar;
@end

ViewController.m:


#import "PTTableViewController.h"
@implementation PTTableViewController
MPMediaQuery *songsQuery;
NSArray *songsArray;
NSMutableArray *filteredArray;
NSMutableArray *songTitlesArray;
-(void)viewDidLoad{
[super viewDidLoad];

self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,[UIScreen mainScreen].bounds.size.width - 75,150) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:_tableView];

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0,0,320,44)];
self.searchBar.delegate = self;
self.searchBar.placeholder = @"Search";
self.tableView.tableHeaderView = self.searchBar;

songsQuery = [MPMediaQuery songsQuery];
songsArray = [songsQuery items];

songTitlesArray = [[NSMutableArray alloc] init];
for (MPMediaItem *item in songsArray) {
[songTitlesArray addObject:[item valueForProperty:MPMediaItemPropertyTitle]];
}
filteredArray = [[NSMutableArray alloc] init];
filteredArray = [songTitlesArray copy];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return filteredArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
cell.textLabel.text = [filteredArray objectAtIndex:indexPath.row];
return cell;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
NSLog(@"search changed");
[self performSelectorInBackground:@selector(helper) withObject:nil];
}
-(void)helper{
[filteredArray removeAllObjects];

if ([self.searchBar.text isEqualToString:@""]){
filteredArray = [songTitlesArray copy];
} else {
for (NSString *object in songTitlesArray){
if ([object rangeOfString:self.searchBar.text].location == NSNotFound){
NSLog(@"string not found");
} else {
NSLog(@"string found");
[filteredArray addObject:object];
}
}
} [self.tableView reloadData];
}
@end

第一。。。

你这样做会导致崩溃:

filteredArray = [songTitlesArray copy];

它将songTitlesArray非可变副本分配给filteredArray

当你尝试这样做时:

[filteredArray removeAllObjects];

您正试图更改一个不可变的对象。

你可以用几种方法来解决这个(第一个(问题。。。

一种方法是将copy的所有实例更改为mutableCopy:

filteredArray = [songTitlesArray mutableCopy];

然而,使用您的确切代码,您将引入新的崩溃,因为您将在后台线程上执行UI操作。

下一步。。。你确定你得到了";键盘滞后";?

你可能想改变一些事情:

  • 使_filteredArray不可变
  • 不调用removeAllObjects,只需重新创建数组
  • 使用filteredArrayUsingPredicate,而不是循环遍历和比较每个字符串

试试看——因为我没有你的MPMediaQuery,所以我会生成500个字符串作为";歌曲标题":

@interface PTTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>
@property (strong,nonatomic)UITableView* tableView;
@property (strong,nonatomic)UISearchBar* searchBar;
@end
@implementation PTTableViewController
//MPMediaQuery *songsQuery;
NSArray *songsArray;
NSArray *filteredArray;
NSMutableArray *songTitlesArray;
-(void)viewDidLoad{
[super viewDidLoad];

self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,[UIScreen mainScreen].bounds.size.width - 75,150) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:_tableView];

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0,0,320,44)];
self.searchBar.delegate = self;
self.searchBar.placeholder = @"Search";
self.tableView.tableHeaderView = self.searchBar;

//  songsQuery = [MPMediaQuery songsQuery];
//  songsArray = [songsQuery items];
//
//  songTitlesArray = [[NSMutableArray alloc] init];
//  for (MPMediaItem *item in songsArray) {
//      [songTitlesArray addObject:[item valueForProperty:MPMediaItemPropertyTitle]];
//  }
//  filteredArray = [[NSMutableArray alloc] init];
//  filteredArray = [songTitlesArray copy];
// I don't have your Query, so let's create a 500 element string array,
//  using the row number + one of the following words in each entry
NSString *samples = @"These are some random words for the song titles.";
// So, we'll have:
//  "Row: 0 These"
//  "Row: 1 are"
//  "Row: 2 some"
//  "Row: 3 random"
//  "Row: 4 words"
//  "Row: 5 for"
//  "Row: 6 the"
//  "Row: 7 song"
//  "Row: 8 titles."
//  "Row: 9 These"
//  "Row: 10 are"
//  "Row: 11 some"
//  "Row: 12 random"
//  "Row: 13 words"
//  "Row: 14 for"
//  ... etc

NSArray *a = [samples componentsSeparatedByString:@" "];

songTitlesArray = [[NSMutableArray alloc] init];

for (int i = 0; i < 500; i++) {
NSString *w = a[i % [a count]];
NSString *s = [NSString stringWithFormat:@"Row: %d %@", i, w];
[songTitlesArray addObject:s];
}

filteredArray = [songTitlesArray copy];

}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return filteredArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}

cell.textLabel.text = [filteredArray objectAtIndex:indexPath.row];

return cell;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self helper];
}
-(void)helper{
if ([self.searchBar.text isEqualToString:@""]){
filteredArray = [songTitlesArray copy];
} else {
NSString *w = [NSString stringWithFormat:@"SELF contains[c] '%@'", self.searchBar.text];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:w];
filteredArray = [songTitlesArray filteredArrayUsingPredicate:sPredicate];
}
[self.tableView reloadData];
}
@end

顺便说一句,您已经很好地证明了NOT尝试在越狱设备上开发的(许多(原因之一。

最新更新