web-dev-qa-db-ja.com

UITabBarControllerでタブを切り替えた後にUIRefreshControlがスタックする

UINavigationControllerのルートビューコントローラーとしてUITableViewControllerがあります。これは、UITabBarControllerのビューコントローラーの1つです。すべてストーリーボードに接続されています。

ストーリーボードでもテーブルのUIRefreshControlを構成しましたが、通常、プルすると次のようになります。

Normal UIRefreshControl

ただし、他のタブを1〜2回切り替えると、次のようになります。

Buggy UIRefreshControl

回転していないか、「いっぱい」になっているだけで、完全に引っ張ってリフレッシュをトリガーするまでそのままです。

どんなアイデアや提案もありがたいです。

28
diakonos

私はこれが信じられないほど遅いことを知っています、しかし私は決して遅くないよりよく理解します。

残念ながら、与えられた答えはどれも私にはうまくいきませんでした。動作したのは、viewWillAppearのこのひどいコードだけでした。

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

基本的に、ビューが表示されるたびにUIRefreshControlを再作成します。次の警告を出している間は機能します。

アイドル状態でないときにリフレッシュコントロールを変更しようとすることは強くお勧めできません。おそらく正しく機能しません。

私は正直なところ、これがまだ問題であることに驚いています(iOS 9でもこれが見られます)。うまくいけば、これは他の人に役立つかもしれません。

11
diakonos

user2009606はほぼ正しかったので、電話して修正しました

[refreshControl endRefreshing];

オン

viewWillAppear:

RefreshControlは、タブを切り替えた後、その状態に関係なく正しく動作するようになりました。

12
user3006173

要約して、完全なソリューションを提供します。

問題:

画面遷移中にUIRefreshControlがアニメーション化されている場合、UIRefreshControlは表示されたままになりますが、アニメーション化されません。ビデオ https://vid.me/Bkb7

また、プルトゥリフレッシュアニメーションが開始されたが完了しておらず、その後トランジションが実行された場合、UIRefreshControlは非表示になりますがスタックします。ビデオ https://vid.me/Bkb7

解決:

ViewWillAppearでUIRefreshControlアニメーションを開始し、viewDidDisappearで終了します。更新プロセスの状態を保存して、UIRefreshControlをいつ表示するかを確認します。

ベローは、適切なアニメーションとアニメーションを更新するための単純なプルも処理するソリューション全体です。

UITableViewまたはサブクラスに追加

初期化:

 /// Refresh indicator
var refreshControl = UIRefreshControl()

/// Refresh state
var isRefreshing = false

/// Refresh controll update funcion. Set to enable pull to refresh
var refreshControllUpdateFunction: (() -> ())?

/// Prepeares UIRefreshControll. Call from init
func initRefreshControl(){
    addSubview(refreshControl)

    refreshControl.addTarget(self, action: "refreshControllTarget", forControlEvents: .ValueChanged)
    refreshControl.beginRefreshing()

    isRefreshing = true
}

スーパービューイベントハンドラー:

/// Call on viewWillApper
func superviewWillApper(){
    if isRefreshing && !refreshControl.refreshing{
        startRefreshAnimation()
    }
}

/// Call on viewDidDisapper
func superviewDidDisappear(){
    endRefreshAnimation(false, dataFetched: !isRefreshing)
}

UIRefreshControlアニメーションハンドラー:

/// Presents animating UIRefreshControll
func startRefreshAnimation(){
    refreshControl.beginRefreshing()
    contentOffset = CGPointMake(0, -refreshControl.bounds.size.height)

    isRefreshing = true
}

/// Hides UIRefreshControll and saves state of refresh
func endRefreshAnimation(wasEmpty: Bool, dataFetched: Bool){
    refreshControl.endRefreshing()

    isRefreshing = !dataFetched

    if !wasEmpty{
        setContentOffset(CGPointZero, animated: true)
    }else{
        setContentOffset(CGPointZero, animated: false)
    }
}

追加

table.isRefreshing = true

リフレッシュ呼び出しの開始まで。

結果ビデオ https://vid.me/LyuI

5
Ivan Rep

次の解決策が役立つ場合があります。

CGFloat yTableViewOffset;

- (void)viewDidLoad {

      yTableViewOffset = kNilOptions;
}
- (void)viewWillAppear:(BOOL)animated
{
   if(yTableViewOffset != kNilOptions) {

     CGPoint offset = CGPointMake(tableView.contentOffset.x, yTableViewOffset);
     [refreshControl beginRefreshing];
     tableView.contentOffset = offset;

  }
}
- (void)viewWillDisappear:(BOOL)animated
{
   if(refreshControl.isRefreshing) {
     yTableViewOffset = tableView.contentOffset.y;
     [refreshControl endRefreshing];
  }
}
4
Prasanna

viewWillDisappear:endRefreshingを呼び出すだけで、すべての問題が修正されました。

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.refreshControl endRefreshing];        
}

viewWillAppear:で同じことを行うと、テーブルを引っ張るときに更新コントロールが奇妙に回転しました。

4
maxkonovalov

私はちょうど同じことを見ました。私がやったことは、viewWillDisappearのendRefreshingであり、少なくともこの問題は解消されます。ただし、タブに戻ると、更新プロセスを再開してbeginRefreshingを再度呼び出すと、タブが再び回転し始めると思いますが、そうではありません。ナビゲーションをドリルダウンしてから戻ってきた場合も同様です。

