iPad App Crashes on Orientation change - ios

I am developing an iPad app. I allow both landscape and portrait mode. My UI is fine in portrait mode but when I change it to landscape mode, my UI gets messed up. I saw some SO posts related to this and I added following code in initWith... in my UIView.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(abc)
name:UIDeviceOrientationDidChangeNotification
object:nil];
My UI is working fine in portrait mode after doing this. When I change it to landscape mode, my UI is fine. But after I change it back into portrait mode, my app crashes. I read some posts on SO related to app crashing an got to know about instruments. I enabled zombies and found that a message is being sent to already released object and this message is coming from NSNotificationCenter.
Is there something else that I need to handle apart from registering my device ? Also, is there any way where in I can change the implementation from UIView to UIViewController and implement the methods that UIViewController has regarding device orientation ? Please let me know the steps I need to follow in order to get this done. Thanks!

Where are you registering for the notifications? You need to remove the observer when you are about to change orientations (either in prepForSegue or willAnimateRotationToInterfaceOrientation depending on however you've got your setup) in order prevent messaging a no longer valid object. You also don't want to pile up several notifications if your registering in viewDidAppear/viewWillAppear.
Remove the observer using:
[[NSNotificationCenter defaultCenter] removeObserver:self];//removes all notifications for that object (the way I've used it before)
or if you want to be specific, do something like:
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice];//remove just that notification

The UIViewController class has several methods that deal with changes in orientation. See the docs for a discussion of those methods.
One method you should look into is viewWillLayoutSubviews. This is a common place to perform manual view layout. This is called anytime the view controller's orientation changes.
Using these methods is much more common than registering for device orientation change notifications. Based on your statements about the crash, a possible issue is that you never remove the observer that you add. For every call to addObserver there must be a corresponding call to removeObserver. Otherwise the observer is called even if it has long gone away. And this results in the crash you describe.

Related

Fixed video capture orientation for RTCMTLVideoView webrtc

I have an iOS app that only supports portrait when rotating the device the video captured by the RTCMTLVideoView rotates to landscape orientation, even when the rest of the UI stays in portrait.
So far the only solution that I found is to listen for the UIDeviceOrientationDidChangeNotification notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
and disabling it
- (void)orientationChanged:(NSNotification *)notification{
NSLog(#"orientation changed");
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
Is there any way to prevent this behaviour and keep it locked to portrait without this ugly workaround?
The problem in my case was that the video captured with the front camera was no mirrored.
I fixed the issue flipping the RTCMTLVideoView
self.myRTCMTLVideoView.transform = CGAffineTransformMakeScale(-1.0, 1.0)
The answer assumes usage of the latest stable M70 branch of WebRTC at the moment, as it's a moving target and API of its internal classes changes frequently.
Looks like RTCMTLVideoView is still work in progress and doesn't handle all scenarios appropriately. It has a rotationOverride property, but no documentation or example on how to use it. There is a similar question on Google Groups, which hasn't yet received attention, I encourage you to participate in discussion there, so WebRTC developers would know about that issue relevancy and made actions to fix it.
In the meantime, I suggest to switch to RTCEAGLVideoView which should work fine in that case.

Is applicationDidBecomeActive called in every app?

I'm making a jailbreak tweak for my iOS device and have run into a problem regarding application bundleIDs and multitasking.
I currently have it set up so that when an application icon is tapped, it grabs the application ID and stores it for later. I needed to get this for multitasking so I tried applicationDidBecomeActive with no luck as it was never called when I thought it would be. Is there any way to tell when an application loads from multitasking and/or app switching?
You can register notification in your viewDidLoad:
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(selectorYouWant)
name:UIApplicationDidBecomeActiveNotification
object:nil];
Here are all the UIApplicationDelegate methods that may be called. Upon first launch application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: will be called when initially loading the app when it is launching for the first time/is no longer in memory. As for becoming active while still in memory I would recommend you use applicationWillEnterForeground:.

Is it possible that NSNotificationCenter doesn't work on certain devices?

Am using NSNotificationCenter in my iPhone App to post a notification
// I add an observer in didFinishLanchingWithOptions() in the AppDelegate
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(getData:) name:kNotif_GetData object:nil];
....
....
// then in another method, I post the notification
[[NSNotificationCenter defaultCenter] postNotificationName:kNotif_GetData object:nil];
....
One user says that this functionality (which is executed by getData()) is not working. so that might mean that the notification hasn't gotten fired. Any idea why this might happen? When I test it with different devices, it works perfect. The user uses iPhone5 and iOS7. Is there any more setting or any explicit user setting which is needed or which could turn this on/off?
No, notification centre is reliable.
"Not working" is not enough information to diagnose the problem. Get more information from the user or add more logging so that you know what is actually going on.

Keep ios keyboard open

I have a ios app that launch a UIWebView and you can interact with this web (the app is like a container). In the interaction with the web you need the keyboard a lot. So, I want (if it's possible) to keep the keyboard always open.
I've found some solutions, but none of them work for me.
I've tried with:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
and I able to detect when the keyboard are going to hide, but I don't know what I can do in keyboardDidHide method to avoid the keyboard to be closed.
I've tried also with:
webView.keyboardDisplayRequiresUserAction
But nothing happens.
Do you know how I can do this?
Thanks!
You can try playing with UIViewController's disablesAutomaticKeyboardDismissal property. Try overriding this property and returning NO.

Detecting device rotation when UIImagePicker is presented view

I am using the UIImagePickerController class and my buttons are in the camera overlay.
I would like to adjust the orientation of my camera buttons dynamically depending on device orientation the way Apple's Camera.app does. I understand that UIImagePickerController is portrait mode only and should not be subclassed. Still, I would like to be able to trap and respond to the device rotation viewController events.
Is there any clean way to do this? The viewController which presents the UIImagePickerController no longer responds to events once the picker is presented.
There seem a few related questions on this topic but none that clarify if what I want to do is possible or not. Compounding confusion, there seems to be some differences with UIImagePickerController functionality between iOS versions. I am developing this on iOS6/iPhone4 but would like to be compatible with iOS5.
Here is a clean way to do it, tested on iPhone4s/iOS5.1 and iPhone3G/iOS6.1
I am using Apple's PhotoPicker sample and making a couple of small changes. I expect you can adapt this approach for your project. The basic idea is to use notifications to trigger a method every time we rotate. If that method is in the overlay's view controller, it can carry on manipulating the overlay while the imagePicker is showing.
In OverlayViewController.m add this into initWithNibName
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(didChangeOrientation)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
These notifications continue to be sent while the pickerController is showing. So here, in the overlay's view controller, you can continue to play with the interface, for example:
- (void) didChangeOrientation
{
if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {
self.cancelButton.image =[UIImage imageNamed:#"portait_image.png"];
} else {
self.cancelButton.image =[UIImage imageNamed:#"landscape_image.png"];
}
}
you will need to kill the notification and remove the observer in viewDidUnload:
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
Note the way this app is designed: the overlayViewController acts like a wrapper around imagePickerController. So you invoke the imagePicker through the overlayViewController:
[self presentModalViewController:self.overlayViewController.imagePickerController animated:YES];
The overlayViewController acts as the delegate for imagePickerController, and in turn has delegate methods to relay information back to the invoking view controller.
An alternative is not to use UIImagePickerController at all, but to use AVFoundation media capture instead which gives you much more fine-grained control over the picture-taking process, at the expense of (slightly) greater complexity.

Resources