2017-12-14 3 views
0

타사 라이브러리의 알림에 의해 호출되는 대리자 메서드가 2 개 있습니다.변수가 설정되지 않은 경우 변수가 설정 될 때까지 기다립니다.

방법 1 : mediaContentWasUpdated()

방법 2 방법 1에서, 키 변수 (adDuration)은 통지와 함께 전달 된 파라미터로부터 설정 adMediaDidBeginPlaying()

. 내가 알 수있는 한,이 정보를 얻을 수있는 유일한 곳입니다.

방법 2에서는 adDuration을 확인하고 0보다 큰 경우 사실 우리가 광고를 반영하도록 UI를 업데이트합니다.

때때로이 두 메서드가 잘못된 순서로 호출되는 버그가 나타납니다. adDuration이 설정되지 않았 음을 의미하고, 방법 2는 재생할 광고 미디어가 없다고 생각하고 이에 따라 UI를 업데이트하지 않습니다.

현재 해결책으로는 adDuration을 선택 사항으로 만들고 NSCondition을 사용하여 방법 2가 방법 1이 adDuration으로 설정 될 때까지 대기 한 다음 계속 진행합니다.

var adDuration : Double? 
let condition = NSCondition() 

func mediaContentWasUpdated(notification: NSNotificiation) { 
    condition.lock() 

    if(notificationHasAdDurationInfo(notification)) { 
     self.adDuration = getAdDuration(notification) 
     condition.signal() 
    } 

    condition.unlock() 
} 

func adMediaDidBeginPlaying(notification: NSNotification) { 
    condition.lock() 

    while adDuration == nil { 
     condition.wait() 
    } 

    if adDuration! > Double(0) { 
     updateUIForAd() 
    } 

    condition.unlock() 
} 

이것은 처음 시도한 것입니다. 제가 잘못 생각하고 있습니다. 또한 불필요하게 스레드를 잠 그거나 잠금 해제하는 것에 대한 우려가 있습니다 (시간 초과 실행시 또는 재생할 광고 컨텐트가없는 경우).

외부 요인이 테스트 능력을 저해하고 있으며 문제 해결을 기다리는 동안 올바른 방향으로 가고 있는지 알기 위해 몇 가지 정보를 얻고 싶었습니다.

+2

왜 첫 번째 메소드에서 'adDuration'을 얻은 후에 두 번째 메소드를 호출하지 않는 것이 좋을까요? –

+0

@SanthoshR 두 번째 방법은 알림 위임 메서드이기도합니다. 재생할 광고가있는 경우에만 호출해야합니다. – Conor

+0

첫 번째 메소드에서 'adDuration'이 0보다 큰 경우 광고가 있음을 의미하므로 가짜 알림을 사용하여 두 번째 메소드를 호출 할 수 있습니다. –

답변

1

NSCondition에 대한 토론에서 나와 같은 길을 가졌고, DispatchGroup (이것에 대한 더 나은 도구 임)을 사용하여 2 ~ 3 개의 솔루션을 만들었지 만, 그들은 항상 나쁜 행동을 할 수있는 작은 코너 케이스를 가지고있었습니다. 정말 의도를 포착하지 않습니다.

(당신이 DispatchGroup 솔루션에 관심이 있다면, 그들은 형태의 위치 :. 재생이 시작되면 그것은 잘 작동 notify() 전화, 기간이 오면 .leave() 전화, init에서 .enter()를 호출하지만 코너를 소개합니다 . 단지 NSCondition처럼 충돌 할 경우)

다시 진정한 의도에 도착 :

업데이트 UI 기간이 알려져 있고, 광고가 재생되기 때.

여기에는 동시성이 없습니다. 따라서 GCD를 꺼내는 것은 과도하지 않습니다. 복잡한 코너 케이스가 많이 생기기 때문에 실제 상황이 악화됩니다.

그래서 나는 GCD 전에 이것을 어떻게 풀어 냈는지 생각했습니다. 그리고 대답은 명백합니다. 원하는 데이터가 있는지 확인한 다음 작업을 수행하십시오. (의견을 통해 읽으면, Paulw11이 이것을 지적했다.)

개인적으로 나는 이런 종류의 것을 자신의 유형으로 끌어내어보다 독립적 인 것을 만들어 가고 싶다.여기 이름의 일부를 싫어하지만, 생각은 명확해야한다 : 각 일을 설정하면 업데이트 준비하는 경우, 참조

class AdPlayer { 
    private var readyToPlay = false 
    private var duration: Double = 0.0 
    private let completion: (Double) -> Void 

    func setDuration(from notification: Notification) { 
     if(notificationHasAdDurationInfo(notification)) { 
      duration = getAdDuration(notification) 
     } 
     playIfReady() 
    } 

    func play() { 
     readyToPlay = true 
     playIfReady() 
    } 

    private func playIfReady() { 
     if duration > 0 && readyToPlay { 
      completion(duration) 
     } 
    } 

    init(completion: @escaping (Double) -> Void) { 
     self.completion = completion 
    } 
} 

, 만약 그렇다면, 갱신. 의도는 "0 지속 시간은 항상 잘못된 것"이라고 생각하기 때문에 선택 사항도 제거했습니다. 그러나 선택적으로 사용할 수 있으므로 알림에서 실제로 0을 수신하는 것을 감지 할 수 있습니다. 그와

, 당신은 단지 플레이어 속성 설정 :

player = AdPlayer(completion: updateUIForAd) 

((가) 위가 updateUIForAd이 무엇인지에 따라 루프를 유지 생성 될 수 있습니다를, 당신이 [weak self] 폐쇄 또는 여기에 등을해야 할 수도 있습니다 . 필요에 따라)

그리고 다음 업데이트 :

func mediaContentWasUpdated(notification: NSNotificiation) { 
    player.setDuration(from: notification) 
} 

func adMediaDidBeginPlaying(notification: NSNotification) { 
    player.play() 
} 

AdPlayer 유형을 만드는 큰 장점이 있다는 것입니다 광고가 완료되었을 때 (또는 무언가 잘못되었을 때) 시스템을 쉽게 재설정 할 수 있습니다. 그냥 전체 개체를 버리고 다른 개체를 만듭니다.

관련 문제