我是初学者,当我第一次创建这个应用程序(简单的待办事项列表应用程序)时,我不知道Core Data。现在我正在尝试实现核心数据,但似乎我想这样做,我基本上必须完全改变我的应用程序。例如,我使用Core Data创建了一个新的Master Detail Application,并将其与我当前的应用程序进行了比较,基本上没有一个是相同的。
一个特别令人困惑的部分是,在我目前的表视图中,我有两个部分从两个不同的数组中获取它们的对象。如果我要添加核心数据,我不知道该怎么做。我是否必须完全消除数组并仅使用NSFetchedResultsController?此外,在我的应用程序中,我有模态视图控制器。在Master Detail应用程序中,Core Data似乎仅在Master视图中工作。我不知道如何在模态视图控制器(它定义任务对象的值)中实现核心数据。我是否必须在模态视图controller.h中再次为所有managedObjectContext,managedObject,entityDescription,fetchRequest等声明属性?
如果您关心,以下是我的一些代码:
TableViewController.m
-(NSMutableArray *)taskArray {
if (!taskArray) {
taskArray = [NSMutableArray array];
}
return taskArray;
}
-(NSMutableArray *)completedArray {
if (!completedArray) {
completedArray = [NSMutableArray array];
}
return completedArray;
}
-(IBAction)changeSettings:(id)sender{
SettingsViewController *svc = [[SettingsViewController alloc]initWithColor:baseColor];
[svc setDelegate:self];
[svc setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:svc animated:YES completion:NULL];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cellSubclassCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (!cell)
cell = [[cellSubclassCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
if([indexPath section] == 0){
cell.textLabel.text = [[[self.taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:@"unchecked.png"];
cell.imageView.highlightedImage = [UIImage imageNamed:@"uncheckedhighlighted.png"];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setBackgroundColor:[UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f]];
cell.textLabel.textColor = baseColor;
NSString *detailText = [[self.taskArray objectAtIndex:[indexPath row]] timeIntervalString];
cell.detailTextLabel.text = detailText;
[[cell detailTextLabel] setFont:[UIFont fontWithName:@"Avenir-Black" size:12]];
[[cell textLabel] setFont:[UIFont fontWithName:@"AvenirNext-DemiBold" size:16]];
[cell.contentView setAlpha:1];
} else if ([indexPath section] == 1) {
cell.textLabel.text = [[[self.completedArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:@"checked.png"];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setBackgroundColor:[UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f]];
cell.textLabel.textColor = baseColor;
NSString *detailText = [[self.completedArray objectAtIndex:[indexPath row]] timeIntervalString];
cell.detailTextLabel.text = detailText;
[[cell detailTextLabel] setFont:[UIFont fontWithName:@"Avenir-Black" size:12]];
[[cell textLabel] setFont:[UIFont fontWithName:@"AvenirNext-DemiBold" size:16]];
[cell.contentView setAlpha:0.5];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handlechecking:)];
//cell.contentView
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES;
return cell;
}
-(void)handlechecking:(UITapGestureRecognizer *)t{
CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
NSIndexPath *newIndexPath = nil;
if (tappedIndexPath.section == 0) {
NSUInteger newRowIndex = self.completedArray.count;
[self.completedArray addObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
[self.taskArray removeObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:1];
} else {
NSUInteger newRowIndex = self.taskArray.count;
[self.taskArray addObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
[self.completedArray removeObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:@[tappedIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSInteger num = 0;
if (section == 0) {
num = self.taskArray.count;
} else {
num = self.completedArray.count;
}
return num;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
-(void)buttonPressed:(id)sender{
for(UIView *v in holdViewsArray){
if(button == sender){
[button setHighlighted:YES];
}
}
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
if (completedArray == nil){
headerView2.hidden = YES;
[headerView2 setNeedsDisplay];
} else {
headerView2.hidden = NO;
[headerView2 setNeedsDisplay];
}
switch (section) {
case 0:
return [holdViewsArray objectAtIndex:0];
break;
case 1:
return [holdViewsArray objectAtIndex:1];
break;
}
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
switch (section) {
case 0:
return 60.0;
break;
case 1:
return 43.0;
break;
}
return 0;
}
-(IBAction)addCell:(id)sender{
Properties2ViewController *pvc = [[Properties2ViewController alloc]init];
[pvc setDelegate:self];
[self presentViewController:pvc animated:YES completion:NULL];
[pvc setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
if (![[t taskName] isEqual: @""]) {
[taskArray addObject:t];
}
[self.tableView reloadData];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
Tasks *task = [[Tasks alloc]init];
if (indexPath.section == 0){
task.taskName = [[self.taskArray objectAtIndex:[indexPath row]] taskName];
task.timeInterval = [[self.taskArray objectAtIndex:[indexPath row]] timeInterval];
task.dateCreated = [[self.taskArray objectAtIndex:[indexPath row]] dateCreated];
} else if (indexPath.section == 1){
task.taskName = [[self.completedArray objectAtIndex:[indexPath row]] taskName];
task.timeInterval = [[self.completedArray objectAtIndex:[indexPath row]] timeInterval];
task.dateCreated = [[self.completedArray objectAtIndex:[indexPath row]] dateCreated];
}
DetailViewController *dvc = [[DetailViewController alloc]init];
[dvc setTestTask:task];
[[self navigationController] pushViewController:dvc animated:YES];
}
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
if (sourceIndexPath.section == 0){
Tasks *taskToMove = [taskArray objectAtIndex:[sourceIndexPath row]];
if (sourceIndexPath.row > destinationIndexPath.row) {
[taskArray insertObject:taskToMove atIndex:destinationIndexPath.row];
[taskArray removeObjectAtIndex:(sourceIndexPath.row + 1)];
}
else if (sourceIndexPath.row < destinationIndexPath.row) {
[taskArray insertObject:taskToMove atIndex:(destinationIndexPath.row + 1)];
[taskArray removeObjectAtIndex:(sourceIndexPath.row)];
}
} else if (sourceIndexPath.section == 1){
Tasks *completedTaskToMove = [completedArray objectAtIndex:[sourceIndexPath row]];
if (sourceIndexPath.row > destinationIndexPath.row) {
[completedArray insertObject:completedTaskToMove atIndex:destinationIndexPath.row];
[completedArray removeObjectAtIndex:(sourceIndexPath.row + 1)];
}
else if (sourceIndexPath.row < destinationIndexPath.row) {
[completedArray insertObject:completedTaskToMove atIndex:(destinationIndexPath.row + 1)];
[completedArray removeObjectAtIndex:(sourceIndexPath.row)];
}
}
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
if ([self isEditing]){
for(UIView *v in holdViewsArray){
button.hidden = YES;
}
} else {
button.hidden = NO;
}
}
-(void)loadView{
[super loadView];
}
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
if (proposedDestinationIndexPath.section != sourceIndexPath.section)
{
return sourceIndexPath;
}
return proposedDestinationIndexPath;
}
-(void)changeBackgroundColor:(UIColor *)c{
baseColor = c;
[self.tableView setSeparatorColor:c];
[self.tableView setBackgroundColor:c];
button.fillColor = c;
[button setNeedsDisplay];
}
@end
基本上我需要做的就是保存用户添加的对象,并保存用户指定的时间间隔,因为我想为每个对象添加一个计时器(这样如果应用程序关闭,对象就是还在那儿)。我是否需要完整的Core Data实现才能执行此操作?我甚至需要核心数据吗?我真的很感激一些指导,因为我不知道该做什么。
--- --- EDIT 另一个问题。在添加Core Data之前,我有自定义委派将属性从我的模态视图控制器发送到我的表视图控制器。有了核心数据,我还需要这些吗?我想我没有,但有没有办法将属性从一个视图控制器发送到下一个核心数据?
答案 0 :(得分:4)
不,您不必废弃您的申请。但是,核心数据的学习曲线相当陡峭,对于初学者来说,将其重新编写到现有应用程序中可能相当困难。
基本上,您需要设置所谓的核心数据堆栈。这只意味着你有适当的类来使用Core Data。
我建议您在自己的应用代表(或类似地方)中设置NSPersistentStoreCoordinator
,NSPersistentStore
和NSManagedObjectContext
。在核心数据术语中,持久存储本质上是您的数据库文件。托管对象上下文是您访问该文件中对象的方式:它的功能类似于暂存器,因此您可以对对象进行更改,并且在您调用save:
之前,它们不会被写入持久性存储区。托管对象上下文。
让应用程序代理在应用程序启动时设置这些对象。 (Core Data Xcode项目模板将为您提供帮助。)然后,访问Core Data对象的每个视图控制器都需要了解您的托管对象上下文。我建议你在每个这样的视图控制器上定义一个属性。然后,无论何时创建视图控制器,都要传入托管对象上下文(以便App Delegate将其传递给根视图控制器,并且该视图控制器将其传递给下一个控制器等)。
一个特别令人困惑的部分是,在我目前的表视图中,我有两个部分从两个不同的数组中获取它们的对象。如果我要添加核心数据,我不知道该怎么做。我是否必须完全消除数组并仅使用NSFetchedResultsController?
如果你愿意的话,你可以使用它,这只是一种不同的模式。
基本上,NSFetchedResultsController
是将Core Data查询映射到表视图的便捷方式。它做了一些聪明的事情,比如在Core Data对象发生变化时使表自动刷新。
另一种方法是运行您自己的查询(可能是viewDidLoad:
或viewWillAppear:
或类似)。然后,您将拥有一系列对象,您可以将这些对象提供给现有代码。查看NSFetchRequest
进行查询,以及executeFetchRequest:error:
上NSManagedObjectContext
方法实际运行查询。
另一个问题。在添加Core Data之前,我有自定义委派将属性从我的模态视图控制器发送到我的表视图控制器。有了核心数据,我还需要这些吗?我想我没有,但有没有办法将属性从一个视图控制器发送到下一个核心数据?
有很多方法可以解决这个问题。
如果每个视图控制器都在同一个数据库中编辑核心数据对象,那么只要视图出现,您就可以让每个视图控制器刷新其数据(即再次执行获取)。
或者您仍然可以使用您的委托模式,但是让委托方法只是为了触发获取:它不会传递属性,它只是说“某些内容已经更改,您可能想重新加载,好吗?”。< / p>
或者您可以使用NSFetchedResultsController,它应该自动获取更改。
答案 1 :(得分:0)
我也是一个初学者。对我来说,最好从CoreData启动您的应用程序。模型必须是持久性存储的“图像”(或商店的一部分的“图像”,称为配置)。如果您没有持久属性(那些可以在应用程序运行时更改的属性,然后需要在应用程序关闭后使用更改的值保存),那么您不需要CoreData。