iOS는 안드로이드와 달리 자동 SMS 전송은 불가능하고  수신받을 번호와 메세지 내용은 미리 작성하여 문자 앱 호출이 가능하다.


recipents에 전화번호를 쓰고 message에 메세지 내용을 쓰면 된다.

- (IBAction)sendSms:(id)sender {
    
    if(![MFMessageComposeViewController canSendText]) {
        UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"이 기기는 SMS 발송을 지원하지 않습니다." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [warningAlert show];
        return;
    }
    
    NSArray *recipents = @[@"010-1234-5678"];
    NSString *message = [NSString stringWithFormat:@"SMS 발송 테스트"];
    
    MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
    messageController.messageComposeDelegate = self;
    [messageController setRecipients:recipents];
    [messageController setBody:message];
    
    // Present message view controller on screen
    [self presentViewController:messageController animated:YES completion:nil];
}



iOS 10과 더불어 업데이트 된 Xcode 8.x 버전으로 기존 앱을 빌드 했을 때,

기존에 tableView Header를 커스텀 뷰로 개발하였을 때 section header view가 보이지 않는 문제가 생긴다.


해당 문제는 기존에는 디폴트 높이를 설정하지 않아도 알아서 높이가 들어 갔는데 이번 버전부터는 해당 기능이 삭제가 된듯(....)

앞으로 점점 스토리보드 위주로 갈 것이라고 생각했는데  이번 건은 오히려 스토리보드의 역할이 줄어든 듯한 느낌.. 다른 이유가 있겠지.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 30;
}

위 코드를 추가 하여 높이를 지정해주면 다시 section header view가 나타난다!

이 사실을 알기 전까지는 커스텀 헤더 뷰 지원이 중단 된 줄 알았음 ㅠ_ㅠ


아래는 대략적인 헤더 뷰 생성 예제 코드

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UIView *customTitleView = [ [UIView alloc] initWithFrame:CGRectMake(10, 0, 300, 44)];
    UILabel *titleLabel = [ [UILabel alloc] initWithFrame:CGRectMake(20, 0, 300, 44)];
    
    if(section == 0)
    {
        titleLabel.text = @"섹션1";
        titleLabel.textColor = UIColorFromHEX(0x008080);
        
    }
    else if(section == 1)
    {
        titleLabel.text = @"섹션2";
        titleLabel.textColor = UIColorFromHEX(0xFFCC66);
        
    }
    else
    {
        titleLabel.text = @"섹션3";
        titleLabel.textColor = UIColorFromHEX(0x1E90FF);
    }
     titleLabel.font = [UIFont fontWithName:@"NanumBarunGothic" size:16];
    titleLabel.backgroundColor = [UIColor clearColor];
    [customTitleView addSubview:titleLabel];
    
     return customTitleView;
}


TableView 를 사용하다 보면, 어떤 셀을 선택했느냐에 따라서 다음 화면에서의 동작이나 표시되는 컨텐츠가 다를 수 있다.


먼저, Destination ViewController의 헤더파일에서 데이터를 받을 프로퍼티를 선언

@property (strong, nonatomic) NSString *receiveID;


스토리보드에서 Segue 연결을 셀에다 다음화면을 직접 연결하는게 아니라 뷰 컨트롤러에서 다음 뷰 컨트롤러를 연결한 후 Segue ID를 설정 해 준다

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    transData = [self.datalist objectAtIndex:indexPath.row]; // Cell의 index에 따라서 datalist 배열의 해당하는 index의 데이터를 transData 변수에 저장
    [self performSegueWithIdentifier:@"DataTestSegue" sender:self];  // DataTestSegue : 스토리보드에서 연결 후 설정 한 Segue ID
}


이 후에 화면전환 시 호출되는 prepareForSegue 메소드에서 데이터 넘기기

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
    if ([[segue identifier] isEqualToString:@"DataTestSegue"]) {    // Segue ID에 따라서 구분. 한 화면에서 여러 뷰 컨트롤러로 나뉠 때 분기별로 나눠주면 됨
        SafeZoneDetailViewController *destination = [segue destinationViewController];
        destination.receiveID = transData;
        NSLog(@"ID: %@",transData);
    }
    else if ([[segue identifier] isEqualToString:@"newDataSegue"]) {
        NewSafezoneViewController *destination = [segue destinationViewController];
        
        destination.childID = receiveID;
        NSLog(@"child ID: %@",receiveID);
    }
}


