-1

我遇到了一个问题,需要你的帮助。我正在开发一个应用程序来管理事件,当应用程序加载时,所有帖子都会按预期显示,无论是否有图像进入帖子。如果我添加一个包含图像的新帖子,它会正确保存并返回到显示新帖子的滚动视图,如果我编辑任何有图像的项目并在保存时保留图像或将图像添加到没有图像的帖子中在编辑之前它保存得很好,并且帖子立即显示到滚动视图中。问题是如果我尝试创建没有图像的新帖子,或者如果我编辑删除图像并保存的帖子,应用程序由于展开选项而崩溃,但奇怪的是我正在将 nil 值检查到滚动视图的位置显示图像。

ScrollView {
            VStack(spacing: 15){
                ForEach(items, id: \.self) { item in
                    VStack(spacing: 15) {
                        if item.pic != nil {
                            
                            ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
                                
                                Image(uiImage: UIImage(data: item.pic!)!)
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .cornerRadius(15)
                            }
                            .padding()
                            .opacity(1)
                        }

有任何想法吗 ?我将非常感谢您的支持。

4

1 回答 1

1

这里有两个强制展开。您的测试!= nil仅保护第一个;item.pic访问数据的尝试。但是,如果该数据转换UIImage失败怎么办?- 可失败的初始化程序将返回nil,然后您强制解包 - 这将导致崩溃。

一种更安全的方法是避免所有力展开。我会在您的模型中添加一个计算属性:

extension Item {
    var image: Image? {
        guard let data = self.pic, let uiImage = UIImage(data: data) else {
            return nil
        }
        return Image(uiImage: uiImage)
    }
}

然后你可以说:

ScrollView {
    VStack(spacing: 15){
        ForEach(items, id: \.self) { item in
            VStack(spacing: 15) {
            if let image = item.image {
                ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
                    image
                     .resizable()
                     .aspectRatio(contentMode: .fill)
                     .cornerRadius(15)
                 }
                  .padding()
                  .opacity(1)
                }
            }
        }
    }
}

您还可以将整体封装ZStack在一个View子类中以进一步简化事情

Image您可以返回一个占位符图像,而不是返回一个可选项;由你决定。

于 2020-12-24T01:36:33.160 回答