본문 바로가기

스터디/2013 여름

8월 6일



cocos2d-x 프로젝트의 iOS ver.  Twitter 연동시키기.


참고한 원문: http://blog.saltfactory.net/74


1. Twitter.framework 와 Account.framework 추가


2. CCApplication.mm 파일에 아래 헤더/디파인 추가

#import <Twitter/Twitter.h>

#import <Accounts/Accounts.h>


#define TWITTER_TEXT_URL   @"http://api.twitter.com/1/statuses/update.json"

#define TWITTER_TEXT_WITH_IMG_URL @"https://upload.twitter.com/1/statuses/update_with_media.json"


3. CCApplication.h 에 사용해야하는 함수 추가

 bool isTwitterLogin()

 void SendTwitterText( const char *_message )

 void SendTwitterTextWithIMG( const char *_message )


4. 3의 함수 세 가지를 구현


5. 참 쉽죠..가 아니라ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ



디바이스의 트위터 계정이 로그인 되어있는지, 그렇지 않은지 확인.

트윗을 보낼 수 없는지, 있는지에 대한 메서드. canSendTweet.

bool CCApplication::isTwitterLogin()

{

    if([TWTweetComposeViewController canSendTweet])

    {

        return true;

    }

    else

    {

        return false;

    }

}



iPhone native App에서는 Twitter.framework만으로도 무리없이 트위터에 메세지를 보내거나, 사진을 보낼 수 있지만, 애석하게도 Cocos2d-X 에서는 그런 편리한 기능을 그대로 가져다 쓸 수가 없다. 때문에 Account.framework를 통하여 twitter type 의 account 를 받아온다.


매개변수는 트위터로 보낼 메세지를 받아오는 역할.

우선 sendTwitterText 함수의 틀부터 구현한다.

void CCApplication::sendTwitterText( const char* _message )

{


// 트위터 로그인이 되어있는지 확인

    if(isTwitterLogin())

    {

// 트위터가 로그인되어 있음.

    }

    else

    {

// 트위터 로그인이 되지 않음.

    }

}




트위터 로그인이 확인되었으면 이제 Account를 받아올 차례.

먼저 트위터에 접근할 수 있는지부터 확인한다.

위 코드에서 // 트위터가 로그인 되어 있음. 부분에 주석을 지우고 아래 코드를 작성한다.

ACAccountStore *accountStore = [[ACAccountStore alloc] init];

ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

        

[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error){

if(granted)

{

    // 트위터에 접근 성공 ! 

} // if(granted)  

}];


원래 if(granted) 부분에서 AlertView가 호출된다고들 하던데 대체 왜!!! 나는 왜ㅠㅠㅠㅠ 그냥 내가 뭔가 잘못했겠지, 싶다.




이제  //트위터 접근 성공! 부분의 코드를 작성한다.

실제로 accountType에 맞는 account를 accountstore으로부터 받아오고 해당 계정에 메세지만 보내는 기능을 구현한다.


NSArray *accounts = [accountStore accountsWithAccountType:accountType];


if([accounts count] > 0)

{


ACAccount *twitterAccount = [accounts objectAtIndex:0];

TWRequest *postRequest;

postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:TWITTER_TEXT_URL] parameters:[NSDictionary dictionaryWithObject:_message forKey:@"status"] requestMethod:TWRequestMethodPOST];

[postRequest setAccount:twitterAccount];

                    