타이머 선언

타이머 ID를 여러 개 선언해서 동시에 여러 개의 타이머를 돌리는 것도 가능하다.

NSTimer *timer;
NSString *str = @"Timer";
timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self
                                           selector:@selector(updateMethod:) userInfo:str repeats:YES];


콜백 함수

- (void) updateMethod:(NSTimer *)incomingTimer
{
    NSLog(@"Inside update method");
    if ([incomingTimer userInfo] != nil)
        NSLog(@"userInfo: %@", [incomingTimer userInfo]);
}


아래와 같이 다중 타이머 선언 시 selector를 이용하여 각 타이머 별로 다중 작업이 가능하다

    NSTimer *locktimer;
    NSTimer *policytimer;
    NSString *lockstr = @"DeviceLock Timer";
    NSString *policystr = @"Policy Timer";
    
    locktimer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self
                                           selector:@selector(updateDeviceLockInfo:) userInfo:lockstr repeats:YES];
    
    policytimer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self
                                           selector:@selector(updatePolicyInfo:) userInfo:policystr repeats:YES];
- (void) updatePolicyInfo:(NSTimer *)incomingTimer
{
    NSLog(@"Inside updatePolicyInfo method");
    if ([incomingTimer userInfo] != nil)
        NSLog(@"userInfo: %@", [incomingTimer userInfo]);
}
- (void) updateDeviceLockInfo:(NSTimer *)incomingTimer
{
    NSLog(@"Inside updateDeviceLockInfo method");
    if ([incomingTimer userInfo] != nil)
        NSLog(@"userInfo: %@", [incomingTimer userInfo]);
}


맥 OS X에 node.js 및 폰갭 설치 방법


1. Xcode 설치 (따로 말 안해도 개발자라면 설치되어 있을거라고 믿습니다...!)

2. node.js 설치 (https://nodejs.org/en/)

3. node.js를 통해 cordova 설치

터미널에서 아래 명령어를 통해 cordova 설치

sudo npm install -g cordova


맥의 로그인 비밀번호를 입력한 후 설치가 완료되면 아래와 같이 정보가 표시됨

/usr/local/bin/cordova -> /usr/local/lib/node_modules/cordova/bin/cordova

cordova@6.1.1 /usr/local/lib/node_modules/cordova

├── underscore@1.7.0

├── q@1.0.1

├── ansi@0.3.1

├── nopt@3.0.1 (abbrev@1.0.7)

├── cordova-common@1.2.0 (cordova-registry-mapper@1.1.15, unorm@1.4.1, underscore@1.8.3, q@1.4.1, semver@5.1.0, shelljs@0.5.3, osenv@0.1.3, elementtree@0.1.6, bplist-parser@0.1.1, glob@5.0.15, plist@1.2.0)

├── update-notifier@0.5.0 (is-npm@1.0.0, semver-diff@2.1.0, string-length@1.0.1, chalk@1.1.3, repeating@1.1.3, configstore@1.4.0, latest-version@1.0.1)

└── cordova-lib@6.1.1 (valid-identifier@0.0.1, opener@1.4.1, properties-parser@0.2.3, semver@4.3.6, shelljs@0.3.0, nopt@3.0.6, dep-graph@1.1.0, cordova-app-hello-world@3.10.0, xcode@0.8.0, aliasify@1.9.0, tar@1.0.2, init-package-json@1.9.3, cordova-serve@1.0.0, request@2.47.0, npm@2.15.4, cordova-js@4.1.4)


설치 완료 후 cordova 버전 확인

cordova -v

앱을 개발하다 보면 구현하고자 하는 기능에 따라서 위치정보를 이용해야 할 때가 있는데

iOS에서 위치정보를 사용하려고 하면 사용자의 동의를 먼저 받아야 한다.


먼저 프로젝트에 CoreLocation Framework를 추가한다.




이후에 해당 뷰 컨트롤러에서 위치정보 사용 동의를 받는 코드를 추가한다.

.h 헤더 파일
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController @property (strong, nonatomic) CLLocationManager *locationManager;
.m 구현 파일
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
}
self.locationManager.pausesLocationUpdatesAutomatically = NO;


