DirTy™의 하루일과/DirTy™의 가당찮은iOS

[IOS] 데이터 저장방법.

DirTy™ 2015. 10. 6. 14:43

아무것도 모르고 시작했을때... NSArray 의 writeToFile을 사용하여 plist파일을 강제로

만들어서 사용했었다... NSUserDefaults를 사용하면 자동으로 plist만들어 진다는 것을 알지도 못한체...

iOS 에서 사용되는 다양한 데이터 저장방법에 대해 알아보자.


1. NSArray의 writeToFile사용.


iOS를 아무 정보도 없이 하게 된 이후로... NSArray에 아래와 같은 메서드가 있었다.

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;


당연히 아무것도 모르고 데이터 저장에 자주 쓰는 방법으로 지금까지도 쓰고있다.

뭐 방법은 간단하다. 간단히 아래에 예를 들어보겠다.


NSMutableArray *arr = [[NSMutableArray alloc] init];

[arr addObject:@"data"];


[arr writeToFile:[self dataFilePath:@"InfoFilename.plist"] atomically:YES];

 

 


2. NSUserDefaults


저장하는 방법.

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject:@"저장값" forKey:@"저장키"]; //저장키 이름으로 스트링 형태의 저장값을 저장


타입을 바꾸어 저장할때는 위의 setObject대신 아래를 사용하면된다.

setInteger : Integer값

setDouble : Double

setFloat : Float


[defaults synchronize]; 저장한다.


읽어오는 방법

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSString *str = [defaults stringForKey@"저장키"]; // 저장키에 들어있는 스트링 형태의 값을 읽어온다.


타입을 바꾸어 저장할때는 위의 setObject대신 아래를 사용하면된다.

setInteger : Integer값

setDouble : Double

setFloat : Float


3.sqlite 사용.

http://ddirty.tistory.com/26 참조.


4. coredata 사용.


SQLite를 이용하여, 데이터를 저장하고 읽어올수 있는데 그러기 위해서는 SQL과 관련지식이 필요한데

CoreData를 이용하면 SQL에 대한 지식없이도 간단하게 데이터를 저장할수 있다.


일단, Single View Application 프로젝트를 생성할때 아래와 같이 Use Core Data를 선택하였다면 필요없고


혹여 선택하지 않았다면 아래와 같은 방식으로 추가 해보자.

1. coredata framework를 추가

2. 프로젝트이름-Prefix.pch파일에 #import <CoreData/CoreData.h> 를 추가

pch파일이 없다면 File->New->File 에서 아래 그림과 같이 pch파일을 추가한다.



후에 아래그림과 같이 추가한 pch파일의 경로를 추가해준다.





3. AppDelegate.h에 @Property 및 함수를 추가

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;


- (void)saveContext;

- (NSURL *)applicationDocumentsDirectory;

4. AppDelegate.m 에 관련 메서드 추가

@implementation AppDelegate


@synthesize managedObjectContext = _managedObjectContext;

@synthesize managedObjectModel = _managedObjectModel;

@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;


- (void)saveContext

{

    NSError *error = nil;

    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;

    if (managedObjectContext != nil) {

        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {

            // Replace this implementation with code to handle the error appropriately.

            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

            abort();

        }

    }

}


#pragma mark - Core Data stack

 

// Returns the managed object context for the application.

// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.

- (NSManagedObjectContext *)managedObjectContext

{

    if (_managedObjectContext != nil) {

        return _managedObjectContext;

    }

     

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {

        _managedObjectContext = [[NSManagedObjectContext alloc] init];

        [_managedObjectContext setPersistentStoreCoordinator:coordinator];

    }

    return _managedObjectContext;

}

 

// Returns the managed object model for the application.

// If the model doesn't already exist, it is created from the application's model.

- (NSManagedObjectModel *)managedObjectModel

{

    if (_managedObjectModel != nil) {

        return _managedObjectModel;

    }

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreData" withExtension:@"momd"];

    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return _managedObjectModel;

}

 

// Returns the persistent store coordinator for the application.

// If the coordinator doesn't already exist, it is created and the application's store added to it.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

{

    if (_persistentStoreCoordinator != nil) {

        return _persistentStoreCoordinator;

    }

     

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"DBUCoreData.sqlite"];

     

    NSError *error = nil;

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

        /*

         Replace this implementation with code to handle the error appropriately.

          

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

          

         Typical reasons for an error here include:

         * The persistent store is not accessible;

         * The schema for the persistent store is incompatible with current managed object model.

         Check the error message to determine what the actual problem was.

          

          

         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

          

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:

         * Simply deleting the existing store:

         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

          

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:

         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

          

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

          

         */

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

        abort();

    }

     

    return _persistentStoreCoordinator;

}

 

#pragma mark - Application's Documents directory

 

// Returns the URL to the application's Documents directory.

- (NSURL *)applicationDocumentsDirectory

{

    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

}


이렇게 준비가 끝났다면

File > Core Data > Data Model을 선택해서 추가한다. 추가하면 Model.xcdatamodelld가 추가되었을 것이다.

이파일에 저장하고자 하는 형태의 데이터가 저장된다.


추가된 Model.xcdatamodelld를 클릭해보자. 아무것도 없는 상태가 표출 될것이다.

아래 그림과 같이 Add Entity를 눌러서 Entity를 추가하고 Attribute 를 추가해보자.


Attibute를 추가한 모습이다.



이것으로 CoreData를 사용하기 위한 셋팅은 준비가 끝났다.

이제 추가한 dataModel을 저장소와 연결하여 보자.

위에서 추가한 Model.xcdatamodelld 파일의 Model이라는 이름으로 아래와 같이 리소스 이름을 설정한다.


후에 데이터를 기본적으로 저장하는 방법이다.


 위처럼 setValue를 사용해 직접적으로 저장하는 방법도 있는 한편 클래스를 만들어서 저장하는 방법도 있다.

아래와 같이 NSManagedObject 파일을 추가해보자.



추가하면 아래와같이 TestEntity+CoreDataProperties.m, h 와 TestEntity.m,h 4개의 파일이 추가로 생성된다.




추가된 파일을 아래와 같이 #import한후 클래스를 통해 저장도 가능하다.

#import "TestEntity+CoreDataProperties.h"


TestEntity *usageDate = [NSEntityDescription insertNewObjectForEntityForName:@"TestEntity" inManagedObjectContext:context];

    usageDate.testString = @"This is test String. using TestEntity class";


데이터를 읽어올때는 아래와 같이 해보자.

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"TestEntity"

                                              inManagedObjectContext:context];

[fetchRequest setEntity:entity];

NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

for (TestEntity *info in fetchedObjects) {

    NSLog(@"Name: %@", info.testString);

}


이로써 내가 알고있는 4가지 데이터 저장방법을 정리해 보았다.

더욱 다양한 저장방법이 있을지도 모른다. 내가 아는 4가지만 정리해 본것이다.

 

coredata는 내가 써본적이 없어 직접 구글링 해가면서 해보았는데 준비과정이 여간 불편한게 아니다.익숙해 지면 coredata도 아주 편할것 같으나... 굳이 여지껏 써오던 sqlite나 array의 writetofile을 버리지는 못할것 같은 느낌이다.