web-dev-qa-db-ja.com

UIRefreshControl-タッチがリリースされた後に更新アクションを発生させるにはどうすればよいですか?

長時間のリスナー、ここでの最初の呼び出し元はスタックオーバーフローです。穏やかな。

テーブルのデータを更新するために、UITableViewにUIRefreshControlを実装しています。他のプルツーリフレッシュの実装では、プルのリフレッシュ距離内にあるユーザーの指を離すまで、リフレッシュプロセスは開始されません。 UIRefreshControlは、このカスタマイズがあるようにすぐには見えません。

私のUIRefreshControl初期化コード:

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

私のリフレッシュ:コードはかなり基本的です:

-(void)refresh:(id)sender {
(... refresh code ...)
[sender endRefreshing];
}

ユーザーがプルから指を離すまで、更新機能をどのように遅延させることができますか?

29
outphase

私も同じ問題で立ち往生しています。私のアプローチはとてもいいとは思いませんが、うまくいくようです。

  1. 初期化UIRefreshControl

    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    self.refreshControl = refreshControl;
    
  2. ユーザーがテーブルのドラッグを終了したときにUIRefreshControlの状態を確認します(UITableViewDelegateUIScrollViewDelegateに準拠しています)

    - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView
    {    
        if( self.refreshControl.isRefreshing )
            [self refresh];
    }
    
  3. テーブルを更新

    - (void)refresh
    {
        [self.refreshControl endRefreshing];
    
        // TODO: Update here your items
    
        [self.tableView reloadData];
    }
    

それがあなたを助けることを願っています。

37
Ned

UIRefreshControlには、「適切な」タイミングで開始するための宿泊施設がすでにあります。プルトゥリフレッシュコントロールの正しい動作は、ユーザーがドラッグを解放したときではなく、ユーザーが「十分に十分な」しきい値を超えた後にリフレッシュを開始することです。

これを実行するには、-refresh:メソッドを変更して、コントロールがrefreshing状態に移行したことを確認する必要があります。

-(void)refresh:(id)sender {
    UIRefreshControl *refreshControl = (UIRefreshControl *)sender;
    if(refreshControl.refreshing) {
        (... refresh code ...)
    }
}

UIがフリーズしないように、(... refresh code ...)に対して呼び出すメソッドはすべて非同期でなければならないことに注意してください。メインキューに移動し、-endRefreshingの最後ではなく、(... refresh code ...)ブロックの最後で-refresh:を呼び出す必要があります。

- (void)refresh:(id)sender {
    __weak UIRefreshControl *refreshControl = (UIRefreshControl *)sender;
    if(refreshControl.refreshing) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            /* (... refresh code ...) */
            dispatch_sync(dispatch_get_main_queue(), ^{
                [refreshControl endRefreshing];
                //reload the table here, too
            });
        });
    }
}

コントロールイベントをUIControlEventTouchUpInsideに変更しても機能しません。UIRefreshControlは、直接操作することを目的としたUIコンポーネントではないためです。ユーザーがtouchUIRefreshControlを実行することはないため、UIControlEventTouchUpInsideイベントはトリガーされません。

21
user1059264

NSRunLoopを使用すると、指が離されたときにのみ更新が行われるようにスケジュールを設定できます。配列内のNSRunLoopDefaultModeを使用して-(void)performInModes:(NSArray<NSRunLoopMode> *)modes block:(void (^)(void))block;を呼び出します。

タッチがまだ保持されている間、runloopモードはUITrackingRunLoopModeであり、リフトオフ後にのみデフォルトに戻ります。

3
DrMickeyLauer