Accessibility in custom drawn UITableViewCell - iphone

UITableViewCells scrolling speed increases dramatically when you do custom drawing, however, Accessibility breaks. How should one add accessibility support to a cell like this?

Old question, but iOS has built in support for this kind of accessibility. Take a look at the UIAccessibilityContainer informal protocol which will allow you to define rects in your view and label them appropriately. Thus, if you draw a big X at 0,0 with a size of 44x44, then you can set the accessibilityLabel for that rect to "Delete".

You'll need to set the relevant accessibilityLabel yourself if you're using custom views to display information (in this case, to draw a table cell). Depending on exactly which view you've taken over drawing for, the label you need might be either the table cell's (for a UITableViewCell subclass) or your custom content view's.
If you're drawing complex information in your custom cells, consider including all that you can reasonably vocalise in the label, separated by commas as discussed in the accessibility guide. What to include is usually common sense but talking to a regular voiceover user can be really helpful, especially regarding what piece of information they want to know first.

I'm a bit in the dark as well on what you are trying to ask. To me, it sounds like you're having trouble accessing methods/objects on your custom cell. When you have a class named CustomCell, use a line like
CustomCell *cell = (CustomCell *)[localTableView dequeueReusableCellWithIdentifier:MyIdentifier];
to create a custom cell.
Suppose your custom cell contains a few labels. You can then access them easily using something like
[cell.aLabel setText:#"Accessed by load"];
When you try to access methods, for example: an IBAction when pressed on a button inside a cell, you should declare those methods in your class CustomCell (and not in your table view's class). After that, link your button's connector to the CustomCell's connector.
Note: this connector won't necessarily be in File's Owner. I'm using XCode 4, and I see 3 objects: File's Owner, First Responder, and Custom Cell. My IBAction is located in Custom Cell, even though I'm used to having it linked to File's Owner.
I hope this was of any help.

Related

iPhone- how to use Storyboard with custom UITableView cells and CellWithIdentifier

I'm trying to make use of the new Storyboard designer and the ease of drawing UITableView cells instead of programmatically "designing" each row.
A good example of a standard cell is linked here at stack overflow:
iPhone - dequeueReusableCellWithIdentifier usage
Instead of the linked approach of using "[cell textLabel]" I want to use my own labels, buttons and images on top of each row.
Therefore I created several prototype cells/rows and assigned identifiers to them (using Storyboard).
Now: what is the smartest way of accessing each row's "custom" controls/labels? I tried searching for accessing them by ID, but didn't find anything.
My thinking was it should work along this lines:
[[[cell subviews] getObjectByID:#"labelTime"] setText:#"Whatever"];
Is my expectation of the APIs completely wrong or didn't I just find the right API, yet?
Any ideas or recommendations?
For each new custom UITableViewCell that you create in storyboard, you will want to create a new class file which implements UITableViewCell to link it to. Be sure to map all of the controls within your new cell that you laid out in storyboard to instance properties. Then you'll just use it with dequeuing like normal:
YourTableViewCellClass *cell = (YourTableViewCellClass*)[tableView dequeueReusableCellWithIdentifier:#"YourCellIdentifierStringDefinedInStoryBoard"];
// then set the properties for the class.
cell.labelTime = #"whatever";
There are two ways you can get to your custom subviews. The simpler way is using tags. Every view has a tag property which is an integer. You can set the tag in the nib, and set or get it in code. You can search a view tree for a view with a given tag by sending viewWithTag: to the root of the tree. So, for example, you could give your labelTime view the tag 57, and in your code, you'd find the view like this:
UILabel *label = (UILabel *)[cell viewWithTag:57];
The downside of using tags is that you have to keep the tag numbers in sync between your nib and your code. If they get out of sync, you'll either get the wrong view back or you'll get nil (and since you can send messages to nil, the system won't give you an error when that happens). Still, tags are so convenient that it's pretty common to use them like this.
The other way is to create a custom subclass of UITableViewCell with an IBOutlet property for each custom subview. You can hook up the outlets to the subviews in the nib, and access the subviews via the properties in your code:
MyTableViewCell *myCell = (MyTableViewCell *)cell;
UILabel *label = cell.labelTime;
This entails writing a lot more boilerplate than using tags, but it has the advantage that you will get warnings or errors (either at compile-time or when you first try to load the nib) if your nib and your code get out of sync.
Don't be a doofus like I was being. :)
Make sure you set the Identifier value in the Attributes Inspector of the custom cell. Setting the Restoration ID of the custom cell in the Identity Inspector is the wrong way to go, and that's exactly what I did. Major facepalm for myself.
For more implementation details of how to do it, using the methods described by mservidio and rob, check out the section "Designing Our own Prototype Cells" in this tutorial.

How can I make my custom UITableViewCells as fast as possible?

I'm creating custom UITableViewCells, and I'd like to make them in a way that allows the table view's scrolling to be as smooth as possible. In their current state, with a custom background image on each cell using the cell's backgroundView property, scrolling is is still fairly smooth.
But my question is, how can I add content to the cell and maintain this? The cells are fairly different from each other -- one may have a single label, another may have two labels and an icon, and another may have a bunch of other controls.
I've found that using unique cell identifiers for non-similar rows makes the overall experience laggy, so I need a method that allows me to use the same cell identifier and have very different cells.
Should I be using an XIB for this? If not, how should my subclass function? I was thinking of adding all of the controls to the cell, and only hiding/using the ones necessary at the time. Is there a cleaner way?

Multiple images per row in UITableView's cell

Is there any sample code that would illustrate how to have multiple images within each row?
Typical apps show a thumbnail to the left side with text to the right. I'd like to do that plus an image to the right of the text.
How would I go about doing this?
In interface builder, simply create a tableview cell that looks like you want. Then create a UITableViewCell subclass that has properties pointing to the elements of the new cell. Set the class of cell to the subclass then add cells of that class to the table in the standard way.
A tableview cell is just a view and you modify it and use it just like any other view.
You'll have to create a custom UITableView cell. Here's an example of using multiple UILabels in one. Here's another.
Pretty easy - follow Apple's documentation to create exactly the cell you want in Interface Builder with as many UIImage or whatever else you like. Look at Table View Programming Guide for details on how to make and load the custom cells - just be careful about performance when you put a lot of visual elements in a table view.

UITextField in UITableViewCell's and proper usage

I have a complex settings style table where individual cells represent different aspects of a data model class. Users can click into a cell and edit individual attributes, such as say if I have a user class, a name, date of birth, etc. My question is, do I need to have an instance of UITextField for each unique cell? Can I just create one subclass of UITableViewCell, set up a delegate, and determine where it is from there?
What's the best approach?
I would recommend creating a subclass of a UITableViewCell. You could do this either purely programaticaly, or if you have an aversion to CGRect's (or want to be able to drag and drop your layout around) with a combination of a XIB and a custom class file.
The Subclass would then contain the UITextFiled's you need, and can also have a delegate or datasource that you can use to point it to your data model object.
It's better to have the UITableViewController you are using act as the text view delegate for each cell - make sure you are re-using cells and when you create them or reuse them attach your class as the delegate for the UITextViews you have via a custom UITableViewCell class with accessors to get to the UITextViews.
If you set cell classes as text delegates you may run into issues if the user scrolls a table view cell off screen with the keyboard up.

Toggling display of image in UITableViewCell

Depending on the result of a condition, I want to display a UIImageView in a table cell. Otherwise display UITableViewCellAccessoryCheckmark. I'd like to construct the cell in IB. The part I'm not sure of what to do with the UIImageView when I don't want it displayed. If I were constructing it all programmatically, I'd add the UIImageView as needed. But since it will be done in IB, the UIImageView is always there. Should the default be leave the cell alone (image displays), otherwise remove UIImageView and display UITableViewCellAccessoryCheckmark? If that is done, will I need a tag on UIImageView so it can be accessed and removed?
You can easily control the visibility of any control, including UIImageView. If you'd like to build things in IB then one solution is to add the controls you need, expose them as properties, and then hide the ones you don't want for a given cell.
E.g.
cell.image.hidden = YES;
When hidden they have no draw-overhead, and although your cell may have thousands of rows there will be very few actual cells, so it's a fairly efficient solution. Just remember that cells are reused if you call [tableView dequeueReusableCellWithIdentifier] (which you should do) so you'll have to explicitly show/hide control whose visibility may have been changed.
An alternative is to have cells with and without images and choose the correct one when adding data to your table. For cells that are similar managing two similar-yet-minorly-different assets would probably be a pain though.