Что такое модификатор matchedGeometryEffect в SwiftUI?

«Что такое модификатор matchedGeometryEffect в SwiftUI?» — вопрос из категории SwiftUI, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

matchedGeometryEffect — это модификатор в SwiftUI, который создает плавную анимацию плавного перемещения и изменения размера view между разными позициями в иерархии.

Принцип работы: Вы помечаете две (или более) view как «совпадающие», указывая одинаковые пространство имен (namespace) и идентификатор (id). При изменении условий (например, в if или switch) SwiftUI автоматически анимирует переход одной view в другую, а не простое появление/исчезновение.

Базовый пример (анимация переключения размера):

struct ContentView: View {
    @Namespace private var namespace // 1. Создаем пространство имен
    @State private var isExpanded = false

    var body: some View {
        VStack {
            if isExpanded {
                // 2. View в большом состоянии
                RoundedRectangle(cornerRadius: 16)
                    .matchedGeometryEffect(id: "shape", in: namespace) // Совпадающий ID
                    .frame(width: 200, height: 200)
                    .foregroundColor(.blue)
            } else {
                // 3. View в маленьком состоянии (может быть в другом месте VStack)
                RoundedRectangle(cornerRadius: 16)
                    .matchedGeometryEffect(id: "shape", in: namespace) // Тот же ID
                    .frame(width: 100, height: 100)
                    .foregroundColor(.blue)
            }
            Button("Анимировать") { isExpanded.toggle() }
        }
        .animation(.spring(), value: isExpanded)
    }
}

Ключевые параметры:

  • id: Hashable — уникальный идентификатор для связи view.
  • in: Namespace.ID — пространство имен, ограничивающее область связи.
  • properties: MatchedGeometryProperties — какие свойства анимировать (.frame, .position и др.).
  • anchor: UnitPoint — точка привязки для совмещения view.

Важные ограничения:

  • Работает только внутри одного ViewBuilder (например, внутри одного body).
  • Если view с совпадающим id исчезает из иерархии, анимация прерывается.
  • Часто комбинируется с transition для более сложных эффектов.