How to Use a Completion Handler to Put an Image in a Swiftui View

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

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!

How to use completionHandler response in swiftui?

You could create a subview that would take a search result (locationSearchService.searchResults[index]) as a parameter. And whose purpose would be to display the calculated distance.
The function that calculates the distance (getDistance) could be executed when this (each) subview appears (onAppear).
And the completion handler would update the state of this subview.

struct DistanceView: View {
@State private var distance: String?
let placeMarkLocation: MKLocalSearchCompletion
var body: some View {
Text(distance ?? "getting distance")
.onAppear {
getDistance(placeMarkLocation: placeMarkLocation, currentLocation: CLLocation(latitude: 47.2, longitude: -1.5)) { value in
distance = value
}
}
}
}

SwiftUI - Can I use a completion handler in Button action?

In your function you're not calling the completion parameter:

func getCityStateFromPostalCode(zip: String, completion: @escaping () -> ()) {
let geocoder = CLGeocoder()
var city = ""
var state = ""

geocoder.geocodeAddressString(zip) { (placemarks, error) in
if let placemark = placemarks?[0] {
if placemark.postalCode == zip {
city = placemark.locality!
state = placemark.administrativeArea!
self.city = city
self.state = state
}
}
completion() // <- add this (may be moved depending on the `error` parameter
}
}

How to display in a View a returned value from a completion handler in Swift?

Below is a Playground with a complete example. I'll walk through some of the important things to note.

First I simplified the "send" method since I don't have all the types and things from your original example. This send will wait 3 seconds then call the completion handler with whatever message you give it.

Inside the view, when the button is pushed, we call "send". Then, in the completion handler you'll notice:

DispatchQueue.main.async {
message = msg
}

I don't know what thread the Timer in send is going to use to call my completion handler. But UI updates need to happen on the main thread, so the DispatchQueue.main... construct will ensure that the UI update (setting message to msg) will happen on the main thread.

import UIKit
import SwiftUI
import PlaygroundSupport

func send(message: String, completionHandler: @escaping (String) -> Void) {
Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { timer in
completionHandler(message)
timer.invalidate()
}
}

struct ContentView: View {
@State var message : String = ""

var body: some View {
print("Building view")
return VStack {
TextField("blah", text: $message)
Button("Push Me", action: {
send(message: "Message Received") { msg in
DispatchQueue.main.async {
message = msg
}
}
})
}.frame(width: 320, height: 480, alignment: .center)
}
}

let myView = ContentView()
let host = UIHostingController(rootView: myView)
PlaygroundSupport.PlaygroundPage.current.liveView = host

SwiftUI - How to call function with completion from view model

Return city and state in the completion handler, not in the return:

func getCityStateFromPostalCode(zip: String, completion: @escaping ((String, String)) -> ()) {
let geocoder = CLGeocoder()
var city = ""
var state = ""

geocoder.geocodeAddressString(zip) { (placemarks, error) in
if let placemark = placemarks?[0] {
if placemark.postalCode == zip {
city = placemark.locality!
state = placemark.administrativeArea!
}
}
completion((city, state))
}
}

Then you can do:

settingsVM.getCityStateFromPostalCode(zip: companyZip) { city, state in
let newCompany = Company(context: self.moc)
newCompany.id = UUID()
newCompany.city = city
newCompany.state = state
}

How to call completion handler in list item in SwiftUI?

First, I'd move your async code to a view model. Then, use onAppear to call the async method to retrieve the cohorts. Then, you can use ForEach on the result stored in a Published variable:

class CohortRetriever : ObservableObject {
@Published var retrievedCohorts: [ProfilesInCohortModel.ProfilesArrayItem] = []

func retrieve(cohortItem: CohortArrayItem) {
self.usersInCohort(cohortItem: cohortItem) { result in
self.retrievedCohorts = result
}
}

private func usersInCohort(cohortItem: CohortArrayItem, completion:@escaping ([ProfilesInCohortModel.ProfilesArrayItem]?)->Void) {
let params = ["offset":6,"cohortWebID":cohortItem.cohort?.webID ?? ""] as [String : Any]

var request = URLRequest(url: URL(string: "url")!)
request.httpMethod = HTTPMethod.post.rawValue
request.httpBody = try? JSONSerialization.data(withJSONObject: params, options: [])
request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")


AF.request(request).responseDecodable(of: ProfilesInCohortModel.self) { (response) in
if response.response?.statusCode == 200{
completion(response.value?.profiles)
}
}
}
}

struct CohortItemView:View {
@State var cohortsGetter: ProfilesInCohort
let cohortItem:CohortArrayItem
@ObservedObject var profilesGetter = CohortProcessor()

@StateObject var retriever = CohortRetriever()

init(item:CohortArrayItem) {
self.cohortItem = item
self.cohortsGetter = ProfilesInCohort.init(cohortWebId: cohortItem.cohort?.webID ?? "")
}

var body: some View {
VStack{
HStack{
Text(cohortItem.cohort?.name ?? "no data")
.padding(.leading,10)
.multilineTextAlignment(.leading)
Spacer()

ZStack{
Text("Show all \(cohortItem.profilesNum!)")
}.padding(.trailing,10)
}

ScrollView(.horizontal, showsIndicators: false) {
HStack{
ForEach(retriever.retrievedCohorts) { user in //<-- Here
UserCard(user: UserModel(name: user.firstName ?? "", position: user.lastName ?? "", image: "moon.stars.fill"))
}
}.padding(10)
}
}.onAppear { //<-- Here
self.retriever.retrieve(cohortItem: cohortItem)
}
}
}

Note that I don't have all of your code, so there may be minor issues, like if your model doesn't conform to Hashable, you may have to pass an id: to ForEach.

Also, you could refactor retrieve to be one function without a callback -- you can see that I've wrapped usersInCohort. But, that's just busywork that you could do if you're interested.

Lastly, I'm not too sure what CohortProcessor does in your code -- it's initialized and then never used. Perhaps that code should be combined with my idea.

How can I put the Image in the background of a Form in SwiftUI?

You need to clear both the UITableView and the UITableViewCell appearance:

UITableView.appearance().backgroundColor = UIColor.clear
UITableViewCell.appearance().backgroundColor = UIColor.clear

Then, you can change the background as you wish:

struct ContentView: View {
init() {
UITableView.appearance().backgroundColor = UIColor.clear
UITableViewCell.appearance().backgroundColor = UIColor.clear
}

var body: some View {
Form {
Text("Item!")
.listRowBackground(Color.clear)
}
.background(
Image("Background")
)
}
}

(You also need .listRowBackground if you want to change the row background.)

Adding completion Handler to withAnimation in SwiftUI

Maybe just wrap your reset function to asyncAfter DispatchQueue with length of your animation?

DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
self.viewModel.resetGame()
}


Related Topics



Leave a reply



Submit