Mam widok tabeli z przyciskami i chcę użyć indexpath.row, gdy jeden z nich zostanie dotknięty. To jest to, co obecnie mam, ale zawsze jest to 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
źródło
źródło
Odpowiedzi:
giorashc prawie miał to w swojej odpowiedzi, ale przeoczył fakt, że komórki mają dodatkową
contentView
warstwę. Dlatego musimy zejść o jedną warstwę głębiej:Dzieje się tak, ponieważ w hierarchii widoków tableView ma komórki jako podglądy, które następnie mają swoje własne „widoki zawartości”, dlatego musisz uzyskać nadzór tego widoku zawartości, aby uzyskać samą komórkę. W rezultacie, jeśli twój przycisk znajduje się w podglądzie, a nie bezpośrednio w widoku zawartości komórki, będziesz musiał przejść o wiele warstw głębiej, aby uzyskać do niego dostęp.
Powyższe jest jednym z takich podejść, ale niekoniecznie najlepszym podejściem. Chociaż jest funkcjonalny, zakłada szczegóły dotyczące elementu,
UITableViewCell
którego Apple nigdy nie dokumentował, takie jak hierarchia widoków. Może to ulec zmianie w przyszłości, a powyższy kod może w rezultacie zachowywać się nieprzewidywalnie.W związku z powyższym, ze względu na długowieczność i niezawodność, zalecam przyjęcie innego podejścia. W tym wątku jest wiele alternatyw i zachęcam do przeczytania, ale mój osobisty faworyt jest następujący:
Przytrzymaj właściwość zamknięcia w swojej klasie komórek, niech metoda akcji przycisku wywoła this.
Następnie, kiedy utworzysz swoją komórkę w
cellForRowAtIndexPath
, możesz przypisać wartość do zamknięcia.Przenosząc tutaj swój kod obsługi, możesz skorzystać z już obecnego
indexPath
argumentu. Jest to znacznie bezpieczniejsze podejście niż to wymienione powyżej, ponieważ nie opiera się na nieudokumentowanych cechach.źródło
Moje podejście do tego rodzaju problemu polega na użyciu protokołu delegata między komórką a widokiem tabeli. Pozwala to zachować procedurę obsługi przycisku w podklasie komórki, co umożliwia przypisanie procedury obsługi operacji retuszu do komórki prototypu w programie Interface Builder, jednocześnie zachowując logikę obsługi przycisku w kontrolerze widoku.
Pozwala również uniknąć potencjalnie kruchego podejścia do poruszania się po hierarchii widoków lub korzystania z
tag
właściwości, co powoduje problemy, gdy zmieniają się indeksy komórek (w wyniku wstawienia, usunięcia lub zmiany kolejności)CellSubclass.swift
ViewController.swift
źródło
buttonTapped
jest funkcją delegata i znajduje się w kontrolerze widoku. W moim przykładziesomeButtonTapped
jest to metoda akcji w komórce@IBAction func someButtonTapped(sender: UIButton) { self.delegate?.buttonTapped(self) }
UPDATE : Pobieranie indexPath komórki zawierającej przycisk (zarówno sekcja, jak i wiersz):
Korzystanie z pozycji przycisku
Wewnątrz
buttonTapped
metody możesz pobrać położenie przycisku, przekonwertować go na współrzędną w tableView, a następnie pobrać indexPath wiersza o tej współrzędnej.UWAGA : Czasami możesz napotkać przypadek krawędzi, gdy użycie funkcji
view.convert(CGPointZero, to:self.tableView)
powoduje znalezienienil
wiersza w punkcie, nawet jeśli znajduje się tam komórka tableView. Aby to naprawić, spróbuj podać rzeczywistą współrzędną, która jest nieco odsunięta od początku, na przykład:Poprzednia odpowiedź: Używanie właściwości tagu (zwraca tylko wiersz)
Zamiast wspinać się po drzewach Superview, aby złapać wskaźnik do komórki, w której znajduje się przycisk UIButton, istnieje bezpieczniejsza, bardziej powtarzalna technika wykorzystująca właściwość button.tag wspomnianą przez Antonio powyżej, opisaną w tej odpowiedzi i pokazaną poniżej:
W
cellForRowAtIndexPath:
ustawiasz właściwość tagu:Następnie w
buttonClicked:
funkcji odwołujesz się do tego tagu, aby pobrać wiersz indexPath, w którym znajduje się przycisk:Wolę tę metodę, ponieważ odkryłem, że kołysanie się w drzewach nadzoru może być ryzykownym sposobem projektowania aplikacji. Ponadto w przypadku obiektywu C używałem tej techniki w przeszłości i byłem zadowolony z wyniku.
źródło
indexPath.section
dodatek doindexPath.row
(bez resetowania właściwości tagu jakoindexPath.section
),cellForRowAtIndexPath:
możesz po prostu zmienić tag nabutton.tag = indexPath
, a następnie wbuttonClicked:
funkcji można uzyskać dostęp zarówno za pomocą, jaksender.tag.row
isender.tag.section
.Użyj rozszerzenia UITableView, aby pobrać komórkę dla dowolnego widoku:
@ Paulw11 odpowiedź dotycząca skonfigurowania niestandardowego typu komórki z właściwością delegata, która wysyła komunikaty do widoku tabeli, jest dobrym rozwiązaniem, ale wymaga pewnej ilości pracy do skonfigurowania.
Myślę, że chodzenie po hierarchii widoku komórki w widoku tabeli w poszukiwaniu komórki to zły pomysł. Jest kruchy - jeśli później umieścisz przycisk w widoku w celach związanych z układem, kod prawdopodobnie się zepsuje.
Używanie tagów widoku jest również delikatne. Musisz pamiętać o skonfigurowaniu tagów podczas tworzenia komórki, a jeśli użyjesz tego podejścia w kontrolerze widoku, który używa tagów widoku do innego celu, możesz mieć zduplikowane numery znaczników, a kod może nie działać zgodnie z oczekiwaniami.
Utworzyłem rozszerzenie do UITableView, które pozwala uzyskać indexPath dla dowolnego widoku zawartego w komórce widoku tabeli. Zwraca wartość,
Optional
która będzie nil, jeśli przekazany widok faktycznie nie mieści się w komórce widoku tabeli. Poniżej znajduje się plik źródłowy rozszerzenia w całości. Możesz po prostu umieścić ten plik w swoim projekcie, a następnie użyć dołączonejindexPathForView(_:)
metody, aby znaleźć indexPath, która zawiera dowolny widok.Aby go użyć, możesz po prostu wywołać metodę w IBAction dla przycisku zawartego w komórce:
(Zwróć uwagę, że
indexPathForView(_:)
funkcja będzie działać tylko wtedy, gdy przekazany obiekt widoku jest zawarty w komórce, która jest obecnie na ekranie. Jest to rozsądne, ponieważ widok, którego nie ma na ekranie, nie należy w rzeczywistości do określonej ścieżki indexPath; prawdopodobnie być przypisane do innego indexPath, gdy zawiera komórkę jest odtwarzana).EDYTOWAĆ:
Możesz pobrać działający projekt demonstracyjny, który używa powyższego rozszerzenia z Github: TableViewExtension.git
źródło
Dla
Swift2.1
Znalazłem sposób, żeby to zrobić, mam nadzieję, że to pomoże.
źródło
Masz przycisk (myButton) lub inny widok w komórce. Przypisz tag w cellForRowAt w ten sposób
Teraz w tobie TapFunction lub jakikolwiek inny. Pobierz go w ten sposób i zapisz w zmiennej lokalnej.
Następnie możesz użyć w dowolnym miejscu tego currentCellNumber, aby uzyskać indexPath.row wybranego przycisku.
Cieszyć się!
źródło
W Swift 4 po prostu użyj tego:
źródło
tableView
jest to zmienna outlet, do której należy odwołać się przed zadziałaniem tej odpowiedzi.Bardzo proste uzyskanie szybkiej ścieżki indeksu 4, 5
Jak uzyskać IndexPath Inside Btn Click:
źródło
Ponieważ nadawcą programu obsługi zdarzeń jest sam przycisk, użyłbym właściwości przycisku
tag
do przechowywania indeksu zainicjowanego wcellForRowAtIndexPath
.Ale przy odrobinie więcej pracy wykonałbym zupełnie inny sposób. Jeśli używasz niestandardowej komórki, podszedłbym do problemu:
cellForRowAtIndexPath
źródło
Po zapoznaniu się z sugestią Paulw11 dotyczącą użycia funkcji wywołania zwrotnego delegata, chciałem ją nieco rozwinąć / przedstawić inną, podobną sugestię. Jeśli nie chcesz używać wzorca delegata, możesz szybko użyć domknięć w następujący sposób:
Twoja klasa komórkowa:
Twoja
cellForRowAtIndexPath
metoda:źródło
Znalazłem bardzo łatwy sposób zarządzania dowolną komórką w tableView i collectionView przy użyciu klasy Model i działa to równie doskonale.
Obecnie istnieje znacznie lepszy sposób radzenia sobie z tym. To zadziała do zarządzania komórką i wartością.
Oto moje wyjście (zrzut ekranu), więc zobacz to:
RNCheckedModel
, napisz kod jak poniżej.źródło
Użyłem metody convertPoint, aby pobrać punkt z widoku tabeli i przekazać ten punkt do metody indexPathForRowAtPoint, aby uzyskać indexPath
źródło
Spróbuj użyć #selector, aby wywołać IBaction.In the cellforrowatindexpath
W ten sposób możesz uzyskać dostęp do indexpath wewnątrz metody editButtonPressed
źródło
W moim przypadku mam wiele sekcji i zarówno indeks sekcji, jak i wiersza są kluczowe, więc w takim przypadku właśnie utworzyłem właściwość w UIButton, w której ustawiłem indexPath komórki w następujący sposób:
Następnie ustaw właściwość w cellForRowAt w następujący sposób:
Następnie w handleTapAction możesz pobrać indexPath w następujący sposób:
źródło
Swift 4 i 5
Metoda 1 przy użyciu delegata protokołu
Na przykład masz
UITableViewCell
z imieniemMyCell
Teraz utwórz plik
protocol
W następnym kroku utwórz rozszerzenie
UITableView
W swoim
UIViewController
zaimplementuj protokółMyCellDelegate
Metoda 2 z użyciem domknięć
W
UIViewController
źródło
W Swift 3. Użyto również instrukcji guard, unikając długiego łańcucha nawiasów.
źródło
Czasami przycisk może znajdować się wewnątrz innego widoku UITableViewCell. W takim przypadku superview.superview może nie dać obiektu komórki i dlatego indexPath będzie równa zero.
W takim przypadku powinniśmy szukać superwizji, aż otrzymamy obiekt komórki.
Funkcja pobierania obiektu komórki przez superview
Teraz możemy uzyskać indexPath po dotknięciu przycisku, jak poniżej
źródło
źródło