Chcę zmienić przesunięcie tabeli po zakończeniu ładowania, a przesunięcie to zależy od liczby komórek załadowanych do tabeli.
Czy mimo to w SDK jest informacja, kiedy zakończyło się ładowanie uitableview? Nie widzę nic ani na delegacie, ani w protokołach źródła danych.
Nie mogę użyć liczby źródeł danych z powodu ładowania tylko widocznych komórek.
ios
iphone
uitableview
czarnogóra
źródło
źródło
Odpowiedzi:
Popraw do @RichX odpowiedź:
lastRow
może to być oba[tableView numberOfRowsInSection: 0] - 1
lub((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
. Więc kod będzie wyglądał następująco:AKTUALIZACJA: Cóż, komentarz @ htafoya jest słuszny. Jeśli chcesz, aby ten kod wykrył koniec ładowania wszystkich danych ze źródła, nie zrobiłby tego, ale to nie jest oryginalne pytanie. Ten kod służy do wykrywania, kiedy wyświetlane są wszystkie komórki, które mają być widoczne.
willDisplayCell:
używany tutaj dla płynniejszego interfejsu użytkownika (pojedyncza komórka zwykle wyświetla się szybko powillDisplay:
wywołaniu). Możesz też spróbowaćtableView:didEndDisplayingCell:
.źródło
viewForFooterInSection
metodzie.Wersja Swift 3 i 4 i 5:
źródło
Zawsze używam tego bardzo prostego rozwiązania:
źródło
[tableView numberOfRowsInSection: 0] - 1
. Musisz zastąpić0
wymaganą wartością. Ale to nie jest problem. Problem polega na tym, że UITableView ładuje się tylko jako widoczny. Jednak((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
rozwiązuje problem.Oto inna opcja, która wydaje się działać dla mnie. W metodzie delegata viewForFooter sprawdź, czy jest to ostatnia sekcja i dodaj tam swój kod. Takie podejście przyszło mi do głowy po zdaniu sobie sprawy, że willDisplayCell nie uwzględnia stopek, jeśli je masz.
Uważam, że to podejście działa najlepiej, jeśli szukasz końcowego obciążenia dla całego
UITableView
, a nie tylko widocznych komórek. W zależności od potrzeb możesz chcieć tylko widocznych komórek, w takim przypadku odpowiedzią folexu jest dobra trasa.źródło
nil
ztableView:viewForFooterInSection:
bałaganu z moim układem w iOS 7 przy użyciu Auto Layout.return CGRectMake(0,0,0,0);
self.tableView.sectionFooterHeight = 0
. Tak czy inaczej, wydaje się, że wstawiany jest widok stopki sekcji o wysokości około 10. Założę się, że mógłbym to naprawić, dodając ograniczenie wysokości 0 do widoku, który zwracam. W każdym razie jestem dobry, ponieważ tak naprawdę chciałem dowiedzieć się, jak uruchomić UITableView na ostatniej komórce, ale zobaczyłem to jako pierwszy.Rozwiązanie Swift 2:
źródło
Korzystanie z prywatnego interfejsu API:
Korzystanie z publicznego interfejsu API:
Możliwym lepszym projektem jest dodanie widocznych komórek do zestawu, wtedy gdy trzeba sprawdzić, czy tabela jest załadowana, można zamiast tego zrobić pętlę for wokół tego zestawu, np.
źródło
Dla wybranej wersji odpowiedzi w Swift 3:
Potrzebowałem zmiennej isLoadingTableView, ponieważ chciałem się upewnić, że tabela została załadowana przed dokonaniem domyślnego wyboru komórki. Jeśli tego nie uwzględnisz, za każdym razem, gdy przewiniesz tabelę, ponownie wywoła twój kod.
źródło
Najlepszym podejściem, jakie znam, jest odpowiedź Erica pod adresem: Otrzymywać powiadomienie, gdy UITableView zakończy proszenie o dane?
Aktualizacja: Aby to zadziałało, muszę włączyć te połączenia
-tableView:cellForRowAtIndexPath:
źródło
Aby wiedzieć, kiedy widok tabeli kończy ładowanie zawartości, najpierw musimy mieć podstawową wiedzę o tym, jak widoki są wyświetlane na ekranie.
W cyklu życia aplikacji istnieją 4 kluczowe momenty:
Czasy 2 i 3 są całkowicie oddzielone. Czemu ? Ze względu na wydajność nie chcemy wykonywać wszystkich obliczeń w momencie 3 za każdym razem, gdy wprowadzana jest modyfikacja.
Myślę więc, że masz do czynienia z takim przypadkiem:
Co tu jest nie tak?
Jak każdy widok, widok tabeli leniwie ponownie ładuje zawartość. Właściwie, jeśli zadzwonisz
reloadData
wiele razy, nie spowoduje to problemów z wydajnością. Widok tabeli tylko ponownie oblicza swój rozmiar zawartości na podstawie swojej implementacji delegata i czeka na moment 3, aby załadować swoje komórki. Ten czas nazywa się przebiegiem układu.OK, jak dostać się do karty układu?
Podczas przebiegu układu aplikacja oblicza wszystkie klatki hierarchii widoków. Aby wziąć udział, można zastąpić dedykowane metody
layoutSubviews
,updateLayoutConstraints
etc w krótkim czasieUIView
oraz równoważne metody w podklasie widok kontrolera.Dokładnie to robi widok tabeli. Zastępuje
layoutSubviews
i na podstawie implementacji delegata dodaje lub usuwa komórki. WywołujecellForRow
bezpośrednio przed dodaniem i ułożeniem nowej komórki,willDisplay
zaraz po. Jeśli wywołałeśreloadData
lub właśnie dodałeś widok tabeli do hierarchii, widok tabel dodaje tyle komórek, ile potrzeba, aby wypełnić ramkę w tym kluczowym momencie.W porządku, ale teraz, jak sprawdzić, kiedy widok tabel zakończył ponowne ładowanie zawartości?
Możemy teraz przeformułować to pytanie: skąd wiedzieć, kiedy widok tabeli skończył układać podglądy?
• Najłatwiej jest wejść do układu widoku tabeli:
Zwróć uwagę, że ta metoda jest wywoływana wiele razy w cyklu życia widoku tabeli. Ze względu na przewijanie i usuwanie z kolejki widoku tabeli komórki są często modyfikowane, usuwane i dodawane. Ale to działa zaraz po
super.layoutSubviews()
załadowaniu komórek. To rozwiązanie jest równoważne oczekiwaniu nawillDisplay
zdarzenie ostatniej ścieżki indeksu. To zdarzenie jest wywoływane podczas wykonywanialayoutSubviews
widoku tabeli dla każdej dodanej komórki.• Innym sposobem jest wywołanie, gdy aplikacja zakończy przebieg układu.
Jak opisano w dokumentacji , możesz skorzystać z opcji
UIView.animate(withDuration:completion)
:To rozwiązanie działa, ale ekran odświeży się jeden raz między utworzeniem układu a wywołaniem bloku. Jest to równoważne
DispatchMain.async
rozwiązaniu, ale określone.• Alternatywnie wolałbym wymusić układ widoku tabeli
Istnieje specjalna metoda wymuszania natychmiastowego obliczenia ramek widoku podrzędnego w dowolnym widoku
layoutIfNeeded
:Należy jednak zachować ostrożność, ponieważ spowoduje to usunięcie leniwego ładowania używanego przez system. Wielokrotne wywoływanie tych metod może powodować problemy z wydajnością. Upewnij się, że nie zostaną one wywołane przed obliczeniem ramki widoku tabeli, w przeciwnym razie widok tabeli zostanie ponownie załadowany i nie zostaniesz o tym powiadomiony.
Myślę, że nie ma idealnego rozwiązania. Tworzenie podklas może prowadzić do trubli. Przebieg układu zaczyna się od góry i przechodzi do dołu, więc nie jest łatwo otrzymać powiadomienie, gdy cały układ jest gotowy. I
layoutIfNeeded()
może powodować problemy z wydajnością itp. Ale znając te opcje, powinieneś być w stanie pomyśleć o jednej alternatywie, która będzie pasować do Twoich potrzeb.źródło
Oto jak to się robi w Swift 3:
źródło
oto jak to robię w Swift 3
źródło
Oto co bym zrobił.
W twojej klasie bazowej (może to być rootVC BaseVc itp.),
A. Napisz protokół, aby wysłać wywołanie zwrotne „DidFinishReloading”.
B. Napisz ogólną metodę ponownego ładowania widoku tabeli.
W implementacji metody klasy bazowej wywołaj reloadData, a następnie delegateMethod z opóźnieniem.
Potwierdź protokół zakończenia przeładowania we wszystkich kontrolerach widoku, w których potrzebujesz wywołania zwrotnego.
Źródła: https://discussions.apple.com/thread/2598339?start=0&tstart=0
źródło
Odpowiedź @folex jest prawidłowa.
Ale zakończy się niepowodzeniem, jeśli tableView ma więcej niż jedną sekcję wyświetlaną jednocześnie.
źródło
W Swift możesz zrobić coś takiego. Następujący warunek będzie spełniony za każdym razem, gdy osiągniesz koniec tableView
źródło
Wiem, że to odpowiedź, po prostu dodaję zalecenie.
Zgodnie z następującą dokumentacją
https://www.objc.io/issues/2-concurrency/thread-safe-class-design/
Naprawianie problemów z synchronizacją za pomocą dispatch_async to zły pomysł. Proponuję załatwić to dodając FLAG czy coś.
źródło
Jeśli masz wiele sekcji, oto jak uzyskać ostatni wiersz w ostatniej sekcji (Swift 3):
źródło
Dość przypadkowo wpadłem na to rozwiązanie:
Musisz ustawić footerView przed pobraniem contentSize, np. W viewDidLoad. Przy okazji. ustawienie footeView pozwala usunąć „nieużywane” separatory
źródło
Czy szukasz łącznej liczby pozycji, które zostaną wyświetlone w tabeli, czy łącznej liczby aktualnie widocznych pozycji? Tak czy inaczej… Uważam, że metoda „viewDidLoad” jest wykonywana po wywołaniu wszystkich metod źródła danych. Jednak będzie to działać tylko przy pierwszym załadowaniu danych (jeśli używasz jednego alokowanego ViewController).
źródło
Kopiuję kod Andrew i rozszerzam go, aby uwzględnić przypadek, w którym masz tylko 1 wiersz w tabeli. Jak dotąd to dla mnie działa!
UWAGA: używam tylko 1 sekcji z kodu Andrew, więc miej to na uwadze.
źródło
W iOS7.0x rozwiązanie jest nieco inne. Oto co wymyśliłem.
źródło
Cel C
Szybki
źródło
UICollectionView
ile rozumiem.