iPhone: Domyślnie ukryj pasek wyszukiwania UITableView

85

Użyłem Interface Builder do stworzenia widoku tabeli, do którego dodałem pasek wyszukiwania biblioteki i kontroler wyświetlania wyszukiwania, aby dodać funkcję wyszukiwania. Jednak IB skonfigurował go tak, aby pasek był widoczny u góry ekranu, gdy widok jest wyświetlany po raz pierwszy.

Chciałbym wiedzieć, jak domyślnie ukryć pasek wyszukiwania, ale nadal można go przewijać w widoku tabeli (zobacz przykład aplikacji Mail firmy Apple). Próbowałem nazywając scrollRectToVisible:animated:w viewDidLoadprzewijać widok tabeli w dół, ale bezskutecznie. Jaki jest preferowany sposób domyślnego ukrywania paska wyszukiwania?

Tim
źródło

Odpowiedzi:

116

Najpierw upewnij się, że dodajesz UISearchBar do tableHeaderView UITableView, tak aby był przewijany wraz z zawartością tabeli i nie był ustalony na górze widoku.

Pasek wyszukiwania nie jest liczony jako wiersz w widoku tabeli, więc jeśli przewiniesz górę widoku tabeli do pierwszego wiersza, „ukryje” on pasek wyszukiwania:

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

lub w Swift:

yourTableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)

Upewnij się, że nie przewijasz widoku tabeli, zanim nie zawiera on danych ( scrollToRowAtIndexPathspowoduje zgłoszenie wyjątku, jeśli podana ścieżka_indeksu nie wskazuje prawidłowego wiersza (tj. Jeśli widok tabeli jest pusty)).

Zargony
źródło
12
Właściwie pojawia się problem polegający na tym, że widok tabeli nie przewija się, jeśli nie ma wystarczającej liczby wierszy, aby wypełnić ekran - w tabeli z jednym lub dwoma wierszami ten kod nic nie robi. Czy to oczekiwane zachowanie? Czy mogę to jakoś obejść?
Tim,
18
Znalazłem sposób: zamiast przewijać do ścieżki indeksu, zmień przesunięcie zawartości widoku przewijania tabeli na CGRect o 0,0, 44,0
Tim
107
Tim, to jest droga! Użyłem self.tableView.contentOffset = CGPointMake (0, self.searchDisplayController.searchBar.frame.size.height);
Joe D'Andrea
1
Btw - kiedy wstawiałem ten kod po wywołaniu [tableView reloadData], co spowodowało, że moja tabela przeszła z 2 wierszy do wystarczającej liczby wierszy, aby umożliwić normalne przewijanie, stwierdziłem, że użycie metody contentOffset spowodowało szarpnięcie w wyświetlaniu i ukrywaniu wyszukiwania box podczas korzystania z metody scrollToRowAtIndexPath nie miał takiego samego szarpania.
Chris R
1
To jedyny ostateczny sposób, który działa w KAŻDYCH okolicznościach. Ustawienie contentOffsetdowolnej wartości nie działa, jeśli używasz złożonego układu kontrolera widoku. Nie polecam tego.
eonil
45

Nie dodawaj UISearchBar jako podwidoku UITableView, nie jest to konieczne.

UITableView ma właściwość tableHeaderView, która jest idealna do tego:

- (void) viewDidLoad {
    [super viewDidLoad]; 
    self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease];
    self.searchBar.showsCancelButton = YES;    
    self.searchBar.delegate = self;
    self.tableView.tableHeaderView = self.searchBar;     
}

Jeśli nie chcesz go widzieć domyślnie:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.tableView setContentOffset:CGPointMake(0, 44)];
}

