How to use a completion handler to put an image in a SwiftUI view

Viewed 6168

I have tried this, but I didn't know how to use the results in a SwiftUI View:

func getProfilePicture(_ completion: @escaping ((UIImage) -> Void)) {

    Alamofire.request(GIDSignIn.sharedInstance()?.currentUser.profile.imageURL(withDimension: 75) ?? "https://httpbin.org/image/png").responseImage { response in

        if let image = response.result.value {
            completion(image)

        }
    }
}

If you can help, I would like to put the returned image from the completion handler in this view:

struct ProfileView: View {
let profileInfo = ProfileInfo()
var placeHolderImage = Image(systemName: "person")

var body: some View {
    Group {
            placeHolderImage
                .clipShape(Circle())
                .overlay(
                    Circle().stroke(Color.white, lineWidth: 4))
                .shadow(radius: 10)
                .padding(10)
    }

}

}

I would like this to return a UIImage so I can eventually use it in a SwiftUI view. I have already tried using a method with an @escaping completion handler, but I couldn't figure out how to use it to fix the issue. Thanks!

3 Answers

You can try something let this:

struct ProfileView: View {
    @State var placeHolderImage = Image(systemName: "person")


    var body: some View {
        Group {
            placeHolderImage
                .clipShape(Circle())
                .overlay(
                    Circle().stroke(Color.white, lineWidth: 4))
                .shadow(radius: 10)
                .padding(10)
        }.onAppear{
            getProfilePicture{ image in
                self.placeHolderImage = Image(uiImage: image)
            }
        }

    }

}

When ProfileView appears it will call getProfilePicture. The image specified in image in (when calling the function) is what the completion handler passes through (completion(image)). What you can then do is change your placeHolderImage to what you get in getProfilePicture, but before you do that you need to make your uiImage into an Image. Also make sure you add the @State keyword to your variable so once it changes your View is updated.

Hope that helps!

Use a completion handler as below,

func getProfilePicture(_ completion: @escaping ((UIImage) -> Void)) {

        Alamofire.request(GIDSignIn.sharedInstance()?.currentUser.profile.imageURL(withDimension: 75) ?? "https://httpbin.org/image/png").responseImage { response in

            if let image = response.result.value {
                completion(image)

            }
        }
    }
import SwiftUI

@available(macCatalyst 14.0, *)
@available(iOS 14.0, *)

struct MyUIView : View {
    
    // MARK: - Properties -
    
    @StateObject var myStore : MyStore = MyStore()
    @State var imgArray : Array<Image> = Array<Image>.init(repeating: Image("no-image"), count: 100)

    // MARK: - View -

    var body : some View {
        
        ScrollView {
                                        
            Text("IMAGES")

            LazyVStack (alignment: .leading, spacing: 8.0) {
                
                // actionPlans
                
                ForEach((0 ..< myStore.data.count).clamped(to: 0..<2), id: \.self) { i in
                    
                    HStack {
                        
                        let url = myStore.data[i]
                                       
                        let img : Image = imgArray[i]
                        
                        img
                            .resizable()
                            .scaledToFit()
                            .frame(width: 50, height: 50, alignment: .leading)
                            .padding(EdgeInsets(top: 0, leading: 0.0, bottom: 0, trailing: 16.0))
                            .onAppear(){
                            
                                imageFrom(url: url, completion: { image in
                                                                    
                                    imgArray[i] = Image(uiImage: image!)
                                                                            
                                })
                                
                            }
                                                    
                    }
                    
                    Divider()
                    
                }
                            
            }
                        
        }.onAppear(perform: {
            
            fetch()
            
        })
                
    }
    
    // MARK: - Media -

    private func fetch() {
        
        DispatchQueue.main.async {
            
            myStore.getData()

        }

    }
    
    func imageFrom(url: String, completion: @escaping (UIImage?) -> Void) {
        
        // image
                                
        if ImageLoader.sharedInstance.checkForImage(url: url as NSString?) {
            
            // has image
            
            completion(ImageLoader.sharedInstance.returnImage(url: url as NSString?)!)
            
        } else {
            
            ImageLoader.sharedInstance.getImage(url: url as NSString?) { (image) in
                                    
                if image != nil {
                    
                    completion(image)
                    
                } else {
                    
                    completion(UIImage.init(named: "no-image"))
                    
                }
                            
            }
            
        }
    }
    
}

@available(macCatalyst 14.0, *)
@available(iOS 14.0, *)

struct MyUIView_Previews: PreviewProvider {

    static var previews: some View {
        MyUIView()
    }

}
Related