问题
你好。我正在学习SwiftUI。
我尝试使用PHPickerController从图库中挑选多张照片,并显示多个视图,这些视图逐一表示每张照片。然而,每当我尝试访问vm.images
的任何索引时,都会发生致命错误。我该如何解决这个问题?
我的源代码如下
已解决
问题来自vm.images
,我认为.onChange
修改器是在所有图像都保存到vm.images
中之后操作的。但事实并非如此。
我在调用PickerTabView
时添加了if语句,解决了这个问题;相当简单的
// Added code
if let images = vm.images {
if images.count > 0 {
PickerTabView()
}
}
struct PickerTabView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
TabView {
if let images = vm.images{
ForEach(images, id: .self) { image in
PickerSettingView(image: image)
}
}
}
.tabViewStyle(.page)
}
}
struct ImagesPicker: UIViewControllerRepresentable {
@Binding var selectedImages: [UIImage]?
//var selectionLimit: Int
//var filter: PHPickerFilter?
var itemProvider: [NSItemProvider] = []
func makeUIViewController(context: Context) -> some PHPickerViewController {
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 20
configuration.filter = .images
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
func makeCoordinator() -> Coordinator {
return ImagesPicker.Coordinator(parent: self)
}
class Coordinator: NSObject, PHPickerViewControllerDelegate, UINavigationControllerDelegate {
var parent: ImagesPicker
init(parent: ImagesPicker) {
self.parent = parent
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
if !results.isEmpty {
parent.itemProvider = []
parent.selectedImages = []
}
parent.itemProvider = results.map(.itemProvider)
loadImage()
}
private func loadImage() {
for itemProvider in parent.itemProvider {
if itemProvider.canLoadObject(ofClass: UIImage.self) {
itemProvider.loadObject(ofClass: UIImage.self) { image, error in
DispatchQueue.main.sync {
if let image = image as? UIImage {
self.parent.selectedImages?.append(image)
}
}
}
}
}
}
}
}
struct PickerHomeView: View {
@EnvironmentObject var vm: ViewModel
@State private var isSelected = false
var body: some View {
NavigationView {
VStack {
NavigationLink("Tab View", isActive: $isSelected) {
PickerTabView()
}
.hidden()
HStack {
Button {
vm.showPicker()
} label: {
ButtonLabel(symbolName: "photo.fill", label: "Photos")
}
}
Spacer()
}
.sheet(isPresented: $vm.showPicker) {
ImagesPicker(selectedImages: $vm.images)
.ignoresSafeArea()
}
.onChange(of: vm.images, perform: { _ in
isSelected = true
})
}
}
}
struct PickerSettingView: View {
@EnvironmentObject var vm: ViewModel
var image: UIImage
let myImage = MyImage(category: Category.unCategorized)
@State private var selectedCategory: Category = Category.unCategorized
var body: some View {
VStack {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(minWidth: 0, maxWidth:.infinity)
SwiftUI.Picker("Category Picker", selection: $selectedCategory) {
Text("Formal").tag(Category.formal)
Text("Casual").tag(Category.casual)
Text("Semi Formal").tag(Category.semiFormal)
}
.pickerStyle(.segmented)
.padding([.leading, .trailing], 16)
HStack {
Button {
if vm.selectedImage == nil {
vm.addMyImage(category: selectedCategory, image: image)
} else {
vm.updateSelected()
}
} label: {
ButtonLabel(symbolName: vm.selectedImage == nil ? "square.and.arrow.down.fill" :
"square.and.arrow.up.fill",
label: vm.selectedImage == nil ? "Save" : "Update")
}
}
}
}
}
class ViewModel: ObservableObject {
@Published var images: [UIImage]?
@Published var showPicker = false
}
我认为loadImage
中的image
没有添加到self.parent.selectedImages
中当它为零时,也就是说,当ViewModel
中的images
为零时,就像开始时一样。因此,每当您尝试访问vm.images
中images
数组的任何索引时,应用程序都会崩溃。
您可以在loadImage
(也请注意.async
)中尝试添加图像:
DispatchQueue.main.async {
if let image = image as? UIImage {
if self.parent.selectedImages == nil { self.parent.selectedImages = [] }
self.parent.selectedImages!.append(image)
}
}