Sorry if the answer to this is obvious,
But I was wondering if anyone knew how to pass data from the detailed view to the master view of a UITableView system in swift using storyboards?
I have used prepareForSegue() to go from the master to the detailed view, but I don't think that that works when going from detailed to master. If it helps I'm working off the pre built "master-detail" template in Xcode.
Any help would be great appreciated. Thanks!!
There's a few approaches. It really depends what data you are trying to pass back. For example, if you're selecting a single item from a list, I'd define a delegate protocol for the detailViewController and have the master controller adopt it. Define a property for the delegate in detail, and set it in prepareForSegue:
destinationViewController.delegate = self
Then in the detail controller when the choice is made you just do [delegate didChooseObject:object] (Obj-C, sorry, I don't do Swift yet.)
Alternatively, if your detail controller is changing some value in a data structure, you probably want to have some sort of separated model object that both master & detail operate on. Pass the model object into detail in prepareForSegue. Use Key-Value Observing in master so that it knows what detail changed (if it cares).
A third option is to use a "completion block". Pass the block into detail, and have detail run the block with whatever data got picked.
Related
In my application there are two view controllers that navigate to a DetailsViewController.
Right now, when the DetailsViewController appears, I fetch data from the server and display it on the UI. I dislike this because the UI is blank while the network request is going on. What I want is that the data be loaded in the previous view controllers and then passed to DetailsViewController.
Now the problem is that I have the exact same "load-data-and-then-push" code in two view controllers and I'm not sure what the most sensible way is to remove the repetition.
One idea is to have the two view controllers inherit from a common superclass which contains the loading/pushing method. I don't like this strategy because, supposing I have more ViewControllers like DetailsViewController down the line, I wouldn't like to write a loading superclass for each one.
Another idea would be to define a static method in the DetailsViewController which the two view controllers can invoke but this method contains UI related code (specifically, code to show an HUD Progressbar and a UIAlertView in case network fetch fails) which makes me uncomfortable.
I am very new to iOS and Objective-C so I might be missing something simple and obvious.
My favorite would be in this case to create a new class which handles the loading of the data (like http-request, etc.) and to create a delegate protocol for this class. This delegate callback might then be implemented in your two viewControllers which would then perform the push segue to your DetailsViewController when called. Delegation is a very nice and powerful feature, check out the documentation here: Delegation
Well, I'd better write it in the comments, but I have no reputation for that.
Imagine you are reading a json with several students information (name, year, etc.)
you can create a student object with the property that will be read and an object that will have a method that will run in the background that will be responsible for accessing your WS (JSON or whatever it is) and record this information to the student object. So if you have 10 students you will have an NSArray containing 10 students. This array is what you will for your next viewcontroller.
It is a lot of code, but you think examples easily.
If you use Storyboards you can use prepareForSegue: sender: to pass your data/model class to your DetailsViewController. If you use xib's you can do the same after instantiating the DetailsViewController and before pushing it.
If you need to load subsequent data from your server you should write a class that does this network stuff for you.
If DetailsViewController needs to load some additional data, you can use something like a loading view like Andy suggested. This is a widely used method.
I'm studying developing for iOS and while building a simple app which loads data from database and shows it as a tableview, I've got some issues which I fail to understand so far.
The master - detail controllers' classes were created by me, not by the XCode template, if this matters.
I try to pass data from master tableview controller to detail
controller. The data is as simple as a couple of strings. I use
segue for this purpose. In prepareForSegue method I do the
following:
if ([segue.identifier isEqualToString: #"DetailsSegue"]) {
DetailsViewController* dvc = (DetailsViewController*)segue.destinationViewController;
NSInteger selectedRow =[self.tableView indexPathForSelectedRow].row;
dvc.nameLabel.text = [NSString stringWithFormat:#"%#",
[[self.entitiesArray objectAtIndex:selectedRow name]];
...
}
The problem here is that dvc.nameLabel is nil. And I guess, that
is possibly because the controller has not been fully created yet.
Well, the dvc pointer is not nil, but I don't see the log in my
init method, so my idea that it was not initialized.
I decided to create an instance variable of DetailsViewController
and in prepareForSegue set it:
dvc->name = [NSString stringWithFormat:#"%#",
[[self.entitiesArray objectAtIndex: selectedRow] name]];
and then I set nameLabel property in viewDidLoad method
And it actually worked! So I guess I wouldn't be able to set instance variable of an unitialized instance. But I did. So what was wrong? And I feel this is not the way people do it,
as to have one more variable that holds the same thing seems
redundant.
So what is the proper way of passing a variable (in my case NSString) using a segue to another controller?
Thank you guys for help
The problem in your code is that you're trying to manipulate the other VCs views. Don't do that. Instead, you should create properties in the destination view controller to hold the data you want to display.
As the other poster said, it makes sense to create a class that contains the data for a record, and pass that. You might have your master view controller's model be an array of these objects. The master would use the data objects to populate a table view. When the user clicked on a row to open a detail view, you'd pass a copy of that data object to the detail view controller in prepareForSegue.
The detail view controller could then edit it if desired, and pass the edited object back to the master view controller if the user saved changes, or simply discard the edited object if the user cancels.
Yes, you could use a singleton to save your data model.
If you want to pass data, you're doing it reasonably. UI elements are not guaranteed to be initialized until the main view of the view controller has finished loading, so a non-UI variable is fairly common.
For a more complex app or one that you expect to grow and maintain, the better approach would be to create a class (or classes) that make up the application's data model. Anything that modifies shared data sends updates to the model and anything that needs to use shared data reads from the model. Among many positive results from that strategy, one is less crosstalk between view controller.
This is a concept question.
Like many others, I have a parent scene and a child or detail scene. When I click on a specific button in my parent scene, prepare to segue gets called and I pass over a couple of properties. In my detail scene, I gather more information and need to save it for use by the parent. I have seen various methods involving delegates, using singletons, and passing directly back to the parent properties. Here is my question, would it be more correct to store the data in a database in the detail controller, or pass it back to the parent controller to store it? It seems to me that since it was collected in the child, it should be stored there.
Would that be the more correct way of handling it?
For simplicity, say the larger model is an array of custom objects and the detail view presents and edits one of those objects. If you pass a custom object to the detail vc on before the segue, there's no need to "pass it back" later. The parent vc passed that object in the first place, so we know it already has a pointer.
Instead, the parent vc should notice that the work has been done on the object it passed and react accordingly (usually update it's view) This can be done by one of a handful techniques:
just assume something changed and update the view on viewWillAppear
notice the custom object changed via KVO (observing one of its properties)
be notified that the object changed because the detail vc posts an NSNotification
learn that the object changed by arranging to be the delegate of the detail vc
pass the detail vc a block to execute when it updates the custom object
It's hard to say what's better without knowing more about your situation. I can say that simple is usually better, and that favors (1). I can also say that delegates are fine, but often overused.
If you're dealing with more than a few pieces of information, it would likely be much easier in the long run to use Core Data. If, down the road, you decided to add more functionality to the app, or wanted to store different kinds of information, it would take no more than a few extra lines of code to do this.
But from what it sounds like, you have a really simple app, so you should probably be fine just making an instance of your "parent scene" in your "detail scene" and storing whatever values you may have in the "detail scene" into properties that already exist in the "parent scene".
Does that answer your question well enough?
I am pretty new to stackoverflow so please let me know if there's anything I should add or leave out in my posts from now on.
problem:
I have one original view controller that has a tableview on it with 2 options, "Date" and "hairstyle" the user is able to click on one of these table cells and it brings them to a new view controller where they can select a hairstyle/date. When they click done, they're chosen date/style reflects on the original view controller. The problem is, that it won't reflect both choices at once. Whenever you try to reflect one, the information from the other is reset for some reason.
Feel free to let me know if there is any more information you would like me to share in this post. Thanks for all the help.
Whenever your detail view controllers are about to pop back to the original view controller you can send the data using prepareForSegue.
In order to give you more detailed info we need more details about how you are doing things.
Eagle11 is right you need to use prepareForSegue, before jumping to code you better check this very useful(for me) links:
Passing Data between View Controllers
iphonedevsdk (my personal favourite)
Storyboard tutorial
Passing Data Between VC
Some issues:
passing data between views
I found this in SO; it doesn't exactly answer my question, which is: is there a way to clone a UITableView from one controller to another while using Storyboards and maintain synchronization?
You can clone them in the sense that their initial property values remain the same, like position, layout etc. For this, just copy the UITableView from storyboard, go to destination view controller and paste it there.
If you share same UITableView object between two view controllers, it is still possible, but you must estimate how much work you would have to do yourself. When a view controller solely handles a table view, much of the work is done under the hood and table is handed over to you. In case of your UITableView shared between two view controllers, you would have to play with it quite carefully. You need to take care of entire life cycle of the view - see the usual methods like viewDidLoad, viewDidAppear and so on. How would you take care of them when your view exists in two scenes? Maybe you would be inventing a unique design pattern - if at all you find the most optimistic and programmatically correct way to accomplish it.
With storyboards, you cannot achieve cloning up to the level wherein data changes will reflect seamlessly between the two. Storyboard is, as the name suggest, just a board, where you can draw things to know how would they look initially, before your code takes over.
In order to achieve what you want, you have to create a shared model that updates two table views through proper delegate methods. Most likely such a model (NSArray, or any such collections as per your requirement) can reside inside a shared class (app delegate isn't a wrong choice), from where both your view controllers can refer to it. That is neat practice, it not only is right from programming perspective but also extensible and helpful to anyone who deals with the code any time.
For details about how to update UI from your model, there is nothing better than starting from scratch, going through the books I mean.
I am not aware of such possibilities.
I would pass the tableview source object amongst different controllers and let the view controller handle their own table view.
I think the best approach would be to use a framework such as the freely available Sensible TableView, then use the same model for both table views. This should be really straight forward.