I am new with swift. For my project I need to use google geocoding and to put the result in a text. For the user interface I am using swiftUI. I tried to do the same with Completition Handler but that didn't work. Below I have the code done with DispatchQueue and DispatchGroup but the whole application freezes when I try to use this func. Please help me with this. The code for UI is just a Text calling the func.
func reverseGeocoding(lat: Double, lng: Double) -> String{
var place:String?
let url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=\(lat),\(lng)&key=KEY"
let group = DispatchGroup()
group.enter()
DispatchQueue.global(qos: .default).async {
AF.request(url).responseJSON{ response in
// group.leave()
guard let data = response.data else {
return
}
do {
let jsonData = try JSON(data: data)
let result = jsonData["results"].arrayValue
for result in result {
let address_components = result["types"].arrayValue
for component in address_components {
if(component == "locality"){
place = result["formatted_address"].stringValue
}
}
}
} catch let error {
print(error.localizedDescription)
}
}
}
group.wait()
return place ?? ""
}
continuation for @vadian answer
As mentioned in the above publisher depends on context .This will give you a rough idea.This is from what I understood..
// Replace String with [String] if you want to add multiple locations at once based on it Publisher.send() accepts [String] instead of String
var LocationPublisher = PassthroughSubject<String,Never>()
class Subscriber :ObservableObject {
@Published var currentLocation :[String] = Array<String>()
private var cancellebels = Set< AnyCancellable>()
func createSubscriber(){
let subscriber = LocationPublisher.handleEvents(
receiveSubscription: {subscription in
print("New subscription \(subscription)")},
receiveOutput: {output in
print("New Output \(output)")
},
receiveCancel: {
print("Subscription Canceled")
})
.receive(on: RunLoop.main)
// if you replace String with [String],TypeOf(value) becomes [String]
.sink{value in
print("Subscriber recieved value \(value)")
self.currentLocation.append(value)
// use self.currenLocation.append(contentsOf:value) instead
}
.store(in: &cancellebels)
}
init() {
createSubscriber()
}
}
And inside this contentView
struct ContentView: View {
@ObservedObject var locationObject:Subscriber = Subscriber()
var body: some View {
VStack{
List{
locationObject.currentLocation.forEach{ location in
Text(location)
}
}
}
}
}
and from the above answer inside the success completion handler use
LocationPublisher.send(location)
instead of print statement
it will be notified to subscribers and locationObject.currentLocation will be updated
Its just one way to do it and most basic way.