24

今朝、iOS6を含む新しいXcodeをインストールしました。

章と行を含むplistファイルがロードされたテーブルビューがあります。章はセクションを定義します。

ユーザーが章と行を選択すると、テーブルビューが自動的に正しい位置(viewDidLoad内)にスクロールされます。

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES];

これはiOS5シミュレーターでうまく機能します。

iOS 6シミュレーターでこれを試してみると、スクロールは実行されません。エラーは発生しません。linePosとchapterPosが正しい値を受け取ることを確認しましたが、スクロールが実行されません。

なぜアイデアはありますか?

4

9 に答える 9

68

Objective-C

[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
        NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0];
        [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
});

迅速

tableView.reloadData()
DispatchQueue.main.async {
    let indexPath = IndexPath(row: linePos, section: chapterPos)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
于 2014-12-12T15:40:13.390 に答える
29

iOSの最近のバージョンについては、FyodorVolchyokの回答をお読みください。質問が最初に尋ねられたとき(2012年9月)、現在の回答が実用的な解決策であったという理由だけで、受け入れられた回答としてマークされていないことに注意してください。iOSの最近のバージョンでも同じ問題が発生しましたが、これはFyodor Volchyokの回答によって解決されているため、その時点で彼の回答を+1する必要があります。


私は答えを見つけました。最初にテーブルビューのデータをリロードする必要があります

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];

[self.tableView reloadData];

[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES];

答えを見つけたのに、なぜそれがiOS6ではなくiOS5で機能しているのかわかりません。

編集

おそらく、それが機能していても、最後の行を表示するのに問題があり、そのための質問を投稿したことを追加する必要があります

UItableviewscrollToRowAtIndexPathが最後の行を正しく表示しない

@Rajもそれを求めたので、私はそれをトリガーしていたと言うべきviewDidLoadです。最後の行が正しく表示されないという問題を修正するには、それをに配置する必要がありましたviewDidAppear

于 2012-09-21T08:11:55.827 に答える
3

フョードル・ヴォルチョクの答えに加えて、この答えを追加します。また、ディスパッチによって問題が解決することもわかりました。ディスパッチしない回避策を見つけることができました。

self.tableView.reloadData()
let index = // the desired index path

// For some reason, requesting the cell prior to 
// scrolling was enough to workaround the issue.
self.tableView.cellForRowAtIndexPath(index)

self.tableView.scrollToRowAtIndexPath(index, atScrollPosition: .Top, animated: false)
于 2016-01-05T17:00:09.417 に答える
3

これはiOS12および13で機能します。

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { 
    self.tableView.scrollToRow(at: IndexPath(row: 0, section: 1), at: .bottom, animated: true) 
}
于 2020-01-17T15:47:17.833 に答える
2

特にios11を実行しているiPhoneXで、scrollToRowAtIndexPathに関する別の問題(おそらくバグ)が発生しました。私のテーブルには数百のセクションがあり、折りたたみモードでは最大10が表示画面に収まります。indexPathが深くなるにつれて、スクロールは徐々に遅れていきました。

たとえば、検索で行30のアイテムを検索したい場合、ScrollPositionTopには、実際の行が一番上にあると予想される前に1行追加されます。

そして、より深い行の検索をテストすると、さらに遅れ始めました。たとえば、100行を超えると、予想される行が表示領域に表示されませんでした。

私がこれまでに見つけた回避策は、dispatch_async内のスクロールに対してanimated:NOと言うことです。そうすれば、グリッチなしで機能します。

于 2017-11-28T22:18:12.943 に答える
1

automaticallyAdjustsScrollViewInsetsiOS7以降、UIViewControllerのデフォルトのプロパティはですYEScontentOffsetこれにより、View Controllerがプッシュされたときに、システムがtableViewのを調整します。あなた[self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];viewWillAppear。またcontentOffset、以降はシステムにより変更されますviewWillAppear。だから私の解決策は:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = NO;

    /// any other codes
}

- (void)viewWillLayoutSubviews {
    self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
}

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

    // change tableView data source

    [self.tableView reloadData];
     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.dataSourceArray count] - 1 inSection:0];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
}
于 2015-12-17T08:27:32.453 に答える
1

もう1つの可能な回避策は、を呼び出すlayoutIfNeeded前に呼び出すことscrollToRowAtIndexPathです。

[self.view layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath...];
于 2019-07-10T11:55:01.210 に答える
0

SwiftでのFyodorVolchyokの答え:

tableView.reloadData()
let indexPath = NSIndexPath(forRow: linePos, inSection: chapterPos)
// make sure the scroll is done after data reload was finished
dispatch_async(dispatch_get_main_queue()) {
   self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}
于 2016-10-23T07:54:32.840 に答える
0

それはios11で私のために働いた

self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0

dispatch_async(dispatch_get_main_queue(), ^{
   NSInteger numberOfSections = self.tableView.numberOfSections;
   if (numberOfSections > 0)
   {
     NSInteger lastSection = numberOfSections - 1;
     NSInteger lastRowInLastSections = [self.tableView numberOfRowsInSection:lastSection] - 1;

     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRowInLastSections inSection:lastSection];
     [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:isAnimated];
}
});
于 2017-10-12T06:20:15.447 に答える