본문 바로가기

개발도구/iOS - 아이폰 개발

[iOS]twitter API

https://github.com/bengottlieb/Twitter-OAuth-iPhone



SA_OAuthTwitterEngineDelegate / 트위터 로그아웃

안녕하세요^^ 오랫만에 맥부기에 글을 올리네요!
이번에 어플리케이션 업데이트를 하면서 SNS연동을 처리하게 되었습니다.
단순 연동에 관해서는 글들이 많이 있어서 처리하기 쉬웠습니다!

그런데!! 트위터나 페이스북의경우 한번 로그인하면 앱을 종료하기까지는 그 아이디만 사용할 수 있더라구여...
관련자료를 계속 검색하다가 결국 구현해서 맥부기에 자료삼아 남겨볼까합니다^^(너무 받기만해서..)

//많은 분들이 아시고 있을 듯하지만 자세한 내용은 있지 않아서 글을 남기네요!!
일단 페이스북 관련입니다!
페이스북은 트위터보다 로그아웃에 관련된 정보가 많아서 쉽게 찾을 수 있었는데요!
일단 페이스북의 기본예제인 Hackbook을 확인하시면 쉽게 구현 가능하실 거에요!

아래의 메서드는 로그인 처리시 불려지고 실행이되게 됩니다.
- (void)fbDidLogin;

또한 로그아웃 처리시 불려지는 메서드로
- (void)fbDidLogout; 라는 메서드가 존재합니다.
facebook 객체에서 [facebook logout:self];을 실행하면 자동으로 객체에 저장한 정보들을 지워주는데
일반적으로 fbDidLogin에서 아래와같이 토큰을 저장해 줬기 때문에

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
[defaults synchronize];

로그아웃 메서드가 호출될때는 반대로 등록한 키값을 제거해 주어야 합니다.

[defaults removeObjectForKey:@"FBAccessTokenKey"];
[defaults removeObjectForKey:@"FBExpirationDateKey"];
[defaults synchronize];

일단 페이스북의 내용은 Hackbook에 정말 잘 작성되어 있기때문에 꼭 참고하셔서 구현하시길 바랍니다!!
(제가 글을 못써서 이것만 보시면 정말 아무것도 안될수도....꼭 확인하세여..ㅠㅠ)

다음으로 Twitter 로그아웃 부분입니다. iOS 5 부터는 트위터 라이브러리를 제공하기 때문에 로그인, 로그아웃
이러한 처리자체가 필요없습니다!!(정말 좋더라구여..) 하지만 이하의 버전부터는 다른방법으로 구현을 해 주어야하는데요
저같은 경우는 Twitter+OAuth를 사용해서 붙여 넣었습니다.
이미지 전송 및 텍스트 전송을 위해 SA_OAuthTwitterEngine에 메서드를 따로 선언하여 구현하였습니다.
혹시나 필요하신분은 아래 소스를 참고하시면 될것 같네요^^

- (NSString *)_sendRequestWithMethod:(NSString *)method 
                                path:(NSString *)path
                               image:(UIImage *)image
                         requestType:(MGTwitterRequestType)requestType 
                        responseType:(MGTwitterResponseType)responseType
{
    // 이미지 전송하기 소스코드
    NSURL *finalURL = [NSURL URLWithString:path];

    if (!finalURL) {
        return nil;
    }

    OAMutableURLRequest *theRequest = [[[OAMutableURLRequest alloc] initWithURL:finalURL
                                                                       consumer:self.consumer 
                                                                          token:_accessToken 
                                                                          realm: nil
                                                              signatureProvider:nil] autorelease];
    if (method) {
        [theRequest setHTTPMethod:method];
    }
    
    [theRequest setHTTPShouldHandleCookies:NO];
    
    // Set headers for client information, for tracking purposes at Twitter.
    [theRequest setValue:_clientName    forHTTPHeaderField:@"X-Twitter-Client"];
    [theRequest setValue:_clientVersion forHTTPHeaderField:@"X-Twitter-Client-Version"];
    [theRequest setValue:_clientURL     forHTTPHeaderField:@"X-Twitter-Client-URL"];
    
    // Set body
    NSString *boundary = @"----------------------------991990ee82f7";
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [theRequest setValue:contentType forHTTPHeaderField:@"content-type"];
    
    NSMutableData *body = [NSMutableData dataWithLength:0];
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"media[]\"; filename=\"MansCoordinate.jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];  
    [body appendData:UIImageJPEGRepresentation(image, 1.0)];
    
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"status\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];

    /* 이부분은 단지 지역화를 위해 로컬라이징 스트링을 사용하였고,
    * 
해당 라이브러리의 경우 같은내용의 메시지로 글을 올리면
    * 메서드 수행으로 이미지, 텍스트는 이상없이 올라가는데 수행결과로 403?401? 에러코드를 내밷습니다.
    * 따라서 시간값을 추가해서 전송할 메시지가 이전에 올린 글과 중복되지 않도록 처리해 주었습니다.
    */
    [body appendData:[[NSString stringWithFormat:@"%@ [%@]\r\n", NSLocalizedString(@"share_msg", @"sns"), [NSDate date]] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    [theRequest prepare];
    [theRequest setHTTPBody:body];
    
    // Create a connection using this request, with the default timeout and caching policy,
    // and appropriate Twitter request and response types for parsing and error reporting.
    MGTwitterHTTPURLConnection *connection;
    connection = [[MGTwitterHTTPURLConnection alloc] initWithRequest:theRequest 
                                                            delegate:self 
                                                         requestType:requestType 
                                                        responseType:responseType];
    
    if (!connection) {
        return nil;
    } else {
        [_connections setObject:connection forKey:[connection identifier]];
        [connection release];
    }
    
    return [connection identifier];
}

음... 로그아웃을 말씀드리다가 다른길로 새버렸네요;;; 혹시나..혹시나 필요하신분은 참고해주세요!
아무튼 마지막으로 트위터의 로그아웃!!
트위터도 페이스북과 마찬가지로 로그인시 NSUserDefaults에 키값을 저장하는 부분이 있습니다.
따라서 로그아웃 버튼을 클릭시 Twitter 객체의 clearAccessToken을 불러와 토큰값을 지워주고
할당된 객체를 해제시켜버렸습니다.

[_engine clearAccessToken];
                         
_engine = nil;
[_engine release];
                        
[defaults removeObjectForKey:@"authData"];
[defaults synchronize];

그런데! 이렇게 로그아웃 처리를 해도 가장 처음 로그인할때 모달뷰로 뜨는 창에는 아직도 로그인상태인것을 확인할 수 있습니다!
따라서 해당 뷰의 로그인 상태를 해지하기위해서 Twitter객체를 선언해줄때 아래와같이 하나의 메서드를 포함시켜주세요

_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey    = kOAuthConsumerKey;
_engine.consumerSecret = kOAuthConsumerSecret;
[_engine setClearsCookies:YES];

이렇게 setClearsCookies값을 YES로 만들어주시면 로그아웃하고 다시 로그인창을 불러올때
이전에 로그인한 정보는 날려버리고, 새롭게 아이디, 패스워드를 입력하는 창으로 나오게 됩니다^^

밤을새고 수업시간에 심심해서 글을 올리게되서 두서없이 글을 적게된것 같네요...
여기까기 글을 읽어주셔서 감사합니다!! 아참, 틀리거나 이상한 부분은 댓글로 수정부탁드리겠습니다.ㅠ
아직까지도 초보프로그래머이기 때문에 많은 가르침 부탁드리겟습니다!!
새롭게 시작되는 한주 즐겁게 보내세요!!