I have a UITableViewCell
with UISwitch
as accessoryview of each cell. When I change the value of the switch in a cell, how can I know in which row the switch is? I need the row number in the switch value changed event.
相关问题
- CALayer - backgroundColor flipped?
- Core Data lightweight migration crashes after App
- Core Data lightweight migration crashes after App
- How can I implement password recovery in an iPhone
- State preservation and restoration strategies with
相关文章
- 现在使用swift开发ios应用好还是swift?
- UITableView dragging distance with UIRefreshContro
- Could I create “Call” button in HTML 5 IPhone appl
- TCC __TCCAccessRequest_block_invoke
- Where does a host app handle NSExtensionContext#co
- Unable to process app at this time due to a genera
- Swift - hide pickerView after value selected
- Popover segue to static cell UITableView causes co
One common way to do this is to set the
tag
of the control (in your case the switch) to something that can be used to identify the row or represented object.For example, in
tableView:cellForRowAtIndexPath:
set thetag
property of the switch to theindexPath.row
and in your action method you can get the tag from the sender.Personally, I don't like this approach and prefer subclassing UITableViewCell. Also, it may be a good idea to add an "offset" to the tag to prevent any conflicts with the tags of other views.
A colleague suggested the following, which I made into a UITableView category:
Still hackly - but it works.
in
cellForRowAtIndexPath:
, set thetag
property of your control toindexPath.row
I prefer using subviews, if you know your layout it's generally super simple and 1 line short...
Thats it, if its more nested, add in more superviews.
Bit more info:
all you are doing is asking for the parent view and its parent view which is the cell. Then you are asking your tableview for the indexpath of that cell you just got.
Accepted solution is a clever hack.
However why do we need to use hitpoint if we can utilize already available
tag
property on UIView? You would say that tag can store only either row or section since its a single Int.Well... Don't forget your roots guys (CS101). A single Int can store two twice-smaller size integers. And here is an extension for this:
In your
tableView(_:, cellForRowAt:)
you can then:And then in the action handler you would can:
However please note it's limitation: row and section need to be not larger then 65535. (UInt16.max)
I doubt your tableView's indexes will go that high but in case they do, challenge yourself and implement more efficient packing scheme. Say if we have a section very small, we don't need all 16 bits to represent a section. We can have our int layout like:
that is our 4 LSBs indicate the length of section area - 1, given that we allocate at least 1 bit for a section. Thus in case of our section is 0, the row can occupy up to 27 bits ([1][27][4]), which definitely should be enough.
The accepted answer on this post is perfectly fine. I'd like to suggest to readers that the following, derived from @robmayoff on this post, is also perfectly fine:
Some have asserted that this approach contains too much computational work because of the while loop. The alternative, convert the view's origin to table view coordinate space and call
indexPathForRowAtPoint:
, hides even more work.Some have asserted that this approach is unsafe relative to potential SDK changes. In fact, Apple has already changed the tableview cell hierarchy once, adding a
contentView
to the cell. This approach works before and after such a change. As long as view ancestors can be found via a chain of superviews (which is as fundamental as anything in UIKit), this is good code.