Sorry for beginner question, I am trying to transition from UIKit to SwiftUI. @State variable's didSet does not get triggered like it does in UIKit.
I have KFImage that loads an image from a user's photoUrl and I want it when tapped, launches image picker, then update the userUIImage
but since KFImage needs a url to be updated, I am not sure how I can call my updateUserImage()
to update the photoUrl to update KFImage.
Here' my code below
struct ProfileView: View {
//MARK: Properties
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
@State private var isImageLoaded: Bool = false
@State private var showImagePicker = false
@State private var photoUrl: URL? = URL(string: (Customer.current?.photoUrl)!)
@State private var userImage: Image? = Image(uiImage: UIImage())
@State private var userUIImage: UIImage? = UIImage() {
didSet {
if isImageLoaded {
updateUserImage()
}
}
}
var body: some View {
KFImage(photoUrl)
.resizable()
.onSuccess { result in
self.userUIImage = result.image
self.isImageLoaded = true
}
.aspectRatio(contentMode: .fill)
.frame(width: screenWidth / 2.5)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
.onTapGesture { self.showImagePicker = true }
.sheet(isPresented: $showImagePicker) {
CustomImagePickerView(sourceType: .photoLibrary, image: $userImage, uiImage: $userUIImage, isPresented: $showImagePicker)
}
}
//MARK: Methods
func updateUserImage() {
CustomerService.updateUserImage(image: userUIImage!) { (photoUrl, error) in
if let error = error {
handleError(errorBody: error)
return
}
guard var user = Customer.current else { return }
self.photoUrl = photoUrl
user.photoUrl = photoUrl?.absoluteString
CustomerService.updateUserDatabase(user: user) { (error) in
if let error = error {
handleError(errorBody: error)
return
}
Customer.setCurrent(user, writeToUserDefaults: true)
}
}
}
}
Try using onChange
/ onReceive
instead:
KFImage(photoUrl)
.resizable()
// ...
// remove .onSuccess implementation as self.userUIImage = result.image will result in an infinite loop
.onChange(of: userUIImage) { newImage in
updateUserImage()
}
or
import Combine
...
KFImage(photoUrl)
.resizable()
// ...
.onReceive(Just(userUIImage)) { newImage in
updateUserImage()
}