ios – ExpressibleByIntegerLiteral with parameter pack “Cannot convert value of type ‘Int’ to expected argument type”


I’m trying to create an extension for the UIView helping to activate the constraints easily.

Using the new Swift 5.9 feature Parameter Pack, I have the value of the constraint that confirms to ExpressibleByIntegerLiteral and the active function tasks parameter pack of UIViewConstraint.

protocol UIViewConstraint {
    
    associatedtype Anchor: AnyObject
    
    var anchor: NSLayoutAnchor<Anchor>? { get }
    var attribute: NSLayoutConstraint.Attribute { get }
    var value: UIView.ConstraintValue { get }
}

extension UIView {
    
    struct Constraint<Anchor: AnyObject>: UIViewConstraint {
        
        var anchor: NSLayoutAnchor<Anchor>?
        var attribute: NSLayoutConstraint.Attribute
        var value: UIView.ConstraintValue
    }
}

extension UIViewConstraint where Anchor == NSLayoutYAxisAnchor {
    
    static func top(_ value: UIView.ConstraintValue, to anchor: NSLayoutYAxisAnchor? = nil) -> UIView.Constraint<NSLayoutYAxisAnchor> {
        UIView.Constraint(anchor: anchor, attribute: .top, value: value)
    }
    
    static func bottom(_ value: UIView.ConstraintValue, to anchor: NSLayoutYAxisAnchor? = nil) -> UIView.Constraint<NSLayoutYAxisAnchor> {
        UIView.Constraint(anchor: anchor, attribute: .bottom, value: value)
    }
}

extension UIView {
   
    struct ConstraintValue {
        
        var constant: CGFloat
    }
}

extension UIView.ConstraintValue: ExpressibleByIntegerLiteral {
    
    init(integerLiteral value: Int) {
        self.init(constant: CGFloat(value))
    }
}

extension UIView {
    
    func active<each Anchor>(_ constraint: repeat UIView.Constraint<each Anchor>) {
        (repeat _active(each constraint))
    }
    
    func active2<each Constraint: UIViewConstraint>(_ constraint: repeat each Constraint) {
        (repeat _active(each constraint))
    }
    
    private func _active<T: UIViewConstraint>(_ anchor: T) {
        //
    }
}

When I tried to pass an int literal to the generic functions active(_:) or active2(_:) I got an error Cannot convert value of type ‘Int’ to expected argument type ‘UIView.ConstraintValue’.

But creating an object from ‘UIView.Constraint‘ directly works fine.

let superView = UIView()
let view = UIView()

superView.addSubview(view)
view.active(
    .top(10), // ❌ Cannot convert value of type 'Int' to expected argument type 'UIView.ConstraintValue'
    .bottom(20) // ❌ Cannot convert value of type 'Int' to expected argument type 'UIView.ConstraintValue'
)

view.active2(
    .top(10), // ❌ Cannot convert value of type 'Int' to expected argument type 'UIView.ConstraintValue'
    .bottom(20) // ❌ Cannot convert value of type 'Int' to expected argument type 'UIView.ConstraintValue'
)

let top: UIView.Constraint<NSLayoutYAxisAnchor> = .top(10) // ✅
let bottom: UIView.Constraint<NSLayoutYAxisAnchor> = .bottom(20) // ✅
view.active(top, bottom) // ✅
view.active2(top, bottom) // ✅

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img