コアデータベースの事前入力

画像 多くの場合、iPhone / iPadアプリケーションが機能するには、データベースに「デフォルト」のデータセットが必要です。 残念ながら、Appleはアプリケーションデータベースに開発者を事前入力するための標準ツールを提供していません。
必要なデータ量が少ない場合は、アプリケーションの起動時にそれらをデータベースにロードできます。 アプリケーションが機能するために大量の初期情報が必要な場合、そのようなソリューションは機能せず、すべてのロード操作が終了するまでユーザーを待たせなければならず、顧客はアプリケーションのロード時間を見て、将来の協力の計画を修正できます。

この記事では、Core Dataを使用してアプリケーションのsqliteデータベースにすばやくデータを入力する方法を説明します。



アイデアの本質:
-sqliteデータベースに入力する
-アプリケーションリソースに追加する
(シミュレーターで実行されているアプリケーションのベースは次の場所にあります:/ユーザー/%ユーザー名%/ライブラリ/アプリケーションサポート/ iPhoneシミュレーター/%iOSバージョン%/アプリケーション/%GUID of application%/ Documents /)
-アプリケーションの最初の起動時に、データベースを作成せずに、デフォルトのデータベースに置き換えます。

この記事では、データベースは(xmlファイルから)アプリケーションに直接取り込まれます。 もちろん、データベースにデータを入力するには他の多くの方法がありますが、そのためにはコアデータによって作成されたデータベーススキームを理解する必要があります。

このような記事でプロセス全体の面白くない説明をスクロールする必要があるときは気に入らないのですが、例のソースコードをすぐに見たいだけです。 したがって、私はすぐに言います: サンプルアプリケーションのソースコードはこちら (SDK 4.1)

アイデアの仕組みを確認するには、コアデータを使用するナビゲーションベースのアプリケーションテンプレートに基づいて小さなアプリケーションを作成します。 私の例では、CoreDataExampleと呼ばれます。


ベースを事前に入力し、最初の開始時に使用します。
ソースデータをEvents.xmlファイルに保存します。 このファイルをアプリケーションリソースに追加します。
<イベント>
<Event timeStamp = "01/16/2010" />
<Event timeStamp = "02/01/2010" />
<Event timeStamp = " 03/05/2010 " />
</イベント>

イベントクラスを生成します。 これを行うには、ファイルCoreDataExample.xdatamodelを右クリックして、[追加]-> [新規ファイル...]を選択します。


管理対象オブジェクトクラスを作成するオプションがあります

作成後、Event.mおよびEvent.hファイルが生成されます。
//Event.h
#import <CoreData / CoreData.h>

@interfaceイベント: NSManagedObject
{
}

@property ( nonatomic、retain ) NSDate * timeStamp;

@end

//Event.m
#import "Event.h"

@implementationイベント

動的タイムスタンプ。

@end


次に、データをデータベースに保存するクラスを作成します。 EventsRepositoryと呼び、同時にEventsRepositoryDe​​legateプロトコルを作成します。 テンプレートによって生成されたクラスのデータの操作方法は変更しません。このトピックはいくつかの独立した記事に発展させることができますが、事前入力にはEventsRepositoryを使用します。
//EventsRepositoryDe​​legate.h

#import <UIKit / UIKit.h>

@protocol EventsRepositoryDe​​legate

@property (非アトミック、保持) NSFetchedResultsController * fetchedResultsController;

@end

//EventsRepository.m

#import <Foundation / Foundation.h>
#import "EventsRepositoryDe​​legate.h"
#import "Event.h"


@interface EventsRepository : NSObject {

id <EventsRepositoryDe​​legate>デリゲート;

}

@property ( assign ) id <EventsRepositoryDe​​legate>デリゲート;
- ( void ) saveEventWithTimeStamp : ( NSDate * ) timeStamp;

@end

//EventsRepository.m

#import "EventsRepository.h"


@implementation EventsRepository

@synthesizeデリゲート;

- ( void ) saveEventWithTimeStamp : ( NSDate * ) timeStamp {

NSManagedObjectContext * context = [デリゲート.fetchedResultsController managedObjectContext ] ;

イベント*イベント= [ NSEntityDescription insertNewObjectForEntityForName : @ "Event" inManagedObjectContext : context ] ;

event.timeStamp = timeStamp;

NSError * error = nil ;
if ( ! [ context save :& error ] ) {

NSLog ( @ "Unresolved error%@、%@" 、error、 [ error userInfo ] ) ;
abort ( ) ;
}

[イベントリリース] ;
}

@end



また、xmlファイルを解析し、リポジトリを介してデータを保存するクラスが必要です。 EventsXmlParserクラスとEventsXmlParserDelegateプロトコルを作成します。
//EventsXmlParser.h

#import <Foundation / Foundation.h>
#import "EventsXmlParserDelegate.h"
#import "Event.h"


@interface EventsXmlParser : NSObject <NSXMLParserDelegate> {

id <EventsXmlParserDelegate>デリゲート;
}

@property ( assign ) id <EventsXmlParserDelegate>デリゲート;

- ( void ) saveEventWithTimeStamp : ( NSDate * ) timeStamp;

@end

//EventsXmlParser.m

#import "EventsXmlParser.h"


@implementation EventsXmlParser

@synthesizeデリゲート;

