How to instantiate and load a view controller before segueing to it using swift
You can move all the heavy code out of viewDidLoad()
into some custom method
func prepare() {
// Something hard
}
than you can prepare your controller at anytime and store it
var heavyController: HeavyViewController?
override func viewDidLoad() {
super.viewDidLoad()
heavyController = HeavyViewController()
heavyController?.prepare()
}
than just use heavyController in segue instead of creating new one. Hope this helps.
P.S. consider moving heavy parts of code into background thread, you can check the example.
UPDATE:
To show your prepared controller using segue do something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "HeavyController" {
present(heavyController, animated: true, completion: nil)
}
}
Instantiate and Present a viewController in Swift
This answer was last revised for Swift 5.4 and iOS 14.5 SDK.
It's all a matter of new syntax and slightly revised APIs. The underlying functionality of UIKit hasn't changed. This is true for a vast majority of iOS SDK frameworks.
let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myVCID")
self.present(vc, animated: true)
Make sure to set myVCID
inside the storyboard, under "Storyboard ID."
Swift how to trigger prepare for segue before target view load?
What I would do first is to DELETE ❌ the segue you've probably created by drag and drop from the button on VC1 to VC2. Replace it by a regular segue which is not attached to any UI component so that you can trigger it manually in code (from its identifier, don't forget to provide one). It will allow you to first perform some asynchronous code, and only when getting the callback trigger the navigation (if data fetch is successful).
To create such a segue:
- click on your VC1 in the storyboard => A small rectangle with icons should be now displayed right above the VC1
- Ctrl + drag from the yellow icon (probably at the most left of that rectangle) to the VC2 (on main view, does not rally matter where you drop it as long as it is on VC2)
- Provide identifier after having clicked on the newly created segue so that you can trigger it from code
That was for the segue, but now, when to trigger it?
- Create an an @IBAction on the button which is suppose to trigger the fetch + navigation (or equivalent, like didSelectRowAtIndexPath)
- This IBAction should call another method like the following:
private func fetchPostingAndNavigateIfSuccessful() {
// Should probably first set the activity indicator to `.startAnimating()`
let docRef = db.collection("Posting").getDocuments() { [weak self] querySnapshot, error in
// Should probably set the activity indicator to `.stopAnimating()`
guard error != nil,
let documents = querySnapshot?.documents else {
print("error getting documents") //probably a good place to display an alert
return
}
let postingsData = documents.map { $0.data() }
self?.performSegue(withIdentifier: "NavigateToPostingsSegue", sender: postingsData)
}
}
Your prepare for segue would then look like that:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let postingListTableViewController = segue.destination as? PostingListTableViewController,
let postingsData = sender as? [[String:Any]] {
postingListTableViewController.updatedPostings = postingsData
}
}
Initialising a ViewController before Segue
Segues should be subclassed only when you need to show custom animation/transition during the segue.
In usual scenario, you would want to do this:
__ block Destination *destinationVC = [self.storyboard instantiateViewControllerWithIdentifier:@"destination "];
//START BUSY CURSOR HERE
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// init whatever you want for destinationVC HERE.
dispatch_async(dispatch_get_main_queue(),
^{
//STOP BUSY CURSOR
//PERFORM UI UPDATE HERE
[self presentViewController:destinationVC animated:YES completion:nil];
});
Make instance of view controller and segue to it programatically
You want to use presentViewController
instead of performSegue
:
// however you want to initialize the new vc
let vc2 : View2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("view2.id") as! View2
an alternate way to init the vc is to do this:
let vc2 = View2()
and then set the data and present:
vc2.index = index // whatever you want to pass
self.presentViewController(vc2, animated: true, completion: nil)
Otherwise you could create a new view controller in your storyboard, but I wouldn't recommend it.
How to load initial view controller in Swift?
I solved the problem by changing resetAppToFirstController method to:
self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier(PageNames.LOGIN_PAGE) as LoginPageViewController
and firing the following code when Logout is clicked:
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.resetAppToFirstController()
However, I have no idea why this is worked. Any little explanation would be great.
Pass data to view controller before initializer when using segues. (Swift)
There is two possible options as you mentioned:
The first one is the easiest which is to pass the data in prepareForSegue
. which you don't have to care about dismissing the controller or keeping a track of inner view controllers,because storyboard will take care of it.
The second way is to set a Storyboard ID
in storyboard,for the controller you need to present programmatically, which need more things to handle, like to dismiss the controller or keep track of inner presented controllers.
let nextViewControllerName = storyboard?.instantiateViewControllerWithIdentifier("Storyboard ID") as! nextViewControllerName
nextViewControllerName.event = self.event
self.presentViewController(nextViewControllerName, animated: true, completion: nil).
At the end they does the same purpose.
Note: You should always pass the data before presenting the controller.
Related Topics
Swift Good Coding Practice: If Statement with Optional Type Bool
Didoutputsamplebuffer Delegate Not Called
Ios: How to Create Expandable Tableview in Swift Without Using Third Party Libraries or Pods
Rxswift - Generic Parameter 'Self' Could Not Be Inferred
Cgaffinetransformmakerotation with Negative M_Pi
Uitextview as Inputaccessoryview Doesn't Render Text Until After Animation
Vnfaceobservation Boundingbox Not Scaling in Portrait Mode
Swift 3 - Loading Multiple Viewcontrollers at Launch
iOS 8: Autorotation Is Not Working Without Storyboard
How to Work with Udp Sockets in iOS, Swift
Video with Gpuimagechromakeyfilter Has Tint When Played in Transparent Gpuimageview
Save Struct in Class to Nsuserdefaults Using Swift
Records, Zone Doesn't Displayed in Dashboard and Delete Zone Issue Cloudkit
Navigationlink Inside Lazyvgrid Cycles All Entries on Back, Swiftui
How to Convert Base64 into Nsdata in Swift