Updating a cell in UITableViewController after changes in a DetailViewController - iphone

I have a fairly simple setup: RootViewController (which is a UITableViewController). Each cell in it shows some stats for a different person. You can tap on any of these cells to push on a DetailViewController (UIViewController), and modify the stats (which are stored in a model object). After the user is done modifying the stats for that person, they click the Back button, causing popViewControllerAnimated to get called.
My question is: What's the best way to know in the RootViewController that the stats for this player have been changed, and updated the cell accordingly? Do I have to record in the RootViewController which cell was tapped, and then call the appropriate setNeedsDisplay after the DetailViewController completes? And if so, which method should I do this from? viewWillAppear?
Or is there a nicer way? This seems like it'd be a fairly common task, and that I'm missing something obvious.

This depends on how your model is designed and whether or not you're using Core Data.
The basic principle is to observe the properties of your model objects that might change in the detail views. When something changes in the detail controller, somehow mark its table cell as dirty. Then, when the table view becomes visible again, get the changed cell with [tableView cellForRowAtIndexPath:] and reconfigure the cell. The cellForRowAtIndexPath: method will handily return nil if the cell is not visible which will keep you from spending time updating cells that don't need it.
If you're using Core Data (and you probably should be), NSFetchedResultsController does almost all of this work for you. It will observe your model objects and send the controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: message to its delegate for each changed cell. Then, you can make the proper changes to the table view.
I recommend creating a new Xcode project using the Navigation-based Application template with the Use Core Data for Storage checkbox ticked. The template has a good default implementation of the aforementioned pattern.

Related

Detect when NSTabview reloads in Swift

I am trying to add a label to the window whenever the tableview item count is zero. I figured that the best way to do this would be to check tableView.numberOfRows after tableview reloads . However, I can't seem to find a way to detect it when the tableview reloads. Is there a way to do this?
Table views don't spontaneously reload. You tell them when to reload. You should probably have a central data model object, and have it notify your view controller when the items count reaches zero. (You could set up your data model object to have a delegate, for example, and give the delegate a itemCountChanged(to:) method.)

Swift - Reuse the old instance of view when switch between Views and Passing data over views

I am trying to create a simple app and here is how it works:
When the user clicks the button "Picking", it'll show a tableview. And when the user selects a row in the table view, it will show the first view and display the data on the label.
I have 2 problems:
Every time I click the button "Picking", a new instance of the table view controller gets created; but does not reuse the existing one. How can I make it reuse the old one?
I want to pass the selected data to the root view. I tried by creating a segue to show the root view when user selects a cell and then passing the data on prepareForSegue method. But, I faced the above problem of memory leak. How do I pass the data between screens without leaking memory?
It sounds like you may be making a circular view hierarchy. When you tap on the cell in the table view, if you're pushing a new instance of the first VC, that is the wrong way to do it IMO.
Instead, you should pass the data back to the first VC then dismiss the second VC. Then, when you tap on the "Picking" button again, it's a new instance of the table view but your previous instance has already been removed from memory.
This allows for the smallest amount of memory to be used at any given time. When the table view controller isn't on the screen, it doesn't need to be in memory.
IMO, the best way to pass data up a navigation stack is to use a protocol and delegate. It's similar to how Objective-C protocols and delegates worked if you're familiar with that. Here is Apple's documentation on both. The delegate section is about 1/3 the way down the page.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

iPhone programming guideline : List / detail / modify

I have a program that displays a list (a TableView).
When the user clicks an item, it's detail is shown.
On the detail view, the user can ask to modify it so a modify window is shown.
Here, the user can ask to delete the item.
I would like at this time return to the list with the item deleted from the list and from the data source.
There may be thousands of methods to do this, but I wonder which is the best / good one.
Could you help me, and/or give me a good reference to read about this ?
I think he ask how to get from view number 3 back to first view.
Then you can put your three views inside a UINavigationController and call on the last view popToRootViewControllerAnimated:
at least Two options:
Delegation - Create a protocol called something like: TableDetailModifierDelegat
and add methods like modifierDidChangedItem:(id)item
or modifierDidDeleteItem:(id)item
and to the modifying view controller add instance variable id so when you done editing or deleting you will call the appropriate methods.
of course you will need to make your table view controller implement the protocol you created. if you modified or deleted an item you should update your data source and reload the data to the table.
also pass the Table View Controller as the delegate when creating the Modifying View Controller.
Passing The Data Model.
This is much more simple to implement.
you can simply pass your data model to the modifying view controller, and make the changes directly to the data model.
You should keep the data model as Instance Variable in the modifying view controller.
when you done, dont forget to reload the data to your table.
In this instance, you could simply remove the data from the data source the UITableView is using and then call the reloadData method on the table. (As you're editing the data in question, you'll presumably have a suitable method/reference by which to delete it.)
As a bit of reading, I'd recommend Apple's Table View Programming Guide for iOS - this provides a lot of useful background information.

