How do I write video/image to saved photos album using PHPhotoLibrary? - ios

Hi all I'm using ALAssetsLibrary to write videos/images to the album.
But XCode is telling me that ALAssetsLibrary is deprecated and I need to use PHPhotoLibrary, which is all well and good but there are no examples or documentation of how to make this transition.
Can anyone show me how to change this code to use PHPHotoLibrary?
let data:NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
let image:UIImage = UIImage( data: data)!
let library:ALAssetsLibrary = ALAssetsLibrary()
let orientation: ALAssetOrientation = ALAssetOrientation(rawValue: image.imageOrientation.rawValue)!
library.writeImageToSavedPhotosAlbum(image.CGImage, orientation: orientation, completionBlock: nil)
and for video:
ALAssetsLibrary().writeVideoAtPathToSavedPhotosAlbum(outputFileURL, completionBlock: {
(assetURL:NSURL!, error:NSError!) in
if error != nil{
print(error)
}
do {
try NSFileManager.defaultManager().removeItemAtURL(outputFileURL)
} catch _ {
}
if backgroundRecordId != UIBackgroundTaskInvalid {
UIApplication.sharedApplication().endBackgroundTask(backgroundRecordId)
}
})

Saving image:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: image)
}, completionHandler: { (success, error) in
// completion callback
})
Video:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: mediaUrl as URL)
}, completionHandler: { (success, error) in
// completion callback
})

Related

setImageWith Url completion block swift ios

I am new to swift. I am loading image with url
mainImageView.setImageWith(URL(string: ("https:" + (content?.imagePath)!)), placeholderImage: nil)
print("dimensions after loading \(String(describing: mainImageView.image?.size))")
In case, I print the dimensions of the image as shown above then dimensions come out to be 21*6.5. However, if I wait for sometime and then print the dimensions are 188*109. How do I add a completion block to setImageWith so that I can come to know when image has finished loading?
You can use Sdwebimage for loading the image with completion block https://github.com/rs/SDWebImage
imageView.sd_setImageWithURL(NSURL(string: urlString), completed: {
(image, error, cacheType, url) in
// you can get the image width here...
})
It is happening because URL will always take a time to load image thats why first you got 21*6.5 dimensions and then got real dimensions 188*109.
As best way to prefer 3rd party library SDWebImage that will manage all the thing, You just need to set image URL.
There is method name is
open func sd_setImage(with url: URL!, placeholderImage placeholder: UIImage!, options: SDWebImageOptions = [], completed completedBlock: SDWebImage.SDWebImageCompletionBlock!)
that has completion block so you can manage whatever you want.
Convert image URL into data then Data into UIIamge, Here is a function:
func getImageFromUrl(_ strUrl: String, completionHandler handler: #escaping (_ img: UIImage) -> Void) {
DispatchQueue.global(qos: .background).async {
let url = URL(string: strUrl)
let dataFromUrl = Data(contentsOf: url!)
if dataFromUrl == nil {
return
}
DispatchQueue.main.async(execute: {() -> Void in
handler(UIImage(data: dataFromUrl!))
})
})
}
Use This: -
let imageCache = NSCache<AnyObject, AnyObject>()
typealias CompletionHandler = (_ success:Bool, _ image:UIImage?) -> Void
func loadImageUsingCacheWithUrlString(_ urlString:
String,completionHandler: #escaping CompletionHandler) {
let image = UIImage()
//check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
image = cachedImage
completionHandler(true, image!)
return
}
if urlString.characters.count == 0 {
completionHandler(false, image)
return
}
//otherwise fire off a new download
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//download hit an error so lets return out
if error != nil {
print(error ?? "")
completionHandler(false,nil)
return
}
DispatchQueue.main.async(execute: {
if let downloadedImage = UIImage(data: data!) {
image = downloadedImage
imageCache.setObject(downloadedImage, forKey: urlString as AnyObject)
completionHandler(true,image)
}
})
}).resume()
}

Capture Filtered Image with GPUImage and Save to Photo Library with Metadata

I am developing a simple came app for iOS 10. I need to live filter a camera feed, and then capture and save the filtered image.
Using GPUImage, I have been able to setup the live feed and the image capture using GPUImageStillCamera. I am also using the PHPhotoLibrary APIs:
func saveToPhotoLibrary(data: Data, completion: #escaping (PHAsset?) -> ()) {
var assetIdentifier: String?
PHPhotoLibrary.requestAuthorization { (status) in
if status == .authorized {
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.forAsset()
let placeholder = creationRequest.placeholderForCreatedAsset
creationRequest.addResource(with: .photo, data: data, options: .none)
assetIdentifier = placeholder?.localIdentifier
}, completionHandler: { (success, error) in
if let error = error {
print("There was an error saving to the photo library: \(error)")
}
var asset: PHAsset? = .none
if let assetIdentifier = assetIdentifier {
asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetIdentifier], options: .none).firstObject
}
completion(asset)
})
} else {
print("Need authorisation to write to the photo library")
completion(.none)
}
}
}
The problem is that when this image gets saved, the metadata (such as camera and device information) is missing. How can I save this image with the filter, yet still retain the image metadata?

