129

UITableViewController(UINavigationController内にあります)にUIRefreshControlを設定しましたが、期待どおりに機能します(つまり、プルダウンによって正しいイベントが発生します)。beginRefreshingただし、次のように、更新コントロールでインスタンスメソッドをプログラムで呼び出す場合。

[self.refreshControl beginRefreshing];

何も起こりません。アニメーション化してスピナーを表示する必要があります。更新後にメソッドを呼び出すと、endRefreshingメソッドは正しく機能します。

この動作で基本的なプロトタイププロジェクトを作成しました。UITableViewControllerをアプリケーションデリゲートのルートビューコントローラーに直接追加すると、正しく機能します。例:

self.viewController = tableViewController;
self.window.rootViewController = self.viewController;

ただし、tableViewController最初にをUINavigationControllerに追加してから、ナビゲーションコントローラーをとして追加するとrootViewController、このbeginRefreshingメソッドは機能しなくなります。例えば

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
self.viewController = navController;
self.window.rootViewController = self.viewController;

私の感じでは、これはナビゲーションコントローラー内のネストされたビュー階層がリフレッシャーコントロールでうまく機能していないことと関係があります-何か提案はありますか?

ありがとう

4

15 に答える 15

201

プログラムで更新を開始する場合は、たとえばcontentoffsetを変更して、テーブルビューを自分でスクロールする必要があるようです。

[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];

これの理由は、ユーザーがテーブルビューの中央/下部にいるときに、更新コントロールにスクロールするのは望ましくない可能性があるためだと思いますか?

@muhasturkによるSwift2.2バージョン

self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)

一言で言えば、このポータブルを維持するには、この拡張機能を追加します

UIRefreshControl + ProgramaticallyBeginRefresh.swift

extension UIRefreshControl {
    func programaticallyBeginRefreshing(in tableView: UITableView) {
        beginRefreshing()
        let offsetPoint = CGPoint.init(x: 0, y: -frame.size.height)
        tableView.setContentOffset(offsetPoint, animated: true)        
    }
}
于 2013-02-06T00:43:02.417 に答える
80

UITableViewControllerには、iOS 7以降のautomaticallyAdjustsScrollViewInsetsプロパティがあります。テーブルビューには、通常(0、-64)のcontentOffsetが既に含まれている場合があります。

したがって、プログラミングで更新を開始した後にrefreshControlを表示する正しい方法は、refreshControlの高さを既存のcontentOffsetに追加することです。

 [self.refreshControl beginRefreshing];
 [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
于 2014-03-18T05:34:21.363 に答える
35

上記の戦略を使用したSwift拡張機能を次に示します。

extension UIRefreshControl {
    func beginRefreshingManually() {
        if let scrollView = superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: true)
        }
        beginRefreshing()
    }
}
于 2016-02-17T21:50:34.703 に答える
15

他の答えはどれも私にはうまくいきませんでした。それらはスピナーを表示してスピンさせますが、リフレッシュアクション自体は決して起こりません。これは機能します:

id target = self;
SEL selector = @selector(example);
// Assuming at some point prior to triggering the refresh, you call the following line:
[self.refreshControl addTarget:target action:selector forControlEvents:UIControlEventValueChanged];

// This line makes the spinner start spinning
[self.refreshControl beginRefreshing];
// This line makes the spinner visible by pushing the table view/collection view down
[self.tableView setContentOffset:CGPointMake(0, -1.0f * self.refreshControl.frame.size.height) animated:YES];
// This line is what actually triggers the refresh action/selector
[self.refreshControl sendActionsForControlEvents:UIControlEventValueChanged];

この例ではテーブルビューを使用していますが、コレクションビューである可能性もあることに注意してください。

于 2014-05-20T18:01:19.893 に答える
13

すでに述べたアプローチ:

[self.refreshControl beginRefreshing];
 [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];

スピナーが見えるようになります。しかし、それはアニメートされません。私が変更した1つのことは、これら2つの方法の順序であり、すべてが機能しました。

[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
[self.refreshControl beginRefreshing];
于 2015-02-13T12:50:10.857 に答える
11

Swift 4/4.1の場合

既存の答えの組み合わせが私のために仕事をします:

refreshControl.beginRefreshing()
tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentOffset.y - (refreshControl.frame.size.height)), animated: true)

