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.)
Related
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
What is the preferred method of creating detail view controllers for table rows? Let's say I have a UITableView with 100 rows in total. Each row can show a detail view controller. Should I re-allocate a new detail view controller for each row selected, or can I re-use the existing one using some sort of reset method?
Right now I have both options present in my code:
For side swiping, I reset the same controller using a short fade animation.
For Core Data UITableView, I allocate a new controller for each row.
Should I try to reset the UITableView's detail controller when rows are selected, or is it a bad practice?
Update:
I ended up allocating the controller for each table row selected. Within the controller, I added 2 extra buttons with fast forward and reverse icons. These allow the user to traverse the table data one by one, viewing all the details. I found that going back to the table to select one row after another to be too tedious.
The extra buttons reset the controller for next/previous event. Since I'm using only one controller, I cannot user Core Animation to perform a view transtion. Instead, I scale the buttons on the controller to indicate that something has happened with "fast forward" has been tapped.
thank you!
I think the answer to your question depends on a number of factors, but it's definitely a very good thing you have both options currently present in your code. This gives you a chance to run Instruments and do a bit of memory profiling and allocation tracking.
The way I'd do it would be to check out what the difference is in memory between opening up one detail view controller and then instantiating 10, 20 or even all 100 detail view controllers.
If the memory footprint increases dramatically, I might be inclined to do the "reset the detail view" route.
If there's really only a small increase in memory for each detail view created (and it's faster to not have to reset everything on each table row selection), then I'd go that route.
so i want to achieve something like this:
when clicking on this cell, there should pop a new tableview with the items availible, by clicking one of these items, it should go back and update the cell. normal stuff i think.
but i'm not shure how to do it the best way.
first i need to subclass a uitableview cell , because there is no default one for this, right?
and the rest?
should i set an ivar to the new popped tableviewcontroller with the selected cell and update the content after an item was selected? but then i had to reload table data , don't i ? wouldn't this break my selection, the scrolled way and all this stuff? would be a bit weird while the navigation-controller goes back to this tableview.
please help me with some best practices for this.
thanks and please leave a comment if something is unclear.
That cell style is UITableViewCellStyleValue1.
I would write a custom delegate protocol that the parent controller implements so that the child controller can inform it when the user has made the selection. But you can also use a property on the child controller. Or use a notification.
To update the cell in the parent view controller, just call [tableView reloadRowsAtIndexPaths:withRowAnimation:]. No need to reload the entire table.
I want to add a refresh button in UINavigationBar that refreshes the entire table contents. Nothing happens when i click on the refresh button.
I searched google and found that reloadData method refreshes the tableview so I tried using it.
Are you sure your tableView outlet is linked correctly to your tableView property in Interface Builder ?
Is your internal datasource `refreshed' before you call reloadData?
-[UITableView reloadData] tells the table view to request again from you the number of rows in the table, and the cells at each section and row. It's up to you to update your internal data structures as appropriate. So in this case, your IBAction should call your own method to refetch the data from the server.
A few other notes:
Method names should have leading lowercase.
-initWithContentsOfURL: is blocking. This can hang your program for a long time. You should be using asynchronous fetching here (generally with NSURLConnection).
make sure you have the tableView outlet hooked up to the tableView.
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.