IOS. Sharing image to Instagram without using a menu display

Can anyone help and explain how to do sharing to Instagram without displaying the menu? For example, the application Prisma does it without using a menu display.
You must do this:
Save your photo to photo library
Take asset url of saved photo
Open Instagram through URL Scheme with this URL
instagram://library?AssetPath=ASSET_PATH
Where ASSET_PATH is asset url taken on the second step.
Code example on Swift 3:
let library = ALAssetsLibrary()
library.writeImage(toSavedPhotosAlbum: image.cgImage, metadata: nil) { (url, error) in
if let url = url {
DispatchQueue.main.async {
let path = url.absoluteString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
let instagram = URL(string: "instagram://library?AssetPath=\(path)")
UIApplication.shared.open(instagram!)
}
}
}
I know this is an old questions but I just wanted to provide an updated answer for those who may be looking.
Vitaly Berg has the right approach just with deprecated code. Here is up to date code (Swift 5) That worked for me:
#IBAction func instagramButtonClicked(_ sender: Any) {
//check and see if we can save photos
let status = PHPhotoLibrary.authorizationStatus()
if (status == PHAuthorizationStatus.authorized) {
// Access has been granted.
self.shareToInstagram(theImage!)
}else if (status == PHAuthorizationStatus.denied) {
// Access has been denied.
Notifications.showNotification("Please Allow Access To Photos To Share", style: .danger)
}else if (status == PHAuthorizationStatus.notDetermined) {
// Access has not been determined.
PHPhotoLibrary.requestAuthorization({ (newStatus) in
if (newStatus == PHAuthorizationStatus.authorized) {
self.shareToInstagram(theImage!)
}else {
Notifications.showNotification("Please Allow Access To Photos To Share", style: .danger)
}
})
}else if (status == PHAuthorizationStatus.restricted) {
// Restricted access - normally won't happen.
Notifications.showNotification("Please Allow Access To Photos To Share", style: .danger)
}
}
func shareToInstagram(_ theImageToShare: UIImage){
self.saveToCameraRoll(image: theImageToShare) { (theUrl) in
if let url = theUrl {
DispatchQueue.main.async {
if let path = url.absoluteString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed){
let instagram = URL(string: "instagram://library?AssetPath=\(path)")
UIApplication.shared.open(instagram!)
}
}
}
}
}
func saveToCameraRoll(image: UIImage, completion: #escaping (URL?) -> Void) {
var placeHolder: PHObjectPlaceholder? = nil
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
placeHolder = creationRequest.placeholderForCreatedAsset!
}, completionHandler: { success, error in
guard success, let placeholder = placeHolder else {
completion(nil)
return
}
let assets = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let asset = assets.firstObject else {
completion(nil)
return
}
asset.requestContentEditingInput(with: nil, completionHandler: { (editingInput, _) in
completion(editingInput?.fullSizeImageURL)
})
})
}
Hope this helps someone!

iOS 9 save gif to photo library

Now that AssetsLibrary has been deprecated, we're supposed to use the photos framework, specifically PHPhotoLibrary to save images and videos to a users camera roll.
Using ReactiveCocoa, such a request would look like:
func saveImageAsAsset(url: NSURL) -> SignalProducer<String, NSError> {
return SignalProducer { observer, disposable in
var imageIdentifier: String?
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromImageAtFileURL(url)
let placeholder = changeRequest?.placeholderForCreatedAsset
imageIdentifier = placeholder?.localIdentifier
}, completionHandler: { success, error in
if let identifier = imageIdentifier where success {
observer.sendNext(identifier)
} else if let error = error {
observer.sendFailed(error)
return
}
observer.sendCompleted()
})
}
}
I created a gif from a video using Regift and I can verify that the gif exists inside my temporary directory. However when I go save that gif to the camera roll, I get a mysterious error: NSCocoaErrorDomain -1 (null), which is really super helpful.
Has anyone ever experienced this issue?
You can try this.
let data = try? Data(contentsOf: /*Your-File-URL-Path*/)
PHPhotoLibrary.shared().performChanges({
PHAssetCreationRequest.forAsset().addResource(with: .photo, data: data!, options: nil)
})

Save GIF image from URL to Camera Roll

I'm trying to save a GIF from URL to Camera Roll with the following code:
var image = UIImage(data: NSData(contentsOfURL: self.imageView.sd_imageURL())!)
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
but after saving, the GIF become a still image, anyone can help me?
Thanks!
You can save GIF via PHPhotoLibrary
PHPhotoLibrary.shared().performChanges({
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, fileURL: YOUR_GIF_URL, options: nil)
}) { (success, error) in
if let error = error {
completion(.failure(error))
} else {
completion(.success(true))
}
}
Try this:
import AssetsLibrary
let image = NSData(contentsOfURL: url)
ALAssetsLibrary().writeImageDataToSavedPhotosAlbum(image, metadata: nil, completionBlock: { (assetURL: NSURL!, error: NSError!) -> Void in
print(assetURL)
})

Resources