SDK 3.0(iOS) User guide

문서 이력관리

개요

라이브러리 셋팅

Requirements

라이브러리 적용

  1. PMS.framework를 App 프로젝트 폴더에 옮겨 넣는다

  2. TARGET > Build Phases > Link Binary With Libraries에 Add Other… 을 선택 후 PMS.framework를 추가





  3. TARGET > Build Phases > Link Binary With Libraries에 에서 PMS의 의존 프레임워크 4가지를 추가



  4. Project > Apple LLVM 6.0 - Language - Modules의 Enable Modules (C and Objective-C) 값을 YES로 변경

  5. ******-Info.plist파일에 AppKey와 ApiUrl설정

  6. PMS를 사용하려는 클래스에서 #import <PMS/PMS.h> 한 후 사용

step by step

step1 : APNS푸시를 사용하기

// APNS서버에 Push토큰 요청
  if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
      // Xcode5.x 이하에서 빌드 안됨
      [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
      [[UIApplication sharedApplication] registerForRemoteNotifications];
        
      if([UIApplication sharedApplication].currentUserNotificationSettings.types == UIUserNotificationTypeNone){
          // 시스템 알림 설정 == OFF
      }
  } else {
      [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
        
      if([UIApplication sharedApplication].enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone){
          // 시스템 알림 설정 == OFF
      }
  }
-(void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken
{
    // [PMS deviceCert]는 setPushToken에서 자동으로 수행
    [PMS setPushToken:devToken];
}
-(void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
    [PMS deviceCert];
}

step2 : 푸시허용여부 설정과 설정상태 확인

[PMS setConfigWithNotiFlag:YES MsgFlag:NO MktFlag:YES CompleteBlock:^(PMSResult *result) {
    // TODO Something
}];
// Local에 저장되어 있는 값으로 확인하는 경우
[PMS getNotiFlag]; // Push(정보성) 수신여부 확인
[PMS getMsgFlag]; // 메시지함 적재여부 확인
[PMS getMktFlag]; // 마케팅 수신 동의여부 확인 (NotiFlag의 영향 받지 않음)

// 서버상에 설정되어있는 값을 확인 (네트워크 요청이 발생하며 가급적 사용을 지양함)
[PMS getConfigFlagsWithCompleteBlockV2:^(PMSResult *result, BOOL notiFlag, BOOL msgFlag, BOOL mktFlag) {
    // TODO Something
}];
// 22:30~09:00 으로 설정하는 경우
[PMS setEtqStartHour:22
         EtqStartMin:30
          EtqEndHour:09
           EtqEndMin:00
       CompleteBlock:nil];

step3 : PMS에 사용자 Login

step4 : 메시지 그룹 조회

// 네트워크 통신을 통해 그룹을 받아오는 경우
[PMS loadGrpListWithCompleteBlock:^(PMSResult *result, NSArray *groupArray) {
    if([result isSuccess]){
        // 받아온 그룹을 저장하고 테이블에 데이터 표시
        mGroupData = [NSMutableArray arrayWithArray:groupArray];
        // groupArray는 PMSModelMessageGroup[]
        [mGroupTableView reloadData];
    }else{
        // TODO 그룹 로드 실패시
    }
}];

// 네트워크 통신없이 Local DB에서 그룹을 받아오는 경우
mGroupData = [NSMutableArray arrayWithArray:[PMS loadGrpListWithCompleteBlock:nil]];
[mGroupTableView reloadData];

step5 : 메시지 리스트 조회

@interface MessageBoxViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
    NSString *targetGrpCode; // 그룹핑하여 메시지를 가져올 경우
    int deleteCount; // 삭제 기능을 사용할 경우에만
    int page; // 현재 조회중인 페이지 저장
    int totalCount; // 모든 메시지 개수 저장
}
- (void) loadNextPageData
{
    if(mMsgData == nil){
        // PMS에서 받아온 메시지를 저장할 NSMutableArray를 alloc
        mMsgData = [NSMutableArray new];
    }
    if(page == 0){
        // 페이지가 0일 경우는 새로고침이나 기타 동작으로 첫페이지부터 다시 불러오는 경우
        [mMsgData removeAllObjects];
        [mMsgTableView setContentOffset:CGPointZero animated:NO];
    }

    // 네트워크 요청하면서 받아올때
    [PMS loadMsgListWithGrpCode:targetGrpCode
                           Page:++page
                        PerPage:perPage
                  CompleteBlock:^(PMSResult *result, NSArray *msgArray) {
                      if([result isSuccess]){
                          // 받아온 데이터를 add
                          // msgArray는 PMSModelMessage[]
                          [mMsgData addObjectsFromArray:msgArray];
                          dispatch_async(dispatch_get_main_queue(), ^{
                              [mMsgTableView reloadData];
                          });
                          // 그룹 newCount리셋 (새로받아온 메시지의 카운트를 0으로)
                          [PMS resetNewCountWithGrpCode:targetGrpCode];
                          // 메시지 개수 확인 (다음페이지 요청을 할 필요가 있는지 판단하기 위함)
                          totalCount = [PMS getMessageCountWithGrpCode:targetGrpCode];
                      }else{
                          // 실패시 -1 페이지
                          page--;
                      }
    }];
}
// 섹션당 로우개수는 서버에서 받아온 메시지 데이터 길이
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (mMsgData) {
        return [mMsgData count];
    }else{
        return 0;
    }
}

