iOS 15中的ubieview单元格的高度约束的奇怪行为15

发布于 2025-02-11 04:58:25 字数 5867 浏览 1 评论 0原文

升级iOS 15后,我以前的代码开始工作很奇怪。

我有带有嵌入式视图的单元格的Uitable视图。当它在ViewDidload Cell的高度约束中加载时,我在情节板中设置的高度限制会变得活跃,并且单元格变得接近。点击单元格使高度约束变得不活跃并打开单元格。 foldView的高度约束

,但在iOS 15中,加载时始终打开。即使高度约束是活跃的。

在这里,我的代码使其打开或关闭:

var expanded: Bool = false {
        didSet {
            let duration = CATransaction.animationDuration()
            UIView.animate(withDuration: duration) {
                self.arrow.transform = self.expanded ? CGAffineTransform(rotationAngle: .pi / 2) :  .identity
               
                self.height.priority = .defaultHigh
                self.height.isActive = !self.expanded
                self.foldView.alpha = self.expanded ? 1 : 0
                self.container.layoutIfNeeded()
            }
            
        }
    }

这就是我添加嵌入式视图的方式:

func addEmbeddedView(_ view: UIView) {
        self.foldView.subviews.forEach { $0.removeFromSuperview() }
        self.foldView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        let constraints = [
            view.leadingAnchor.constraint(equalTo: self.foldView.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: self.foldView.trailingAnchor),
            view.topAnchor.constraint(equalTo: self.foldView.topAnchor),
            view.bottomAnchor.constraint(equalTo: self.foldView.bottomAnchor, constant: -9)
        ]
        constraints[3].priority = .defaultHigh
        NSLayoutConstraint.activate(constraints)
    }

但是!如果我从预期的所有作品中点击所有单元

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let cell = tableView.cellForRow(at: indexPath) as? TableViewCell else { return }
        tableView.beginUpdates()
        cell.expanded.toggle()
        tableView.fixCellBounds()
        tableView.endUpdates()
    }

,并且在iOS 15中也打开和关闭单元格。

有什么建议是什么? 正如我在iOS 15中的假设,自动层上的一些变化可能会影响我的代码。

在这里我的完整自定义单元类别:

import UIKit

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var headerLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!
    @IBOutlet weak var arrowImage: UIImageView!
    @IBOutlet weak var container: UIView!
    @IBOutlet weak var foldView: UIView!
    @IBOutlet weak var arrow: UIImageView!

    let layer1 = CALayer(), layer2 = CALayer(), layer3 = CALayer()

    var expanded: Bool = false {
        didSet {
            let duration = CATransaction.animationDuration()
            UIView.animate(withDuration: duration) {
                self.arrow.transform = self.expanded ? CGAffineTransform(rotationAngle: .pi / 2) :  .identity
               
                self.height.priority = .defaultHigh
                self.height.isActive = !self.expanded
         
                self.foldView.alpha = self.expanded ? 1 : 0
                self.container.layoutIfNeeded()
               
            }
            
        }
    }


    @IBOutlet weak var height: NSLayoutConstraint!
    override func awakeFromNib() {
        super.awakeFromNib()
        self.expanded = false
        
        
        container.layer.cornerRadius = 8
        container.layer.cornerCurve = .continuous
        container.backgroundColor = Colors_8_5.offWhite.color
        self.contentView.backgroundColor = .clear

        self.container.clipsToBounds = true
        self.contentView.clipsToBounds = false
        self.clipsToBounds = false
        self.selectionStyle = .none
        self.backgroundColor = .clear

        [layer1, layer2, layer3].forEach {
            $0.masksToBounds = false
            $0.backgroundColor = UIColor.clear.cgColor
            self.contentView.layer.insertSublayer($0, at: 0)
        }

        
    }

    func configure(with model: CustomCellModel) {
        self.headerLabel.attributedText = model.header
        self.descriptionLabel.attributedText = model.text
        self.descriptionLabel.isHidden = model.text == nil
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
    }

    func addEmbeddedView(_ view: UIView) {
        self.foldView.subviews.forEach { $0.removeFromSuperview() }
        self.foldView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        let constraints = [
            view.leadingAnchor.constraint(equalTo: self.foldView.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: self.foldView.trailingAnchor),
            view.topAnchor.constraint(equalTo: self.foldView.topAnchor),
            view.bottomAnchor.constraint(equalTo: self.foldView.bottomAnchor, constant: -9)
        ]
        constraints[3].priority = .defaultHigh
        NSLayoutConstraint.activate(constraints)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        [layer1, layer2, layer3].forEach {
            $0.frame = container.frame
        }

        layer1.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 4, blur: 8, spread: 0)
        layer2.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 16, blur: 24, spread: 0)
        layer3.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 24, blur: 32, spread: 0)

    }

}


extension CALayer {
    func CustomapplySketchShadow(
        color: UIColor = .black,
        alpha: Float = 0.2,
        x: CGFloat = 0,
        y: CGFloat = 2,
        blur: CGFloat = 4,
        spread: CGFloat = 0)
    {
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowOffset = CGSize(width: x, height: y)
        shadowRadius = blur / 2
        if spread == 0 {
            shadowPath = UIBezierPath(rect: self.bounds).cgPath
        } else {
            let dx = -spread
            let rect = bounds.insetBy(dx: dx, dy: dx)
            shadowPath = UIBezierPath(rect: rect).cgPath
        }
    }
}

