accessoryButtonTappedForRowWithIndexPath: не вызывается
Я создаю кнопку раскрытия сведений, которая заполняется с помощью массива.... Однако accessoryButtonTappedForRowWithIndexPath: функция не вызывается в моем классе. Это TableviewDelegate
а также TableviewDatasource
делегировать.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
NSLog(@"reaching accessoryButtonTappedForRowWithIndexPath:");
[self performSegueWithIdentifier:@"modaltodetails" sender:[self.eventsTable cellForRowAtIndexPath:indexPath]];
}
NSLog не печатает на консоль, что наводит меня на мысль, что функция не вызывается... Это, конечно, когда я выбираю ячейку. На скриншоте ниже показано, как у меня настроена ячейка.
9 ответов
Вы просто щелкнули по ячейке, чтобы выбрать ее, или вы действительно нажали на индикатор дополнительной кнопки на ячейке? Это не ясно из вашего вопроса.
accessoryButtonTappedForRowWithIndexPath
применимо, когда вы нажимаете на значок кнопки внутри ячейки, а не когда вы выбираете ячейку.
Док говорит, что метод tableView:accessoryButtonTappedForRowWithIndexPath:
не вызывается, когда для строки в indexPath
, Метод вызывается только тогда, когда accessoryView
свойство nil
и когда кто-то использует и устанавливает accessoryType
свойство для отображения встроенного вспомогательного представления.
Как я понимаю, accessoryView
а также accessoryType
являются взаимоисключающими. Когда используешь accessoryType
, система позвонит tableView:accessoryButtonTappedForRowWithIndexPath:
как и ожидалось, но вы должны разобраться с другим делом самостоятельно.
То, как Apple это делает, показано в Accessory
Пример проекта SDK. в cellForRowAtIndexPath
Метод делегата источника данных, они устанавливают цель / действие для пользовательской вспомогательной кнопки. Так как нельзя пройти indexPath
к действию, они вызывают вспомогательный метод для получения соответствующего indexPath
и они передают результат в метод делегата:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
...
// set the button's target to this table view controller so we can interpret touch events and map that to a NSIndexSet
[button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
...
cell.accessoryView = button;
return cell;
}
- (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];
}
}
По какой-то причине ваша установка, кажется, попадает в случай accessoryView. Вы пытались установить accessoryType
с кодом вместо использования Interface Builder?
Это кажется очень актуальным...
Индикатор раскрытия. Когда этот элемент присутствует, пользователи знают, что могут нажать в любом месте строки, чтобы увидеть следующий уровень в иерархии или варианты, связанные с элементом списка. Использование индикатора раскрытия в строке при выборе строки приводит к отображению другого списка. Не используйте индикатор раскрытия для раскрытия подробной информации об элементе списка; вместо этого используйте кнопку раскрытия информации для этой цели.
Кнопка подробного раскрытия: пользователи нажимают на этот элемент, чтобы просмотреть подробную информацию об элементе списка. (Обратите внимание, что этот элемент можно использовать в представлениях, отличных от представлений таблицы, для раскрытия дополнительных сведений о чем-либо; см. "Кнопки раскрытия подробностей" для получения дополнительной информации.) В представлении таблицы используйте кнопку раскрытия подробностей в строке, чтобы отобразить сведения о элемент списка. Обратите внимание, что кнопка подробного раскрытия, в отличие от индикатора раскрытия, может выполнять действие, отдельное от выбора строки. Например, в Избранном телефоне нажатие на строку инициирует вызов контакта; При нажатии на кнопку раскрытия подробностей в строке открывается дополнительная информация о контакте.
Преобразование верхнего ответа в Swift 3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
let unseletcedImage = UIImage(named: "<imagename>")
let seletcedImage = UIImage(named: "<imagename>")
let button = UIButton(type: .custom)
// match the button's size with the image size
let frame = CGRect(x: CGFloat(0.0), y: CGFloat(0.0), width: CGFloat((unseletcedImage?.size.width)!), height: CGFloat((unseletcedImage?.size.height)!))
button.frame = frame
button.setBackgroundImage(unseletcedImage, for: .normal)
button.setBackgroundImage(seletcedImage, for: .selected)
cell?.accessoryView = button
let action = #selector(checkButtonTapped(sender:event:))
(cell?.accessoryView as? UIButton)?.addTarget(self, action: action, for: .touchUpInside)
....
return cell!
}
@objc func checkButtonTapped(sender: UIButton?, event: UIEvent) {
let touches = event.allTouches
let touch = touches!.first
guard let touchPosition = touch?.location(in: self.tableView) else {
return
}
if let indexPath = tableView.indexPathForRow(at: touchPosition) {
tableView(self.tableView, accessoryButtonTappedForRowWith: indexPath)
}
}
Согласно документации UITableViewCellAccessoryType это ожидаемое поведение:
typedef enum : NSInteger {
UITableViewCellAccessoryNone,
UITableViewCellAccessoryDisclosureIndicator,
UITableViewCellAccessoryDetailDisclosureButton,
UITableViewCellAccessoryCheckmark,
UITableViewCellAccessoryDetailButton } UITableViewCellAccessoryType;
Константы UITableViewCellAccessoryNone Ячейка не имеет дополнительного представления. Это значение по умолчанию.
UITableViewCellAccessoryDisclosureIndicator Ячейка имеет вспомогательный элемент управления в форме шеврона. Этот элемент управления указывает, что касание ячейки запускает действие толчка. Элемент управления не отслеживает прикосновения.
UITableViewCellAccessoryDetailDisclosureButton Ячейка имеет информационную кнопку и изображение шеврона в качестве содержимого. Этот элемент управления указывает, что касание ячейки позволяет пользователю настраивать содержимое ячейки. Контрольные треки касаются.
UITableViewCellAccessoryCheckmark У ячейки есть галочка с правой стороны. Этот элемент управления не отслеживает прикосновения. Делегат табличного представления может управлять галочками в секции строк (возможно, ограничивая галочку одной строкой секции) в своем tableView:didSelectRowAtIndexPath: метод.
UITableViewCellAccessoryDetailButton В ячейке есть информационная кнопка без шеврона. Этот элемент управления указывает, что при нажатии на ячейку отображается дополнительная информация о содержимом ячейки. Контрольные треки касаются.
Дрю на месте.
Если вы переключитесь на "DetailDisclosure" в раскадровке, то метод сработает. (xCode 4.6 DP3)
Мой tableView's accessoryButtonTappedForRowWithIndexPath(…)
не вызывался при нажатии кнопки раскрытия подробностей. В конце концов я обнаружил, что проблема заключалась просто в том, что делегат tableView не был установлен:
self.tableView.delegate = self
Протестировано на Swift 5.7/iOS 16 (очевидно, будет работать в гораздо более ранних версиях).
В этом решении используются вложенные функции, чтобы обработчики и настройки оставались локальными для ограниченных вариантов использования.
extension MyViewController : UITableViewDelegate {
@objc func findRowOfTappedButton(sender: UIButton?, event: UIEvent) {
let touches = event.allTouches
let touch = touches!.first
guard let touchPosition = touch?.location(in: self.tableView) else { return }
if let indexPath = tableView.indexPathForRow(at: touchPosition) {
tableView(self.tableView, accessoryButtonTappedForRowWith: indexPath)
}
}
// Note: By implementing the following handler as appropriate delegate method,
// the scheme will still work if accessoryType changes to OS-provided type.
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
tableView.delegate?.tableView!(tableView, didSelectRowAt: indexPath)
// Do whatever when button at this row is pressed.
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Do whatever when row is selected w/o button press.
}
}
extension MyViewController : UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myContent.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
func addAccessoryButtonToCell(_ cell : UITableViewCell) {
let image = UIImage(systemName: "paintpalette")
let button = UIButton(type: .custom)
button.frame = CGRect(x:0, y:0, width: 20, height: 20)
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(findRowOfTappedButton(sender:event:)), for: .touchUpInside)
cell.accessoryView = button
}
let cell = tableView.dequeueReusableCell(withIdentifier: "MyReusableCell", for: indexPath)
addAccessoryButtonToCell()
content.attributedText = NSAttributedString(string: myContent[indexPath.row], attributes: myAttributes[indexPath.row])
}
}
Это еще один способ обработки кнопки раскрытия с использованием раскадровки. Вы должны щелкнуть ячейку табличного представления и перейти к Инспектору соединений. Есть раздел, называемый Seggered Segues, и вы можете перетащить его из строки выбора в UIViewController, к которому вы хотите перейти. Переход произойдет автоматически, и вы можете захватить prepareForSegue, чтобы захватить уведомление, когда это произойдет.
Функция accessoryButtonTappedForRowWithIndexPath никогда не вызывается для кнопки раскрытия. Он вызывается только для кнопки подробного раскрытия.