К сожалению, этот метод не вызывается, пока не будет нажат внутренний тип кнопки, предоставленный при использовании одного из предопределенных типов. Чтобы использовать свой собственный, вам нужно будет создать свой аксессуар в виде кнопки или другого подкласса UIControl (я бы рекомендовал кнопку с использованием -buttonWithType:UIButtonTypeCustom
и настройкой изображения кнопки, а не с использованием UIImageView).
Вот некоторые вещи, которые я использую в Outpost, который настраивает достаточно стандартных виджетов (совсем немного, чтобы соответствовать нашей бирюзовой окраске), которые я закончил, создав свой собственный промежуточный подкласс UITableViewController для хранения служебного кода для всех других представлений таблиц (теперь они подклассы OPTableViewController).
Во-первых, эта функция возвращает новую кнопку раскрытия подробностей, используя нашу настраиваемую графику:
- (UIButton *) makeDetailDisclosureButton
{
UIButton * button = [UIButton outpostDetailDisclosureButton];
[button addTarget: self
action: @selector(accessoryButtonTapped:withEvent:)
forControlEvents: UIControlEventTouchUpInside];
return ( button );
}
Когда это будет сделано, кнопка вызовет эту процедуру, которая затем подает стандартную процедуру UITableViewDelegate для дополнительных кнопок:
- (void) accessoryButtonTapped: (UIControl *) button withEvent: (UIEvent *) event
{
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: self.tableView]];
if ( indexPath == nil )
return;
[self.tableView.delegate tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath];
}
Эта функция определяет местонахождение строки, получая местоположение в табличном представлении касания из события, предоставленного кнопкой, и запрашивая табличное представление о пути индекса строки в этой точке.
self.tableView
. что, если вы не знаете, какое представление таблицы содержит строку?Я нашел этот веб-сайт очень полезным: пользовательский вид аксессуаров для вашего uitableview на iphone
Короче говоря, используйте это в
cellForRowAtIndexPath:
:UIImage *image = (checked) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height); button.frame = frame; [button setBackgroundImage:image forState:UIControlStateNormal]; [button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside]; button.backgroundColor = [UIColor clearColor]; cell.accessoryView = button;
затем реализуйте этот метод:
- (void)checkButtonTapped:(id)sender event:(id)event { NSSet *touches = [event allTouches]; UITouch *touch = [touches anyObject]; CGPoint currentTouchPosition = [touch locationInView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition]; if (indexPath != nil) { [self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath]; } }
источник
Мой подход заключается в создании
UITableViewCell
подкласса и инкапсуляции логики, которая будет вызывать в нем обычныйUITableViewDelegate
метод.// CustomTableViewCell.h @interface CustomTableViewCell : UITableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; @end // CustomTableViewCell.m @implementation CustomTableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; { // the subclass specifies style itself self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]; if (self) { // get the button elsewhere UIButton *accBtn = [ViewFactory createTableViewCellDisclosureButton]; [accBtn addTarget: self action: @selector(accessoryButtonTapped:withEvent:) forControlEvents: UIControlEventTouchUpInside]; self.accessoryView = accBtn; } return self; } #pragma mark - private - (void)accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableViewCell *cell = (UITableViewCell*)button.superview; UITableView *tableView = (UITableView*)cell.superview; NSIndexPath *indexPath = [tableView indexPathForCell:cell]; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } @end
источник
button.superview
,cell.superview
и[tableView.delegate tableView:...]
не достаточно безопасны.Расширение ответа Джима Дови выше:
Будьте осторожны при использовании UISearchBarController с UITableView. В этом случае вы хотите проверить
self.searchDisplayController.active
и использоватьself.searchDisplayController.searchResultsTableView
вместоself.tableView
. В противном случае вы получите неожиданные результаты, когда searchDisplayController активен, особенно когда результаты поиска прокручиваются.Например:
- (void) accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableView* tableView = self.tableView; if(self.searchDisplayController.active) tableView = self.searchDisplayController.searchResultsTableView; NSIndexPath * indexPath = [tableView indexPathForRowAtPoint:[[[event touchesForView:button] anyObject] locationInView:tableView]]; if(indexPath) [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; }
источник
Определите макрос для тегов кнопок:
#define AccessoryViewTagSinceValue 100000 // (AccessoryViewTagSinceValue * sections + rows) must be LE NSIntegerMax
Создать кнопку и установить cell.accessoryView при создании ячейки
UIButton *accessoryButton = [UIButton buttonWithType:UIButtonTypeContactAdd]; accessoryButton.frame = CGRectMake(0, 0, 30, 30); [accessoryButton addTarget:self action:@selector(accessoryButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; cell.accessoryView = accessoryButton;
Установите cell.accessoryView.tag с помощью indexPath в методе UITableViewDataSource -tableView: cellForRowAtIndexPath:
cell.accessoryView.tag = indexPath.section * AccessoryViewTagSinceValue + indexPath.row;
Обработчик событий для кнопок
- (void) accessoryButtonTapped:(UIButton *)button { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:button.tag % AccessoryViewTagSinceValue inSection:button.tag / AccessoryViewTagSinceValue]; [self.tableView.delegate tableView:self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; }
Реализуйте метод UITableViewDelegate
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { // do sth. }
источник
tag
кроме случаев крайней необходимости, ищите другое решение.Когда кнопка нажата, вы можете вызвать следующий метод внутри подкласса UITableViewCell
-(void)buttonTapped{ // perform an UI updates for cell // grab the table view and notify it using the delegate UITableView *tableView = (UITableView *)self.superview; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:[tableView indexPathForCell:self]]; }
источник
При подходе Янченко мне пришлось добавить:
[accBtn setFrame:CGRectMake(0, 0, 20, 20)];
Если вы используете файл xib для настройки tableCell, то initWithStyle: reuseIdentifier: не будет вызван.
Вместо этого переопределите:
-(void)awakeFromNib { //Put your code here [super awakeFromNib]; }
источник
Вы должны использовать a,
UIControl
чтобы правильно получить диспетчер событий (например, aUIButton
) вместо простогоUIView/UIImageView
.источник
Swift 5
В этом подходе
UIButton.tag
для хранения indexPath используется базовый битовый сдвиг. Подход будет работать в 32- и 64-битных системах, если у вас не более 65535 разделов или строк.public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellId") let accessoryButton = UIButton(type: .custom) accessoryButton.setImage(UIImage(named: "imageName"), for: .normal) accessoryButton.sizeToFit() accessoryButton.addTarget(self, action: #selector(handleAccessoryButton(sender:)), for: .touchUpInside) let tag = (indexPath.section << 16) | indexPath.row accessoryButton.tag = tag cell?.accessoryView = accessoryButton } @objc func handleAccessoryButton(sender: UIButton) { let section = sender.tag >> 16 let row = sender.tag & 0xFFFF // Do Stuff }
источник
Начиная с iOS 3.2, вы можете избегать кнопок, которые рекомендуют другие, и вместо этого использовать свой UIImageView с распознавателем жестов касания. Обязательно включите взаимодействие с пользователем, которое по умолчанию отключено в UIImageViews.
источник