2017-03-09 3 views
2

Je travaille sur la mise en œuvre de la capture d'écran d'une application Mac en appliquant CGDisplayStream, similaire à la question here, mais dans Swift.Utilisation de CGDisplayStream avec une file d'attente

est Ci-dessous le code que j'ai dans mon application unique ViewController de:

override func viewDidAppear() { 

    super.viewDidAppear() 

    let backgroundQueue = DispatchQueue(label: "com.app.queue", 
             qos: .background, 
             target: nil) 


    let displayStream = CGDisplayStream(dispatchQueueDisplay: 0, outputWidth: 100, outputHeight: 100,pixelFormat: Int32(k32BGRAPixelFormat), properties: nil, queue: backgroundQueue) { (status, code, iosurface, update) in 

     switch(status){ 
     case .frameBlank: 
      print("FrameBlank") 
      break; 
     case .frameIdle: 
      print("FrameIdle") 
      break; 
     case .frameComplete: 
      print("FrameComplete") 
      break; 
     case .stopped: 
      print("Stopped") 
      break; 
     } 

     self.update() 

    } 

    displayStream?.start() 

} 


func update(){ 
    print("WORKING") 
} 

Ce qui semble se produire est que le processus de file d'attente n'est pas initialisé correctement, mais je ne suis pas sûr ... quand l'application démarre, la self.update() est appelée une seule fois, mais une seule fois. Étant donné que le flux d'affichage a démarré correctement, je m'attendrais à ce que cette fonction soit appelée à plusieurs reprises, mais elle n'est appelée qu'une seule fois.

Vous avez des idées? Est-ce que je ne configure pas correctement une file d'attente?

Merci!

Répondre

2

Le problème est qu'aucune référence à displayStream est gardé à l'extérieur de viewDidAppear, de sorte que le flux sera désalloué sur le retour de cette méthode.

Faire une propriété du contrôleur de vue devrait résoudre le problème:

class ViewController: NSViewController { 

    var displayStream: CGDisplayStream? 

    override func viewDidAppear() { 
     super.viewDidAppear() 

     // ... 

     displayStream = CGDisplayStream(...) 
     displayStream?.start() 
    } 

    override func viewWillDisappear() { 
     super.viewWillDisappear() 
     displayStream?.stop() 
     displayStream = nil 
    } 

} 

Libérer le flux dans viewWillDisappear brise le conserver le cycle et permet au contrôleur de vue de désalloué (si elle fait partie de une voir la hiérarchie du contrôleur).

+0

Ouais, c'était exactement le problème. Je vous remercie! – narner

+0

Un autre piège avec des symptômes similaires qui m'a bloqué pendant un moment: le rappel du gestionnaire se déclenche seulement quand il y a des changements à l'affichage d'entrée. Donc, si vous êtes comme moi et que vous faites la plupart de votre travail sur un moniteur externe, le rappel peut ne pas se déclencher jusqu'à ce que vous déplaciez votre souris sur l'affichage que vous avez sélectionné comme affichage d'entrée. –