58

トランザクションを挿入するためのユーザー インターフェイスがあります。ユーザーがプラスをクリックすると、画面が表示され、Core Data NSManagedObject エンティティをインスタンス化したいので、ユーザーに作業させます。次に、ユーザーが [保存] ボタンをクリックすると、保存機能が呼び出されます。

コードまで:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
//even if i dont call save: its going to show up on my table
[self.managedObjectContext save:&error]

PS 私はそのテーブルで NSFetchedResultsController を使用していますが、NSFetchedResultsController がセクションとオブジェクトをテーブルに挿入していることがわかります。

私の考えでは、トランザクション NSManagedObject をインスタンス化する方法があれば、クライアントが選択するまで保存せずに更新できます。

4

6 に答える 6

38

価値のあることとして、Marcus Zarra はnilコンテキスト アプローチを推進しているようで、新しいコンテキストを作成するにはコストがかかると主張しています。詳細については、同様の質問に対するこの回答を参照してください。

アップデート

私は現在 nil context アプローチを使用しており、他の人にとって興味深いものに遭遇しました。コンテキストなしで管理対象オブジェクトを作成するには、 のinitWithEntity:insertIntoManagedObjectContext:メソッドを使用しますNSManagedObject。この方法に関するAppleのドキュメントによると:

contextではない場合nil、このメソッドが呼び出されます[context insertObject:self] (これによりawakeFromInsert、呼び出されます)。

ここでの意味は重要です。nil管理対象オブジェクトの作成時にコンテキストを使用するinsertObject:と、呼び出されなくなり、したがって呼び出されなくなりますawakeFromInsert。したがって、オブジェクトの初期化またはデフォルト プロパティ値の設定は、コンテキストawakeFromInsertの使用時に自動的には行われません。nil

結論: コンテキストなしでマネージド オブジェクトを使用する場合、awakeFromInsertは自動的に呼び出されず、補正するために追加のコードが必要になる場合があります。

于 2010-10-06T00:01:39.263 に答える
19

これが私がそれをどのように解決したかです:

新しいトランザクションを処理していることがわかっているロード時に、コンテキスト外のトランザクションを作成しました。

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext];
        transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

それから関係船を設立することになると私はこれをしました:

if( transaction.managedObjectContext == nil){
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext];
        Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
        category.title = ((Category *)obj).title;
        transaction.category = category;
        [category release];
    }
    else {
        transaction.category = (Category *)obj;
    }

そして最後に保存します:

if (transaction.managedObjectContext == nil) {
        [self.managedObjectContext insertObject:transaction.category];
        [self.managedObjectContext insertObject:transaction];
    }
    //NSLog(@"\n saving transaction\n%@", self.transaction);

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
于 2010-10-06T14:34:30.843 に答える
18

nil MOC の使用には根本的な問題があります。異なる MOC 内のオブジェクトは相互に参照することは想定されていません。これはおそらく、関係の片側に nil MOC がある場合にも当てはまります。保存するとどうなりますか?(アプリの別の部分が保存されるとどうなりますか?)

オブジェクトに関係がない場合、できることはたくさんあります (NSCoding など)。

NSPredicateで使用できる可能性があります-[NSManagedObject isInserted](おそらく、挿入と正常な保存の間は YES です)。または、同じ動作を持つ一時的なプロパティを使用することもできます (awakeFromInsert で YES に設定し、willSave で NO に設定します)。アプリの別の部分が保存される場合、これらの両方が問題になる可能性があります。

ただし、2 番目の MOC を使用することは、CoreData の使用が「想定」される方法です。競合の検出と解決を自動的に処理します。もちろん、変更があるたびに新しい MOC を作成する必要はありません。UI の一部が他の部分の保存されていない変更を表示することを気にしない場合は、低速の「ユーザー スレッド」による保存されていない変更に対して 1 つの MOC を使用することが漠然と賢明かもしれません (MOC 間通信のオーバーヘッドは無視できます)。

于 2010-10-06T00:51:50.147 に答える
8

を挿入しNSManagedObjectContextて、管理対象オブジェクト コンテキスト-[NSManagedObject initWithEntity:insertIntoManagedObjectContext:]を渡すことができます。nilもちろん、それをコンテキストに割り当てる必要があります(-[NSManageObjectContext insertObject:]保存する前に使用します。これは、私が知る限り、Core Dataの意図したパターンではありません(ただし、@mzarraの回答を参照してくださいhere)。いくつかのトリッキーな順序の問題があります(つまり、インスタンスがコンテキストを持つことを期待する前に、インスタンスがコンテキストに割り当てられることを確認するなど) より標準的なパターンは、新しい管理オブジェクト コンテキストを作成し、新しいオブジェクトをそのコンテキストに挿入することです。コンテキストを処理NSManagedObjectDidSaveNotificationし、変更を「メイン」コンテキストにマージします. ユーザーがトランザクションをキャンセルした場合、コンテキストを吹き飛ばしてビジネスを続行します.

于 2010-10-05T23:34:40.770 に答える
2

nil をコンテキストとして使用して NSManagedObject を作成できますが、他の NSManagedObjects にリンクする必要がある場合、エラーが発生します。私が行う方法では、コンテキストを宛先画面に渡し、その画面で NSManagedObject を作成します。すべての変更を他の NSManagedObjects にリンクします。ユーザーがキャンセル ボタンをタップすると、NSManagedObject が削除され、コンテキストが保存されます。ユーザーが保存ボタンをタップすると、NSManagedObject のデータが更新され、コンテキストに保存され、画面が解放されます。ソース画面で、テーブルをリロードして更新します。

宛先画面で NSManagedObject を削除すると、コア データにファイルを更新する時間が与えられます。これは通常、テーブルビューに変更が表示されないのに十分な時間です。iPhone カレンダー アプリでは、保存してからテーブルビューに表示されるまでに遅延があります。これは、ユーザーが追加されたばかりの行に集中するという UI の観点からは良いことと見なすことができます。これが役立つことを願っています。

于 2012-06-29T14:42:49.243 に答える