web-dev-qa-db-ja.com

UITableViewでscrollToRowAtIndexPathが機能しない

IOS8には、次のようなテーブルビューがあります。

tableView = UITableView(frame: view.bounds, style: .Plain)
view.addSubview(tableView)

ユーザーがキーボードでテキストを入力して送信すると、アプリケーションは次のメソッドを呼び出してtableViewをスクロールします。目標は、画面に新しいテキストを表示することです(チャットなど)

let numberOfRows = tableView.numberOfRowsInSection(0)
        if numberOfRows > 0 {
            let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: 0)
            tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
        }

しかし、テーブルビューは、ブースにスクロールしません。

誰かが解決策を持っていますか?

ありがとうございました。

説明:

クラスの定義:

class ChatViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate 

次に、テーブルビューの定義があります:

var tableView: UITableView! 

viewDidLoadで:

tableView = UITableView(frame: view.bounds, style: .Plain) 
tableView.dataSource = self 
tableView.delegate = self 
view.addSubview(tableView) 

次に、スクロールを行う必要のあるコードを呼び出します(回答の2番目のコードブロック)。アプリケーションを起動すると、tableviewが下にスクロールするはずですが、機能しません。

21
Kobazzo

以下の解決策は私のために働いた。 StackOverflowにあるソリューションの組み合わせです。非常に短い遅延の後、「scrollToRowAtIndexPath」を呼び出しました。

func tableViewScrollToBottom(animated: Bool) {

    let delay = 0.1 * Double(NSEC_PER_SEC)
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

    dispatch_after(time, dispatch_get_main_queue(), {

        let numberOfSections = self.tableView.numberOfSections()
        let numberOfRows = self.tableView.numberOfRowsInSection(numberOfSections-1)

        if numberOfRows > 0 {
            let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: (numberOfSections-1))
            self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
        }

    })
}

呼び出し元:

tableViewScrollToBottom(true)

Swift

func tableViewScrollToBottom(animated: Bool) {
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
        let numberOfSections = self.tableView.numberOfSections
        let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)

        if numberOfRows > 0 {
            let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
            self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: animated)
        }
    }
}
79
Fox5150

私の問題の解決策は次のとおりです。

let numberOfSections = tableView.numberOfSections()
let numberOfRows = tableView.numberOfRowsInSection(numberOfSections-1)

if numberOfRows > 0 {
    println(numberOfSections)
    let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: (numberOfSections-1))
    tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
}
9
Kobazzo

スクロールを呼び出す前に、最初にリロードしてみてください。非常に奇妙ですが、iOS8で動作します。

   tableView.reloadData()
   tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
6
Ankish Jain

@ Fox5150回答のSwift 3バージョン、拡張子付き:

extension UITableView {

    func tableViewScrollToBottom(animated: Bool) {

        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {

            let numberOfSections = self.numberOfSections
            let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
            if numberOfRows > 0 {
                let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
                self.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: animated)
            }
        }
    }
}

使用法:

self.tableView.tableViewScrollToBottom(animated: true)
6
Phil

簡単だ。 viewDidLayoutSubViews()でスクロール操作を行うだけです

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.scrollToBottom(animated: false)
}

fileprivate func scrollToBottom(animated: Bool) {
    if self.items.count > 0 {
        let lastIndex = IndexPath(row: items.count - 1, section: 1)
        self.tableView.scrollToRow(at: lastIndex, at: .bottom, animated: animated)
    }
}

レイアウトサブビューの後に、tableviewが正しい位置を取得できるようです。

2
Lucas Lin

インデックスが15を超えると、大きな問題が発生します。5〜6までのインデックスしか使用できません。 「アニメーション:false」を作成することにより、scrollToRowAtIndexPath()は完全に機能しました。

2
Imran

より良い解決策は、tableViewを上下逆にして、-insertRowsAtIndexPaths:withRowAnimation:

それを行うには、まず次の方法でテーブルを反転する必要があります。

_tableView.transform = CGAffineTransformMakeScale (1,-1);

次に、セルを元に戻すことを忘れないでください。サブクラス化することで-awakeFromNibでそれを行うのに最適な場所です。

- (void)awakeFromNib {
    [super awakeFromNib];
    self.contentView.transform = CGAffineTransformMakeScale (1,-1);

//if you have accessoryView
    self.accessoryView.transform = CGAffineTransformMakeScale (1,-1);
}
1
Ivan Androsenko

`viewWillLayoutSubviews()でscrollToRow()を呼び出すことで問題を解決しました

0
Murat Yasar

キーボードがまだ表示されている場合は、UITableViewcontentInsetプロパティを設定して、画面下部のキーボードの高さを補正する必要があります。そうしないと、UITableViewはコンテンツの半分がセルによって隠されていることを知らないため、セルがキーボードの後ろに隠れている可能性があります。

または、それを自動的に処理するUITableViewControllerを使用します。

0
fluidsonic

私はこれが古いスレッドであることを知っていますが、それでも関連があります。タイミングがうまく取れない場合があるタイムアウトを処理する代わりに、メインスレッドで同期ブロックを使用します(通常、私は何もしませんが、ミリ秒を話しています)。

DispatchQueue.main.sync {
  // Reload code goes here...
  tableView.reloadData()
}

DispatchQueue.main.sync {
  // Row, section and other checks / initialization go here...
  tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

これは私にとって常に有効です。

0
Aaron

Heres Swift 3バージョン

let numberOfSections = self.tableView.numberOfSections
let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)

if numberOfRows > 0 {
    let indexPath = NSIndexPath.init(row: numberOfRows-1, section: numberOfSections-1)
    self.tableView.scrollToRow(at: indexPath as IndexPath, at: UITableViewScrollPosition.bottom, animated: animated)
}
0
Pankaj Gaikar

ViewWillAppear()からの呼び出しのようにtableviewを読み込んだ後、または何かがtableviewに変更されたときにtable viewを再読み込みした後にscrollToLastPosition()メソッドを呼び出します

func scrollToLastPosition() {
 if !message.isEmpty {
    let indexpath = NSIndexPath(forRow: message.count - 1 , inSection:     0)
    self.tableView.scrollToRowAtIndexPath(indexpath, atScrollPosition: .Bottom, animated: true)
}
}
0
bikram sapkota
// First figure out how many sections there are
 let lastSectionIndex = self.tblTableView!.numberOfSections() - 1

// Then grab the number of rows in the last section

let lastRowIndex = 
self.tblTableView!.numberOfRowsInSection(lastSectionIndex) - 1

// Now just construct the index path

let pathToLastRow = NSIndexPath(forRow: lastRowIndex, inSection: lastSectionIndex)

// Make the last row visible
self.tblTableView?.scrollToRowAtIndexPath(pathToLastRow, atScrollPosition: UITableViewScrollPosition.None, animated: true)
0