Ios 表视图部分中的搜索结果对象不应有的行为
我有一个带有节的Ios 表视图部分中的搜索结果对象不应有的行为,ios,uitableview,core-data,uisearchbar,Ios,Uitableview,Core Data,Uisearchbar,我有一个带有节的UITableView。每个核心数据对象显示在预期部分下。为了测试应用程序,我添加了3个对象 1. item 2(overdue)-> OVERDUE section 2. item 1(today)-> TODAY section 3. item 3(upcoming)->UPCOMING section. 我还实现了一个搜索栏,它通过属性todoName过滤对象(只需要匹配3个字符)。 这是应用程序第一个视图中的屏幕截图: 如果我在搜索栏控制器中引入搜索
UITableView
。每个核心数据对象
显示在预期部分下。为了测试应用程序,我添加了3个对象
1. item 2(overdue)-> OVERDUE section
2. item 1(today)-> TODAY section
3. item 3(upcoming)->UPCOMING section.
我还实现了一个搜索栏
,它通过属性todoName过滤对象(只需要匹配3个字符)。
这是应用程序第一个视图中的屏幕截图:
如果我在搜索栏控制器中引入搜索字符串,结果对象将重复显示,并显示在所有部分下。搜索“day”后,请参见下面的示例
以下是我的问题:
1。我需要结果对象可以显示在其上一节下,也可以不显示在任何节下,但不能显示在所有节下
2.结果对象失去了右>符号,点击时不提供任何操作
欢迎任何建议或帮助。
以下是我目前的代码:
#import "ToDoItemsTableViewController.h"
#import "AppDelegate.h"
#import "AddToDoItemViewController.h"
#import "ToDoSubItemsTableViewController.h"
@interface ToDoItemsTableViewController ()
@property (nonatomic, strong)NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong)NSFetchedResultsController *fetchedResultsController;
@end
@implementation ToDoItemsTableViewController
@synthesize searchResults;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(NSManagedObjectContext *)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//navigation bar background image
[self.navigationController.navigationBar
setBackgroundImage:[UIImage imageNamed:@"navBar.png"]
forBarMetrics:UIBarMetricsDefault];
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor blackColor],NSForegroundColorAttributeName,
[UIColor blackColor],NSBackgroundColorAttributeName,nil];
self.navigationController.navigationBar.titleTextAttributes = textAttributes;
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]){
NSLog(@"Error %@",error);
abort();
}
self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];
[self.tableView reloadData];
}
-(void) viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
}
- (void)viewDidUnload
{
self.searchResults = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier]isEqualToString:@"addToDoItem"]){
UINavigationController *navigationController = segue.destinationViewController;
AddToDoItemViewController *addToDoItemViewController = (AddToDoItemViewController*)navigationController.topViewController;
ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"ToDoItem" inManagedObjectContext:self.managedObjectContext];
addToDoItem.todoDueDate = [NSDate date];
addToDoItemViewController.addToDoItem = addToDoItem;
}
if ([[segue identifier] isEqualToString:@"toToDoSubItems"]){
ToDoSubItemsTableViewController *todoSubItemsTableViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ToDoItem *selectedToDoItem = (ToDoItem*)[self.fetchedResultsController objectAtIndexPath:indexPath];
todoSubItemsTableViewController.selectedToDoItem = selectedToDoItem;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else {
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
ToDoItem *toDoItem = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSLog(@"Configuring cell to show search results");
toDoItem = [self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.todoName;
NSDate *fechaToDO = toDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
else
{
ToDoItem *todoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoItem.todoName;
NSDate *fechaToDO = todoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *header = @"customHeader";
UITableViewHeaderFooterView *vHeader;
vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];
if (!vHeader) {
vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
if (section == 0) {
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
else if (section == 1) {
vHeader.textLabel.backgroundColor = [UIColor orangeColor];
vHeader.textLabel.textColor = [UIColor blueColor];
vHeader.contentView.backgroundColor = [UIColor orangeColor];
}
else if (section == 2) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];
return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
NSString *sectionname = [theSection name];
if ([sectionname isEqualToString:@"0"]){
NSString *valor = [NSString stringWithFormat:@"O V E R D U E (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"1"]){
NSString *valor = [NSString stringWithFormat:@"T O D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:@"2"]){
NSString *valor = [NSString stringWithFormat:@"U P C O M I N G (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
if ([[self.fetchedResultsController sections]count]>0){
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo name];
}
else{
return nil;
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil){
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ToDoItem" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"todoName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"sectionIdentifier" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
-(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
UITableView *tableView = self.tableView;
switch (type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:{
ToDoItem *changeToDoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changeToDoItem.todoName;
NSDate *fechaToDO = changeToDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
NSManagedObjectContext *context = [self managedObjectContext];
ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:ToDoItemToDelete];
NSError *error = nil;
if (![context save:&error]){
NSLog(@"Error: %@",error);
}
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark -
#pragma mark Content Filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
self.searchResults = [[self.fetchedResultsController fetchedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
ToDoItem * item = evaluatedObject;
NSString* name = item.todoName;
//searchText having length < 3 should not be considered
if (!!searchText && [searchText length] < 3) {
return YES;
}
if ([scope isEqualToString:@"All"] || [name isEqualToString:scope]) {
return ([name rangeOfString:searchText].location != NSNotFound);
}
return NO; //if nothing matches
}]];
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:@"All"];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:@"All"];
return YES;
}
@end
但在尝试删除搜索结果对象时,应用程序显示以下异常:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
请检查我更改的方法以检测问题所在,谢谢
这里是完整的异常,可能有助于您检测问题:
[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x89be750
2014-01-16 22:54:08.530 To-Do Pro Light[2319:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x89be750'
*** First throw call stack:
(
0 CoreFoundation 0x01aab5e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0182e8b6 objc_exception_throw + 44
2 CoreFoundation 0x01b48903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x01a9b90b ___forwarding___ + 1019
4 CoreFoundation 0x01a9b4ee _CF_forwarding_prep_0 + 14
5 To-Do Pro Light 0x00004eda -[ToDoItemsTableViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 298
6 UIKit 0x0068cba3 -[UITableView animateDeletionOfRowWithCell:] + 107
7 UIKit 0x0080c695 -[UITableViewCell _swipeDeleteButtonPushed] + 70
8 libobjc.A.dylib 0x01840874 -[NSObject performSelector:withObject:withObject:] + 77
9 UIKit 0x0059e0c2 -[UIApplication sendAction:to:from:forEvent:] + 108
10 UIKit 0x0059e04e -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
11 UIKit 0x006960c1 -[UIControl sendAction:to:forEvent:] + 66
12 UIKit 0x00696484 -[UIControl _sendActionsForEvents:withEvent:] + 577
13 UIKit 0x00695733 -[UIControl touchesEnded:withEvent:] + 641
14 UIKit 0x00910c7f _UIGestureRecognizerUpdate + 7166
15 UIKit 0x005db19a -[UIWindow _sendGesturesForEvent:] + 1291
16 UIKit 0x005dc0ba -[UIWindow sendEvent:] + 1030
17 UIKit 0x005afe86 -[UIApplication sendEvent:] + 242
18 UIKit 0x0059a18f _UIApplicationHandleEventQueue + 11421
19 CoreFoundation 0x01a3483f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
20 CoreFoundation 0x01a341cb __CFRunLoopDoSources0 + 235
21 CoreFoundation 0x01a5129e __CFRunLoopRun + 910
22 CoreFoundation 0x01a50ac3 CFRunLoopRunSpecific + 467
23 CoreFoundation 0x01a508db CFRunLoopRunInMode + 123
24 GraphicsServices 0x038bc9e2 GSEventRunModal + 192
25 GraphicsServices 0x038bc809 GSEventRun + 104
26 UIKit 0x0059cd3b UIApplicationMain + 1225
27 To-Do Pro Light 0x00007d2d main + 141
28 libdyld.dylib 0x020e7725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException
您需要将
numberOfSectionsInTableView:
更改为
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return 1;
}
else
{
return [[self.fetchedResultsController sections]count];
}
}
编辑关于崩溃的第二个问题
更改committeditingstyle:forRowAtIndexPath:
如:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
[self.searchResults removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
NSManagedObjectContext *context = [self managedObjectContext];
ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:ToDoItemToDelete];
NSError *error = nil;
if (![context save:&error])
{
NSLog(@"Error: %@",error);
}
}
}
}
@mvasco:您需要在
viewForHeaderInSection
和titleForHeaderInSection
@mvasco:您需要使用if(tableView==self.searchDisplayController.searchResultsTableView)
检查if(tableView==self.searchDisplayController.searchResultsTableView)并从这些方法返回适当的视图和标题。您还可以使用cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator在cellForRowAtIndexPath中设置>arrow@mvasco:对不起,我离线了。您需要实现didSelectRowAtIndexPath
方法,在此方法中,您需要打开新的视图控制器。@mvasco:我认为没有,因为searchDisplayController.searchResultsTableView
是动态创建的。它不会使用您在故事板中设计的tableview。@mvasco:如果条件问题相同:)现在将其放在-(void)tableview:(UITableView*)tableview CommittedItingStyle:(UITableViewCellEditingStyle)editingStyle for RowAtIndexPath:(NSIndexPath*)indexPath上,对于searchDisplayTable,删除不能这样做。您需要使用RowAnimation:UITableViewRowAnimationFade调用tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]代码>
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
[self.searchResults removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
NSManagedObjectContext *context = [self managedObjectContext];
ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:ToDoItemToDelete];
NSError *error = nil;
if (![context save:&error])
{
NSLog(@"Error: %@",error);
}
}
}
}