// UITableView에 셀 표시
// 페이징은 구현방법에 따라 상이할 수 있음
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *identifier = @"MessageTableViewCell";
    MessageTableViewCell *cell = (MessageTableViewCell *)[mMsgTableView dequeueReusableCellWithIdentifier: identifier];
    
    if (!cell) {
        cell = [[[NSBundle mainBundle] loadNibNamed:identifier owner:self options:nil] objectAtIndex:0];
    }

    PMSModelMessage *msg = [mMsgData objectAtIndex:[indexPath row]];
    [cell renderingCellWithMsg:msg];
    
    // 다음페이지 가져옴 (5개 아이템 남은경우)
    if([indexPath row] >= mMsgData.count - 5
       && mMsgData.count+deleteCount < totalCount){
        [self loadNextPageData];
    }
    return cell;
}
// 로우 선택시 상세보기 페이지로 이동
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    PMSModelMessage *msg = [mMsgData objectAtIndex:[indexPath row]];
    [msg setReadYn:@"Y"];
    
    MessageDetailViewController *msgDetailViewController = [[MessageDetailViewController alloc] initWithNibName:@"MessageDetailViewController" bundle:nil msg:msg];

    [self.navigationController pushViewController:msgDetailViewController animated:YES];
}

step6 : 메시지 삭제와 복구

step7 : 메시지 읽음처리

// Batch로 요청하는 경우
[PMS sendReadMsgEventWithMsgId:currentMsg.msgId];

// Direct로 요청하는 경우
[PMS sendReadMsgEventWithMsgId:currentMsg.msgId CompleteBlock:^(PMSResult *result) {
    // TODO 읽음처리 요청 이후 동작
}];

step8 : Rich푸시 클릭처리

// 클릭 링크발생시 PMS 링크인지 확인한 후 요청처리
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if([PMS isPmsClickRequest:request]){
        // PMS클릭 처리가 가능할 경우
        NSURLRequest *innerRequest = [PMS clickMsgProcess:request];
        [self.webView loadRequest:innerRequest];
        return NO;
    }else{
        return YES;
    }
}

// 수신한 리치 푸시의 HTML의 Anchor태그를 PMS에서 처리할 수 있는 링크주소로 변환
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    [PMS replaceAnchorTagForPMSClick:self.webView];
}

step9 : 푸시 수신후 동작

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [PMS receivePush:userInfo tagString:@"didReceive"];
}
    if(launchOptions){
        [PMS receivePush:launchOptions tagString:@"didFinish"];
    }
-(void)pmsDidReceivePush:(PMSModelMessage *)resultModel Payload:(NSDictionary *)payload Tag:(NSString *)tag
{
    if(resultModel && [resultModel isSuccess]){
        // 성공적으로 메시지를 받아온 경우
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:resultModel.pushTitle message:resultModel.pushMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];
    }else{
        // 메시지를 받아오지 못한경우 돌려받은 Payload를 이용해서 팝업 출력
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"[Push message]" message:[[payload objectForKey:@"aps"] objectForKey:@"alert"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];
    }
}

