2

私は初心者で、最初にこのアプリケーション (シンプルな To Do リスト アプリ) を作成したとき、Core Data について知りませんでした。現在、Core Data を実装しようとしていますが、実装したい場合は、基本的にアプリケーションを完全に変更する必要があるようです。たとえば、Core Data を使用して新しいマスター ディテール アプリケーションを作成し、それを現在のアプリケーションと比較しましたが、基本的にどれも同じではありません。

特に紛らわしい部分の 1 つは、現在のテーブル ビューに、2 つの異なる配列からオブジェクトを取得する 2 つのセクションがあることです。コア データを追加するとしたら、その方法がわかりません。配列を完全に削除し、NSFetchedResultsController のみを使用する必要がありますか? また、私のアプリケーションにはモーダル ビュー コントローラーがあります。マスター詳細アプリケーションでは、コア データはマスター ビューでのみ機能するようです。モーダルビューコントローラー(タスクオブジェクトの値を定義する)にコアデータを実装する方法がわかりません。モーダル ビュー 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 の完全な実装が必要ですか? Core Data も必要ですか? この時点で何をすべきか分からないので、アドバイスをいただければ幸いです。

---編集--- 別の質問です。コア データを追加する前に、モーダル ビュー コントローラーからテーブル ビュー コントローラーにプロパティを送信するカスタム委任がありました。コア データの場合、これらはまだ必要ですか? 私はそうではないと思っていますが、コアデータを使用して、あるビューコントローラーから次のビューコントローラーにプロパティを送信する方法はありますか?

4

2 に答える 2

4

いいえ、申請を破棄する必要はありません。ただし、Core Data の学習曲線はかなり急勾配であり、既存のアプリに作り直すことは、初心者にとってかなり難しい場合があります。

基本的に、Core Data スタックと呼ばれるものをセットアップする必要があります。つまり、Core Data を使用するための適切なクラスが用意されているということです。

NSPersistentStoreCoordinatorApp Delegate (または同様の場所) で、 、NSPersistentStore、およびを設定することをお勧めしますNSManagedObjectContext。Core Data の用語では、永続ストアは基本的にデータベース ファイルです。save:管理オブジェクト コンテキストは、そのファイル内のオブジェクトにアクセスする方法です。これはスクラッチ パッドのように機能するため、オブジェクトに変更を加えることができ、管理オブジェクト コンテキストを呼び出すまで、オブジェクトは永続ストアに書き込まれません。

アプリの起動時に、アプリ デリゲートにこれらのオブジェクトを設定してもらいます。(Core Data Xcode プロジェクト テンプレートが役に立ちます。) 次に、Core Data オブジェクトにアクセスする各ビュー コントローラーは、管理対象オブジェクト コンテキストを認識する必要があります。そのようなビュー コントローラーごとにプロパティを定義することをお勧めします。次に、ビュー コントローラーを作成するたびに、マネージド オブジェクト コンテキストを渡します (アプリ デリゲートがそれをルート ビュー コントローラーに渡し、そのビュー コントローラーがそれを次のビュー コントローラーに渡すなど)。

特に紛らわしい部分の 1 つは、現在のテーブル ビューに、2 つの異なる配列からオブジェクトを取得する 2 つのセクションがあることです。コア データを追加するとしたら、その方法がわかりません。配列を完全に削除し、NSFetchedResultsController のみを使用する必要がありますか?

する必要はありません。必要に応じて使用できる別のパターンです。

基本的に、NSFetchedResultsControllerは Core Data クエリをテーブル ビューにマップする便利な方法です。Core Data オブジェクトが変更された場合にテーブルを自動的に更新するなど、いくつかの巧妙な処理を行います。

別の方法は、独自のクエリを実行することです (おそらく inviewDidLoad:またはviewWillAppear:類似)。次に、おそらく既存のコードにフィードできるオブジェクトの配列が得られます。NSFetchRequestクエリを作成する方法executeFetchRequest:error:NSManagedObjectContext、実際に実行する方法を調べてください。

別の質問です。コア データを追加する前に、モーダル ビュー コントローラーからテーブル ビュー コントローラーにプロパティを送信するカスタム委任がありました。コア データの場合、これらはまだ必要ですか? 私はそうではないと思っていますが、コアデータを使用して、あるビューコントローラーから次のビューコントローラーにプロパティを送信する方法はありますか?

それにアプローチする方法はいくつかあります。

各View Controllerが同じデータベース内のCore Dataオブジェクトを編集している場合、ビューが表示されるたびに各View Controllerにデータを更新させる(つまり、フェッチを再度実行させる)ことができます。

または、引き続きデリゲート パターンを使用することもできますが、フェッチをトリガーするためだけにデリゲート メソッドを使用することもできます。これはプロパティを渡さず、「一部のコンテンツが変更されました。リロードしますか?」と言うだけです。

または、変更を自動的に取得する NSFetchedResultsController を使用することもできます。

于 2013-07-25T18:29:58.723 に答える