I've implemented a singleton to display adWhirl ads. However, when I change scenes in my storyboard app, the viewController for the ad is not updated until a new ad is requested. I have viewControllerForPresentingModalView implemented in the singleton and I set it with displayVC on every viewdDidLoad. But since the VC is not changed until a new ad is requested, any previous ads (specifically admob) cannot display fullscreen because their VC is set to the previous scene. Any help is greatly appreciated!
adWhirlSingleton *adWhirlSingle = [adWhirlSingleton sharedAdSingleton];
adWhirlSingle.displayVC = self;
[adWhirlSingle adjustAdSize:0 :self.view.frame.size.height -50];
[self.view addSubview:adWhirlSingle.awView];
[self.view bringSubviewToFront:adWhirlSingle.awView];
Are your ViewControllers part of some containing View Controller by any chance (are they in a Navigation Controller or a Tabbed Controller for example?). If they are, I'd recommend just setting the displayVC to be the containing View Controller so you don't have to change it.
If not, maybe something like what is outlined here would help. Basically creating a proxy type of class that then forwards the correct messages to the currently selected ViewController?
Related
I am in the process of building a reasonably complex iPad app that will run on iOS7+. The app has a login screen that must be accessed once every user session, this is the starting view controller in my storyboard. The user can log out from any other screen in the app (there are about 60 other screens) by touching a button that is always available in every other ViewController. When the user logs out, a custom transition animation should be used.
It seems I can achieve this in one of two ways, either with a segue from every screen in the app to the login page, which makes the storyboard impossible to read, or presentViewController.
I've implemented this with presentViewController, by looking up the view controller by id from the storyboard (which creates a new instance, which is a desired behavior) and then presenting it from the current view controller.
Not surprisingly, this does not dismiss the original login view controller and essentially creates a stack of view controllers, eventually I run out of memory as each time a user logs out, a new login view controller is created and retained.
Is there a way to clear this "stack" of view controllers?
Is there a different way to present a view controller, with an animation, that does not involve presentViewController or segues? I've considered view controller containment, but that doesn't seem quite right when used with storyboards.
Have you considered replacing the root view controller? If the app delegate observes a logout notification and replaces the root view controller with the initial content of the storyboard that should get the app back to the initial screen.
I've seen that presented as a solution for login/logout issues elsewhere on the web, but I'm not sure if there's a transition you can animate there.
I think your approach is wrong. Correct me else wise.
Login mechanisms are supposed to be singleton instances. Hence you should define your view controllers, models, views all as singleton instances. Please look at my following code for example.
static id objectInstance;
+ (id) sharedInstanceID {
if (!objectInstance) {
objectInstance = [[YourClass alloc] init];
}
return objectInstance;
}
Let me know if this helps you.
I decided to give the use of storyboards a go in my current iPhone app. I am facing a bit of a problem. I really need to reuse my UIViewController instances.
What do I mean by that? Well, for example I have a table view controller. When I tap a cell, another view controller is loaded from the storyboard and pushed onto the navigation controller stack. This all works well, but it takes about half a second to a second each time this view controller is loaded. Before I was using story boards I simply solved this problem by caching the created instance so the second time you tap a cell the view controller can be immediately shown.
By caching the created instance I mean something like this:
if (!cachedInstance) {
cachedInstance = [MyViewController new];
}
[self.navigationController pushViewController:cachedInstance];
Does anyone know how to accomplish this using the storyboard? Thanks in advance.
If you are using segues, you will need to create custom segues in order to use a cached view controller like you did before. Otherwise, the typical "push" segue will create a new instance of the view controller for segue.destinationViewController. If you write a custom UIStoryboardSegue class and use custom segues you can override initWithIdentifier:source:destination: and put your cached view controller in for the destinationViewController, and then override perform to use the classic pushViewController call.
That is how you handle the segue if you are really intent on using them. I would just skip it though, unless you really want the fancy arrows to lay everything out on your storyboard. If you skip it you can just instantiate the view controllers into the cache and then push them on just like you did before.
If your question is more about locating a view controller inside a storyboard then you can use:
UIViewController *vc = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"Some View Controller"];
Then you can save that to your cache and push it like you did in your example code.
Hope that helps.
I recently encountered a small problem with Storyboards. I have a UINavigationController than has a relationship with the MainView RootViewController(This one has all the buttons leading to the rest of my app). However, I tried to change the RootViewController so that I could enable persistent login rather than a UIWebview Login. When I made the new Logon Form ViewController as the Root, the buttons on my MainView simply stop working.
I also have set the UINavigationController as the initial View Controller.
Any ideas on what has to be done here?
I do know that I can simply have the logon screen in the storyboard and call it programmatically, set it to advance on a boolean condition(loginDidSucceed). However, I am confused on why this behavior happens in StoryBoard.
Solution Referred from: Present Splash/Login ViewController With StoryBoard
Thanks for the Help and Effort!
I think the principal problem here is that the target of your butttons is the old view controller instance; when it goes out of scope their target no longer exists.
The structure of my MainStoryboard is:
->Tab Bar Controller -> Navigation Controller -> View Controller (Search)
The behaviour I want to have is that when the user re-selects the Search tab, the UIScrollView on it scrolls to the top. I am unsure how to get the event from the TabBarController, however.
I've been looking at a lot of stuff about UITabBarDelegate, particularly:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
I have, not quite managed to get this to work properly though. I am very unsure about how to go about setting the delegate (assuming that is the way it's done). I've tried hooking it up in IB, but it wouldn't let me. I also tried to get the UITabBar from the AppDelegate (after looking at some seemingly-related answers).
Any pointers will be greatly appreciated (unless they're null).
UITabBar *aTabBar = [UITabBarItem alloc] init];
....Any other modifications you want to make to aTabBar....
[aTabBar setDelegate:self]
Don't forget to add "<UITabBarDelegate>" to the "#interface" part of whatever object you're trying to designate as the delegate.
For my own code, I usually use some object that isn't the application delegate (as the app delegate is usually meant for application level events like "application is suspending" or "application is coming back into foreground"). If you add "<UITabBarDelegate>" to your Search view controller, make sure that whatever you do with the "didSelectItem" method is applicable only to the Search view controller. Otherwise instantiate some different object if you want to do actions on various view controllers based on which tab bar item is being displayed.
This is my first app using storyboards/segues, and I'm pretty sure the answer to this is easy, but I'll be as thorough as possible in describing my issue.
I am making a simple app which has a Tab Bar Controller scene and two View Controllers.
My app launches by being sent a URL from another app. The application:openURL:sourceApplication:annotation: method in the app delegate performs some work to determine
which tab to display first, and
what information to display on it.
My goal is to use the performSegueWithIdentifier method (I'm open to alternatives though) from within the AppDelegate to select the tab, and also find a way to send a method to the instance of the view controller created by the storyboard.
Issue #1 is that I can't set an identifier. When I select the tab "relationship" there are no choices available in the Attributes Inspector (it says "Not Applicable"). How do I set a name for this segue? Can I? Or is there some rule under which UITabBarController segues can't be trigger programmatically?
Issue #2 is that I can't find a way to have a pointer to the view controller. Pre-Storyboard I would alloc and init a new view controller and then set it up, but here if I do that, it does not get displayed when my app launches (I think this is because Storyboard is displaying a different instance of the same view controller.)
I know this post is long, but I feel like I'm missing something simple. What is it?
Sounds like you need to have your AppDelegate set the entry point to your storybard.