Как в Swift отследить момент копирования структуры?

Ответ

Прямого механизма для отслеживания автоматического копирования структур (copy-on-write) в Swift не существует. Однако можно реализовать кастомное копирование с логированием.

Практические подходы:

  1. Кастомный метод копирования:

    struct TrackableStruct {
        var id: Int
    
        func copied() -> TrackableStruct {
            print("Создана копия структуры с id: (id)")
            return TrackableStruct(id: self.id)
        }
    }
    
    let original = TrackableStruct(id: 1)
    let copy = original.copied() // Логируется
  2. Для классов с протоколом NSCopying:

    class MyClass: NSCopying {
        var data: String
    
        init(data: String) { self.data = data }
    
        func copy(with zone: NSZone? = nil) -> Any {
            print("Копирование MyClass")
            return MyClass(data: self.data)
        }
    }

Важно: Swift использует оптимизацию copy-on-write для стандартных типов и собственных структур. Явное копирование происходит только при изменении одной из переменных, ссылающихся на одни и те же данные. Отследить это системное поведение без модификации низкоуровневого кода невозможно.

Ответ 18+ 🔞

А, слушай, вот тут такой прикол, блядь. Хочешь подсмотреть, как твои структуры в Swift копируются на лету, эта самая copy-on-write магия? Так вот, хуй тебе, а не прямой механизм! Система это всё делает тихо, по-английски, чтобы твой код не бздел лишний раз.

Но если прям приперло и надо понять, где эта сука-оптимизация срабатывает, можно наколхозить свои костыли, блядь.

Смотри, как быдлокодеры выкручиваются:

  1. Свой метод, ручной, блядь, внатуре: Ты просто делаешь свою функцию копирования и там вставляешь логирование. Просто как три копейки, но зато видно.

    struct TrackableStruct {
        var id: Int
    
        func copied() -> TrackableStruct {
            print("Создана копия структуры с id: (id)") // Вот, бля, смотришь в консоль и рыдаешь
            return TrackableStruct(id: self.id)
        }
    }
    
    let original = TrackableStruct(id: 1)
    let copy = original.copied() // И тут оно бабахнет в лог
  2. Для этих, своих классов, если ты вдруг на них переполз: Тут уже можно NSCopying прикрутить, это как старый дедовский способ, но работает.

    class MyClass: NSCopying {
        var data: String
    
        init(data: String) { self.data = data }
    
        func copy(with zone: NSZone? = nil) -> Any {
            print("Копирование MyClass") // И опять логируем, ёпта!
            return MyClass(data: self.data)
        }
    }

Но запомни главное, чувак: сам Swift, этот хитрожопый компилятор, для своих стандартных типов и твоих структур использует оптимизацию copy-on-write. Это значит, что реальное копирование данных происходит только тогда, когда одна из переменных начинает менять эти общие данные. А отследить эту внутреннюю кухню без того, чтобы лезть в кишки системы, — нихуя не возможно. Так что либо верь на слово, либо ставь свои костыли, как выше.