A pattern for having the topmost UITableViewCell feature a "Settings" Cell - iphone

If it is unclear what I mean from the headline, I am referring to the functionality that is in the Facebook app where to topmost cell in a "Feed" view is a "Load new posts" button that extends upwards "forever". You have to pull it down a bit for it to display it self.
Background
In my case I reload the data for the entire UITableView (plain style) as the user type in a search field (which means fairly often), I then let the user filter the results using a slider. This functionality makes it so that there are more than one version of my data source, an array and a filteredArray.
If I were to implement the functionality the "quick" way I would set my:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.productListFiltered count] +1;
}
To return the count plus one, this would give me an extra cell.
Then I would have to go through cellForRowAtIndexPath, DidSelectRowAtIndexPath etc. etc. all the delegate methods for the tableView and do exceptions for when indexPath.row == 0.
It would have to riddle the controller with so many exceptions that it would be unreadable.
I could also try to change my model array, so each time It was set the data source for my tableVIew I would make the NSArray into an NSMutableArray and stuff an "empty" object in the first place.
This would also give some strange code as I would just have to move all the exception code to my CustomTableCellView (a custom view I add to the cell's subview). I populate the TableVIew often and from different places depending on whether the data is filtered or not.
Would it maybe be a better approach to attach a subview to the top of the tableView it self? but how would I go about giving the user the possibility to pull it on screen?
I am having a hard time finding a sound way through this, some way that does not fight the "best practice" for the UITableView.
Hope someone can offer a bit of guidance.
Thank you.

You should just use table sections. The search field and controls go in one section and the data in the second. When you return cells you just need to check the section and then access the data for that section instead of the other.

Related

Handling an empty Table view

What I am trying to do is pretty simple, I just want to display some message to the user that there are no entries in this table, rather than just displaying a blank page. An ideal example is in the app store, if you search for something, but get no results, it just displays in the middle of the page "No Matches".
I've looked at a few solutions, and decided that the one i like best is here But theres a few little problems with it:
1) I can still drag around the image as if it was just a very large cell in the tableview
2) when I try to re-add the tableview to the tabelviewcontroller's view, I seem to get some kind of infinite recursion that eventually crashes
Anyone know a simpler way to do this? Or how I can resolve my current issues?
Don't remove the tableView, just add an UIView with your message (i.e. UIImageView) on top off it. It only needs to be big enough to cover the tableView. Place something like
at the appropriate place in your UITableViewController:
if (results == 0) {
[self.view addSubview:noResultsView];
}
Dan F it's very easy all you need to do is the following:
if there is no data in your source, add one object like No Data Found
Set a flag like BOOL bNoDataFound = YES
in CellForRowAtIndexPath delegate check your flag is YES fill the only cell with your text that you set before

How to deal with Custom Cells when these are not visible and want to get the cell using indexPath?

Guys, I didn't find a clean and a simple solution for the following issue. I've a UITableViewController view which uses a UITextFieldCustomCell that I implemented.
The table has several rows, that requires the user to scroll down an enter values on each cell, which contains a UILabel and a UITextField.
Every time the user change the value on the UITextField the UIViewController gets notified and stores the value in a NSDictionary using the cell indexPath.row property, in order to identify what's the key for the cell where the value needs to be stored.
The problem is if the user keep focus on a cell and then scrolls up or down (removing the cell from the view) makes me unable to get the indexPath for the cell, since it's not visible.
So, I cannot store the value since I don't know from which cell the value is coming.
Have anyone run through this issue before?. It seems to be a common design between iPhone applications, does anyone have an idea if is this a good implementation or not?
Thanks!
I assume you're observing textFieldDidEndEditing:. Are you saying it's not firing, or that it is firing, but it's no longer in any of the cells (possibly because it's in the process of being removed)?
Assuming the latter, my approach would be to use setTag: on the UITextField to make it easy to keep track of its index. This would save you from ever hunting around in your cells, even in the case that they are on the screen.

sticky selected cell in UITableView like the new twitter ipad app?

