iOSのコアデータ。 章番号1。 理論部

ハブラリュディ、こんにちは!
本日、マイケル・プリバートとロバート・ワーナーの本「iOS用のプロコアデータ」に関する実践的な演習で一連の講義を書き始めたいと思います。 各章には、理論的および実用的な部分が含まれます。



内容:



降りる


コアデータとは

コンピューターを使用してタスクを実行すると、変更が保存されることが期待されます。 変更の保存は、オフィスソフトウェアパッケージ、テキストエディター、ゲーム、ブラウザーなどで重要な役割を果たします。 ほとんどのソフトウェアには、作業状態を後で復元するためにユーザーが入力したデータを保存する機能が必要ですが、もちろん、それを必要としないソフトウェアがあります-電卓、ニュースフィード、アラーム、天気ウィジェット。
高度なアプリケーションを開発するときは、iDeviceにデータを保存する方法を理解することが重要です。

Appleは、デバイスに保存されているデータを扱うための柔軟なフレームワーク、Core Dataを提供しています。 もちろん、Core Dataは万能薬ではなく、特定のタスクにより適したデータを保存するためのオプションは他にもありますが、Core DataはCocoa Touchに非常によくフィットします。 Core Dataは、データウェアハウスでの作業に関する詳細のほとんどを隠し、アプリケーションを本当に楽しくユニークで使いやすいものにすることに集中できます。

Core DataはSQLiteのようなリレーショナルデータベースにデータを保存できるという事実にもかかわらず、Core DataはDBMSではありません。 実際、Core Dataはリレーショナルデータベースをストレージとしてまったく使用しない場合があります。 Core DataはHibernateのようなものではありませんが、いくつかのORM機能を提供します。 コアデータは、通常のオブジェクト指向プログラミングでオブジェクトグラフを操作するのに似た形式で、エンティティとその関係(他のオブジェクトとの関係)、属性を操作できるデータラッパー/フレームワークである可能性があります。

知ってる?
コアデータは、Mac OS X 10.4 TigerおよびiPhone SDK 3.0以降にのみ導入されました


IOSストレージ履歴

ピクサーがリリースしたアニメーション映画についてNeXTに感謝すべきであるように、Core Dataにも感謝すべきです。 コアデータは、Enterprise Objects Framework(EOF)と呼ばれるテクノロジーから生まれ、進化しました。
フレームワークのデビューは2005年にMac OS X 10.4(Tiger)の発売とともに行われますが、iPhoneはバージョン3.0以降でのみ表示されます。
Core DataがiPhoneに届く前は、開発者は苦労し、次のオプションを使用してデータを保存できました。
1)さまざまなデータ型のキーと値のペアを含むプロパティのリスト。
2)データのシリアル化とファイルへの保存(NSCodingプロトコルが使用された)
3)SQLiteリレーショナルデータベース
4)クラウド内のデータストレージ

これらの方法は現在も使用されていますが、Core Dataを使用して利便性の観点から比較できる4つの方法の1つはありません。 FMDatabaseやActiveRecordなどのフレームワークの誕生にもかかわらず、Core Dataの登場前のデータストレージの問題を解決するため、開発者は喜んでCore Dataに切り替えました。
Core Dataはすべての病気の治療法ではないことを繰り返しますが、もちろん、たとえばプロパティのリストを使用してソリューションを参照することもありますが、ほとんどの場合、アプリケーションでCore Dataをあなたの問題を解決する最良の方法。
Core Dataをより頻繁にプログラミングして使用するほど、「Core Dataを使用する必要がありますか?」という質問は頻繁になくなりますが、「Core Dataを使用しない理由はありますか?」

Core Dataを使用したシンプルなアプリケーションの作成

このセクションでは、Xcodeテンプレートの1つからコアデータに基づいて簡単なアプリケーションを作成し、その主要部分を分析します。 このパートの最後では、アプリケーションがどのようにCore Dataとやり取りしてデータを保存および取得するかを理解します。

コアデータコアコンポーネントについて

コードに飛び込んでテストアプリケーションを解析する前に、Core Dataのコンポーネントについて理解する必要があります。 次の図は、テストアプリケーションで使用する主な要素を示しています。

コアデータユーザーとして、データウェアハウスを直接操作しないでください。 ストレージから離れて、ストレージの種類から、データのみを考えてください! このアプローチの特徴は、大量のコードを変更せずにストレージのタイプを簡単に変更できることです(XMLファイルがありましたが、SQLiteになりました)。
フレームワークによって管理されるオブジェクト(コアデータ)は、NSManagedObjectクラスのメソッド/プロパティを継承する必要があります。
人々と同じように、オブジェクトにはオブジェクトが存在できる環境が必要です。そのような環境は管理オブジェクトコンテキスト(管理オブジェクトのコンテキスト)または単にコンテキストと呼ばれます。 オブジェクトが置かれている環境は、作業中のオブジェクトの状態だけでなく、関連するオブジェクト(これに依存し、依存しているオブジェクト)の状態も監視します。
NSManagedObjectContextクラスのインスタンスは、オブジェクトに対して同じ環境を提供します。このタイプのオブジェクトは、アプリケーションで常に利用可能である必要があります。 通常、NSManagedObjectContextクラスのインスタンスは、アプリケーションのデリゲートプロパティです。 環境がなく、NSManagedObjectContextクラスのインスタンスがないと、コアデータを操作できません。