그리고 info.plist의 Custom iOS Target Properties에서 다음과 같이 설정해 준다.


위치정보 사용은 [사용 안함/앱을 사용할 때만/항상]  이렇게 3가지 형태가 있는데 필요한 기능에 따라서

requestAlwaysAuthorization 이나 requestWhenInUseAuthorization을 써주면 된다.

만약 항상 위치정보를 사용하지 않아도 되는데 requestAlwaysAuthorization을 사용한다면 심사 과정에서 리젝이 날 수도있으니 주의한다.

(경험 상 리뷰어한테도 충분히 설명을 해 줘야함)






'프로그래밍 > iOS - OBJC' 카테고리의 다른 글

iOS NSTimer 호출하기  (1) 2016.05.12
맥 OS X PhoneGap 설치  (0) 2016.04.27
iOS 8에서 푸시 알림 동의 받기  (0) 2016.03.10
Singleton 패턴 사용하기  (0) 2016.03.09
iOS 앱 자동로그인  (0) 2016.03.09

iOS 7->8 로 넘어오면서 푸시알림 동의 받는 코드가 바뀌었다.

개발 중인 앱은 최소 iOS 버전이 iOS 8버전 이상이지만 혹시나 구버전을 지원해야 하는 경우도 있기 때문에 함께 기록 해 본다.


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

    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        NSLog(@"Requesting permission for push notifications...iOS 8"); // iOS 8
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:
                                                UIUserNotificationTypeAlert | UIUserNotificationTypeBadge |
                                                UIUserNotificationTypeSound categories:nil];
        [UIApplication.sharedApplication registerUserNotificationSettings:settings];
    } else {
        NSLog(@"Registering device for push notifications...iOS 7 and earlier"); // iOS 7 and earlier
        [UIApplication.sharedApplication registerForRemoteNotificationTypes:
         UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |
         UIRemoteNotificationTypeSound];
    }
}


그리고 아래는 디바이스가 APN 서버에 정상적으로 등록 되었는지 로그를 찍어서 확인 할 수 있는 코드

- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)settings
{
    NSLog(@"Registering device for push notifications...iOS 8"); // iOS 8
    [application registerForRemoteNotifications];
}

- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token
{
    NSLog(@"Registration successful, bundle identifier: %@, mode: %@, device token: %@",
          [NSBundle.mainBundle bundleIdentifier], [self modeString], token);
}

- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"Failed to register: %@", error);
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)notification completionHandler:(void(^)())completionHandler
{
    NSLog(@"Received push notification: %@, identifier: %@", notification, identifier); // iOS 8
    completionHandler();
}

- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)notification
{
    NSLog(@"Received push notification: %@", notification); // iOS 7 and earlier
}

- (NSString *)modeString
{
#if DEBUG
    return @"Development (sandbox)";
#else
    return @"Production";
#endif
}



'프로그래밍 > iOS - OBJC' 카테고리의 다른 글

iOS NSTimer 호출하기  (1) 2016.05.12
맥 OS X PhoneGap 설치  (0) 2016.04.27
iOS에서 위치정보 사용 동의 받기  (0) 2016.03.10
Singleton 패턴 사용하기  (0) 2016.03.09
iOS 앱 자동로그인  (0) 2016.03.09

앱 개발 시에 Singleton 패턴 이라는 이야기를 자주 듣게 되는데 널리 쓰이는 만큼 한번 배워 놓으면 써먹을 데가 많다.

위키 백과에서의 싱글톤 패턴에 대한 정의는 아래와 같다.

소프트웨어 디자인 패턴에서 싱글턴 패턴(Singleton pattern)을 따르는 클래스는, 
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 
최초의 생성자가 생성한 객체를 리턴한다. 이와 같은 디자인 유형을 싱글턴 패턴이라고 한다.


