Skip to content

Commit f860536

Browse files
committed
close #15, save live photos and videos to photo library all the time
1 parent 021d405 commit f860536

File tree

7 files changed

+53
-44
lines changed

7 files changed

+53
-44
lines changed

ExampleApp/ViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ let sectionsData: [(String?, String?)] = [
5252
("Assets Source", nil),
5353
("Asset Items in a row", nil),
5454
("Capture mode", nil),
55-
("Save Assets", "Assets will be saved to Photo Library")
55+
("Save Assets", "Assets will be saved to Photo Library. This applies to photos only. Live photos and videos are always saved.")
5656
]
5757

5858
///
@@ -227,7 +227,7 @@ class ViewController: UITableViewController {
227227
}
228228

229229
// save capture assets to photo library?
230-
imagePicker.captureSettings.savesCapturedAssetToPhotoLibrary = savesCapturedAssets
230+
imagePicker.captureSettings.savesCapturedPhotosToPhotoLibrary = savesCapturedAssets
231231

232232
// presentation
233233
// before we present VC we can ask for authorization to photo library,

ImagePicker/CaptureSession.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,6 @@ final class CaptureSession : NSObject {
106106

107107
var presetConfiguration: SessionPresetConfiguration = .photos
108108

109-
///
110-
/// Save assets to library or not. Appropriate delegate is called in all cases.
111-
///
112-
var saveCapturedAssetsToPhotoLibrary = false
113-
114109
///
115110
/// Set this method to orientation that mathches UI orientation before `prepare()`
116111
/// method is called. If you need to update orientation when session is running,
@@ -699,7 +694,7 @@ extension CaptureSession {
699694

700695
extension CaptureSession {
701696

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

798-
photoCaptureDelegate.savesPhotoToLibrary = self.saveCapturedAssetsToPhotoLibrary
793+
photoCaptureDelegate.savesPhotoToLibrary = saveToPhotoLibrary
799794

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

812807
extension CaptureSession {
813808

814-
func startVideoRecording() {
809+
func startVideoRecording(saveToPhotoLibrary: Bool) {
815810

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

889884
// start recording
890885
movieFileOutput.startRecording(to: outputURL, recordingDelegate: recordingDelegate)

ImagePicker/CaptureSettings.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,23 @@ public struct CaptureSettings {
3636
public var cameraMode: CameraMode
3737

3838
///
39-
/// Return true if captured assets will be saved to photo library. Image picker
40-
/// will prompt user with request for permisssions when needed. Default value is false.
39+
/// Return true if captured photos will be saved to photo library. Image picker
40+
/// will prompt user with request for permisssions when needed. Default value is false
41+
/// for photos. Live photos and videos are always true.
4142
///
42-
public var savesCapturedAssetToPhotoLibrary: Bool
43+
/// - note: please note, that at current implementation this applies to photos only. For
44+
/// live photos and videos this is always true.
45+
///
46+
public var savesCapturedPhotosToPhotoLibrary: Bool
47+
48+
let savesCapturedLivePhotosToPhotoLibrary: Bool = true
49+
let savesCapturedVideosToPhotoLibrary: Bool = true
4350

4451
/// Default configuration
4552
public static var `default`: CaptureSettings {
4653
return CaptureSettings(
4754
cameraMode: .photo,
48-
savesCapturedAssetToPhotoLibrary: false
55+
savesCapturedPhotosToPhotoLibrary: false
4956
)
5057
}
5158
}

ImagePicker/ImagePickerController.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ open class ImagePickerController : UIViewController {
323323
let session = CaptureSession()
324324
captureSession = session
325325
session.presetConfiguration = captureSettings.cameraMode.captureSessionPresetConfiguration
326-
session.saveCapturedAssetsToPhotoLibrary = captureSettings.savesCapturedAssetToPhotoLibrary
327326
session.videoOrientation = UIApplication.shared.statusBarOrientation.captureVideoOrientation
328327
session.delegate = self
329328
session.videoRecordingDelegate = self
@@ -685,15 +684,15 @@ extension ImagePickerController : CaptureSessionVideoRecordingDelegate {
685684
extension ImagePickerController: CameraCollectionViewCellDelegate {
686685

687686
func takePicture() {
688-
captureSession?.capturePhoto(livePhotoMode: .off)
687+
captureSession?.capturePhoto(livePhotoMode: .off, saveToPhotoLibrary: captureSettings.savesCapturedPhotosToPhotoLibrary)
689688
}
690689

691690
func takeLivePhoto() {
692-
captureSession?.capturePhoto(livePhotoMode: .on)
691+
captureSession?.capturePhoto(livePhotoMode: .on, saveToPhotoLibrary: captureSettings.savesCapturedLivePhotosToPhotoLibrary)
693692
}
694693

695694
func startVideoRecording() {
696-
captureSession?.startVideoRecording()
695+
captureSession?.startVideoRecording(saveToPhotoLibrary: captureSettings.savesCapturedVideosToPhotoLibrary)
697696
}
698697

699698
func stopVideoRecording() {

ImagePicker/LivePhotoCameraCell.xib

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@
5454
</button>
5555
<view opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OHT-YT-HK2" customClass="CarvedLabel" customModule="ImagePicker" customModuleProvider="target">
5656
<rect key="frame" x="92" y="53" width="35" height="18.5"/>
57+
<accessibility key="accessibilityConfiguration">
58+
<accessibilityTraits key="traits" notEnabled="YES"/>
59+
</accessibility>
5760
<userDefinedRuntimeAttributes>
5861
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
5962
<real key="value" value="2"/>
6063
</userDefinedRuntimeAttribute>
6164
<userDefinedRuntimeAttribute type="string" keyPath="text" value="LIVE"/>
62-
<userDefinedRuntimeAttribute type="number" keyPath="padding">
63-
<real key="value" value="3"/>
64-
</userDefinedRuntimeAttribute>
6565
<userDefinedRuntimeAttribute type="number" keyPath="horizontalInset">
6666
<real key="value" value="5"/>
6767
</userDefinedRuntimeAttribute>

ImagePicker/VideoCaptureDelegate.swift

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate
1717

1818
// MARK: Public Methods
1919

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

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

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

59+
func deleteFileIfNeeded() {
60+
61+
guard deleteFile == true else { return }
62+
63+
let path = outputFileURL.path
64+
if FileManager.default.fileExists(atPath: path) {
65+
do {
66+
try FileManager.default.removeItem(atPath: path)
67+
}
68+
catch let error {
69+
log("capture session: could not remove recording at url: \(outputFileURL)")
70+
log("capture session: error: \(error)")
71+
}
72+
}
73+
}
74+
5975
if let currentBackgroundRecordingID = backgroundRecordingID {
6076
backgroundRecordingID = UIBackgroundTaskInvalid
6177
if currentBackgroundRecordingID != UIBackgroundTaskInvalid {
@@ -69,30 +85,22 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate
6985
PHPhotoLibrary.shared().performChanges({
7086
let creationRequest = PHAssetCreationRequest.forAsset()
7187
let videoResourceOptions = PHAssetResourceCreationOptions()
72-
videoResourceOptions.shouldMoveFile = false
88+
videoResourceOptions.shouldMoveFile = true
7389
creationRequest.addResource(with: .video, fileURL: outputFileURL, options: videoResourceOptions)
7490
}, completionHandler: { success, error in
7591
if let error = error {
7692
log("capture session: Error occurered while saving video to photo library: \(error)")
93+
deleteFileIfNeeded()
7794
}
78-
}
79-
)
95+
})
8096
}
81-
}
82-
}
83-
84-
if deleteFile {
85-
let path = outputFileURL.path
86-
if FileManager.default.fileExists(atPath: path) {
87-
do {
88-
try FileManager.default.removeItem(atPath: path)
89-
}
90-
catch let error {
91-
log("capture session: could not remove recording at url: \(outputFileURL)")
92-
log("capture session: error: \(error)")
97+
else {
98+
deleteFileIfNeeded()
9399
}
94100
}
95-
101+
}
102+
else {
103+
deleteFileIfNeeded()
96104
}
97105
}
98106

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

115123
if successfullyFinished {
116124
recordingWasInterrupted = true
117-
cleanUp(deleteFile: false, saveToAssets: savesPhotoToLibrary, outputFileURL: outputFileURL)
125+
cleanUp(deleteFile: true, saveToAssets: savesVideoToLibrary, outputFileURL: outputFileURL)
118126
didFail(self, error)
119127
}
120128
else {
@@ -127,7 +135,7 @@ final class VideoCaptureDelegate: NSObject, AVCaptureFileOutputRecordingDelegate
127135
didFinish(self)
128136
}
129137
else {
130-
cleanUp(deleteFile: false, saveToAssets: savesPhotoToLibrary, outputFileURL: outputFileURL)
138+
cleanUp(deleteFile: true, saveToAssets: savesVideoToLibrary, outputFileURL: outputFileURL)
131139
didFinish(self)
132140
}
133141

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ Currently Image Picker supports capturing *photos*, *live photos* and *videos*.
7171

7272
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.
7373

74-
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*.
74+
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.
7575

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

7878
```swift
7979
let imagePicker = ImagePickerController()
8080
imagePicker.captureSettings.cameraMode = .photoAndLivePhoto
81-
imagePicker.captureSettings.savesCapturedAssetToPhotoLibrary = true
81+
imagePicker.captureSettings.savesCapturedPhotosToPhotoLibrary = true
8282
```
8383

8484
Please refer to `CaptureSettings` public header for more information.

0 commit comments

Comments
 (0)