UITableViewがデータの要求を完了したときに通知を受け取りますか?


108

UITableViewデータソースからのデータの要求をいつ終了したかを確認する方法はありますか?

関連するビューコントローラー()のviewDidLoad/ viewWillAppear/ viewDidAppearメソッドはどれも、UITableViewController早すぎるため、ここでは使用されません。それらのどれも(完全に理解できる)、データソースへのクエリが当面の間(たとえば、ビューがスクロールされるまで)完了することを保証しません。

私が見つけた1つの回避策は、を呼び出すことreloadDataですviewDidAppear。これは、reloadData戻ったときに、テーブルビューデータソースのクエリを当面必要なだけ完了することを保証しているためです。

ただし、データソースreloadDataが最初に読み込まれたときに、データソースに同じ情報を2回(自動的に1回、呼び出しのために1回)要求されるため、これはかなり厄介なようです。

これを実行したい理由はUITableView、最も近い行だけでなく、ピクセルレベルまでのスクロール位置を保持したいからです。

(を使用してscrollRectToVisible:animated:)スクロール位置を復元するとき、テーブルビューに十分なデータが既に含まれている必要があります。そうでない場合、scrollRectToVisible:animated:メソッド呼び出しは何もしません(viewDidLoadviewWillAppearまたはのいずれかで呼び出しを独自に配置した場合に起こりますviewDidAppear)。


このstackoverflow.com/a/11672379/2082172のようなものを探しているようです。
Timur Kuchkarov 2013

私の経験では、UITableViewは、行の挿入や削除などの呼び出しをキャッシュするのと同じように、reloadDataの呼び出しをキャッシュできます。UITableViewは、CPUの使用状況などに応じて、準備ができるとデータソースデリゲートを呼び出します。
Walt Sellers、

回答:


61

回答が書かれてからUITableView実装にいくつかの変更が加えられたため、この回答はもう機能していないようです。このコメントを参照してください:UITableViewがデータの要求を完了したときに通知を受け取りますか?

私は数日間、この問題で遊んとサブクラス化することを考えてきたUITableViewのがreloadData最良の方法です。

- (void)reloadData {

    NSLog(@"BEGIN reloadData");

    [super reloadData];

    NSLog(@"END reloadData");

}

reloadDataテーブルがデータを再ロードする前に終了しません。したがって、2番目NSLogが発生すると、テーブルビューは実際にデータの要求を終了します。

UITableViewbeforeとafterのメソッドをデリゲートに送信するようにサブクラス化しましたreloadData。それは魅力のように働きます。


2
お奨めは、これが最善の解決策のようです。ちょうどそれを実装し、あなたが言うように、それは魅力のように機能します。ありがとう!
理論

2
@EricMORAND「テーブルがデータを再ロードし終える前にreloadDataは終了しない」とあなたは言う。それが何を意味するのか明確にできますか?私はそれを見つけるreloadDataすぐに復帰して、私は「END reloadData」を参照してくださいする前に細胞が実際に(つまり、前に再ロードされているUITableViewDataSourceメソッドが呼び出されます)。私の実験は、あなたの言うことと正反対のことを示しています。私はあなたが言っていることを誤解しなければなりません。
Rob

3
reloaddataを呼び出し、(オーバーライド読んでいない)reloaddataを実装していないようではないエリックの答えと同じです(基本的にされる[スーパーreloaddata]、およびそれを呼び出した後、あなたはその終了時にしたいものですか?
Nirav Bhattさん

5
むかしむかし、reloadDataは終了する前にロードプロセスを完了しました。しかし、Appleはある時点でそれを変更しました。これで、UITableViewクラスは、すべての行の挿入と削除の呼び出しでreloadData呼び出しをキャッシュできます。UITableViewの@interface宣言を見ると、NSMutableArrayメンバー_reloadItemsが_insertItemsおよび_deleteItemsのすぐ下にあります。(この変更のため、継承したコードを作り直す必要がありました。)
Walt Sellers

3
呼び出し後にメインキューのブロックに完了コードを投稿すると[super reloadData]、私にとってはうまくいきますdispatch_async(dispatch_get_main_queue(), ^{NSLog(@"reload complete");});。基本的には、のテーブルビューによって投稿されるブロックを跳躍させますreloadData
ティモシームース

53

私のアプリには同じシナリオがあり、ここに記載されている他の回答はiOS7以降では機能しないため、私の回答を皆さんに投稿すると思いました

最後に、これは私のためにうまくいった唯一のものです。

[yourTableview reloadData];

dispatch_async(dispatch_get_main_queue(),^{
        NSIndexPath *path = [NSIndexPath indexPathForRow:yourRow inSection:yourSection];
        //Basically maintain your logic to get the indexpath
        [yourTableview scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
 });

Swiftアップデート:

yourTableview.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    let path : NSIndexPath = NSIndexPath(forRow: myRowValue, inSection: mySectionValue)
    //Basically maintain your logic to get the indexpath
    yourTableview.scrollToRowAtIndexPath(path, atScrollPosition: UITableViewScrollPosition.Top, animated: true)

})

