iPad : two-stage method implementation - iphone

here is my problem, I hope someone can help me.
My iPad app is made like this : I have several viewControllers added as tabs in a tabBarController added to window in my appDelegate. In each of these viewControllers I got two navigationControllers with one viewController in.
Appdelegate
TabBarController
viewController
navigationController
viewController
navigationController
viewController
viewController
navigationController
viewController
navigationController
viewController
Everything work fine in simulator but when I run it on device I got this warning :
Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations.
It only happen when I run it on a device in landscape mode. The first navigationController of the default view shown by the tabBarController take all the screen width (not important here but it's to explain that this warning makes my layout going crazy). In portrait nothing is traced in the console.
I read many things about this message but I can't find any solution to make it go away.
I'm sure it's a story of shouldAutoRotate or something like this.
I also notice that if i remove the tabBarController and simply add my first viewController to window, the message is not shown.
Very strange... please help :)

I think you should rely on the standard UISplitViewController available under iPad. This controller is what is used under the Settings app and various other apps.
If you do not feel comfortable with such a tool, you can take a look at the APSplitViewController plugin developed by slatvick on GitHub. This could solve a lot of your problems, I hope.
Edit
Googling about this issue, I found out that this warning appears when you create a wrong hierarchy of view controllers. In this case, you are pushing two navigation controllers inside a view controller, even if a view controller is not meant to contain different navigation controller. Probably there could be a problem related on how you send up to the parent view controller methods like viewDidLoad or viewWillLoad: etc. You should try to understand if you are passing all these call correctly to the parent view controller from the inner navigation controllers.

Related

iOS Storyboard Modal Segues and Memory

My apps "short" description:
Basically an interactive storybook, I have a class that sets up a audio session and audio player which every other class(ViewControllers) in my app imports and calls a function or two to set the right sound to be played each time something happens(for instance.. user reads the story). Each ViewController has it's own .m and .h classes and uses them for animations and action handling. My app is only about 60 mb's in size (audio/images/code).
Now these ViewControllers are set up in a storyboard (they are 13 now) and are modal segued from one to the next one and then programmatically dismissed to go back.
When I run my app on my iPad now, I'm starting to get memory warnings and yes Instruments is showing me that my app is adding roughly about 40 Mb's for every ViewController that I segue to.
My questions are:
Do they reside in real memory no matter what I do? (I thought I wasn't holding any strong pointers to these view controllers).
Is there an easy way for me to dismiss one controller and still use a modal segue to get to the next one?(ran into troubles trying this)
Modal Segues are probably not the way I should be doing things in my App are they?!. They looked so nice and easy for my "storybook", but now they are giving me a very rough time.
Any other tips you can give me from what I described are appreciated.
Thank you.
Yes, as long as you present it modally. The presenter view controller keeps a strong pointer to the presented view controller. What you could do here is in the viewWillDisappear: release all the images and other views that might use memory !
You could instantiate your view controller using the method instantiateViewControllerWithIdentifier: and then presentViewController:animated:completion: like you would do with any view controller
It's up to you to decide. But you could easily mimic the animation if you wanted to.
If I understood everything correctly I would go with a singleton class kinda like 'AudioEngine' which is accessible from anywhere in any class. Then I would design all my viewcontrollers in my storyboard like you did. When I need to present modally another view controller, I'll do it using the answer of your 2nd question. If I still had a memory issue, I would try to cheat and keeps always 3 view controllers (like we do with the UIScrollView's infinite scroll) that I would reuse and I'll mimic the modal presentation using UIView's animation blocks.

Switching between views not working for iPhone 5.1 (XCode 4.3.2)

