代码之家  ›  专栏  ›  技术社区  ›  iKK

iOS14 CollectionView组合不再工作

  •  0
  • iKK  · 技术社区  · 6 年前

    使用iOS14.0.1、Swift5.3、Xcode12.0.1,

    在iOS12和iOS13下,我的代码运行良好。但是自从iOS14以后,我的CollectionView组合就不再允许触摸事件了。

    自从iOS14破坏了我的代码之后,有什么变化???

    以下是我的CollectionView组合代码:

    class SettingsViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
        
        let cellId = "cellID"
        
        init() {
            let collectionViewFlowLayout = UICollectionViewFlowLayout()
            collectionViewFlowLayout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 1)
            super.init(collectionViewLayout: collectionViewFlowLayout)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()        
            // ...                        
            collectionView.register(SettingsCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
        }
            
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 1
        }
        
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SettingsCollectionViewCell
            cell.setup(titlesFirstSection: titlesFirstSection, iconsFirstSection: iconsFirstSection, onStatesFirstSection: onStatesFirstSection, )
            return cell
        }
    }
    
    class SettingsCollectionViewCell: UICollectionViewCell {
        
        var SettingsStackView = UIStackView()
        var attries: UICollectionViewLayoutAttributes!
        var myContentHeight: CGFloat = 0.0
        
        var firstSettingsSectionView: MenuSwitchListSectionView?
        
        let elementHeight: CGFloat = 44.0
        let separatorLineThickness: CGFloat = 1.0
        let sectionViewBackgroundColor = ImageConverter.UIColorFromRGB(0x2C2C2E, alpha: 1.0)
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
            
        func setup(titlesFirstSection: [String],
                    iconsFirstSection: [UIImage?]?,
                 onStatesFirstSection: [Bool]) {
                    
            myContentHeight = UIScreen.main.bounds.height - 120
                                    
            initFirstSettingsSectionView(titles: titlesFirstSection, icons: iconsFirstSection, onStates: onStatesFirstSection)
            
            SettingsStackView = VerticalStackView(arrangedSubviews: [
                UIView(),
                firstSettingsSectionView! as UIView,
                UIView()
            ], spacing: 10.0, alignment: .center )
            
            contentView.addSubview(SettingsStackView)
            contentView.isUserInteractionEnabled = true
            
            setConstraints(nrOfItemsFirstSection: titlesFirstSection.count)
        }
        
        fileprivate func initFirstSettingsSectionView(titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
    
            firstSettingsSectionView = MenuSwitchListSectionView(frame: .zero,
                                      elementHeight: elementHeight,
                             separatorLineThickness: separatorLineThickness,
                                    backgroundColor: sectionViewBackgroundColor,
                                             titles: titles,
                                              icons: icons,
                                           onStates: onStates
            )
            firstSettingsSectionView?.switchMutatedDelegate = self
            firstSettingsSectionView?.assignDelegate()
        }
        
        fileprivate func setConstraints(nrOfItemsFirstSection: Int) {
    
            contentView.translatesAutoresizingMaskIntoConstraints = false
            SettingsStackView.translatesAutoresizingMaskIntoConstraints = false
            firstSettingsSectionView?.translatesAutoresizingMaskIntoConstraints = false
            
            SettingsStackView.anchor(top: safeAreaLayoutGuide.topAnchor, leading: contentView.leadingAnchor, bottom: nil, trailing: contentView.trailingAnchor)
                            
            let totalHeightFirstSection: CGFloat = elementHeight * CGFloat(nrOfItemsFirstSection) + separatorLineThickness * CGFloat(nrOfItemsFirstSection - 1)
            firstSettingsSectionView?.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0).isActive = true
            firstSettingsSectionView?.heightAnchor.constraint(equalToConstant: totalHeightFirstSection).isActive = true
            firstSettingsSectionView?.widthAnchor.constraint(equalToConstant: contentView.bounds.width - 16.0).isActive = true
        }
    
    class MenuSwitchElementStackView: UIStackView {
        
        weak var switchMutatedDelegate: SwitchMutatedDelegate?
    
        let imgViewWidth: CGFloat = 23.0
            
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        convenience init(frame: CGRect, text: String, icon: UIImage?, onState: Bool, switchID: Int) {
            self.init(frame: frame)
            composeStackView(text: text, icon: icon, onState: onState, switchID: switchID)
        }
        
        required init(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        fileprivate func composeStackView(text: String, icon: UIImage?, onState: Bool, switchID: Int) {
            
            // StackView properties
            axis = .horizontal
            alignment = .center
            spacing = 23.0
            
            var iconImgView: UIImageView?
            
            // create Icon
            if let icon = icon {
                iconImgView = UIImageView()
                iconImgView?.image = icon
                iconImgView?.contentMode = .scaleAspectFit
            }
            
            // create Title
            let titleLabel = UILabel()
            titleLabel.font = AppConstants.Font.ListSectionElementTitleFont
            titleLabel.text = text
            titleLabel.textColor = .white
            titleLabel.tintColor = .white
            titleLabel.heightAnchor.constraint(equalToConstant: 19.0).isActive = true
            
            // create choice TextLbl
            let mySwitch = UISwitch()
            mySwitch.tag = switchID
            mySwitch.setOn(onState, animated: false)
            mySwitch.addTarget(self, action: #selector(MenuSwitchElementStackView.switchChanged(_:)), for: UIControl.Event.valueChanged)
            
            // text stackView creation
            if let iconImgView = iconImgView {
                addArrangedSubview(iconImgView)
            }
            addArrangedSubview(titleLabel)
            addArrangedSubview(mySwitch)
            // set Constraints
            setConstraints(iconImgView, titleLabel, mySwitch)
        }
        
        @objc func switchChanged(_ mySwitch: UISwitch) {
            switchMutatedDelegate?.switchChanged(isOn: mySwitch.isOn, switchID: mySwitch.tag)
        }
        
        fileprivate func setConstraints(_ iconImgView: UIImageView?, _ titleLabel: UILabel, _ mySwitch: UISwitch) {
            
            translatesAutoresizingMaskIntoConstraints = false
            iconImgView?.translatesAutoresizingMaskIntoConstraints = false
            titleLabel.translatesAutoresizingMaskIntoConstraints = false
            mySwitch.translatesAutoresizingMaskIntoConstraints = false
            
            iconImgView?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0).isActive = true
            iconImgView?.widthAnchor.constraint(equalToConstant: 24.0).isActive = true
            iconImgView?.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
    
            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
            
            mySwitch.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
            mySwitch.leadingAnchor.constraint(equalTo: trailingAnchor, constant: -64.0).isActive = true
        }
    }
    
    class MenuSwitchListSectionView: UIView {
        
        var sectionElementsStackView: MenuSwitchListSectionWithElementsStackView?
        weak var switchMutatedDelegate: SwitchMutatedDelegate?
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        convenience init(frame: CGRect,
                 elementHeight: CGFloat,
        separatorLineThickness: CGFloat,
               backgroundColor: UIColor,
                        titles: [String],
                         icons: [UIImage?]?,
                      onStates: [Bool]) {
            self.init(frame: frame)
            composeView(elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, backgroundColor: backgroundColor, titles: titles, icons: icons, onStates: onStates)
        }
        
        required init(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        func assignDelegate() {
            self.sectionElementsStackView?.switchMutatedDelegate = switchMutatedDelegate
            sectionElementsStackView?.assignDelegate()
        }
        
        fileprivate func composeView(elementHeight: CGFloat, separatorLineThickness: CGFloat, backgroundColor: UIColor, titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
    
            // create background View
            let totalHeight: CGFloat = elementHeight * CGFloat(titles.count) + separatorLineThickness * CGFloat(titles.count - 1)
            let backGroundView = ListSectionBackgroundView(frame: .zero, height: totalHeight, backgroundColor: backgroundColor)
                   
            // create stackView
            sectionElementsStackView = MenuSwitchListSectionWithElementsStackView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: totalHeight), elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, titles: titles, icons: icons, onStates: onStates)
            
            // add background and stackView to self
            addSubview(backGroundView)
            addSubview(sectionElementsStackView!)
            
            // set Constraints
            translatesAutoresizingMaskIntoConstraints = false
            backGroundView.translatesAutoresizingMaskIntoConstraints = false
            sectionElementsStackView?.translatesAutoresizingMaskIntoConstraints = false
            
            backGroundView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
            backGroundView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
            backGroundView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
            backGroundView.heightAnchor.constraint(equalToConstant: totalHeight).isActive = true
            sectionElementsStackView?.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
            sectionElementsStackView?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0).isActive = true
            sectionElementsStackView?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10.0).isActive = true
        }
    }
    
    class MenuSwitchListSectionWithElementsStackView: UIStackView {
        
        weak var switchMutatedDelegate: SwitchMutatedDelegate?
        var elementStackView: MenuSwitchElementStackView?
        var elements: [MenuSwitchElementStackView]?
        var titles: [String]? // needed for gesture callback
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        convenience init(frame: CGRect,
                 elementHeight: CGFloat,
        separatorLineThickness: CGFloat,
                        titles: [String],
                         icons: [UIImage?]?,
                      onStates: [Bool]) {
            self.init(frame: frame)
            self.titles = titles // needed for gesture callback
            composeStackView(elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, titles: titles, icons: icons, onStates: onStates)
        }
        
        required init(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        func assignDelegate() {
            if let elements = elements {
                for element in elements {
                    element.switchMutatedDelegate = switchMutatedDelegate
                }
            }
        }
        
        fileprivate func composeStackView(elementHeight: CGFloat, separatorLineThickness: CGFloat, titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
    
            // stackView properties
            axis = .vertical
            alignment = .leading
            spacing = 0.0
            
            // create stackView elements
            elements = (0..<titles.count).map { (idx) -> MenuSwitchElementStackView in
                if icons?.count ?? 0 > 0 {
                    elementStackView = MenuSwitchElementStackView(frame: .zero, text: titles[idx], icon: icons?[idx], onState: onStates[idx], switchID: idx)
                } else {
                    elementStackView = MenuSwitchElementStackView(frame: .zero, text: titles[idx], icon: nil, onState: onStates[idx], switchID: idx)
                }
                elementStackView?.isUserInteractionEnabled = true
                elementStackView?.tag = idx
                return elementStackView!
            }
            
            var singleLines = [UIView]()
            let lineThickness: CGFloat = separatorLineThickness
            
            // compose the stackView
            if let elements = elements {
                for (idx, view) in elements.enumerated() {
                    
                    // add element to stackView
                    addArrangedSubview(view)
                    
                    if idx < titles.count - 1 {
                        // add single Line to stackView
                        let singleLineView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: lineThickness))
                        singleLineView.backgroundColor = ImageConverter.UIColorFromRGB(0x606060, alpha: 1.0)
                        singleLines.append(singleLineView)
                        
                        addArrangedSubview(singleLineView)
                    }
                }
            }
            
            // set constraints
            translatesAutoresizingMaskIntoConstraints = false
    
            if let elements = elements {
                for (idx, element) in elements.enumerated() {
                    element.translatesAutoresizingMaskIntoConstraints = false
                    element.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
                    element.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
                    element.heightAnchor.constraint(equalToConstant: elementHeight).isActive = true
                    if idx < titles.count - 1 {
                        singleLines[idx].translatesAutoresizingMaskIntoConstraints = false
                        singleLines[idx].topAnchor.constraint(equalTo: element.bottomAnchor).isActive = true
                        singleLines[idx].heightAnchor.constraint(equalToConstant: lineThickness).isActive = true
                        if icons?.count ?? 0 > 0 {
                            if let _ = icons?[idx] {
                                singleLines[idx].leadingAnchor.constraint(equalTo: leadingAnchor, constant: 39.0).isActive = true
                            }
                        } else {
                            singleLines[idx].leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
                        }
                        singleLines[idx].trailingAnchor.constraint(equalTo: trailingAnchor, constant: 9.0).isActive = true
                    }
                }
            }
        }
    }
    
    class ListSectionBackgroundView: UIView {
        
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        
        convenience init(frame: CGRect, height: CGFloat = 60.0, backgroundColor: UIColor) {
            self.init(frame: frame)
            composeView(height: height, backgroundColor: backgroundColor)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        fileprivate func composeView(height: CGFloat, backgroundColor: UIColor) {
            
            // View properties
            self.backgroundColor = backgroundColor
            self.layer.cornerRadius = 10.0
            self.layer.masksToBounds = true
            self.clipsToBounds = true
            
            // set Constraints
            setConstraints(height)
        }
        
        fileprivate func setConstraints(_ height: CGFloat) {
            self.translatesAutoresizingMaskIntoConstraints = false
            self.heightAnchor.constraint(equalToConstant: height).isActive = true
        }
    }
    
    0 回复  |  直到 6 年前