我想在我的应用中为TableView
添加搜索功能。我使用NSArray
填充了一个表格,x
Objects
个NSStrings
包含3个NSArray
。以下是我如何构建Code.h
:
首先我创建一个班级#import <Foundation/Foundation.h>
@interface Code : NSObject
@property (nonatomic, strong) NSString *codeName;
@property (nonatomic, strong) NSString *codeNumber;
@property (nonatomic, strong) NSString *codeDesc;
@end
:
NSStrings
接下来,我在Code.m
中合成了这些SearchViewController.m
。
现在我的NSMutableArray *codes;
codes = [[NSMutableArray alloc] init];
Code *c = [[Code alloc] init];
[c setCodeNumber:@"1"];
[c setCodeName:@"First Title Here"];
[c setCodeDesc:@"I might write a desc in here."];
[codes addObject:c];
c = [[Code alloc] init];
[c setCodeNumber:@"2"];
[c setCodeName:@"Second Title Here"];
[c setCodeDesc:@"2nd desc would be written here."];
[codes addObject:c];
,以下是我创建数据集的方法:
cellForRowAtIndexPath
依旧......
以下是我展示它的方式: Code *c = [codes objectAtIndex:indexPath.row];
NSString *fused = [NSString stringWithFormat:@"%@ - %@",[c codeNumber],[c codeName]];
cell.textLabel.text = fused;
return cell;
:
NSArray
现在您已了解我的数据的结构和显示方式,您是否了解如何搜索已创建的TableCells
或可能(最好)Adding a Search Bar to a TableView
?< / p>
我已经浏览了一些关于arrayWithObjects
的在线教程,但所有这些教程都是为使用简单arrayWithObjects:@"aaa-1",@"bbb-2",@"ccc-3"...
使用数组设置而编写的。
SIDETHOUGHT:我可以从我的数据构建@property (nonatomic, strong) NSString *searchString;
吗?如果我可以管理它,我可以使用这些教程填充我的单元格并搜索它们!
更新:
你的第二个答案对我来说更有意义!感谢那。我相信我已经按照你的指示,但我得到一个&#34; - [代码搜索:]:无法识别的选择器在命中该行时发送到实例0x6a2eb20`。
Code.h
添加到Code.m
并在NSMutableSet *searchResults;
SearchViewController.h
添加到@interface
&#39; s performSearchWithString
matchFound
和SearchViewController.m
添加到performSearchWithString
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchString {
NSLog(@"%@",searchString); //Just making sure searchString is set
[self performSearchWithString:searchString];
[self.tableView reloadData];
}
X
[codes makeObjectsPerformSelector:@selector(search:) withObject:self];
searchResults
运行时出现错误。我很困惑b / c它听起来像Code不识别searchString,但我知道我在Code.h中添加了它。
更新:
为了在searchResults
中存储对象,我必须将NSMutableSet
从NSMutableArray
更改为- (void)matchFound:(Code *) matchingCode {}
并将-(void) matchFound:(Code *) matchingCode {
Code *match = [[Code alloc] init];
if (searchResults.count == 0) {
searchResults = [[NSMutableArray alloc] init];
[match setCodeName:[matchingCode codeName]];
[match setCodeNumber:[matchingCode codeNumber]];
[match setCodeDesc:[matchingCode codeDesc]];
[searchResults addObject:match];
}
else
{
match = [[Code alloc] init];
[match setCodeName:[matchingCode codeName]];
[match setCodeNumber:[matchingCode codeNumber]];
[match setCodeDesc:[matchingCode codeDesc]];
[searchResults addObject:match];
}
修改为:
NSRange rangeName = [codeName rangeOfString: searchString options:NSCaseInsensitiveSearch];
通过其他一些推文,我的tableView上有一个可用的搜索栏。谢谢Tim Kemp!
哦,我也在寻找不区分大小写的搜索。 {{1}}
我希望这个问题和答案有助于下一个开发人员学习这个问题的目标-c!
答案 0 :(得分:2)
更简单的方法
你问了一个更简单的解决方案。这个并不是那么灵活,但它会达到和我之前对这个特定情况的答案相同的东西。
我们再一次要求Code
为我们搜索字符串。这一次,我们将跳过SearchRequest
和块回调并直接实现它。
在SearchViewController
中,您将创建两种方法。一个进行搜索,一个回调处理任何结果,因为他们回来了。您还需要一个容器来存储匹配的Code
对象(可能是多个匹配的对象)。您还需要向Code
添加一个方法来告诉它搜索字符串是什么。
NSMutableSet
的ivar searchResults
添加到SearchViewController
。NSString *
的{{1}}类型的媒体添加到searchString
将搜索方法添加到Code
。当您想要在所有代码中启动搜索时,这就是您要调用的内容:
SearchViewController
然后您还需要-(void) performSearchWithString:(NSString *) searchString {
// Tell each Code what string to search for
[codes makeObjectsPerformSelector:@selector(setSearchString:) withObject:searchString];
// Make each code perform the search
[codes makeObjectsPerformSelector:@selector(search:) withObject:self];
}
中的回调。这样,您的SearchViewController
个对象就可以告诉Code
他们找到了匹配项:
SearchViewController
但请注意, 使用-(void) matchFound:(Code *) matchingCode {
[searchResults addObject:matchingCode];
// do something with the matching code. Add it to a different table
// view, or filter it or whatever you need it to do.
}
可变集;您可能希望只调用另一种方法立即将返回的结果添加到屏幕上的其他列表中。这取决于您的应用程序的需求。
在searchResults
中,添加一个与之前相同的搜索方法,但我们会在Code
的引用中传递SearchRequest
参数:
SearchViewController
你看到它是如何工作的吗?如果任何字符串中存在匹配( - (void) search:(SearchViewController *) searchVC {
// Search each string in turn
NSRange rangeNum = [codeNumber rangeOfString : searchString];
NSRange rangeName = [codeName rangeOfString : searchString];
NSRange rangeDesc = [codeDesc rangeOfString: searchString];
if (rangeNum.location != NSNotFound || rangeName.location != NSNotFound || rangeDesc.location != NSNotFound) {
[searchVC matchFound:self];
}
}
表示'或'),则传递||
(这意味着它的确切含义:当前正在运行此代码的当前对象)返回方法在名为self
的视图控制器中。这称为回调,因为我们正在“回调”最初向我们发送消息以进行搜索的对象。我们必须使用回调而不是简单的返回类型,因为我们使用searchVC
来告诉makeObjectsPerformSelector
数组中的每个Code
进行搜索。我们从未明确地调用codes
方法,因此我们无法从每个search
中捕获返回值。这就是为什么它的返回类型是search
。
您可以扩展void
以获取一个附加参数,该参数标识匹配所在的字符串(即matchFound
,çodeNumber
或codeName
。)查看{{1作为传递这种数据的一种好方法。
希望这有点简单。
Here is a link to an excellent language introduction/tutorial这将消除很多混乱。
编辑在上一条评论中,您说codeDesc
为空。我说要在enums
的某处添加它作为ivar。在SearchViewController的初始化方法中,您应该调用
searchResults
或者你可以在SearchViewController
中'懒惰地初始化':
searchResults = [[NSMutableSet alloc] initWithCapacity:50]` // Choose some sensible number other than 50; enough to hold the likely number of matching Code objects.
虽然如果你这样做,你应该知道,如果以前从未调用matchFound
,你访问- (void) matchFound:(Code *) matchingCode {
if (!searchResults)
searchResults = [[NSMutableSet alloc] initWithCapacity:50];
[searchResults addObject:matchingCode];
}
的任何其他地方都可能会发现它为空。
答案 1 :(得分:1)
原创,灵活,更复杂的答案
我有点不清楚你要做什么,所以我要用你的标题,“在数组的每个对象中搜索每个字符串。”在您的情况下,您的Code
有三个字符串,您的数组有多个Code
。我假设你需要一种方法告诉调用者 - 想要进行搜索的代码 - Code
匹配。
这是一种方法。有更简单的方法,但这种技术非常灵活。从广义上讲,我们将使Code
对象完成搜索自己的字符串的工作。然后我们将赋予Code
对象能够告诉调用者(即拥有codes
数组的对象,可能是您的表视图控制器)是否其任何字符串与搜索字符串匹配。然后,我们将使用NSArray
的方法makeObjectsPerformSelector
来告诉所有Code
个对象自行搜索。我们将使用一个块进行回调。
首先,将search
方法添加到Code
(在界面中,或根据您的设计作为类别),如下所示:
-(void) search:(SearchRequest *) request {
// Search using your favourite algorithm
// eg bool matches = [searchMe [request searchString]];
if (matches) {
[request foundMatch:self];
}
}
SearchRequest
是新的。这是一个将搜索字符串和回调块组合在一起的地方。它看起来像这样:
@interface SearchRequest
@property (retain) NSString * searchString;
@property (copy) void (^callback)(Code *);
- (id) initWithSearchString:(NSString *) search callback:(void (^)(Code *)) callback;
- (void) foundMatch:(Code *) matchingCode;
@end
@implementation SearchRequest
// synthesize...
// initialiser sets ivars
- (void) foundMatch:(Code *) matchingCode {
callback(matchingCode);
}
callback
块是我们与呼叫者进行通信的方式。
当您想要执行搜索时,使用您要搜索的字符串构造一个SeachRequest
对象,以及一个包含要在匹配时调用的方法的块。
在调用者中看起来像这样:
- (void) performASearchWithString:(NSString *) searchForMe {
SearchRequest * req = [[SearchRequest alloc] initWithSearchString:searchForMe
callback:^(Code * matchingCode) {
[self foundAHit:matchingCode];
}];
[codes makeObjectsPerformSelector:@selector(search:) withObject:req];
}
然后,您需要在调用者中实现foundAHit
,这将获取匹配的Code
并对其执行某些操作。 (你不必使用一个块:你可以存储对调用者的引用和一个选择器来调用它。我不会在这里讨论任何一个案例的参数。其他的回答者可以提出替代方案。)