Saving a photo and using it immediately

5.7k Views Asked by At

I have the following code for taking a photo and saving it to the camera roll. I need to be able to use it there and then after saving without having to go back into the gallery and selecting it.

I haven't found any examples on how to do this.

    @IBOutlet weak var imagePicked: UIImageView!

    @IBAction func CameraBtn(sender: UIButton) {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
            var imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = UIImagePickerControllerSourceType.Camera;
            imagePicker.allowsEditing = false
            self.presentViewController(imagePicker, animated: true, completion: nil)
            cameraBool = true
        }
    }

    @IBAction func GalleryBtn(sender: UIButton) {
        println("gallery button clicked")
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
            var imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            imagePicker.allowsEditing = true
            self.presentViewController(imagePicker, animated: true, completion: nil)
            cameraBool = false
        }
    }

func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
        imagePicked.image = image
        if (cameraBool){
            var imageData = UIImageJPEGRepresentation(imagePicked.image, 0.6)
            var compressedJPGImage = UIImage(data: imageData)
            UIImageWriteToSavedPhotosAlbum(compressedJPGImage, nil, nil, nil)

        }
        self.dismissViewControllerAnimated(true, completion: nil);
    }

I need to be able to use this saved image in the following webservice function:

func urlRequestWithComponents(urlString:String, parameters:Dictionary<String, String>, imageData:NSData) -> (URLRequestConvertible, NSData) {

        // create url request to send
        var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue
        let boundaryConstant = "myRandomBoundary12345";
        let contentType = "multipart/form-data;boundary="+boundaryConstant
        mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")



        // create upload data to send
        let uploadData = NSMutableData()

        // add image
        uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
        uploadData.appendData(imageData)

        // add parameters
        for (key, value) in parameters {
            uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
        }
        uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)



        // return URLRequestConvertible and NSData
        return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData)
    }

My web service is working when I choose an image from the gallery and place that in my imageView on screen. But when I take a photo, I need to save it to the library first which I have now done but the piece I am missing is how to reference this newly created photo from the library programmatically.

UPDATE: I assume converting from nsurl to nsdata would be as below in the retrieved from camera block below. Note cameraBool is set to true when the user selects the option to take a picture. ImageChanged is set in the imagePickerController function

if (imageChanged){
        //changed from placeholder
            if (!cameraBool){
                //retrieved from gallery
                let image = pic
                let imageData = UIImagePNGRepresentation(image)
            }
            else{
                //retrieved from camera
                let imageData = NSData(contentsOfURL: cameraPath)
            }
        }
        else{
            //upload nil
            let imageData = nil
        }

My issue is that the path of the image is only defined in my imagePickerController function. So I need to declare the cameraPath at the top of the file so it can be used in the imagePickerController function and then in my upload webservice. It seems I cannot initialise cameraPath as nil. So I'm not sure how to initialise it?

var cameraPath : NSURL = nil
//not allowed

When I just have:

var cameraPath : NSURL

I am getting the error that my controller has no initialisers

3

There are 3 best solutions below

3
On BEST ANSWER

You can get Path of the recently added image by camera this way:

func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
    imagePicked.image = image
   if (cameraBool){
        var imageData = UIImageJPEGRepresentation(imagePicked.image, 0.6)
        var compressedJPGImage = UIImage(data: imageData)
        ALAssetsLibrary().writeImageToSavedPhotosAlbum(compressedJPGImage!.CGImage, orientation: ALAssetOrientation(rawValue: compressedJPGImage!.imageOrientation.rawValue)!,
        completionBlock:{ (path:NSURL!, error:NSError!) -> Void in
            println("\(path)")  //Here you will get your path
        })
    }
    self.dismissViewControllerAnimated(true, completion: nil);
}

Which will print path like this:

assets-library://asset/asset.JPG?id=C5E0EB97-5D3D-41F9-8782-F48140144432&ext=JPG
0
On

You can use protocols/Delegation-pattern for this. See the Apple Doc.

Basically you create a Protocol in your class with the requiered functions, set a delegate variable, and then hand off your Image to the new View Controller. You can find a tutorial here.

1
On

Use the ALAssetsLibrary, if you save the image using UIImageWriteToSavedPhotosAlbum, you don't get a pointer to it. More info.

Edit: I think the solution of @DharmeshKheni should work. My guess is that you read the cameraPath before this is set. In other words: I think you try to use the new picture before it's saved. Can you tell where the cameraPath is set, and where you read it?