iOS сохранить в фотографии не работает - PullRequest
0 голосов
/ 17 мая 2018

Я занимаюсь разработкой приложения с использованием Swift 4 и iOS 11.

Проблема в том, что я могу отобразить UIImage в UIImageView, но не могу сохранить его в фотоальбом своего iPhone. Я долго искал, но не знаю, как ее решить.

Вот часть моего кода:

Поместите весь код videoCapture в VideoCapture.swift.

public class VideoCapture: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {
public var previewLayer: AVCaptureVideoPreviewLayer?
public var fps = 15

let captureSession = AVCaptureSession()
let videoOutput = AVCaptureVideoDataOutput()
let queue = DispatchQueue(label: "net.machine.cameraqueue")
var photoOutput: AVCapturePhotoOutput?
var image: UIImage?

public func setUp(sessionPreset: AVCaptureSession.Preset = .medium, completion: @escaping (Bool) -> Void) {
    queue.async {
        let success = self.setUpCamera(sessionPreset: sessionPreset)
        DispatchQueue.main.async {
            completion(success)
        }
    }
}

public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    image = sampleBuffer.image()
}

func setUpCamera(sessionPreset: AVCaptureSession.Preset) -> Bool {
    captureSession.beginConfiguration() // begin configuration (not commited yet)
    captureSession.sessionPreset = sessionPreset

    guard let captureDevice = AVCaptureDevice.default(for: AVMediaType.video) else {    //set to video mode
        print("Error: No video devices available")
        return false
    }
    guard let videoInput = try? AVCaptureDeviceInput(device: captureDevice) else {      //set device input
        print("Error: could not create AVCaptureDeviceInput")
        return false
    }

    if captureSession.canAddInput(videoInput) { // add device input
        captureSession.addInput(videoInput)
    }

    // previewLayer setup
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect
    previewLayer.connection?.videoOrientation = .portrait
    self.previewLayer = previewLayer

    // video output setup
    let settings: [String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: kCVPixelFormatType_32BGRA),]
    videoOutput.videoSettings = settings
    videoOutput.alwaysDiscardsLateVideoFrames = true
    videoOutput.setSampleBufferDelegate(self, queue: queue)
    if captureSession.canAddOutput(videoOutput) {
        captureSession.addOutput(videoOutput)
    }

    videoOutput.connection(with: AVMediaType.video)?.videoOrientation = .portrait
    captureSession.commitConfiguration()
    return true
}

public func toggleRunning() {
    if captureSession.isRunning {
        captureSession.stopRunning()
    } else {
        captureSession.startRunning()
    }
}
}

extension CMSampleBuffer {
func image(orientation: UIImageOrientation = .up, scale: CGFloat = 1.0) -> UIImage? {
    if let buffer = CMSampleBufferGetImageBuffer(self) {
        let ciImage = CIImage(cvPixelBuffer: buffer)
        return UIImage(ciImage: ciImage, scale: scale, orientation: orientation)
    }
    return nil
}
}

ViewController.swift Файл имеет вид:

class ViewController: UIViewController {
    @IBOutlet weak var videoPreview: UIView!

    var videoCapture: VideoCapture!
    let semaphore = DispatchSemaphore(value: 2)
    override func viewDidLoad() {
        super.viewDidLoad()

        setUpCamera()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showPhotoSegue" {
            let previewVC = segue.destination as! PreviewViewController
            previewVC.image = videoCapture.image
        }
    }

    @IBAction func toggleCamera(_ sender: Any) {
        performSegue(withIdentifier: "showPhotoSegue", sender: nil)
    }

    func setUpCamera() {
        videoCapture = VideoCapture()
        videoCapture.fps = 50
        videoCapture.setUp(sessionPreset: AVCaptureSession.Preset.vga640x480) { success in
            if success {
                if let previewLayer = self.videoCapture.previewLayer {
                    self.videoPreview.layer.addSublayer(previewLayer)
                    self.resizePreviewLayer()
                }
                self.videoCapture.toggleRunning()
            }
        }
    }

    func resizePreviewLayer() {
        videoCapture.previewLayer?.frame = videoPreview.bounds
    }
    }
    }

PreviewViewController.swift выглядит следующим образом:

class PreviewViewController: UIViewController {

var image: UIImage?
@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()
    imageView.image = self.image
}

@IBAction func cancelButton(_ sender: Any) {
    dismiss(animated: true, completion: nil)
}

@IBAction func saveButton(_ sender: Any) {
    print(type(of: self.imageView.image!))
    UIImageWriteToSavedPhotosAlbum(self.imageView.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac,animated: true)
    } else {
        let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved!", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac,animated: true)
    }
}
}

Я использовал переход от ViewController к PreviewViewController и передал изображение в ViewController в imageView в PreviewViewController. Но почему он не сохраняет изображение в фотоальбоме?

Кстати, я добавил все авторизации конфиденциальности в info.plist.

1 Ответ

0 голосов
/ 30 мая 2018

UIImageWriteToSavedPhotosAlbum () - довольно старый API, я верю. Вы, вероятно, хотите использовать каркас Фотографии для сохранения изображений. Следующий код запросит доступ к фотобиблиотеке, а затем сохранит ваше изображение.

func saveImage(image : UIImage) {
    let data = UIImageJPEGRepresentation(image, 0.9)
    PHPhotoLibrary.requestAuthorization { [unowned self] status in
        if status == .authorized {
            PHPhotoLibrary.shared().performChanges({
                let creationRequest = PHAssetCreationRequest.forAsset()
                creationRequest.addResource(with: .photo, data: data, options: nil)
            }, completionHandler: { success, error in
                if let error = error {
                    print("Error occured while saving photo to photo library: \(error)")
                }
            })
        }
    }
}

Убедитесь, что это верхняя часть вашего файла

import Photos
...