앱개발자가 혼자서 개발 할 경우에 고민되는 문제중 하나가 서버개발이다. 그런문제를 한방에 해결해 줄수 있는 서비스가 있는데 그게 바로  Parse라는 서비스이다.

https://parse.com/



물론 앱개발쪽에 관심이 있는 개발자라면 다 아는곳이겠지만, 노티피케이션 서버라던가 API서버, 클라우드등등.. 여러가지 기능을 쉽게 구현해준다.







제공해 주는 많은 기능중에 이번에 포스팅할 내용은 Core(데이타베이스)이다. Parse에 도큐먼트와 튜토리얼을 보면 너무나도 자세히 설명되어 있지만 간단히 소개를 하자면,



모델클래스(PFObject)의 인스턴스를 생성하는것 만으로도 테이블이 생성되며 그인스턴스를 save..라는 메소드를 이용하여 저장할 수 있다. (모델과 테이블에 영속화 되어 있는개념이다.)


게다가 사전(NSDictionary)처럼 사용하면 된다.

PFObject *campSite = [PFObject objectWithClassName:@"campSites"];

campSite[@"name"] = @"テストコード";

campSite[@"access"] = @"hogehoge";

campSite[@"address"] = @"fugafuga";

    

[campSite saveInBackground];



그리고 저장된 데이타를 검색하는 여러가지 메소드를 지원해 주는데 이것또한 직관적으로 알기 쉽게 되어 있다.


PFQuery *query1 = [PFQuery queryWithClassName:@"CampSites"];

[query1 whereKey:@"access" equalTo:@"Dan Stemkoski"];

    

    [query1 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

        if (!error) {

            // The find succeeded.

            NSLog(@"Successfully retrieved %d scores.", (int)objects.count);

            // Do something with the found objects

            for (PFObject *object in objects) {

                NSLog(@"name[%@]", object[@"name"]);

            }

        } else {

            // Log details of the failure

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

        }

    }];


위의 샘플소스는 도큐먼트에 나와있는 방법으로 코딩한 것이다.

그러나 한가지 불만스러운 점이 있었는데 문자열을 키로 사용한다는것이 뭔가 이펙티브하지 않다는 생각이 들었다. 뭔가 방법이 있을텐데.. PFObject를 상속받아 각각의 매핑된 모델클래스를 만들수 있을것 같다는 강력한 의구심이 생겼다.


어쨋든 Stackflow와 Parse블로그 등등 조금 둘러보니 역시나 이펙티브한 방법이 있었다.





먼저 테이블에 매핑될 모델클래스를 만들어준다.

클래스를 만들때에 PFSubclassing라는 프로토콜을 선언해 줘야 한다.


#import <Parse/Parse.h>


@interface CampSites : PFObject<PFSubclassing>


+ (NSString *)parseClassName;


@property (retain) NSString *name;


@end



#import "CampSites.h"

#import <Parse/PFObject+Subclass.h>


@implementation CampSites 


@dynamic name;


+ (NSString *)parseClassName {

    return @"CampSites";

}


@end



그다음 모델을 이용하여 테이블 생성 및 데이타 저장을 할 수 있다.

//effective!!

CampSites *obj = [CampSites object];

obj.name = @"effecitve!!!";


[obj saveInBackground];



검색한 결과도 모델로 넘어온다. 한번 해보자.


PFQuery *query1 = [PFQuery queryWithClassName:[CampSites parseClassName]];

    

[query1 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    if (!error) {

        // The find succeeded.

        NSLog(@"Successfully retrieved %d scores.", (int)objects.count);

        // Do something with the found objects

        for (CampSites *object in objects) {

            NSLog(@"name[%@]", object.name);

        }

    } else {

        // Log details of the failure

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

    }

 }];



한가지 주의해야 할 점은 이 모델클래스를 사용하기전에 반드시 등록을 해줘야 한다는 점이다.

한번만 등록을 해주면 되므로 AppDelegate.m 에 코딩해 주자.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch.

     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    

    //regist PFObject subClassing

    [CampSites registerSubclass];

    

    return YES;

}


근데 모델을 등록해주려면 AppDelegate.m에다가 모델을 써줘야 하고 임포트까지 해줘야 하는데 이러면 AppDelegate가 너무 지저분해지잖아! 참을수 없다.



각각의 모델클래스에서 사용되어지기전에 한번만 실행되도록 바꾸어 주자.

AppDelegate에 있는 등록소스를 각각의 모델클래스로 옮겨준다.

#import "CampSites.h"

#import <Parse/PFObject+Subclass.h>


@implementation CampSites 


@dynamic name;

// 모델클래스가 로드되면 클래스를 먼저 등록해준다. dispatch_once를 이용하여 한번만 등록되도록 한다.

+ (void)load {

    __weak typeof(self) weakSelf = self;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        [weakSelf registerSubclass];

    });

}


+ (NSString *)parseClassName {

    return @"CampSites";

}


@end





확인해본결과 잘 동작하는것을 알수 있다.






더자세한 내용을 공부하려면 아래의 도큐먼트를 참조하면된다.


https://parse.com/docs/kr/ios_guide#objects




Posted by 악당잰 트랙백 0 : 댓글 0

댓글을 달아 주세요