添加新项目后 UITableView 未更新(使用核心数据)
Posted
技术标签:
【中文标题】添加新项目后 UITableView 未更新(使用核心数据)【英文标题】:UITableView not being updated after adding new items (using Core Data) 【发布时间】:2014-05-14 11:06:12 【问题描述】:我使用 Core Data 来跟踪一个简单的待办事项列表中的条目。我使用带有 UITextField 的简单 UIAlertView 供用户添加新条目。条目是使用 NSManagedObject 保存的,但即使在我运行 [self.tableView reloadData];
之后,最新条目也不会添加到 tableview 中
这个 GIF 展示了它现在的工作原理:
头文件:
#import <UIKit/UIKit.h>
@interface PakkelisteViewController : UITableViewController <UIAlertViewDelegate>
@end
实现文件:
#import "PakkelisteViewController.h"
#import "AUFToDoItem.h"
@interface PakkelisteViewController ()
@property NSMutableArray *toDoItems;
-(IBAction)addNewToDoItem;
@end
@implementation PakkelisteViewController
- (id)initWithStyle:(UITableViewStyle)style
self = [super initWithStyle:style];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// defaultTodos = [[NSMutableArray alloc] initWithObjects:@"Badetøy", @"Skrivesaker", @"Lommepenger", @"Godt humør", nil];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
-(void)viewWillAppear:(BOOL)animated
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"AUFToDoItem"];
self.toDoItems = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
-(void)loadInitialData
-(IBAction)addNewToDoItem
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Legg til ny" message:nil delegate:self cancelButtonTitle:@"Avbryt" otherButtonTitles:@"Legg til", nil];
[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[alertView textFieldAtIndex:0] setPlaceholder:@"Rent undertøy"];
[[alertView textFieldAtIndex:0] setAutocapitalizationType:UITextAutocapitalizationTypeSentences];
[alertView show];
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if ([inputText length] > 0)
return YES;
else
return NO;
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
if (buttonIndex == 1)
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:@"itemName"];
[toDoItem setValue:[NSDate date] forKey:@"creationDate"];
[toDoItem setValue:NO forKey:@"completed"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error])
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
// [self.tableView reloadData];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// Return the number of sections.
return 1;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// Return the number of rows in the section.
return self.toDoItems.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];
NSManagedObject *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
cell.textLabel.text = [toDoItem valueForKey:@"itemName"];
if ((BOOL)[toDoItem valueForKey:@"completed"] == YES)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
/*
[tableView deselectRowAtIndexPath:indexPath animated:NO];
AUFToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
*/
-(NSManagedObjectContext *)managedObjectContext
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:@selector(managedObjectContext)])
context = [delegate managedObjectContext];
return context;
// 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
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete)
[context deleteObject:[self.toDoItems objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error])
NSLog(@"Can't delete! %@ %@", error, [error localizedDescription]);
return;
[self.toDoItems removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
/*
// 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 storyboard-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.
*/
@end
【问题讨论】:
if (cell == nil) in before add cell=nil;这个想法在我的代码中完美运行。 取消注释 [self.tableView reloadData];它会正常工作的。 @DarshanKunjadiya:不确定你的意思? @PrabhuNatarajan:没用。这就是为什么它被注释掉了,而我正在尝试reloadRowsAtIndexPaths:
方法。
您只需将该行添加到您的列表数组 [self.toDoItems addObject:toDoItem];
【参考方案1】:
您还需要将新的 toDoItem 添加到您的数组中。试试这个:
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:@"itemName"];
[toDoItem setValue:[NSDate date] forKey:@"creationDate"];
[toDoItem setValue:NO forKey:@"completed"];
[self.toDoItems addObject:toDoItem];
[self.tableView reloadData];
【讨论】:
谢谢,这解决了。我怎么会忘记将它添加到数组中.. facepalm【参考方案2】:您应该更新您的数据源self.toDoItems
,因为它仍然与viewDidLoad
方法中的关闭相同。您只是将其保存在 CoreData 中,而不是刷新您的 dataSourse 和 [tableView reloadData]
不会做任何事情
【讨论】:
以上是关于添加新项目后 UITableView 未更新(使用核心数据)的主要内容,如果未能解决你的问题,请参考以下文章
MapItemView 在 dataChanged 信号后未更新
IOS 蓝牙 LE 扫描设备未添加到 uitableview
在 swift uiTableView 中调用 reloadData() 后,旧项目剩余,新项目未显示