UIRefreshControl bez UITableViewController

Tak z ciekawości, ponieważ nie od razu wydaje się to możliwe, ale czy istnieje sprytny sposób na wykorzystanie nowej klasy iOS 6 UIRefreshControl bez użycia podklasy UITableViewController?

Często używam UIViewController z UITableView subview i zgodne z UITableViewDataSource i UITableViewDelegate zamiast używać UITableViewController wprost.

Author: Venkadesh, 2012-09-19

12 answers

Na przeczucie i na podstawie inspiracji Drummerba, próbowałem po prostu dodać instancję UIRefreshControl jako subview do mojego UITableView. I to magicznie po prostu działa!

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];

To dodaje UIRefreshControl powyżej widoku tabeli i działa zgodnie z oczekiwaniami bez konieczności używania UITableViewController :)


EDIT: powyższe nadal działa, ale jak zauważyli niektórzy, podczas dodawania interfejsu UIRefreshControl w ten sposób występuje lekkie "zacinanie się". Rozwiązaniem jest utworzenie instancji UITableViewController, a następnie ustawienie Twój UIRefreshControl i UITableView do tego, czyli:

UITableViewController *tableViewController = [[UITableViewController alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;
 386
Author: Keller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-05 00:46:48

Aby wyeliminować jąkanie, które jest spowodowane zaakceptowaną odpowiedzią, możesz przypisać UITableView do UITableViewController.

_tableViewController = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
[self addChildViewController:_tableViewController];

_tableViewController.refreshControl = [UIRefreshControl new];
[_tableViewController.refreshControl addTarget:self action:@selector(loadStream) forControlEvents:UIControlEventValueChanged];

_theTableView = _tableViewController.tableView;

EDIT:

Sposób na dodanie UIRefreshControl Bez UITableViewController bez jąkania i zachowanie ładnej animacji po odświeżeniu danych w widoku tableview.

UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.theTableView addSubview:refreshControl];
[self.theTableView sendSubviewToBack:refreshControl];

Później podczas obsługi odświeżonych danych...

- (void)handleRefresh:(UIRefreshControl *)refreshControl {
    [self.theTableView reloadData];
    [self.theTableView layoutIfNeeded];
    [refreshControl endRefreshing];
}
 94
Author: Piotr Tomasik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 18:29:21

Spróbowałbyś użyć widoku kontenera wewnątrz Viewcontrollera, którego używasz. możesz zdefiniować czystą podklasę UITableViewController za pomocą dedykowanego tableview i umieścić ją w ViewController.

 21
Author: Tomohisa Takaoka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-25 21:09:31

Cóż UIRefreshControl jest podklasą UIView, więc możesz jej używać samodzielnie. Nie jestem pewien, jak to się przedstawia. Renderowanie może po prostu zależeć od ramki, ale może również polegać na UIScrollView lub UITableViewController.

Tak czy inaczej, będzie to bardziej hack niż eleganckie rozwiązanie. Polecam zajrzeć do jednego z dostępnych klonów 3rd party lub napisać swój własne.

ODRefreshControl

Tutaj wpisz opis obrazka

SlimeRefresh

Tutaj wpisz opis obrazka

 18
Author: DrummerB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-19 15:38:46

Spróbuj opóźnić wywołanie metody refreshControl -endRefresh o ułamek sekundy po przeładowaniu zawartości tableView, używając NSObject -performSelector:withObject:afterDelay: lub GCD dispatch_after.

Utworzyłem kategorię na UIRefreshControl dla tego:

@implementation UIRefreshControl (Delay)

- (void)endRefreshingAfterDelay:(NSTimeInterval)delay {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self endRefreshing];
    });
}

@end

Przetestowałem go i działa to również na widokach kolekcji. Zauważyłem, że opóźnienie tak małe jak 0.01 sekundy wystarczy:

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
 7
Author: boliva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-03 04:48:41

IOS 10 Swift 3.0

It ' s simple

import UIKit

class ViewControllerA: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myTableView.delegate = self
        myTableView.dataSource = self

        if #available(iOS 10.0, *) {
            let refreshControl = UIRefreshControl()
            let title = NSLocalizedString("PullToRefresh", comment: "Pull to refresh")
            refreshControl.attributedTitle = NSAttributedString(string: title)
            refreshControl.addTarget(self,
                                     action: #selector(refreshOptions(sender:)),
                                     for: .valueChanged)
            myTableView.refreshControl = refreshControl
        }
    }

    @objc private func refreshOptions(sender: UIRefreshControl) {
        // Perform actions to refresh the content
        // ...
        // and then dismiss the control
        sender.endRefreshing()
    }

    // MARK: - Table view data source

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 12
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        cell.textLabel?.text = "Cell \(String(indexPath.row))"
        return cell
    }

}

Tutaj wpisz opis obrazka

Jeśli chcesz dowiedzieć się więcej o IOS 10 UIRefreshControl przeczytaj Proszę..

 6
Author: Ashok R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-22 15:49:46

Dodanie kontrolki odświeżania jako podglądu podrzędnego tworzy pustą przestrzeń nad nagłówkami sekcji.

