Situation
Let’s say there is an iPhone app that shows articles. Articles are loaded from a server.
It has two views.
TableView: Shows list of articles
DetailView: Shows detail of selected article
Problem / Question
I want to know better way of passing data from TableView to Detail View.
Which one of the following is a better practice?
Option 1
Pass an actual Article object from TableView to DetailView
DetailView just displays the Article
Option 2
Pass reference ID of Article from TableView to DetailView
This case, the DetailView loads the article from server by the ID of the Article.
Option2 seems a better design since relation between TableView and DetailView is minimum.
Option1 seems a little bit faster since i doesn’t have to connect to API ever time it loads an article
I understand it depends on situation but i would like to know if there is any reasonable guideline.
You should use a combo of both since many apps such as Facebook also do the same. For eg. if I have a photo that has likes in my notification bar, I can click on that photo and see it even if I do not have an active connection at that time. I will obviously be shown the older data. However at that time, Facebook immediately sends a call to the server and the updated likes are shown.
Therefore it should be ideal to pass the entire object to the next VC and immediately send an async call to the server. Any changes should then be reloaded in your complete data model. Hope this helps :)
Related
What is the best way to have multiple UIViewControllers that can be accessed from a side menu and without having to re-download any data each time the view controller is shown?
Say for example I have three view controllers, one is a homepage that shows recent notifications, one is a news page that shows recent articles and one is a page that has a collection of images. When each view controller is loaded, data is downloaded from a remote server and displayed - if the user switches to another view controller and back again I want the previously downloaded data to be shown immediately without having to be re-downloaded (until a UIRefreshControl is used or similar).
Off the top of my head I can see this being achieved in 4 ways:
Store the data in a singleton and load the data from this if it has been previously downloaded, however, this seems to go against general practices that I have seen and also doesn't seem efficient - especially if there is a lot of data and/or multiple view controller.
Use a UITabBarController that selects the index based on the side menu instead of the traditional bottom bar, would this cause issues if there were 10-12 items on the side menu?
Cache the data to disk (using NSCache etc) and instantiate/dismiss each view controller as needed, the view controller can use the cached data - only one view controller will exist in memory at a time.
Use some kind of customised container view that caches the view controllers and loads them as they are needed, feels a bit hacky and not very efficient?
What are the best ways to achieve this? Most tutorials I see just show how to segue/present view controllers but I have struggled to find anything that explains how to preserve the data that was downloaded on them.
Just as an FYI. If one of your ViewControllers is supposed to "show recent notifications/articles" then caching data won't work because it might not be the most recent unless you pull from the server every time. (Unless the recents are getting pushed and even then you might have huge sync issues if you don't pull every time.)
That said, you options 1 and 3 are effectively the same, the only difference is where you are keeping the information.
You should not be using a tab bar controller. If you can't use UISplitViewController then you should make your own custom container view controller.
As for the caching issue. I would implement some sort of caching mechanism for each endpoint. It could store in ram or on disk but I think in ram is better because the data sounds pretty volatile.
Set it up so that when a view controller makes a "network" call, the function it uses calls the closure with the last data it pulled and then optionally can make the network call again and call the closure a second time with the new data. This way the VCs will be very responsive in getting data up ASAP and still pull in the new data on every view will appear.
I would go with a combination of option 3 and 4.
There are many formats you could use to cache the data to disk. You could use a database like CoreData or Realm, or write directly to files as a Plist, JSON, NSKeyedArchive.
You probably should build a container view controller as well. Thats what a TabBarController is after all. It's pretty easy to do and the docs cover what you need to do. This will make you app more efficient by only having to load data from the database/file the first tome you go to the view controller. Then when switching sections, it can just show the VC thats already been loaded.
What I basically want is to show the user's name in the first tableView but have a disclosure indicator (segue) to go to a second tableView which will show the history of the selected user. I know how to load data into a table and how to segue from one row to the detail table but I just don't know how to show different data for each user. I know this may be out of my scope of knowledge at the moment but I would like to give it a try.
1- What would be the best way to store the data for each user (history), an array per user?
2- How can I relate data to a specific user so it loads when the user's name is touched?
3- How can I capture the row being selected?
Any suggestions will be appreciated.
Honestly, you shouldn't worry about it being outside of your scope of knowledge, as that's how people learn. You will need to do some amount of work, however, and that part can be a little difficult.
Luckily, what you're trying to do is a very well documented function and Xcode even provides a template for master -> detail views.
Check out this wonderful tutorial by Ray Wenderlich on creating a simple master-detail application: http://www.raywenderlich.com/1797/ios-tutorial-how-to-create-a-simple-iphone-app-part-1
His other tutorials will also be immensely helpful to beginning iOS development: http://www.raywenderlich.com/tutorials
In my iOS app, there are various Core Data entities that represent things like Appointments, Notes and Contacts.
I'd like the user to be able to edit selected attributes of each entity via a UITableView. Similar to the iOS Calendar app, when you click 'Edit', you're presented with a UITableView with editable values for Start Time, End Time, etc.
It's occurred to me that there could be a large amount of code re-use going on here, so I'm now considering creating a generic class, ManagedObjectEditorViewController that takes a managed object, displays selected attribute values within a table view, formatted according to their type, and allows them to be edited.
I can think of several neat ways of doing this, but before I spend a long time on this, I'm wondering if there's already something out there to accomplish this task? It seems like such a frequently used approach that I can't believe there isn't already some open source code out there.
Anyone heard of, or used anything similar?
I am about to do the same thing. Just started and works so far. A table that represents an NSManagedObject (Detail to a master view controller, has aspects of a master view controller itself.).
The whole table represents one NSManagedOjbect. There are fields and other controls that correspond with the simple properties.
There are to-one references where the referenced object is just displayed but can be changed.
There are to-one references which are editable NSObjects itself where 1 and exactly 1 of them exists.
There are to-many references which can be added, deleted and edited. Pretty similar to the calendar app or the address book app. (from a functional point of view. It looks different though).
For that I establish a delegate between the table cells and the view controller. This is mainly because I try to stick on the MVC pattern.
E.G. the cell serves as delegate for UITextViews, UITextFields or as target for Buttons etc.
The (Detail-) View controller which owns the NSManagedObject and all related objects serves as my delegate for the cells. It provides methods similar to IBActions to the cells so that the cell can 1) inform about the event and 2) hand over a related view, if required (I need that to display some popups accordingly) and 3) the object itself e.g. the object that is to be deleted or a person-object for which the data is to be fetched from the address book etc.
The View controller can then does its very own duties which is invoking other view controllers (Send Mail, select from Address Book, present a popover with options for the user to choose from, ...).
I just built that up yesterday evening. (It is a free-time project of mine).
I am happy so far but the concept is not really proven yet :) .
What is your current favorite approach?
I'm making a sample app to learn iOS dev, and I have the app create default items to populate the tableview originally, and you can add further ones as well.
If I tap on the default ones (well, there's only one) and segue to the detail view it shows all the details (Name, Location and Date) as intended. But if I add a new one, it comes up with those fields being Empty.
I can't figure out why. I have seemingly all the view refreshing methods set, and it should be setting the detail view's data object which then feeds the labels.
Could anyone help? I'd supply further code if requested, I just don't know what to supply now as I'm not sure exactly where the problem is. It's a rather simple app, though.
Project available here: http://cl.ly/3N0o272M3y1K
Ok this took a bit longer than planned - but it is a good way to learn.
I have attached the project in a zip file.
The code is a bit different then what you posted, but if you compare them side by side, you will see how they are planned and build differently.
It shows the Segue working within the Storyboard.
There where 2 big problems with your project outside of your misuses of the methods.
You need something like Core Data if you want your data to be persistant. In the example I have given you I have used Plist, this will do the trick, but is not persistant in this case.
Also your detailViewController had no labels for the text to appear, so you will need to look into Custom Cells for that - to match your design.
Good Luck and I hope this is useful:-)
Updated Project
I have two buttons on a action sheet, when I click one of the button, it will display all the students record in another view. All these records need to be retrieved from DB. Currently I put the logic of retrieve the record in the viewwillAppear method, But after I click the button the screen froze there for a few seconds then the student list will displayed.
Per my understanding my logic of retrieve the record was in viewWillAppear method in student list view. After I click the button , it should to directly to student list view , then in the student list view it will try to load the data. But now after I click the button why it froze in the action sheet? Or are there any other place that I can put the load record logic in so that it will not froze in the previous action sheet After I clicked the button.
If you're going to post to SO, you always should include your existing code. I'd suggest you update your question accordingly. See the FAQ.
When you say that it "froze", do I infer that you're saying that there was a delay before you saw your new view with the data, but that it eventually appeared? If so your task is how to identify where the delay took place. So, I'd suggest you start inserting NSLog statements in the various methods so you can identify where exactly the delay is taking place. Did it take a long time for the new view to be loaded? For the data to be retrieved? Etc. Until you narrow down the problem, identify the source of the delay, you won't be able to solve it. You need to develop the skills to diagnose and troubleshoot your problems. By the way, if you're still having problems figuring out how to diagnose your code and the NSLog doesn't help, you can also refer to Apple's documentation on debugging and stepping through your code. You should only post here after you've narrowed down precisely where in your code the problem is manifesting itself.
Third, most people load their data for their new views in viewDidLoad, not viewWillAppear; if you ever went to a subview of your student list view and then came back to your student list (i.e. the student list view reappeared, i.e. viewWillAppear will trigger again), would you really want to load the data again, even though you've already loaded it? Probably not. I know you might not have another view that you're loading after you load your student list view, but you may eventually (e.g., a student detail view), so good practice is that you should load your view's data in viewDidLoad (which will trigger only the first time the view is initially loaded).