UITabBarController moreNavigationController table cell background images - iphone

Wow, was that ever a mouthful. :)
We've already seen a good thread on customizing the more menu (table view) in a tab bar.
For our next trick … how might one add a background image to the table cells?
I thought I could get away with overriding tableView:cellForRowAtIndexPath: in my More Table View's Data Source class (see earlier link for the methodology). Alas, it only changes the background under the image and accessory views to the left and right of each cell.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Let the original Data Source get a hold of the cell first.
UITableViewCell *cell = [originalDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
// If we override the textColor, that works fine. (Commented out for now.)
//cell.textLabel.textColor = [UIColor whiteColor];
// If we override the background view … that doesn't work so well.
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellBackground.png"]];
return cell;
}
I know, imageNamed: is evil, and perhaps I should create one background image and just reuse it throughout (vs. allocating multiple UIImageView objects). Apart from those items, any thoughts? (I tried adjusting the textLabel's backgroundColor too, to no avail … unless I'm doing something wrong there.)

Here is the answer...
Add the code in
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
method of MoreTableViewDataSource

In addition to Sijo's answer post (thank you!), I just realized there was another thread on SO that takes a similar tack ... except I understand this code a bit more. However, I never cross-referenced it back to this question/thread! So here it is. See Ian1971's response in particular.

Related

How to Clear cached UITableViewCells

