How do I segueing to the UIViewController I'm in? - swift

I'm trying to go from one view, filled with data from an object, to the same view but filled with a different object via segue.
Using a segue is necessary as apposed to switching the object and refreshing the view because my users need to be able to go back to the past view controller when they hit the back button.
Example:
(ThisView, with thisObject populating the view) -> (ThisView, with thisOtherObject populating the view)
What I've tried:
presentView Controller: This didn't work because it is not the default segue I'm trying to achieve.
let next: NewClubProfile = storyboard?.instantiateViewControllerWithIdentifier("clubProfile") as! NewClubProfile
presentViewController(next, animated: true, completion: nil)
Using Navigation Controller: Can't figure out how to segue the new object to populate the other view
let next: NewClubProfile = storyboard?.instantiateViewControllerWithIdentifier("clubProfile") as! NewClubProfile
self.navigationController?.pushViewController(next, animated:true)

Should have taken longer to solve this myself before posting this but I couldn't find an answer that fit what I needed. Anyway, solved it, here's what worked for me.
let next: ViewController = storyboard?.instantiateViewControllerWithIdentifier("viewName") as! ViewController
next.object = newObject
self.navigationController?.pushViewController(next, animated:true)

Related

UIPageViewController wont refresh UITableViewControllers

Have a controller, we'll call it Bob, as a modal and it contains some labels and a UIPageViewController that loads 2 table controllers. The first time the page controller loads it loads the table controllers with all the correct data. Whenever Bob is opened again the table controllers data does not change. Bob's labels do change so it is receiving different requests from it's parent.
pageController is the name of the UIPageViewController
I've tried doing the following in the datasource section for the pageController
pageController.dataSource = nil
pageController.dataSource = self
but it didn't work. I've also tried setting the controller again after the new data is loaded and that didn't work either
pageController.setViewControllers([viewController(At: 0)!], direction: .forward, animated: true, completion: nil)
In the table controllers they are set to refresh their data like so and this is called after the new data is passed to them. I've verified that this is called whenever Bob is opened.
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
I've also tried recreating the UIPageViewController altogether and that didn't work either.
I'm really stumped as to how to get the page controller to reload the table controllers with the new data. I don't think the issue is at the table controllers but I'm open to trying anything. Anyone have any ideas?
So the cause wasn't any of what I had listed. Go figure. Instead it was how I was defining the table controllers. I was setting the value they where to use for loading when I was defining the controller and not at the time of when I load it.
So
private lazy var thatTableViewController: ThatTableViewController = {
let storyboard = UIStoryboard(name: "ModalsStoryBoard", bundle: Bundle.main)
var viewController = storyboard.instantiateViewController(withIdentifier: "ThatTableViewController") as! ThatTableViewController
viewController.view.tag = 0
return viewController
}()
used to also have a line like so
viewController.controller = Controller(id: self.markerId, activeController: .Problem)
Controller is a custom struct that I was passing. But by setting this at the same level as where the variable thatTableViewController is defined it would not change between calls since it was cached. So moving the
viewController.controller = Controller(id: self.markerId, activeController: .Problem)
outside the definition part, allowed it get changed and not cached.
This then allowed me to remove
pageController.dataSource = nil
pageController.dataSource = self
since the data is defined at the time that I get the controller that I want to load and not predefined.
Hopefully, this will help someone else to not do the same thing I did and set any values you need the other controllers to use to be defined not when you define the controller but later on when you need to use the controller.

clearing variables of root view controller when switching tabs programmatically

I have a storyboard/root viewcontroller as the third tab on my app. On that tab the user selects an image, and writes a caption, which are stored as variables. From the root viewcontroller the user is taken to a preview screen via a segue which passes the variables, i.e. image and text. From this screen the user posts the object. From the post button, I am popping the viewcontroller, and programatically navigating to the first tab of my app. That all works, but the problem is when I then navigate back to the third tab, the stored variables are still there, and I'd like them to be cleared out.
I've seen many posts on keeping the variables, but none on how to reset them. I've tried to use viewWillDissapear but I don't want them cleared when I use the segue because I want the user to be able to go back and make some changes if needed.
UPDATED CODE WITH CORRECT ANSWER
#IBAction func postButtonPressed(_ sender: Any) {
PostFunction.createPost(image: self.postImage, postText: self.hashtag) { (true) in
self.tabBarController?.selectedIndex = 0
let tab3 = self.tabBarController!.viewControllers![2] as! UINavigationController
let vc = tab3.viewControllers.first as! PostHomeVC
vc.clear()
self.navigationController?.popViewController(animated: false)
}
}
Any suggestions on how to "reset" the rootviewcontroller from the above method?
Thanks!
I am popping the viewcontroller, and programatically navigating to the first tab of my app
before you do the programmatic switch to the first tab do
let tab3 = self.tabBarController.viewControllers[2] as! UINavigationController
let vc = tab3.viewControllers.first as! VCName
vc.clear()
or
let vc = self.navigationController!.viewControllers.first as! VCName
vc.clear()
and write that clear method inside the vc as you need

Segue and Unwind segue without UI element