I'm trying to develop an iPhone app that uses 4 views(View-based app), and I want to navigate from one view to the other. It would be ideal if for example the Submit ID button automatically sent a message to UIViewController to switch to View 2, and selecting a cell in View 2 would load View 3.
See a screenshot of the Storyboard here.
I'm not sure how to do that, so I've tried using a separate button to switch between views, but that isn't working either and I can't figure out why.
You can have a look at the source code which I've uploaded to Dropbox.
First, I would suggest posting your code in your question. As appreciative as I'm sure other people are that you provided a dropbox link to the code, most people presumably have little interest in downloading the file to their computer, unzipping, and launching the project (me being one of them).
That being said, let's make sure you're clear on Storyboards and the general view controller hierarchy principles. You have, in your storyboard, four UIViewControllers dragged out into your workspace. So, you're not switching the views of a single UIViewController, telling it to switch from View1 to View2 to View3 and so on. You need to be telling the view controller hierarchy (which, in your case, probably needs to be managed by a UINavigationController), to push and/or pop view controller on and off its stack. It appears that you have some segues set up between your view controllers. Are you calling performSegueWithIdentifier:sender: in your code? Alternatively, you could hook up the Submit ID button to perform a push segue to View Controller 2 in much the same manner.
Once you have that working, you can override prepareForSegue:sender: to send information from ViewController1 to ViewController2 and so on.

UITableView does not work after switching rootViewController?

I couldn't find any tutorial that i could understand about switching views but i found out that i can switch them by changing the window's rootViewController property.
The problem is my other view has 2 UITableViews in it, but they don't respond to swipes when the controller just became the rootViewController, but after i turn my ipad 90 degrees the view changes to landscape then it starts to work.
Can anyone tell me how to make them work when the view is loaded?
You can't change directly the windows rootViewController property and have it to work, because the system doesn't get notify that that change occurred. That is why the change took effect only when the system asked for that view again.
You need to use a method to change it. Depending on your architecture you may want to use a method from UIViewController
transitionFromViewController:toViewController:duration:options:animations:completion:
UINavigationController :
setViewControllers:animated:
UIView :
transitionFromView:toView:duration:options:completion:

How to add tabbarcontroller inside viewcontroller in iphone

hi
i am currently working in iphone navigation based application. so my app have 30 screen,after navigating five screen i need a TabbbarController . I add tabbar Controller OverMy viewController ( [self.View addSubView:tab.View];) my application work fine and navigation work perfect but my problem is that after navigating from tabScreen to other myViewController which inside tabbbar controller are not relaods but navigated view controller work fine .
so above my code adding tabbar is wrong then plz help me ,thanks in advance.
I have to say, that I don't fully understand your question, I guess this is due to the language barrier, but maybe you can elaborate your explanation a little more. However, I think that I understood your problem. You want a UITabbarController (respectively it's view) to be a subview of a UINavigationController. Is that correct?
The answer to this question is simple, but, I'm afraid, unsatisfying your you: You can't do that and even if you could, you shouldn't. Please have a look at Apple's excellent ViewController guide. It says:
Thus, a navigation controller can incorporate custom view controllers, and a tab bar controller can incorporate both navigation controllers and custom view controllers. However, a navigation controller should not incorporate a tab bar controller as part of its navigation interface. The resulting interface would be confusing to users because the tab bar would not be consistently visible.

UISplitViewController and complex view hierarchy

