1

I am trying to take image with camera on share extension. Is it possible to do? Currently, in my main app, I write like this.

self.pickerController = [[UIImagePickerController alloc] init];
[self.pickerController setSourceType:UIImagePickerControllerSourceTypeCamera];
[self.pickerController setDelegate:self.delegate];
self.pickerController.showsCameraControls = NO;

//In main VC, I write like this 
[self presentViewController:[ImageTakingHelper sharedInstance].pickerController animated:YES completion:nil];

It is okay in my main app but in my share extension, it show black screen for camera view. How shall I do?

Khant Thu Linn
  • 5,905
  • 7
  • 52
  • 120

2 Answers2

1

You can't do it. Remember, your share extension is operating in someone else's app. It can only do a small range of things there, and using the camera is not one of them. (Even if you could do it, their app might not have permission to use the camera.) Also, your share extension does not own the screen, so it can't present the image picker.

Apple's documentation about this limitation can be found here: https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html

user229044
  • 232,980
  • 40
  • 330
  • 338
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • While the Camera access aspect of this answer is correct, it is possible to access photos using UIImagePickerController in the context of the other app. When I tested on iOS 11, it presents the image picker and displays the security alert, under the context of the extension's app. So it looks like permissions are inherited from the extension's parent. This even works when presenting the share extension within apps that have no photos access. – Vinny Coyne Sep 27 '17 at 10:03
  • @meagar Point taken, no problem. – matt Aug 14 '20 at 19:56
0
import UIKit

class SSImagePicker: NSObject {

    static let shared = SSImagePicker()
    fileprivate var thisVC: UIViewController!
    var imagePickedBlock: ((UIImage) -> Void)?

    //MARK: Used to Open Camera/Library
    private func openCamera(){
        if UIImagePickerController.isSourceTypeAvailable(.camera){
            let myPickerController = UIImagePickerController()
            myPickerController.delegate = self;
            myPickerController.sourceType = .camera
            myPickerController.allowsEditing = false
            thisVC.present(myPickerController, animated: true, completion: nil)
        }
    }

    private func openGallery(){
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
            let myPickerController = UIImagePickerController()
            myPickerController.delegate = self;
            myPickerController.sourceType = .photoLibrary
            myPickerController.allowsEditing = true
            thisVC.present(myPickerController, animated: true, completion: nil)
        }
    }


    func ssActionSheetFor(viewRect : UIButton?,controller: UIViewController,with imagePickerTypes : [SSImagePickerType]) {
        guard viewRect != nil else {
            return
        }
        thisVC = controller
        let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        for objImagePickerType in imagePickerTypes {
            let objAction = UIAlertAction(title: objImagePickerType.rawValue, style: .default, handler: { (alert:UIAlertAction!) -> Void in

                switch  alert.title {
                case SSImagePickerType.ssCamera.rawValue:
                    self.openCamera()
                case SSImagePickerType.ssGalery.rawValue:
                    self.openGallery()
                default:
                    self.openGallery()
                }
            })
            actionSheet.addAction(objAction)
        }
        actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        if let presenter = actionSheet.popoverPresentationController {
            presenter.sourceView = viewRect;
            presenter.sourceRect = viewRect!.bounds
            presenter.permittedArrowDirections = UIPopoverArrowDirection.up;
        }
        thisVC.present(actionSheet, animated: true, completion: nil)
    }


}

extension SSImagePicker: UIImagePickerControllerDelegate, UINavigationControllerDelegate{

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        thisVC.dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[.editedImage] as? UIImage {
            self.imagePickedBlock?(image)
        }else{
            if let image = info[.originalImage] as? UIImage {
                 self.imagePickedBlock?(image)
            }else{
                alertMessase(message: "Something went wrong", okAction: {})
            }
        }
        thisVC.dismiss(animated: true, completion: nil)
    }
}

enum SSImagePickerType : String {
    case ssCamera = "Camera"
    case ssGalery = "Gallery"
    case ssVideo = "Videos"
    init(){
        self = .ssGalery
    }
}

//MARK:- You can use like this

SSImagePicker.shared.ssActionSheetFor(viewRect: sender, controller: self, with: [.ssCamera,.ssGalery])
    SSImagePicker.shared.imagePickedBlock = { (selectedImage) in
        self.imgProfile?.image = selectedImage
    }