web-dev-qa-db-ja.com

UITableViewControllerなしのUIRefreshControl

すぐには可能ではないようですが、UIRefreshControlサブクラスを使用せずに新しいiOS 6のUITableViewControllerクラスを活用するための卑劣な方法はありますか。

UIViewControllerをそのまま使用するのではなく、UITableViewUITableViewDataSourceサブビューとともに使用し、UITableViewDelegateおよびUITableViewControllerに準拠させることがよくあります。

305
Keller

急いで、そしてDrummerBのインスピレーションに基づいて、私は単にUIRefreshControlのサブビューとしてUITableViewインスタンスを追加することを試みました。そしてそれは魔法のようにちょうどうまくいきます!

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

これにより、テーブルビューの上にUIRefreshControlが追加され、UITableViewControllerを使用しなくても期待どおりに機能します。


編集:これはまだうまくいくが、少数が指摘したように、この方法でUIRefreshControlを追加するとき、わずかな「吃音」がある。その解決策は、UITableViewControllerをインスタンス化してから、UIRefreshControlとUITableViewをそれに設定することです。

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
Keller

受け入れられた答えによって引き起こされる吃音を排除するために、あなたはUITableViewUITableViewControllerに割り当てることができます。

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

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

_theTableView = _tableViewController.tableView;

編集:

テーブルビューでデータを更新した後に、UIRefreshControlを付けずにUITableViewControllerを付け加え、Niceアニメーションを保持する方法。

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

後で更新されたデータを処理するとき...

- (void)handleRefresh:(UIRefreshControl *)refreshControl {
    [self.theTableView reloadData];
    [self.theTableView layoutIfNeeded];
    [refreshControl endRefreshing];
}
94
Piotr Tomasik

あなたがしようとしているのはあなたが使っているViewControllerの中でcontainer viewを使うことです。専用のtableviewを使用してきれいなUITableViewControllerサブクラスを定義し、それをViewControllerに配置することができます。

21

UIRefreshControlはUIViewのサブクラスなので、単独で使用できます。それがどのように自分自身をレンダリングするとしても私はよくわからない。レンダリングは単にフレームに依存しますが、UIScrollViewまたはUITableViewControllerにも依存する可能性があります。

いずれにせよ、それは優雅な解決策よりももっとハックになるでしょう。私はあなたが利用可能なサードパーティクローンの1つを調べるか、あなた自身のものを書くことを勧めます。

ODRefreshControl

enter image description here

SlimeRefresh

enter image description here

18
DrummerB

NSObjectの-endRefreshまたはGCDの-performSelector:withObject:afterDelay:を使用して、tableViewがその内容をリロードした後、refreshControl dispatch_afterメソッドの呼び出しを数分の1秒遅らせるようにしてください。

このためにUIRefreshControlにカテゴリを作成しました。

@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

私はそれをテストしました、そしてこれはコレクションビューにも働きます。 0.01秒という短い遅延で十分であることに気付きました。

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];
7
boliva

IOS 10 Swift 3.0

それは簡単です

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
    }

}

enter image description here

iOS 10のUIRefreshControlについて知りたい場合は、 ここを参照してください。

6
Ashok R

サブビューとして最新表示コントロールを追加すると、セクションヘッダーの上に空のスペースが作成されます。

代わりに、私はUITableViewControllerを私のUIViewControllerに埋め込み、それからtableViewプロパティを埋め込みのものを指すように変更しました。最小限のコード変更。 :-)

ステップ:

  1. ストーリーボードで新しいUITableViewControllerを作成し、それを元のUIViewControllerに埋め込む
  2. 以下に示すように、@IBOutlet weak var tableView: UITableView!を新しく埋め込まれたUITableViewControllerのものに置き換えます。

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
cbh2000

Swift 2.2の場合

まずUIRefreshControl()を作ります。

var refreshControl : UIRefreshControl!

ViewDidLoad()メソッドに次の行を追加します。

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

そしてリフレッシュ機能を作る

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}
2
stakahop

これを試して、

上記の解決策は問題ありませんが、tableView.refreshControlは、iOS 9.xまではUITableViewControllerでのみ使用可能で、iOS 10.x以降はUITableViewで提供されています。

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

これはもう一つ別の解決策です。

ビュー階層の問題があるため、これを使用する必要がありました。ビュー階層内のさまざまな場所にビューを渡す必要がある機能を作成していました。これは通常のビューだけではなく、コントローラ/ビューの階層が矛盾しているためクラッシュしていました。

基本的に独自のUITableViewControllerのサブクラスを作成し、loadViewをオーバーライドしてself.viewに別のビューを割り当て、tableViewプロパティをオーバーライドして別のtableviewを返します。

例えば:

@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

ケラーのソリューションと組み合わせると、tableViewがVCのルートビューではなく通常のビューになるという意味でより堅牢になり、ビュー階層の変更に対してより堅牢になります。このように使う例:

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;

これには別の使用方法があります。

このようにサブクラス化するとself.viewとself.tableViewが分離されるため、このUITableViewControllerを通常のコントローラとして使用し、他のサブビューをself.viewに追加することが可能になります。ビューコントローラは、UITableViewControllerの子を持つのではなく、直接UITableViewControllerのサブクラスです。

注意すべき点がいくつかあります。

Superを呼び出さずにtableViewプロパティをオーバーライドしているので、注意が必要な点がいくつかあり、必要に応じて処理する必要があります。たとえば、上の例でテーブルビューを設定しても、テーブルビューがself.viewに追加されたり、フレームを設定したりすることはできません。また、この実装では、クラスがインスタンス化されたときにデフォルトのtableViewが指定されていません。これも追加を検討することができます。これはケースバイケースであるため、ここでは説明しません。このソリューションは、実際にはKellerのソリューションに適しています。

0
psilencer