0

I have Swift code:

    func makeSceenshot() {
        // Set up the inputs
        var displayCount: UInt32 = 0;
        var result = CGGetActiveDisplayList(0, nil, &displayCount)
        if (result != CGError.success) {
            print("error when try to get displays: \(result)")
            return
        }
        let allocated = Int(displayCount)
        let activeDisplays = UnsafeMutablePointer<CGDirectDisplayID>.allocate(capacity: allocated)
        result = CGGetActiveDisplayList(displayCount, activeDisplays, &displayCount)
        
        if (result != CGError.success) {
            print("error whe try get displays list: \(result)")
            return
        }
        
        for i in 1...displayCount {
            // Set up the input
            let display: CGDirectDisplayID = activeDisplays[Int(i-1)]
            guard let input = AVCaptureScreenInput(displayID: display) else {
                    print("error AVCaptureScreenInput")
                    return
            }
            input.minFrameDuration = CMTimeMake(value: 1, timescale: Int32(FPS))
            
            let session = AVCaptureSession()
            
            if session.canAddInput(input) {
                print("Input added")
                session.addInput(input)
            } else {
                print("Input error")
            }
            
            // Set up the output
            let output = AVCapturePhotoOutput()
            let screenshotSettings = AVCapturePhotoSettings()
            
            if session.canAddOutput(output) {
                print("Output added")
                session.addOutput(output)
            } else {
                print("Output error")
            }
            
            session.startRunning()
                
            output.capturePhoto(with: screenshotSettings, delegate: self)
                
            session.stopRunning()
            
        }
  
    }

}

And delegate:

extension ViewController: AVCapturePhotoCaptureDelegate {
        func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
            
            if (error != nil) {
                print("\(String(describing: error?.localizedDescription)) debug: \(error.debugDescription)")
                return
            }
            
            guard let imageData = photo.cgImageRepresentation() else {
                    print("eror")
                    return
            }
            
            let unixTimestamp = CreateTimeStamp()
            let path = folderName + "\(unixTimestamp)" + ".jpg"
            let fileUrl = URL(fileURLWithPath: path, isDirectory: true)
            let bitmapRep = NSBitmapImageRep(cgImage: imageData.takeUnretainedValue())
            let jpegData = bitmapRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
    
            do {
                try jpegData.write(to: fileUrl, options: .atomic)
            }
            catch {print("error: \(error)")}
        }
    
        func CreateTimeStamp() -> Int32
          {
              return Int32(Date().timeIntervalSince1970)
          }
    }

And i have a problem: When i click on the Button, i need to make screenshots from all of Mac's displays. But when i click on the button, i get this message in Logs:

Optional("The operation could not be completed") debug: Optional(Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSLocalizedFailureReason=An unknown error occurred (-11800)})
    

But this function

makeScreenshot()

is working if i launch it from viewDidLoad() but it doesn't launch from button action

Any ideas?

  • Your code gives me the same error even when launched from viewDidLoad. Please try [this version](https://stackoverflow.com/a/40864231/2227743) which works for me (granted that you have the rights to write in the selected folder, and that the user has authorized screen capture). – Eric Aya Apr 16 '21 at 10:37
  • @EricAya Sorry, but CGDisplayCreateImage it's not my way because it take screenshot only from active application, i need to take screenshots from all displays with different applications – ilia khuzhakhmetov Apr 17 '21 at 20:55

1 Answers1

0

You can use:

let id = CGMainDisplayID()
let image = CGDisplayCreateImage(id)

Then, an alert will pop up asking the user to give your App screen recording permission. When the user adds your App to the list in the Security and Privacy Settings, CGDisplayCreateImage will capture all windows and the whole screen.

techrisdev
  • 606
  • 4
  • 10