What's the best way to refresh a UITableView within a UINavigationController hierarchy

I'm pretty new to iPhone development and have struggled to find what I consider to be a neat way around this problem.
I have a user interface where a summary of record data is displayed in a table inside a navigation controller. When the user clicks the accessory button for a row, a new view is pushed onto the navigation controller revealing a view where the user can edit the data in the corresponding record. Once done, the editing view is popped from the navigation controller's stack and the user is returned to the table view.
My problem is that when the user returns to the table view, the table still shows the state of the data before the record was edited. I must therefore reload the table data to show the changes.
It doesn't seem possible to reload the table data before it is displayed as the call only updates displayed records. Reloading it after the table has been displayed results in the old data changing before the user's eyes, which I'm not too happy with.
This seems to me like a pretty normal thing to want to do in an iPhone app.
Can anyone please suggest the best practice approach to doing this? I feel like I'm missing something.
Cheers - Steve.
The standard approach may sound like a lot of hassle at first, but is a useful pattern for a lot of situations.
In your tableview class create a method like:
-(void)editDone {
[self.tableView reloadData];
}
Add a property to your edit controller like:
#property (assign) id delegate;
Set the delegate when your accessory is clicked:
editController.delegate = self;
And when editing is complete, call your method like so:
[delegate performSelector:#selector(editDone) withObject:nil];
You can create similar methods to handle cancel of your edit component, or to carry out dismissing of modal edit controllers, etc. It's considered more classy to put all this in a protocol, if you like.
I'd implement this in the following way:
Save indexPath of a clicked cell.
Implement -[UIViewController viewWillAppear:] method of the view controller, which contains the UITableView. If saved indexPath is not nil, reload specified cells with:
-[UITableView reloadRowsAtIndexPaths:withRowAnimation:]

Passing data from modal navigation controller to parent controller?

I'm starting out in iPhone development, and I'm trying to do a Contacts-style controller to add items to a table. I've got the two controllers designed, but I can't seem to figure out how to pass data between them. How can I get data from the modal controller to its parent?
Just trying to call methods on parentViewController won't work (and results in compiler warnings and crashes). I've considered moving the data out of the controller itself (which is going to happen anyway, I'm just trying to keep things as simple as possible for now), but even then I still have to somehow tell the parent view to refresh its data. Again, how can I do this?
I've considered moving the data out of the controller itself (which is going to happen anyway
I think now may be the time to follow that consideration and create a separate "ContactList" model object to store your data.
Your modal view controller just adds new "Contacts" into the "ContactList".
Your TableViewController should observe the same "ContactList". As items are added/removed to/from the "ContactList" your TableViewController will simply add and remove rows from its tableView.
In this way you will keep each ViewController independent, your code will be more flexible and adding/removing single rows will be much more efficient than reloading an entire tableView.
You either keep a link to the sub view you create and ask it for data that has changed on return, or else ad yourself as a delegate of a subview and have it call you back directly (which does work if you have a valid reference).
I had the same question and found this sample code: http://developer.apple.com/iphone/library/samplecode/LocateMe/Introduction/Intro.html
Helped me a ton and was pretty easy to figure out from the code.
In short, use delegate.
I would suggest you have a look at Lecture 11: Text input, Presenting content modally (May 6) - iPhone App Programming course offered by Stanford. Search for it on iTunes U.
Download this sample app if you want to know how to implement delegate: http://www.stanford.edu/class/cs193p/downloads/11-Pickers.zip