Невозможно присвоить свойству: 'self' - неизменная быстрая ошибка

Внутри своего приложения я создал протокол под названием «Positions» и расширил класс UIView, чтобы он соответствовал этому протоколу, чтобы добавить некоторые свойства в класс UIView. Я использовал приведенный ниже код.

import Foundation
import UIKit

protocol Positions {
    var initialPositions: [CGRect] {get set}
    var finalPositions: [CGRect] {get set}
    var positionsAreDefined: Bool {get}
}

public enum PositionsType {
    case initial
}

private var initialPositionKey: UInt = 0
private var finalPositionKey: UInt = 0

extension Positions {
    var initialPositions: [CGRect] {
        get {
            if objc_getAssociatedObject(self, &initialPositionKey) != nil {
                return objc_getAssociatedObject(self, &initialPositionKey) as! [CGRect]
            } else {
                return [] as! [CGRect]
            }

        }
        set {
            objc_setAssociatedObject(self, &initialPositionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    var finalPositions: [CGRect] {
        get {
            if objc_getAssociatedObject(self, &finalPositionKey) != nil {
                return objc_getAssociatedObject(self, &finalPositionKey) as! [CGRect]
            } else {
                return [] as! [CGRect]
            }
        }

        set {
            objc_setAssociatedObject(self, &finalPositionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    var positionsAreDefined: Bool {
        get {return initialPositions.count != 0 && finalPositions.count != 0 && initialPositions.count == finalPositions.count}
    }

    var positionsCount: Int {
        get {return initialPositions.count}
    }
}

extension UIView: Positions {}

Итак, сегодня я попытался расширить класс UIView новым методом, который изменяет добавленные мной свойства, но компилятор выдал мне эту ошибку в строке, где я пытался изменить значение свойств:

Cannot assign to property: 'self' is immutable

Вот способ:

public func horizontallyInContainer(withShift shift: CGFloat, forExpansionNumber index: Int, forPositionType type: PositionsType) {
    if self.positionsAreDefined && self.superview != nil {
        if type == .initial {

            var newPositions = self.initialPositions
            newPositions[index].origin.x = self.superview!.bounds.width * 0.5 - self.bounds.width + shift
            self.initialPositions = newPositions //Here happens the error

        } else {

            var newPositions = self.finalPositions
            newPositions[index].origin.x = self.superview!.bounds.width * 0.5 - self.bounds.width + shift
            self.finalPositions = newPositions //Also here happens

        }
    }
}

Может ли кто-нибудь объяснить мне природу этой ошибки?

Протоколы, не связанные с классом, имеют семантику значений, поэтому любые изменяющие функции должны быть объявлены с помощью модификатора mutating, как если бы они находились внутри определения структуры.

Alexander 09.10.2018 20:38

Если вы собираетесь использовать objc_getAssociatedObject и другие функции времени выполнения Objective C, вам необходимо сделать этот протокол привязанным к классу. В противном случае это сработает, но вы заметите странное поведение. Структуры помещаются в __SwiftValue, который может использоваться средой выполнения ObjC, но у них нестабильная идентификация объекта. Идентичность объекта - это то, что среда выполнения ObjC использует в качестве ключей в своей таблице связанных объектов.

Alexander 09.10.2018 20:40

@Carcigenicate Я отредактировал свой пост

Lorenzo Santini 09.10.2018 20:53

@Alexander, вы предлагаете мне поставить ключевое слово "mutating" перед объявлением метода "HorizontallyInContainer"?

Lorenzo Santini 09.10.2018 20:54

@Alexander Можете ли вы объяснить мне, как я могу сделать этот протокол привязанным к классу?

Lorenzo Santini 09.10.2018 20:56

Это то, что показывает @vadian в своем ответе.

Alexander 09.10.2018 21:31

Да, я видел ... спасибо тебе тоже

Lorenzo Santini 09.10.2018 21:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
7
5 465
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сделать протокол эталонным типом

protocol Positions: AnyObject {

Хорошо, спасибо, это работает ... Можете ли вы объяснить мне, что это делает, и, может быть, указать мне на то, что я могу прочитать об этом, просто для того, чтобы снова не упасть на ту же ошибку? :)

Lorenzo Santini 09.10.2018 21:01

Это обсуждается в Swift Language Guide: протоколы, однако в самой последней версии рекомендуется соответствовать AnyObject, а не абстрагироваться от class.

vadian 09.10.2018 21:17

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