Dostaję również przycisk anulowania, aby ponownie go ukryć ... (i usunąć klawiaturę)

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES];
    [self.searchBar resignFirstResponder];
}
bandejapaisa
źródło
Dla mnie było to jedyne rozwiązanie, które stworzyło ukrytą implementację UISearchBar, która wydawała się zgodna z HIG. Inne rozwiązania, w których „utknął” na górze widoku tabeli, wydają się nienaturalne.
kurtzmarc
1
To rozwiązanie działało najlepiej. Moim zdaniem to powinna być odpowiedź.
darwindeeds
To fajne rozwiązanie (+1). Jednak tableView nie ukrywa poprawnie paska wyszukiwania w niektórych przypadkach (w moim przypadku: gdy kontroler tableview jest wypychany z innego kontrolera widoku). Jest pytanie dotyczące tego problemu: stackoverflow.com/questions/15222186/… Myślę, że udzielona odpowiedź na to pytanie nie jest jednak zbyt dobra. @bandejapaisa, masz jakiś pomysł?
Brian
3
To działało dobrze dla mnie, chociaż zamiast sztywnego kodowania 44 przez cały czas sugeruję użycie self.tableView.tableHeaderView.frame.size.height in viewWillAppear, aby umożliwić zmiany, które Apple może wprowadzić w przyszłości do wysokości paska wyszukiwania.
John Stephen
umieszczenie tego viewWillAppearjest złym pomysłem, ponieważ będzie się uruchamiać za każdym razem, gdy wrócisz do widoku. Oznacza to, że widok stołu będzie się powoli zmniejszał. Irytujący błąd!
Syreny,
25

ContentOffset zostało odnotowane w komentarzach Tima i Joe D'Andrea, ale zostało to nieco rozszerzone poprzez dodanie animacji ukrywania paska wyszukiwania. Zauważyłem, że to trochę nieoczekiwane, że pasek wyszukiwania po prostu znika.

Mała aktualizacja dla tych, którzy chcą kierować reklamy na iOS 4.0 i nowsze, wypróbuj to:

[UIView animateWithDuration:0.4 animations:^{
    self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);
 } completion:nil];

Poprzednia odpowiedź:

[UIView beginAnimations:@"hidesearchbar" context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];

self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);

[UIView commitAnimations];

Andrei
źródło
9
Odkryłem, że kluczem do tego rozwiązania jest animacja. Wydaje się, że próba ustawienia przesunięcia zawartości bez animacji nic nie da. Zamiast jednak używać metod animacji (lub bloków) w tym przykładzie, stwierdzam, że samo wywołanie [self.tableView setContentOffset: CGPointMake (0,44) animated: TRUE] działa wystarczająco dobrze.
quickthyme
Wydaje się, że bez animacji w ogóle nie działa. @quickthyme dokonał tej samej obserwacji.
Thilo,
5
Udało mi się to bez potrzeby animacji, jeśli zaimplementujesz to viewDidAppear:zamiast viewDidLoad.
wbyoung
8

Odpowiedzi na to rozwiązanie jest wiele, jednak żadna nie działała dobrze.

To działa doskonale. Brak animacji i jest wykonywana-viewDidLoad

 - (void)viewDidLoad {
     [super viewDidLoad];
     self.tableView.contentOffset = CGPointMake(0,  self.searchBar.frame.size.height - self.tableView.contentOffset.y);
 }

Uwaga:

Kod zakłada, że ​​masz searchBar @propertylink do paska wyszukiwania. Jeśli nie, możesz użyć self.searchDisplayController.searchBarzamiast tego

Matej
źródło
to jedyny, który działał dla mnie! , ale robi to tylko un viewdidload ... więc za pierwszym razem jest ukryty, ale potem nie jest już ukrywany, gdy aplikacja jest uruchomiona. I próbowałem go pokazać, a widok zniknął, ale działa nieprawidłowo. Dzięki!
fguespe
@fguespe to dziwne .. ViewDidLoad powinno być wywoływane za każdym razem, gdy tworzony jest widok. Nigdy nie zdarzyło mi się, że UISearchBar był widoczny po powrocie z innego widoku.
Matej
korzystam z aplikacji z kartami. Może to?
fguespe
@fguespe Widzę, że to może być problem hmm. Niestety nie jestem pewien, jak rozwiązać ten -viewWillAppearproblem, jeśli nie działa .. Czy jest wywoływana, gdy kontroler kart przełącza się na widok?
Matej
viewwillappear i viewdidappear są wywoływane, ale próbowałem z obydwoma i widok jest źle przesunięty. Nie zwraca oczekiwanego wyniku. To znaczy, coś robi, ale robi to źle.
fguespe
7

