0

我在 StackOverflow 上看到了很多问题,但其中大多数都没有得到解答。我创建了一个使用 CoreData 的应用程序。要访问数据,您必须单击正确的 UITableView 单元格,其中单元格名称(textLabel)来自 Core Data 属性,例如

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...
    NSManagedObject *data = [self.datas objectAtIndex:indexPath.row];
    [cell.textLabel setText:[NSString stringWithFormat:@"%@", [data valueForKey:@"name"]]];
    [cell.detailTextLabel setText:nil];
}

之后,我遵循了许多关于如何添加 UISearchBar 的教程,但应用程序总是崩溃,因为他无法将 UISearchBar 文本与存储在用于单元格的 textLabel 的核心数据中的信息匹配(应该被过滤)

对于过滤,我使用了在网上找到的这种方法:

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{ // searchDati = array where i'm supposed to store the filtered rows
  /* datas was created like this:
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Data"];
self.datas = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];  to manage the Core Data i suppose.*/

    [_searchDati removeAllObjects];
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", searchText];
    _searchDati = [NSMutableArray arrayWithArray:[_datas filteredArrayUsingPredicate:resultPredicate]];
}


-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                      objectAtIndex:[self.searchDisplayController.searchBar
                                                     selectedScopeButtonIndex]]];

    return YES;
}

你能告诉我应该如何进行吗?如果很难提供代码,您至少可以告诉我是否有一种简单的方法可以让 UISearchBar 与核心数据交互(以便我在网上查看)或者我应该做什么。提前致谢

4

1 回答 1

1

让我们从您对 CoreData 的调用开始,然后一旦它起作用,您就可以继续查询它并从搜索栏响应。

由于 UITableViewControllerDelegate 协议方法期望一个非常快速的响应,标准做法是从数据库中获取您需要的数据并将其存储在一个类变量中,然后让 tableview:cellForRowAtIndexPath: 方法根据需要从类变量中加载它们的数据。

When you make changes to the data, you update the class variable, and can call reloadData: on the tableView to have the interface catch up (view is not model...)

Start with configuring a proper fetch request, and loading the response into a NSMutableArray class variable. An example looks like this:

- (void)loadFiltersFromStore {
    _enabledFilters = nil;
    AppDelegate* delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext* moc = [delegate managedObjectContext];
    NSEntityDescription* description = [NSEntityDescription entityForName:@"Filter" inManagedObjectContext:moc];
    NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    NSFetchRequest* request = [[NSFetchRequest alloc] init];
    [request setEntity:description];
    [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
    NSError *error;
    _enabledFilters = [NSMutableArray arrayWithArray:[moc executeFetchRequest:request error:&error]];
    if (error) {
        NSLog(@"%@",error.localizedDescription);
    }
}

Now you have some data fetched and present in a class variable (in this example that variable is an NSMutableArray called "enabledFilters", and it contains multiple instances of an NSManagedObject called "Filter")

Now you can access that data for your tableView to consume like so:

FreeCell* cell = [cv dequeueReusableCellWithReuseIdentifier:@"oneCell" forIndexPath:indexPath];
Filter* thisFilter = (Filter*)[_enabledFilters objectAtIndex:indexPath.row];
cell.label.text = thisFilter.name;
cell.label.backgroundColor = [UIColor clearColor];
NSString*targetName = thisFilter.imageName;
UIImage *image = [UIImage imageNamed:targetName];
cell.image.image = image;
BOOL purchased = (BOOL)[[NSUserDefaults standardUserDefaults] valueForKey:k_upgradePurchased];
if ([thisFilter.paidOrFree isEqual: @"free"]) {
    cell.lockImage.hidden = YES;
}
else if (purchased) {
    cell.lockImage.hidden = YES;
}
else {
    cell.lockImage.hidden = NO;
}
return cell;

I purposely setup this table view so that the row will always correspond to the index of an object in _enabledFilters. You don't have to do that, but it is pretty common practice.

Now you can access the attributes for each instance of your NSManagedObject with simple 'dot' accessors. In that example, I'm pulling the values stored in three different attributes (.name .imageName and .paidOrFree) and using them to configure the specific cell.

Get your underlying CoreData working properly first, and the searchBar problem will become far more approachable.

于 2013-10-18T20:38:10.150 回答