How to get an ALAsset URL from a PHAsset?

后端 未结 5 1020
灰色年华
灰色年华 2020-11-27 06:36

You can do it sneakily† using the undocumented PHAsset.ALAssetURL property, but I\'m looking for something documented.


† In Objective-C, this will

相关标签:
5条回答
  • 2020-11-27 07:05

    Read the bottom!

    The resultHandler for PHImageManager.requestImage returns 2 objects: result and info

    You can get the original filename for the PHAsset (like IMG_1043.JPG) as well as it's full path on the filesystem with:

    let url = info?["PHImageFileURLKey"] as! URL
    

    This should work right, but for some reason Apple fucked it up. So basically, you have to copy your image to a file then access that then delete it.

    The PHImageFileURLKey is usable to get the original file name, but you cannot actually access that file. It probably has to do with the fact that code in the background can access the file while other apps can delete it.

    Think how much time you would waste figuring that out since Apple fucked up rather that just documenting it. Maybe it's sincere, maybe it's that they had different developers who didn't understand and did not want to work. Here I am working though, and Apple has how many hundreds of billions in the bank?

    Yea, sorry Apple but I do not agree when I have < 500 dollars and a net worth of less than than 1 year of 1700 subscribers paying for 1TB iCloud @ $10 a month for working for the same period of time that you have been revived from debt (2001 -> now). That was the original iPhone right? You sure are teaching them those data sizes though aren't you, scaling the iCloud monthly prices < 1% of the average US monthly income!

    0 讨论(0)
  • 2020-11-27 07:06

    Create the assetURL by leveraging the localidentifier of the PHAsset. Example: PHAsset.localidentifier returns 91B1C271-C617-49CE-A074-E391BA7F843F/L0/001

    Now take the 32 first characters to build the assetURL, like:

    assets-library://asset/asset.JPG?id=91B1C271-C617-49CE-A074-E391BA7F843F&ext=JPG

    You might change the extension JPG depending on the UTI of the asset (requestImageDataForAsset returns the UTI), but in my testing the extensions of the assetURL seems to be ignored anyhow.

    0 讨论(0)
  • 2020-11-27 07:07

    I wanted to be able to get a URL for an asset too. However, I have realised that the localIdentifier can be persisted instead and used to recover the PHAsset.

    PHAsset* asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil].firstObject;
    

    Legacy asset URLs can be converted using:

    PHAsset* legacyAsset = [PHAsset fetchAssetsWithALAssetUrls:@[assetUrl] options:nil].firstObject;
    NSString* convertedIdentifier = legacyAsset.localIdentifier;
    

    (before that method gets obsoleted...)

    (Thanks holtmann - localIdentifier is hidden away in PHObject.)

    0 讨论(0)
  • 2020-11-27 07:12

    Here is a PHAsset extension written in Swift that will retrieve the URL.

    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)
                    }
                })
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 07:21

    Here is working code tested on iOS 11 both simulator and device

    PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
        [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            PHAsset *asset = (PHAsset *)obj;
            [asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
                NSLog(@"URL:%@",  contentEditingInput.fullSizeImageURL.absoluteString);
                NSString* path = [contentEditingInput.fullSizeImageURL.absoluteString substringFromIndex:7];//screw all the crap of file://
                NSFileManager *fileManager = [NSFileManager defaultManager];
                BOOL isExist = [fileManager fileExistsAtPath:path];
                if (isExist)
                    NSLog(@"oh yeah");
                else {
                    NSLog(@"damn");
                }
            }];
        }];
    
    0 讨论(0)
提交回复
热议问题