step10 : 푸시를 허용하지 않은경우의 처리

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    // 푸시 허용하지 않은경우
    if([PMS isReadyForUse] && !notificationSettings.types){
        // 설정값과 다를경우 PMS시스템에 팝업 허용하지 않은 사용자로 업데이트
        if([PMS getNotiFlag]){
            [PMS setConfigWithNotiFlag:NO MsgFlag:YES CompleteBlock:nil];
        }
    }
}
    // iOS버전 분기
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
        if([UIApplication sharedApplication].currentUserNotificationSettings.types == UIUserNotificationTypeNone){
            // 시스템 알림 설정 == OFF
        }
    } else {   
        if([UIApplication sharedApplication].enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone){
            // 시스템 알림 설정 == OFF
        }
    }

step11 : ATS 임의허용

<!-- ATS 모두 허용 -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key><true/>
</dict>
<!-- ATS 특정 도메인만 허용 -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>amail.co.kr</key>  <!-- 허용할 도메인 1 (고객사에 MsgApi 따라 서로 상이함) -->
        <dict>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
        <key>pushpia.com</key>  <!-- 허용할 도메인 n (PMS이외에 다른 도메인을 추가로 허용) -->
        <dict>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

SDK의 기능

주요기능

기타기능

설정 옵션 변경

// AppKey와 MsgApiUrl변경
// PMSConfig에서 다시 설정할 경우 plist에 선언한 값은 무시됨
[PMSConfig setApiUrl:@"http://apiUrl.com"];
[PMSConfig setAppKey:@"YourAppKey"];

// 서버 msgApi 버전설정 (특수한 경우에만 사용)
[PMSConfig setMsgApiVersionMajor:2 minor:0 patch:5];

// 네트워크 타임아웃 시간 설정
[PMSConfig setNetworkTimeout:10.0f];

// 메시지를 한번에 몇페이지씩 받아올 것인지 설정
[PMSConfig setPerPage:20];

// 네트워크 요청 재시도 횟수
[PMSConfig setReattemptCount:3];

// readMsg, clickMsg의 Batch timer interval설정
[PMSConfig setTimerInterval:10.0f];

// 암호화 사용여부설정 (특수한 경우에만 사용)
[PMSConfig cryptEnable:YES];

// PMSLog를 출력할 것인지의 설정 (오류 발생시 YES로 설정하여 원인파악)
[PMSConfig logEnable:YES];

// PMSApiLog를 출력할 것인지의 설정 (오류 발생시 YES로 설정하여 원인파악)
[PMSConfig apiLogEnable:YES];

// Msg를 LocalDB에 저장할 것인지에 대한 여부 결정 (특수한 경우에만 사용)
[PMSConfig useMsgDB:YES];

// PushToken을 UUID로 사용할 것인지에 대한 옵션
// YES로 설정할 경우 푸시허영하지 않음으로 APNS토큰이 발급되지 않은단말은 PMS에 등록되지 않음
[PMSConfig usePushTokenToUUID:NO];

UserData 전송

// Sample Code
// 모두 전송할 필요 없이 PMS 서버에 저장하고자 하는 값만 전송
NSMutableDictionary* userData = [NSMutableDictionary new];
[userData setValue:@"Tester" forKey:@"custName"];
[userData setValue:@"19850101" forKey:@"birthday"];
[userData setValue:@"01012345678" forKey:@"phoneNumber"];
[userData setValue:@"loc 1" forKey:@"location1"];
[userData setValue:@"loc 2" forKey:@"location2"];
[userData setValue:@"M" forKey:@"gender"]; // M or F
[userData setValue:@"data1" forKey:@"data1"];
[userData setValue:@"data2" forKey:@"data2"];
[userData setValue:@"data3" forKey:@"data3"];

framework 구성

PMS.h

PMSConfig.h

PMSCore.h

PMS Models

PMSResultCode.h

PMSJastor

에러 코드표

MsgApi 코드

Code 설명
000 통신성공
100 파라미터 오류, 필수 파라미터 누락
101 파라미터 오류, 잘못된 파라미터 크기
102 파라미터 오류, 유효하지 않은 파라미터
103 복호화 오류
104 JSON형식 오류
105 잘못된 세션(타임아웃 등)
106 암호화 오류
109 사용할 수 없는 msgApi
110 기타오류 (msgApi)
120 기타오류 (확인되지 않음)
130 -
510 유효하지 않은 앱키

SDK 에러

Code 설명
700 SDK 기타 오류, PMSResult의 msg 확인 필요
702 UUID 생성 오류
720 링크 클릭 처리 오류
730 읽음 처리 오류
920 네트워크 타임아웃, MsgApi 주소 확인 필요