15

I am using a third party library to select multiple images from the Photo Library. On selecting multiple images it returns an array of PHAsset objects. Now, I want to save the URL (or some reference) for these objects in the core data. But I do not know how to get the URL. Is there any other reference I could store in the core data which could help me in fetching the same image from the photo library?

Utsav Dusad
  • 2,139
  • 4
  • 31
  • 52

1 Answers1

49

I used @iMHitesh Surani answer and it worked perfect, I converted it into Swift 3.1 and put it into an extension of PHAsset in order to use that method everywhere, here it is:

extension PHAsset {

    func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
        if self.mediaType == .image {
            let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
            options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
                return true
            }
            self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
                completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
            })
        } else if self.mediaType == .video {
            let options: PHVideoRequestOptions = PHVideoRequestOptions()
            options.version = .original
            PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
                if let urlAsset = asset as? AVURLAsset {
                    let localVideoUrl: URL = urlAsset.url as URL
                    completionHandler(localVideoUrl)
                } else {
                    completionHandler(nil)
                }
            })
        }
    }
}
Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65
diegomen
  • 1,804
  • 1
  • 23
  • 37
  • Thanks. But how to use it? – rick Sep 10 '17 at 07:23
  • Add a file PHAssetExtension.swift with this code in your project, and then everywhere you'll have a PHAsset object you just have to do asset.getUrl... – diegomen Sep 11 '17 at 12:58
  • doesn't getURL need any parameter? – rick Sep 11 '17 at 13:00
  • 1
    nope, because is the asset itself the one who's calling the method, so he got all the needed info :) – diegomen Sep 11 '17 at 19:49
  • @diegomen it requires completionHandler in a parameter, what should we put there? please help – user3420180 Nov 02 '17 at 16:23
  • @user3420180 `asset.getUrl() { url in` `// ... use url here` `}` – Leo Dabus Nov 02 '17 at 20:23
  • @LeoDabus I still didn't know how to make it work. I have the image stored in `selectedAssets[0]` and I get its `PHAsset` through `selectedAssets[0].PHAsset`. can you guide me how to use `getURL`? am I doing it the right way like the following `selectedAsset[0].PHAsset.getURL()`? if yes, what do you mean by "use url here?" from where I get it? sorry for my long reply – user3420180 Nov 02 '17 at 21:03
  • It is an asynchronous method you need to use url inside the closure – Leo Dabus Nov 02 '17 at 21:04
  • @LeoDabus can you explain to me in layman terms please, i still don't know how to get it working – user3420180 Nov 02 '17 at 21:09
  • @user3420180 better to open a new question and post your attempt and the issues you are facing. If you would like me to take a look at it post the link here when you are done – Leo Dabus Nov 02 '17 at 21:10
  • @LeoDabus I tried to do "asset = PHAsset()" then "asset.getURL(selectedAssets[0].PHAsset) but it was silly attempt from me, here is my question (Please help me) https://stackoverflow.com/questions/47083712/how-to-get-the-path-of-an-image – mazin Nov 02 '17 at 21:24
  • @user3420180 PHAsset() it is not enough to find a photo. Where is the photo coming from? Is it a UIImagePicker? – Leo Dabus Nov 02 '17 at 21:29
  • 2
    @user3420180 try `selectedAssets[0].PHAsset.getURL() { url in ... your code to use url here}` or ``selectedAssets[0].getURL() { url in ... your code to use url here}`` – Leo Dabus Nov 02 '17 at 21:30
  • @LeoDabus I am using TLPhotoPicker package which stores the user selected images inside selectedAssets. Do you advice me to change and use the standard way? or can I still get the URLs using TLPhotoPicker ? https://github.com/tilltue/TLPhotoPicker – mazin Nov 02 '17 at 21:42
  • 1
    I won't download that picker. What's your goal? Why do you need your asset url? Your question is too vague. Btw this might help you understand it https://stackoverflow.com/a/43944769/2303865 – Leo Dabus Nov 02 '17 at 21:44
  • @LeoDabus my goal is to upload the images to Firebase and based on Firebase docs, to upload local file, i need its path. https://firebase.google.com/docs/storage/ios/upload-files?authuser=0 – mazin Nov 02 '17 at 21:47
  • @LeoDabus can you advice me of the best way based on your experience to choose multiple images and get their path? please – mazin Nov 02 '17 at 21:49
  • You will need to get the data from the PHAsset and save it locally and use their urls to post to firebase. With the link I posted You can get the data. Just write the data to a local url (in your documentsDirectory or a temporary directory) and then pass those url to your firebase – Leo Dabus Nov 02 '17 at 21:52
  • @user3420180 bte the is a new key to get the asset from the info dictionary https://developer.apple.com/documentation/uikit/uiimagepickercontrollerphasset – Leo Dabus Nov 02 '17 at 21:54
  • 1
    @LeoDabus Thank you a lot for the help, I really appreciate your time and will to help me. I am looking into what you said and going through the link again. Thanks – mazin Nov 02 '17 at 21:57
  • @LeoDabus Can I ask one last question please. Is the above code in the answer stores the paths in some local file or directory so that I can try to remove it. because to me it doesn't seem like it is storing it somewhere, am I right or wrong? – user3420180 Nov 02 '17 at 23:44
  • @user3420180 this only stores the asset url which it is probably not enough to upload to Firebase. You need to use the fetch method to get the data and instead of initializing an UIImage you need to write the data to a temporary folder. The destination url which you use to write the data locally is what you need to pass to your Firebase method – Leo Dabus Nov 02 '17 at 23:48
  • @LeoDabus "file:///var/mobile/Media/DCIM/100APPLE/IMG_0004.PNG" this is what I get printed to the console, isn't it the image path that Firebase needs? because I am a bit confused here – user3420180 Nov 02 '17 at 23:59
  • @user3420180 this looks like a valid path but it depends if the user device stores the photos in iCloud. If the url has a file:// scheme it means it is a local resource and you can use that url. If it is an asset url you need to get the data and save it locally – Leo Dabus Nov 03 '17 at 00:01
  • @LeoDabus now I get what you mean, I will work on getting the data as it seems more reliable option. Thank you – user3420180 Nov 03 '17 at 00:04
  • @LeoDabus from swift docs, i found this (https://developer.apple.com/documentation/photos/phimagemanager#1656241). so I believe I should use ` PHImageManager.default().requestImageData(for: selectedAssets[0].phAsset!, options: PHImageRequestOptions(), resultHandler:{}` but what should I put inside the `resultHandler` to retrieve the metadata needed to get the image Path? sorry for troubling you with my questions – user3420180 Nov 04 '17 at 09:24
  • 6
    This crashes sometimes with `contentEditingInput ` being `nil`. Does anyone have any idea why this can be and what should I do in that case? – Jelly May 05 '18 at 09:03
  • Is there any synchronized way? Can I change this extension to get URL synchronisely? – rick Aug 07 '18 at 06:32
  • 2
    It is returning the AVUrlAsset as nil, for some PHAssets. Have anyone encountered the same issue? – Shivani Bajaj Nov 15 '20 at 19:30
  • 1
    add `options.isNetworkAccessAllowed = true` for avoiding nil URL – sagarthecoder Jun 20 '22 at 05:55