Быстрое расширение UIColor для "невозможно присвоить значению:" self "является неизменным"

Я написал расширение UIColor изменить альфа напрямую:

public extension UIColor {

    public var rgbaComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
        var components: [CGFloat] {
            let c = cgColor.components!
            if c.count == 4 {
                return c
            }
            return [c[0], c[0], c[0], c[1]]
        }
        let r = components[0]
        let g = components[1]
        let b = components[2]
        let a = components[3]
        return (red: r, green: g, blue: b, alpha: a)
    }

    public var alpha: CGFloat {
        get {
            return cgColor.alpha
        }
        set {
            var rgba = rgbaComponents
            self = UIColor(red: rgba.red  // error here: "cannot assign to value: 'self' is immutable"
            , green: rgba.green, blue: rgba.blue, alpha: newValue)
        }
    }
}

но есть ошибка:

нельзя присвоить значению: "self" является неизменным

Но расширение даты для присваивания себе в порядке

public extension Date {

    public var day: Int {
        get {
            return Calendar.current.component(.day, from: self)
        }
        set {
            let allowedRange = Calendar.current.range(of: .day, in: .month, for: self)!
            guard allowedRange.contains(newValue) else { return }

            let currentDay = Calendar.current.component(.day, from: self)
            let daysToAdd = newValue - currentDay
            if let date = Calendar.current.date(byAdding: .day, value: daysToAdd, to: self) {
                self = date // This is OK
            }
        }
    }
}

Это из-за UIColor из NSObject а Date - это структура Swift? В чем причина?

1 ответ

Вы правы, потому что Date - это структура (тип значения), а UIColor - это класс (ссылочный тип).

Когда вы присваиваете себе для структуры, вы на самом деле просто обновляете все свойства этой структуры (проще говоря), чтобы фактическое расположение в памяти не менялось. Таким образом, вы на самом деле не мутируете ценность самого себя.

Однако, когда вы назначаете self для класса, вы создаете в памяти новый класс, поэтому, когда вы назначаете его себе, вы пытаетесь видоизменить себя. Даже если бы это было разрешено, как бы что-нибудь, содержащее ссылку на цвет, обрабатывало бы это, поскольку оно все равно будет содержать ссылку на исходный класс.

Другие вопросы по тегам