Dla Swift 3+

Ja to zrobiłem:

Oświadcz, że var:

    var searchController = UISearchController()

I w viewDidLoad()metodzie

    searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = true
    searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "")
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.size.height)
Dasoga
źródło
5

Moim celem było ukrycie paska wyszukiwania dodanego do tableHeaderView zwykłego stylu TableView w scenorysie, gdy kontroler widoku jest załadowany i wyświetlenie paska, gdy użytkownik przewinie w dół u góry UITableView. Więc używam Swift i dodałem rozszerzenie:

extension UITableView {
    func hideSearchBar() {
        if let bar = self.tableHeaderView as? UISearchBar {
            let height = CGRectGetHeight(bar.frame)
            let offset = self.contentOffset.y
            if offset < height {
                self.contentOffset = CGPointMake(0, height)
            }
        }
    }
}

w viewDidLoad () po prostu wywołaj:

self.tableView.hideSearchBar()
HotJard
źródło
5

Wszystkie istniejące rozwiązania nie działają dla mnie na iOS 8, gdy nie ma wystarczającej liczby wierszy do wypełnienia tableView, ponieważ iOS dostosuje wstawkę automatycznie w tej sytuacji. (Istniejące odpowiedzi są dobre, gdy jest wystarczająco dużo wierszy)

Po zmarnowaniu 6 godzin na tę kwestię w końcu dostałem to rozwiązanie.

Krótko mówiąc, musisz wstawić puste komórki do tableView, jeśli nie ma wystarczającej liczby komórek, więc rozmiar zawartości tableView jest na tyle duży, że iOS nie dostosuje wstawki za Ciebie.

Oto, jak zrobiłem to w Swift:

1.) zadeklarować zmienną minimumCellNumjako właściwość klasy

var minimumCellNum: Int?

2.) Oblicz minimumCellNumi zestaw tableView.contentOffsetwviewWillAppear

let screenHeight = Int(UIScreen.mainScreen().bounds.height)

// 101 = Height of Status Bar(20) + Height of Navigation Bar(44) + Height of Tab Bar(49)
// you may need to subtract the height of other custom views from the screenHeight. For example, the height of your section headers.
self.minimumCellNum = (screenHeight - 103 - heightOfOtherCustomView) / heightOfYourCell
self.tableView.contentOffset = CGPointMake(0, 44)

3.) w tableView(tableView: UITableView, numberOfRowsInSection section: Int))

let numOfYourRows = YOUR LOGIC
if numOfYourRows > minimumCellNum {
    return numOfYourRows
} else {
    return minimumCellNum!
}

4.) Zarejestruj pustą komórkę, której selectionatrybutem jest None, w serii ujęć i wtableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)

if indexPath.row < numOfYourRows {
    return YOUR CUSTOM CELL
} else {
    let cell = tableView.dequeueReusableCellWithIdentifier("EmptyCell", forIndexPath: indexPath) as! UITableViewCell
    return cell
}

5.) w tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

if tableView == self.tableView {
    if numOfYourRows < (indexPath.row + 1) {
        return
    }
    YOUR LOGIC OF SELECTING A CELL
}

To nie jest idealne rozwiązanie, ale jest to jedyne obejście, które naprawdę działa dla mnie na iOS 8. Chciałbym wiedzieć, czy istnieje lepsze rozwiązanie.

