Here is my DemoView
:
struct ImageCropData: Identifiable {
var id = UUID()
var image: UIImage?
}
typealias CropImageHandler = (UIImage) async throws -> String
struct DemoView: View {
@State private var data: ImageCropData?
var body: some View {
VStack {
Button {
data = ImageCropData(image: nil)
} label: {
Text("abc")
}
}
.demo(data: $data) { image in
print("do anything with image") // I need this block called everytime, no matter what ios system is in use
return ""
}
}
}
extension View {
func demo(data: Binding<ImageCropData?>, completion: @escaping CropImageHandler) -> some View {
modifier(DemoModifier(croppingData: data, completion: completion))
}
}
struct DemoModifier: ViewModifier {
@Binding var croppingData: ImageCropData?
var completion: CropImageHandler
func body(content: Content) -> some View {
if #available(iOS 17.0, *) {
content
.fullScreenCover(item: $croppingData) { data in
Text("Example View")
}
} else {
// content
// .task {
// Task {
// print("different behavior")
// if let image = croppingData?.image {
// _ = try await completion(image)
// }
// }
// }
// What should I do here to return content and call completion immediately when iOS is 16.4 and lower.?
}
}
}
Simply when demo modifier is called I need two things:
- If iOS is 17 or more then display another View and care about completion inside. That is ok and works✅
- If iOS is 16.4 or less then return just that View and immediately call completion with given image. You might consider there always is an image. How can I achieve that?
else
clause.else
is not called and not working directly. I can replace nil with any UIImage value. It will also not work.task
only runs once per lifetime of the view. In this case it runs before you have set thecroppingData
to non-nil. Do you want it to run whenevercroppingData
changes to non-nil?