SwiftUI - GeometryReader 崩溃 SIGABRT
SwiftUI - GeometryReader crashes SIGABRT
我正在尝试根据设备宽度实现两种不同的视图。因此,此视图的 iPad 版本应该与 iPhone 版本不同。为此,我使用 GeometryReader 检查宽度。但是,应用程序总是因“Thread 1: signal SIGABRT”而崩溃。
每一个关于他们自己的观点都很好。
如果我在 iPad 的分屏中启动它,宽度小于 592,它工作正常。之后能不崩溃而改为大尺寸。如果以大于 592 的宽度开始,它会崩溃。
此外,如果我只使用 if 语句而不使用 else,它也可以。
即使是在 top 上的测试也会崩溃。
这是我的代码:
import SwiftUI
struct DetailView: View {
let food: FoodList
@State var showRightMenu = false
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
// Test
if bounds.size.width > 592 {
Text("Test")
} else {
Text("Test1")
Text("Test2")
}
// Actual code
// if bounds.size.width > 592 {
// HStack {
// FoodDetailPadViewLeft(food: self.food)
// .frame(width: bounds.size.width / 2)
//
// FoodDetailPadViewRight(food: self.food)
// }
// } else {
// ScrollView {
// FoodDetailViewImage(food: self.food)
// .animation(.none)
//
// FoodDetailViewNutris(food: self.food)
//
// Spacer()
// }
// }
HStack {
BackButton()
Spacer()
InfoButton(showRightMenu: self.$showRightMenu)
}
}
.background(Color("background"))
.edgesIgnoringSafeArea(.all)
.navigationBarTitle("")
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
这是一些可重现的代码:
import SwiftUI
struct ContentView: View {
@State var foodlist: [FoodList] = Bundle.main.decode("ingredientsList.json")
var body: some View {
NavigationView {
List {
ForEach(foodlist) { food in
NavigationLink (destination: TestView(food: food)) {
Text(food.name)
}
}
}
}
}
}
struct TestView: View {
let food: FoodList
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
if bounds.size.width > 592 {
Text(self.food.name)
} else {
Text(self.food.name)
Text(self.food.category)
}
}
}
}
}
struct FoodList: Codable, Identifiable, Hashable {
let id: Int
let category: String
let name: String
}
extension Bundle {
func decode<T: Codable>(_ file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data (contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
和Json-文件:
[
{
"id": 1,
"category": "vegetables",
"name": "Tomato",
},
{
"id": 2,
"category": "vegetables",
"name": "Potato",
}
]
有什么想法吗?
在这种情况下,最好明确检查您需要什么:
var body: some View {
ZStack (alignment: .topLeading) {
if UIDevice.current.userInterfaceIdiom == .pad {
Text(self.food.name)
} else {
Text(self.food.name)
Text(self.food.category)
}
}
}
注意:崩溃是由于堆栈上的布局更改而发生的,这是因为 GeometryReader
在同一布局堆栈上获得了不同的值(第一轮是 .zero,第二轮它是真实的),所以你的条件的不同分支在同一个布局堆栈上被激活,这让 SwiftUI 渲染引擎变得疯狂。 (你可以向 Apple 提交反馈,但很难解决,因为它是 chicken-egg 问题 - 几何 reader 总是走两次)。
不确定这是否是正确的解决方案,但当宽度大于 592 时,我使用不透明度来隐藏视图。
目前似乎可以工作。
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
Text(self.food.name)
.opacity(bounds.size.width > 592 ? 0 : 1)
VStack {
Text(self.food.name)
Text(self.food.category)
}
.opacity(bounds.size.width <= 592 ? 0 : 1)
}
}
}
我正在尝试根据设备宽度实现两种不同的视图。因此,此视图的 iPad 版本应该与 iPhone 版本不同。为此,我使用 GeometryReader 检查宽度。但是,应用程序总是因“Thread 1: signal SIGABRT”而崩溃。 每一个关于他们自己的观点都很好。
如果我在 iPad 的分屏中启动它,宽度小于 592,它工作正常。之后能不崩溃而改为大尺寸。如果以大于 592 的宽度开始,它会崩溃。
此外,如果我只使用 if 语句而不使用 else,它也可以。
即使是在 top 上的测试也会崩溃。
这是我的代码:
import SwiftUI
struct DetailView: View {
let food: FoodList
@State var showRightMenu = false
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
// Test
if bounds.size.width > 592 {
Text("Test")
} else {
Text("Test1")
Text("Test2")
}
// Actual code
// if bounds.size.width > 592 {
// HStack {
// FoodDetailPadViewLeft(food: self.food)
// .frame(width: bounds.size.width / 2)
//
// FoodDetailPadViewRight(food: self.food)
// }
// } else {
// ScrollView {
// FoodDetailViewImage(food: self.food)
// .animation(.none)
//
// FoodDetailViewNutris(food: self.food)
//
// Spacer()
// }
// }
HStack {
BackButton()
Spacer()
InfoButton(showRightMenu: self.$showRightMenu)
}
}
.background(Color("background"))
.edgesIgnoringSafeArea(.all)
.navigationBarTitle("")
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
这是一些可重现的代码:
import SwiftUI
struct ContentView: View {
@State var foodlist: [FoodList] = Bundle.main.decode("ingredientsList.json")
var body: some View {
NavigationView {
List {
ForEach(foodlist) { food in
NavigationLink (destination: TestView(food: food)) {
Text(food.name)
}
}
}
}
}
}
struct TestView: View {
let food: FoodList
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
if bounds.size.width > 592 {
Text(self.food.name)
} else {
Text(self.food.name)
Text(self.food.category)
}
}
}
}
}
struct FoodList: Codable, Identifiable, Hashable {
let id: Int
let category: String
let name: String
}
extension Bundle {
func decode<T: Codable>(_ file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data (contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
和Json-文件:
[
{
"id": 1,
"category": "vegetables",
"name": "Tomato",
},
{
"id": 2,
"category": "vegetables",
"name": "Potato",
}
]
有什么想法吗?
在这种情况下,最好明确检查您需要什么:
var body: some View {
ZStack (alignment: .topLeading) {
if UIDevice.current.userInterfaceIdiom == .pad {
Text(self.food.name)
} else {
Text(self.food.name)
Text(self.food.category)
}
}
}
注意:崩溃是由于堆栈上的布局更改而发生的,这是因为 GeometryReader
在同一布局堆栈上获得了不同的值(第一轮是 .zero,第二轮它是真实的),所以你的条件的不同分支在同一个布局堆栈上被激活,这让 SwiftUI 渲染引擎变得疯狂。 (你可以向 Apple 提交反馈,但很难解决,因为它是 chicken-egg 问题 - 几何 reader 总是走两次)。
不确定这是否是正确的解决方案,但当宽度大于 592 时,我使用不透明度来隐藏视图。
目前似乎可以工作。
var body: some View {
GeometryReader { bounds in
ZStack (alignment: .topLeading) {
Text(self.food.name)
.opacity(bounds.size.width > 592 ? 0 : 1)
VStack {
Text(self.food.name)
Text(self.food.category)
}
.opacity(bounds.size.width <= 592 ? 0 : 1)
}
}
}