0

I'm using the following condition which doesn't execute for Images (but executes for Videos).

if let imgUrl = info[UIImagePickerControllerReferenceURL] as? URL{

            let imgName = imgUrl.lastPathComponent
            let documentDirectory = NSTemporaryDirectory()
            let localPath = documentDirectory.appending(imgName)

            let image = info[UIImagePickerControllerOriginalImage] as! UIImage
            let data = UIImageJPEGRepresentation(image, 0.3)! as NSData
            //data.write(toFile: localPath, atomically: true)
            let photoURL = URL.init(fileURLWithPath: localPath)
            let attr: NSDictionary = try! FileManager.default.attributesOfItem(atPath: (photoURL.path)) as NSDictionary
            print("file size is :", attr.fileSize(), attr.fileSize()/1024, (attr.fileSize()/1024)/1024)
            print(photoURL)
        }

I am getting the error:

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=260 "The file “asset.JPG” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/engineering07/Library/Developer/CoreSimulator/Devices/5B35C341-204E-43F0-A2DE-199757E38835/data/Containers/Data/Application/43182136-8C82-4385-99A7-F0F30B30A785/tmp/asset.JPG, NSUnderlyingError=0x608000246360 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

I am not able to understand what's wrong here or what's missing here. Please help me understand how to correct it. Thank you.

Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
Enrik Qaz
  • 243
  • 4
  • 14
  • check this https://stackoverflow.com/questions/28255789/getting-url-of-uiimage-selected-from-uiimagepickercontroller – Vishnu Oct 16 '18 at 09:21

3 Answers3

0

What you are doing is correct to retrieve the URL but for image you need to fetch image using UIImagePickerControllerOriginalImage key.

if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
}
Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
  • Sharad, how do I get the file url path in this case then? I also need this path to calculate the image size and upload it to the server? – Enrik Qaz Oct 16 '18 at 09:42
  • You can try this key inside that block : UIImagePickerControllerReferenceURL – Sharad Chauhan Oct 16 '18 at 09:46
  • Hey Sharad, on your suggestion, I tried implementing the same. It throws the error as above. Please help me correct it. Thanks. – Enrik Qaz Oct 16 '18 at 09:53
  • Okay, I just looked into apple docs and *UIImagePickerControllerReferenceURL* is deprecated and instead we should use *UIImagePickerControllerPHAsset*. Once we have the asset we can get the path. You can refer this for path : https://stackoverflow.com/questions/38183613/how-to-get-url-for-a-phasset. Let me know if this works. Also don't force '!' things, try to use **guard-let/if-let and do-catch**. – Sharad Chauhan Oct 16 '18 at 10:00
0

Please take help from this code only if you are proceeding with PHAsset approach. This is one of the solution I prefer:

extension MyViewController: UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        dismiss(animated: true, completion: nil)
        var done = false
        if #available(iOS 11.0, *) {
            if let asset = info[UIImagePickerControllerPHAsset] as? PHAsset {
                self.processAsset(asset)
                done = true
            }
        }

        if done == false {
            guard let capturedImage = info[UIImagePickerControllerEditedImage] as? UIImage else { return }
            let authorizationStatus = PHPhotoLibrary.authorizationStatus()
            if authorizationStatus == .notDetermined {
                PHPhotoLibrary.requestAuthorization({status in
                    if status == .authorized {
                        DispatchQueue.main.async {
                            self.proceedWithImageToAsset(capturedImage)
                        }
                    } else {
                        self.showErrorAlert("Our app need your camera and photo library access to upload your specified images".localized())
                    }
                })
            }
            else if authorizationStatus == .authorized {
                DispatchQueue.main.async {
                    self.proceedWithImageToAsset(capturedImage)
                }
            }
            else {
                self.showErrorAlert("Our app need your camera and photo library access to upload your specified images".localized())
            }
        }
    }

    private func proceedWithImageToAsset(_ capturedImage:UIImage) {
        var localIdentifier:String?
        PHPhotoLibrary.shared().performChanges({
            let changeRequest = PHAssetChangeRequest.creationRequestForAsset(from: capturedImage)
            localIdentifier = changeRequest.placeholderForCreatedAsset?.localIdentifier
        }) { (success, error) in
            if success {
                if let localIdentifier = localIdentifier {
                    DispatchQueue.main.async {
                        let selectedAssetFetch = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil)
                        var assets = [PHAsset]()
                        selectedAssetFetch.enumerateObjects({ (asset, index, _) in
                            assets.append(asset)
                        })
                        if let firstAsset = assets.first {
                            self.processAsset(firstAsset)
                        }
                    }
                }
            }
            else {
                debugPrint(error?.localizedDescription ?? "")
            }
        }
    }

    private func processAsset(_ asset: PHAsset) {
        PHImageManager.default().requestImageData(for: asset, options: nil) { (data, _, _, _) in
            if let imageData = data {
                debugPrint(imageData.count)
            }
            else {
                debugPrint("Handle error")
            }
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
}
Devanshu Saini
  • 765
  • 5
  • 24
0
let data: NSData = NSData(data: UIImageJPEGRepresentation((image)!, 0.3)!)
let imageSize: Int = data.length
let imageSizeInKB: Double = Double(imageSize) / 1024.0
Arie Pinto
  • 1,274
  • 1
  • 11
  • 19
  • why 0.3 here? can you explain? – Enrik Qaz Oct 17 '18 at 06:06
  • Because that’s the value you used :), so you will get the image size in kb of an image compressed by 0.3, if it were up to me i leave it at 1 to get the size of the original image – Arie Pinto Oct 17 '18 at 10:03
  • 1
    but the size I get here is different from the real size of the image. Any reason why? – Enrik Qaz Oct 17 '18 at 10:10
  • What do you mean by ‘the real size of the image’ ? – Arie Pinto Oct 17 '18 at 10:29
  • the size that i saw in photo investigator is different from the one which i get using UIImagePNGRepresentation(imageValue). any idea why? – Enrik Qaz Oct 17 '18 at 10:31
  • I don’t know photo investigator, but maybe behind the scenes apple already compress your’e image when you initialize a UIImaeJPEGRepresentation because if im not mistaken the images are in PNG format in the camera roll, don’t take my word for it do some research about the subject, what i can tell you for sure is with this code, the image you will upload to your server will be of this size ‘imageSizeInKb’ – Arie Pinto Oct 17 '18 at 10:35