#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. Спасибо за решение, можете ли вы сказать мне причину, по которой это происходило, и как предотвратить это в будущем?