결합 및 CoreLocation, 2부 - 이벤트 수신 및 처리

In our previous post, Publisher Factory 또는 Publicist를 구축하는 방법에 대해 이야기했습니다. 이 게시물에서는 새로운 Publicist 클래스에서 ObservableObject의 이벤트를 수신하고 처리하는 방법에 대해 설명합니다.
  • Creating Publishers from Delegates
  • 함수 반응형 프로그래밍을 사용하여 값 변환
  • flatMap 및 기본 제공 게시자 이해

  • ObservableObject에서 이벤트 수신 및 처리



    우리ObservableObject는 CoreLocation 게시자의 말을 듣는 동안 SwiftUI를 업데이트하기 위해 몇 가지 작업을 수행해야 합니다. 우선 다음을 수행해야 합니다.
  • CoreLocation Manager 생성
  • CoreLocation 홍보 담당자 만들기
  • 홍보 담당자를 관리자의 대리인으로 연결
  • 승인 상태 및 위치 게시자 만들기

  • 이를 염두에 두고 보면 다음과 같습니다.

    class CoreLocationObject: ObservableObject {
      @Published var authorizationStatus = CLAuthorizationStatus.notDetermined
      @Published var location: CLLocation?
    
      let manager: CLLocationManager
      let publicist: CLLocationManagerCombineDelegate
    
      var cancellables = [AnyCancellable]()
    
      init() {
        let manager = CLLocationManager()
        let publicist = CLLocationManagerPublicist()
    
        manager.delegate = publicist
    
        self.manager = manager
        self.publicist = publicist
    
        let authorizationPublisher = publicist.authorizationPublisher()
        let locationPublisher = publicist.locationPublisher()
        ...
    
    

    다음으로 게시자로부터 이벤트를 수신하고 처리하는 작업을 실제로 처리할 수 있습니다. 먼저 CLAuthorizationStatus를 다루겠습니다.

    Sink 및 Assign으로 이벤트 수신 및 처리



    CLAuthorizationStatus까지 인증 상태가 변경될 때 수행해야 하는 두 가지 작업이 있습니다.
  • CLAuthorizationStatus가 유효한 경우 트리거 위치 업데이트
  • CLAuthorizationStatus@Published CLAuthorizationStatus 속성authorizationStatus에 할당

  • 메서드 호출에 싱크 사용



    먼저 해당 업데이트를 시작하는 메서드를 만들어 위치 업데이트 트리거를 처리해 보겠습니다.

    class CoreLocationObject: ObservableObject {
      @Published var authorizationStatus = CLAuthorizationStatus.notDetermined
      @Published var location: CLLocation?
    
      let manager: CLLocationManager
    
    ...
    
      func beginUpdates(_ authorizationStatus: CLAuthorizationStatus) {
        if authorizationStatus == .authorizedAlways || authorizationStatus == .authorizedWhenInUse {
          manager.startUpdatingLocation()
        }
      }
    }
    
    

    우리의 beginUpdate 메서드는 CLAuthorizedStatus에서 오는 대로 Publisher를 받아들입니다. 결과적으로 상태가 위치 업데이트를 허용하는 경우 startUpdatingLocation에서 CLLocationManager를 호출합니다.

    이를 염두에 두고 authorizationPublisherbeginUpdates 메서드에 연결해 보겠습니다.

    class CoreLocationObject: ObservableObject {
    
      ...
      var cancellables = [AnyCancellable]()
    
      init() {
        let publicist = CLLocationManagerPublicist()
    
        ...
    
        let authorizationPublisher = publicist.authorizationPublisher()
    
        // trigger an update when authorization changes
        authorizationPublisher
          .sink(receiveValue: beginUpdates)
          .store(in: &cancellables)
        ...
    
    

    이 경우 sink를 사용하고 새 메서드에 대한 참조를 전달합니다. sinkCancellable를 반환하며 제대로 처리되었는지 확인해야 합니다. 따라서 .store를 사용하여 Cancellablecancelables\ Array에 올바르게 저장되었는지 확인합니다.

    이제 권한이 부여되면 위치 업데이트를 올바르게 시작해야 합니다. 다음으로 CLAuthorizationStatus 속성에 @Published를 저장하여 SwiftUI 보기에 표시할 수 있도록 합니다.

    Assign으로 이벤트 수신 및 처리(iOS 13 및 iOS 14)



    UIKit을 사용하는 iOS 개발자로서 가장 먼저 배우는 것 중 하나는 메인 디스패치 큐에서 UI 업데이트를 만드는 것의 중요성입니다. 즉, 이 작업을 수행하지 않으면 잘못된 UI 업데이트가 발생하거나 앱이 충돌할 수도 있습니다. 마찬가지로 SwiftUI에서는 메인 디스패치 큐에서 UI 업데이트를 지정해야 합니다. 따라서 receive를 사용하여 업데이트가 기본DispatchQueue에 있는지 확인할 수 있습니다.

    ...
          authorizationPublisher
            // since this is used in the UI,
            //  it needs to be on the main DispatchQueue
            .receive(on: DispatchQueue.main)
            ...
    
    

    할당하는 한 몇 가지 옵션이 있습니다. sink를 사용하여 게시된 속성에 값을 할당할 수 있습니다.

    ...
          authorizationPublisher
            // since this is used in the UI,
            //  it needs to be on the main DispatchQueue
            .receive(on: DispatchQueue.main)
            .sink(receiveValue: {
              self.authorizationStatus = $0
            })
    ...
    
    

    그러나 assign를 사용하여 이를 단순화할 수 있습니다.

    ...
          authorizationPublisher
            // since this is used in the UI,
            //  it needs to be on the main DispatchQueue
            .receive(on: DispatchQueue.main)
            // store the value in the authorizationStatus property
            .assign(to: &$authorizationStatus)
    ...
    
    

    This new assign available in all the new 2020 OSes (iOS 14, macOS 11, watchOS 7, etc…)을 사용하면 &(in-out 매개변수용) 및 $(게시자용)를 사용하여 게시자에게 직접 값을 할당할 수 있습니다.

    또한 noCancellable가 반환되므로 저장할 필요가 없습니다.

    이벤트 수신 및 처리 시 싱크 대 할당





    올바른 방법을 선택하는 것은 어려울 수 있지만 다음은 몇 가지 지침입니다.
  • 값을 할당하는 것 외에 추가 논리를 수행하는 경우 sink를 사용하십시오.
  • 값만 할당하려면 assign를 사용하십시오.
  • UI(예: UIKit View 또는 SwiftUI View)에서 직접 사용 중인 값을 할당할 때 .receive(on: DispatchQueue.main) 을 사용합니다.
  • sink 또는 2019 version of assign (즉, assign(to:on:) )를 사용할 때 결과 Cancellableusing .store 으로 저장하십시오.
  • 하나 이상의 AnyCancellable 속성이 있는 경우 Set or Array for storing the Cancellables 사용을 고려하십시오.

  • 다음 블로그 게시물에서는 CLLocation를 더 유용한 것으로 변환할 때 Combine의 고급 함수형 프로그래밍 기술을 다룰 것입니다.

    좋은 웹페이지 즐겨찾기