I'm doing an iPad tech demo and I'm running into a serious technical problem.
I have an app concept that leverages UISplitViewController, but NOT as the primary controller for the entire app.
The app flow could be described roughly as this:
Home screen (UIViewController)
List->Detail "Catalog" (UISplitViewController)
Super Detail Screen (UIViewController but could conceivable also be a child of SplitView).
The problem is in the flow between Home and Catalog. Once a UISplitViewController view is added to the UIWindow, it starts to throw hissy fits.
The problem can be summarized at this:
When a UISplitView generates a popover view, it appears to then be latched to its parent view. Upon removing the UISplitView from the UIWindow subviews, you will get a CoreGraphics exception and the view will fail to be removed.
When adding other views (presumably in this case, the home screen to which you are returning), they do not autorotate, instead, the UISplitView, which has failed to be removed due to a CG exception, continues to respond to the rotation instead, causing horrible rendering bugs that can't be just "dealt with". At this point, adding any views, even re-adding the SplitView, causes a cascade of render bugs.
I then tried simply to leave the SplitView ever present as the "bottom" view, and keeping adding and removing the Home Screen from on top of it, but this fails as SplitView dominates the Orientation change calls, and Home Screen will not rotate, even if you call [homeScreen becomeFirstResponder]
You can't put SplitView into a hierarchy like UINavigationController, you will get an outright runtime error, so that option is off the table. Modals just look bad and are discourages anyway.
My presumption at this moment is that the only proper way to deal with this problem is so somehow "disarm" UISplitViewController so that it can be removed from its parent view without throwing an unhandled exception, but I have no idea how.
If you want to see an app that does exactly what I need to do, check out GILT Groupe in the iPad app store. They pulled it off, but they seem to have programmed an entire custom view transition set.
Help would be greatly appreciated.
Apple states:
The split view controller’s view
should always be installed as the root
view of your application window. You
should never present a split view
inside of a navigation or tab bar
interface.
This does mean it should be root view and not subview of another view. Even though they add:
You should never present a split view inside of a navigation or tab bar interface
That does not mean you can add it as a subview of any other controller either. (sorry)
I have a feeling that what you are experiencing is the byproduct of trying to do so. I am actually surprised that GILT Groupe's app did not get rejected. Apple has a tendency to enforce these HIG guidelines rather strictly lately. They (as you found out already) cause a rather nasty runtime error when you attempt to add them to a NavigationController.
I've solved this for myself... actually worked around... by presenting all other possible full screen views as modals of the SplitView...
This is an unsavory way of doing things in my book, but Apple leaves you little choice if you want to leverage a SplitView only "sometimes" within an app.
I had some success by creating a second UIWindow. I associate the UISplitViewController with that, and switch it out with the main window when I want to show the splitview. It seems to work they way I wanted, except for a slight delay in rotations and a log message about "wait_fences".
Unless your developing for jail-broken devices then bending apples rules/wishes isn't a good idea. Like Jann and Jasconius state above this means keeping a splitView controller view root, not over-using modals (vague) and not using multiple windows.
Also, the Gilt app is only available in the US
I'v been trying to find a solution too and have ended up programatically removing views from the window like Tuannd talks about but the landscape rendering bug is unforgivable.
#Jasconius, What is the max number of modals are you are presenting at any time?
I am struggling with this same issue. I've been trying various things poking at the UISplitViewController as a black box and see how it reacts.
I seem to have come up with a solution to my case which seems to be working satisfactorily.
The key appears to be that the first view added to the UIWindow is the only view properly initialized. All the problems I've had tend to stem from incorrect notification of the orientation of the device. The first view added, apparently has this correctly configured.
In my case I didn't want the UISplitView as the first view. The following is working for me.
The app delegate application:didFinishLaunching method is special. Adding the view to the UIWindow must occur here. If it is done elsewhere it does not get configured properly.
Essentially the magic sauce, is have the split view be the first view added to the window. Its then ok to remove it as long as you retain the UISplitViewController. From then on you can swap other views in and out, including the UISplitView and most things seem to be ok.
I've still run into a few issues. Popovers on views other than the split view are confused on the views frames and location of toolbar buttons and will display in the wrong location. I place then in a specific location and that seems to handle that case.
If a popover on the split view is still displayed, and you try to view another view, the orientation of the second view is confused and shows up sideways. If that view is accessed before the popup is displayed, all is well. I've fixed this my manually dismissing the popover before switching to any other view.
Here's the code if it helps. All the controllers are instance variables of appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// This also seems to work as good magic. Seems to set orientation and size properties that persist.
[window addSubview:splitViewController.view];
[splitViewController.view removeFromSuperview];
[self switchToNewViewController:firstController];
[window makeKeyAndVisible];
return TRUE;
}
- (void)switchToNewViewController:(UIViewController *)newViewController {
[popoverController dismissPopoverAnimated:FALSE];
if (newViewController != currentViewController) {
[currentViewController removeFromSuperview];
currentViewController = newViewController;
[window addSubView:newViewController.view];
}
}
Just wanted to say that I was running into these same issues, found this forum topic, and followed the advice from g051051 above. This is working perfectly for me. I am not seeing any glitch, and no messages about wait_fences in the console of the device.
I simply used IB to create two UIWindow objects in the main XIB, created as normal the UISplitViewController and then also an instance of my other controller derived from UIViewController (which I am using for full screen display). I have simply hooked them up by attaching the rootViewController for each UIWindow to its appropriate controller.
In application:didLaunch...: method I can decide which window to send the makeKeyAndVisible method and which to set to hidden. When the user want to switch back and forth I simply have to send makeKeyAndVisible to one and set the hidden property on the other, that's all there is to it.
As indicated all of the rotation related messages are sent to each controller appropriately, regardless of which one is associated with the currently visible window.
Anyway, works great for me, and actually quite easy to set up.