Skip to content

Commit

Permalink
close #15, save live photos and videos to photo library all the time
Browse files Browse the repository at this point in the history
  • Loading branch information
tankista committed Oct 26, 2017
1 parent 021d405 commit f860536
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 44 deletions.
4 changes: 2 additions & 2 deletions ExampleApp/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ let sectionsData: [(String?, String?)] = [
("Assets Source", nil),
("Asset Items in a row", nil),
("Capture mode", nil),
("Save Assets", "Assets will be saved to Photo Library")
("Save Assets", "Assets will be saved to Photo Library. This applies to photos only. Live photos and videos are always saved.")
]

///
Expand Down Expand Up @@ -227,7 +227,7 @@ class ViewController: UITableViewController {
}

// save capture assets to photo library?
imagePicker.captureSettings.savesCapturedAssetToPhotoLibrary = savesCapturedAssets
imagePicker.captureSettings.savesCapturedPhotosToPhotoLibrary = savesCapturedAssets

// presentation
// before we present VC we can ask for authorization to photo library,
Expand Down
13 changes: 4 additions & 9 deletions ImagePicker/CaptureSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,6 @@ final class CaptureSession : NSObject {

var presetConfiguration: SessionPresetConfiguration = .photos

///
/// Save assets to library or not. Appropriate delegate is called in all cases.
///
var saveCapturedAssetsToPhotoLibrary = false

///
/// Set this method to orientation that mathches UI orientation before `prepare()`
/// method is called. If you need to update orientation when session is running,
Expand Down Expand Up @@ -699,7 +694,7 @@ extension CaptureSession {

extension CaptureSession {

func capturePhoto(livePhotoMode: LivePhotoMode) {
func capturePhoto(livePhotoMode: LivePhotoMode, saveToPhotoLibrary: Bool) {
/*
Retrieve the video preview layer's video orientation on the main queue before
entering the session queue. We do this to ensure UI elements are accessed on
Expand Down Expand Up @@ -795,7 +790,7 @@ extension CaptureSession {
}
})

photoCaptureDelegate.savesPhotoToLibrary = self.saveCapturedAssetsToPhotoLibrary
photoCaptureDelegate.savesPhotoToLibrary = saveToPhotoLibrary

/*
The Photo Output keeps a weak reference to the photo capture delegate so
Expand All @@ -811,7 +806,7 @@ extension CaptureSession {

extension CaptureSession {

func startVideoRecording() {
func startVideoRecording(saveToPhotoLibrary: Bool) {

guard let movieFileOutput = self.videoFileOutput else {
return log("capture session: trying to record a video but no movie file output is set")
Expand Down Expand Up @@ -884,7 +879,7 @@ extension CaptureSession {
}
}
})
recordingDelegate.savesPhotoToLibrary = strongSelf.saveCapturedAssetsToPhotoLibrary
recordingDelegate.savesVideoToLibrary = saveToPhotoLibrary

// start recording
movieFileOutput.startRecording(to: outputURL, recordingDelegate: recordingDelegate)
Expand Down
15 changes: 11 additions & 4 deletions ImagePicker/CaptureSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,23 @@ public struct CaptureSettings {
public var cameraMode: CameraMode

///
/// Return true if captured assets will be saved to photo library. Image picker
/// will prompt user with request for permisssions when needed. Default value is false.
/// Return true if captured photos will be saved to photo library. Image picker
/// will prompt user with request for permisssions when needed. Default value is false
/// for photos. Live photos and videos are always true.
///
public var savesCapturedAssetToPhotoLibrary: Bool
/// - note: please note, that at current implementation this applies to photos only. For
/// live photos and videos this is always true.
///
public var savesCapturedPhotosToPhotoLibrary: Bool

let savesCapturedLivePhotosToPhotoLibrary: Bool = true
let savesCapturedVideosToPhotoLibrary: Bool = true

/// Default configuration
public static var `default`: CaptureSettings {
return CaptureSettings(
cameraMode: .photo,
savesCapturedAssetToPhotoLibrary: false
savesCapturedPhotosToPhotoLibrary: false
)
}
}
Expand Down
7 changes: 3 additions & 4 deletions ImagePicker/ImagePickerController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ open class ImagePickerController : UIViewController {
let session = CaptureSession()
captureSession = session
session.presetConfiguration = captureSettings.cameraMode.captureSessionPresetConfiguration
session.saveCapturedAssetsToPhotoLibrary = captureSettings.savesCapturedAssetToPhotoLibrary
session.videoOrientation = UIApplication.shared.statusBarOrientation.captureVideoOrientation
session.delegate = self
session.videoRecordingDelegate = self
Expand Down Expand Up @@ -685,15 +684,15 @@ extension ImagePickerController : CaptureSessionVideoRecordingDelegate {
extension ImagePickerController: CameraCollectionViewCellDelegate {

func takePicture() {
captureSession?.capturePhoto(livePhotoMode: .off)
captureSession?.capturePhoto(livePhotoMode: .off, saveToPhotoLibrary: captureSettings.savesCapturedPhotosToPhotoLibrary)
}

func takeLivePhoto() {
captureSession?.capturePhoto(livePhotoMode: .on)
captureSession?.capturePhoto(livePhotoMode: .on, saveToPhotoLibrary: captureSettings.savesCapturedLivePhotosToPhotoLibrary)
}

func startVideoRecording() {
captureSession?.startVideoRecording()
captureSession?.startVideoRecording(saveToPhotoLibrary: captureSettings.savesCapturedVideosToPhotoLibrary)
}

func stopVideoRecording() {
Expand Down
6 changes: 3 additions & 3 deletions ImagePicker/LivePhotoCameraCell.xib
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@
</button>
<view opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OHT-YT-HK2" customClass="CarvedLabel" customModule="ImagePicker" customModuleProvider="target">
<rect key="frame" x="92" y="53" width="35" height="18.5"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" notEnabled="YES"/>
</accessibility>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<real key="value" value="2"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="text" value="LIVE"/>
<userDefinedRuntimeAttribute type="number" keyPath="padding">
<real key="value" value="3"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="horizontalInset">
<real key="value" value="5"/>
</userDefinedRuntimeAttribute>
Expand Down
48 changes: 28 additions & 20 deletions ImagePicker/VideoCaptureDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate

// MARK: Public Methods

/// set this to false if you dont wish to save taken picture to photo library
var savesPhotoToLibrary = true
/// set this to false if you dont wish to save video to photo library
var savesVideoToLibrary = true

/// true if user manually requested to cancel recording (stop without saving)
var isBeingCancelled = false
Expand Down Expand Up @@ -56,6 +56,22 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate

private func cleanUp(deleteFile: Bool, saveToAssets: Bool, outputFileURL: URL) {

func deleteFileIfNeeded() {

guard deleteFile == true else { return }

let path = outputFileURL.path
if FileManager.default.fileExists(atPath: path) {
do {
try FileManager.default.removeItem(atPath: path)
}
catch let error {
log("capture session: could not remove recording at url: \(outputFileURL)")
log("capture session: error: \(error)")
}
}
}

if let currentBackgroundRecordingID = backgroundRecordingID {
backgroundRecordingID = UIBackgroundTaskInvalid
if currentBackgroundRecordingID != UIBackgroundTaskInvalid {
Expand All @@ -69,30 +85,22 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.forAsset()
let videoResourceOptions = PHAssetResourceCreationOptions()
videoResourceOptions.shouldMoveFile = false
videoResourceOptions.shouldMoveFile = true
creationRequest.addResource(with: .video, fileURL: outputFileURL, options: videoResourceOptions)
}, completionHandler: { success, error in
if let error = error {
log("capture session: Error occurered while saving video to photo library: \(error)")
deleteFileIfNeeded()
}
}
)
})
}
}
}

if deleteFile {
let path = outputFileURL.path
if FileManager.default.fileExists(atPath: path) {
do {
try FileManager.default.removeItem(atPath: path)
}
catch let error {
log("capture session: could not remove recording at url: \(outputFileURL)")
log("capture session: error: \(error)")
else {
deleteFileIfNeeded()
}
}

}
else {
deleteFileIfNeeded()
}
}

Expand All @@ -114,7 +122,7 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate

if successfullyFinished {
recordingWasInterrupted = true
cleanUp(deleteFile: false, saveToAssets: savesPhotoToLibrary, outputFileURL: outputFileURL)
cleanUp(deleteFile: true, saveToAssets: savesVideoToLibrary, outputFileURL: outputFileURL)
didFail(self, error)
}
else {
Expand All @@ -127,7 +135,7 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate
didFinish(self)
}
else {
cleanUp(deleteFile: false, saveToAssets: savesPhotoToLibrary, outputFileURL: outputFileURL)
cleanUp(deleteFile: true, saveToAssets: savesVideoToLibrary, outputFileURL: outputFileURL)
didFinish(self)
}

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ Currently Image Picker supports capturing *photos*, *live photos* and *videos*.

To configure Image Picker to support desired media type use `CaptureSettings` struct. Use property `cameraMode` to specify what kind of output you are interested in. If you don't intend to support live photos at all, please use value `photo`, otherwise `photoAndLivePhoto`. If you wish to capture photos and videos use `photoAndVideo`. Capturing videos and live photos at the same time is not supported and you nor can't switch between presets after it's been configrued.

By default, all captured assets are not saved to photo library but rather provided to you by the delegate right away. However if you wish to save assets to photo library set `savesCapturedAssetToPhotoLibrary` to *true*.
By default, all captured photos are not saved to Photo Library but rather provided to you by the delegate right away. However if you wish to save photos to photo library set `savesCapturedPhotosToPhotoLibrary` to *true*. Live photos and videos are saved to Photo Library automatically.

An example of configuration for taking photos and live photos and saving them to photo library:

```swift
let imagePicker = ImagePickerController()
imagePicker.captureSettings.cameraMode = .photoAndLivePhoto
imagePicker.captureSettings.savesCapturedAssetToPhotoLibrary = true
imagePicker.captureSettings.savesCapturedPhotosToPhotoLibrary = true
```

Please refer to `CaptureSettings` public header for more information.
Expand Down

0 comments on commit f860536

Please sign in to comment.