Kingfisher, обновляющий URL-адрес KFImage, не обновляет изображение в SwiftUI

#swift #swiftui #kingfisher

#swift #swiftui #kingfisher

Вопрос:

Извините за вопрос новичка, я пытаюсь перейти с UIKit на SwiftUI. didSet переменной @State не запускается, как в UIKit.

У меня есть KFImage, который загружает изображение из пользовательского photoUrl, и я хочу, чтобы оно при нажатии запускало средство выбора изображений, а затем обновляло userUIImage , но поскольку KFImage нуждается в обновлении URL-адреса, я не уверен, как я могу вызвать my updateUserImage() , чтобы обновить photoUrl для обновления KFImage.

Вот мой код ниже

 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)
            }
        }
    }
}
 

Ответ №1:

Попробуйте использовать onChange / onReceive вместо:

 KFImage(photoUrl)
    .resizable()
    // ...
    // remove .onSuccess implementation as self.userUIImage = result.image will result in an infinite loop
    .onChange(of: userUIImage) { newImage in
        updateUserImage()
    }
 

или

 import Combine
...
KFImage(photoUrl)
    .resizable()
    // ...
    .onReceive(Just(userUIImage)) { newImage in
        updateUserImage()
    }
 

Комментарии:

1. Привет, спасибо за ваш ответ. Запуск .onChange решил это для меня. Я отредактировал ваш ответ на то, что на самом деле сработало для меня, поскольку isImageLoaded было неправильно использовано. Хотя это моя вина, я должен был назвать его isImageInitiallyLoaded вместо этого