Brian
źródło
Musiałem to zrobić dla iOS 11. Samo ustawienie contentOffset działało dla iOS 9/10 dla 0 lub więcej komórek, a także działało na iOS 11 dla 8+ komórek. Wszystko, co mniej wymagało tego rozwiązania. Czy jest powód dlaczego?
Tony
Myślę, że pierwszy akapit tego posta wyjaśnia, dlaczego.
Brian
Zrozumiałem pierwszy akapit, ale nadal było dziwne, że był „zepsuty” tylko na iOS 11 dla mnie. Spodziewałbym się podobnego zachowania w przypadku iOS 9, 10 i 11, gdy liczba komórek jest taka sama (mniej niż wystarczająca). Jeszcze raz dziękuję i przepraszam za przywołanie starego posta!
Tony
4

Żadne z powyższych nie działało u mnie, więc na wszelki wypadek, gdyby ktoś miał ten sam problem.

Mam searchBarustawiony tableHeaderViewna stole zgrupowane na iOS7. W viewDidLoadmuszę początkowo tableView.contentOffset = CGPointMake(0, 44);zachować searchBar„ukrycie”. Gdy użytkownik przewinie w dół, searchBarzostanie odtworzony

Cel: ukryj pasek wyszukiwania po naciśnięciu przycisku anulowania

W searchBarCancelButtonClicked(searchBar: UISearchBar!)

To nie zadziałało: [yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; tableView przewijał się zbyt mocno w górę, w wyniku czego wiersz 0 przeszedł za toolBar.

To nie zadziałało: tableView.ContentOffset = CGPointMake(0, 44) - nic się nie dzieje

To nie zadziałało: tableView.ContentOffset = CGPointMake(0, searchBar.frame.size.height) - nic się nie dzieje

To nie zadziałało: tableView.setContentOffset(CGPointMake(0, 44), animated: true); ponownie tableView przewijał się zbyt mocno w górę, w wyniku czego wiersz 0 przeszedł za toolBar.

To działało częściowo: tableView.setContentOffset(CGPointMake(0, 0) ale titleForHeaderInSectionznajdowało się za toolBarem

TO DZIAŁAŁO: tableView.setContentOffset(CGPointMake(0, -20)

Wydaje się to nielogiczne, ale tylko -20 przesunęło go na właściwą pozycję

grep
źródło
Naprawdę nie powinieneś twardo kodować swoich punktów, dlaczego nie używasz CGRectGetHeight(searchBar.bounds)?
Zorayr
Myślę, że musisz to robić w viewDidLoad () / init (), gdzie nie została ustawiona żadna ramka, aby uzyskać wysokość paska wyszukiwania. Może powinieneś spróbować z
viewDidLayoutSubviews
Jeśli tableView nie zakończył ładowania, żadne z ContentOffsetrozwiązań nie zadziała
Maor
4

Przesunięcie zawartości jest drogą do zrobienia, ale nie działa w 100% przypadków.

To nie działa, jeśli są ustawione estimatedRowHeightna stałą liczbę. Nie znam jeszcze pracy. Stworzyłem projekt pokazujący problem (y) i utworzyłem radar z Apple.

Sprawdź projekt, jeśli chcesz mieć przykład, jak szybko to wszystko skonfigurować.

RyanJM
źródło
1
Dziękuję Ci! To było to, czego szukałem. Musisz iść wysoko.
user2387149
3

Zwróć uwagę, że zaakceptowana odpowiedź ulegnie awarii, jeśli w widoku tabeli nie ma danych. A dodanie go do viewDidLoad może nie działać w pewnych okolicznościach.

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; // crashes if no rows/data

Dlatego zamiast tego dodaj ten wiersz kodu:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [yourTableView setContentOffset:CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)];
}
user3246173
źródło
2

Szczerze mówiąc, żadna z odpowiedzi tak naprawdę nie rozwiązała problemu (dla mnie). Jeśli w widoku tabeli nie ma wierszy LUB wysokość wiersza jest inna, te odpowiedzi nie wystarczą.

Jedyne, co działa:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.tableView.contentOffset = (CGPoint){.y =  self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height};
}
p0lAris
źródło
Dobre rozwiązanie problemu przesunięcia. Działa dla mnie, gdy używam UINavigationController.
Andreas Kraft
1
Rozwiązanie nie działa, gdy liczba wierszy nie obejmuje całego ekranu - czy znasz obejście tego problemu?
Zorayr
Nie jestem pewien, czy całkowicie to rozumiem. Działa to w przypadku mnie, gdy mam tylko kilka wierszy w tabeli. Jednak mam użyć następujących: self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];.
p0lAris
2

