2017-12-26 5 views
1

사용자 장치의 위치를 ​​가져 오는 위치 관리자 클래스를 만들었습니다. 여기에서는 두 개의 성공과 실패를 사용했습니다. 나는이 클로저를 여러 클래스에서 사용한다. 하지만 한 클래스에서 클로저를 사용한 다음 다른 클래스에서 클로저를 호출하면 문제가 발생합니다. 위치를 사용할 수있는 여부를클로저가 여러 클래스로 호출 되었습니까?

LocationManager.shared.start() 
       LocationManager.shared.success = { location in 
         _ = LocationManager.shared.getAddressFromLocation(location: location, completion: { (address) in 
          Utility.shared.saveLocation(objCLLocatin: location.coordinate,address: address) 

         }) 
       } 

       LocationManager.shared.failure = { 
        DILog.print(items: "Failed location") 
        if $0.code == .locationPermissionDenied { 
         self.showPlacePicker() 
         return 
        } else { 
         Utility.shared.showNAlert(titleStr: $0.title, messageStr: $0.message, actionStr: ["Ok".localized], tag: "") 
         DILog.print(items: "other denied") 
        } 
       } 

실패 폐쇄는 내가 다른 클래스의 위치를 ​​확인하고 또한 경우에 다른 클래스를 호출하는 경우

class LocationManager: NSObject, CLLocationManagerDelegate { 

     static let shared = LocationManager() 

     let locationManager = CLLocationManager() 

     /// This is the clouser that will return the current Address through google login in 
     var success: (_ addrees: CLLocation) -> Void = { _ in } 

     /// This clouser will return the error 
     var failure: Failure = { _ in } 

     //MARK: - Permission Checks 
     internal var isEnabled: Bool { 
      switch CLLocationManager.authorizationStatus() { 
      case .authorizedAlways, .authorizedWhenInUse: return true 
      default: return false 
      } 
     } 

     private var notDetermined: Bool { 
      switch CLLocationManager.authorizationStatus() { 
      case .notDetermined: return true 
      default: return false 
      } 
     } 

     func start() -> Void { 
      locationManager.delegate = self 
      locationManager.desiredAccuracy = kCLLocationAccuracyBest 
      if isEnabled { 
       locationManager.startUpdatingLocation() 
      } else if notDetermined { 
       request() 
      } else { 
       failure(DIError.locationPermissionDenied) 
      } 
     } 
     func request() -> Void { 
      locationManager.requestWhenInUseAuthorization() 
     } 

     //MARK:Location Manager Delegate 
     func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
      if let currentLocation: CLLocation = manager.location { 
       self.success(currentLocation) 
      }else { 
       self.failure(DIError.locationPermissionDenied) 
      } 
      locationManager.stopUpdatingLocation() 
      locationManager.delegate = nil 

     } 

     func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { 
      failure(DIError.unKnowError()) 
     } 

     func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { 
      switch status { 
      case .notDetermined: 
       // If status has not yet been determied, ask for authorization 
       request() 
       break 
      case .authorizedWhenInUse: 
       // If authorized when in use 
       manager.desiredAccuracy = kCLLocationAccuracyBest 
       manager.startUpdatingLocation() 
       break 
      case .authorizedAlways: 
       // If always authorized 
       manager.desiredAccuracy = kCLLocationAccuracyBest 
       manager.startUpdatingLocation() 
       break 
      case .restricted: failure(DIError.locationPermissionDenied) 
      // If restricted by e.g. parental controls. User can't enable Location Services 
       break 
      case .denied: 
       failure(DIError.locationPermissionDenied) 
       // If user denied your app access to Location Services, but can grant access from Settings.app 
       break 
      } 
     } 
} 

폐쇄가 확인하기 위해 클래스에 사용됩니다. 그래서 하나의 클로저는 여러 클래스를 호출했습니다.

EDIT : I는 두 클래스 클래스 따라 성패 블록이라 제 제어기 & 체크 I에 위치 페치 & 클래스 B.이 . 나는 첫 번째 컨트롤러에서 두 번째 컨트롤러로 누른 다음 다시 현재 위치를 확인합니다. 만약 두 번째 컨트롤러에 즉. B. 그래서 실패 블록이 두 번째 컨트롤러에 대해 호출되면 첫 번째 컨트롤러에 대해서도 호출됩니다. 나는 왜 이런 일이 일어나는지 놀랍다.

답변

0

여러 클래스에 싱글 톤 클래스를 사용하는 경우 클로저가 매번 덮어 쓰기되어 success = ...으로 설정되고 마지막 하나만 호출되고 그 중 하나만이 마지막 클래스에 설정되고 그렇지 않은 경우에는 정상적인 동작입니다. 현재 클래스가 클로저를 사용하는 것

싱글 톤을 제거하거나 (각 클래스에 대해 다른 인스턴스를 생성) 사전 기반 처리기 (예 : [ "ClassName": successClosure])를 사용하십시오. 대리자를 사용하는 경우에는 위임자와 동일합니다. 또한 처리 클래스를 변경할 때마다 덮어 써야합니다.

+0

이 제안에 동의하지 않습니다. 어떤 이유 때문에 여러 클래스에서 사용하고 후속 작업에 대한 단일 참조를 갖는 싱글 톤은 모든 할당 된 사람을 기억하고 실패()를 수행 할 때마다 호출합니다. 마지막으로 할당 된 실패 종결자가 호출됩니다. –

+0

이것이 확실하지 않다고 생각합니다. 성공 및 실패 종결 클래스가있는 경우, 각각의 마지막 클래스 만 보유됩니다. 이제 그 클로저에 보관 된 다른 참조는 유지되지만 각 의지 중 가장 최근의 참조 만 호출되지는 않습니다. 그 외의 경우는 if의 나머지 인스턴스가 유효하거나 배열/핸들러 사전이 유효합니다. –

+0

내가 잘못 설명했는데 Closure가 덮어 쓰여질 것이고 마지막 하나만 호출되고 그 클래스는 Closure를 사용하는 현재 클래스가 아니라 마지막 클래스에 설정되어 있다고 생각한다. 이 상황으로하고있는 메신저 (다른 클래스를 기반으로 한 키보드 처리 클로저와 정확히 똑같은 것을 사용함) – Tj3n

관련 문제