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
How to Change Audio Pitch During Playback? (Swift 4)
How to Test Asynchronous Methods Swift
How to Make High Score of Game to Be Saved on Leaderboard, with Swift
iOS Swift Error: 'T' Is Not Convertible to 'Mirrordisposition'
Limit Rectangle to Screen Edge on Drag Gesture
Swiftui on MACos, How to Use Custom Image Symbol on Button
How to Check the Type of a Variable Against Another Variable in Swift
Arkit - How to Display the Feed from a Virtual Scncamera Placed on Scnplane
Swift: Make Translucent Overlapping Lines of the Same Color Not Change Color When Intersecting
What Does This Two Question Mark Mean
How to Deal with Buffered Strings from C in Swift
Text Overlapping Itself in Table Cells Swift
Uitextview Draw Invisible/Whitespace Characters
How to Convert Data of Int16 Audio Samples to Array of Float Audio Samples
Swiftui: Using View Modifiers Between Different iOS Versions Without #Available
Sending an Email from Your App with an Image Attached in Swift