What I am asking may be impossible and sound weird, but here it goes.
Here is similar to what I want to achieve:
A user opens the app for the first time, there are two tab bars, in the first one (he has not tapped the second one yet) he presses a button that should initiate a progress view and text view changes and other view changes EVEN THOUGH the user has not loaded the other view controller by clicking the second tab bar.
So, is there a way to generally load a view controller before the user manually loads it himself, I know calling viewDidLoad manually will not help, any suggestions? Pretty confusing, it is like modifying a view but the controller has not loaded yet...
Thanks!
Make the changes in the other view controller and then let the controller configure its own view when it does its natural loading.
Related
I have been charged with updating an existing TVOS project. I have run into a bit of a snag.
If I am on the root controller(ie: the controller that presents on app launch.)
Pressing the Menu button takes me to an empty gray/white screen. A second press of menu returns me to the Dashboard.
I have tried to use the hierarchy viewer to see what exactly that gray/white screen is, but it has not helped. The gray/white screen consists of a UIWindow with a UILayoutContainerView, that contains a single UINavigationTransitionView in it. I can find no other identifiable characteristics about it to help me identify what exactly is going on.
When launched the app loads a UINavigationController that presents a UIViewController. Neither the Nav controller nor the presented ViewController override pressesBegin, pressesEnd or assign any gestureRecongnizers to intercept or otherwise override the Menu button functionality.
Near as I can tell the app should exhibit the default Menu button pressed behavior of navigate back to the root, then exit to the Dashboard once at the root. That said, the Menu button does navigate backwards as it should. It just does not terminate the app once at the root. When it does go to the gray/white screen none of the functions: applicationWill... are executed until after the second press of the Menu button on the remote. The app will also resume to this gray/white screen instead.
My question is thus, what is going on here. Baring that how can I
debug this behavior more effectively.
I have tried to be thorough with this explanation. I recognize that without code things get hard. Thing is, I have no idea what code would be relevant so any guidance or requests for specific code that may be useful will be posted.
Thanks.
Let's call your navigation controller A and the presented view controller B.
It sounds like what's happening is that A doesn't actually have any children, or it has a blank view controller as it's only child. I'm assuming that you never call pushViewController(_, animated:) on A? What are you passing to A when you create it with init(rootViewController:)?
When you press the Menu button the first time, UIKit is automatically dismissing the presented view controller B, and revealing the empty navigation controller A. The gray screen you see is actually the tvOS wallpaper, which is rendered outside the app's view hierarchy.
Then pressing the Menu button the second time actually causes the app to resign, since the navigation controller A doesn't have any more children to pop.
So it sounds like you should either:
Add the view controller B as a child of A, instead of presenting it.
Or, set B as the root view controller and forget about A.
I have a view controller with user content like text/images/location data and i would like to duplicate the viewController and present it modally (presentModalViewController) when the user taps the edit button. The reason for doing this is because i want it to be clear that the user is entering the edit mode by using the transition/animation that comes with a modally presented controller.
Does anybody knows how to duplicate an entire viewController + its view? i don't want the overhead of reallocating the entire viewController. I tried a couple of things, but i haven't had any luck.
Any help/information would be welcome.
That sounds a little impractical. You could make an image of the current screen contents, present that using whatever animation you like on top of everything, and then remove it?
Or make other changes to your view (rearrangement of views, appearance of other controls, changes of colour) in your viewController's setEditing:animated: method.
Ultimately, I'd like to know how to store a UIView (globally, if necessary) from one view controller, so that it can be referenced, and called back up to the top, from within another view controller?
I've built an app that has a Home tab and a Guide tab as the two main tabs, but the Guide tab's functionality is a bit unique in that it's a dynamic tab, which will ideally show different content depending on what "guide" has been chosen from the Home tab. Thus, on the Home tab, there are several UIButtons that are meant to load a given guide. Each guide is simply a collection of images that the user can interact with. No problem there.
Now, on the Home tab, when a user selects the guide they want to view, I wanted to transition between the Home tab and the Guide tab with a CurlDown animated transition. This is the only place I'll have a UIView transition animation—meaning normal tab switching by the user will be the standard instant transition without effects.
Here's how I have implemented the Home-to-Guide transition when a user selects a guide from the Home tab. This is done in the HomeViewController, as an IBAction assigned to all the guide-loading UIButtons, each of which has a unique tag that tells the GuideViewController which guide to load:
- (IBAction)loadGuide:(id)sender
{
UIButton *button = (UIButton*) sender;
GuideViewController *guideController = [[GuideViewController alloc] initWithNibName:#"GuideViewController" bundle:nil];
self.guideViewController = guideController;
[self.guideViewController activateGuide:button.tag];
[UIView transitionFromView:self.view
toView:guideController.view
duration:1.0
options:UIViewAnimationOptionTransitionCurlDown
completion:^(BOOL finished){
UITabBarItem *tabBarGuide = [[self.tabBarController.tabBar items] objectAtIndex:1];
[tabBarGuide setEnabled:TRUE];
self.tabBarController.selectedIndex = 1;
}];
[guideController release];
}
// End (IBAction)loadGuide
This works really well, up until the point where I then have to enable the Guide tab and switch to it. What happens at that point seems to be that another instance of the GuideViewController is created and replaces the one that was initially instantiated and transitioned to from the HomeViewController as shown above.
So I thought maybe I could work around it by, instead, moving the guide-loading to a new view, on that isn't used with the UITabBar, then load and transition to this view from the Home tab, just like I did in the above code. Then, after switching tabs, I'd need to somehow recall it into my Guide tab's view controller, as a subview or the like.
I'd think the view would still exist in memory after the tab-switching process, I just don't know how to access it, so I can show it again after the Guide tab's view has hidden it. Should I assign the view to some sort of globally accessible variable from the HomeViewController so that I can then access it from the GuideViewController (Guide tab's view)?
I'm open to any alternate suggestions as well, if you think this approach is bad form! I initially tried to overcome the problem by loading the details of the active guide into the database, then recovering that data when the Guide tab's view controller kicked in. However, the Guide tab's view must be cached or something, because if the user goes back to the home page and chooses a new guide, it'll animate the transition to that guide, but then when the Home-to-Guide-tab-switch kicks in, it flips back to the same state that the Guide tab's view was in before the user went back to the home page to choose a new tab. Also, I noticed the ViewDidLoad method doesn't get called again when manually nor programmatically switching tabs, so I figured that the other view must still be around in memory too! (The "other view" being either the original instance of the GuideViewController's view initiated from the Home tab upon selecting a guide button, or a new view as previously mentioned that would essentially do the same thing, albeit in a separate class.)
So to summarize:
I have two tabs, Home and Guide
Home has several UIButtons that when tapped will load a specific guide
When a UIButton on Home is tapped, it transitions from the Home tab's view to the Guide tab's view view CurlDown, without first switching to the Guide tab because that would lose the CurlDown effect
Then I have to trigger the tab switch programmatically, which seems to load a new instance of the Guide view, which effectively covers up the other instance
I want to know if I can somehow just call back up the first instance by somehow maybe storing the other instance as a global or some such?
Hense the question about how to pass a UIView instance around several UIViewControllers
If I were you I'd ditch the transition and just the tabbar as normal.
Firstly as it's giving you problems, but also and more importantly as it would seem strange to the end user who is used to tab bars just switching when you press the tab (well it would to me).
I'd read and re-read Apple's HIG on tabbars too. I think your users will find it very confusing that something other than the tab bar buttons causes the selected tab to switch.
You would have the data in the model.
The home tab would specify to the model which guide is chosen.
The guide would view load it's data every time it appears.
If you do need to keep the transition, then ditch the guide tab and use a navigationbar inside the home tab. You mention that screen space is the one issue for not doing so, but you can have the navigation bar present but not visible. You could then have a button in the guide tab to close that viewcontroller (pop the guide vc).
Another option might be to present the guide view modally instead - but the partial page curl also restricts screen space a little.
The ideal approach to doing this is to store a retained reference to the UIView object in a persistent object such as the app delegate subclass UIApplicationDelegate. The app delegate can then instantiate the view. Then, each controller needing to show the view would just ask the app delegate for the view. Also, if a root view controller is always available, it could be retained there as well.
Here is the situation, I have a login page as the initial rootView of a tab bar. Once the login process is done, the view is removed from the navigation controller, so you don't navigate back to it. I have places in the app where you can logout. The logout process works fine, but when I try to forward the user back to the initial login view (the one we removed) from inside the same tab bar item, I can't seem to reset the view controller stack to contain only the desired element. Is this a question of where I am changing the view? It just doesn't seem to remove the current view. I have tried alot of stuff, popto, popview, and many others, and nothing seems to work properly. Has anyone had to deal with this?
Take a look at the View Controller Programming Guide and the various way to alter the navigation stack (push, pop, set, etc).
Look into making your login view controller into a modal view controller, which pops up when credentials need to be entered.
A modal view controller is perfect for view controllers that you don't need to keep around, but which can be needed at different points in your application usage "flow".
Laurent's link will explain to you what the different options are for a navigation stack, and Apple's document suggests contexts in which those different view controller types are useful. I highly recommend reading it.
In my iPhone application, a user selects an item from a UITableView to choose a resource to view. The UIViewController subclass required to handle the resource is not known until the resource is retrieved, which may take a few seconds.
In response to the selection action, I push a "loading" view controller on the nav stack. That controller presents a view with a UIActivityIndicatorView along with (possibly) other status information, and initiates the download of the selected resource. From this view, the user might cancel the download, in which case I would return to the list of resources. If the resource arrives, though, an appropriate new view controller is created corresponding to its type.
Here's where it gets sticky. If I push the new type-specific view on the nav stack, the "loading" view is still in the stack; obviously once the loading is complete, there's no need to "go back" to that view. I've tried simply adding the type-specific view as a subview of the "loading" view, but that doesn't get my type-specific controller onto the nav stack, so it doesn't have a [self navigationController] for further navigation.
How can I "replace" the current view on the nav stack with a new one? Or, more generally, how can I show activity / progress when I don't yet know what controller will be used to display the resource being retrieved?
I've found pretty cool "HUD" progress indicator classes, but I don't want the progress indication to appear on top of the list of items being selected from. Instead, I want the user to perceive that they have "gone" to a new space that is waiting to be filled in.
I'm pretty new at this stuff, so I hope I've at least worded the question coherently. Thanks for any help anyone can provide.
Update: Actually, it would probably be better to display your "loading" view as a modal view. Check out this question for a few examples.
You should pop the "loading" view controller and push the "specific" view controller once the latter has been downloaded and allocated. Play around with NOT animating one or both of those actions to see what gives the best experience.