これがどのように機能するか。

基本的に、リロードを実行するとメインスレッドがビジーになるため、ディスパッチ非同期スレッドを実行すると、ブロックはメインスレッドが完了するまで待機します。テーブルビューが完全に読み込まれると、メインスレッドが終了し、メソッドブロックをディスパッチします

iOS7とiOS8でテストされ、素晴らしい動作をします;)

iOS9のアップデート:これはiOS9でも正常に機能します。POCとしてサンプルプロジェクトをgithubに作成しました。 https://github.com/ipraba/TableReloadingNotifier

テストのスクリーンショットをここに添付しています。

テスト済み環境:Xcode7のiOS9 iPhone6シミュレーター

ここに画像の説明を入力してください


8
私が見つけた最高のanswear!
Nikolay Shubenkov 2014年

@ゴン私はiOS9でテストを行いましたが、それはうまくいきます。github.com/ipraba/TableReloadingNotifier
iPrabu

私のエミュレータでは問題なく動作しますが、実際のデバイスでは動作しないようです。この問題を抱えている他の人はいますか?
sosale151

1
このソリューションは最終的に私のために働きます!iOS 9で正常に機能します
強力な

1
実際のデバイス、iPhone 6sでテストしました。それもうまくいきます。
強い

25

編集:この答えは実際には解決策ではありません。リロードは非常に速く発生する可能性があるため、おそらく最初は機能しているように見えますが、実際には、データのリロードが完全に完了した後に完了ブロックが呼び出されるとは限りません。reloadDataはブロックしないためです。あなたはおそらくより良い解決策を探すべきです。

@Eric MORANDの答えを拡張するために、完了ブロックを入れましょう。ブロックが好きではないのは誰ですか?

@interface DUTableView : UITableView

   - (void) reloadDataWithCompletion:( void (^) (void) )completionBlock;

@end

そして...

#import "DUTableView.h"

@implementation DUTableView

- (void) reloadDataWithCompletion:( void (^) (void) )completionBlock {
    [super reloadData];
    if(completionBlock) {
        completionBlock();
    }
}

@end

使用法:

[self.tableView reloadDataWithCompletion:^{
                                            //do your stuff here
                                        }];

2
ブロックが足りません。あなたが素敵なブロックを持っているときに誰がデリゲートを必要とするのですか!
bandejapaisa

私はこれが好きですが、システムがreloadData()を呼び出すとき、たとえばテーブルが最初に表示されるときはどうですか?
対称的な

12
これはソリューションではありません。完了ブロックがcellForRowAtIndexPathの前に実行を開始します
zvjerka24

1
これは機能しません。reloadDataはブロッキングメソッドではありません。このコードは、セルがまだリロードされていない場合でも、reloadDataを呼び出した直後に呼び出されます。さらに、このコードを見ると、reloadDataの後にコードを配置するだけで済むことがわかります。
コリンタ2013

1
これはマイナーな変更で私のために働きます。完了ブロックを直接呼び出すのではなく、メインキューに投稿されたブロックで呼び出しますdispatch_async(dispatch_get_main_queue(), ^{completionBlock();});。これは基本的に、のテーブルビューによって投稿されたブロックを跳躍させますreloadData
ティモシームース

11

reloadDataは、表示されているセルのデータを要求するだけです。テーブルの指定部分がロードされたときに通知を受けるには、tableView: willDisplayCell:メソッドをフックしてください。

