How do I remove a view controller from the memory? - swift

I am using segues to present a new view controller. I have a 1 button that goes to VC 2. I am using this code:
func jumpToVC() {
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier("whatVC", sender: self)
}
}
However the VC will not remove itself from the memory. How can I achieve this? I am presenting my views modally.

I think that you got a little bit lost here. What you want is a segue that will cause you to change UIViewController object to another one. You don't need to delete the first UIViewController and it's against practice in Swift.
From what I guess, you're just starting your journey with Swift and I know how confusing it might be. Therefore, I recommend you try this tutorial: https://itunes.apple.com/us/course/developing-ios-9-apps-swift/id1104579961
I've recently learnt from that and it's the best thing I've found.
Let me know if you have any more questions and whether I can help you somehow.

Related

Open new ViewController from itself

I have a view controller where I present a multiple choice question to the user. The idea is to skip to next question, so I would like to call the same viewcontroller (newsViewController) again to each new question just changing the variable question. I have a button btnNetQuestionAction. I tried this solution, and it works fine. is this a good approach ? Any better idea ?
#IBAction func btnNetQuestionAction(_ sender: Any) {
question = question + 1
if question > total {
question = total
}
UserDefaults.standard.set(questao,forKey: "questao")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "newsViewController") as UIViewController
navigationController?.pushViewController(vc,animated: true)
}
There is no silver-bullet rule that judges whether it's a good approach or not. It's a valid code anyway, it depends on how it should behave.
Based on the current approach, a stand-alone view controller will be created for each question thus added to the navigation stack; It's a good idea if you believe that each view controller should have it own UI behavior (for example), it will be easy to maintain since they are separated.
Another option is to keep dealing with the same view controller by changing the question and reload the UI. Again I wouldn't confirm it's a better approach, but at least it's an available one.
I don't think this is a great idea. You are piling UIViewControllers one on top of the other. A much cleaner solution would be to have a data source for your viewController. Have the button message the data source, update the data, and redisplay your viewController.

NSView not being deallocated

I've got a weird situation here that's almost certainly because I'm new to macOS development and I am missing some core knowledge.
I have a modal sheet that I'm displaying programmatically. (I'm not using a storyboard segue because it needs to be the result of a validation and so far I haven't seen a way to launch a segue programmatically - that's a sub-question here if anyone has advice)
Here's how I'm doing it:
searchVC = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "SearchSceneIdentifier") as? SearchViewController
if searchVC != nil {
searchVC!.searchTerm = searchTextField.stringValue
self.presentAsSheet(searchVC!)
}
This presents the sheet nicely and lets me interact with it. In it, I'm using a class which has a delegate in order to return asynchronous search queries.
Where this gets weird is that when I call
self.view.window!.close()
from inside the view controller, I don't think the view controller is getting deallocated. This seems to be because the delegate is still connected to it, even though the object that has this delegate is within the scope of the view controller itself. This delegate appears to be holding the view controller in memory.
I've gotten around this by doing this before closing the window:
search.delegate = nil
But this is not a good solution for other view controllers that have the same problem because they are inside windows and I don't want to have to catch the window closing then send some kind of notification to each in order to nil-ify their delegates.
Another approach that seems wrong as well is that I keep a reference to these windows in the application delegate and nil-ify it from there.
All of these seem like nasty solutions to the deallocation problem and my hope is that there is a cleaner way of doing this. In Objective-C, reference counts were always a problem but there were patterns to handle them cleanly.
Any advice appreciated.
I updated all my delegates to weak var and that has solved all of my problems with deallocation.

How to get rid of or change a storyboard created segue programatically

I have a segue from one view controller to another, which was created in the storyboard of my project. I'm wondering if there is a way to change or get rid of that segue through code. Thanks, using Xcode 9 Swift 4.
Apparently it's not possible... look at the answer on this post. And the documentation says this about creating segues:
"You do not create segue objects directly. Instead, the storyboard runtime creates them when it must perform a segue between two view controllers."
Although it's not about changing or deleting the segue, I think it's the same logic.
If you just want to avoid the segue to happen you can do that inside "shouldPerformSegue" (like vacawama said in the comments):
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "aSegueIWantToDisable" {
return false
}
return true
}

Swift - TabBarController - Decide segue at runtime

i have the following situation:
In my TabBarController i have multiple tabs and it all works fine, but:
The destination of one specific tab is dynamic.
If a certain condition matches, this specific tab should open a NavigationViewController.
If an other condition matches, this specific tab should open a ViewController.
Are there any built in solutions?
How can i modify the destination of a tab at runtime?
Greetings and thanks
Long long ago, in a galaxy far far away...
Segues didn't even exist. So yeah
The UITabBarController has a setter in which you can pass the new view controllers you want it to handle. You won't be able to decide what shows at the point of the tapping this way, but you'll be able to change the controllers as the condition changes.
open func setViewControllers(_ viewControllers: [UIViewController]?, animated: Bool)
If you however DO need to decide as the tab is tapped... You could have your tab controller direct to a controller that's essentially empty, and use view controller containment for that controller to have the 2 options on it, and have one of them hidden. Pretty doable from the storyboard with very little supporting code. I think I prefer this option.
If you would rather continue to use Segues, then you can perform a specific Segue depending on the state of some condition variable like this:
func presentAppropriateView() {
if condition {
performSegue(withIdentifier: "ToNavBar", sender: self)
} else {
performSegue(withIdentifier: "ToVC", sender: self)
}
}
write a delegate method which you want to perform on certain condition on runtime and call
[self.tabBarController setSelectedIndex:0];
where index could be of your choice

Come back to the tabBarController, swift

Currently on my viewController : Upload, my button send the data to my database only if all the information are filled out, and I come back to the preview view (table View) with :
self.navigationController?.popViewControllerAnimated(true)
I would like, if it is possible, to come back to my main view on the tabBarController. I tried many things, like directly on the storyboard with Present modally segue to "TabBar controller", but I come back to the TabBar without sending my data to the database and without checking in the information are filled out..
How can I do it?
Thanks!
UITabBarController has a property selectedIndex with which you can switch the selected tab. So on completion after dismissing the UploadViewController you can run:
self.tabBarController?.selectedIndex = 0 // Index to select
It would probably be best to create a delegate for your UploadViewController to fire a function to do all the work in your previewVC on API call completion.
(Super late response...in case someone has similar questions, presumably in later version of Swift, such as mine which is Swift 5, iOS 13.2). Steps:
Be sure to set an id for your UITabBarController storyboard, e.g. "TabBarViewController"
Next, add the following to an action that has already been connected to a button:
let ID_TABBAR = "TabBarViewCOntroller"
#IBAction func returnToTabbar(_ sender: Any) {
let tabBarController = self.storyboard?.instantiateViewController(identifier:ID_TABBAR) as! UITabBarController
self.navigationController?.pushViewController(tabBarController, animated:true)
}
Referenced from one of the responses from this post.
Update: In case your Tab Bar View Controller also happens to be the root view controller, the two lines of the code in the returnToTabbar method above can be:
self.dismiss(animated:true, completion:nil);
self.navigationController?.popViewController(animated:true);
(ref.: See answer here, for Swift4 but works just fine in Swift5)