SwiftUI: [Неизвестное имя процесса] CGAffineTransformInvert: ошибка сингулярной матрицы

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Ожидание: анимация загрузки зеленой точки при нажатии на значок сердца

Результат: ничего не происходит, кажется, что он зависает, поскольку анимация сердца также не работает

Ошибка: [Неизвестное имя процесса] CGAffineTransformInvert: сингулярная матрица.

Скриншот приложения (нерабочее состояние)

Код:

 struct ContentView: View {
    @State private var count=0
     @State var isPressed = false
    @State var pressed = false
    @State var isLoading = false
    var body: some View {
       
        VStack {
            ZStack{
                Circle()
                    .fill( isPressed ? Color(.systemGray4) : .red )
                    .overlay(Image(systemName:"heart.fill")
                        .foregroundColor(isPressed ? .red :.white)
                        .font(.system(size:100))
                        
                        .scaleEffect( pressed ? 1.5 : 1.0)
                )
                .frame(width: 300, height: 300)
                
                
            }
            
            .onTapGesture{
                self.isLoading.toggle()
                withAnimation(.spring(response: 1,dampingFraction: 0.4, blendDuration :0.9)){
                self.isPressed.toggle()
                    self.pressed.toggle()
                    self.isLoading.toggle()
                }
                
            }
        
    
            HStack{
                ForEach(0...4, id: .self){index in
                    Circle()
                        .frame(width:10,height:10)
                        .foregroundColor(.green)
                        .scaleEffect(self.isLoading ? 1:0)
                        .animation(Animation.linear(duration:0.6).repeatForever().delay(0.2*Double(index)))
                }
            }

        .padding()

            
    }
    
    }
    
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

  

Примечание: Загрузка анимации работает, когда я не переключаю isLoading переменную состояния внутри onTapGesture() блока и напрямую устанавливаю ее в значение true, когда вид появляется внутри onAppear() блока

Ответ №1:

Причина :

Проблема в основном в CGAffinTransform

Когда вы используете модификатор ScaleEffect для своего представления, в фоновом режиме компилятор выполняет некоторые короткие преобразования для предоставленного вами значения масштаба.

Поскольку вы указали значение 0 (ноль) для .scaleEffect (), оно принимает размер за ноль и обрабатывает его как сингулярную матрицу (это тип матрицы, определитель которой равен нулю). и это также считается математическим нарушением для выполнения операций над матрицами с определителем, равным нулю.

РЕШЕНИЕ :

Убедитесь, что если вы используете .scaleEffect() , не масштабируйте представление с точностью до 0. Вы можете использовать наименьшее возможное значение, то есть 0,1 или 0,01

Комментарии:

1. Если вам нужно очень маленькое ненулевое значение, вы можете использовать CGFloat.ulpOfOne

Ответ №2:

Проблема заключается в 0 эффекте масштабирования.

Вот исправленный код. Протестировано с Xcode 11.4 / iOS 13.4. Также исправлена анимация для случая isLoading = false

ДЕМОНСТРАЦИЯ

 struct ContentView: View {
    @State private var count=0
    @State var isPressed = false
    @State var pressed = false
    @State var isLoading = false
    var body: some View {

        VStack {
            ZStack{
                Circle()
                    .fill( isPressed ? Color(.systemGray4) : .red )
                    .overlay(Image(systemName:"heart.fill")
                        .foregroundColor(isPressed ? .red :.white)
                        .font(.system(size:100))

                        .scaleEffect( pressed ? 1.5 : 1.0)
                )
                .frame(width: 300, height: 300)
            }
            .onTapGesture{
                self.isLoading.toggle()
                withAnimation(.spring(response: 1,dampingFraction: 0.4, blendDuration :0.9)){
                    self.isPressed.toggle()
                    self.pressed.toggle()
                }
            }

            HStack{
                ForEach(0...4, id: .self){index in
                    Circle()
                        .frame(width:10,height:10)
                        .foregroundColor(.green)
                        .scaleEffect(self.isLoading ? 1:0.01)
                        .animation(self.isLoading ? Animation.linear(duration:0.6).repeatForever().delay(0.2*Double(index)) :
                            .default
                        )
                }
            }
            .padding()
        }
    }
}
  

Комментарии:

1. Спасибо за решение, можете ли вы сказать мне причину, по которой это происходило, и как предотвратить это в будущем?