新しいプロジェクトを作成する

Xcodeを起動し、マスター/ディテールアプリケーションテンプレートから新しいプロジェクトを作成します。
画像

次のようにフィールドに入力します。
画像

作成が完了すると、次のようなものが表示されます。
画像

プロジェクトを立ち上げます

このアプリケーションの内部にあるものを理解する前に、アプリケーションが一般的に何をするのかを始めましょう。
「実行」ボタンをクリックすると、これが目の前に表示されます。
画像

「+」の付いたボタンを数回押すと、時間の経過とともにリストにいくつかのエントリが表示されます。
画像

ここで、アプリケーションを終了(停止)し、アプリケーションがデータの保存にコアデータを使用しない場合、次の開始時に空のリストが再び表示されますが、再起動後、同じ画像が表示されます。
画像

アプリケーションのコンポーネントを分析します

アプリケーションの構造は比較的単純です。 データベース(ストレージ)に格納されているエンティティを記述するデータモデルが存在する場合。 画面(テーブル)とデータウェアハウス間の相互作用を促進するコントローラー。 アプリケーションの初期化と実行を支援するアプリケーションデリゲート。
以下の画像は、アプリケーションで使用されるクラスとそれらの相互関係を示しています。
画像

MasterViewControllerクラスには、NSManagedObjectContextクラスのインスタンスを参照してコアデータとやり取りするプロパティが含まれていることに注意してください。 コードを確認すると、MasterViewControllerがアプリケーションのデリゲートプロパティから管理対象オブジェクトコンテキストを取得していることがわかります。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if(self){ self.title = NSLocalizedString(@"Master", @"Master"); id delegate = [[UIApplication sharedApplication] delegate]; self.managedObjectContext = [delegate managedObjectContext]; } return self; } 


BasicApplication.xcdatamodelは、データモデルの構造に関する情報を含むファイルシステム内のディレクトリです。 データモデルは、コアデータを使用するすべてのアプリケーションの基盤です。
このアプリケーションのデータモデルは、1つのエンティティ-イベントのみを記述します。 イベントエンティティには、1つのプロパティ(フィールド、属性)のみが含まれます-タイプDateのtimeStamp。


NSManagedObjectタイプのイベントエンティティ。コアデータの制御下にあるすべてのエンティティのメインエンティティと見なされます。 2番目の章では、NSManagedObject型をさらに詳しく見ていきます。

データの取得/取得

次に興味のあるクラスはMasterViewControllerです。 そのヘッダーファイルには、注意する2つのプロパティが記述されています。
 @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 

NSFetchedResultsControllerは、ストレージ要求を管理するためにCore Dataフレームワークによって提供されるコントローラーです。
NSManagedObjectContextは、NSManagedObject型のオブジェクトが存在する環境としてすでに知られています。

MasterViewController.mファイルにあるMasterViewControllerクラスの実装は、データを取得および保存するためにCore Dataと対話する方法を示しています。 MasterVIewControllerクラスの実装には、ストレージからデータを選択する要求を事前設定する明示的なゲッターfetchedResultsControllerがあります。

データサンプリングのクエリを作成する最初の手順は、クエリを作成することです。
 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; 

クエリ結果は、NSSortDescriptorを使用してソートできます。 NSSortDescriptorは、ソートフィールドとソートタイプ(昇順または降順)を定義します。
この例では、レコードの作成時間を降順に並べ替えます。
 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; 

リクエストが定義されたら、NSFetchedResultsControllerの作成に進むことができます。
NSFetchedResultsController MasterVIewControllerをデリゲートとして使用して、ストレージデータの状態(削除、追加、移動など)を監視し、このソリューションをUITableViewとシームレスに統合できます。 もちろん、管理オブジェクトコンテキストでexecuteFetchRequestメソッドを呼び出すことで同じ結果を取得できますが、この場合、NSFetchedResultsControllerを受信せず、十分に活用できません。
NSFetchedResultsControllerクラスのインスタンス変数を作成して構成します。
 NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; 