scrollToRowAtIndexPathMetoda powoduje awarię czy są zerowe wiersze w tabeli.

UITableView to jednak tylko widok przewijania, więc możesz po prostu zmienić przesunięcie zawartości.

To sprawdza, czy masz coś jako tableHeaderView i zakładając, że przewijasz, aby to ukryć

    if let searchHeight = tableView.tableHeaderView?.frame.height {
        tableView.setContentOffset(CGPoint.init(x: 0, y:searchHeight ), animated: false)
    }
Zdezorientowany Vorlon
źródło
1

Uważam, że aplikacja „Notatki” nie może wyszukiwać elementów, gdy tableView jest puste. Więc myślę, że -(void)addSubview:(UIView *)viewnajpierw używa się do dodania pustej tabeli. Po dodaniu elementu do jego tablicy źródła danych, uruchomi on kolejny fragment kodu w celu załadowania tableView.

Więc moje rozwiązanie to:

if([self.arrayList count] > 0)
{
     [self.tableView reloadData];     //use jdandrea's code to scroll view when cell==nil in cellForRowAtIndexPath
     self.tableView.scrollEnabled = YES;
}
else
{
     tableBlank = [[UITableView alloc]initWithFrame:CGRectMake(0,0,320,416) style:UITableViewStylePlain] autorelease];
     tableBlank.delegate = self;
     tableBlank.dataSource = self;
     [self.view addSubview:tableBlank];
}

Mam nadzieję że to pomoże :-)

Chilly Zhong
źródło
1

Zmień granice tableView, można to zrobić wewnątrz viewDidLoadi nie musisz się martwić, czy tabela jest pusta, czy nie (aby uniknąć wyjątku).

CGRect newBounds = self.tableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.tableView.bounds = newBounds;

Gdy użytkownik przewinie tabelę w dół, pojawi się pasek wyszukiwania i będzie się zachowywał normalnie

LightMan
źródło
1

Inne odpowiedzi na to pytanie albo w ogóle nie działały, zachowywały się dziwnie, gdy tableView miało 0 wierszy, albo powodowały zakłócenia pozycji przewijania podczas przechodzenia między nadrzędnymi i zagnieżdżonymi elementami zamówienia. To zadziałało dla mnie (celem było ukrycie paska UISearchBar podczas ładowania):

public override func viewWillAppear(animated: Bool) {        
    if self.tableView.contentOffset.y == 0 {
        self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height) 
    }
}

Objaśnienie
Za każdym razem, gdy tableViewpojawi się pojawi się, ten kod sprawdza, czy UISearchBar jest widoczny (co oznacza, że ypozycja contentOffset, czyli pozycja przewijania, to 0). Jeśli tak, po prostu przewija w dół wysokość paska wyszukiwania. Jeśli pasek wyszukiwania nie jest widoczny (pomyśl o większej liście elementów w tableView), nie będzie próbował przewijać elementu tableView, ponieważ zepsułoby to pozycjonowanie po powrocie z zagnieżdżonego elementu zamówienia.

Uwaga boczna
Zalecam umieszczenie tego kodu w oddzielnej metodzie, aby zapewnić pojedynczą odpowiedzialność i umożliwić ponowne użycie go w dowolnym momencie w kodzie.

kbpontius
źródło
1

Jeśli twoja tabela zawsze będzie miała co najmniej jeden wiersz, po prostu przewiń do pierwszego wiersza tabeli, a pasek wyszukiwania zostanie automatycznie ukryty.

let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)

self.tableView.selectRowAtIndexPath (firstIndexPath, animated: false, scrollPosition: .Top)