After upgrade on IOS 15 my previous code start works strange.

I have UITableView with cells with embedded views. When it loads in viewDidLoad cell's height constrain that I setup in storyboard become active and cell become close. Tap on cell makes height constraint become not active and cell open.
Height constraint for foldView

But in IOS 15 cell always open when loading. Even if height constraint is active.

here my code that makes it open or close:

var expanded: Bool = false {
        didSet {
            let duration = CATransaction.animationDuration()
            UIView.animate(withDuration: duration) {
                self.arrow.transform = self.expanded ? CGAffineTransform(rotationAngle: .pi / 2) :  .identity
               
                self.height.priority = .defaultHigh
                self.height.isActive = !self.expanded
                self.foldView.alpha = self.expanded ? 1 : 0
                self.container.layoutIfNeeded()
            }
            
        }
    }

and this is how I add embedded view:

func addEmbeddedView(_ view: UIView) {
        self.foldView.subviews.forEach { $0.removeFromSuperview() }
        self.foldView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        let constraints = [
            view.leadingAnchor.constraint(equalTo: self.foldView.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: self.foldView.trailingAnchor),
            view.topAnchor.constraint(equalTo: self.foldView.topAnchor),
            view.bottomAnchor.constraint(equalTo: self.foldView.bottomAnchor, constant: -9)
        ]
        constraints[3].priority = .defaultHigh
        NSLayoutConstraint.activate(constraints)
    }

BUT! if I tap on cell from

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let cell = tableView.cellForRow(at: indexPath) as? TableViewCell else { return }
        tableView.beginUpdates()
        cell.expanded.toggle()
        tableView.fixCellBounds()
        tableView.endUpdates()
    }

all works as expected and cell open and close in IOS 15 too.

Any suggestions what it could be?
As I assume in IOS 15 was some changes in AutoLayout that may affect my code..

Here my full custom cell class:

import UIKit

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var headerLabel: UILabel!
    @IBOutlet weak var descriptionLabel: UILabel!
    @IBOutlet weak var arrowImage: UIImageView!
    @IBOutlet weak var container: UIView!
    @IBOutlet weak var foldView: UIView!
    @IBOutlet weak var arrow: UIImageView!

    let layer1 = CALayer(), layer2 = CALayer(), layer3 = CALayer()

    var expanded: Bool = false {
        didSet {
            let duration = CATransaction.animationDuration()
            UIView.animate(withDuration: duration) {
                self.arrow.transform = self.expanded ? CGAffineTransform(rotationAngle: .pi / 2) :  .identity
               
                self.height.priority = .defaultHigh
                self.height.isActive = !self.expanded
         
                self.foldView.alpha = self.expanded ? 1 : 0
                self.container.layoutIfNeeded()
               
            }
            
        }
    }


    @IBOutlet weak var height: NSLayoutConstraint!
    override func awakeFromNib() {
        super.awakeFromNib()
        self.expanded = false
        
        
        container.layer.cornerRadius = 8
        container.layer.cornerCurve = .continuous
        container.backgroundColor = Colors_8_5.offWhite.color
        self.contentView.backgroundColor = .clear

        self.container.clipsToBounds = true
        self.contentView.clipsToBounds = false
        self.clipsToBounds = false
        self.selectionStyle = .none
        self.backgroundColor = .clear

        [layer1, layer2, layer3].forEach {
            $0.masksToBounds = false
            $0.backgroundColor = UIColor.clear.cgColor
            self.contentView.layer.insertSublayer($0, at: 0)
        }

        
    }

    func configure(with model: CustomCellModel) {
        self.headerLabel.attributedText = model.header
        self.descriptionLabel.attributedText = model.text
        self.descriptionLabel.isHidden = model.text == nil
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
    }

    func addEmbeddedView(_ view: UIView) {
        self.foldView.subviews.forEach { $0.removeFromSuperview() }
        self.foldView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        let constraints = [
            view.leadingAnchor.constraint(equalTo: self.foldView.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: self.foldView.trailingAnchor),
            view.topAnchor.constraint(equalTo: self.foldView.topAnchor),
            view.bottomAnchor.constraint(equalTo: self.foldView.bottomAnchor, constant: -9)
        ]
        constraints[3].priority = .defaultHigh
        NSLayoutConstraint.activate(constraints)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        [layer1, layer2, layer3].forEach {
            $0.frame = container.frame
        }

        layer1.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 4, blur: 8, spread: 0)
        layer2.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 16, blur: 24, spread: 0)
        layer3.CustomapplySketchShadow(color: .black, alpha: 0.04, x: 0, y: 24, blur: 32, spread: 0)

    }

}


extension CALayer {
    func CustomapplySketchShadow(
        color: UIColor = .black,
        alpha: Float = 0.2,
        x: CGFloat = 0,
        y: CGFloat = 2,
        blur: CGFloat = 4,
        spread: CGFloat = 0)
    {
        shadowColor = color.cgColor
        shadowOpacity = alpha
        shadowOffset = CGSize(width: x, height: y)
        shadowRadius = blur / 2
        if spread == 0 {
            shadowPath = UIBezierPath(rect: self.bounds).cgPath
        } else {
            let dx = -spread
            let rect = bounds.insetBy(dx: dx, dy: dx)
            shadowPath = UIBezierPath(rect: rect).cgPath
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文