Swiftui - Unwrap Optional Image Data to Create Image Based on Uiimage(Data)

SwiftUI - Unwrap optional image data to create Image based on UIImage(data)

You have a few options available. I think the most straightforward is to make an extension on Image and define a new initialiser that will serve your needs:

extension Image {

public init?(data: Data?) {
guard let data = data,
let uiImage = UIImage(data: data) else {
return nil
}
self = Image(uiImage: uiImage)
}
}

Then you can simply use it like this:

Image(data: userService.user.imageData)

since it is nullable it needs to be contained in another View with at least one other View.

If you want to provide a placeholder in place of a missing image you could use an extension like this:

extension Image {

public init(data: Data?, placeholder: String) {
guard let data = data,
let uiImage = UIImage(data: data) else {
self = Image(placeholder)
return
}
self = Image(uiImage: uiImage)
}
}

Then you can simply use it like this:

Image(data: userService.user.imageData, placeholder: "nameOfPlaceholder")

since it is not nullable it doe not need to be contained in another View with at least one other View.

How to unwrap an optional list of type Images in SwiftUI

The simplest direct answer to this is to use the same ?? operator you mentioned to provide an empty array:

struct ContentView : View {
@State var list_of_images : [Image]? = nil

var body: some View {
ForEach(0..<(list_of_images ?? []).count) {
list_of_images?[$0]
.resizable()
.aspectRatio(contentMode: .fill)
}
}
}

However, I'd be concerned in general about the idea of storing the Images themselves. I might look into another way of storing references to them (paths? names? UIImages?) that could be iterated over instead. In that case, you could do something like this:

struct ContentView : View {
@State var imageNames : [String]? = nil

var body: some View {
ForEach(imageNames ?? [], id: \.self) { imageName in
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fill)
}
}
}

This approach doesn't work with the array of Images because Image doesn't conform to Identifiable

Update, based on comments:

struct ContentView : View {
@State var images : [UIImage]? = nil

var body: some View {
ForEach(images ?? [], id: \.self) { image in
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
}
}
}

How to use published optional properties correctly for SwiftUI

Below is an extension of Binding you can use to convert a type like Binding<Int?> to Binding<Int>?. In your case, it would be URL instead of Int, but this extension is generic so will work with any Binding:

extension Binding {
func optionalBinding<T>() -> Binding<T>? where T? == Value {
if let wrappedValue = wrappedValue {
return Binding<T>(
get: { wrappedValue },
set: { self.wrappedValue = $0 }
)
} else {
return nil
}
}
}

With example view:

struct ContentView: View {
@StateObject private var model = MyModel()

var body: some View {
VStack(spacing: 30) {
Button("Toggle if nil") {
if model.counter == nil {
model.counter = 0
} else {
model.counter = nil
}
}

if let binding = $model.counter.optionalBinding() {
Stepper(String(binding.wrappedValue), value: binding)
} else {
Text("Counter is nil")
}
}
}
}

class MyModel: ObservableObject {
@Published var counter: Int?
}

Result:

Result

How to unwrap an Optional Binding and pass value to another view?

You don't need boundModel for such body, use instead

var body: some View {
if selectedModel == nil {
Text("Kindly select a value in the list to start editing.")
} else {
EditModelView(model: Binding(selectedModel)!) // << here !!
}
}


Related Topics



Leave a reply



Submit