페이스북에 공유하기 기능은 대부분의 앱에서 활용을 하고 있습니다.


앱에서 공유하기 버튼을 눌렀을 때 페이스북 앱이 없다면 Web 화면을 통해 공유할 수 있도록 브라우저가 뜨게 되는데 이렇게 공유를 하면 잘 되는데, 페이스북 앱이 있어서 Native으로 앱이 실행되었을 때 글을 작성하고 게시 버튼을 누르면 게시가 되지 않고 앱으로 돌아오는 경우가 있습니다.


제 경우 Error code 102 가 나와서 검색을 해보니 페이스북 개발자 페이지의 해당 앱의 Display Name 이 문제가 되어서 그런걸로 확인되었습니다.


개발자 페이지의 Display Name : AAA 라고 되어있는데

앱의 plist의 FacebookDisplayName 항목에는 BBB 라고 되어있으면 공유가 안되네요.


해당 키값을 동일하게 맞춰놓고 테스트 해보니 공유기능이 정상적으로 돌아갑니다.


아래 매크로는 http://dadabeatnik.wordpress.com/2013/09/12/xcode-and-asynchronous-unit-testing/ 에서 찾은 내용입니다.


// Macro - Set the flag for block completion

#define StartBlock() __block BOOL waitingForBlock = YES


// Macro - Set the flag to stop the loop

#define EndBlock() waitingForBlock = NO


// Macro - Wait and loop until flag is set

#define WaitUntilBlockCompletes() WaitWhile(waitingForBlock)


// Macro - Wait for condition to be NO/false in blocks and asynchronous calls

// Each test should have its own instance of a BOOL condition because of non-thread safe operations

#define WaitWhile(condition) \

do { \

while(condition) { \

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; \

} \

} while(0)




사용 예제


페이스북의 문자로 된 ID를 숫자 형태의 ID로 바꿀 때 사용하는 facebook의 graph api 조회를 예로 들어보겠습니다.


비동기로 수행되는 로직이 있는경우 해당 로직이 끝나기 전에 테스트 케이스가 끝나버리기 때문에 위의 매크로를 이용해서 비동기 처리가 끝날 때 까지 테스트 케이스가 종료되지 않도록 기다립니다.


주의할 점은 비동기 로직이 실패했을 때에도 EndBlock();을 호출 해 주어야 정상적으로 종료 됩니다.


- (void)testFacebookURL {

NSString *urlString = @"https://graph.facebook.com/사용자 또는 페이지 아이디";

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

manager.responseSerializer = [AFJSONResponseSerializer serializer];


StartBlock();

[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

NSLog(@"response : %@", responseObject);

NSLog(@"id : %@", responseObject[@"id"]);


EndBlock();


} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

NSLog(@"Error : %@", error);

EndBlock();

}];

WaitUntilBlockCompletes();

}


iOS 7 AutoLayout 과 topLayoutGuide 를 이용한 화면 맞추기 에서 했던 방법은


스토리보드를 사용 시 적용할 수 있는 방법이고 XIB 위주로 만들어진 레이아웃에서 iOS6 이하와, 7 모두 잘 맞게 맞추는 방법을 알아보겠습니다.




기존 6.0 미만을 지원하는 프로젝트인 경우 Xib의 우측 유틸리티 섹션에 첫번째 탭인 File inspector 에 보면 Use Autolayout 항목이 체크 해제되어있을 것입니다.


보통 이 상태로 iOS7 에서 실행해보면 아래와같이 상태바 영역까지 콘텐츠가 밀려 올라와있는것을 볼 수 있습니다.


일단 iOS7 에서 잘 보일 수 있도록 ViewController.view의 sub view 들을 모두 선택하여 20포인트 아래로 끌어줍니다.


메인 뷰의 자식뷰들을 모두 선택


객체들을 상태바 아래로 이동


일단 에디터 창에서 상태바 아래로 모두 내렸으면 하위뷰들을 모두 선택한 상태에서 오른쪽 Size inspector 를 선택합니다.


그리고 아래와 같이 iOS6 / 7 Deltas 라고 되어있는곳의 Delta Y 항목을 -20을 셋팅합니다.


그리고 iOS6으로 실행!


짜잔~ 잘 나왔죠? (Text Field 문자열 짤린건 패스.. ㅋㅋ)



xib에서 배치된 객체들은 이렇게 한번에 처리가 됩니다.


다만 뷰가 로드된 이후 프로그램 로직에 의해 재 배치 되는 경우는 iOS 버전에 따라 위치를 보정해줘야 합니다.


자~ 이제 모두모두 즐거운 iOS7 호환성 작업을 시작해 봅시다!


iOS 2.x 일 때 부터 개발을 해왔지만 그땐 메모리 관리도 잘 몰라서 자주 뻗고 그랬는데

어느덧 iOS 7 이 정식으로 공개가 되었습니다.


