等到scrollToRowAtIndexPath在swift中完成

时间:2015-06-04 10:46:55

标签: ios uitableview swift

我有一个UITableView,屏幕上有更多的单元格。当我从我的数据模型中收到通知时,我想跳转到特定的行并显示一个非常基本的动画。

我的代码是:

 func animateBackgroundColor(indexPath: NSIndexPath) {        
    dispatch_async(dispatch_get_main_queue()) {
        NSLog("table should be at the right position")
        if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? BasicCardCell {
            var actColor = cell.backgroundColor
            self.manager.vibrate()
            UIView.animateWithDuration(0.2, animations: { cell.backgroundColor = UIColor.redColor() }, completion: {
                _ in

                UIView.animateWithDuration(0.2, animations: { cell.backgroundColor = actColor }, completion: { _ in
                        self.readNotificationCount--
                        if self.readNotificationCount >= 0 {
                            var legicCard = self.legicCards[indexPath.section]
                            legicCard.wasRead = false
                            self.reloadTableViewData()
                        } else {
                            self.animateBackgroundColor(indexPath)
                        }
                })
            })
        }
    }
}    

func cardWasRead(notification: NSNotification) {
    readNotificationCount++
    NSLog("\(readNotificationCount)")

        if let userInfo = notification.userInfo as? [String : AnyObject], let index = userInfo["Index"] as? Int {

            dispatch_sync(dispatch_get_main_queue()){
                self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: index), atScrollPosition: .None, animated: true)

                self.tableView.layoutIfNeeded()
                NSLog("table should scroll to selected row")
            }
            self.animateBackgroundColor(NSIndexPath(forRow: 0, inSection: index))
        }
}

我希望dispatch_sync部分会延迟执行animateBackgroundColor方法,直到滚动完成为止。不幸的是,情况并非如此,以便在行不可见时调用animateBackgroundColor - > cellForRowAtIndexPath returns nil我的动画不会发生。如果不需要滚动,则动画可以正常工作。

在滚动完成之前,有人能告诉我如何延迟执行animateBackgroundColor功能吗?

非常感谢和亲切的问候

3 个答案:

答案 0 :(得分:4)

延迟动画似乎不是一个好的解决方案,因为scrollToRowAtIndexPath动画持续时间是根据当前列表项到指定项的距离设置的。要解决此问题,您需要在scrollToRowAtIndexPath动画完成后通过实现scrollViewDidEndScrollingAnimation UITableViewDelegate方法执行animateBackgroudColor。这里棘手的部分是获取tableview滚动的indexPath。可能的解决方法:

var indexPath:NSIndexpath?

func cardWasRead(notification: NSNotification) {
readNotificationCount++
NSLog("\(readNotificationCount)")

    if let userInfo = notification.userInfo as? [String : AnyObject], let index = userInfo["Index"] as? Int{

        dispatch_sync(dispatch_get_main_queue()){

            self.indexPath = NSIndexPath(forRow: 0, inSection: index)
            self.tableView.scrollToRowAtIndexPath(self.indexPath, atScrollPosition: .None, animated: true)

            self.tableView.layoutIfNeeded()

            NSLog("table should scroll to selected row")
        }

    }

}

func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
    self.animateBackgroundColor(self.indexPath)
    indexPath = nil
}

答案 1 :(得分:0)

这是我的解决方法

1)创建一个.swift文件,并将下面的代码复制到其中:

typealias SwagScrollCallback = (_ finish: Bool) -> Void 

class UICollectionViewBase: NSObject, UICollectionViewDelegate {
    static var shared = UICollectionViewBase()

    var tempDelegate: UIScrollViewDelegate?
    var callback: SwagScrollCallback?

    func startCheckScrollAnimation(scroll: UIScrollView, callback: SwagScrollCallback?){
        if let dele = scroll.delegate {
            self.tempDelegate = dele
        }
        self.callback = callback
        scroll.delegate = self
    }
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        callback?(true)
        if let dele = self.tempDelegate {
            scrollView.delegate = dele
            tempDelegate = nil
        }
    }
}

extension UICollectionView {

    func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionView.ScrollPosition, _ callback: SwagScrollCallback?){
        UICollectionViewBase.shared.startCheckScrollAnimation(scroll: self, callback: callback)
        self.scrollToItem(at: indexPath, at: scrollPosition, animated: true)
    }

}

2)示例:

@IBAction func onBtnShow(){

        let index = IndexPath.init(item: 58, section: 0)
        self.clv.scrollToItem(at: index, at: .centeredVertically) { [weak self] (finish) in

            guard let `self` = self else { return }

            // Change color temporarily
            if let cell = self.clv.cellForItem(at: index) as? MyCell {
                cell.backgroundColor = .yellow
                cell.lbl.textColor = .red
            }


            // Reset
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                self.clv.reloadData()
            }
        }
    }

3)我的github代码示例:github here

答案 2 :(得分:-2)

我有类似的问题。我就是这样做的。

UIView.animateWithDuration(0.2,delay:0.0,options: nil,animations:{
          self.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: .Middle, animated: true)},
                        completion: { finished in UIView.animateWithDuration(0.5, animations:{
                            self.animateBackgroundColor(self.indexPath)})})}