Как передавать данные между двумя наблюдаемыми объектами в SwiftUI - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть следующие настройки:

MainView

API Class

API - это Observed Object на главном экране, и все работает хорошо.

Я хотел бы добавить в уравнение LocationManager Class, и смог бы сделать это как еще Observed Object и View обновления при получении обновлений местоположения.

Что бы я хотел как делать, и не уверен, что правильный путь - передать местоположение в API class для использования в вызове API.

Что такое рекомендуемый поток выполнения этого.

1 My View

struct TempMainView: View {


    @ObservedObject var api = APIFetcher()
    @ObservedObject var locationMan = LocationMan()

    // HOW TO MAKE API CALL ONCE LOCATION IS KNOWN

    var body: some View {

        Text(api.sampleText)

    }

}

2 My API Class

public class APIFetcher: ObservableObject {

    @Published var sampleText: String = "Local"

    init() {
        self.load()
    }

    func load(){

        //
        // HIT API without LOCATION
        //

        let url = URL(string: "https://example.com/api/nolocation")!

        URLSession.shared.dataTask(with: url) {(data,response,error) in
            do {
                if let d = data {
                    let decoder = JSONDecoder()
                    decoder.dateDecodingStrategy = .secondsSince1970
                    let newString = try decoder.decode(String.self, from: d)
                    DispatchQueue.main.async {
                        self.sampleText = newString
                    }
                }
            } catch {
                print ("Error - \(error)")
            }

        }.resume()
    }

    func loadWithCoordinates(){

        let coordinates: CLLocationCoordinate2D

        //
        // HIT API with LOCATION
        // (HOW TO CALL THIS WHEN THERE IS A KNOWN LOCATION)
        //

        let stringFromCoordinates = String("\(coordinates.longitude),\(coordinates.latitude)")

        let url = URL(string: "https://example.com/api/location/\(stringFromCoordinates)")!

            URLSession.shared.dataTask(with: url) {(data,response,error) in
                do {
                    if let d = data {
                        let decoder = JSONDecoder()
                        decoder.dateDecodingStrategy = .secondsSince1970
                        let newString = try decoder.decode(String.self, from: d)
                        DispatchQueue.main.async {
                            self.sampleText = newString
                        }
                    }
                } catch {
                    print ("Error - \(error)")
                }

            }.resume()
    }
}

3 Location Manager Class

class LocationManager: NSObject, ObservableObject {

    private let locationManager = CLLocationManager()

  @Published var location: CLLocation? {
    willSet { objectWillChange.send() }
  }

  override init() {
    super.init()

    self.locationManager.delegate = self
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
    self.locationManager.requestWhenInUseAuthorization()
    self.locationManager.startUpdatingLocation()
  }




}
extension LocationManager: CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        //
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        guard let location = locations.last else { return }
        self.location = location
        //
    }
}

1 Ответ

0 голосов
/ 07 февраля 2020

Я бы просто прислушивался к отправке уведомлений. Для ясности я удалил ошибочный код обработки ответа URL:

struct TempMainView: View {
  @ObservedObject var api = APIFetcher()
  var locationMan = LocationManager()
  let locationChange = NotificationCenter.default.publisher(for: .location)
  var body: some View {
    Text(api.sampleText)
      .onReceive(locationChange) { note in
        let loc = note.userInfo!["location"]! as! CLLocation
        self.api.loadWithCoordinates(coordinates: loc.coordinate)
    }
  }
}
public class APIFetcher: ObservableObject {
  @Published var sampleText: String = "Local"
  init() {
    self.load()
  }
  func load(){
    let url = URL(string: "https://example.com/api/nolocation")!
    URLSession.shared.dataTask(with: url) {(data,response,error) in
      DispatchQueue.main.async {
        self.sampleText = "loaded w/o location"
      }
    }.resume()
  }

  func loadWithCoordinates(coordinates: CLLocationCoordinate2D){
    let stringFromCoordinates = String("\(coordinates.longitude),\(coordinates.latitude)")
    let url = URL(string: "https://example.com/api/location/\(stringFromCoordinates)")!
    URLSession.shared.dataTask(with: url) {(data,response,error) in
      DispatchQueue.main.async {
        self.sampleText = "loaded from \(stringFromCoordinates)"
      }
    }.resume()
  }
}

class LocationManager: NSObject, ObservableObject {
  private let locationManager = CLLocationManager()
  override init() {
    super.init()
    self.locationManager.delegate = self
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
    self.locationManager.requestWhenInUseAuthorization()
    self.locationManager.startUpdatingLocation()
  }
}
extension Notification.Name {
  static let location = Notification.Name("location")
}
extension LocationManager: CLLocationManagerDelegate {
  func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
  }
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let location = locations.last else { return }
    let note = Notification(name: .location, object: nil, userInfo: ["location": location])
    NotificationCenter.default.post(note)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...