2017-02-15 1 views
0

내에서 FUNC를 호출하는 방법을, 나는 현재 도시의 이름을 얻을 시티. 그러나 self.currentCity = city은 클로저 내부에서 발생합니다. 그래서 난 그냥 뷰 컨트롤러에서 FUNC 실행하는 경우 :는 모델의 클래스 <code>Location</code>에서 클로저

func updateUI() { 
     cityLbl.text = Location.sharedInstance.currentCity 
} 
  • 폐쇄 실행이 완료되지 않았기 때문에 난 아무데도받지 못했습니다합니다. 완성 처리기를 getLocationName()에 추가하고 그 내부에 UI를 업데이트 할 func에 대한 호출을 수행하는 것이 좋습니다. 그러나 클로저, 완료 핸들러에 대한 모든 자습서에서부터 어떻게 달성해야하는지 명확하지 않습니다. 완성 처리기를 생성하는 방법은 getLocationName()에 arg로 전달하고 getLocationName을 뷰 컨트롤러에서 호출하는 방법은 무엇입니까?

답변

2

이 상황을 처리하려면 여러 가지 옵션이 있습니다. 당신의 위치 클래스

  1. 만들기 delegate/protocol

    • 는 하나의 프로토콜을 작성하고 ViewController와 해당 프로토콜의 메소드를 구현하고 Location 클래스의 인스턴스를 선언합니다. 그 후 completionHandlerreverseGeocodeLocation 인이 대리자 메서드를 호출하십시오. 자세한 내용은 Apple 설명서 (Protocol)를 확인하십시오.
  2. 당신은 Location 클래스의 당신의 getLocationName 방법 completionHandler을 만들 수 있습니다.

    • getLocationNamecompletionHandler을 추가라는 것을 이런 식으로 같은 reverseGeocodeLocationcompletionHandler 내부 completionHandler. ViewController에서 이제

      func getLocationName(completionHandler: @escaping (_ success: Bool) -> Void) { 
      
          let geoCoder = CLGeocoder() 
          let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude) 
      
          geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in 
           guard let addressDict = placemarks?[0].addressDictionary else { 
            completionHandler(false) 
            return 
           } 
           if let city = addressDict["City"] as? String { 
            self.currentCity = city 
            print(city) 
           } 
           if let zip = addressDict["ZIP"] as? String { 
            print(zip) 
           } 
           if let country = addressDict["Country"] as? String { 
            print(country) 
           } 
           completionHandler(true) 
           //self.nowUpdateUI() 
          }) 
      } 
      

      이 기능은 완료 블록 안에 당신의 updateUI 메소드를 호출 요구하고있다.

      Location.sharedInstance.getLocationName { (success) in 
          if success {//If successfully got response 
           self.updateUI() 
          } 
      } 
      
  3. 당신은 (NS)NotificationCenter에 대한 관찰자를 추가 할 수 있습니다

    .

    • (NS)NotificationCenter와 관찰자를 등록하고 reverseGeocodeLocationcompletionHandler 내부의 알림을 게시 할 수 있습니다. 자세한 내용은 StackOverflow Post으로 확인할 수 있습니다.
+0

번으로 문의하십시오. –

+0

그래, 아직 프로그래밍에 익숙하지 않아서, 당신이 제공하는 두 번째 옵션의 구현을 보여줄 수 있습니까? (updateUI()는 뷰 컨트롤러의 메소드이며 getLocationName이 구현 된 Location이 아닙니다.) –

+0

@Mr_Vlasov 따라서 메소드와 함께 completionHandler를 사용하려고합니다. 스위프트 3와 일하고 있습니까? –

0

코드의이 전체 조각 :

completionHandler: { placemarks, error in 
     guard let addressDict = placemarks?[0].addressDictionary else { 
      return 
     } 
     if let city = addressDict["City"] as? String { 
      self.currentCity = city 
      print(city) 
     } 
     if let zip = addressDict["ZIP"] as? String { 
      print(zip) 
     } 
     if let country = addressDict["Country"] as? String { 
      print(country) 
     } 

     self.nowUpdateUI() 
    } 

) 

가 (모든 것이 완성 된 후 발생)을 completionHandler에서 일어나는 이미 단지 또한 completionHandler 내부 updateUI() 당신을 실행합니다. 그래서 최종 코드는 다음과 같습니다

completionHandler: { placemarks, error in 
     guard let addressDict = placemarks?[0].addressDictionary else { 
      return 
     } 
     if let city = addressDict["City"] as? String { 
      self.currentCity = city 
      DispatchQueue.main.async { 
       updateUI() 
     } 
     } 
     if let zip = addressDict["ZIP"] as? String { 
      print(zip) 
     } 
     if let country = addressDict["Country"] as? String { 
      print(country) 
     } 

     self.nowUpdateUI() 
    } 

) 

당신이 당신의 completionHandler가 backgroundqueue에 있기 때문에 DispatchQueue.main가 사용해야하는 이유를하지만 당신은 당신은 당신의 mainQueue 이렇게 사용자의 관련 물건을 UI에서 가장 빠른 변화를받을 수 있나요 항상해야 자신의 UI가 이상없이. 상상해보십시오. 백그라운드 스레드에서 작업하고 느린 작업이 있었다고 상상해보십시오. 질문이 있으시면 언제든지 천천히

+0

하지만 updateUI()는 위치 레이블이 선언 된보기 컨트롤러의 기능입니다. View Controller의 인스턴스를 만들고 func을 호출해야합니까? –

+0

@Mr_Vlasov 알겠습니다. 아니, 그렇게해서는 안됩니다. ** Nirav D **에서 제안한 것을해야합니다. – Honey

0
// I thing issue back ground thread you need to update your UI in main thread 
var currentLatitude: Double! 
var currentLongitude: Double! 
var currentLocation: String! 
var currentCity: String! 

func getLocationName() { 

    let geoCoder = CLGeocoder() 
    let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude) 

    geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in 
     guard let addressDict = placemarks?[0].addressDictionary else { 
      return 
     } 
     if let city = addressDict["City"] as? String { 
      self.currentCity = city 
      print(city) 
     } 
     if let zip = addressDict["ZIP"] as? String { 
      print(zip) 
     } 
     if let country = addressDict["Country"] as? String { 
      print(country) 
     } 
     DispatchQueue.main.async { 
      self.nowUpdateUI() 
      // Update your UI in main thread 
     } 

    }) 
} 
관련 문제