- (void) reloadDisplayData
{
    isLoading =  YES;
    NSLog(@"Reload display with last index %d", lastIndex);
    [_tableView reloadData];
    if(lastIndex <= 0){
    isLoading = YES;
    //Notify completed
}

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row >= lastIndex){
    isLoading = NO;
    //Notify completed
}

1
この作品かどうかはわかりません。最後のインデックスはテーブルデータの最後(例:100レコード)ですが、テーブルには画面に表示されているもの(例:8レコード)のみが表示されます。
Travis M.

10

それが私の解決策です。100%が機能し、多くのプロジェクトで使用されます。シンプルなUITableViewサブクラスです。

@protocol MyTableViewDelegate<NSObject, UITableViewDelegate>
@optional
- (void)tableViewWillReloadData:(UITableView *)tableView;
- (void)tableViewDidReloadData:(UITableView *)tableView;
@end

@interface MyTableView : UITableView {
    struct {
        unsigned int delegateWillReloadData:1;
        unsigned int delegateDidReloadData:1;
        unsigned int reloading:1;
    } _flags;
}
@end

@implementation MyTableView
- (id<MyTableViewDelegate>)delegate {
    return (id<MyTableViewDelegate>)[super delegate];
}

- (void)setDelegate:(id<MyTableViewDelegate>)delegate {
    [super setDelegate:delegate];
    _flags.delegateWillReloadData = [delegate respondsToSelector:@selector(tableViewWillReloadData:)];
    _flags.delegateDidReloadData = [delegate    respondsToSelector:@selector(tableViewDidReloadData:)];
}

- (void)reloadData {
    [super reloadData];
    if (_flags.reloading == NO) {
        _flags.reloading = YES;
        if (_flags.delegateWillReloadData) {
            [(id<MyTableViewDelegate>)self.delegate tableViewWillReloadData:self];
        }
        [self performSelector:@selector(finishReload) withObject:nil afterDelay:0.0f];
    }
}

- (void)finishReload {
    _flags.reloading = NO;
    if (_flags.delegateDidReloadData) {
        [(id<MyTableViewDelegate>)self.delegate tableViewDidReloadData:self];
    }
}

@end

これは、1つの例外を除いてJosh Brownのソリューションに似ています。performSelectorメソッドで遅延は必要ありません。どれだけ時間reloadDataがかかっても。質問tableViewDidLoadData:tableView終了すると常に起動しdataSource cellForRowAtIndexPathます。

サブクラス化したくない場合でも、UITableView単に呼び出すことができ[performSelector:@selector(finishReload) withObject:nil afterDelay:0.0f]、テーブルの再読み込みが完了した直後にセレクターが呼び出されます。ただし、selectorが次の呼び出しごとに1回だけ呼び出されるようにする必要がありますreloadData

[self.tableView reloadData];
[self performSelector:@selector(finishReload) withObject:nil afterDelay:0.0f];

楽しい。:)


1
performSelector呼び出しの使用は見事です。シンプルで機能的、ありがとう
Julia

これは絶対に素晴らしいです。私は何日もこれに取り組んできました。ありがとうございました!
David Carrico

@MarkKryzhanouski、iOS 9でテストしましたか?
ビクター

@MarkKryzhanouski、迅速なフィードバックに感謝します!iOS 7および8で問題なく動作します
Victor

ソリューションperformSelectorまたはメインスレッドでのdispatch_asynch実行は、iOS 9では機能しません。
マヌエル、

8

これは、少し異なる質問への回答です。UITableView通話もいつ終了したかを知る必要がありましたcellForRowAtIndexPath()。私はサブクラス化しlayoutSubviews()(@Eric MORANDに感謝)、デリゲートコールバックを追加しました。

SDTableView.h:

@protocol SDTableViewDelegate <NSObject, UITableViewDelegate>
@required
- (void)willReloadData;
- (void)didReloadData;
- (void)willLayoutSubviews;
- (void)didLayoutSubviews;
@end

@interface SDTableView : UITableView

@property(nonatomic,assign) id <SDTableViewDelegate> delegate;

@end;

SDTableView.m:

#import "SDTableView.h"

@implementation SDTableView

@dynamic delegate;

- (void) reloadData {
    [self.delegate willReloadData];

    [super reloadData];

    [self.delegate didReloadData];
}

- (void) layoutSubviews {
    [self.delegate willLayoutSubviews];

    [super layoutSubviews];

    [self.delegate didLayoutSubviews];
}