쉽게 생각해서 여러 클래스에서 공통적으로 자주 쓰이는 인스턴스들을 필요할 때마다 

매번 초기화 할 필요 없이 한번 초기화 된 인스턴스를 불러온다는 것이다.

필요할 때마다 매번 인스턴스를 생성한다는 것은 시스템 자원의 낭비를 가져온다.


예제를 하나 들자면 아래 내용은 실제 네트워크를 통해 앱에서 Database에 엑세스 할때 주로 사용하였다.

Singleton.h 헤더 파일
@interface Singleton : NSObject

+ (NSString *) getBaseURL;
+ (NSString *) getProfileImageBaseURL;

@end

Singleton.m 구현 파일 @implementation Singleton + (NSString *) getBaseURL { static NSString * const BaseURLString = @"http://서버 주소"; return BaseURLString; } + (NSString *) getProfileImageBaseURL { static NSString * const BaseURLString = @"http://이미지 파일이 저장된 서버 주소"; return BaseURLString; } @end

이렇게 자주 쓰일 URL을 미리 선언 해 놓은 후


싱글톤 패턴 활용
#import "Singleton.h"

NSString *urlStr = [NSString stringWithFormat:@"%@/login_check.php",[Singleton getBaseURL]];
NSString *imageurlStr = [NSString stringWithFormat:@"%@/get_image.php",[Singleton getProfileImageBaseURL]];

이런 식으로 필요할 때마다 불러와서 사용하면 된다.


만약에 싱글톤 패턴을 사용하지 않고 필요할 때마다 인스턴스를 만들어서 사용을 한다면

기존 URL 값이 바뀌어야만 하는 상황이 생겼을 때 생성했던 모든 인스턴스를 찾아서 

각각 수정해줘야 하기 때문에 효율성 측면에서 추천하지 않는 방법이다.


'프로그래밍 > iOS - OBJC' 카테고리의 다른 글

iOS NSTimer 호출하기  (1) 2016.05.12
맥 OS X PhoneGap 설치  (0) 2016.04.27
iOS에서 위치정보 사용 동의 받기  (0) 2016.03.10
iOS 8에서 푸시 알림 동의 받기  (0) 2016.03.10
iOS 앱 자동로그인  (0) 2016.03.09

프로젝트 진행 중에 처음에는 없던 자동로그인 기능 구현이 결정되었다.

최대한 간단하게 구현하려고 노력했으며 실제로 그렇게 되었다고 본다.


바로 NSUserDefaults 를 이용한 방법인데 LoginState, Autologin 이라는 NSUserDefault를 선언하고

LoginState는 YES/NO 값을 가지고 ID와 PW를 스트링으로 저장하여 다음 앱 실행 시 활용하였다.


앱 메인에 로그인 유지를 선택 할 수 있는 체크박스를 만들어 놓은 후

if (autoLoginChecked) { // 자동로그인 체크 NSUserDefaults *autologin = [NSUserDefaults standardUserDefaults]; [autologin setObject:@"yes" forKey:@"loginstate"]; // 자동로그인 State를 yes로 저장 [autologin setObject:userID.text forKey:@"userid"]; // User ID 필드 값 저장 [autologin setObject:userPass.text forKey:@"pass"]; // User PW 필드 값 저장 [autologin synchronize]; }

이렇게 설정을 해 놓은 후 다음 앱 실행 시 loginstate 의 키 값이 yes냐 no냐에 따라서 분기를 주면 된다.

사용자 로그아웃 시에는 loginstate를 no로 바꾸고 synchronize를 해주면 간단하다.


'프로그래밍 > iOS - OBJC' 카테고리의 다른 글

iOS NSTimer 호출하기  (1) 2016.05.12
맥 OS X PhoneGap 설치  (0) 2016.04.27
iOS에서 위치정보 사용 동의 받기  (0) 2016.03.10
iOS 8에서 푸시 알림 동의 받기  (0) 2016.03.10
Singleton 패턴 사용하기  (0) 2016.03.09

+ Recent posts