I have 3 view controllers with the NSUserDefault bool values for detecting first launch and calling the tutorial func. But, in one of view controllers, it doesn't work as it should:
I have a custom animated segue with VCs
main vc -> img vc
img vc exit -> main vc
main vc -> sett vc
sett vc exit -> main vc
I tried to write println in the viewDidLoad in main vc and I find out that the viewDidLoad method works only when the app opens, all other time when I come back to main vc it doesn't work. (in two other vcs it works every time when I segue to them)
I have no idea how to correct it.
Your question is hard to understand. I try an answer here, and if it doesn't satisfy your needs, please provide more code.
I believe you mix up a didLoad and a didAppear delegate method.
If you want to trigger code every time a view will be shown to the user, use the viewDidAppear delegate-method.
viewDidLoad is called only once, when the view is loaded to memory. If you use a navigationcontroller and segue back to the view (which is already loaded in memory), viewDidLoad will NOT be called again. But viewDidAppear will
Related
Please help me with this. I have created a simple project with two views as shown. I have attached the images for my storyboard and swift files. So, I read that viewdidload will be executed only once while loading the view into the memory. But, when I make a transition from secondview to the firstview the viewdidload is executing again and so is the print statement in the viewdidload method.
Someone please explain me this.
viewDidLoad is not called once for the Application. It is get called once for that viewController when the view holds memory and loaded.
So as many number of of time you push to the viewController, that many times it will call the viewDidLoad
viewDidLoad() — Called when the view controller’s content view (the top
of its view hierarchy) is created and loaded
viewWillAppear() — Intended for any operations that you want always to
occur before the view becomes visible.
For more info about this look at the link : https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html
So if the view is already in memory (Like your case), then no need to push again, only need to pop back by this code
self.navigationController?.popViewControllerAnimated(true)
You should not make transition from secondViewController to firstViewController for back. Pop the second view controller by this code to back:
self.navigationController?.popViewControllerAnimated(true)
When you make a transition it makes a new instance from your firstViewController but when you pop the second view controller it dismiss your secondViewController and shows your last viewed viewController again.
Or
in the case that you are not using navigationController you should use below code to dismiss your secondViewController
self.dismissViewControllerAnimated(true, completion: {});
The main point is that you should not use new transition for back.
The simplest way:
1.First embed your ViewController in NavigationController
2.Call to this (instead of create segue for backing)
navigationController?.popToRootViewController(animated: true)
viewDidLoad will be called only once
I understand that you can use ViewDidLoad to run some code when a view is loaded. However that only happens once. How can I run a method every single time that view is shown. So for example: let says you are currently in ViewController A and you press a UIButton to go to ViewController B. Then you press a button to go back to ViewController A, how would you then re-run the ViewDidLoad code??
I hope my question makes sense. In essence I want to re-run a small method every single time the user is on a particular ViewController.
Thanks for your time, Dan.
viewWillAppear:
Notifies the view controller that its view is about to be added to a
view hierarchy.
or
viewDidAppear:
Notifies the view controller that its view was added to a view
hierarchy.
This answer didn’t help. I found myself in the same situation and the solution is simple.
Create a method with codes you want to be executed every time your view controllerA shows up.
Place your method under viewDidAppear()
Make sure that the modal type of your viewcontrollerB is set to fullscreen (fullscreen removes viewcontrollerA from the stack)
Under viewcontrollerB viewDidLoad()
Set its background other color than clear. White works for me
Dismiss from your viewControllerB and “voila!”
Create an AbstractController that every view controller inherits from that controller, and you override the viewDidLoad method and make it do whatever you want at every view opened.
Using:
Xcode 4.6
Storyboards
ARC
Model segue to SecondViewController
I have an app that has the main ViewController that loads a new veiwController when the device is rotated to the right. When the app starts everything works great. If I rotate the device, then back which unloads the secondview controller, about 15-20 times the app is very slugish. I have narrowed down that it only happenes when the seconed view controller is loaded and only when i rotate the device a nunmber of times. I also have narrowed down that is is a memory issue. I installed an app that keeps track of the memory used and available. My memory goes from 400mb to 900mb used when i rotate the device a number of times. I am trying to give as much info as I can. Each view has 8 NSTimers that fire every second.
Is there a way to programmatic unload a view, to make sure is is being unloaded?
I have included this code to ensure the loading and unloading:
`- (void)setView:(UIView *)aView
{
NSLog(#">>> Entering %s <<<", PRETTY_FUNCTION);
if (!aView) // view is being set to nil
{
NSLog(#"Should be unloading now");
}
[super setView:aView];
NSLog(#"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
}
log result:
2013-04-22 16:42:03.588 xxxxxxxx[xxxxxxx] >>> Entering -[GraphViewController setView:] <<<
2013-04-22 16:42:03.589 xxxxxxxx[xxxxxxx] <<< Leaving -[GraphViewController setView:] >>>
`
I am not sure what I need to be looking at to correct this.
Any "points" in the right direction will be very appreciated .
Thanks
You haven't given much information about how you "unload" SecondViewController. Are you doing a modal segue to it as well? If so, that's your problem -- every time you do a segue, you instantiate a new view controller, and if these are modal segues, the presented controller has a strong pointer to the presenting controller, so none of these controllers will ever get deallocated as you go back and forth.
As a rule, you should never go backwards in a storyboard using anything but an unwind segue. So, the solution to your problem is to use an unwind segue to go from SecondViewController back to MainViewController -- this will actually go back to the same instance of MainViewController that you came from, and SecondViewController will be deallocated. If you don't know how to make an unwind segue, I will edit my answer to show you how.
After Edit:
To make an unwind segues, you do two things. In the controller that you're going back to, you add a method -- the two important things are that it be an IBAction, and that it has a single argument that's typed to UIStoryboardSegue*. It doesn't matter what you call it, and it doesn't even need to have any code inside it, though I usually put in a log statement just to be sure it's called. Then, in IB in the controller you're unwinding from, you control drag from your UI element like a button or table view cell (or from the controller itself if you want to fire it from code), down to the green Exit icon at the bottom of the scene -- it's important to note that you are dragging from a UI element to the exit icon in the same controller, not between controllers. When you let go of the drag over the exit icon, you will see any methods you created with the signature I mentioned above. Choose the one you want, and that's it. You can implement prepareForSegue in the source controller just like any other segue if you want to pass any information back to the destination controller.
I have an iPhone application which consists of two View Controllers; a main one, and one with the help screen. Each one has a button that performs the segue from one to the other.
The problem I have is, when I segue back from the help screen to the main screen, the main view controller's viewDidLoad method gets called, so all of the initialization I did when the app was first started is repeated. Is there another method in the view controller that gets called just once, where I can do the initialization?
My first thought was, "Have a boolean variable that is initially set to false, then have viewDidLoad test it, and if it is false, do the initialization, then set it to true" - but how do I initialize it to false in the first place?
My guess is that you're doing a "Push" segue (which is the most standard kind of segue one can do in an iOS app), and if you are using a "Push" segue that means you have a navigation controller in your app.
The best thing to do here is not to push another "Main" view controller onto the stack of other view controllers (which is why you are seeing "viewDidLoad" called each time you push the main view), but instead when you click a "go to main" button in your help screen, pop the help screen off and return to the previous one. The call that would do this is UINavigationController's popViewControllerAnimated method.
Doing that means "viewDidLoad" on that view controller only gets called once, as the main view gets loaded once.
on the .m class file create a bool on #implementaition:
#implementation yourClass{
bool initialize = 0;
}
and then test it on view did load:
-(void)viewDidLoad{
if(initialize == 0){
//do everything you need to do
initialize = 1;
}
}
I think it will work...
I have a fairly simple app thats a game for small children. There is a main screen and 5 separate levels. 3 of the 5 levels are made up of more than one VC where actions take place in the first VC in that row then code calls a modal segue to the next one in the line and so on till it reaches the end of the row and a modal segue is called linking back to the main screen. The levels that have only one VC just perform actions then segue back to the main VC.
Every segue in the app in modal.
Also every page (VC) has a home button that will segue to the main page if pressed
I set this all up in the StoryBoard and visually everything works as Id expect but when adding sound I realized that there seems to be a major problem.
If I now understand correctly (and maybe I dont) modal segues dont actually replace the current VC with the newly requested one but rather slide the newly requested one over top the original and make it the visible display.
Currently I go from main to level 1. Level 1 does some stuff and plays some sounds that repeat via a timer. If I segue back to main visually everything is fine except the sounds being played by the timers in level 1 VC continue to play and xCdoe give me the following error quite a few times
2013-01-21 22:16:07.901 TTBetaDev[678:c07] Warning: Attempt to present <MainMenuViewController: 0x7e02f40> on <BonusViewController: 0x7ecbfa0> whose view is not in the window hierarchy!
Below is a screenshot of my storyboard in case I havent explained the layout well enough.
How should this be set up to allow the navigation I would like? A what steps will I need to take to apply that to the what I already have built in the storyboards? Or will I have to re-do all my storyborad work?
I tried apples VC documentation but I couldnt understand what relates to what Im trying to do.
COuld someone please help explain this to me
You have segues going forwards AND backwards. You shouldn't do this.
e.g. Look and Main and VC 2.
You have a segue going from Main to VC 2. This means that Main will present VC 2 as a modal view controller.
When Main does this though it is still on the stack underneath VC2.
Then you have a segue from VC2 to Main. This means that VC2 will create a new Main and present it modally too. If you continue using the app you will have multiple instances of main and all the other VCs and memory consumption will rocket.
What you need to do is delete ALL the segues that go backwards. (i.e. like the one from VC2 to Main)
Then when you want to get back to main from VC2 you have to dismiss VC2.
i.e.
in Main...
//present VC2
[self performSegueWithIdentifier:#"VC2Segue" sender:nil];
//dismiss VC2
[self dismissViewController:vc2ViewControllerInstance];
or in VC2...
//dismiss VC2 from itself
[self dismissViewController:self];
The main thing though is that you can't use segues to go backwards.
TL:DR
Nothing should segue INTO Main. Any segues that go into the left hand side of main should be deleted and dealt with properly.