Can't beginReceivingRemoteControlEvents in iOS - objective-c

In my app i want let user to control audio playback in background. I set backGround modes in .plist, and in plays in bg just like i wanted.But i can't get any response from touching the control buttons.
I set the AudioSession like this
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance]setActive:YES error:nil];
Then, in viewContoller where my player is placed i beginReceivingRemoteControlEvents like this
if ([[UIApplication sharedApplication] respondsToSelector:#selector(beginReceivingRemoteControlEvents)]){
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
[self becomeFirstResponder];
NSLog(#"Responds!");
}
And it prints Responds!
But the problem is that this method is never called
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
NSLog(#"Where is my event?");
if(event.type == UIEventTypeRemoteControl)
{
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
NSLog(#"Pause");
[self playWords:playButton];
break;
case UIEventSubtypeRemoteControlNextTrack:
NSLog(#"Next");
[self next];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
NSLog(#"Prev");
[self prev];
break;
}
}
I even tried to write a category on UIApplication to let it become the first responder, but it doesn't help
#implementation UIApplication (RemoteEvents)
-(BOOL)canBecomeFirstResponder
{
return YES;
}
#end
Why can this happen?
SOLUTION
Here's what solved my problem Entering background on iOS4 to play audio

I have done the same work in my project, it's working fine. Please follow this, perhaps it will help you. Change the event name etc. In my code _audio is the object of AVAudioPlayer.
- (void)viewDidLoad {
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryErr];
[[AVAudioSession sharedInstance] setActive: YES error: &activationErr];
}
- (void)viewWillAppear {
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
switch (event.subtype) {
case UIEventSubtypeRemoteControlPlay:
[_audio play];
break;
case UIEventSubtypeRemoteControlPause:
[_audio pause];
break;
default:
break;
}
}

There is a newer mechanism for listening to remote control events. For example, to execute a block when the headphone play/pause button is pressed:
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
NSLog(#"toggle button pressed");
return MPRemoteCommandHandlerStatusSuccess;
}];
or, if you prefer to use a method instead of a block:
[commandCenter.togglePlayPauseCommand addTarget:self action:#selector(toggleButtonAction)];
To stop:
[commandCenter.togglePlayPauseCommand removeTarget:self];
or:
[commandCenter.togglePlayPauseCommand removeTarget:self action:#selector(toggleButtonAction)];
You'll need to add this to the includes area of your file:
#import MediaPlayer;
For it to work in the background, you must have the background audio mode added to your app's capabilities.

Review this sample code from Apple for an example of usage. Likely your primary view controller is not actually becoming the first responder. An alternative usage is to place this code in your Application Delegate (which will always be the first responder) and respond to these events before they have had a chance to propagate, and potentially be consumed by other responders.

You have
respondsToSelector:#selector(beginReceivingRemoteControlEvents)]){
but in the method signature you have
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
The place where you are registering the signature is wrong. Just replace it by
respondsToSelector:#selector(beginReceivingRemoteControlEvents:)]){
You are missing the : which is making the app send the even to a non existing method I am assuming. I am surprised that your app is not crashing.

Related

Setting object to nil iOS7 vs iOS8

WI have an iPad kiosk app that displays videos on an external monitor connected to the iPad via HDMI. I have a viewController that manages the view on the external monitor. When I am done playing back a video I nil out the MPMoviePlayerController instance. In iOS7 this works fine, but in iOS8 I get a hard crash after setting the moviePlayer to nil.
- (void)removeMoviePlayer {
[self.moviePlayerController.view removeFromSuperview];
[self removeMovieNotificationHandlers];
self.moviePlayerController = nil;}
With Zombies enabled I get a message in the debugger:
[MPAVController release]: message sent to deallocated instance
Again, this crash does not happen when the app runs under iOS7. What has changed that is causing this crash?
After a couple days of trial and error I discovered that when trying to nil out the MPMoviePlayerController instance when the MPMoviePlayerPlaybackState was MPMoviePlaybackStatePaused, the app would crash. When a video reaches the end, the MPMoviePlayerController sends a MPMoviePlaybackDidFinish notification that reports the playback state as MPMoviePlaybackStatePaused. The fix was to test for playback state and if paused call [MPMoviePlayerController stop]. That changes the MPMoviePlaybackState to MPMoviePlaybackStateStopped, and you can then nil out the instance without a crash.
This crash did not happen before iOS 8. Code below:
-(void)moviePlayBackDidFinish:(NSNotification *)notification {
[self stopVideo:notification];
}
- (void)stopVideo:(NSNotification *)notification {
if (self.moviePlayerController) {
if (self.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying || self.moviePlayerController.playbackState == MPMoviePlaybackStatePaused) {
[self.moviePlayerController stop];
}
[self cleanUpVideo];
}
}
- (void)cleanUpVideo {
[self killProgressTimer];
[UIView animateWithDuration:1.0f animations:^{
self.closedCaptionLabel.alpha = 0.0f;
self.moviePlayerController.view.alpha = 0.0f;
self.backgroundImageView.alpha = 1.0f;
} completion:^(BOOL finished) {
[self removeMoviePlayer];
[self resetClosedCaptions];
[self.delegate videoDidStop];
}];
}
- (void)removeMoviePlayer {
[self.moviePlayerController.view removeFromSuperview];
[self removeMovieNotificationHandlers];
self.moviePlayerController = nil;
}

ios8 iPad uiwebview crashes while displaying popover when user taps drop down list HTML select tag

On ios8 and iPad if a uiwebview is displaying a HTML page containing a drop down list
eg this page http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select
then
repeatedly tap on the HTML drop down list that contain lists of cars . first item is Volvo.
tap every 1/2 second or so that uipopover opens and closes
app will crash:
Terminating app due to uncaught exception 'NSGenericException',
reason: 'UIPopoverPresentationController
() should have a non-nil
sourceView or barButtonItem set before the presentation occurs.'
Is there anyway to work around this in uiwebview in ios8?
It doesn't happen using wkwebview, but I would like to fix it in uiwebview.
Update: This seems to help but unsure of side effects. I have overridden the following in the view controller that contains the uiwebview.
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
if (completion)
{
completion();
}
[super dismissViewControllerAnimated:NO completion:nil];
}
The solution mentioned in the question did not help me, however it did point me in the right direction.
After some investigation I would say it's some sort of race condition between presenting and removing the popover. As a workaround you can postpone the presentation in the delegate of the UIWebView:
-(void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_USEC), dispatch_get_main_queue(),
^{
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
});
}
The previous solutions did not help me.
There is a bug already logged to Apple (see openradar) for this.
The issue seems to be that the web view tries to present a view controller in a popover without setting the sourceView of the popover. Although it's definitely an Apple issue I have used the following workaround to avoid my app to crash:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
// Override this method in the view controller that owns the web view - the web view will try to present on this view controller ;)
if (viewControllerToPresent.popoverPresentationController && !viewControllerToPresent.popoverPresentationController.sourceView) {
return;
}
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
I worked around it in the following way after noticing that sourceView is set in the cases where it crashes:
-(void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
UIPopoverPresentationController* pres = viewControllerToPresent.popoverPresentationController;
if(pres.sourceView) {
//log the fact you are ignoring the call
}
else {
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
}
I had different exception in the same scenario, and none of workarounds from here helped me.
This was my exception:
Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (4) beyond bounds (0) for section (0).'
This is code I used to workaround it:
-(void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
if ([viewControllerToPresent respondsToSelector:NSSelectorFromString(#"_cachedItems")]) {
if([viewControllerToPresent valueForKey:#"_cachedItems"] == nil) {
if (completion != nil) {
completion();
}
return;
}
}
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
It's very nasty workaround that prevents from showing dropdown in cases when it's about to crash, and this solution can stop working in any time as it uses internal properties. However it was the only solution that worked for me so maybe it will be helpful for someone.
I have decreased the probability of occurrence of crash in this way..
Used javascript code and native ios
Web Side code changes
Register a 'click' event listener to your html component(drop down).
In the call back method send notification to native code. ex : "window.location='fromJavaScript://PopoverIssue'; "
It will call uiwebviews shouldStartLoadWithRequest
Native Side code changes
Implement UIPopoverPresentationControllerDelegate protocol on viewcontroller which has uiwebview and over ride popoverPresentationControllerShouldDismissPopover popoverPresentationControllerDidDismissPopover
put below code in shouldStartLoadWithRequest method of uiwebview for the above click notification
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
self.popoverPresentationController = self.presentedViewController.popoverPresentationController;
self.existedPopoverDelegate = [self.popoverPresentationController delegate];
self.popoverPresentationController.delegate = self;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
int64_t delay = 2.0;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
if([[UIApplication sharedApplication] isIgnoringInteractionEvents])
{
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
});
});
implement the overridden protocol methods as follows
(BOOL)popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
[self.existedPopoverDelegate popoverPresentationControllerShouldDismissPopover:popoverPresentationController];
return YES;
}
(void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
[self.existedPopoverDelegate popoverPresentationControllerDidDismissPopover:popoverPresentationController];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
int64_t delay = 2.0;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
if([[UIApplication sharedApplication] isIgnoringInteractionEvents])
{
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
});
});
}
Hope it will help to decrease the crash occurrence .