any idea how to have the selected cell in UITableView sticky and remain visible while scrolling? like how the twitter ipad app works. i would like it on my splitview's uitableview.
You are probably using a UITableViewController right? This automatically deselects a selected row. To avoid this, the best option would be to use a normal UIViewController with the protocols UITableViewDelegate and UITableViewDataSource.
Building from a comment Vince made on my previous answer (since deleted since it was more of an explanation of how long and how much effort a feature like this would take rather than an attempt at answering the question).
You could store the index path of a cell when it becomes selected, and then as the cell is about to scroll offscreen (you'll need some trickery to detect this) you could retrieve the cell view returned from cellForRowAtIndexPath and set a section header view to use this cell view.
This would be a pretty monstrous hack though, and you'd need to find a way to elegantly split the table into sections in order to use the section header.
I wouldn't recommend this approach, although its a step in the right direction.

How do I create a TableView like in network Settings App on the iphone?

How do i make such a Table view? So if I turn on the switch, 2 cells should be added.
I've already tried
[tableView numberForRowsInSection:6];
[tableView reloadData];
but this doesn't work as expected :(
any ideas?
The best thing would be 2 sections the first section contains 5 cells, the second section contains one cell with a switch turned off and if the Switch has changed 2 cells will be added to section 2.(Added with an animation :))
mhh..
Thanks in advance, I'm very excited on every answer :)
Where did you pull this -numberForRowsInSection: method from? As far as I (and the documentation) know, it doesn't exist and has never existed as a method of UITableView. Guessing is going to get you nowhere, much less inventing methods from thin air.
Perhaps you should review some tutorials that cover the basics of using UITableView before you attempt this. I doubt someone is going to take the time to write you a full class to do this and put it in an answer, and you'll be much better off in the long run if you don't simply try to copy/paste code that you don't understand. There exists much documentation and examples that cover UITableView, and that's just considering what's available from Apple - UITableView is such a frequently used class that searching Google for something like "UITableView tutorial" is going to give you pages and pages of results.
I will give you a quick overview of what you would need to do, though:
1. Of course, you can start with the UITableViewController template in Xcode and start customizing it to fit your requirements...two sections, however many rows per section, etc, determining that based on some model-level objects if necessary.
You'll need to either create a custom UITableViewCell subclass or customize the default UITableViewCell layout a good bit (at least by adding a UISwitch subview) when you create new cell objects in tableView:cellForRowAtIndexPath:.
The UISwitch should be configured to send a message to your view controller when the switch's value changes using -[UIControl addTarget:action:forControlEvents:] for the UIControlEventValueChanged event.
In your implementation of the action method for this switch value change, you'll need to implement logic to determine whether rows should be added or subtracted, and then actually add or subtract the rows. You can use beginUpdates/endUpdates, insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: to have the nice smooth row animation behavior instead of simply calling reloadData.

When is the right time to change the datasource for a UITableViewController

After rendering a UITableView with a given datasource, I want to be able to switch to a different one prior to calling reloadData.
Tried doing it in the method
- (void)viewDidAppear:(BOOL)animated;
but as far as I can see this isn't called when all the visible cells are rendered.
By placing a breakpoint it seems as if nothing is actually rendered. So I must have misunderstood its actual purpose.
Is there a API callback for that or do I have to programmatically look for it?
e.g. in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
when indexPath holds the index for the last rendered cell in the tableview.
To put it into perspective (somewhat).
Suppose we have a UITableView which has a "static" datasource. Once all the static data is displayed, you want to switch to a dynamic datasource which fetches the data off the internet and reloads each row as fetched.
So I'm actually looking for the "right hook" in which to make that change from one datasource to the other.
Are there any other issues one should be concerned about?
Further clarification. I have written all the required code (e.g. an UITableViewController with the static data initialized, different datasources, background threads for the dynamic views, a delegate to notify the UITableViewController as new data is coming in) what I haven't figured out (what the question is all about) is when to actually make the switch from one datasource to the next.
When you call reloadData it forces your UITableView to re-query your data source regardless of the amount of data that is already loaded. Also, the cells that are not visible are not being loaded, so practically the last cell is only filled with data if and when you scroll down to it. If you know for sure that all your cells are visible at once, as you might have a small number of them, you might do as you suggested and call your update function when indexPath holds the index for the last cell in the tableview.
Edit:
In the light of your edits, I'm thinking that perhaps the moment you should switch data sources depends on the state of your "live" data - when you've got enough data in it to be able to show enough of it on the screen. That is, let the static data be displayed, and only switch when you've already fetched a number of values in your live data source.
Another idea might be keeping only one mutable data source, with pre-loaded static initial data. As you fetch new "live" values, you start by replacing the ones that you already have, and then continue adding new values if their number exceeds the initial number of static entries.
viewDidAppear is all about the view controller, not the table. The table reloading will never call that method.
What you want to do, is better handled either via a delegate approach or using notifications. Set up the static data set in viewDidLoad, but then right away start the background dynamic data fetch. When that fetch is complete, have the code downloading the new data call you either as a delegate, or issue a notification your the view controller with the table listens to, and reset the table view data - then you can simply call reloadData, and the cellForRow:AtIndexPath: method will be called again for the rows on the screen (reload data will also revert back to the top of the table).
UITableView load the cells lazy, in other means it only loads the cells that are visible to the user. When the user then scrolls down, the table view will load the new cells while the "old" cells will be released. There are ways to load the entire data source, but this is not recommended from Apple - since it will be heavy on the memory load of the iPhone.
viewDidAppear() is probably your best bet.
The viewWillAppear: and viewDidAppear: methods are only called when your UIViewController gets pushed on the screen (e.g. by an UINavigationContoller or UITableViewController).
What I would do in your situation is to call a method on your own view controller when your dynamic data source is ready (or whenever you intend to change the data source). In this method set the data source and then call [[self tableView] reloadData];
What you should look out for is, if you are constructing your dynamic data source in the background (which I suppose you do) then you need to call your method on the main thread using performSelectorOnMainThread: