Permalink
Browse files

Refactoring by removing delegates and much simpler workflow

  • Loading branch information...
1 parent 4472389 commit b0e80aac48a9e5e5849eb380a8e9d80679083e79 @MugunthKumar committed Mar 14, 2012
View
4 TwitterDemo.xcodeproj/project.pbxproj
@@ -77,6 +77,7 @@
5B9771231497927C00791728 /* RSTwitterEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = RSTwitterEngine.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
5BAA64D51497D8CB00ED569D /* logo_cube_57.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_cube_57.png; path = ../logo_cube_57.png; sourceTree = "<group>"; };
5BAA64D71497D8D300ED569D /* logo_cube_114.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_cube_114.png; path = ../logo_cube_114.png; sourceTree = "<group>"; };
+ AB31731715106A0B005530E3 /* RSTwitterConfigs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RSTwitterConfigs.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -213,6 +214,7 @@
children = (
5B9771221497927C00791728 /* RSTwitterEngine.h */,
5B9771231497927C00791728 /* RSTwitterEngine.m */,
+ AB31731715106A0B005530E3 /* RSTwitterConfigs.h */,
);
path = Twitter;
sourceTree = "<group>";
@@ -243,7 +245,7 @@
5B9770BA149789C200791728 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0420;
+ LastUpgradeCheck = 0430;
ORGANIZATIONNAME = SharpCube;
};
buildConfigurationList = 5B9770BD149789C200791728 /* Build configuration list for PBXProject "TwitterDemo" */;
View
19 TwitterDemo/Twitter/RSTwitterConfigs.h
@@ -0,0 +1,19 @@
+//
+// RSTwitterConfigs.h
+// TwitterDemo
+//
+// Created by Mugunth Kumar on 14/3/12.
+// Copyright (c) 2012 Steinlogic. All rights reserved.
+//
+
+#ifndef TwitterDemo_RSTwitterConfigs_h
+#define TwitterDemo_RSTwitterConfigs_h
+
+
+#define TW_CONSUMER_KEY @"UOMKm7KaBpIQXWqMRaXwvw"
+#define TW_CONSUMER_SECRET @"CZMJlf2R2ttsg85i1GbaD35Pxs0CzMU5RJECekTw8"
+
+// This will be called after the user authorizes your app
+#define TW_CALLBACK_URL @"http://kulatribe.com/twitter_auth_token"
+
+#endif
View
12 TwitterDemo/Twitter/RSTwitterEngine.h
@@ -28,28 +28,22 @@
@protocol RSTwitterEngineDelegate;
typedef void (^RSTwitterEngineCompletionBlock)(NSError *error);
+typedef void (^RSTwitterEngineStatusChangeHandler)(NSString *newStatus);
@interface RSTwitterEngine : RSOAuthEngine
{
RSTwitterEngineCompletionBlock _oAuthCompletionBlock;
NSString *_screenName;
}
-@property (assign) id <RSTwitterEngineDelegate> delegate;
+@property (nonatomic, copy) RSTwitterEngineStatusChangeHandler statusChangeHandler;
@property (readonly) NSString *screenName;
-- (id)initWithDelegate:(id <RSTwitterEngineDelegate>)delegate;
+- (id)initWithStatusChangedHandler:(RSTwitterEngineStatusChangeHandler) handler;
- (void)authenticateWithCompletionBlock:(RSTwitterEngineCompletionBlock)completionBlock;
- (void)resumeAuthenticationFlowWithURL:(NSURL *)url;
- (void)cancelAuthentication;
- (void)forgetStoredToken;
- (void)sendTweet:(NSString *)tweet withCompletionBlock:(RSTwitterEngineCompletionBlock)completionBlock;
@end
-
-@protocol RSTwitterEngineDelegate <NSObject>
-
-- (void)twitterEngine:(RSTwitterEngine *)engine needsToOpenURL:(NSURL *)url;
-- (void)twitterEngine:(RSTwitterEngine *)engine statusUpdate:(NSString *)message;
-
-@end
View
424 TwitterDemo/Twitter/RSTwitterEngine.m
@@ -24,14 +24,8 @@
// THE SOFTWARE.
#import "RSTwitterEngine.h"
-
-// Never share this information
-#error Put your Consumer Key and Secret here, then remove this error
-#define TW_CONSUMER_KEY @""
-#define TW_CONSUMER_SECRET @""
-
-// This will be called after the user authorizes your app
-#define TW_CALLBACK_URL @"rstwitterengine://auth_token"
+#import "WebViewController.h"
+#import "RSTwitterConfigs.h"
// Default twitter hostname and paths
#define TW_HOSTNAME @"api.twitter.com"
@@ -48,261 +42,285 @@ - (void)removeOAuthTokenFromKeychain;
- (void)storeOAuthTokenInKeychain;
- (void)retrieveOAuthTokenFromKeychain;
+@property (strong, nonatomic) WebViewController *webController;
@end
@implementation RSTwitterEngine
-@synthesize delegate = _delegate;
+@synthesize webController = _webController;
+@synthesize statusChangeHandler = _statusChangeHandler;
#pragma mark - Read-only Properties
- (NSString *)screenName
{
- return _screenName;
+ return _screenName;
}
#pragma mark - Initialization
-- (id)initWithDelegate:(id <RSTwitterEngineDelegate>)delegate
+- (id)initWithStatusChangedHandler:(RSTwitterEngineStatusChangeHandler) handler
{
- self = [super initWithHostName:TW_HOSTNAME
- customHeaderFields:nil
- signatureMethod:RSOAuthHMAC_SHA1
- consumerKey:TW_CONSUMER_KEY
- consumerSecret:TW_CONSUMER_SECRET
- callbackURL:TW_CALLBACK_URL];
-
- if (self) {
- _oAuthCompletionBlock = nil;
- _screenName = nil;
- self.delegate = delegate;
-
- // Retrieve OAuth access token (if previously stored)
- [self retrieveOAuthTokenFromKeychain];
- }
-
- return self;
+ self = [super initWithHostName:TW_HOSTNAME
+ customHeaderFields:nil
+ signatureMethod:RSOAuthHMAC_SHA1
+ consumerKey:TW_CONSUMER_KEY
+ consumerSecret:TW_CONSUMER_SECRET
+ callbackURL:TW_CALLBACK_URL];
+
+ if (self) {
+ _oAuthCompletionBlock = nil;
+ _screenName = nil;
+ self.statusChangeHandler = handler;
+ // Retrieve OAuth access token (if previously stored)
+ [self retrieveOAuthTokenFromKeychain];
+ }
+
+ return self;
}
#pragma mark - OAuth Access Token store/retrieve
- (void)removeOAuthTokenFromKeychain
{
- // Build the keychain query
- NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
- self.consumerKey, kSecAttrService,
- self.consumerKey, kSecAttrAccount,
- kCFBooleanTrue, kSecReturnAttributes,
- nil];
-
- // If there's a token stored for this user, delete it
- CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
- SecItemDelete(query);
- CFRelease(query);
+ // Build the keychain query
+ NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
+ self.consumerKey, kSecAttrService,
+ self.consumerKey, kSecAttrAccount,
+ kCFBooleanTrue, kSecReturnAttributes,
+ nil];
+
+ // If there's a token stored for this user, delete it
+ CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
+ SecItemDelete(query);
+ CFRelease(query);
}
- (void)storeOAuthTokenInKeychain
{
- // Build the keychain query
- NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
- self.consumerKey, kSecAttrService,
- self.consumerKey, kSecAttrAccount,
- kCFBooleanTrue, kSecReturnAttributes,
+ // Build the keychain query
+ NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
+ self.consumerKey, kSecAttrService,
+ self.consumerKey, kSecAttrAccount,
+ kCFBooleanTrue, kSecReturnAttributes,
+ nil];
+
+ CFTypeRef resData = NULL;
+
+ // If there's a token stored for this user, delete it first
+ CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
+ SecItemDelete(query);
+ CFRelease(query);
+
+ // Build the token dictionary
+ NSMutableDictionary *tokenDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ self.token, @"oauth_token",
+ self.tokenSecret, @"oauth_token_secret",
+ self.screenName, @"screen_name",
nil];
-
- CFTypeRef resData = NULL;
-
- // If there's a token stored for this user, delete it first
- CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
- SecItemDelete(query);
- CFRelease(query);
-
- // Build the token dictionary
- NSMutableDictionary *tokenDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- self.token, @"oauth_token",
- self.tokenSecret, @"oauth_token_secret",
- self.screenName, @"screen_name",
- nil];
-
- // Add the token dictionary to the query
- [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:tokenDictionary]
- forKey:(__bridge_transfer NSString *)kSecValueData];
-
- // Add the token data to the keychain
- // Even if we never use resData, replacing with NULL in the call throws EXC_BAD_ACCESS
- query = (__bridge_retained CFDictionaryRef) keychainQuery;
- SecItemAdd(query, (CFTypeRef *) &resData);
- CFRelease(query);
+
+ // Add the token dictionary to the query
+ [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:tokenDictionary]
+ forKey:(__bridge_transfer NSString *)kSecValueData];
+
+ // Add the token data to the keychain
+ // Even if we never use resData, replacing with NULL in the call throws EXC_BAD_ACCESS
+ query = (__bridge_retained CFDictionaryRef) keychainQuery;
+ SecItemAdd(query, (CFTypeRef *) &resData);
+ CFRelease(query);
}
- (void)retrieveOAuthTokenFromKeychain
{
- // Build the keychain query
- NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
- self.consumerKey, kSecAttrService,
- self.consumerKey, kSecAttrAccount,
- kCFBooleanTrue, kSecReturnData,
- kSecMatchLimitOne, kSecMatchLimit,
- nil];
+ // Build the keychain query
+ NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass,
+ self.consumerKey, kSecAttrService,
+ self.consumerKey, kSecAttrAccount,
+ kCFBooleanTrue, kSecReturnData,
+ kSecMatchLimitOne, kSecMatchLimit,
+ nil];
+
+ // Get the token data from the keychain
+ CFTypeRef resData = NULL;
+
+ // Get the token dictionary from the keychain
+ CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
+
+ if (SecItemCopyMatching(query, (CFTypeRef *) &resData) == noErr)
+ {
+ NSData *resultData = (__bridge_transfer NSData *)resData;
- // Get the token data from the keychain
- CFTypeRef resData = NULL;
-
- // Get the token dictionary from the keychain
- CFDictionaryRef query = (__bridge_retained CFDictionaryRef) keychainQuery;
-
- if (SecItemCopyMatching(query, (CFTypeRef *) &resData) == noErr)
+ if (resultData)
{
- NSData *resultData = (__bridge_transfer NSData *)resData;
+ NSMutableDictionary *tokenDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:resultData];
+
+ if (tokenDictionary) {
+ [self setAccessToken:[tokenDictionary objectForKey:@"oauth_token"]
+ secret:[tokenDictionary objectForKey:@"oauth_token_secret"]];
- if (resultData)
- {
- NSMutableDictionary *tokenDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:resultData];
-
- if (tokenDictionary) {
- [self setAccessToken:[tokenDictionary objectForKey:@"oauth_token"]
- secret:[tokenDictionary objectForKey:@"oauth_token_secret"]];
-
- _screenName = [tokenDictionary objectForKey:@"screen_name"];
- }
- }
+ _screenName = [tokenDictionary objectForKey:@"screen_name"];
+ }
}
-
- CFRelease(query);
+ }
+
+ CFRelease(query);
}
#pragma mark - OAuth Authentication Flow
- (void)authenticateWithCompletionBlock:(RSTwitterEngineCompletionBlock)completionBlock
{
- // Store the Completion Block to call after Authenticated
- _oAuthCompletionBlock = [completionBlock copy];
-
- // First we reset the OAuth token, so we won't send previous tokens in the request
- [self resetOAuthToken];
-
- // OAuth Step 1 - Obtain a request token
- MKNetworkOperation *op = [self operationWithPath:TW_REQUEST_TOKEN
- params:nil
- httpMethod:@"POST"
- ssl:YES];
-
- [op onCompletion:^(MKNetworkOperation *completedOperation)
- {
- // Fill the request token with the returned data
- [self fillTokenWithResponseBody:[completedOperation responseString] type:RSOAuthRequestToken];
-
- // OAuth Step 2 - Redirect user to authorization page
- [self.delegate twitterEngine:self statusUpdate:@"Waiting for user authorization..."];
- NSURL *url = [NSURL URLWithString:TW_AUTHORIZE(self.token)];
- [self.delegate twitterEngine:self needsToOpenURL:url];
- }
- onError:^(NSError *error)
- {
- completionBlock(error);
- _oAuthCompletionBlock = nil;
- }];
-
- [self.delegate twitterEngine:self statusUpdate:@"Requesting Tokens..."];
- [self enqueueSignedOperation:op];
+ // Store the Completion Block to call after Authenticated
+ _oAuthCompletionBlock = [completionBlock copy];
+
+ // First we reset the OAuth token, so we won't send previous tokens in the request
+ [self resetOAuthToken];
+
+ // OAuth Step 1 - Obtain a request token
+ MKNetworkOperation *op = [self operationWithPath:TW_REQUEST_TOKEN
+ params:nil
+ httpMethod:@"POST"
+ ssl:YES];
+
+ [op onCompletion:^(MKNetworkOperation *completedOperation)
+ {
+ // Fill the request token with the returned data
+ [self fillTokenWithResponseBody:[completedOperation responseString] type:RSOAuthRequestToken];
+
+ // OAuth Step 2 - Redirect user to authorization page
+ self.statusChangeHandler(@"Waiting for user authorization...");
+ NSURL *url = [NSURL URLWithString:TW_AUTHORIZE(self.token)];
+ [self openURL:url];
+ }
+ onError:^(NSError *error)
+ {
+ completionBlock(error);
+ _oAuthCompletionBlock = nil;
+ }];
+
+ self.statusChangeHandler(@"Requesting Tokens...");
+ [self enqueueSignedOperation:op];
}
- (void)resumeAuthenticationFlowWithURL:(NSURL *)url
{
- // Fill the request token with data returned in the callback URL
- [self fillTokenWithResponseBody:url.query type:RSOAuthRequestToken];
-
- // OAuth Step 3 - Exchange the request token with an access token
- MKNetworkOperation *op = [self operationWithPath:TW_ACCESS_TOKEN
- params:nil
- httpMethod:@"POST"
- ssl:YES];
-
- [op onCompletion:^(MKNetworkOperation *completedOperation)
- {
- // Fill the access token with the returned data
- [self fillTokenWithResponseBody:[completedOperation responseString] type:RSOAuthAccessToken];
-
- // Retrieve the user's screen name
- _screenName = [self customValueForKey:@"screen_name"];
-
- // Store the OAuth access token
- [self storeOAuthTokenInKeychain];
-
- // Finished, return to previous method
- if (_oAuthCompletionBlock) _oAuthCompletionBlock(nil);
- _oAuthCompletionBlock = nil;
- }
- onError:^(NSError *error)
- {
- if (_oAuthCompletionBlock) _oAuthCompletionBlock(error);
- _oAuthCompletionBlock = nil;
- }];
-
- [self.delegate twitterEngine:self statusUpdate:@"Authenticating..."];
- [self enqueueSignedOperation:op];
+ // Fill the request token with data returned in the callback URL
+ [self fillTokenWithResponseBody:url.query type:RSOAuthRequestToken];
+
+ // OAuth Step 3 - Exchange the request token with an access token
+ MKNetworkOperation *op = [self operationWithPath:TW_ACCESS_TOKEN
+ params:nil
+ httpMethod:@"POST"
+ ssl:YES];
+
+ [op onCompletion:^(MKNetworkOperation *completedOperation)
+ {
+ // Fill the access token with the returned data
+ [self fillTokenWithResponseBody:[completedOperation responseString] type:RSOAuthAccessToken];
+
+ // Retrieve the user's screen name
+ _screenName = [self customValueForKey:@"screen_name"];
+
+ // Store the OAuth access token
+ [self storeOAuthTokenInKeychain];
+
+ // Finished, return to previous method
+ if (_oAuthCompletionBlock) _oAuthCompletionBlock(nil);
+ _oAuthCompletionBlock = nil;
+ }
+ onError:^(NSError *error)
+ {
+ if (_oAuthCompletionBlock) _oAuthCompletionBlock(error);
+ _oAuthCompletionBlock = nil;
+ }];
+
+ self.statusChangeHandler(@"Authenticating...");
+ [self enqueueSignedOperation:op];
}
- (void)cancelAuthentication
{
- NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:@"Authentication cancelled.", NSLocalizedDescriptionKey, nil];
- NSError *error = [NSError errorWithDomain:@"com.sharpcube.RSTwitterEngine.ErrorDomain" code:401 userInfo:ui];
-
- if (_oAuthCompletionBlock) _oAuthCompletionBlock(error);
- _oAuthCompletionBlock = nil;
+ NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:@"Authentication cancelled.", NSLocalizedDescriptionKey, nil];
+ NSError *error = [NSError errorWithDomain:@"com.sharpcube.RSTwitterEngine.ErrorDomain" code:401 userInfo:ui];
+
+ if (_oAuthCompletionBlock) _oAuthCompletionBlock(error);
+ _oAuthCompletionBlock = nil;
}
- (void)forgetStoredToken
{
- [self removeOAuthTokenFromKeychain];
-
- [self resetOAuthToken];
- _screenName = nil;
+ [self removeOAuthTokenFromKeychain];
+
+ [self resetOAuthToken];
+ _screenName = nil;
}
#pragma mark - Public Methods
- (void)sendTweet:(NSString *)tweet withCompletionBlock:(RSTwitterEngineCompletionBlock)completionBlock
{
- if (!self.isAuthenticated) {
- [self authenticateWithCompletionBlock:^(NSError *error) {
- if (error) {
- // Authentication failed, return the error
- completionBlock(error);
- } else {
- // Authentication succeeded, call this method again
- [self sendTweet:tweet withCompletionBlock:completionBlock];
- }
- }];
-
- // This method will be called again once the authentication completes
- return;
- }
-
- // Fill the post body with the tweet
- NSMutableDictionary *postParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- tweet, @"status",
- nil];
-
- // If the user marks the option "HTTPS Only" in his/her profile,
- // Twitter will fail all non-auth requests that use only HTTP
- // with a misleading "OAuth error". I guess it's a bug.
- MKNetworkOperation *op = [self operationWithPath:TW_STATUS_UPDATE
- params:postParams
- httpMethod:@"POST"
- ssl:YES];
-
- [op onCompletion:^(MKNetworkOperation *completedOperation) {
- completionBlock(nil);
- } onError:^(NSError *error) {
+ if (!self.isAuthenticated) {
+ [self authenticateWithCompletionBlock:^(NSError *error) {
+ if (error) {
+ // Authentication failed, return the error
completionBlock(error);
+ } else {
+ // Authentication succeeded, call this method again
+ [self sendTweet:tweet withCompletionBlock:completionBlock];
+ }
}];
- [self.delegate twitterEngine:self statusUpdate:@"Sending tweet..."];
- [self enqueueSignedOperation:op];
+ // This method will be called again once the authentication completes
+ return;
+ }
+
+ // Fill the post body with the tweet
+ NSMutableDictionary *postParams = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ tweet, @"status",
+ nil];
+
+ // If the user marks the option "HTTPS Only" in his/her profile,
+ // Twitter will fail all non-auth requests that use only HTTP
+ // with a misleading "OAuth error". I guess it's a bug.
+ MKNetworkOperation *op = [self operationWithPath:TW_STATUS_UPDATE
+ params:postParams
+ httpMethod:@"POST"
+ ssl:YES];
+
+ [op onCompletion:^(MKNetworkOperation *completedOperation) {
+ completionBlock(nil);
+ } onError:^(NSError *error) {
+ completionBlock(error);
+ }];
+
+ self.statusChangeHandler(@"Sending tweet...");
+ [self enqueueSignedOperation:op];
+}
+
+-(void) openURL:(NSURL*) url {
+
+ self.webController = [[WebViewController alloc] initWithURL:url];
+ self.webController.callbackURL = TW_CALLBACK_URL;
+ UIViewController *presentingViewController = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
+ [presentingViewController presentModalViewController:self.webController animated:YES];
+
+ __unsafe_unretained RSTwitterEngine *weakSelf = self;
+
+ self.webController.authenticationCanceledHandler = ^{
+
+ __strong RSTwitterEngine *strongSelf = weakSelf;
+ [presentingViewController dismissModalViewControllerAnimated:YES];
+ [strongSelf cancelAuthentication];
+ };
+
+ self.webController.authenticationCompletedHandler = ^(NSURL* url) {
+
+ __strong RSTwitterEngine *strongSelf = weakSelf;
+ [strongSelf resumeAuthenticationFlowWithURL:url];
+ };
}
@end
View
3 TwitterDemo/ViewController.h
@@ -27,10 +27,9 @@
#import "RSTwitterEngine.h"
#import "WebViewController.h"
-@interface ViewController : UIViewController <RSTwitterEngineDelegate, WebViewControllerDelegate>
+@interface ViewController : UIViewController
@property (strong, nonatomic) RSTwitterEngine *twitterEngine;
-@property (strong, nonatomic) WebViewController *webView;
@property (unsafe_unretained, nonatomic) IBOutlet UITextView *textView;
@property (unsafe_unretained, nonatomic) IBOutlet UIBarButtonItem *sendButton;
View
40 TwitterDemo/ViewController.m
@@ -28,7 +28,6 @@
@implementation ViewController
@synthesize twitterEngine = _twitterEngine;
-@synthesize webView = _webView;
@synthesize textView = _textView;
@synthesize sendButton = _sendButton;
@synthesize statusLabel = _statusLabel;
@@ -44,7 +43,10 @@ - (void)viewDidLoad
{
[super viewDidLoad];
- self.twitterEngine = [[RSTwitterEngine alloc] initWithDelegate:self];
+ self.twitterEngine = [[RSTwitterEngine alloc] initWithStatusChangedHandler:^(NSString *newStatus) {
+
+ self.statusLabel.text = newStatus;
+ }];
// A right swipe on the status label will clear the stored token
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedRight:)];
@@ -97,40 +99,6 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-#pragma mark - RSTwitterEngine Delegate Methods
-
-- (void)twitterEngine:(RSTwitterEngine *)engine needsToOpenURL:(NSURL *)url
-{
- self.webView = [[WebViewController alloc] initWithURL:url];
- self.webView.delegate = self;
-
- [self presentModalViewController:self.webView animated:YES];
-}
-
-- (void)twitterEngine:(RSTwitterEngine *)engine statusUpdate:(NSString *)message
-{
- self.statusLabel.text = message;
-}
-
-#pragma mark - WebViewController Delegate Methods
-
-- (void)dismissWebView
-{
- [self dismissModalViewControllerAnimated:YES];
- if (self.twitterEngine) [self.twitterEngine cancelAuthentication];
-}
-
-- (void)handleURL:(NSURL *)url
-{
- [self dismissModalViewControllerAnimated:YES];
-
- if ([url.query hasPrefix:@"denied"]) {
- if (self.twitterEngine) [self.twitterEngine cancelAuthentication];
- } else {
- if (self.twitterEngine) [self.twitterEngine resumeAuthenticationFlowWithURL:url];
- }
-}
-
#pragma mark - Custom Methods
- (void)swipedRight:(UIGestureRecognizer *)recognizer
View
18 TwitterDemo/WebViewController.h
@@ -25,24 +25,12 @@
#import <UIKit/UIKit.h>
-@protocol WebViewControllerDelegate;
-
@interface WebViewController : UIViewController <UIWebViewDelegate>
-@property (retain, nonatomic) NSURL *currentURL;
+@property (strong, nonatomic) NSString *callbackURL;
-@property (assign, nonatomic) id <WebViewControllerDelegate> delegate;
-@property (unsafe_unretained, nonatomic) IBOutlet UIWebView *webView;
-@property (unsafe_unretained, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
+@property (nonatomic, copy) void (^authenticationCompletedHandler)(NSURL *url);
+@property (nonatomic, copy) void (^authenticationCanceledHandler)();
- (id)initWithURL:(NSURL *)url;
-- (IBAction)cancelAction:(id)sender;
-
-@end
-
-@protocol WebViewControllerDelegate <NSObject>
-
-- (void)dismissWebView;
-- (void)handleURL:(NSURL *)url;
-
@end
View
88 TwitterDemo/WebViewController.m
@@ -26,90 +26,108 @@
#import "WebViewController.h"
#import "AppDelegate.h"
+// Private Methods
+// this should be added before implementation
+@interface WebViewController (/*Private Methods*/)
+@property (retain, nonatomic) NSURL *currentURL;
+@property (unsafe_unretained, nonatomic) IBOutlet UIWebView *webView;
+@property (unsafe_unretained, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
+
+- (IBAction)cancelAction:(id)sender;
+@end
+
@implementation WebViewController
-@synthesize delegate = _delegate;
@synthesize currentURL = _currentURL;
@synthesize webView = _webView;
@synthesize activityIndicator = _activityIndicator;
+@synthesize callbackURL = _callbackURL;
+
+@synthesize authenticationCompletedHandler = _authenticationCompletedHandler;
+@synthesize authenticationCanceledHandler = _authenticationCanceledHandler;
#pragma mark - Initialization
- (id)initWithURL:(NSURL *)url
{
- self = [self initWithNibName:@"WebViewController" bundle:nil];
-
- if (self) {
- self.currentURL = url;
- self.delegate = nil;
- }
-
- return self;
+ self = [self initWithNibName:@"WebViewController" bundle:nil];
+
+ if (self) {
+ self.currentURL = url;
+ }
+
+ return self;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
- [super viewDidLoad];
-
- self.webView.scalesPageToFit = YES;
- [self.webView loadRequest:[NSURLRequest requestWithURL:self.currentURL]];
+ [super viewDidLoad];
+
+ self.webView.scalesPageToFit = YES;
+ [self.webView loadRequest:[NSURLRequest requestWithURL:self.currentURL]];
}
- (void)viewDidUnload
{
- [self setWebView:nil];
- [self setActivityIndicator:nil];
-
- [super viewDidUnload];
+ [self setWebView:nil];
+ [self setActivityIndicator:nil];
+
+ [super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - UIWebView Delegate Methods
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
- if ([request.URL.scheme isEqualToString:@"rstwitterengine"] && (self.delegate)) {
- if (self.activityIndicator) [self.activityIndicator stopAnimating];
- [self.delegate handleURL:request.URL];
- return NO;
+ if ([[request.URL absoluteString] rangeOfString:@"http://kulatribe.com/twitter_auth_token"].location != NSNotFound) {
+
+ if (self.activityIndicator) [self.activityIndicator stopAnimating];
+
+ if ([request.URL.query hasPrefix:@"denied"]) {
+ self.authenticationCanceledHandler();
} else {
- return YES;
- }
+ self.authenticationCompletedHandler(request.URL);
+ }
+ return NO;
+ } else {
+ return YES;
+ }
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
- if (self.activityIndicator) [self.activityIndicator startAnimating];
+ if (self.activityIndicator) [self.activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
- if (self.activityIndicator) [self.activityIndicator stopAnimating];
+ if (self.activityIndicator) [self.activityIndicator stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
- if (self.activityIndicator) [self.activityIndicator stopAnimating];
-
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
- message:[error localizedDescription]
- delegate:nil
- cancelButtonTitle:@"Dismiss"
- otherButtonTitles:nil];
- [alert show];
+ if (self.activityIndicator) [self.activityIndicator stopAnimating];
+
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
+ message:[error localizedDescription]
+ delegate:nil
+ cancelButtonTitle:@"Dismiss"
+ otherButtonTitles:nil];
+ [alert show];
}
#pragma mark - Custom Methods
- (IBAction)cancelAction:(id)sender
{
- if (self.delegate) [self.delegate dismissWebView];
+ self.authenticationCanceledHandler();
}
@end

0 comments on commit b0e80aa

Please sign in to comment.