使用viewDidLayoutSubviews检测UITableView滚动会导致过多的回调

时间:2016-08-22 20:18:10

标签: ios swift uitableview if-statement parallax

我有一个tableView,它是我在Github上找到的Parallax表视图的子类。完成所有正常设置的表视图(删除其中的一些,因为它无关紧要)。

class EventDetailTableViewController: ParallaxTableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the image:
        self.imageView.image = eventImage

        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.translucent = true
    }


    // MARK: - UITableViewDelegate
     override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

    override    
     func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 4
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
       // SET UP CELL
    }

    @IBAction func backButtonPressed(sender: AnyObject) {
        print("backButtonPressed")
        self.navigationController?.navigationBar.translucent = false

        self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)

        self.navigationController?.popViewControllerAnimated(true)
    }
} // END OF VIEWCONTROLLER CLASS

这里需要注意的重要事项是我navigationBar透明了。调用backButtonPressed时,我希望将navigationBar.Color更改回上一个视图控制器(红色)的颜色。所以我在backButtonPressed()

中对此进行了编码

这是我的Parallax代码。请查看最后一个功能moveImage()。我有一个简单的效果,当tableview向下滚动到足够描述时navigationBar出现标题"事件描述"

class ParallaxTableViewController: UITableViewController {

    // Create the UIView
    //var bottomFloatingView =  UIView()

    // Create the UIImageView
    let imageView = UIImageView()

    // Set the factor for the parallaxEffect. This is overwritable.
    var parallaxFactor:CGFloat = 2

    // Set the default height for the image on the top.
    var imageHeight:CGFloat = 320 {
        didSet {
            moveImage()
        }
    }

    // Initialize the scrollOffset varaible.
    var scrollOffset:CGFloat = 0 {
        didSet {
            moveImage()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the contentInset to make room for the image.
        self.tableView.contentInset = UIEdgeInsets(top: imageHeight, left: 0, bottom: 0, right: 0)

        // Change the contentMode for the ImageView.
        imageView.contentMode = UIViewContentMode.ScaleAspectFill

        // Add the imageView to the TableView and send it to the back.
        view.addSubview(imageView)
        view.sendSubviewToBack(imageView)
    }

    override func viewDidLayoutSubviews() {
        // Update the image position after layout changes.
        moveImage()
    }

    // Define method for image location changes.
    func moveImage() {
        let imageOffset = (scrollOffset >= 0) ? scrollOffset / parallaxFactor : 0
        let imageHeight = (scrollOffset >= 0) ? self.imageHeight : self.imageHeight - scrollOffset
        imageView.frame = CGRect(x: 0, y: -imageHeight + imageOffset, width: view.bounds.width, height: imageHeight)

        if imageOffset > 150 {
            print("imageOffSet")
            self.navigationItem.title = "Event Description"
            self.navigationController?.navigationBar.translucent = false
            self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
            self.navigationController?.navigationBar.shadowImage = nil

        } else {
            print("else")
            self.navigationItem.title = ""
            self.navigationController?.navigationBar.shadowImage = UIImage()
            self.navigationController?.navigationBar.translucent = true

            // This is being called after the back button is being pressed. Which means this else function overrides my backButtonPressed() therefore making my navigation bar in the new VC not the correct color.
        }
    }
}

正如您在我的笔记中看到的那样,在调用backButtonPressed()之后再次调用此else函数。因此它并没有给我新VC中所需的红色,而是让它变成半透明的。当调用backButtonPressed时,如何停止调用其他函数?

2 个答案:

答案 0 :(得分:2)

viewDidLayoutSubviews永远不应该参与响应用户事件。它是一种很少使用的内部生命周期方法,除非您将程序化NSLayoutConstraints添加或修改为已添加到Storyboard中的方法UITableViewDelegate。它被称为非常频繁和明显的冗余。

请改用表委托方法。特别是UIScrollViewDelegate继承自tableView所以参考:

UITableView Scroll event

然后查询indexPathsForVisibleRows本身以获取可见性信息,例如GROUP BY

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instp/UITableView/indexPathsForVisibleRows

答案 1 :(得分:1)

你不应该像这样使用viewDidLayoutSubviews(),正如BaseZen在他的回答中所解释的那样。 您可以使用scrollViewDidScroll来实现您的目标。

替换此

@IBAction func backButtonPressed(sender: AnyObject) {
    print("backButtonPressed")
    self.navigationController?.navigationBar.translucent = false

    self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)

    self.navigationController?.popViewControllerAnimated(true)
}

有了这个

    var backButtonWasPressed = false

@IBAction func backPressed(sender: AnyObject) {

    print("backButtonPressed")

    backButtonWasPressed = true

    self.navigationController?.navigationBar.translucent = false

    self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)

    self.navigationController?.popViewControllerAnimated(true)

}

并替换此

override func viewDidLayoutSubviews() {

// Update the image position after layout changes.
moveImage()
}

有了这个

override func scrollViewDidScroll(scrollView: UIScrollView) {
    if !backButtonWasPressed {
        moveImage()
    }
}

并将backButtonWasPressed = false放入viewDidLoad()