Detecting which UIButton was pressed in a UITableView

前端 未结 26 3226
小蘑菇
小蘑菇 2020-11-22 00:40

I have a UITableView with 5 UITableViewCells. Each cell contains a UIButton which is set up as follows:

- (UITableView         


        
26条回答
  •  轮回少年
    2020-11-22 00:55

    This problem has two parts:

    1) Getting the index path of UITableViewCell which contains pressed UIButton

    There are some suggestions like:

    • Updating UIButton's tag in cellForRowAtIndexPath: method using index path's row value. This is not an good solution as it requires updating tag continuously and it does not work with table views with more than one section.

    • Adding an NSIndexPath property to custom cell and updating it instead of UIButton's tag in cellForRowAtIndexPath: method. This solves multiple section problem but still not good as it requires updating always.

    • Keeping a weak refence to parent UITableView in the custom cell while creating it and using indexPathForCell: method to get the index path. Seems a little bit better, no need to update anything in cellForRowAtIndexPath: method, but still requires setting a weak reference when the custom cell is created.

    • Using cell's superView property to get a reference to parent UITableView. No need to add any properties to the custom cell, and no need to set/update anything on creation/later. But cell's superView depends on iOS implementation details. So it can not be used directly.

    But this can be achieved using a simple loop, as we are sure the cell in question has to be in a UITableView:

    UIView* view = self;
    while (view && ![view isKindOfClass:UITableView.class])
        view = view.superview;
    UITableView* parentTableView = (UITableView*)view;
    

    So, these suggestions can be combined into a simple and safe custom cell method for getting the index path:

    - (NSIndexPath *)indexPath
    {
        UIView* view = self;
    
        while (view && ![view isKindOfClass:UITableView.class])
            view = view.superview;
    
        return [(UITableView*)view indexPathForCell:self];
    }
    

    From now on, this method can be used to detect which UIButton is pressed.

    2) Informing other parties about button press event

    After internally knowing which UIButton is pressed in which custom cell with exact index path, this information needs to be sent to other parties (most probably the view controller handling the UITableView). So, this button click event can be handled in a similar abstraction and logic level to didSelectRowAtIndexPath: method of UITableView delegate.

    Two approaches can be used for this:

    a) Delegation: custom cell can have a delegate property and can define a protocol. When button is pressed it just performs it's delegate methods on it's delegate property. But this delegate property needs to be set for each custom cell when they are created. As an alternative, custom cell can choose to perform its delegate methods on it's parent table view's delegate too.

    b) Notification Center: custom cells can define a custom notification name and post this notification with the index path and parent table view information provided in userInfo object. No need to set anything for each cell, just adding an observer for the custom cell's notification is enough.

提交回复
热议问题