Eu tenho um tableview com botões e quero usar o indexpath.row quando um deles é tocado. Isso é o que eu tenho atualmente, mas sempre é 0
var point = Int()
func buttonPressed(sender: AnyObject) {
let pointInTable: CGPoint = sender.convertPoint(sender.bounds.origin, toView: self.tableView)
let cellIndexPath = self.tableView.indexPathForRowAtPoint(pointInTable)
println(cellIndexPath)
point = cellIndexPath!.row
println(point)
}
swift
button
touch
nsindexpath
Vincent
fonte
fonte
Respostas:
Giorashc quase acertou a resposta, mas não percebeu o fato de que as células têm uma
contentView
camada extra . Portanto, temos que ir uma camada mais a fundo:Isso ocorre porque dentro da hierarquia de visualização, uma tableView possui células como subvisualizações que subsequentemente têm suas próprias 'visualizações de conteúdo', é por isso que você deve obter a supervisão dessa visualização de conteúdo para obter a própria célula. Como resultado disso, se o botão estiver contido em uma subvisualização em vez de diretamente na visualização do conteúdo da célula, você terá que ir muitas camadas mais fundo para acessá-lo.
A abordagem acima é uma dessas abordagens, mas não necessariamente a melhor abordagem. Embora seja funcional, assume detalhes sobre um
UITableViewCell
que a Apple nunca necessariamente documentou, como sua hierarquia de visualização. Isso pode ser alterado no futuro e, como resultado, o código acima pode se comportar de maneira imprevisível.Como resultado do acima, por razões de longevidade e confiabilidade, recomendo adotar outra abordagem. Existem muitas alternativas listadas neste tópico, e eu encorajo você a ler, mas minha favorita é a seguinte:
Mantenha uma propriedade de um fechamento em sua classe de célula, faça com que o método de ação do botão invoque isso.
Então, ao criar sua célula em
cellForRowAtIndexPath
, você pode atribuir um valor ao seu fechamento.Ao mover o código do manipulador para cá, você pode tirar vantagem do
indexPath
argumento já presente . Esta é uma abordagem muito mais segura do que a listada acima, pois não depende de características não documentadas.fonte
Minha abordagem para esse tipo de problema é usar um protocolo delegado entre a célula e o tableview. Isso permite que você mantenha o manipulador de botão na subclasse de célula, o que permite atribuir o manipulador de ação de retoque à célula de protótipo no Interface Builder, enquanto mantém a lógica do manipulador de botão no controlador de visualização.
Também evita a abordagem potencialmente frágil de navegar na hierarquia de visualização ou o uso da
tag
propriedade, que tem problemas quando os índices das células mudam (como resultado de inserção, exclusão ou reordenação)CellSubclass.swift
ViewController.swift
fonte
buttonTapped
é a função delegada e está no controlador de visualização. No meu exemplo,someButtonTapped
é o método de ação na célula@IBAction func someButtonTapped(sender: UIButton) { self.delegate?.buttonTapped(self) }
ATUALIZAÇÃO : Obtendo o indexPath da célula que contém o botão (seção e linha):
Usando a posição do botão
Dentro do seu
buttonTapped
método, você pode pegar a posição do botão, convertê-lo em uma coordenada em tableView e, em seguida, obter o indexPath da linha nessa coordenada.NOTA : Às vezes, você pode chegar a um caso extremo ao usar os
view.convert(CGPointZero, to:self.tableView)
resultados da funçãonil
para encontrar uma linha em um ponto, mesmo que haja uma célula tableView lá. Para corrigir isso, tente passar uma coordenada real ligeiramente deslocada da origem, como:Resposta anterior: Usando a propriedade da tag (retorna apenas linha)
Em vez de subir nas árvores de supervisualização para pegar um ponteiro para a célula que contém o UIButton, há uma técnica mais segura e mais repetível que utiliza a propriedade button.tag mencionada por Antonio acima, descrita nesta resposta e mostrada abaixo:
No
cellForRowAtIndexPath:
você define a propriedade da tag:Então, no
buttonClicked:
função, você faz referência a essa tag para capturar a linha do indexPath onde o botão está localizado:Eu prefiro esse método, pois descobri que balançar nas árvores do superview pode ser uma maneira arriscada de projetar um aplicativo. Além disso, para o objetivo-C, usei essa técnica no passado e estou feliz com o resultado.
fonte
indexPath.section
além doindexPath.row
(sem redefinir a propriedade do tag comoindexPath.section
), emcellForRowAtIndexPath:
você poderia apenas alterar o tag parabutton.tag = indexPath
e, em seguida, nabuttonClicked:
função você poderia acessar usandosender.tag.row
esender.tag.section
.Use uma extensão para UITableView para buscar a célula para qualquer visualização:
A resposta de @Paulw11 de configurar um tipo de célula customizado com uma propriedade delegate que envia mensagens para a table view é um bom caminho a seguir, mas requer uma certa quantidade de trabalho para configurar.
Acho que percorrer a hierarquia de visualização da célula da table view procurando pela célula é uma má ideia. É frágil - se mais tarde você colocar o botão em uma visualização para fins de layout, o código provavelmente será quebrado.
O uso de tags de visualização também é frágil. Você deve se lembrar de configurar as tags ao criar a célula e, se usar essa abordagem em um controlador de visualização que usa tags de visualização para outro propósito, você pode ter números de tag duplicados e seu código pode não funcionar como esperado.
Eu criei uma extensão para UITableView que permite obter o indexPath para qualquer exibição contida em uma célula de exibição de tabela. Ele retorna um
Optional
que será nulo se a visão passada realmente não se enquadrar em uma célula de visão de tabela. Abaixo está o arquivo fonte da extensão em sua totalidade. Você pode simplesmente colocar esse arquivo em seu projeto e, em seguida, usar oindexPathForView(_:)
método incluído para encontrar o indexPath que contém qualquer visualização.Para usá-lo, você pode simplesmente chamar o método na IBAction para um botão que está contido em uma célula:
(Observe que o
indexPathForView(_:)
função só funcionará se o objeto de visualização que é passado estiver contido em uma célula que está atualmente na tela. Isso é razoável, uma vez que uma visualização que não está na tela não pertence realmente a um indexPath específico; é provável que ser atribuído a um indexPath diferente quando ele contém a célula reciclada.)EDITAR:
Você pode baixar um projeto de demonstração funcional que usa a extensão acima no Github: TableViewExtension.git
fonte
Para
Swift2.1
Eu encontrei uma maneira de fazer isso, espero que ajude.
fonte
Você tem um botão (myButton) ou qualquer outra visualização na célula. Atribuir tag em cellForRowAt assim
Agora em você toque em Função ou em qualquer outro. Pegue-o assim e salve-o em uma variável local.
Depois disso, você pode usar em qualquer lugar este currentCellNumber para obter o indexPath.row do botão selecionado.
Aproveitar!
fonte
No Swift 4, basta usar isto:
fonte
tableView
é uma variável de saída que precisa ser referenciada antes de esta resposta funcionar.Muito simples obter o caminho do índice swift 4, 5
Como obter IndexPath Inside Btn Click:
fonte
Como o remetente do manipulador de eventos é o próprio botão, eu usaria a
tag
propriedade do botão para armazenar o índice inicializado emcellForRowAtIndexPath
.Mas com um pouco mais de trabalho eu faria de uma maneira completamente diferente. Se você estiver usando uma célula personalizada, é como eu abordaria o problema:
cellForRowAtIndexPath
fonte
Depois de ver a sugestão de Paulw11 de usar um retorno de chamada de delegado, eu queria elaborá-la um pouco / apresentar outra sugestão semelhante. Se você não quiser usar o padrão de delegado, pode utilizar os fechamentos rapidamente da seguinte forma:
Sua classe de celular:
Seu
cellForRowAtIndexPath
método:fonte
Eu descobri uma maneira muito fácil de usar para gerenciar qualquer célula em tableView e collectionView usando uma classe Model e isso funciona perfeitamente.
Na verdade, há uma maneira muito melhor de lidar com isso agora. Isso funcionará para gerenciar célula e valor.
Aqui está minha saída (captura de tela), então veja isto:
RNCheckedModel
, escreva o código como abaixo.fonte
Usei o método convertPoint para obter o ponto de tableview e passar este ponto para o método indexPathForRowAtPoint para obter indexPath
fonte
Tente usar #selector para chamar o IBaction.In the cellforrowatindexpath
Desta forma você pode acessar o indexpath dentro do método editButtonPressed
fonte
No meu caso, eu tenho várias seções e o índice da seção e da linha é vital, então, nesse caso, acabei de criar uma propriedade no UIButton que defini a célula indexPath assim:
Em seguida, defina a propriedade em cellForRowAt assim:
Em seguida, em handleTapAction você pode obter o indexPath assim:
fonte
Swift 4 e 5
Método 1 usando protocolo delegado
Por exemplo, você tem um
UITableViewCell
com nomeMyCell
Agora crie um
protocol
Próxima etapa, crie uma extensão de
UITableView
Em sua
UIViewController
implementação do protocoloMyCellDelegate
Método 2 usando fechamentos
No
UIViewController
fonte
Em Swift 3. Também usado instruções de guarda, evitando uma longa cadeia de chaves.
fonte
Às vezes, o botão pode estar dentro de outra visualização de UITableViewCell. Nesse caso, superview.superview pode não fornecer o objeto de célula e, portanto, o indexPath será nulo.
Nesse caso, devemos continuar encontrando a supervisão até obter o objeto de célula.
Função para obter objeto de célula por superview
Agora podemos obter indexPath no toque do botão como abaixo
fonte
fonte