@end

使用法:

MyTableViewController.h:

#import "SDTableView.h"
@interface MyTableViewController : UITableViewController <SDTableViewDelegate>
@property (nonatomic) BOOL reloadInProgress;

MyTableViewController.m:

#import "MyTableViewController.h"
@implementation MyTableViewController
@synthesize reloadInProgress;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    if ( ! reloadInProgress) {
        NSLog(@"---- numberOfSectionsInTableView(): reloadInProgress=TRUE");
        reloadInProgress = TRUE;
    }

    return 1;
}

- (void)willReloadData {}
- (void)didReloadData {}
- (void)willLayoutSubviews {}

- (void)didLayoutSubviews {
    if (reloadInProgress) {
        NSLog(@"---- layoutSubviewsEnd(): reloadInProgress=FALSE");
        reloadInProgress = FALSE;
    }
}

注: これはサブクラスでUITableViewあるため、すでにデリゲートプロパティをポイントしてMyTableViewControllerいるため、別のプロパティを追加する必要はありません。「@動的デリゲート」は、このプロパティを使用するようコンパイラーに指示します。(これを説明するリンクは次のとおりです:http : //farhadnoorzay.com/2012/01/20/objective-c-how-to-add-delegate-methods-in-a-subclass/

新しいクラスを使用するには、のUITableViewプロパティをMyTableViewController変更する必要がありますSDTableView。これは、Interface Builder Identity Inspectorで行われます。のUITableView内側を選択し、UITableViewControllerその「カスタムクラス」をに設定しSDTableViewます。


MyTableViewControllerをSDTableViewのデリゲートとしてどこに設定しますか?スーパークラスにその名前のプロパティ(UITableView.delegate)が既にある場合に、SDTableViewに "delegate"という名前のプロパティを設定できるのはなぜですか?プロパティが「UITablewView」タイプで、オブジェクト(SDTableViewのインスタンス)が「SDTableView」タイプの場合、カスタムSDTableViewをMyTableViewController.tableViewプロパティにどのように到達しますか?私は同じ問題と闘っています。したがって、これらの問題の解決策があることを
Earl Gray

対称(SDTableView)のコードでは、didLayoutSubviewsではなく、didReloadDataでreloadInProgressをFALSEに設定しないでください。reloadDataは、layoutSubviewsの後に呼び出され、reloadDataが完了する前にロードが完了したと見なすべきではないためです。
tzuchien.chiu 2012

これはiOS 8では機能しません。iPrabuの回答を組み込む必要がありました
Stunner、2015年

6

私は中に変更の通知を得るために似たような発見したcontentSizeのをTableView。contentSizeもデータの読み込みに応じて変化するため、ここでも機能するはずです。

これを試して:

viewDidLoad書き込み、

[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionPrior context:NULL];

このメソッドをviewControllerに追加します:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"contentSize"]) {
        DLog(@"change = %@", change.description)

        NSValue *new = [change valueForKey:@"new"];
        NSValue *old = [change valueForKey:@"old"];

        if (new && old) {
            if (![old isEqualToValue:new]) {
                // do your stuff
            }
        }


    }
}

変更のチェックで、若干の修正が必要になる場合があります。これは私にとってもうまくいきました。

乾杯!:)


1
非常に賢い。私にとっては完璧に機能します。共有してくれてありがとう!
DZenBot

2
エレガント!私が追加する唯一のものは、自分とオブザーバーを削除する必要があるということです(おそらく-deallocメソッドで)。または、自分をオブザーバーとしてに追加し、自分をメソッド-viewWillAppearから削除します-viewWillDisapear
Loozie

2

これはハックですが、考えられる解決策は次のとおりです。

[self.tableView reloadData];
[self performSelector:@selector(scrollTableView) withObject:nil afterDelay:0.3];

-scrollTableViewメソッドがでテーブルビューをスクロールする場所-scrollRectToVisible:animated:。そしてもちろん、上記のコードの遅延を0.3から適切に機能するように設定できます。ええ、それは途方もなくハックですが、私のiPhone 5と4Sで私のために機能します...


2
「ハック」に見えるかもしれませんが、これは実際にはスクロールの標準的なアプローチです。次の実行サイクルまで延期します。遅延を0に変更します。これは同様に機能し、レイテンシが少ないためです。
ファットマン2013