2
kos

リフレッシュコントロールが回転しているときに、他のコントローラーを提示して「リフレッシュの終了」の前に戻った場合。更新アニメーションがスタックします。

上記の答えはどれも私にはうまくいきませんでした、そして私はブール値を設定して、ViewControllerのすべてのライフサイクルを通してそれに従うことを望んでいませんでした。

私の解決策は、viewWillAppearの最後に以下のコードを追加することです。

objcで;

if (self.refreshControl.isRefreshing) {
    [self.refreshControl endRefreshing];
    [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated: true];
    [self.refreshControl beginRefreshing];
}

swiftで;

if self.refreshControl.isRefreshing {
     self.refreshControl.endRefreshing
     self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y-self.refreshControl.frame.size.height), animated: true)
     self.refreshControl.beginRefreshing;
}

ロジックは;リフレッシュコントロールがアニメーションの状態にあることをキャッチすると、スタックしているかどうかを知らずに停止し、アニメーションを再実行します。

それが役に立てば幸い。

1
ysnzlcn

Swiftで最も優れた修正:

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  //fixes bug with refreshControl freezing while switching tabs
  if tableView.contentOffset.y < 0 {
    tableView.contentOffset = .zero
  }
}
1

私がこの問題を最終的に解決するのを手伝うことができることを願っています:

Pull-To-RefreshコントロールでUITableViewを使用すると問題が発生します。これは、UITableViewControllerを追加することで簡単に解決できます。

UITableViewController *tableController = [[UITableViewController alloc] init];
    tableController.automaticallyAdjustsScrollViewInsets = NO;
    [tableController willMoveToParentViewController:self];
    [self addChildViewController:tableController];
    tableController.tableView = self.containerTableView;
    tableController.refreshControl = self.refreshControl;

このように、UITableViewをコントローラー内にラップするだけで、[self.refreshControl endRefreshing]viewWillAppearまたはviewWillDisappear内で完全に正常に機能します。場合によっては、両方で呼び出す必要があります。

お役に立てれば! :)

0
MBerndt

ナビゲーションが発生する前にendRefreshingの呼び出しを機能させることができなかったので、もう一方の端から問題にアプローチし、viewWillAppearでtableView contentOffsetが負の数であるかどうかを確認し、tableViewを0に戻します。

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

    if (self.tableView.contentOffset.y < 0)
    {
        [self.tableView setContentOffset:CGPointZero animated:YES];
    }
}
0
Alberto Lopez

この答え 質問 私の問題を解決しました

基本的に、viewWillAppearでスピナーを停止して再開します

0
Alex Brashear

あなたが試すことができます

refreshControl.beginRefreshing()
refreshControl.endRefreshing()

viewWillAppearで、これは機能するはずです。

0
Jay He

詳細

  • Xcodeバージョン10.3(10G8)、Swift 5

問題

  • タブを切り替えると、アクティビティインジケーターがフリーズします
  • refreshControl.beginRefreshing(); refreshControl.endRefreshing()-イベントを更新するためにもう1つのリクエスト/プルを送信します

解決

refreshControl.removeTarget(actionTarget, action: selector, for: .valueChanged)
refreshControl.endRefreshing()
refreshControl.beginRefreshing()
refreshControl.addTarget(actionTarget, action: actionSelector, for: .valueChanged)

完全なソリューションとサンプル

Swiftでプルを使用して更新する方法は?

0

私はいくつかのポイントが必要で、アルバートの解決策は好きですが、彼のスタイルは好きではありません。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y + 1.0f);
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    _table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y - 1.0f);
}
0
Renetik

次のコードをviewWillDisappearに配置することで、この問題を解決できました。

    DispatchQueue.main.async {
        self.refreshControl.beginRefreshing()
        self.refreshControl.endRefreshing()
    }

上記のコードをviewWillAppearに配置すると、スピナーは数秒以内にアニメーション化して閉じます。どちらの場合も問題は解決しますが、ユーザーの観点からはスピナーが表示されないようにする必要があるため、配置することをお勧めします。 viewWillDisappearでそれ。

0
Raj Kiran

以下のコードを追加するだけで、すべての条件で完全に機能します。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    guard refreshControl.isRefreshing else { return }
    refreshControl.endRefreshing()
    refreshControl.beginRefreshing()
    tableView?.contentOffset = CGPoint(x: 0, y: -(refreshControl.bounds.height))
}
0
Manish

私はcollectionViewを持っていて、それをcontentInsetに設定しました。

一部のViewControllerを押してからホームボタンを押し、戻ってポップバックすると、UIRefreshControlが常に一番上に表示されます。

最後に、このコードを使用して一時的に回避します。 (醜いですが、停止すると常に一番上に表示されます)

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

    [self.refreshControl endRefreshing];

    CGPoint currentContentOffset = self.collectionView.contentOffset;

    [self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
                                                      currentContentOffset.y - 1.0f)
                                 animated:YES];
}

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

    CGPoint currentContentOffset = self.collectionView.contentOffset;

    [self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
                                                      currentContentOffset.y + 1.0f)
                                 animated:YES];
}
0
Albert Chu