I have 3 viewControllers:
VcA: I read data with observers from database and pass with segue to VcB.
VcB: I read data and display it, with a button I call VcC to update data passing datas with segue.
VcC: a STATIC tableview in wich I update data and save them.
The problem is that when I dismiss after saved VcC and go back in VcB all data is old, even if in firebase all datas are perfectly updated.
In VcB for example I read the Title like this:
var groupName: String?
than in didAppear:
Name.title = groupName
Anyway if I also go back from VcB to VcC all data of the table are the old data.
To be more clear:
I call the database in VcA
click the name in the table and pass the data to Vcb, all is fine for now, title and other vars are ok
now I click EDIT and call to VcC, the table where I update the data, make change and save,
after save VcC dismiss and I go back to VcB -> title is still p2 but in firebase not!
I click again on EDIT to return to VcC (the edit table), title is the old one
I think that I have to recall datas from db... anyway to do it without refresh the data from firebase?
I know that if I go back to VcA after save all is fine but I really need to go to VcB, how can I do?
I found many threads, this is the most similar but not exact situation...
Reload tableView after dismiss a viewController
If I can follow this correctly.
VcC:
protocol %NAME%Delegate
{
func reloadData()
}
class VcC: UIViewController /*(or table)*/{
var mDelegate : %NAME%Delegate?
//in the func you use to dismiss self (VcC)
//mDelegate?. reloadData()
}
VcB:
class VcB: UIViewController /* (or table)*/,%NAME%Delegate {
func reloadData(){
tableView.reloadData()
//OR
//Observer for Firebase here to gather the new information. Make sure to reset all datasources if you do this.
}
}
Related
I have created all my views programatically and to the UIView I have created an extension. This extension is present in a different file called App+Extensions.swift
extension UIView {
func setupParentView() -> UIView {
//...
}
}
The setupParentView() gives me a view with my navbar and background colour. As the design is same everywhere I have used this function. This function is called everywhere in viewDidLoad. So, now in this function the navabar consists of points which need to updated every time the user has purchased/spent it.
So, now as this method is only called in viewDidLoad the function is not called again and the point value do not change in the navigation bar. So, how can I update the point value every time it is changed? I thought of using Combine, but this app will be available for iOS 12 users as well, and I am not using RxSwift, so any help?
Well ViewDidLoad won't get refreshed because your view is now in the stack hierarchy. Some override methods that do get called which have a relation to the view are viewWillAppear, viewDidDissapear, and viewDidAppear.
If your view is going back in forth and the point button needs to be updated everytime your view re-appears consider putting the "refresh" point number in one of the above methods.
Note if your sending info back and forth between two views its also best maybe implement a delegation pattern or an observer.
Use notifications.
In other words, have points be a property of a global object that lives off in "data space" as a singleton. Now just use a property observer so that whenever anyone changes that object's points property, it emits a notification through the NotificationCenter.
That way, any view or view controller that needs to update whenever the points property changes just has to register for that notification when it comes into existence.
[Basically, this is the mechanism, or one of the mechanisms, that you would be replacing or even using directly if you were using Combine or RxSwift.]
Create a custom view called NavBarView
This NavBarView has a property called point
var point = 0 { didSet { updateView() } }
You want to avoid singleton, single view object, so that not everything is coupled together.
You don't need RxSwift or notification to do this.
I have been working on an app that has a tableview where users can add information on a seperate ViewController via UITextField. I am now trying to set it up so the user can tap on any given Cell to be able to view the data back on that ViewController or edit it again. Everything is being saved using CoreData.
Best way is you can put the check like this. So that it will never crash or throw the error:-
if let sender = sender as? String {
guest.player = sender
}
I'm making an app in swift 3
I have a TableViewController, when I click on a row it opens a ViewController in which there is a TextView. When I click on it, I am able to edit it, but the changes are not "saved". when I go back to my list and re-click on the same row, the text is back to "Default", I've been on this problem all day, and I don't know how to solve it, I've tried solution from stackoverflow but only give solution to change the text colours.
So how can I do that ?
Based on what you've said so far, I can only assume that you are not storing the new text that's been entered into your UITextView.
The reason that the changes are not being saved is that every time you "open" a new ViewController by tapping on a TableViewCell, it is a brand new instance of that ViewController. That means that it has no input as far as what should be displayed in the TextView, and therefore displays the default text.
But how do I fix it?
This is going to require that you save your TextView's text every time that you leave or dismiss the ViewController. This is because when you leave the ViewController, it is being released from memory. This means that anything that was written there no longer exists. I would suggest storing the text in an array of strings on your TableViewController, which should allow for the text to persist over the life cycle of the app.
The text disappears when I close the app!
This is something that will require data persistence, and for that I would suggest reading up on how to use Core Data to store and persist data across multiple app life cycles.
There are many ways to achieve that, the idea is to set the text of the text view in its view controller's initialization.
So, you need a place to save the data entered by the user, and then read that data again in the view controller's initialization.
One way to do that is using a singleton class to save the data, like this for example:
class SharedData {
static let instance = SharedData()
var textEnteredByUser: String?
}
Now, when the user enters text, save that text in the string we have in 'SharedData' like this:
SharedData.instance.textEnteredByUser = textView.text!
Now, we have the data entered by the user saved, we need to set the data in the text view before it appears in the screen, and this can be achieved inside viewDidLoad method of your view controller like this:
override func viewDidLoad() {
super.viewDidLoad()
textView.text = SharedData.instance.textEnteredByUser
}
You can also save your data in user defaults instead of the singleton class like this:
UserDefaults.standard.set(textView.text!, forKey: "textEnteredByUser")
And then retrieve the saved text this way:
UserDefaults.standard.string(forKey: "textEnteredByUser")
Note: The singleton solution keeps the data shared between different view controllers, but does not persist data after closing the application, and this is what user default does.
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)
Let's assume I have an address book App.
So from the address list I now push to a detail view like so:
User taps on cell in the master list
Segue showDetail is invoked
In prepareForSegue: I set the model object contact of my ContactDetailViewController
viewWillAppear I add an observer for self.contact
So now when the contact object changes in the background, the detail view will automatically be updated.
In viewWillDisappear I remove this observer (I guess it's clean because it is symetrical).
However, viewWillAppear: is called after I set the contact. So should I setup the KVO differently or simply call my updateView function in viewWillAppear which is a bit stupid because I want to get rid of those calls with KVO in the first place.
When you call addObserver:... you want to include the option NSKeyValueObservingOptionInitial. This will cause KVO to send the equivalent of a didChangeValueForKey: notification (i.e. an "Initial" notification) in the same call that adds the observation. This should cause your view to update at that time.