views:

288

answers:

2

@selector(updateStuff:)

This is automatically sends the parameter :(id)sender. Is it possible to override this to be something else? In my particular usage, the actual sender is meaningless.

I'm using a UITableView and setting a UISwitch in the UIAccessoryView slot on every cell. Originally, I was adding the UISwitch to the UIAccessoryView outside of the the cell initialization, which allowed each UISwitch to be a unique instance. However this creates a noticeable lag while scrolling down long list on the iPhone 3G. If I add the UIAccessoryView to the cell when it's initialized, it can be dequeued instead of instantiated and eases the lag considerably. Unfortunately, the cost of doing this is, the instance is NOT unique to each UISwitch in the table, and :(id)sender becomes meaningless.

I need one of two things...

  1. A way to override the parameter associated to @selector, so I may replace :(id)sender
  2. Or a better strategy than the one I am using to keep track of the UISwitches.

I can always resort to adding the UISwitch after the cell is created/dequeued but it is terribly slow and inefficient. Thanks for any help.

Sincerely, Z@K!

+2  A: 

I had a similar problem, the way I've solved it is by setting the "tag" property of the sender, every view has this property and purpose is to help identify it. So while creating/dequeueing the cell set the tag to identify the cell, and on the action use [sender tag] to get the context of the click

Guy Ephraim
Since there is only one tag per object, I cannot see how this would be any different than using the pointer. My problem is one switch will be recycled for two different indicators. That is why I would need to override the @selector
Zak
The trick is setting the only the needed data to the tag and not recreating the UISwitch which is the expensive operation on the dequeue action, therefore you gain the performance improvement while having unique UISwitch
Guy Ephraim
Can you expand on that? Can you tell me how I can link the (reused switch - and therefore tag) to an array of indicators? It is not clicking for me.
Zak
Try saving the array index in the relevant tag, so you will be able to get it when you get back the tag
Guy Ephraim
That's what I'm getting after; you can't. The tag identifies a REUSED cell, it is really no different that just the pointer to that cell, as far as uniquely identifying it. Each tag would have to somehow link off to multiple indicators.
Zak
Well, you should update the tag when reusing the cell and it should be fine
Guy Ephraim
Guy Ephraim is the man! Sorry it took me so long to get a chance to test this and prove you right. Thanks man, you saved my day! The "tag" property acts the same as the textLabel or any other property of the cell. The cell is reused but the properties are unique and the iPhone keeps track of that for you. Whoot!
Zak
A: 

Many, many ways:

  • Set the tag.
  • Set an "associated object" (see objc_setAssociatedObject())
  • Subclass UISwitch. Add some properties.
  • Subclass UITableViewCell. Add some properties. Navigate up the view hierarchy until you reach a table view cell (something like while (v && ![v isKindOfClass:[UITableViewCell class]]) {v = v.superview; }).
  • Navigate up the view hierarchy, as above. Call [tableView indexPathForCell:(UITableViewCell*)v].
  • If there are multiple table views, you can continue navigating up until you hit a UITableView...
tc.
Again, I cannot see how this would be any different than using the pointer. My problem is one switch will be recycled for two different indicators. Adding properties wouldn't help, tags won't help. I have no idea what objc_setAssociatedObject()) is, or where to get information on it. I don't think you fully read my question. If I add the accessory view after, and use a unique switch for each indicator it works fine, but that is really slow. That is why I would need to override the @selector
Zak
I don't think you fully read my answer.
tc.