お役に立てれば!

于 2018-05-27T10:53:47.953 に答える
8

この質問も参照してください

beginRefreshingを呼び出したときにUIRefreshControlがとげのあるものを表示せず、contentOffsetが0の場合

tableViewのcontentOffsetプロパティが0の場合にのみ発生するため、私にはバグのように見えます。

私は次のコード(UITableViewControllerのメソッド)でそれを修正しました:

- (void)beginRefreshingTableView {

    [self.refreshControl beginRefreshing];

    if (self.tableView.contentOffset.y == 0) {

        [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){

            self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);

        } completion:^(BOOL finished){

        }];

    }
}
于 2013-04-27T10:06:40.867 に答える
7

これがSwift3以降の拡張機能で、スピナーとアニメーションを表示します。

import UIKit
extension UIRefreshControl {

func beginRefreshingWithAnimation() {

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {

        if let scrollView = self.superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - self.frame.height), animated: true)
          }
        self.beginRefreshing()
      }
   }
}
于 2017-10-10T12:46:34.053 に答える
5

Swift 5の場合、私にとって不足しているのは、を呼び出すことだけでしたrefreshControl.sendActions(.valueChanged)。私はそれをよりきれいにするために拡張を行いました。

extension UIRefreshControl {

    func beginRefreshingManually() {
        if let scrollView = superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: false)
        }
        beginRefreshing()
        sendActions(for: .valueChanged)
    }

}
于 2019-04-14T10:46:44.690 に答える
4

それは私にとって完璧に機能します:

スウィフト3:

self.tableView.setContentOffset(CGPoint(x: 0, y: -self.refreshControl!.frame.size.height - self.topLayoutGuide.length), animated: true)
于 2017-02-16T15:30:33.740 に答える
3

@DymitryShevchenkoソリューションに加えて。

この問題に対する適切な回避策を見つけました。UIRefreshControlその上書きメソッドの拡張機能を作成できます。

// Adds code forgotten by Apple, that changes content offset of parent scroll view (table view).
- (void)beginRefreshing
{
    [super beginRefreshing];

    if ([self.superview isKindOfClass:[UIScrollView class]]) {
        UIScrollView *view = (UIScrollView *)self.superview;
        [view setContentOffset:CGPointMake(0, view.contentOffset.y - self.frame.size.height) animated:YES];
    }
}

新しいクラスを使用するには、 IdentityInspectorでカスタムクラスを設定してInterfaceBuilderの更新制御を行います。

于 2014-03-11T12:21:00.640 に答える
3

フォートスウィフト2.2+

    self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
于 2016-05-25T18:28:38.327 に答える
3

Swift 3.1にRxswiftを使用する場合は、以下を使用できます。

func manualRefresh() {
    if let refreshControl = self.tableView.refreshControl {
        self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.height), animated: true)
        self.tableView.refreshControl?.beginRefreshing()
        self.tableView.refreshControl?.sendActions(for: .valueChanged)
    }
}

これは、Swift 3.1、iOS10で機能します。

于 2017-05-05T06:27:27.900 に答える
2

Swift5でテスト済み

これを使用してviewDidLoad()

fileprivate func showRefreshLoader() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl.frame.size.height)), animated: true)
        self.refreshControl.beginRefreshing() 
    }
}
于 2020-03-26T16:53:57.947 に答える
0

ユーザーに「データは更新です」という視覚的なサインを表示するために同じ手法を使用します。結果として、ユーザーがアプリをバックグラウンドから持ち込み、フィード/リストは、ユーザーがテーブルをプルして自分自身を更新するようにUIで更新されます。私のバージョンには3つのものが含まれています

1)「ウェイクアップ」を送信する人

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationHaveToResetAllPages object:nil];
}

2)UIViewControllerのオブザーバー

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(forceUpdateData) name:kNotificationHaveToWakeUp:nil];
}

3)プロトコル

#pragma mark - ForcedDataUpdateProtocol

- (void)forceUpdateData {
    self.tableView.contentOffset = CGPointZero;

    if (self.refreshControl) {
        [self.refreshControl beginRefreshing];
        [self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
        [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:1];
    }
}

結果

于 2016-12-23T21:57:18.350 に答える