Last active
May 9, 2024 16:16
-
-
Save lacyrhoades/ccf185739d46ca8743ffd4b7df04602d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Photos | |
typealias AssetID = String | |
class ImageUtil { | |
static var defaultAlbumName = "App Name" | |
static var videosAlbumName = "App Name Videos" | |
static func saveFileToCameraRoll(fromPath: String) { | |
var albumName = ImageUtil.defaultAlbumName | |
var isVideo: Bool = false | |
if fromPath.localizedStandardContains("mp4") { | |
albumName = ImageUtil.videosAlbumName | |
isVideo = true | |
} | |
let fromURL = URL(fileURLWithPath: fromPath) | |
guard let album = ImageUtil.findOrCreateAlbum(named: albumName) else { | |
assert(false, "Could not find or create album") | |
return; | |
} | |
DispatchQueue.global().async { | |
PHPhotoLibrary.shared().performChanges({ | |
var assetReq: PHAssetChangeRequest? | |
if isVideo { | |
assetReq = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fromURL) | |
} else { | |
assetReq = PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fromURL) | |
} | |
if let asset = assetReq?.placeholderForCreatedAsset { | |
let request = PHAssetCollectionChangeRequest(for: album) | |
request?.addAssets([asset] as NSArray) | |
} | |
}) { (done, err) in | |
if err != nil { | |
print("Error creating video file in library") | |
print(err.debugDescription) | |
} else { | |
print("Done writing asset to the user's photo library") | |
} | |
} | |
} | |
} | |
static func save(_ image: UIImage, toAlbumNamed albumName: String, andThen: @escaping (AssetID?) -> ()) { | |
DispatchQueue.global().async { | |
if let album = ImageUtil.findOrCreateAlbum(named: albumName) { | |
var localIdentifier: AssetID? = nil | |
PHPhotoLibrary.shared().performChanges({ | |
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image) | |
let asset = assetChangeRequest.placeholderForCreatedAsset | |
localIdentifier = asset?.localIdentifier | |
let request = PHAssetCollectionChangeRequest(for: album) | |
request?.addAssets([asset!] as NSArray) | |
}, completionHandler: { (success, error) in | |
if success { | |
andThen(localIdentifier) | |
} | |
}) | |
} | |
} | |
} | |
static func saveVideo(atURL url: URL, toAlbumNamed albumName: String, andThen: @escaping (AssetID?) -> ()) { | |
guard FileUtil.fileExists(url.path) else { | |
assert(false, "File does not exist and cannot be saved to Camera Roll") | |
return | |
} | |
DispatchQueue.global().async { | |
if let album = ImageUtil.findOrCreateAlbum(named: albumName) { | |
var localIdentifier: AssetID? = nil | |
PHPhotoLibrary.shared().performChanges({ | |
if let assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) { | |
let asset = assetChangeRequest.placeholderForCreatedAsset | |
localIdentifier = asset?.localIdentifier | |
let request = PHAssetCollectionChangeRequest(for: album) | |
request?.addAssets([asset!] as NSArray) | |
} else { | |
print("Creation request for video failed") | |
} | |
}, completionHandler: { (success, error) in | |
if success { | |
andThen(localIdentifier) | |
} else { | |
print("Creation request failed") | |
print(error?.localizedDescription ?? "None") | |
} | |
}) | |
} | |
} | |
} | |
static func findOrCreateAlbum(named albumName: String) -> PHAssetCollection? { | |
if let album = ImageUtil.findAlbum(named: albumName) { | |
return album | |
} else { | |
do { | |
try PHPhotoLibrary.shared().performChangesAndWait({ | |
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName) | |
}) | |
} catch { | |
print("Problem finding/creating album: ".appending(albumName)) | |
print(error) | |
} | |
return ImageUtil.findAlbum(named: albumName) | |
} | |
} | |
static func findAlbum(named albumName: String) -> PHAssetCollection? { | |
let options = PHFetchOptions() | |
options.predicate = NSPredicate(format: "title = %@", albumName) | |
let findAlbumResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: options) | |
return findAlbumResult.firstObject | |
} | |
static func clearCameraRoll() { | |
let options = PHFetchOptions() | |
let fetch: PHFetchResult<PHAsset> = PHAsset.fetchAssets(with: options) | |
var assets: [PHAsset] = [] | |
fetch.enumerateObjects({ (asset, index, test) in | |
assets.append(asset) | |
}) | |
PHPhotoLibrary.shared().performChanges({ | |
PHAssetChangeRequest.deleteAssets(assets as NSArray) | |
}) { (result, error) in | |
// done | |
} | |
} | |
static func assetExists(_ assetID: AssetID) -> Bool { | |
let options = PHFetchOptions() | |
let request = PHAsset.fetchAssets(withLocalIdentifiers: [assetID], options: options) | |
return request.count > 0 | |
} | |
} |
Hi there,
i have to save a video from Bundle.main and then share the video on Facebook. I don't know how to retreive url of the video saved in library without pickerController.
ps. sorry for my english :D
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there,
this looks like a very thorough toolkit for dealing with image assets. 8•) - as a newbie to Swift - I'm wondering how to use it. I'm trying to save a replaykit video to a custom Photos Album, using ImageUtil.saveVideo method, but I think I need to set everything else up first. Have you got a demo of how to use this class? Many many thanks!