orientation issue on rotation in ios 8 when dismissViewControllerAnimated - objective-c

I am using mobiscan library for scan barcode. After complete barcode scanning I dismiss the current screen and force rotate to portrait mode. At some moment a blank screen appear for some seconds and then display properly. This issue is generate only in ios 8. It's working fine in ios 7. This issue is generate only when scan barcode in landscape mode.
Here are the code and snap of the issue which can generate in my app.
if(![UICommonUtils isiPad]) {
// Force the iPhone or iPod to display the TableViewController in portrait mode.
if (![self.presentedViewController isBeingDismissed])
{
UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
UIViewController *c = [[[UIViewController alloc] init] autorelease];
[c.view setBackgroundColor:[UIColor clearColor]];
[self presentViewController:c animated:NO completion:^{
// Made changes for Issue#2 (When Compiler level flag -DUSE_AUTOLAYOUT=0) as per iOS8 Competibility.
if([UICommonUtils checkIfiOS8])
{
[self performSelector:#selector(dismissSheet) withObject:nil afterDelay:0];
}
else
{
[self dismissViewControllerAnimated:NO completion:nil];
}
}];
}
}
}
-(void)dismissSheet
{
[self dismissViewControllerAnimated:NO completion:nil];
}
Any solution How can I fix it?

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;
}

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 ;-)

Pop up UIViewController with an IBAction UIViewController

Is it possible to pop up an UIViewController (xib file) like UIPopOverControl in iPad ?
I have a separate NIB file which is linked to an UIViewController. I want to popup that NIB file along with the button pressed with a customised size (200,200).
Is this possible?
I am trying to get something like this on the iPhone - http://www.freeimagehosting.net/c219p
You can also use one of these custom made clases to show a popup:
https://github.com/sonsongithub/PopupView
https://github.com/werner77/WEPopover
https://github.com/50pixels/FPPopover
Example with FPPopover:
//the view controller you want to present as popover
YourViewController *controller = [[YourViewController alloc] init];
//our popover
FPPopoverController *popover = [[FPPopoverController alloc] initWithViewController:controller];
//the popover will be presented from the okButton view
[popover presentPopoverFromView:okButton];
//release if you arent using ARC
[controller release];
yes it is. load Your pOpOver controller lazily at the point when it is needed. add its view as a subview (you could animate the addition). make its frame size what You need and add the image You have shown as a background subview of the pOpOver controller along with other controls You want in the pop up.
good luck
UPDATE:
alright, ii will show You how ii do this in my app Lucid Reality Check (deployment target iOS4.3).
one can use a UIPopoverController to present another controllers view. what ii do first is to make sure ii always know the current orientation of the device, so ii can reposition the popup on rotation (maybe this works by itself on iOS6?). so in my base controller (from where ii want to show a popup) ii have an instance variable like this:
UIInterfaceOrientation toOrientation;
and also:
UIPopoverController *popover;
UIButton *popover_from_button;
BOOL representPopover;
popover will be reused for all popups, and popover_from_button will hold the button from which the popup is initiated.
then the next code comes into the base controller:
- (void)popoverWillRotate {
if ([popover isPopoverVisible]) {
[self dismissPopover];
representPopover = YES;
}
}
- (void)popoverDidRotate {
if (popover && representPopover) {
representPopover = NO;
[self representPopover];
}
}
these two methods have to be called every time the device is rotated, like this:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//DLOG(#"willRotateTo %i", toInterfaceOrientation);
toOrientation = toInterfaceOrientation;
if ([Kriya isPad ]) {
[self popoverWillRotate];
}
}
as one can see, first the orientation is captured then popoverWillRotate is called. this would hide the popover during the orientation animation. and after rotating, the popover must be redisplayed like this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
//DLOG(#"didRotateFrom %i", fromInterfaceOrientation);
//[self layout:toOrientation]; //do some layout if You need
if ([Kriya isPad]) {
[self popoverDidRotate];
}
}
- (void)layout:(UIInterfaceOrientation)toInterfaceOrientation {
//one can do view layout here, and call other controllers to do their layout too
}
now that the orientation changes are worked out, the code for presenting the popover arrives here:
#pragma mark Popovers
- (void)presentPopoverWith:(id)controller fromButton:(UIButton*)button {
if (popover)
[popover release];
if (popover_from_button)
[popover_from_button release];
popover_from_button = [button retain];
popover = [[UIPopoverController alloc] initWithContentViewController:controller];
[popover setDelegate:self];
[self representPopover];
}
- (void)representPopover{
if (popover) {
UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
UIViewController *vc = (UIViewController*)[popover contentViewController];
CGSize contentSize = [vc contentSizeForViewInPopover];
if (contentSize.width > 0 && contentSize.height > 0) {
[popover setPopoverContentSize:contentSize animated:NO];
}
//DLOG(#"representPopover rect:%#", [Kriya printRect:popover_from_button.frame]);
[popover presentPopoverFromRect:CGRectOffset(popover_from_button.frame, 0, popover_from_button.frame.size.height + 7.0) inView:self.view permittedArrowDirections:arrowDirection animated:YES];
}
}
- (void)dismissPopover {
if (popover) {
[popover dismissPopoverAnimated:YES];
}
}
finally, if one wants to be notified when the popover is dismissed, the base controller must implement a delegate method:
#pragma mark UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
//do something important here like drink some water
}
and don't forget to make the base controller a UIPopoverControllerDelegate in its header.
a use case for this way of doing popups would then look like this:
- (void)takeImage {
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
[picker setDelegate:self];
[picker setAllowsEditing:NO];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
if ([Kriya isPad]) {
[self presentPopoverWith:picker fromButton:backgroundImageButton];
} else {
//modals on iPhone/iPod
//DLOG(#"takeImage addSubview picker");
[self presentModalViewController:picker animated:YES];
}
} else {
//DLOG(#"no camera");
}
}
this would use an image picker as the content for the popup, but one can use any controller with a valid view. so just do this:
[self presentPopoverWith:popupsContentController fromButton:tappedButton];
one should not have any missing information, :), the method [Kriya isPad] is just this:
+ (BOOL)isPad {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
// iPad capable OS
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//this is an iPad
return YES;
}else {
//this is an iPod/iPhone
return NO;
}
#else
//can not pissible be iPad
return NO;
#endif
}
ENJOY!

Making a UIViewController a UIImagePicker when tapped

I have an app that uses the UITabBarController and one of the tabs is supposed to be a full on camera view (similar to Instagram). When I launch the app and go to that view, most of the screen is blank and no image library picker/camera view loads. Any help would be greatly appreciated.
Here is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
imagePicker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
[imagePicker setDelegate:self];
[imagePicker setEditing:NO];
// Place image picker (camera viewing angle on the screen)
[self presentViewController:imagePicker animated:YES completion:nil];
}
Try putting that code in viewDidAppear instead -- that worked for me. Better yet, would be to put all but the last line in viewDidLoad, so it's only called once, and just put the last line in the viewDidAppear method. When you cancel the image picker (the only thing I tested), it will just reappear, since viewDidAppear will be called again, so you need to implement imagePickerControllerDidCancel: like this to keep that from happening:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:nil];
self.imagePicker = nil;
}
And, in your viewDidAppear, put in an if statement to see if the picker exists before trying to present it:
if (self.imagePicker) {
[self presentViewController:self.imagePicker animated:YES completion:nil];
}