I'm stuck with an issue and need your help. I'm working on an app to manage events and when app loads, all the posts are displayed as expected both with or without images into the post. If I add a new post that contains an image it saves correctly and go back to the scrollview displaying the new post also if I edit any item which have an image and keep the image when saving or add an image into the post that had no image before editing it saves fine and post is displayed immediately into the scrollView. The issue is if I try to create a new post without an image or if I edit a post removing the image and saving, app crashes due to unwrapping option but the weird is that I'm checking nil value into the point of the scrollview where the image is displayed.
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)
}
Any ideas ? I'll really appreciate your support.
You have two force unwraps here. Your test for != nil
only protects the first; The attempt to access the item.pic
data. But, what if the conversion of that data to UIImage
fails? - The failable initialiser will return nil
, which you then force unwrap - which will lead to a crash.
A safer approach is to avoid all force unwraps. I would add a computed property to your model:
extension Item {
var image: Image? {
guard let data = self.pic, let uiImage = UIImage(data: data) else {
return nil
}
return Image(uiImage: uiImage)
}
}
Then you can just say:
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)
}
}
}
}
}
You could also encapsulate the whole ZStack
in a View
subclass to simplify things further
Rather than returning an optional Image
you could return a placeholder image; it's up to you.