iOS7에서 UI가 급격하게 변하면서 개인적으로 가장 시급한 문제는 네비게이션 컨트롤러를 사용하지 않는 Single View 스타일의 앱을 업데이트 하면서 생긴 문제인데, 기존에는 상태바 아래부터 콘텐츠 배치가 되었으나, 이제는 모든 화면을 콘텐츠 영역으로 사용하게 되면서 개발자들에게 멘붕을 선물해주고있죠. ㅋ

기존 버전들과의 호환성을 맞추기 위해 iOS7에서도 여전히 상태바 영역만큼을 띄운 채로 보여주려면 하나하나 OS버전에 따라 분기를 해주거나 AutoLayout과 UIViewController.topLayoutGuide 를 사용해야 합니다.


일단 다른 앱들에 적용하기 전에 샘플로 하나 만들어보았습니다.


참고로 스토리보드에서만 가능하고 XIB 에서는 Top, Bottom Layout Guide가 나오지 않는다. XIB에서는 어떻게 하는지 좀 찾아봐야 할 듯 합니다.



일단 화면 구성은 메인 뷰 안에 UILabel을 하나 추가하고 시계 아래쪽에 보이도록 만듭니다.


그리고 Label의 y 값을 0으로 하고 SuperView에 맞춰진 경우 아래와 같은 화면을 보게 됩니다.


iOS6 에서는 기존대로 잘 나오게 됨.


iOS7 에서는 라벨이 상태바 영역을 침범하게 됨.



일단 여기서 한번 멘붕을 겪고 y 값을 20을 주고 띄워서 iOS7으로 실행해본다.

일단 잘 iOS7 에서는 잘 나오게 되지만..

iOS6 에서는 반대로 20pt 떨어져서 나오게 됩니다.


이렇게 되면 어떻게 처리해야 하나 한참 구글신께 물어보면 edgesForExtendedLayout 를 사용하라고 나오는데, 이런 답변은 대부분 iOS7 Beta 초반의 얘기들입니다.


이 방식으로는 아무리 셋팅을 해봐도 Single View 스타일의 앱에서는 효과가 없었습니다.


이에 대한 해결 방법은. UILabel을 선택하고 Xcode의 Utility 섹션(화면 우측)의 Size 탭에 가보면 아래와 같은 제약조건들이 설정되어있다.


여기서 중요한건 Top Space to 라고 되어있는건데 Xcode 4.5까지는 이 기본 보라색 속성을 지울 수가 없었죠.

하지만 Xcode 5 에서는 이 기본 속성도 삭제가 가능합니다.


일단 오른쪽 설정 버튼을 눌러 해당 제약사항을 삭제해버린다.


그리고 Status Bar가 있는것으로 생각하고 20포인트를 띄워준다. (UILabel.frame.origin.y = 20)



이제 왼쪽의 뷰 구조 쪽에서 제약 조건을 설정하고 싶은 객체를 선택하고 마우스 우클릭을 한 채로 위쪽에 보이는 Top Layout Guide로 끌어놓습니다.


그러면 위와 같이 Spacing 항목 두개가 뜨는데 Vertical Spacing을 선택하고 다시 오른쪽에 제약사항들 목록을 보면 Top Space to : Top Layout Guide 항목이 추가되어있습니다.


이제 실행해보면 아래와 같이 iOS6, iOS7 둘 다 똑같은 위치에 UILabel이 표시됩니다.

하지만.... 여기서 끝이 아닌것이, AutoLayout은 iOS6.0 부터 지원하는 기능이라 iOS4.3 ~ 5.x 까지는 여전히 따로 작업을 해줘야 하는 문제가 있습니다.


설명이 길었는데 중요한건 Top Space to 의 Target이 Superview 가 아니라 topLayoutGuide 가 되어야 한다는 것!


1. iOS 앱에 게임센터 연동을 하기위해서는 iTunesConnect 의 앱 관리메뉴에서 Game Center 를 활성화 시켜줘야 한다.


게임 센터가 활성화 된 상태.

2. 개발자 문서에 있는 게임센터 인증 메소드를 사용하여 인증을 시도한다.
- (void) authenticateLocalPlayer
{
    [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
         if (error == nil)
         {
              // Insert code here to handle a successful authentication.
         }
         else
         {
             // Your application can process the error parameter to report the error to the player.
         }
     }];
}
위의 코드를 호출하게되면 아래와 같은 로그인 화면이 뜨게 된다.


Game Center를 테스트 하기 위해서는 Sandbox용 계정(개발 환경용)을 만들어야 한다.
실제로 사용하던 아이디로는 로그인이 되지 않는다.



3. Use Existing Account 를 누르고 새로 생성한 Sandbox용 계정으로 로그인을 하면 위와 같이 게임센터에 로그인 된 화면을 볼 수 있다..



기타 1. 간혹 아래와 같은 화면이 뜨는 경우가 있을 수 있는데..

이는 Bundle identifier 값이 안맞아서 생기는 오류.. 이 값만 잘 맞춰주면 게임센터 인증하는데 무리가 없음..


+ Recent posts