I have been looking for an answer for this on SO without success.
I have UIViewController A and B. They are NOT linked in Storyboard, and I want to perform a Segue from A to B, and upon clicking a button in B, to activate an unwindSegue to A.
So far I have :
1) The #IBAction in A to unwind back to
2) The function to prepare the Segue from A to B (In A)
3) The button to call the unwindSegue from B to A
What I'm missing is the logic of the function in 2.
More info about B:
Title: FilterView
Class: FilterViewController
Storyboard ID: FilterView
I tried creating a segue:
let segueToFilter = UIStoryboardSegue(identifier: "SegueToFilterView", source: self, destination: FilterViewController)
Thinking this might just get me what I need.
but I get this error:
Cannot convert value of type 'FilterViewController.Type' to expected argument type UIViewController
Help would be appreciated :)
I still do not understand how segues are causing problems to you, but if you really really don't want to use segues, you can try presenting and dismissing VCs programmatically.
The idea goes like this:
Create an instance of your VC
Pass data to it by setting some properties
Present!
In the VC, dismiss.
The actual code will be different if you embedded your VCs in a navigation controller. Instead of calling present and dismiss, you would call pushVC and popVC on the navigation controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "FilterView") as FilterViewController
vc.someProperty = someData // this is where you pass data
vc.present(vc, animated: true, completion: nil)
To pass data back, you should use the delegate pattern by creating a FilterViewDelegate that the first VC conforms to. Look up on Google for more info.

Opening window + view from an other view controller

I've got a ViewControllerOne. ViewControllerOne is connected via Ctrl-Drag (in storyboard) to a menu-button mBtn (which means I don't know how it is implemented programmatically).
Clicking on this mBtn, a ViewOne appears (present modal). This ViewOne is bound to ViewControllerOne. ViewOne has a button btnOne.
Clicking on btnOne I want ViewOne to be dismissed and ViewTwo to be shown. ViewTwo belongs to ViewControllerTwo and to WindowControllerTwo.
The WindowControllerTwo-ViewControllerTwo-binding is the standard case as created on a new project.
I have the following code in the IBAction for button btnOne in ViewControllerOne:
#IBAction func onbtnOnePressed(sender: AnyObject){
let m_WindowControllerTwo = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("WindowControllerTwo")) as! NSWindowController // I have no custom class for the window controller as I don't really know what I can use it for ...
let m_ViewTwo = WindowControllerTwo.contentViewController as! ViewControllerTwo // my custom class for ViewTwo
m_ViewTwo.attributeIWantToPassToThisView = self.x // an attribute I want to pass from view a to view b
m_WindowControllerTwo.contentViewController = m_ViewTwo // passing the attribute from a to b
m_WindowControllerTwo.showWindow(self) // this does not work
self.dismiss(nil) // see NOTE
}
This code actually does not work. On debugging it step by step, I'm seeing the window/view flickering but not appearing...
NOTE: I could connect the button btnOne with a ctrl-drag to ViewControllerTwo. This works. But then the current ViewOne does not get dismissed!
Question: What am I doing wrong here? In iOS swift this also works. I don't quite get the WindowController stuff, so I'll need your advice on this.
Instead of this: m_WindowControllerTwo.showWindow(self)
use:
let application = NSApplication.shared()
application.runModal(for: wordCountWindow) //this will present WindowControllerTwo modally.
then to close your present controller add this line: PresentWindowControllerName.close()

NSUserDefaults changing every segue

Sorry for the newbie question but i am really stuck.
I have a UIViewController and 4 tableviews in an app. When i click on a button on the UIViewcontroller it segues to a UITableviewController called "Beach". When the user clicks on a cell of the table, it segues back to the UIViewController and displays the selected cells title as the buttons title. The problem that i am having is when i click on a nother button to a tableview and then clicks on the cell, the previous buttons title sets back to the previous title.
i have a prepare for segue function in the tables view controllers and this returns the selected table title (named : Titleoftable) to the main VC which, the strings.
the way i am currently doing it is to make a NSUserDefault below but the problem still remains the same - The value changes top "" every time i click on another table V---
let path = tableView.indexPathForSelectedRow
let cell = tableView.cellForRowAtIndexPath(path!)
let persistenceStoreKey = "MyStringKey"
let stringToStore = "\((cell?.textLabel?.text!)!)"
// Store data
NSUserDefaults.standardUserDefaults().setObject(stringToStore, forKey: persistenceStoreKey)
NSUserDefaults.standardUserDefaults().synchronize()
// Get data
let myStringt = NSUserDefaults.standardUserDefaults().stringForKey(persistenceStoreKey)
destination.textOfBeach = (myStringt)!
destination.isBeachSelected = true
}
I have been stuck on this problem for ages now! PLEASE HELP!!
PS- I am using swift-2 and Xcode7
Make sure that you are not pushing a new ViewController after you click on the tableview's cell. It gives me the impression that it might be the case since you are seeing only the title of the last cell you pressed.. Make sure you actually pop the tableview's controller instead of pushing a new one.
If you want to keep using NSUserDefaults, you could just call
navigationController?.popViewController(animated: true)
in your cellSelection function, and read the defaults value in the viewWillAppear of the main ViewController.
override func viewWillAppear(_ animated: Bool) {
let userDefault = NSUserDefaults.standard()
if let beachSelection = userDefault.string(forKey: "BeachControllerSelection") {
textOfBeach = beachSelection
isBeachSelected = true
}
//same for the rest of the other table view's selections
}