2

我是一个初学者,当我第一次制作这个应用程序(简单的待办事项列表应用程序)时,我并不了解 Core Data。现在我正在尝试实现 Core Data,但似乎如果我想这样做,我基本上必须完全改变我的应用程序。例如,我使用 Core Data 创建了一个新的 Master Detail 应用程序,并将其与我当前的应用程序进行比较,基本上没有一个是相同的。

一个特别令人困惑的部分是,在我当前的表视图中,我有两个部分从两个不同的数组中获取它们的对象。如果我要添加 Core Data,我不知道该怎么做。我是否必须完全消除数组并且只使用 NSFetchedResultsController?此外,在我的应用程序中,我有模态视图控制器。在 Master Detail 应用程序中,Core Data 似乎只在 Master 视图中工作。我不知道如何在模态视图控制器(定义任务对象的值)中实现核心数据。我是否必须在模态视图 controller.h 中再次声明所有 managedObjectContext、managedObject、entityDescription、fetchRequest 等的属性?

如果您关心,这是我的一些代码:

表视图控制器.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

基本上我需要做的就是保存用户添加的对象并保存用户指定的时间间隔,因为我想为每个对象添加一个计时器(这样如果应用程序关闭,对象仍然存在) . 我需要一个完整的核心数据实现来做到这一点吗?我什至需要核心数据吗?我真的很感激一些指导,因为我现在不知道该怎么做。

---编辑---另一个问题。在添加核心数据之前,我有自定义委托将属性从我的模式视图控制器发送到我的表视图控制器。有了核心数据,我还需要这些吗?我在想我没有,但有没有办法用核心数据将属性从一个视图控制器发送到下一个视图控制器?

4

2 回答 2

4

不,您不必废弃您的申请。然而,Core Data 的学习曲线相当陡峭,对于初学者来说,将其改造成现有的应用程序可能相当困难。

本质上,您需要设置所谓的核心数据堆栈。这仅仅意味着你有合适的类来使用 Core Data。

我建议在您的 App Delegate(或类似地方)中设置一个NSPersistentStoreCoordinator、一个NSPersistentStore和一个NSManagedObjectContext。在 Core Data 术语中,持久存储本质上是您的数据库文件。save:托管对象上下文是您访问该文件中的对象的方式:它的功能类似于暂存器,因此您可以对对象进行更改,并且在您调用托管对象上下文之前它们不会被写出到持久存储中。

让您的 App Delegate 在应用启动时设置这些对象。(Core Data Xcode 项目模板将为您提供帮助。)然后,访问 Core Data 对象的每个视图控制器都需要了解您的托管对象上下文。我建议您在每个这样的视图控制器上定义一个属性。然后,每当您创建视图控制器时,传入托管对象上下文(因此 App Delegate 将其传递给根视图控制器,然后该视图控制器将其传递给下一个视图控制器,等等)。

一个特别令人困惑的部分是,在我当前的表视图中,我有两个部分从两个不同的数组中获取它们的对象。如果我要添加 Core Data,我不知道该怎么做。我是否必须完全消除数组并且只使用 NSFetchedResultsController?

您不必这样做,这只是您可以根据需要使用的不同模式。

本质上,anNSFetchedResultsController是一种将 Core Data 查询映射到表视图的便捷方式。它做了一些聪明的事情,比如当你的 Core Data 对象改变时让表格自动刷新。

另一种方法是运行您自己的查询(大概是在viewDidLoad:viewWillAppear:类似的)。然后,您将拥有一个对象数组,您可以将其提供给您现有的代码。研究NSFetchRequest进行查询,以及实际运行它们的方法。executeFetchRequest:error:NSManagedObjectContext

另一个问题。在添加核心数据之前,我有自定义委托将属性从我的模式视图控制器发送到我的表视图控制器。有了核心数据,我还需要这些吗?我在想我没有,但有没有办法用核心数据将属性从一个视图控制器发送到下一个视图控制器?

有很多方法可以解决这个问题。

如果您的每个视图控制器都在同一数据库中编辑 Core Data 对象,那么您可以让每个视图控制器在其视图出现时刷新其数据(即再次执行获取)。

或者您仍然可以使用您的委托模式,但委托方法仅用于触发提取:它不传递属性,它只是说“某些内容已更改,您可能想要重新加载,好吗?”。

或者您可以使用 NSFetchedResultsController,它应该会自动获取更改。

于 2013-07-25T18:29:58.723 回答
0

我也是一个初学者。对我来说,最好从 CoreData 启动您的应用程序。模型必须是持久存储的“图像”(或存储的一部分的“图像”,称为配置)。如果您没有持久属性(那些可以在应用程序运行时更改,然后需要在应用程序关闭后与更改的值一起保存的属性),那么您不需要 CoreData。

于 2013-07-25T17:57:15.073 回答