将 UIScrollView 委托和 UICollectionView 委托分配给同一个 Class

Assign UIScrollView Delegate And UICollectionView Delegate to the Same Class

我有一个分页 UIScrollView,每个页面都填充了不同的视图控制器。滚动视图上方是一个 UICollectionView 作为菜单栏。当您滚动浏览滚动视图页面时,菜单栏会移动一点点。从左边的动图可以看出。

将他们的代表设置为不同的 classes 可以使一切正常工作,如左侧的 gif 中所示。但是,将它们设置为相同的 class 会扰乱 UICollectionView 的行为。

如何将他们的代表设置为相同的class?

import UIKit

class MenuView: UIView, UICollectionViewDataSource {

    let collcetionView: UICollectionView = {
        let view = UICollectionView()
        // Setup...
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupCollectionView()
        collcetionView.dataSource = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    fileprivate func setupCollectionView() {
        // Autolayout code...
    }

    // Datasource methods to populate collection view cells
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    // Populate cell code...
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // Populate cell code...
    }
}


class MainView: UIView {
    // Contains paging scroll view and menu bar
    var menu: MenuView!

    let scrollView: UIScrollView = {
        let view = UIScrollView()
        // Setup...
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupMenu()
        setupScrollView()

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    fileprivate func setupScrollView() {
        // Autolayout code...
    }
    fileprivate func setupMenu() {
        menu = MenuView()
        // Autolayout code...
    }
}


class MainController: UIViewController, UIScrollViewDelegate, UICollectionViewDelegate {
    var mainView: MainView!

    override func loadView() {
        super.loadView()
        mainView = MainView()
        view = mainView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        mainView.scrollView.delegate = self
        mainView.menu.collcetionView.delegate = self // <<--- THIS IS WHAT BREAKS EVERYTHING
    }


func scrollViewDidScroll(_ scrollView: UIScrollView) {

        // Moving menu bar with page scroll
        mainView.menu.collectionView.contentOffset = CGPoint(x: scrollView.contentOffset.x/SCROLL_FACTOR - (firstIndexPosition/SCROLL_FACTOR - difference/2), y: 0)



        // Fade in and out highlighted state of menu bar cell
        let exactPage = (scrollView.contentOffset.x / SCREEN_WIDTH)
        let currentPage = (scrollView.contentOffset.x / SCREEN_WIDTH).rounded()
        let unitExact = currentPage - exactPage
        //print(String(format: "exact: %.2f, ", exactPage) + "current: \(currentPage), " + String(format: "unit: %.2f, ", unitExact))

        if exactPage > currentPage {
            // exact > current
            // fade out/in left icon
            // select current
            let unit = 0 - unitExact // from 0 - 0.5
            let cell = mainView.menu.collectionView.cellForItem(at: IndexPath(item: Int(currentPage), section: 0)) as! MenuBarCell
            let mapped = unit.map(from: 0.0...0.5, to: 0...149.0)
            print(cell)
            setCellColor(cell: cell, value: mapped)
        } else if exactPage < currentPage {
            // exact < current
            // fade out/in right icon
            // select current
            let unit = unitExact // from 0 - 0.5
            let cell = mainView.menu.collectionView.cellForItem(at: IndexPath(item: Int(currentPage), section: 0)) as! MenuBarCell
            let mapped = unit.map(from: 0.0...0.5, to: 0...149.0)
            setCellColor(cell: cell, value: mapped)
        } else if exactPage == currentPage {
            // exact = current
            // darken that icon
            // select current
        }
    }
}

UICollectionViewUITableView 继承自 UIScrollView,

如果您将两个对象的 delegate 设置为相同的 class.

,则将为您的集合视图和滚动视图调用 scrollViewDidScroll 委托方法

您需要检查 scrollViewDidScroll 被调用的原因并采取相应措施。

最简单的方法是 guard 声明 returns 如果没有为您感兴趣的滚动视图调用委托方法。

如果您需要根据涉及的滚动视图执行不同的代码,您可以使用一系列 if 语句或 switch 语句。

func scrollViewDidScroll(_ scrollView: UIScrollView) {

   guard scrollView == self.scrollView else {
       return
   }

    // Moving menu bar with page scroll
    mainView.menu.collectionView.contentOffset = CGPoint(x: scrollView.contentOffset.x/SCROLL_FACTOR - (firstIndexPosition/SCROLL_FACTOR - difference/2), y: 0)



    // Fade in and out highlighted state of menu bar cell
    let exactPage = (scrollView.contentOffset.x / SCREEN_WIDTH)
    let currentPage = (scrollView.contentOffset.x / SCREEN_WIDTH).rounded()
    let unitExact = currentPage - exactPage
    //print(String(format: "exact: %.2f, ", exactPage) + "current: \(currentPage), " + String(format: "unit: %.2f, ", unitExact))

    if exactPage > currentPage {
        // exact > current
        // fade out/in left icon
        // select current
        let unit = 0 - unitExact // from 0 - 0.5
        let cell = mainView.menu.collectionView.cellForItem(at: IndexPath(item: Int(currentPage), section: 0)) as! MenuBarCell
        let mapped = unit.map(from: 0.0...0.5, to: 0...149.0)
        print(cell)
        setCellColor(cell: cell, value: mapped)
    } else if exactPage < currentPage {
        // exact < current
        // fade out/in right icon
        // select current
        let unit = unitExact // from 0 - 0.5
        let cell = mainView.menu.collectionView.cellForItem(at: IndexPath(item: Int(currentPage), section: 0)) as! MenuBarCell
        let mapped = unit.map(from: 0.0...0.5, to: 0...149.0)
        setCellColor(cell: cell, value: mapped)
    } else if exactPage == currentPage {
        // exact = current
        // darken that icon
        // select current
    }
}