首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将searchBar添加到TableView中

将searchBar添加到TableView中
EN

Stack Overflow用户
提问于 2012-01-20 18:16:58
回答 2查看 1.4K关注 0票数 1

我想在我的应用程序中向TableView添加搜索功能。我用一个NSArray填充一个表,该表的x值为Objects,包含3 NSStrings。下面是我如何构造这个NSArray

首先,我创建一个类Code.h

代码语言:javascript
运行
复制
#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中,我是如何创建数据集的:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
 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的教程,但它们都是为使用使用简单arrayWithObjects的数组设置而编写的。

SIDETHOUGHT:我可以根据我的数据构造一个arrayWithObjects:@"aaa-1",@"bbb-2",@"ccc-3"...吗?如果我能做到这一点,我就可以使用这些教程填充我的单元格并搜索它们!

更新:

你的第二个答案对我来说更有意义!谢谢你这么说。我相信我已经遵循了您的指示,但是当该行被击中时,我得到了一个"-Code搜索::未识别的选择器发送到实例0x6a2eb20“。

  1. 我将@property (nonatomic, strong) NSString *searchString;添加到Code.h中,并在Code.m中合成了它
  2. 我把NSMutableSet *searchResults;添加到SearchViewController.h@interface中。
  3. 我将您的方法performSearchWithStringmatchFound添加到SearchViewController.m
  4. 在我添加这个命令的直接下面调用performSearchWithString

X

代码语言:javascript
运行
复制
- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchString {
NSLog(@"%@",searchString); //Just making sure searchString is set
[self performSearchWithString:searchString];
[self.tableView reloadData];
}

[codes makeObjectsPerformSelector:@selector(search:) withObject:self];运行时,该错误就会发生。我很困惑b/c --听起来代码不认识searchString,但我知道我在Code.h中添加了它。

更新:为了在searchResults中存储对象,我必须将searchResultsNSMutableSet更改为NSMutableArray,并将- (void)matchFound:(Code *) matchingCode {}修改为:

代码语言:javascript
运行
复制
-(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];

}

在其他几个星期里,我已经为我的tableView找到了一个工作搜索栏。谢谢蒂姆·肯普!

哦,我要找的也是不分大小写的搜索。NSRange rangeName = [codeName rangeOfString: searchString options:NSCaseInsensitiveSearch];

我希望这个问题和答案将有助于下一个开发人员学习这个问题的目标-c!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-21 17:56:31

简单方法

你要求一个更简单的解决方案。这一个几乎没有那么灵活,但它将实现与我先前对这个具体案例的回答相同的东西。

我们将再次要求Code为我们搜索它的字符串。这一次,我们将跳过SearchRequest和块回调,直接实现它。

在您的SearchViewController中,您将创建两个方法。一个执行搜索,一个回调来处理返回的任何结果。您还需要一个容器来存储匹配的Code对象(可能不止一个匹配)。您还需要向Code添加一个方法来告诉它搜索字符串是什么。

  1. NSMutableSet中添加一个名为searchResults的ivar searchResults
  2. NSString *类型的属性searchString添加到Code
  3. 将搜索方法添加到SearchViewController。当你想在你的所有代码中启动搜索时,你会这样称呼: -(PerformSearchWithString) performSearchWithString:(NSString *) searchString { //告诉每个代码使用search :searchString搜索代码的字符串;//使每个代码执行搜索代码makeObjectsPerformSelector:@selector(搜索:);
  4. 然后,还需要在SearchViewController中进行回调。这样您的Code对象就可以告诉SearchViewController他们找到了匹配的: -(void) matchFound:(Code *) matchingCode { searchResults addObject:matchingCode;//处理匹配的代码。将它添加到另一个表//视图中,或者过滤它或您需要它做的任何事情。}

但是,请注意,您不必使用searchResults可变集;您很可能只想调用另一个方法立即将返回的结果添加到屏幕上的其他列表中。这取决于你的应用程序的需求。

Code中,添加一个与以前一样的搜索方法,但我们将传递一个对SearchViewController的引用,而不是SearchRequest参数

代码语言:javascript
运行
复制
    - (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告诉codes数组中的每个Code进行搜索。我们从不自己显式地调用search方法,因此无法从每个search捕获返回值。这就是为什么它的返回类型是void

您可以扩展matchFound以接受一个额外的参数,该参数标识匹配所在的字符串(即çodeNumbercodeNamecodeDesc)。将enums视为传递此类数据的一种很好的方法。

希望那样简单点。

这里是一个链接到一个优秀的语言介绍/教程,这将消除许多混乱。

在您最后的评论中,您说searchResults为null。我说过要把它添加到SearchViewController的某个地方。在SearchViewController的initialiser方法中,应该调用

代码语言:javascript
运行
复制
searchResults = [[NSMutableSet alloc] initWithCapacity:50]` // Choose some sensible number other than 50; enough to hold the likely number of matching Code objects.

或者,您可以在matchFound中“懒惰初始化”它。

代码语言:javascript
运行
复制
- (void) matchFound:(Code *) matchingCode {
  if (!searchResults)
    searchResults = [[NSMutableSet alloc] initWithCapacity:50];

  [searchResults addObject:matchingCode];
}

但是,如果您这样做,您应该知道访问searchResults的任何其他地方都可能会发现,如果matchCode:以前从未被调用过,那么它就是null。

票数 2
EN

Stack Overflow用户

发布于 2012-01-20 21:07:48

原始的,灵活的,更复杂的答案

我有点不清楚你想要做什么,所以我用你的标题“搜索数组的每个对象中的每个字符串”。在您的例子中,Code有三个字符串,数组有多个Code,我假设您需要一种方法来告诉调用者--想要进行搜索的代码-- Code匹配的代码。

这里有一种方法。有更简单的方法,但这种技术是相当灵活的。总的来说,我们将让Code对象完成搜索自己的字符串的工作。然后,我们将让Code对象能够告诉调用方(即拥有codes数组的对象,大概是您的表视图控制器),它的任何字符串是否与搜索字符串匹配。然后,我们将使用NSArray的方法makeObjectsPerformSelector,必须告诉它的所有Code对象来搜索自己,我们将使用一个块进行回调。

首先,将search方法添加到Code (在接口中,或作为一个类别(取决于您的设计)),如下所示:

代码语言:javascript
运行
复制
-(void) search:(SearchRequest *) request {
  // Search using your favourite algorithm
  // eg bool matches = [searchMe [request searchString]];
  if (matches) {
    [request foundMatch:self];
  }
}

SearchRequest是新的。这是一个将搜索字符串和回调块绑定在一起的地方。看起来是这样的:

代码语言:javascript
运行
复制
@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对象,并构造一个块,其中包含匹配时要调用的方法。应该是这样的,在来电者中:

代码语言:javascript
运行
复制
- (void) performASearchWithString:(NSString *) searchForMe {
    SearchRequest * req = [[SearchRequest alloc] initWithSearchString:searchForMe 
                                     callback:^(Code * matchingCode) {
                                                  [self foundAHit:matchingCode];
                                     }];

    [codes makeObjectsPerformSelector:@selector(search:) withObject:req];
}

然后,您需要在调用方中实现foundAHit,它接受匹配的Code并对其执行一些操作。(您不必使用块:您可以存储对调用方的引用和选择器来调用它。我不会在这里讨论这两种情况的论据。其他回答者可以提出替代方案。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8945981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档