知ってる?
おそらく、以前に使用したinitWithFetchRequestメソッドにcacheNameパラメーターがあることに気づいたでしょう。 引数としてnilを渡すと、リクエストの結果をキャッシュする可能性を除外しますが、キャッシュの名前を指定すると、Core Dataが以前に実行された同じリクエストの存在をチェックし、キャッシュから結果を返すことができます。 それ以外の場合、このキャッシュ名のリクエストがない場合、ストレージに対してリクエストが行われ、必要なデータが返され、後でキャッシュされます。


結論として、私たちに残されているのは、データを取得する要求を満たすことだけです。
 NSError *error = nil; if(![self.fetchedResultsController performFetch:&error]){ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } 

以下に、完全なfetchedResultsControllerゲッターがあります。
 - (NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController != nil) return _fetchedResultsController; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; [fetchRequest setFetchBatchSize:20]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; NSError *error = nil; if(![self.fetchedResultsController performFetch:&error]){ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __fetchedResultsController; } 

NSFetchedResultsControllerはNSManagedObject型のオブジェクトのコレクションのようなものです。このため、クエリ結果にアクセスするためにNSArray型のfetchedObjectsプロパティさえ持っています。
UITableViewControllerの機能も拡張するMasterVIewControllerクラスは、NSFetchedResultsControllerを使用してテーブルのコンテンツを管理することがいかに便利かを示しています。

新しいオブジェクトを挿入する

insertNewObject:メソッドを一見すると、新しいイベントがどのように作成され、リポジトリに追加されるかが明確になります。 NSManagedObjectsは、データモデルのエンティティ記述によって定義され、特定のコンテキスト(環境)にのみ存在できます。 新しいオブジェクトを作成する最初のステップは、このオブジェクトが作成されるコンテキストを取得することです。
 NSManagedObjectContext *managedObjectContext = [self.fetchedResultsController managedObjectContext]; NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; 

NSManagedObjectを作成します。
 NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntity:[entity name] inManagedObjectContext:context]; [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; 

実行する必要がある最後の手順は、新しいオブジェクトが作成されたコンテキストを保存することです。 コンテキストを保存すると、以前に保存されなかったすべての変更が保存されることに注意してください。
 NSError *error = nil; if(![context save:&error]){ NSLog(@"Unresolved error: %@, %@", error, [error userInfo]); abort(); } 

新しいオブジェクトを追加する完全な方法を以下に示します。
 - (void)insertNewObject { NSManagedObjectContext *managedObjectContext = [self.fetchedResultsController managedObjectContext]; NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; NSError *error = nil; if(![context save:&error]){ NSLog(@"Unresolved error: %@, %@", error, [error userInfo]); abort(); } } 


コンテキストの初期化(環境)

明らかに、コンテキストオブジェクトを作成せずに、オブジェクトが存在し生活する環境がなければ、以前に行ったことすべてを達成することはできません。 アプリケーションデリゲートは、まさにこの環境を作成する責任があります。 コアデータを使用するアプリケーションで必要な3つのプロパティ:
 @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 

3つのプロパティはすべて読み取り専用であることに注意してください。これは、外部から設定できないようにするためです。 BasicApplicationAppDelegate.mを調べると、3つのプロパティすべてに明示的なゲッターがあることがわかります。

管理オブジェクトモデル:
 - (NSManagedObjectModel *)managedObjectModel { if(_managedObjectModel != nil){ return _managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"BasicApplication" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modeURL]; return _managedObjectModel; } 

その後、作成されたデータモデルをサポートするストレージが作成されます。 実際、コアデータを使用する他のほとんどの場合と同様に、データウェアハウスはSQLiteに基づいています。
 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if(_persistentStoreCoordinator != nil){ return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"BasicApplication.sqlite"]; NSError* error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]){ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; } 


コンテキスト(環境)を作成します。
 - (NSManagedObjectContext *)managedObjectContext { if(_managedObjectContext != nil){ return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if(coordinator != nil){ _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } 


コンテキストは、コアデータおよび永続ストレージと対話するためのインターフェイスとしてアプリケーション全体で使用されます。
コアデータの初期化シーケンス:


メカニズムは、application:didFinishLaunchingWithOptionsメソッドが呼び出されたときに開始されます。
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; MasterViewController *controller = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil]; self.navigationController = [[UINavigationController alloc] initWithRootViewController:controller]; self.window.rootViewController = self.navigationController; [self.window makeKeyAndVisible]; return YES; } 


実行のためにアプリケーションデリゲートのmanagedObjectContextプロパティのgetterを呼び出すと、一連のアクションが起動します。
-(NSManagedObjectContext *)managedObjectContextの呼び出し
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator、これは順番に呼び出しを行います
-(NSManagedObjectModel *)managedObjectModel。
したがって、managedObjectContextのgetterメソッドを呼び出すと、Core Dataオブジェクトのスタック全体が初期化され、Core Dataにアラートが送信されます。

既存のプロジェクトにコアデータを追加する