MPMediaPickerController - iOS7

I developed test application on iOS 7 that pick the music from music library using MPMediaPickerController.
But when I present the media picker controller,it shows empty screen.
This is the code
(void) pickSong
{
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = NO;
mediaPicker.prompt = NSLocalizedString(#"Select Your Favourite Song!", nil);
[mediaPicker loadView];
[self.navigationController presentViewController:mediaPicker animated:YES completion:nil];
}
#pragma mark - MPMediaPickerController delegate
(void) mediaPicker:(MPMediaPickerController *) mediaPicker2 didPickMediaItems:(MPMediaItemCollection *) mediaItemCollection {
[self dismissViewControllerAnimated:YES completion:nil];
MPMediaItem *mediaItem = [[mediaItemCollection items] objectAtIndex:0];
self.item.soundName = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
self.item.soundUrl = [[mediaItem valueForProperty:MPMediaItemPropertyAssetURL] absoluteString];
}
(void) mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker{
[self dismissViewControllerAnimated:YES completion:NULL];
}
Please help me out.
This is an iOS bug, but it only occurs when running a 32 bit build on a 64 bit (A7) device (Only iPhone 5S for now). To work around it, add a 64 bit architecture to your app. (Open build settings in xcode, and change Architecture from $ARCHS_STANDARD to $ARCHS_STANDARD_INCLUDING_64_BIT.) You will then probably need to fix a number of compile, link and runtime issues. See Apple's 64-Bit Transition Guide.
Seems like there is a bug in ios7 where it doesn't like to be presented inside a uinavigation controller - try presenting it directly from a view controller.
I had the same problem and for me the solution was a combination of two of the solutions presented here. First I had to convert my app to be 64-bit ready by changing Architectures to "standard... (including 64-bit)". Once I corrected all the warnings that caused, I had to change the MPMediaPickerController to be presented modally rather than on the navigation stack:
- (IBAction)didSelectMusicPicker:(id)sender {
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker.delegate = self;
picker.allowsPickingMultipleItems = YES;
picker.prompt = NSLocalizedString (#"Add songs to play", "Prompt in media item picker");
//[self.navigationController pushViewController:picker animated:YES];
[self presentViewController:picker animated:TRUE completion:NULL];
}
Of course, I also needed to change mediaPicker:didPickMediaItems: and mediaPickerDidCancel: to use dismissViewControllerAnimated. Once all that was fixed, the picker worked as expected on both iPhone 4 and iPhone 5S running iOS 7.
a thought: is the presented screen completely empty, or are you getting the navigation bar at the bottom but with no tracks listed? I've noticed that as of iOS 7 the picker now defaults to opening to the Playlist tab (it used to open to Albums, if I recall)… if you have no playlists on the device that would account for the empty screen…
I can see the list of songs and select the songs. But I cannot dismiss the view controller on pressing "Done". I've tried PresentViewController since Modal controller is deprecated.
- (IBAction) showMediaPicker: (id) sender {
picker =
[[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio];
picker.delegate = self;
picker.allowsPickingMultipleItems = YES;
picker.prompt = NSLocalizedString (#"AddSongsPrompt", #"Prompt to user to choose some songs to play");
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated:YES];
[self.picker removeFromParentViewController];
[self presentViewController:picker animated:YES completion:nil];
// [picker release];
}
// Responds to the user tapping Done after choosing music.
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection {
[self.picker removeFromParentViewController];
[self dismissViewControllerAnimated:YES completion:nil];
//
[self.delegate updatePlayerQueueWithMediaCollection: mediaItemCollection];
// [self.mediaItemCollectionTable reloadData];
// [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated:YES];
}
I've tried RemovefromSuperview also, nothing seems to work. I'm testing this on an iPhone 6 simulator and an iPhone 5 with iOS 8.1.3.
Anyone???
I also have the same problem before. But I found out just need to restart the device after upgrade. The music picker appear again.

iOS 6 Orientation rotate automatically back to portrait on pressing done on MoviePlayer

I am using MoviePlayer controller to play a video in my iOS app. I am using orientation notification like this
if(deviceOrientation ==UIDeviceOrientationLandscapeLeft)
{
NSLog(#"Replay is in Landscape");
self.fullScreenFlag = YES;
[self.moviePlayer setFullscreen:YES animated:NO];
}
This makes my video screen to play in full screen when user turns the phone to landscape orientation. But when I press done button on moviePlayer control I go into following method
- (void)movieWillExitFullscreen:(NSNotification*)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if(deviceOrientation ==UIDeviceOrientationLandscapeLeft) {
NSLog(#"Pressed Done in Landscape");
//Problem: Here I want to force my VideoViewController to rotate back to portrait Mode
}
}
Not sure how can I make the VC to go back to portrait as soon as user pressed done button or video stops playing. I am aware to the moviePlayerNotificationMethods but what should I call in those method for orientation is not clear.
I solved this issue by having a separate view controller for the video playback.
So, you would have two view controllers
SomeViewController
MoviePlayerViewController
In your SomeViewController, when you want to play the movie:
MoviePlayerViewController *vc = [[MoviePlayerViewController alloc] initWithNibName:#"MoviePlayerViewController" bundle:nil];
[vc setPathToMovie:path];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
And then in your MoviePlayerViewController
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
[[self navigationController] popViewControllerAnimated:YES];
}
You can then lock down your SomeViewController to portrait, and if the user is in landscape when watching the video, they will return to portrait when popping back to SomeViewController.
I never found a solution using the deviceOrientation method and a modal MPMoviePlayerController. There may be one though!
I solved this by doing this in "moviePlayBackDidFinish"
UIViewController* forcePortrait = [[UIViewController alloc] init];
[self presentViewController:forcePortrait animated:NO completion:^{
[forcePortrait dismissViewControllerAnimated:NO completion:nil];
}];
It's not beautiful but it works like a charm :-)
Depending upon whether you using MPMoviePlayerController within a ViewController or as a separate ViewController the answer is as follows :-
Firstly :- This link will explain you how to restrict some views to portrait and allow others to rotate?
In that link you will see that, in the NavigationViewController you have made, following changes:-
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
What it does is, it give the child to make their own decision if they want to auto-rotate or not.
Next the ViewController containing your MoviePlayer should do this :-
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Once you have done this, it gives the power of AutoRotation to your ViewController.
Now here's the tricky part, see I assume that you might have restricted your ViewController to Portrait, and since movie player allows you go fullscreen and in fullscreen when you rotate your screen it will turn to landscape, and now if you press done button it won't turn to portrait rather it will exit the fullscreen in landscape itself. In this case what you should do is, in your:-
- (BOOL)shouldAutorotate
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft) {
if ([[[self.navigationViewController.viewControllers] lastObject] class] == [MoviePlayerViewController class] ) {
return YES;
}
return NO;
}
return NO;
}
So, what it does is, you should auto-rotate only when the orientation is landscape and not when its portrait.
So far so good, next comes the MoviePlayer, considering that you have already played the Video and your only interest is when we click "Done" button it should auto-rotate to portrait.
Register for a notification to your MoviePlayer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerWillExitFullScreen:) name:MPMoviePlayerWillExitFullscreenNotification object:_moviePlayer];
Then in the selector:
- (void) moviePlayerWillExitFullScreen:(NSNotification*)notification{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerWillExitFullscreenNotification object:_moviePlayer];
}
Tada! the magic is done! try out let me know ;-)

