IOS 8 Objective-C 搜索栏和 Table 视图使用 Google 自动完成
IOS 8 Objective-C Search bar and Table view Using Google Autocomplete
我是 iOS 开发的新手,我已经被这个问题困扰了两周了。我正在尝试从 google 搜索结果中创建一个具有自动完成功能的搜索栏。我能做到的最接近的是遵循这个 tutorial by Hybrid Forge。 (我发现的其他教程没有使用 ARC,而且已经过时了。)
我可以通过 NSLog 看到 URL 连接正常工作,但问题出在我重新分配我的 suggestionArray 时。如果我注释掉这部分:
_suggestionArray = [NSArray arrayWithArray:json[@"responseData"][@"results"]];
[_tableView reloadData];
它给出了这个错误:
[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x7f968be3a060
2015-05-21 17:43:11.277 AutoComplete[865:65704] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x7f968be3a060'
*** First throw call stack:
(
0 CoreFoundation 0x00000001077daa75 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000107473bb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001077e1d1d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001077399dc ___forwarding___ + 988
4 CoreFoundation 0x0000000107739578 _CF_forwarding_prep_0 + 120
5 UIKit 0x0000000107f4cdbd -[UITableViewLabel setText:] + 81
6 AutoComplete 0x0000000106f40acd -[ViewController tableView:cellForRowAtIndexPath:] + 333
7 UIKit 0x0000000107cc1e03 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 508
8 UIKit 0x0000000107ca1901 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2846
9 UIKit 0x0000000107cb778c -[UITableView layoutSubviews] + 213
10 UIKit 0x0000000107c441c3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
11 QuartzCore 0x000000010b4d6c58 -[CALayer layoutSublayers] + 150
12 QuartzCore 0x000000010b4cb87e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
13 QuartzCore 0x000000010b4cb6ee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
14 QuartzCore 0x000000010b43936e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
15 QuartzCore 0x000000010b43a482 _ZN2CA11Transaction6commitEv + 390
16 QuartzCore 0x000000010b43aaed _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
17 CoreFoundation 0x000000010770f507 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
18 CoreFoundation 0x000000010770f460 __CFRunLoopDoObservers + 368
19 CoreFoundation 0x0000000107705293 __CFRunLoopRun + 1123
20 CoreFoundation 0x0000000107704bc6 CFRunLoopRunSpecific + 470
21 GraphicsServices 0x000000010adcaa58 GSEventRunModal + 161
22 UIKit 0x0000000107bca580 UIApplicationMain + 1282
23 AutoComplete 0x0000000106f41663 main + 115
24 libdyld.dylib 0x0000000109d88145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
这是我的代码:
[ViewController.h]
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@property (strong, readwrite, nonatomic) NSArray *suggestionArray;
@end
[ViewController.m]
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableViewDataSource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _suggestionArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_suggestionArray objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - UITableViewDelegate Methods
- (void)tableView:(NSIndexPath *)indexPath {
_searchBar.text = [_suggestionArray objectAtIndex:indexPath.row];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[searchText stringByReplacingOccurrencesOfString:@" " withString:@"+"];
[searchText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", searchText);
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=large&q=%@",searchText]] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"connection test marker");
NSLog(@"%@", [NSArray arrayWithArray:json[@"responseData"][@"results"]]);
//_suggestionArray = [NSArray arrayWithArray:[NSArray arrayWithArray:json[@"responseData"][@"results"]]];
//[_tableView reloadData];
}];
[dataTask resume];
}
@end
我还按住 Ctrl 并从搜索显示控制器拖动到 table 视图并选择了 "searchResultsDelegate"(将其放在这里以防万一)。
如有任何帮助,我们将不胜感激。谢谢! :)
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=large&q=%@",searchText]] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(!json){ // is a valid json ?
return;
}
NSDictionary * jsonDict = [json objectForKey:@"responseData"];
_suggestionArray = = [jsonDict objectForKey:@"results"]
[_tableView reloadData];
}];
然后更改密钥(例如:"titleNoFormatting")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[_suggestionArray objectAtIndex:indexPath.row] valueForKey:@"titleNoFormatting"];
return cell;
}
我是 iOS 开发的新手,我已经被这个问题困扰了两周了。我正在尝试从 google 搜索结果中创建一个具有自动完成功能的搜索栏。我能做到的最接近的是遵循这个 tutorial by Hybrid Forge。 (我发现的其他教程没有使用 ARC,而且已经过时了。)
我可以通过 NSLog 看到 URL 连接正常工作,但问题出在我重新分配我的 suggestionArray 时。如果我注释掉这部分:
_suggestionArray = [NSArray arrayWithArray:json[@"responseData"][@"results"]];
[_tableView reloadData];
它给出了这个错误:
[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x7f968be3a060
2015-05-21 17:43:11.277 AutoComplete[865:65704] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary isEqualToString:]: unrecognized selector sent to instance 0x7f968be3a060'
*** First throw call stack:
(
0 CoreFoundation 0x00000001077daa75 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000107473bb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001077e1d1d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001077399dc ___forwarding___ + 988
4 CoreFoundation 0x0000000107739578 _CF_forwarding_prep_0 + 120
5 UIKit 0x0000000107f4cdbd -[UITableViewLabel setText:] + 81
6 AutoComplete 0x0000000106f40acd -[ViewController tableView:cellForRowAtIndexPath:] + 333
7 UIKit 0x0000000107cc1e03 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 508
8 UIKit 0x0000000107ca1901 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2846
9 UIKit 0x0000000107cb778c -[UITableView layoutSubviews] + 213
10 UIKit 0x0000000107c441c3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
11 QuartzCore 0x000000010b4d6c58 -[CALayer layoutSublayers] + 150
12 QuartzCore 0x000000010b4cb87e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
13 QuartzCore 0x000000010b4cb6ee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
14 QuartzCore 0x000000010b43936e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
15 QuartzCore 0x000000010b43a482 _ZN2CA11Transaction6commitEv + 390
16 QuartzCore 0x000000010b43aaed _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
17 CoreFoundation 0x000000010770f507 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
18 CoreFoundation 0x000000010770f460 __CFRunLoopDoObservers + 368
19 CoreFoundation 0x0000000107705293 __CFRunLoopRun + 1123
20 CoreFoundation 0x0000000107704bc6 CFRunLoopRunSpecific + 470
21 GraphicsServices 0x000000010adcaa58 GSEventRunModal + 161
22 UIKit 0x0000000107bca580 UIApplicationMain + 1282
23 AutoComplete 0x0000000106f41663 main + 115
24 libdyld.dylib 0x0000000109d88145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
这是我的代码: [ViewController.h]
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@property (strong, readwrite, nonatomic) NSArray *suggestionArray;
@end
[ViewController.m]
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableViewDataSource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _suggestionArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_suggestionArray objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - UITableViewDelegate Methods
- (void)tableView:(NSIndexPath *)indexPath {
_searchBar.text = [_suggestionArray objectAtIndex:indexPath.row];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[searchText stringByReplacingOccurrencesOfString:@" " withString:@"+"];
[searchText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", searchText);
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=large&q=%@",searchText]] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"connection test marker");
NSLog(@"%@", [NSArray arrayWithArray:json[@"responseData"][@"results"]]);
//_suggestionArray = [NSArray arrayWithArray:[NSArray arrayWithArray:json[@"responseData"][@"results"]]];
//[_tableView reloadData];
}];
[dataTask resume];
}
@end
我还按住 Ctrl 并从搜索显示控制器拖动到 table 视图并选择了 "searchResultsDelegate"(将其放在这里以防万一)。
如有任何帮助,我们将不胜感激。谢谢! :)
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=large&q=%@",searchText]] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(!json){ // is a valid json ?
return;
}
NSDictionary * jsonDict = [json objectForKey:@"responseData"];
_suggestionArray = = [jsonDict objectForKey:@"results"]
[_tableView reloadData];
}];
然后更改密钥(例如:"titleNoFormatting")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[_suggestionArray objectAtIndex:indexPath.row] valueForKey:@"titleNoFormatting"];
return cell;
}