UITableView - 在viewDidAppear

时间:2016-04-25 17:49:57

标签: ios swift uitableview

如果标题不明显,我想要的应该是简单的,因为当用户第一次看到它时,tableView会一直向下滚动到底部(之前他看到了,没有动画)。

所以,我知道这已经回答了几次,但这些解决方案似乎都没有发挥作用。 为了给出一些背景信息,我现在使用Swift,自动布局和最新版本的iOS。

约束

我需要支持一些事情:

  1. 在用户看到它之前加载它(显然没有动画)。
  2. 动态单元格高度,即它们的高度由UILabel确定(如消息传递应用程序 - 在故事板中使用自动布局)。
  3. 我的UITableView位于UIScrollView内(UIScrollView水平滚动,UITableView垂直滚动。
  4. UITableView位于childViewController,即我将其添加到主UIViewController(由于某种原因,导致viewWillAppear无法被调用 - {{ 1}}仍然被称为。)
  5. 我将总结一下我的尝试:

    至于实施:

    1. viewDidAppear

    2. tableView.contentOffset = CGPoint(x: 0, y: CGFloat.max

    3. tableView.scrollToRowAtIndexPath(indexPathForLastItem, atScrollPosition: .Bottom, animated: false)
      1. 
            var contentOffset = tableView.contentOffset
            contentOffset.y = tableView.contentSize.height - tableView.bounds.size.height
            tableView.setContentOffset(contentOffset, animated: false)
        
        

        至于我试图调用这些实施的地方:

        1. dispatch_async(dispatch_get_main_queue(), { // tried option 1., 2. and 3. here })
        2. viewDidLoad
        3. viewWillAppear(仅在第一次调用时,我使用属性进行跟踪)
        4. viewDidLayoutSubviews(尽管这不会给我我想要的东西)
        5. 在我的模型上viewDidAppear
        6. 在那之前,我总是打电话给didSet

          我不想做什么:

          tableView.reloadData

          +

          tableView.transform = CGAffineTransformMakeScale(1, -1)

          (我假设如果您考虑建议使用此解决方案,那是因为您知道我正在谈论的黑客攻击。如果您不这样做,那么您赢了&#39建议这样做,所以你不需要了解它是如何工作的)

          我不想要这个的原因之一是因为现在我无法滚动到顶部......

          我注意到的问题:

          1. cell.transform = CGAffineTransformMakeScale(1, -1)' s tableView(作为contentSize子类)在您出现后第一次滚动时会发生变化。是的,我的意思是UIScrollView,而不是contentSize,当您滚动时,它会更改多次。在您滚动整个contentOffset一次之后,它就不再发生变化。
          2. 有些人说它适用于较少的细胞(说实话,它在某些时候对我有效),所以试试至少20项。
          3. tableView没有被调用,但viewWillAppear会被调用。
          4. 任何解决方案(除了我提到的我不想要的解决方案)都会非常感激。即使是hacky,只要他们不打破其他东西。

            正如旁注所示,viewDidAppear不会缩放,例如,如果你有2000件物品则太慢了。因此,理想情况下,我更喜欢可扩展的解决方案。

            答案后的编辑:

            1. 在@ bsmith11的回答之后,我试过了:

              scrollToRowAtIndexPath...

              它没有用。

7 个答案:

答案 0 :(得分:2)

viewDidLayoutSubviews()中,将.contentOffset设置为tableView.bounds.height。您需要在异步块中启用它,以便tableView时间加载它的内容。

dispatch_async(dispatch_get_main_queue()) { self.tableView.setContentOffset(tableView.bounds.height, animated: false) }

viewDidLayoutSubviews()可以多次调用,因此您可能希望确保上面的代码只被调用一次。

答案 1 :(得分:1)

刚试过下面的代码就行了。

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

      myArray = [["Data": "1234567890", "Height": 44],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "End of Table", "Height": 132]]

    let no = myArray.count-1

    let lastIndex = NSIndexPath(forRow: no, inSection: 0)

    table1.scrollToRowAtIndexPath(lastIndex, atScrollPosition: .Bottom, animated: true)

}

Download sample code

答案 2 :(得分:0)

将以下方法添加到自定义子类。

 - (void)tableViewScrollToBottomAnimated:(BOOL)animated {
        NSInteger numberOfRows = [_tableView numberOfRowsInSection:0];
        if (numberOfRows) {
            [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
        }
    }

[self tableViewScrollToBottomAnimated:NO]结束时致电viewDidAppear。 一个问题是,不幸的是,它还会导致tableView:heightForRowAtIndexPath:被调用三次。

答案 3 :(得分:0)

我遇到了完全相同的问题,在尝试了所有内容(与您相同)后,这很有用,关键是如果您使用autolayout,则必须在viewDidLayoutSubviews中编写scrollToBottom代码

将scrollToBottom初始化为true,然后执行此操作

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    // Scroll table view to the last row
    [self scrollToBottom];
}

-(void)scrollToBottom {
    if (shouldScrollToLastRow)
    {
        CGPoint bottomOffset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height);
        [self.tableView setContentOffset:bottomOffset animated:NO];
    } }

这样做可以确保您几乎位于桌面底部,但可能不会处于最底层,因为当您处于最顶端时,无法知道确切的底部偏移量tableView,之后我们可以实现scrollViewDidScroll

-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    // if you're not at bottom then scroll to bottom
    if (!(scrollOffset + scrollViewHeight == scrollContentSizeHeight))
    {
        [self scrollToBottom];
    } else {
    // bottom reached now stop scrolling
        shouldScrollToLastRow = false;
    }
}

答案 4 :(得分:0)

private var called = false
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if !called {
        dispatch_async(dispatch_get_main_queue(), {
            self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.bounds.height), animated: false)
        })
        called = true
    }
}

我用我的UIScrollView尝试了这段代码。 并且有效。如果我删除dispatch_async则无效。

Swift 3代码

private var called = false
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if !called {
        DispatchQueue.main.async(execute: {
            self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.bounds.height), animated: false)})
        called = true
    }
}

答案 5 :(得分:0)

我认为在ViewDidLoad中调用[table setContentOffset:CGPointMake(0, CGFLOAT_MAX)]table.estimatedRowHeight = 50(change your value);就是您所需要的。

答案 6 :(得分:0)

  1. 取消选中“自动”表视图的属性;行高度和估计

custom CSS

  1. 添加此代码

    override func viewWillAppear(_ animated: Bool) {
    
        super.viewWillAppear(animated)
    
        if scrollToBottomOnce == false {
            scrollToBottomOnce = true
            if self.items.count > 0 {
                self.tableView.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false)
            }
        }
    }