遅延を0に設定しても機能しませんでした。0.3は私が行くことができ、それでもデータを取得できる最低値でした。
Josh Brown、

@phatmannこれは私のために働いた。遅延には0を使用することもできました。お二人に感謝します。
mcphersonjr 2014年

1

私は私と同じようなものを信じていました。インスタンス変数としてBOOLを追加しました。これにより、オフセットが復元されたかどうかがわかり、それをで確認し-viewWillAppear:ます。復元されていない場合は、その方法で復元し、オフセットを回復したことを示すようにBOOLを設定します。

それは一種のハックであり、おそらくもっと良くできるでしょうが、これは今のところ私にとってはうまくいきます。


ええ、問題はviewWillAppearが早すぎるように見えることです(少なくとも私のシナリオでは)。最初にreloadDataを呼び出すハックを追加しない限り、viewWillAppearでオフセットを復元しようとしても何も起こりません。私が理解しているように、viewWillAppear / viewDidAppearは、実際に表示されているテーブルビュー自体のみを参照します。ビューのテーブルセルが列挙または設定されているかどうかについては何も主張しません...回復する前にこれを行う必要があります。オフセット。それ以外の場合は、空のビューのオフセットを回復します(そして、それが機能しない理由を理解しています!)。
kennethmac2000 2009

しかし、おそらく、viewWillAppear内でreloadDataを呼び出して、最初にテーブルセルの読み込みも強制しているということですか?
kennethmac2000 2009

いいえ、リロードを強制していません。問題が発生したとき、オフセットを復元しようとしましたが-viewDidLoad(もちろんそれが発生するはずです)、アニメーション化されたオフセットを設定した場合にのみ機能しました。オフセットの設定をそれに移動する-viewWillAppear:ことで機能しましたが、フラグを維持して一度だけ設定する必要がありました。テーブルビューは、一度ビューに追加されるとそのデータをリロードすると思います-loadView。ビューの読み込み時にデータを利用できますか?それとも別のスレッドか何かに読み込まれていますか?
Joost、

OK、多分ここで私の理解を助けることができます。これは、UITableViewが作成されたときの一連の呼び出しを理解する方法です。1)viewDidLoadが最初に発生します。これは、UITableViewがメモリに読み込まれていることを示します。2)viewWillAppearが起動します。これは、UITableViewが表示されることを示していますが、必ずしもすべての表示可能なUITableViewCellオブジェクトが完全にインスタンス化/終了されたレンダリングであるとは限りません。
kennethmac2000 2009

2
そして、上記のすべてが真である、問題はその後です:非ハックのオプションは、我々はのUITableViewはにそのデータソースから十分な情報を得たときに見つけるために持っていないものを保証アニメーション:コールスクロール要求(すなわち、でscrollRectToVisibleこと)は実際に機能しますか(そして何もしないだけではありませんか)?
kennethmac2000 2009

1

セルの内容を更新したいようですが、セルの挿入と削除に伴う突然のジャンプはありません。

そのための記事がいくつかあります。 これは一つです。

スクロールビューのピクセルパーフェクトな設定には、scrollRectToVisible:animated:ではなく、setContentOffset:animated:を使用することをお勧めします。


1

次のロジックを試すことができます。

-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

    if ( [self chkIfLastCellIndexToCreate:tableView :indexPath]){
        NSLog(@"Created Last Cell. IndexPath = %@", indexPath);
        //[self.activityIndicator hide];
        //Do the task for TableView Loading Finished
    }
    prevIndexPath = indexPath;

    return cell;
}



-(BOOL) chkIfLastCellIndexToCreate:(UITableView*)tableView : (NSIndexPath *)indexPath{

    BOOL bRetVal = NO;
    NSArray *visibleIndices = [tableView indexPathsForVisibleRows];

    if (!visibleIndices || ![visibleIndices count])
        bRetVal = YES;

    NSIndexPath *firstVisibleIP = [visibleIndices objectAtIndex:0];
    NSIndexPath *lastVisibleIP = [visibleIndices objectAtIndex:[visibleIndices count]-1];

    if ((indexPath.row > prevIndexPath.row) && (indexPath.section >= prevIndexPath.section)){
        //Ascending - scrolling up
        if ([indexPath isEqual:lastVisibleIP]) {
            bRetVal = YES;
            //NSLog(@"Last Loading Cell :: %@", indexPath);
        }
    } else if ((indexPath.row < prevIndexPath.row) && (indexPath.section <= prevIndexPath.section)) {
        //Descending - scrolling down
        if ([indexPath isEqual:firstVisibleIP]) {
            bRetVal = YES;
            //NSLog(@"Last Loading Cell :: %@", indexPath);
        }
    }
    return bRetVal;
}

