Tengo una vista de tabla con botones y quiero usar indexpath.row cuando se toca uno de ellos. Esto es lo que tengo actualmente, pero siempre es 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
fuente
fuente
Respuestas:
giorashc casi lo tiene con su respuesta, pero pasó por alto el hecho de que las celdas tienen una
contentView
capa extra . Por lo tanto, tenemos que ir un nivel más profundo:Esto se debe a que dentro de la jerarquía de vistas, una tableView tiene celdas como subvistas que posteriormente tienen sus propias 'vistas de contenido', por lo que debe obtener la supervista de esta vista de contenido para obtener la celda en sí. Como resultado de esto, si su botón está contenido en una subvista en lugar de directamente en la vista de contenido de la celda, tendrá que profundizar muchas capas para acceder a ella.
El anterior es uno de esos enfoques, pero no necesariamente el mejor. Si bien es funcional, asume detalles sobre un
UITableViewCell
que Apple nunca necesariamente ha documentado, como su jerarquía de vista. Esto podría cambiarse en el futuro y, como resultado, el código anterior podría comportarse de manera impredecible.Como resultado de lo anterior, por razones de longevidad y confiabilidad, recomiendo adoptar otro enfoque. Hay muchas alternativas enumeradas en este hilo, y le animo a leer, pero mi favorito personal es el siguiente:
Mantenga una propiedad de un cierre en su clase de celda, haga que el método de acción del botón invoque esto.
Luego, cuando crea su celda en
cellForRowAtIndexPath
, puede asignar un valor a su cierre.Al mover el código de su controlador aquí, puede aprovechar el
indexPath
argumento ya presente . Este es un enfoque mucho más seguro que el mencionado anteriormente, ya que no se basa en rasgos indocumentados.fuente
Mi enfoque para este tipo de problema es utilizar un protocolo delegado entre la celda y la vista de tabla. Esto le permite mantener el controlador de botón en la subclase de celda, lo que le permite asignar el controlador de acción de retoque a la celda prototipo en Interface Builder, mientras mantiene la lógica del controlador de botón en el controlador de vista.
También evita el enfoque potencialmente frágil de navegar por la jerarquía de vistas o el uso de la
tag
propiedad, que tiene problemas cuando los índices de las celdas cambian (como resultado de la inserción, eliminación o reordenación)CellSubclass.swift
ViewController.swift
fuente
buttonTapped
es la función delegada y está en el controlador de vista. En mi ejemplo, ¿someButtonTapped
es el método de acción en la celda@IBAction func someButtonTapped(sender: UIButton) { self.delegate?.buttonTapped(self) }
ACTUALIZACIÓN : Obteniendo el indexPath de la celda que contiene el botón (sección y fila):
Uso de la posición del botón
Dentro de su
buttonTapped
método, puede tomar la posición del botón, convertirlo en una coordenada en el tableView, luego obtener el indexPath de la fila en esa coordenada.NOTA : A veces puede encontrarse con un caso límite cuando el uso de la función
view.convert(CGPointZero, to:self.tableView)
da como resultado la búsquedanil
de una fila en un punto, aunque haya una celda tableView allí. Para solucionar este problema, intente pasar una coordenada real que esté ligeramente desplazada del origen, como por ejemplo:Respuesta anterior: uso de la propiedad de etiqueta (solo devuelve la fila)
En lugar de trepar a los árboles de supervista para agarrar un puntero a la celda que contiene el UIButton, existe una técnica más segura y repetible que utiliza la propiedad button.tag mencionada por Antonio anteriormente, descrita en esta respuesta y que se muestra a continuación:
En
cellForRowAtIndexPath:
usted establece la propiedad de la etiqueta:Luego, en la
buttonClicked:
función, hace referencia a esa etiqueta para tomar la fila de indexPath donde se encuentra el botón:Prefiero este método ya que descubrí que balancearse en los árboles de supervista puede ser una forma arriesgada de diseñar una aplicación. Además, para el objetivo-C he usado esta técnica en el pasado y estoy contento con el resultado.
fuente
indexPath.section
además delindexPath.row
(sin restablecer la propiedad de la etiqueta comoindexPath.section
),cellForRowAtIndexPath:
puede simplemente cambiar la etiqueta abutton.tag = indexPath
, y luego en labuttonClicked:
función puede acceder a ambos usandosender.tag.row
ysender.tag.section
.Use una extensión de UITableView para obtener la celda para cualquier vista:
La respuesta de @ Paulw11 de configurar un tipo de celda personalizado con una propiedad de delegado que envía mensajes a la vista de tabla es un buen camino a seguir, pero requiere una cierta cantidad de trabajo para configurar.
Creo que recorrer la jerarquía de vistas de la celda de la vista de tabla en busca de la celda es una mala idea. Es frágil: si luego incluye su botón en una vista con fines de diseño, es probable que ese código se rompa.
El uso de etiquetas de vista también es frágil. Debe recordar configurar las etiquetas cuando crea la celda, y si usa ese enfoque en un controlador de vista que usa etiquetas de vista para otro propósito, puede tener números de etiqueta duplicados y su código puede no funcionar como se esperaba.
He creado una extensión para UITableView que le permite obtener el indexPath para cualquier vista que esté contenida en una celda de vista de tabla. Devuelve un valor
Optional
que será nulo si la vista pasada en realidad no se encuentra dentro de una celda de vista de tabla. A continuación se muestra el archivo de origen de la extensión en su totalidad. Simplemente puede poner este archivo en su proyecto y luego usar elindexPathForView(_:)
método incluido para encontrar el indexPath que contiene cualquier vista.Para usarlo, simplemente puede llamar al método en IBAction para un botón que está contenido en una celda:
(Tenga en cuenta que la
indexPathForView(_:)
función solo funcionará si el objeto de vista que se le pasa está contenido en una celda que se encuentra actualmente en pantalla. Eso es razonable, ya que una vista que no está en pantalla no pertenece a una ruta de índice específica; es probable que asignarse a un indexPath diferente cuando se recicla la celda que contiene).EDITAR:
Puede descargar un proyecto de demostración funcional que utiliza la extensión anterior de Github: TableViewExtension.git
fuente
por
Swift2.1
Encontré una manera de hacerlo, con suerte, ayudará.
fuente
Tiene un botón (myButton) o cualquier otra vista en la celda. Asignar etiqueta en cellForRowAt así
Ahora en tapFunction o cualquier otro. Consígalo así y guárdelo en una variable local.
Después de esto, puede usar en cualquier lugar este currentCellNumber para obtener el indexPath.row del botón seleccionado.
¡Disfrutar!
fuente
En Swift 4, solo usa esto:
fuente
tableView
es una variable de salida a la que se debe hacer referencia antes de que esta respuesta funcione.Muy simple conseguir Index Path rápido 4, 5
Cómo obtener IndexPath Inside Btn Click:
fuente
Dado que el remitente del controlador de eventos es el botón en sí, usaría la
tag
propiedad del botón para almacenar el índice, inicializado encellForRowAtIndexPath
.Pero con un poco más de trabajo lo haría de una manera completamente diferente. Si está utilizando una celda personalizada, así es como abordaría el problema:
cellForRowAtIndexPath
fuente
Después de ver la sugerencia de Paulw11 de usar una devolución de llamada de delegado, quise desarrollarla un poco / presentar otra sugerencia similar. Si no desea utilizar el patrón de delegado, puede utilizar cierres rápidos de la siguiente manera:
Tu clase celular:
Tu
cellForRowAtIndexPath
método:fuente
Encontré una forma muy fácil de usar para administrar cualquier celda en tableView y collectionView usando una clase Model y esto funciona perfectamente.
De hecho, hay una manera mucho mejor de manejar esto ahora. Esto funcionará para administrar la celda y el valor.
Aquí está mi salida (captura de pantalla), así que mira esto:
RNCheckedModel
, escriba el código como se muestra a continuación.fuente
Utilicé el método convertPoint para obtener el punto de la vista de tabla y pasar este punto al método indexPathForRowAtPoint para obtener indexPath
fuente
Intente usar #selector para llamar a la IBaction.In the cellforrowatindexpath
De esta manera puede acceder a la ruta de índice dentro del método editButtonPressed
fuente
En mi caso, tengo varias secciones y tanto la sección como el índice de fila son vitales, por lo que, en tal caso, acabo de crear una propiedad en UIButton que configuré la celda indexPath así:
Luego establezca la propiedad en cellForRowAt así:
Luego, en handleTapAction puede obtener el indexPath así:
fuente
Swift 4 y 5
Método 1 usando el delegado de protocolo
Por ejemplo, tienes un
UITableViewCell
nombre conMyCell
Ahora crea un
protocol
Siguiente paso, cree una extensión de
UITableView
En su
UIViewController
implementación el protocoloMyCellDelegate
Método 2 usando cierres
En
UIViewController
fuente
En Swift 3. También se utilizan declaraciones de guardia, evitando una larga cadena de llaves.
fuente
A veces, el botón puede estar dentro de otra vista de UITableViewCell. En ese caso, es posible que superview.superview no proporcione el objeto de celda y, por lo tanto, indexPath será nulo.
En ese caso, deberíamos seguir buscando la supervista hasta que obtengamos el objeto de celda.
Función para obtener el objeto de la celda por supervista
Ahora podemos obtener indexPath al tocar el botón como se muestra a continuación
fuente
fuente