- ( void )パーサー: ( NSXMLParser * )パーサー
didStartElement : ( NSString * ) elementName
namespaceURI : ( NSString * ) namespaceURI
QualifiedName : ( NSString * ) QualifiedName
属性: ( NSDictionary * ) attributeDict {

if ( [ elementName isEqualToString : @ "Event" ] ) {

NSDateFormatter * dateFormatter = [ [ NSDateFormatter alloc ] init ] ;
[ dateFormatter setDateFormat : @ "dd.MM.yyyy" ] ;

NSDate * timeStamp = [[ [ [ NSDate alloc ] init ] autorelease ] ;

timeStamp = [ dateFormatter dateFromString : ( NSString * ) [ attributeDict objectForKey : @ "timeStamp" ] ] ;

[ delegate.eventsRepository saveEventWithTimeStamp : timeStamp ] ;

[ dateFormatterリリース] ;
}
}

- ( void ) dealloc {

[スーパーdealloc ] ;
}

@end

//EventsXmlParserDelegate.h

#import <UIKit / UIKit.h>
#import "EventsRepository.h"


@protocol EventsXmlParserDelegate

@property ( nonatomic、retain ) EventsRepository * eventsRepository;

@end


RootViewControllerに新しいクラスの使用を追加するだけです。
第一に、RootViewControllerは新しいプロトコルの両方を実装し、第二にProperty EventsRepositoryを追加します。
//ヘッダーファイル全体RootViewController.h

#import <UIKit / UIKit.h>
#import <CoreData / CoreData.h>
#import "EventsXmlParserDelegate.h"
#import "EventsRepositoryDe​​legate.h"
#import "EventsXmlParser.h"
#import "EventsRepository.h"

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate、EventsXmlParserDelegate、EventsRepositoryDe​​legate> {

@private
NSFetchedResultsController * fetchedResultsController_;
NSManagedObjectContext * managedObjectContext_;
EventsRepository * eventsRepository_;
}

@property (非アトミック、保持) NSManagedObjectContext * managedObjectContext;
@property (非アトミック、保持) NSFetchedResultsController * fetchedResultsController;
@property ( nonatomic、retain ) EventsRepository * eventsRepository;

@end

//そして、プロパティeventsRepositoryのRootViewContorller.mに追加する必要があるもの
...
@synthesize eventsRepository = eventsRepository_;
...
- ( EventsRepository * ) eventsRepository {

if ( eventsRepository_ != nil ) {
return eventsRepository_;
}

eventsRepository_ = [ [ EventsRepository alloc ] init ] ;
eventsRepository_.delegate = self;

return eventsRepository_;
}
...

- ( void ) dealloc {
[ eventsRepository_リリース] ;
[ fetchedResultsController_ release ] ;
[ managedObjectContext_ release ] ;
[スーパーdealloc ] ;
}


ベースを事前充填します。 これを行うには、populateDataBaseメソッドをRootViewControllerに追加し、viewDidLoadで呼び出します。
- ( void ) populateDataBase {

NSLog ( @ "populate" ) ;

NSURL * url = [ NSURL fileURLWithPath : [ [ NSBundle mainBundle ] pathForResource : @ "Events" ofType : @ "xml" ] ] ;
NSXMLParser * xmlParser = [ [ NSXMLParser alloc ] initWithContentsOfURL : url ] ;

EventsXmlParser * eventsXmlParser = [ EventsXmlParser new ] ;
[ eventsXmlParser setDelegate : self ] ;

[ xmlParser setDelegate : eventsXmlParser ] ;

BOOL成功= [ xmlParser解析] ;

if (成功)
NSLog ( @ "データベースが読み込まれました" ) ;
他に
NSLog ( @ "エラー:データベースにデータが入力されていません" ) ;

[ eventsXmlParserリリース] ;
[ xmlParserリリース] ;
}


アプリケーションを実行します-データベースがいっぱいになります。 作成したデータベースをアプリケーションディレクトリにコピーし、データベースファイルをプロジェクト(たとえば、リソースグループ)に追加します(場所はユーザー/%ユーザー名%/ライブラリ/アプリケーションサポート/ iPhoneシミュレータ/%iOSバージョン%/アプリケーション/%GUID of application%/ /)をドキュメント化し、関数呼び出しpopulateDataBaseを削除します-xmlファイルのベースを事前に設定する必要がなくなりました。 シミュレーターからアプリケーションを削除します。このため、/ Users /%UserName%/ Library / Application Support / iPhone Simulator /%iOS version%/ Applications /のアプリケーションフォルダーを強打するか、シミュレーターで削除します(デバイスで削除されます)-左ボタンを押したままにしますアプリケーションのアイコンをクリックして離し、アイコンが変動し始めたら、表示された十字をクリックします-削除します。

最初の起動時にデータベースを作成するのではなく、代わりに作成したデータベースをコピーするようにアプリケーションに指示する必要があります。
これを行うには、CoreDataExampleAppDelegateクラスに移動し、getter persistentStoreCoordinator getterの文字列を置き換えます
NSURL * storeURL = [ NSURL fileURLWithPath : [ [ self applicationDocumentsDirectory ] stringByAppendingPathComponent : @ "CoreDataExample.sqlite" ] ] ;

に
NSString * storePath = [ [ self applicationDocumentsDirectory ] stringByAppendingPathComponent : @ "CoreDataExample.sqlite" ] ;

NSFileManager * fileManager = [ NSFileManager defaultManager ] ;

if ( ! [ fileManager fileExistsAtPath : storePath ] ) {

NSString * defaultStorePath = [ [ NSBundle mainBundle ] pathForResource : @ "CoreDataExample" ofType : @ "sqlite" ] ;
if ( defaultStorePath ) {
[ fileManager copyItemAtPath : defaultStorePath toPath : storePath error : NULL ] ;
}
}

NSURL * storeURL = [ NSURL fileURLWithPath : storePath ] ;


この方法がお役に立てば幸いです。 私はあなたのコメントでそのような問題に対するあなたの解決策を見ることができてうれしいです。

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


All Articles