[postRequest performRequestWithHandler:

^(NSData *resopnseData, NSHTTPURLResponse *urlResponse, NSError *error)

{

// 전송에 관한 결과를 콘솔에 표시

NSString *output = [NSString stringWithFormat:@"HTTP response status: %i", [urlResponse statusCode]];

  NSLog(@"Twitter Post status: %@", output);


// 전송에 관한 결과를 화면에 표시 

// 초반에 썼던 멍청한 방법

const char* _cOutput = [output UTF8String];

if(strcmp(_cOutput, "HTTP response status: 200") == 0)

{

 UIAlertView *alertView2 = [[UIAlertView alloc] initWithTitle:@"Twitter Result" message:@"SUCCESS" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

[alertView2 performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

}

else // failed.

{

// 현재 쓰고있는 좀 나은 방법

if( [urlResponse statusCode] == 200 )

{

NSLog(@"Due to the repetition of the same message, Request is denied.");

 }

                             

  UIAlertView *alertView2 = [[UIAlertView alloc] initWithTitle:@"Twitter Result" message:@"FAILED" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

 [alertView2 performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

                             

}

                         

}];

} //  if([accounts count] > 0)


다시 보기 짜증날만큼 나름 복잡한 코드를 찬찬히 살펴보자면



 받아온 트위터 계정들 중 가장 첫번째 계정을 받아온다. 일반적으로 여러개 두고 쓰는 사람보다 하나 두고 쓰는 사람이 많..아서인가? 글쎄... 나도 참고한 소스라.

ACAccount *twitterAccount = [accounts objectAtIndex:0];



괄호 안에 괄호 안에 괄호 안에... 

TWRequest *postRequest;


postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:TWITTER_TEXT_URL] parameters:[NSDictionary dictionaryWithObject:_message forKey:@"status"] requestMethod:TWRequestMethodPOST];


[postRequest setAccount:twitterAccount];


사실 저 initWithURL 이라는 메서드를 뜯어보면 아래와 같다.

[TWRequest initWithURL: NSURL 타입의 URL주소

parameters: NSDictionary 타입의 매개변수

requestMethod: 데이터를 보낼 방식 

];


URL주소는 "이곳" 에서 확인할 수 있다. GET 방식, POST 방식에 따라 적절한 URL 을 선택하면 될듯. 일단 사진+글 보내는 것과 글만 보내는 것의 URL은 가장 위 define 된 주소를 참고하길.


postRequest에 꾸역구역 넣어두었던 데이터를 꺼내서 보낼 시간 ~ 

[postRequest performRequestWithHandler:

^(NSData *resopnseData, NSHTTPURLResponse *urlResponse, NSError *error)

{

// 전송에 관한 결과물을 콘솔에 표시

NSString *output = [NSString stringWithFormat:@"HTTP response status: %i", [urlResponse statusCode]];

  NSLog(@"Twitter Post status: %@", output);          


// 전송에 대한 결과를 화면에 표시              

}];

위 소스는 별거 없고 블록 코드이다. 블록코드에 대한 설명은 "이곳" 을 참고했다. 글 전체가 블록코드에 대한 것은 아니고, 중간에 블록코드가 대략 어떠한 것이고, 어떻게 쓰는 것인지 잘 나와있다. [Objective-C block code] 로 구글링해도 많이 나온다.

아무튼.


결과는 HTTP status code 로 확인할 수가 있다. 코드의 의미는 "이곳"에서 확인할 수 있는데 주로 200, 403, 404 정도가 나온다. 200 이 나와야 성공. 


전송한 결과를 화면에 표시해주지 않으면 사용자들이.. 불편하겠지. 개발자들이야 콘솔로 확인하면 된다지만.. 그래서 결과를 UIAlertView로 알려준다.

// 전송에 대한 결과를 화면에 표시


// 초반에 썼던 멍청한 방법

const char* _cOutput = [output UTF8String];

if(strcmp(_cOutput, "HTTP response status: 200") == 0)

{

 UIAlertView *alertView2 = [[UIAlertView alloc] initWithTitle:@"Twitter Result" message:@"SUCCESS" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

[alertView2 performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

}

else // failed.

{

// 현재 쓰고있는 좀 나은 방법

if( [urlResponse statusCode] == 200 )

{

NSLog(@"Due to the repetition of the same message, Request is denied.");

 }

                             

  UIAlertView *alertView2 = [[UIAlertView alloc] initWithTitle:@"Twitter Result" message:@"FAILED" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

[alertView2 performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

                             

}


초반에 썼던 멍청한 방법은 output이 왜 string이지? 아 integer 형의 에러코드를 받아오는게 아니라 그냥 string 을 통째로 받아오는구나!!!!^^ 싶어서 string.h 까지 헤더에 include 하고.. 난리를 치면서 짰더니만 방금!!!! 포스팅 할 때 보니까 어.. ? 

NSString *output = [NSString stringWithFormat:@"HTTP response status: %i", [urlResponse statusCode]];


[urlResponse statusCode] 이거 뭥밐ㅋㅋㅋㅋㅋㅋ.. 난 매우 멍청했다. 어차피 당장 커밋될 일 없는 코드지만 큰일날 뻔.. 


아,  한가지 더 짚고 넘어가야할 부분이... 

UIAlertView *alertView2 = [[UIAlertView alloc] initWithTitle:@"Twitter Result" message:@"SUCCESS" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];


[alertView2 performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

CCApplication은 mm 파일이기 때문에 Objective-c 의 문법도 컴파일되지만.. 그렇지만.. 지금 우리가 잊지 말아야 할 건, 이건 일반적인 메서드 안의 alert view 가 아니라 블럭 코드 안의 alert view 라는 것이었다. 이게 대체 왜 show 가 안되니ㅠㅠ.. 하면서 헤매다가 다행히 해결방법을 찾았다. 

MainThread 에서 해당 함수(select에 지정된)를 실행해주세요~ 하는 요청을 주어야 했다. 이건 내 추측? 사실 잘 모르겠고 그냥 그런 거 같다. 


일단 여기까지!!! 나도 퇴근해야해 T_T .. 

텍스트만 올리는 부분의 전체 코드는 아래 접힌 부분이고... 

참, const char* 형태로 받은 인자를 NSString 타입으로 형변환해주어야 한다. 바뀐 코드는 파란색으로 표시해둠.


이 함수를 활용해주기 위해서는 .. 뭐 다시 cocos2d-x의 cpp 파일로 돌아가서, 이 함수를 사용해주어야하는 cpp 파일에 #include "CCApplication.h" 해주고 아래 코드를 원하는 곳에 추가하면 된다.


CCApplication::sharedApplication->SendTwitterText(" 원하는 메세지를 넣는다 ");







스크린 샷 찍어서 텍스트와 함께 보내는 코드

 void SendTwitterTextWithIMG( const char *_message )

는 휴가 다녀와서@''@ 


'스터디 > 2013 여름' 카테고리의 다른 글

8월 16일  (0) 2013.08.16
8월 14일  (0) 2013.08.14
8월 1일  (0) 2013.08.01
7월 31일  (0) 2013.07.31
7월 30일.  (0) 2013.07.30