1

I have a tableView which is a subclass of a Parallax table view I found on Github. Done all table view set up as normal (Deleted some of it since its irrelevant).

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

Important things to note here is I have made the navigationBar transparent. When backButtonPressed is called, I wish to change back the navigationBar.Color to the color of the previous View Controller (Red). So I have coded that in the backButtonPressed()

Here is the Parallax code I have. Please view the last func moveImage(). I have the simple effect of when the tableview scrolls down far enough to the description the navigationBar appears with the title "Event Description"

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.
        }
    }
}

As you can see in my notes, this else function is being called again after the backButtonPressed() is called. Therefore it does not give me the desired red in the new VC but it leaves it translucent instead. How can I stop this else function being called when the backButtonPressed is being called?

BaseZen
  • 8,650
  • 3
  • 35
  • 47
MarkPitch
  • 21
  • 2
  • well `imageOffset < 150` if that else is being called. You probably need to check your math then and find what in there is breaking. – John Riselvato Aug 22 '16 at 20:23

2 Answers2

2

viewDidLayoutSubviews should never be involved in responding to user events. It is an internal lifecycle method that is rarely used unless you're adding or modifying programmatic NSLayoutConstraints to those already added in Storyboard. It is called quite frequently and apparent redundancy.

Use table delegate methods instead. In particular UITableViewDelegate inherits from UIScrollViewDelegate so reference:

UITableView Scroll event

Then query the tableView itself for visibility information e.g. indexPathsForVisibleRows:

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

Community
  • 1
  • 1
BaseZen
  • 8,650
  • 3
  • 35
  • 47
1

You should not use viewDidLayoutSubviews() like this as BaseZen has explained in his answer. You can use scrollViewDidScroll to achieve what you want.

Replace this

@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)
}

With this

    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)

}

And replace this

override func viewDidLayoutSubviews() {

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

With this

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

And put backButtonWasPressed = false in your viewDidLoad()

Swifty
  • 3,730
  • 1
  • 18
  • 23
  • Seems to make sense what you guys are saying but I've changed this. Still seems to be calling the else, hhhmm... – MarkPitch Aug 22 '16 at 21:28
  • I tested It and it seems that using the back button triggers `scrollViewDidScroll` too. I'll edit my answer to fix this problem. – Swifty Aug 22 '16 at 21:42
  • @MarkPitch See my edited answer. It should work now. – Swifty Aug 23 '16 at 18:31