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
}
Related
I am trying to update my firstVC "like Button" Status once the user enters the SecondVC and likes or unlikes the heart for the cell they entered. I've tried a ton of different ways today but none seem to work properly. Any help or ideas
Basically. The user can click on a cell, then gets directed to another view controller which they also can change the status of the like button in there. Once they return back to the mainVC I want the like button to display the change.
I'm wondering if I am suppose to save the cells data locally in the phone or just send variables back and forth to each view controller. But if I send variables back and forth, how do I send a variable back to the first VC to the specific cell and let it know that the cell like button is no longer liked. I hope I make sense. Thank you all in advance. Still new to swift here :)
I think you can use the delegate pattern
protocol ViewController2Delegate: class {
func buttonStatusDidChange(_ viewController2: ViewController2, to status: Bool)
}
Add this property to the second view controller:
weak var delegate: ViewController2Delegate?
When the button status change, call:
delegate?.buttonStatusDidChange(self, to: true)
Make the first view controller conform to the protocol:
extension ViewController1: ViewController2Delegate {
func buttonStatusDidChange(_ viewController2: ViewController2, to status: Bool) {
// change the button according to the status
}
}
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
I have a problem understanding what I can do with the default Back BarButtonItem and how I can instigate a rewind.
The following shows a simplified layout. I embed a ViewController in a Navigation controller and add a BarButtonItem ("Show") and connect to a second VC. This adds the "Back" button to the second controller as shown below.
In the first VC I will show the user some details, in the second VC greater details will be shown. With the show button and the default back button the user can easily navigate back and forth with expected behavior.
My problem comes in that the user will be allowed to modify the "More Details Here" and I will need to pass that to the first VC after the user unwinds back.
I cannot control-drag from the Back to the Exit icon but I have determined I can do this with a "Save" button on the navigation bar as shown. (First dragging an Navigation Item to the top, then the BarButtonItem) then control-drag to Exit icon.
With the Save button, I can initiate a segue unwind and capture the changes back in my first VC with code like the following.
#IBAction func unwindFromSecondVC(_ sender: UIStoryboardSegue) {
if sender.source is AddCharacterViewController {
if let senderVC = sender.source as? SecondViewController {
details = senderVC.newDetails
}
}
}
This creates a problem when the user makes a change and then clicks the back button thereby loosing the changes.
My preferred solution would be to have the back button initiate a segue and transfer the changes. But this does not appear to be possible. My second solution would be to have the back button notice a transfer has not been made and stop the unwind seque. Neither approach appears possible based on my research.
How should I best handle this problem while giving the user the common Back navigation?
If you want to save any changes the user has made in the second VC, you could create a SecondVCDelegate:
protocol SecondVCDelegate : class {
func detailsDidChange(newDetails: String)
}
In SecondVC, declare a delegate property:
weak var delegate: SecondVCDelegate?
And whenever the details change (the text field's value changed, or whatever event happened), you call
delegate?.detailsDidChange(newDetails: newDetails)
In FirstVC.prepareForSegue, you should set self as the delegate of SecondVC:
if let vc = segue.destination as? SecondVC {
vc.delegate = self
}
// ...
extension FirstVC : SecondVCDelegate {
func detailsDidChange(newDetails: String) {
details = newDetails
}
}
This way, whenever the newDetails change, FirstVC will be notified.
If you just want to notify FirstVC when the user leaves SecondVC, you could instead call the delegate in SecondVC.viewWillDisappear or a method like that.
I have a UIViewController that implements UITableViewDelegate, UITableViewDataSource and that contains a UITableView as a member variable. When a user click on one of the rows of that table, the app performs a storyboard segue to open the detail view controller. That detail view controller of course has a button in the top left of the screen that is the "back" button to go back up to the UIViewController with the UIViewTable.
So, suppose that I want to programmatically "click" that back button. How exactly would I do that in swift? This is the most recent version of swift (swift 4?) in XCode 10.1.
UPDATE:
So here is how I solved this. As the answers below show, it is possible to use self.navigationController?.popViewController(animated: true) to just return to the previous view controller. What I discovered I also wanted to do, however, was to call a specific method in that view controller so that it executed a certain behavior once it got shown. It turns out that is also possible, but in my case it was a bit tricky, since that prior view controller was actually a UITabBarController. Therefore I had to get the ViewController that I was interested in from the UITabBarController. I did it like this:
let numvc = navigationController!.viewControllers.count
let tvc:UITabBarController = navigationController!.viewControllers[numvc-2] as! UITabBarController
let my_vc: MyCustomVC = tvc.viewControllers![0] as! MyCustomVC
my_vc.some_function()
Here of course MyCustomV is my custom view controller class and some_function() is the method I want to call on that class. Hope this helps someone.
When You run a segue you perform a "pushViewController" method to the next view, so if you want to go back to the previous view programmatically you just have to do is pop the last view like so:
self.navigationController?.popViewController(animated: true)
UPDATE
You just need the if statement if you have multiple segues from that viewController, if not, you can delete and just cast the next view as you wish and set the properties, let the autocomplete write the *prepare(for segue... * method for you, so You don't run into any problems
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "yourSegueName" {
let destinationVC = segue.destination as! CustomViewController
destinationVC.labelExample.text = "Some text I'm sending"
}
}
Are you sure you need to "click" the button?
If all you need is to dismiss details view controller, you can just call navigationController?.popViewController(animated: true)
Or if you want to deal directly with button, you can tell it to send its actions: backButton.sendActions(for: .touchUpInside)
Or if you absolutely need to show button clicking animation, then you will need something like this (you should play and choose suitable delay):
backButton.isHighlighted = true
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
backButton.isHighlighted = false
backButton.sendActions(for: .touchUpInside)
}
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)