そして、reloadDataを呼び出す前に、prevIndexPathをnilに設定します。お気に入り:

prevIndexPath = nil;
[mainTableView reloadData];

私はNSLogsでテストしましたが、このロジックは問題ないようです。必要に応じてカスタマイズ/改善してください。


0

最後に、これで私のコードを機能させました-

[tableView scrollToRowAtIndexPath:scrollToIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];

世話をする必要があるいくつかのものがありました-

  1. - (UITableViewCell *)MyTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath」内で呼び出す
  2. "scrollToRowAtIndexPath"メッセージがUITableViewの関連するインスタンス(この場合は間違いなくMyTableview)に送信されることを確認してください。
  3. 私の場合、UIViewはUITableViewのインスタンスを含むビューです
  4. また、これはすべてのセルロードに対して呼び出されます。したがって、「cellForRowAtIndexPath」内にロジックを配置して、「scrollToRowAtIndexPath」を複数回呼び出さないようにします。

この部分が2回以上呼び出されないようにしてください。そうでない場合は、スクロールをロックします。
smile.al.d.way

これはうまくいくかもしれませんが、エレガントではなく、私が探しているソリューションでもありません。残念ながら、-reloadDataが実際にデータの取得を終了したかどうかを判断するためのより良い方法はないようです...
Josh Brown

0

すべてのデータが読み込まれたときに、このメソッドでテーブルビューのサイズを変更したり、コンテンツサイズを設定したりできます。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    tableView.frame =CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width, tableView.contentSize.height);
}

0

私は繰り返しスケジュールされたタイマーを実行し、tableHeaderViewの高さ(テーブルに行コンテンツがあることを意味する)のときにテーブルのcontentSizeが大きい場合にのみそれを無効にします。C#(モノタッチ)のコードですが、アイデアが明確であることを願っています。

    public override void ReloadTableData()
    {
        base.ReloadTableData();

        // don't do anything if there is no data
        if (ItemsSource != null && ItemsSource.Length > 0)
        {
            _timer = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.MinValue, 
                new NSAction(() => 
                {
                    // make sure that table has header view and content size is big enought
                    if (TableView.TableHeaderView != null &&
                        TableView.ContentSize.Height > 
                            TableView.TableHeaderView.Frame.Height)
                    {
                        TableView.SetContentOffset(
                            new PointF(0, TableView.TableHeaderView.Frame.Height), false);
                        _timer.Invalidate();
                        _timer = null;
                    }
                }));
        }
    }

0

UITableView layoutSubviewsテーブルビューにコンテンツが表示される直前に呼び出されていませんか?テーブルビューがデータの読み込みを完了すると呼び出されることに気づきました。おそらくその方向で調査する必要があります。


0

iOS 6以降、UITableviewデリゲートメソッドは次を呼び出します:

-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section

テーブルが正常に再読み込みされると実行されます。この方法では、必要に応じてカスタマイズを行うことができます。


0

Swiftで見つけた最高のソリューション

extension UITableView {
    func reloadData(completion: ()->()) {
        self.reloadData()
        dispatch_async(dispatch_get_main_queue()) {
            completion()
        }
    }
}

-1

なぜ延長しないのですか?

@interface UITableView(reloadComplete)
- (void) reloadDataWithCompletion:( void (^) (void) )completionBlock;
@end

@implementation UITableView(reloadComplete)
- (void) reloadDataWithCompletion:( void (^) (void) )completionBlock {
    [self reloadData];
    if(completionBlock) {
        completionBlock();
    }
}
@end

最後までスクロール:

[self.table reloadDataWithCompletion:^{
    NSInteger numberOfRows = [self.table numberOfRowsInSection:0];
    if (numberOfRows > 0)
    {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:numberOfRows-1 inSection:0];
        [self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
    }
}];

大量のデータでテストされていません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.