Request for member 'pin' in something is not a structure or union. MGTwitterEngine [duplicate]

I am developing a iPhone application which sends tweets to twitter. For this I am using SA_OAuthTwitterEngine + MGTwitterEngine classes.
I register applicaiton to www.twitter.com/apps and pass Consumer key and Consumer secret to controller my code is this.
if(!_engine){
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey = slPcFUjUh5y1hex0zvEhPg;
_engine.consumerSecret = u6ydovMdP9yeiVqDukVhIzZPgJR9XDPUwfxymzNs;
}
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
if (controller){
[self presentModalViewController: controller animated: YES];
intTwitterFlag = 1;
}
Previously on twitter.com/apps I select Application type = client and my application will generate PIN and accessToken. But when i change my Application type = Browser it cannot generate PIN and accessToken.
Previously when application type is client i am giving user name and password and then control return to my application from the webview but now after entering user name and password it cannot dismissModalViewController but showing Select and Copy the PIN.
Thank you for your time and any help you can give me!
Here it is:just replace the method in SA_OAuthTwitterController.m:
- (void) webViewDidFinishLoad: (UIWebView *) webView {
_loading = NO;
//[self performInjection];
if (_firstLoad) {
[_webView performSelector: #selector(stringByEvaluatingJavaScriptFromString:) withObject: #"window.scrollBy(0,200)" afterDelay: 0];
_firstLoad = NO;
} else {
/*
NSString *authPin = [self locateAuthPinInWebView: webView];
NSLog(#"authPin: %#", authPin);
if (authPin.length) {
[self gotPin: authPin];
return;
}
NSString *formCount = [webView stringByEvaluatingJavaScriptFromString: #"document.forms.length"];
if ([formCount isEqualToString: #"0"]) {
[self showPinCopyPrompt];
}*/
//*****************************************************
// This is to bypass the pin requirement
// in case the call back URL is set in Twitter settings
//*****************************************************
[_engine requestAccessToken];
if ([_delegate respondsToSelector: #selector(OAuthTwitterController:authenticatedWithUsername:)])
{
[_delegate OAuthTwitterController: self authenticatedWithUsername: _engine.username];
}
[self performSelector: #selector(dismissModalViewControllerAnimated:) withObject: (id) kCFBooleanTrue afterDelay: 1.0];
//[self dismissModalViewControllerAnimated:YES];
}
[UIView beginAnimations: nil context: nil];
_blockerView.alpha = 0.0;
[UIView commitAnimations];
if ([_webView isLoading]) {
_webView.alpha = 0.0;
} else {
_webView.alpha = 1.0;
}
}
I too faced the same issue, and i just removed callback url from the twitter app settings. For my surprise login proceeds without any issue.
The replacement for this method
(void) webViewDidFinishLoad: (UIWebView *) webView
in the class SA_OAuthTwitterController.m works well.
Its better to use xAuth route for mobile apps
http://dev.twitter.com/pages/xauth
check XAuthTwitterEngine which implements xauth for the MGTwitterEngine