iOS14 CollectionView合成不再有效

问题描述

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

在iOS12和iOS13下,我的代码运行正常。但是从iOS14开始,我的CollectionView合成不再允许触摸事件。

自iOS14以来,我的代码发生了什么变化?

之前,我能够选择任何CollectionView'Composition元素,并且它的target-action可以工作。但是自从iOS14开始,没有按钮,没有UISwitch,触摸也没有任何反应!

这是我的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,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],onStates: [Bool]) {
        self.init(frame: frame)
        composeView(elementHeight: elementHeight,backgroundColor: backgroundColor,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,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),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,onStates: [Bool]) {
        self.init(frame: frame)
        self.titles = titles // needed for gesture callback
        composeStackView(elementHeight: elementHeight,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,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,icon: nil,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,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
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...