You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI视图中if语句内函数调用无法终止问题求助

问题分析与解决方案

你的问题出在直接在View的body中执行imageAdd函数——SwiftUI的body会在任何状态/观察对象变化时重新计算,当你调用imageAdd修改imgArray(ObservedObject)时,会触发body再次刷新;即使你把image设为nil,ObservedObject的变化还是会让body重新执行,进而再次进入判断逻辑,导致无限循环。

另外你提到在imagePickerController里调用imageAdd无效,是因为ImagePickerView内部自己初始化了imgArray和imgAdded,这是全新的实例,和bottomButtons里的共享实例不是同一个,所以修改不会同步。


修复步骤

  1. 移除body中的判断逻辑,改用.onChange(of: image)监听图片选中事件,仅在图片被设置时执行一次imageAdd。
  2. 让ImagePickerView不再持有独立的imgArray和imgAdded实例,只负责传递选中的图片到外部的image绑定变量。

修正后的完整代码

struct bottomButtons: View {
    @State private var showImagePicker = false
    @State var image: UIImage?
    @State private var newImageChosen = false
    @ObservedObject var imgArray = imagesArray()
    @ObservedObject var imgAdded = imageAdded()
    
    var body: some View
    {
        HStack
        {
            // 相册选择按钮
            Button(action: {
                self.showImagePicker = true
            },
                   label: {
                Image(systemName: "photo")
            })
            .sheet(isPresented: $showImagePicker) {
                ImagePickerView(image: self.$image, showImagePicker: self.$showImagePicker, newImageChosen: self.$newImageChosen)
            }
            .scaleEffect(3.5)
            .tint(.black)
            .offset(x: -80)
            .padding()
            
            Button(action: {
                
            },
                   label: {
                Image(systemName: "camera.aperture")
            })
            .scaleEffect(4)
            .tint(.black)
            .padding()
            
            Button(action: {
                
            },
                   label: {
                Image(systemName: "arrowshape.right")
            })
            .scaleEffect(3.5)
            .tint(.black)
            .offset(x: 80)
            .padding()
            
        }
        .offset(y: 335)
        .frame(maxWidth: .infinity)
        // 监听image的变化,仅当image不为nil时执行添加逻辑
        .onChange(of: image) { newImage in
            guard let tempImage = newImage else { return }
            imageAdd(imgSource: tempImage, imgArray: imgArray, imgAdded: imgAdded)
            image = nil // 清空image,避免重复触发
        }
    }
}

struct ImagePickerView: UIViewControllerRepresentable {
    @Binding var image: UIImage?
    @Binding var showImagePicker: Bool
    @Binding var newImageChosen: Bool
    
    // 移除内部的imgArray和imgAdded实例,不需要在这里持有
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        imagePicker.sourceType = .photoLibrary
        imagePicker.delegate = context.coordinator
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
        // 无需更新
    }
    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePickerView
        
        init(_ parent: ImagePickerView) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                parent.image = image
                parent.newImageChosen = true // 可选:标记图片已选中
            }
            parent.showImagePicker = false
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.showImagePicker = false
        }
    }
}

func imageAdd(imgSource: UIImage, imgArray: imagesArray, imgAdded: imageAdded) {
    imgAdded.imgAdded = true
    imgArray.images.append(editableImg(id: imgArray.images.count, imgSrc: imgSource, size: [50, 80], scalar: 1.0))
    imgAdded.addIndex = imgArray.images.endIndex - 1
    imgAdded.imgAdded = false
    print("Image Added")
}

// 补充你用到的ObservedObject定义(方便参考)
class imagesArray: ObservableObject {
    @Published var images: [editableImg] = []
}

class imageAdded: ObservableObject {
    @Published var imgAdded: Bool = false
    @Published var addIndex: Int = 0
}

struct editableImg: Identifiable {
    let id: Int
    let imgSrc: UIImage
    let size: [CGFloat]
    let scalar: Double
}

关键说明

  • 使用.onChange(of: image)可以精准监听image变量的变化,只有当image被设置为新值(用户选中图片)时才执行一次添加逻辑,避免了body重绘导致的无限循环。
  • ImagePickerView只负责传递选中的图片到外部的绑定变量,不再持有独立的imgArray实例,确保修改的是共享的数据源。
  • 执行完imageAdd后将image设为nil,避免后续如果image再次被意外设置时重复触发逻辑。

内容的提问来源于stack exchange,提问作者Refactorizer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:02:55