So, I've been implementing Automated testing for my iOS app and I've come across a strange issue.
With the testing framework I'm using (Frank), it attempts to Touch views/buttons/everything based on Accessibility labels. This works great, except for with UITableViews because of how they cache and reuse UITableViewCells. If I "delete" a cell from the table, the table caching system will flip the cell to Hidden. But it will still be there waiting to be reused, and my framework can still see it, which is causing issues.
So, Question: How can I force a UITableView to release all deleted/cached cells so they will no longer be part of the View hierarchy?
This trick might help:
while([tableView dequeueReusableCellWithIdentifier:cellId]!=nil);
Of course, it needs manually repeat it for every possible cellId.
Note, cached cells is not a part of view hierarchy.
One more option. If UITableViewController is not currently visible, then invocation of didReceiveMemoryWarning method releases all its UITableViewCells.
In the method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, use this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]`
then check if your cell is nil. If it is, allocate a new instance of the cell.
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setDelegate:self];
}

Custom UITableViewCell woes

I have an iPhone app with a form input screen. I did this by making a custom UITableViewCell that has a UILabel and a UITextfield. I set it up so that the "cellForRowAtIndexPath" fetches the appropriate value from Core Data, and the UITextField's "textFieldDidEndEditing" method saves the appropriate value to Core Data. It works great... except:
If I edit a text field, then scroll it off screen, then click on another cell's text field:
The cell has been autoreleased because it scrolled off screen
The "textFieldDidEndEditing" gets a BAD ACCESS error
I understand the problem completely, I'm just not sure the best way to fix it. My first thought was to add the logic from "textFieldDidEndEditing" to "dealloc", but that seems hacky. Any suggestions?
I ended up using a delegate method for scroll view (which is built in to the UITableView). When the user starts dragging, I resign first responder.
This works perfectly because it looks nice, and "textFieldDidEndEditing" gets called when the user starts to scroll, which is always before the text field goes off screen.
disable scrolling while editing
retain your textField
that are the things you could do. In my opinion its best to disable scrolling while editing because the user has no need to, so make sure he also can not do so. Limit the things your user can do, makes it more "secure" for you and easier to use for the user.
If you are not sure about such things just look at what apple does, they are always right in their applications. Like in the settings app on iOS 5, when you change your phone's name. You simply get 1 row in the next tableview so you can't really mess anything up as the user..
In your custom cell's dealloc, set the textfield's delegate to nil
I had a similar issue... The problem lies in the reusable cells as part of the Table View. Every time the table is scrolled, the cellforRowatIndexPath gets called, and dequeues a cell and returns it. Sadly, this functionality doesnt work well with cells having retainable data such as labels. Hence you must opt for your own method of dequeueing the cell.
I have an NSMutableArray called cells which holds all my cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [self dequeuwReusableCellwith:indexPath];
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] init];
[cells addObject:cell];
}
// Configure the cell.
NSString *temp = [NSString stringWithFormat:#"Cell %d",indexPath.row];
cell.textField.placeholder=temp;
return cell;
}
and this is my custom method to deque Reusable cells.
-(CustomTableViewCell*)dequeuwReusableCellwith:(NSIndexPath*)indexpath
{
if([cells count]>indexpath.row)
{
return [cells objectAtIndex:indexpath.row];
}
return nil;
}
Hope this helps...

asynchronous UIImageView in custom UITableViewCell

I would like to know how people implement an asynchronous UIImageView loading, if you have it inside a custom UITableViewCell, I've seen quite some examples using GCD, subclassing UIImageView.. all of them must involves NSURLRequest and NSURLConnection. So how do people do this in a subclass of UITableViewCell that has an UIImageView in it?
Look at this category: SDWebImage. It's a image downloader for UIImageView. You place you're image view in your cell, and in the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method, just use:
[myImageView setImageWithURL:[NSURL URLWithString:#"example.com/myimage.jpg"]];
Here is a very good tutorial which explains asynchronous loading in general....
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
You can use the same idea to load your image view..
I think the simple and ideal way to do this is to do the following steps
Inside cellForRowAtIndexPath: check if the image is available locally load it, else fire off nsurl request to download it in a separate thread and show a loading indicator image.
On completion of request thread, store the image locally reload tableView.

is this code OK for setting UITableViewCell background color?

I've read quite a few different ways to tackle the problem of setting the UITableViewCell color. Was just after a quick confirmation that the code/approach below is fine re a best practice / performance point of view?
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor redColor];
}
Some notes/questions associated with this:
Would this be the best re performance in the sense that it seems like this code will be called quite a lot? i.e. as opposed to if the background color was just set once for the cell design, say in IB (which I know doesn't quite work) see here
I see some sample code that loops through the various sub-views of a cell to set them, but this wouldn't normally be required? I've tried this code above and it seemingly works ok.
You are correct, this is the way to do it. The UITableViewCell documentation even explicitly states that background colors should be set in tableView:willDisplayCell:forRowAtIndexPath: as opposed to tableView:cellForRowAtIndexPath:. Don't fear, you are on the right path sir.

UITableViewController not highlighting cell when it's selected

Hi
I've got simple question which I don't know how to answer.
In my app I've got UITableViewController with cells. When I select one item (cell) it's getting higlighted and in other thread I'm loading chunk of data to display to the user (after load is done new VC is pushed). When doing it with thread user still can interact with application like, going back to other NavController and I do want that to happen. What I don't want to happen is that when loading isn't complete user can select other cell in table and it get's highlted. How I can prevent that (only highlit, I'm checking if there was a previous request so I'm not putting another thread untli previous request is done).
So basicly my question is, how can you foribd user from interacting with table view controller?
Set the selectionStyle of the UITableViewCell's to UITableViewCellSelectionStyleNone.
You can use the following to check if row can be selected:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (rowSelected) {
return nil;
}
return indexPath;
}
So, you only select it if no row is selected. In your didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
rowSelected = YES;
// call method that is going to do something and mark rowSelected = NO;
}
You can deselect the row by using
[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES];
There is a risk that your users will be confused. A highlight is not enough. There should be very clear visual feedback that a network opperation is ongoing and that different rules apply.
either push the details view immediately after the user selected a row and show an activity indicator in there.
or give the whole table view a different look while loading data for the selected row: e.g. Show activity indicator in the selected row & hide the disclosure chevrons in all the other. While doing that, you can set the selection style to 'none'