Вопрос:

Обнаружение прокрутки UITableView с viewDidLayoutSubviews вызывает чрезмерные обратные вызовы

ios swift uitableview if-statement parallax

281 просмотра

2 ответа

11 Репутация автора

У меня есть tableView, который является подклассом табличного представления Parallax, который я нашел на Github. Выполнено все таблицы, настроенные как обычно (Удалено некоторые из них, поскольку они не имеют значения).

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цвет на предыдущий View Controller (красный). Так что я закодировал это вbackButtonPressed()

Вот параллакс-код, который у меня есть. Пожалуйста, просмотрите последний функционал moveImage(). У меня есть простой эффект, когда табличное представление прокручивается достаточно далеко, чтобы описание 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()вызова. Поэтому он не дает мне желаемый красный цвет в новом VC, но оставляет его полупрозрачным. Как я могу остановить вызов этой функции еще, когда вызывается backButtonPressed?

Автор: MarkPitch Источник Размещён: 22.08.2016 08:18

Ответы (2)


2 плюса

7311 Репутация автора

viewDidLayoutSubviewsникогда не должен участвовать в реагировании на пользовательские события. Это внутренний метод жизненного цикла, который используется редко, если вы не добавляете или не изменяете программные параметры NSLayoutConstraintsпо сравнению с уже добавленными в раскадровку. Это называется довольно часто и явной избыточностью.

Вместо этого используйте методы делегирования таблицы. В частности UITableViewDelegateнаследует от UIScrollViewDelegateтак ссылки:

Событие прокрутки UITableView

Затем запросите у tableViewсебя информацию о видимости, например indexPathsForVisibleRows:

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

Автор: BaseZen Размещён: 22.08.2016 08:38

1 плюс

3122 Репутация автора

Вы не должны использовать 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 ()

Автор: Sam_M Размещён: 22.08.2016 09:04
Вопросы из категории :
32x32