I have a UIContainerView inside of a ViewController which will be presented as a popoverViewController.
There is a UINavigationViewController embedded inside the containerView.
there is tableViewController embedded in the navigationView which performs a segue on cell selection.
like so
when a user clicks on My sessions from the Settings table view controller a delegate method on the (Main profile View Controller)get called to update the preferredContentSize of the popoverViewController.
and when the custom backButton (<) on the UITableviewcontroller the popoverView will change size again. i managed to get it all to work via delegation
however with that being said it only works once... the delegate method from the settings table view controller doesn't get called anymore.
i think after the setting view controller performs a segue on its own the delegate to the main profile view controller is lost and doesn't get called again.
this is how it looks in run time
now the size changes on click of my sessions and returns to original size after user taps on backbutton
but afterwards the delegate method doesn't get called and the view doesn't change size like so
i am using SWIFT 2.0 and Xcode 7.01 any solution on how to retain the delegate method would be really appreciated.
Ok so i solved it by not using the delegates method at all.
When the view controller that is supposed to change the screen size is presented i use
func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
presentingViewController?.preferedContentSize.width = 500
}
and i reverse it in viewWillDisappear
i hope it helps
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 need a loading screen to show while some data is being downloaded from the server. I present a view controller with modal segue without animation. But I don't know how to dismiss the loading screen view controller since dismissViewController function can only be called from inside.
I should be able to dismiss the loading screen view controller from another view controller. Any suggestions?
One option is using NSNotificationCenter. You can post custom notification and listen it in loading view for closing it.
If you are getting the data in parent view then you can close the loading view from parent view also. You can call dismissViewController from parent view using presentingViewController property of UIViewController class.
In your case from parentView you can dismiss the child view using:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
presentingViewController
The view controller that presented this view controller. (read-only)
Declaration
Swift
var presentingViewController: UIViewController? { get }
Objective-C
#property(nonatomic, readonly) UIViewController *presentingViewController
Discussion
When you present a view controller modally (either explicitly or
implicitly) using the presentViewController:animated:completion:
method, the view controller that was presented has this property set
to the view controller that presented it. If the view controller was
not presented modally, but one of its ancestors was, this property
contains the view controller that presented the ancestor. If neither
the current view controller or any of its ancestors were presented
modally, the value in this property is nil. Import Statement
import UIKit Availability
Available in iOS 5.0 and later.
Do you need to show another VC? You could just show a subview, making it visible=true when you start the app, and on the request success or failure callbacks hide it again (depending on the networking framework you are using)
I don't know were you start the request and were you know when it is done, if the loading screen knows when the download is finished you can do one of two things, or you pass the first VC as a delegate (defining a protocol) to the second VC (loading screen), and when you know on the loading screen that the download is finished you call a method on the delegate that will dismiss the loading screen,
Or you can use NSNotificationCenter, register for some kind of events on the first VC and when the process finishes on the loading screen you notify the first VC with this method, to dismiss the loading screen.
If you start the process on the first VC, and you know when it ends also on the first VC I would not understand your question, as you would just dismiss the loading screen and it would work.
Could you give more info? If you'd like I can post some code in order to help you in one of this approaches.
Hi all I am doing a course in Udemy, and the code calls for placing code in the viewDidLoad function as shown below:
override func viewDidLoad() {
super.viewDidLoad()
placesArray.append(["name":"Taj Mahal", "lat":"27.175607", "lon":"78.042112"])
}
The array append should only run once, however, when I segue to another viewController and come back, it runs the code to append again. So I now have an array with 2 rows, both of which are Taj Mahal.
I thought that the viewDidLoad function only runs code once?
Is there a way around this?
Thanks.
Addendum:
I am using Swift, so I don't see any alloc and init while creating and launching the viewController. And weird as it sounds, the video tutorial has it working in the viewDidLoad and the trainer is using the storyboard to segue from the initial table view controller to a map view on a view controller and just has a back button on the map view that segue's back to the table view controller via the storyboard as well. - Could be because I have the latest version of the Swift language and the trainer was using an earlier version, (cause I noticed some slight differences in coding earlier) but you never know. Either way whenever he touches the back button it does not run the append code anymore.
I am trying to get in contact with the trainer as some of the suggestions here, though they are good don't seem to work.
I will put the solution in here once I get in contact with the trainer.
The viewDidLoad method is called when your view controller's view finishes loading. The view will load when a view controller's view property is nil and something attempts to access it.
UIViewController *myVC = [[UIViewController alloc] init];
UIView *aView = myVC.view; // this loads myVC's view; viewDidLoad is called when it completes loading.
If the view has unloaded (usually due to memory limitations), it will be called when the view property is next accessed.
Manipulation of data sets should generally not be done within view methods. Consider moving this to the init of the view controller (or to a different "datasource" class).
I suppose you are trying to do data initialisation in viewDidLoad. If there is no other operation on placesArray before viewDidLoad, then instead of append, what about setting the placesArray directly:
placesArray = ["name":"Taj Mahal", "lat":"27.175607", "lon":"78.042112"]
Then even if your view is unloaded for some reasons. Taj Mahal will still be added once only.
viewDidLoad is called whenever the view controller's view property is set. When does this happen? It depends on how the view controller is contained:
UINavigationController
- View Controller views are loaded as they are added to the navigation stack and "unloaded" (although the viewDidUnload method is deprecated) as they are removed.
UITabBarController
- View Controller views are loaded as they are added to the tab bar regardless of whether they are on screen or not. They stay loaded as you change from tab to tab.
Depending on your needs and use case, you can create your own view controller container that does what you need. Checkout the Apple docs on the proper way to do this:
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html
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.
I am creating an app using iOS 5 SDK. I managed to push views using the Storyboard's Segues, but I cannot find the proper way to pop the current view and go back to the previous one.
I am not using any navigationController (the app doesn't have any top or bottom bars).
I don't think using modal or push segue the other way would be the solution as it instantiates a new controller.
Do I have to use a custom Segue with the opposite animation and deletion of the view at the end ? Or is there a better way ?
Storyboards in iOS 5 don't provide a "no-code" way to return from a segue -- that's something you'll need to implement yourself.
If you use "push" segues (which require a navigation controller), use the navigation controller's popViewControllerAnimated: method to undo the last push segue. (Or other methods to undo more; see the UINavigationController documentation.)
If you use "modal" segues, call dismissViewControllerAnimated:completion: on the view controller which presented the current view controller (which you can get from its presentingViewController property).
Update: In iOS 6 and later there's unwind segues for going "back" in a storyboard. It's still not a no-code solution -- and it shouldn't be, because you need to be able to do things like differentiating between "Done" and "Cancel" exits from a modal view controller. But it does let you put more of the semantic flow of your app into the storyboard. Apple has a tech note that describes them in detail, and they're also covered in the video from WWDC 2012 Session 407.
You could try calling [self dismissViewControllerAnimated:YES completion:nil]; from the controller you want to dismiss (whether the controller has been pushed, or shown modally).
Here is the related documentation : UIViewController Class Reference
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
Just to clarify.
In the class that was pushed. Simply wire up the following and the controller and view will be popped off.
[self.navigationController popViewControllerAnimated:YES];
Create Segue type "Custom" on your stroyboard. This can be from a button.
Create a new UIStoryboardSegue class named "popSegue"
In the popSegue.m file add the following;
-(void)perform{
UIViewController *sourceViewContreoller = [self sourceViewController];
[sourceViewContreoller.navigationController popViewControllerAnimated:YES];
}
-In the storyboard editor.
-Select the segue and change the Segue Class to "popSegue"
-Set the Identifier to "popSegue"
Done!
You can use the same "popSegue" class throughout your project.
Hope this helps
I'm using Xcode 5 also and here's how it's done. First, in the view code file that pushed the other, create an IBAction method in the .h file such as this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender;
Then in the .m file add this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender {
}
You can add any cleanup code you want executed in this method. Next go to your storyboard and select the pushed view. I assume you've got some kind of button on the view that the user taps to signal he's finished. Click on that button, hold down the key and drag to the the green box below the view which is the Exit. Release the mouse button but continue to hold the key. A popup will appear and your method will show in the list. Select that method. Now when the user clicks on the button, the view will pop and you'll be returned to the starting method.