Zamiast tego, wbudowałem UITableViewController do mojego UIViewController, a następnie zmieniłem moją Właściwość tableView, aby wskazywała na wbudowaną i viola! Minimalne zmiany kodu. :-)

Kroki:

  1. Utwórz nowy UITableViewController w Storyboard i osadzić go w oryginalnym UIViewController
  2. Zastąp @IBOutlet weak var tableView: UITableView! tym z nowo wbudowanego kontrolera UITableViewController, jak pokazano poniżej

class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableViewController = self.childViewControllers.first as! UITableViewController
        tableView = tableViewController.tableView
        tableView.dataSource = self
        tableView.delegate = self

        // Now we can (properly) add the refresh control
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: .ValueChanged)
        tableViewController.refreshControl = refreshControl
    }

    ...
}
 3
Author: cbh2000,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 07:33:38

Dla Swift 2.2 .

Najpierw Utwórz UIRefreshControl() .

var refreshControl : UIRefreshControl!

W metodzie viewDidLoad () dodaj:

refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
    refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refreshControl)

And make refresh function

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}
 2
Author: stakahop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 20:06:31

Oto inne rozwiązanie, które jest trochę inne.

Musiałem go użyć z powodu pewnych problemów z hierarchią widoków: tworzyłem funkcjonalność, która wymagała przekazywania widoków do różnych miejsc w hierarchii widoków, co złamało się podczas używania tableview UITableView kontrolera b / c tableView jest głównym widokiem UITableView kontrolera (self.widok), a nie tylko zwykły widok, stworzył niespójne hierarchie kontrolera / widoku i spowodował awarię.

Zasadniczo utwórz własną podklasę UITableViewController i nadpisaj loadView, aby przypisać self.wyświetl inny widok i Nadpisz właściwość tableView, aby zwrócić oddzielny widok tableview.

Na przykład:

@interface MyTableVC : UITableViewController
@end

@interface MyTableVC ()
@property (nonatomic, strong) UITableView *separateTableView;
@end

@implementation MyTableVC

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectZero];
}

- (UITableView *)tableView {
    return self.separateTableView;
}

- (void)setTableView:(UITableView *)tableView {
    self.separateTableView = tableView;
}

@end

W połączeniu z rozwiązaniem Kellera będzie to bardziej wytrzymałe w tym sensie, że tableView jest teraz regularnym widokiem, a nie głównym widokiem VC, i będzie bardziej odporne na zmiany hierarchii widoków. Przykład użycia go w ten sposób:

MyTableVC *tableViewController = [[MyTableVC alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

Istnieje inne możliwe zastosowanie dla to:

Ponieważ podklasowanie w ten sposób oddziela ja.widok z siebie.tableView, możliwe jest teraz używanie tego kontrolera UITableViewController jako bardziej zwykłego kontrolera i dodawanie innych podglądów do self.Widok bez osobliwości dodawania podwidi do UITableView, więc można rozważyć uczynienie ich kontrolerów widoku bezpośrednio podklasą UITableViewController zamiast mieć dzieci uitableviewcontroller.

Niektóre rzeczy, na które warto uważać:

Ponieważ nadpisujemy widok tabeli nieruchomość bez wywoływania super, mogą być pewne rzeczy, na które należy uważać i powinny obsługiwać w razie potrzeby. Na przykład ustawienie widoku tableview w powyższym przykładzie nie spowoduje dodania widoku tableview do self.Wyświetl i nie ustawiaj ramki, którą chcesz zrobić. Ponadto, w tej implementacji nie ma domyślnego widoku tableView, gdy klasa jest tworzona jako instancja, co jest również czymś, co możesz rozważyć dodanie. Nie zamieszczam go tutaj, bo tak jest w każdym przypadku, a to rozwiązanie faktycznie dobrze pasuje z rozwiązaniem Kellera.

 0
Author: psilencer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-08 21:48:06

Spróbuj tego,

Powyższe rozwiązania są w porządku, ale tableView.refreshControl jest dostępny tylko dla UITableViewController, do iOS 9.x i jest dostępny w widoku UITableView z iOS 10.XD

Napisane w Swift 3-

let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(FeedViewController.loadNewData), for: UIControlEvents.valueChanged)
// Fix for the RefreshControl Not appearing in background
tableView?.addSubview(refreshControl)
tableView.sendSubview(toBack: refreshControl)
 0
Author: Ankit Kumar Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-12 05:12:07

Pierwsza sugestia Kellera powoduje dziwny błąd w iOS 7, gdzie wstawka tabeli jest zwiększana po ponownym pojawieniu się kontrolera widoku. Zmiana na drugą odpowiedź, za pomocą kontrolera uitableviewcontroller, naprawiła dla mnie pewne rzeczy.

 -1
Author: Mark Bridges,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-25 11:13:01

Okazuje się, że podczas używania kontrolera UIViewController z subview UITableView i zgodnego z UITableViewDataSource i UITableViewDelegate można użyć następujących elementów:

self.refreshControl = [[UIRefreshControl alloc]init];
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
 -6
Author: Clint Pick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 19:04:30