Jeśli umieścisz powyższy kod w viewDidLoad , wyrzuci on błąd, ponieważ tableView jeszcze się nie załadował, więc musisz umieścić go w viewDidAppear, ponieważ w tym momencie tableView już się załadował.

Jeśli umieścisz go na viewDidAppear , za każdym razem, gdy otworzysz tableView, przewinie się on do góry.

Może nie chcesz tego zachowania, jeśli tableView pozostaje otwarty, na przykład gdy jest to kontroler widoku UITabBar lub gdy wykonujesz przepływ, a następnie wrócisz. Jeśli chcesz, aby przewijał się do góry podczas początkowego ładowania, możesz utworzyć zmienną, aby sprawdzić, czy jest to ładowanie początkowe, aby tylko raz przewinął na górę.

Najpierw zdefiniuj zmienną o nazwie isInitialLoad w klasie kontrolera widoku i ustaw ją na wartość „true”:

var isInitialLoad = true

Następnie sprawdź, czy isInitialLoad ma wartość true w viewDidAppear, a jeśli tak, przewiń do góry i ustaw zmienną isInitialLoad na false:

if isInitialLoad {
            let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
            self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)

            isInitialLoad = false
        }
drdrdrdr
źródło
1

Poniższy kod działa dla mnie

self.tableView.contentOffset = CGPointMake(0.0, 44.0);
Ashu
źródło
1

Próbowałem ustawić przesunięcie zawartości i scrollToIndexpath, ale nic nie działało zadowalająco. Usunąłem ustawienie tableHeaderView jako searchBar z viewDidLoad i ustawiłem go w delegacie scrollview jak poniżej

override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
    if scrollView.contentOffset.y < 0 && tableView.tableHeaderView == nil {
        tableView.tableHeaderView = searchController.searchBar
        tableView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y + searchController.searchBar.frame.size.height), animated: false)
    }
}

To działało jak urok. Ustawienie przesunięcia zawartości służy do płynnego przewijania

Abdur Rahman
źródło
0

Nie zapomnij wziąć pod uwagę paska stanu i paska nawigacji . Mój kontroler widoku tabeli jest osadzony w kontrolerze nawigacji w viewDidAppear:

tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height)

pracował dla mnie.

fujianjin6471
źródło
0

Dla Swift:

Po prostu ustaw przesunięcie y zawartości tabeli, które powinno być podobne do wysokości paska wyszukiwania.

self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height)
stakahop
źródło
0

Szybki 3

działa również z pustym stołem!

W moim środowisku ładuję komórki niestandardowe za pomocą pliku xib, a parametr rowHeight jest ustawiany automatycznie.

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        self.tableView.contentOffset = CGPoint(x: 0, y: self.tableView.contentOffset.y + self.searchController.searchBar.bounds.height)
}
Jan
źródło
0

Miałem podobny problem. Jedynym sposobem rozwiązania tego problemu było użycie obserwatora wartości klucza we właściwości contentOffset UITableView.

Po pewnym debugowaniu zdałem sobie sprawę, że problem pojawia się tylko wtedy, gdy rozmiar zawartości widoku tabeli jest mniejszy niż widok tabeli. Uruchamiam KVO, gdy jest na viewWillAppear. I zatrzymanie wysyłki KVO 0,3 sekundy po pojawieniu się widoku. Za każdym razem, gdy contentOffset zmienił się na 0.0, KVO reaguje i ustawia contentOffset na wysokość paska wyszukiwania. Zatrzymuję asynchroniczne KVO po 0,3 sekundy, ponieważ układ widoku zresetuje contentOffset nawet po pojawieniu się widoku.

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

-(void)viewDidAppear:(BOOL)animated{
   __weak typeof (self) weakSelf = self;
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [weakSelf.tableView removeObserver:self forKeyPath:@"contentOffset"];});
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"contentOffset"] && self.tableView.contentOffset.y == 0.0) {
       self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.tableView.tableHeaderView.frame));
    }
}

-(void)dealloc {
    [self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}
slobodany
źródło