次の3つのステップで実行されます。
  1. コアデータフレームワークの追加
  2. データモデルの作成
  3. コンテキストの初期化(環境)


コアデータフレームワークの追加

Objective-Cの世界では、ライブラリはフレームワークと呼ばれます。
「クリーン」プロジェクトで既に接続されている標準フレームワークで、最も頻繁に表示されるもの:


新しいフレームワークはどこに追加されますか:


接続するフレームワークを選択します。


データモデルの作成

データモデルがなければ、完全なCore Dataアプリケーションとは見なされません。 データモデルは、コアデータによって管理されるすべてのエンティティを記述します。
新しいデータモデルを作成するには:[ファイル]-> [新規]-> [新しいファイル]


モデルをMyModel.xcdatamodeldと呼びます:


モデルの作成後、エンティティを編集(作成)するためのウィンドウが開きます。


Xcodeの左下にある[+]ボタンをクリックして新しいエンティティを作成し、[属性]セクションに既にある[+]ボタンをクリックして新しいエンティティ属性を追加し、そのタイプを選択します。


コンテキストの初期化(環境)

最後の手順は、コンテキスト、ストレージ、およびオブジェクトモデルを初期化することです。 ほとんどの場合、Core Dataを使用する「空の」プロジェクトでXcodeによって自動的に生成されるコードを使用できます。

DemoAppAppDelegate.h
 #import <UIKit/UIKit.h> #import <CoreData/CoreData.h> @interface DemoAppDelegate : UIResponder <UIApplicationDelegate> { } @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UINavigationController *navigationController; @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; - (void)saveContext; - (NSURL *)applicationsDocumentsDirectory; @end 


* .mファイルDemoAppAppDelegateに切り替えて、次の行を記述します。
 @synthesize managedObjectContext = _managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 


以下は、データモデル、ストレージ、およびコンテキストを初期化するコードです。
 - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil){ return _managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyModel" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modeURL]; return _managedObjectModel; } 


 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if(_persistentStoreCoordinator != nil){ return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"DemoApp.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error&error]){ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; } 


 - (NSManagedObjectContext *)managedObjectContext { if(_managedObjectContext != nil){ return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if(coordinator != nil){ _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; } 


これまでに実装したことのないメソッド:
 - (NSURL *)applicationDocumentsDirectory{ return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; } 

 - (void)saveContext { NSError *error = nil; NSManagedObjectContext *managedObjectContext = [self managedObjectContext]; if(managedObjectContext != nil) { if([managedObjectContext hasChanges] && ![managedObjectContext save:&error]){ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } } } 

コアデータを接続したので、アプリケーションはそれを使用してデータを保存できます。
すべてが正常に機能し、データが実際に保存されることを確認できる簡単な例を実装しましょう。
テスト例では、アプリケーションが起動された回数を判断します。
アプリケーションに小さな変更を加えます。アプリケーションが以前に起動された回数を受け取り、新しい起動イベントを追加するという形で、アプリケーションデリゲートのdidFinishLaunchingWithOptions:メソッドを行います。

以前のアプリケーションの起動を取得するためのコード:
 NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyData" inManagedObjectContext:context]; [request setEntity:entity]; NSArray *results = [context executeFetchRequest:request error:nil]; 


次に、次のように配列全体を調べます。
 for(NSManagedObject *object in results){ NSLog(@"Found %@", [object valueForKey:@"myAttribute"]; } 

新しいエントリを追加して保存します。
 NSString *launchTitle = [NSString stringWithFormat:@"launch %d", [results count]]; NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; [object setValue:launchTitle forKey:@"myAttribute"]; [self saveContext]; NSLog(@"Added : %@", launchTitle); 

最初の起動後、アプリケーションはコンソールに次の行を表示します。
 201102-25 05:13:23.783 DemoApp[2299:207] Added: launch 0 

2回目の実行後:
 201102-25 05:15:48.883 DemoApp[2372:207] Found launch 0 201102-25 05:15:48.889 DemoApp[2372:207] Added: launch 1 


完全な方法は次のとおりです。
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entytyForName:@"MyData" inManagedObjectContext:context]; [request setEntity:entity]; NSArray *results = [context executeFetchRequest:request error:nil]; for(NSManagedObject *object in results){ NSLog(@"Found %@", [object valueForKey:@"myAttribute"]); } NSString *launchTitle = [NSString stringWithFormat:@"launch %d", [results count]]; NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; [object setValue:launchTitle forKey:@"myAttribute"]; [self saveContext]; NSLog(@"Added : %@", launchTitle); [self.window makeKeyAndVisible]; return YES; } 


結論として

コメントの誤りについては書かないようにお願いします。すぐにプライベートメッセージを書くことをお勧めします。

転送を続行する必要がありますか? このトピックに興味はありますか?

ご清聴ありがとうございました!

Source: https://habr.com/ru/post/J191334/


All Articles