2016-12-06 1 views
2

CoreLocation을 사용하여 사용자의 현재 위치 (문자열)를 가져 오는 클래스 UserLocation (아래) & 위도 및 경도 API로 전달).계속 진행하기 전에 객체 인스턴스화를 기다려야합니다.

아래 코드는 작동하지만 클래스를 초기화 할 때 나머지 코드는 초기화가 완료 될 때까지 기다리지 않으므로 위치 관련 값을 할당 할 수 없습니다. 검색하려고합니다.

이 방법을 사용하면 (또는 다른 "MVC"조직에 대해 더 생각해야합니다.) 그렇다면 초기화를 위해 코드가 완료되도록하려면 어떻게해야합니까 (위치 찾기 & 역 지오 코딩). 계속 전진해라. 클래스의 init에 지정된 @ closure의 일종으로 초기화 아래에 코드를 두는 방법이 있습니까? 나는 신속하게 당신의 친절한 조언을 주셔서 감사합니다. ViewController.swift의 viewDidAppear()에서

:

let userLocation = UserLocation() // initializes properly but code below doesn't wait. 
locationsArray[0].name = userLocation.place 
locationsArray[0].coordinates = userLocation.coordinates 

그리고 내 UserLocation.swift 클래스 :

import Foundation 
import CoreLocation 

class UserLocation { 
    var place = "" 
    var coordinates = "" 

    let locationManager = CLLocationManager() 
    var currentLocation: CLLocation! 

    init() { 
     returnResults() 
    } 

    func returnResults() { 
     getUserLocation { placemark in 
      if placemark != nil { 
       self.place = (placemark?.name)! 
       self.coordinates = "\((placemark?.location?.coordinate.latitude)!),\((placemark?.location?.coordinate.longitude)!)" 
      } else { 
       print("Error retrieving placemark") 
      } 
     } 
    } 

    func getUserLocation(completion: @escaping (CLPlacemark?) ->()) { 
     var placemark: CLPlacemark? 

     locationManager.requestWhenInUseAuthorization() 

     if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse || 
      CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) { 
      currentLocation = locationManager.location 

      let geoCoder = CLGeocoder() 
      geoCoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) -> Void in 

       if error != nil { 
        print("Error getting location: \(error)") 
        placemark = nil 
       } else { 
        placemark = placemarks?.first 
       } 
       completion(placemark) 
      } 
     } 
    } 
} 

extension CLPlacemark { 
    var cityState: String { 
     var result = "" 
     switch (self.locality, self.administrativeArea, self.country) { 
     case (.some, .some, .some("United States")): 
      result = "\(locality!), \(administrativeArea!)" 
     case (.some, _ , .some): 
      result = "\(locality!), \(country!)" 
     default: 
      result = name ?? "Location Unknown" 
     } 
     return result 
    } 
} 

답변

2

이 반드시 스위프트 문제가되지 않습니다. 이 문제는 returnResults이 비동기식으로 변수 설정을 실행 함으로 인해 발생합니다. getUserLocation은 비동기식 인 reverseGeocodeLocation과 비동기입니다 (CoreLocation 작동 방식 - 동기식으로 위치를 가져 오지는 않지만 콜백에서).

이 초기화되고 위치를 확인하려고 시도하는 동안 returnResults이 주 스레드를 차단한다는 의미이므로 콜백을 실행하기를 기다리지 않으려 고합니다. 대신 returnResults이 위치 검색 완료를 알리는 완료 블록을 사용하여 비동기 패턴을 따라야합니다.

class UserLocation { 
    var place = "" 
    var coordinates = "" 

    let locationManager = CLLocationManager() 
    var currentLocation: CLLocation! 

    init() { 
     // don't call anymore from here, let the clients ask for the locations 
    } 

    // This was renamed from returnResults to a more meaningful name 
    // Using the Bool in the completion to signal the success/failure 
    // of the location retrieval 
    func updateLocations(withCompletion completion: @escaping (Bool) -> Void) { 
     getUserLocation { placemark in 
      if placemark != nil { 
       self.place = (placemark?.name)! 
       self.coordinates = "\((placemark?.location?.coordinate.latitude)!),\((placemark?.location?.coordinate.longitude)!)" 
       completion(true) 
      } else { 
       print("Error retrieving placemark") 
       completion(false) 
      } 
     } 
    } 
... 

그런 다음 이렇게 뭔가에 호출 코드를 수정할 수 있습니다 :

의 예 위의 것

let userLocation = UserLocation() 
userLocation.updateLocations { success in 
    guard success else { return } 
    locationsArray[0].name = userLocation.place 
    locationsArray[0].coordinates = userLocation.coordinates 
} 

당신은 메인 스레드를 차단하지 않으며, 당신은 실행 위치가 사용 가능할 때 적절한 코드.

+0

엄청난 감사 - 정확히 내가 필요로하는 것. 구문에 대한 아주 명확한 설명. 매우 감사! – Gallaugher

+0

@Gallaugher 기꺼이 도와 드리겠습니다. – Cristik

관련 문제