當使用 Xcode 13.2.1 和 SwiftUI 來實作一個簡單的幻燈片時,我遇到了一個編譯時錯誤,其中 Xcode 在我的 M1 上需要大約 5 分鐘才能確定它無法決議我的代碼,并最終給了我錯誤:
編譯器無法在合理的時間內對該運算式進行型別檢查;嘗試將運算式分解為不同的子運算式
我將其縮小到靠近底部的 NavigationLink 行。如果我將其注釋掉,它會快速編譯并僅發出警告。
以下是我的最小可重現示例:
import SwiftUI
import Foundation
enum MarkerType: Double {
case unlabeled = -99
case end = -4
case start = -3
case stop = -2
case blank = -1
case image = 1
}
class LabeledImage {
let image: Image
let marker: Double
var appeared = false
init(image: Image, marker: Double) {
self.image = image
self.marker = marker
}
}
struct SlideShow {
private let maxImages: Int = 10000
var images = [LabeledImage]()
var labels = [String]()
var totalImages: Int { return self.images.count }
private var fromFolder: URL
init(fromURL: URL = Bundle.main.bundleURL.appendingPathComponent("Contents/Resources/DefaultImages")) {
self.fromFolder = fromURL
}
}
class AppState: ObservableObject {
static var docDir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
@Published var isMainMenuActive = false
@Published var loadFolder: URL = Bundle.main.bundleURL.appendingPathComponent("Contents/Resources/DefaultImages")
@Published var intervalSeconds: Double = 0.6
var saveFolder = URL(fileURLWithPath: "BCILab", relativeTo: docDir)
var labels = [String]()
var totalImages: Int = 0
var saveIndex: Int = 0
}
struct minsample: View {
@StateObject private var appState = AppState()
@State private var slideshow = SlideShow()
@State private var selection: Int = 0
private func insertAppears(_ marker: Double) {
let nmarker = marker 100.0
}
var body: some View {
NavigationView {
ForEach(0..<slideshow.images.count-1, id: \.self) { i in
let thisImage = slideshow.images[i].image
.resizable()
.aspectRatio(contentMode: .fit)
.onAppear(perform: { insertAppears(slideshow.images[i].marker) })
let nextImage = slideshow.images[i 1].image
.resizable()
.aspectRatio(contentMode: .fit)
.onAppear(perform: { insertAppears(slideshow.images[i 1].marker) })
NavigationLink(destination: nextImage, tag: i, selection: self.$selection) { thisImage }
}
}
}
}
uj5u.com熱心網友回復:
通常,使用基于索引的解決方案ForEach是個壞主意。它破壞了 SwiftUI 用于區分視圖的系統,并且還容易導致編譯時問題。
我會先做LabeledImage Identifiable:
class LabeledImage : Identifiable {
var id = UUID()
let image: Image
let marker: Double
var appeared = false
init(image: Image, marker: Double) {
self.image = image
self.marker = marker
}
}
(我也會把它變成一個struct——稍后會詳細介紹)
然后,由于您確實需要索引來實作您的nextImage功能,您可以.enumerated在集合上使用:
struct MinSample: View {
@StateObject private var appState = AppState()
@State private var slideshow = SlideShow()
@State private var selection: Int? = 0
private func insertAppears(_ marker: Double) {
let nmarker = marker 100.0
}
var body: some View {
NavigationView {
ForEach(Array(slideshow.images.enumerated()), id: \.1.id) { (index,imageModel) in
if index < slideshow.images.count - 1 {
let thisImage = imageModel.image
.resizable()
.aspectRatio(contentMode: .fit)
.onAppear(perform: { insertAppears(imageModel.marker) })
let nextImage = slideshow.images[index 1].image
.resizable()
.aspectRatio(contentMode: .fit)
.onAppear(perform: { insertAppears(slideshow.images[index 1].marker) })
NavigationLink(destination: nextImage, tag: index, selection: self.$selection) { thisImage }
} else {
EmptyView()
}
}
}
}
}
以上可以在我的 M1 上快速編譯,沒有任何問題。
現在,與您的問題沒有直接關系,但還有一些其他的事情我會改變:
- 制作你的模型
struct,SwiftUI 在進行狀態比較時通常會處理得更好 - 不要存盤對 SwiftUI
Image的參考——而是存盤對路徑的參考或以其他方式重新創建該影像。無論如何,這將使過渡LabeledImage更容易。struct因此,您的模型可能如下所示:
struct LabeledImage : Identifiable {
var id = UUID()
let imageName: String
let marker: Double
var appeared = false
}
- Consider whether or not you need the
tagandselectionparameters in yourNavigationLink-- perhaps it's just not clear in the minimal example why they're used.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/436435.html
下一篇:快速訪問列舉引數
