Swift - UIImagePickerController - 如何使用它?

50
我正在努力理解这个工作原理,但对我来说还是很难的。=) 我有一个视图,里面有一个按钮和一个小的ImageView区域用于预览。 按钮会触发imagepickercontroller,UIView将显示选择的图片。 没有错误,但图片不显示在UIImageView区域。
var imagePicker = UIImagePickerController()
@IBOutlet var imagePreview : UIImageView

@IBAction func AddImageButton(sender : AnyObject) {
    imagePicker.modalPresentationStyle = UIModalPresentationStyle.CurrentContext
    imagePicker.delegate = self
    self.presentModalViewController(imagePicker, animated: true)
    
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
    var tempImage:UIImage = UIImage(named: UIImagePickerControllerOriginalImage)
    imagePreview.image  = tempImage
    
    self.dismissModalViewControllerAnimated(true)
    
}

func imagePickerControllerDidCancel(picker: UIImagePickerController!) {

    self.dismissModalViewControllerAnimated(true)
}

你是在编程中创建你的imagePreView吗?如果它存在于XIB或Storyboard中,请检查是否已经连接了你的IBOutlet。 - Naga Mallesh Maddali
请分享 imagePreview 的初始化代码? - Markus Rautopuro
哎呀,有些空格错误。我纠正了示例代码。我使用了Storyboard并连接了IBOutlet。 - user3806731
1
对于一些匆忙的人:https://dev59.com/W1gR5IYBdhLWcg3wHqTB#55781021 - tryKuldeepTanwar
6个回答

41
你正在获取一张名为UIImagePickerControllerOriginalImageUIImage,但是并不存在这样的图片。你需要从editingInfo字典中使用UIImagePickerControllerOriginalImage键获取对应的UIImage
let tempImage = editingInfo[UIImagePickerControllerOriginalImage] as! UIImage

谢谢。但现在我遇到了致命错误:无法解包Optional.None。 - user3806731
你知道在你想让我添加的那一行上加什么吗? - user3806731
3
这意味着要么 editingInfonil(我不认为是这种情况),要么字典中不存在 UIImagePickerControllerOriginalImage。你正在实现一种旧的方法,应该实现 imagePickerController:didFinishPickingMediaWithInfo: 而不是 imagePickerController:didFinishPickingImage:editingInfo: - Jesper
谢谢Jesper。我按照你说的修改了代码后,问题已经解决了。我更新了代码。 - user3806731
是的,我做到了!再次感谢。我已经编辑了上面的代码,所以代码正在运行! - user3806731

34

详情

  • Xcode 11.4.1 (11E503a),Swift 5.2

更多

如何构建自己的照片选择器

解决方案

import UIKit
import AVFoundation
import Photos

protocol ImagePickerDelegate: class {
    func imagePicker(_ imagePicker: ImagePicker, grantedAccess: Bool,
                     to sourceType: UIImagePickerController.SourceType)
    func imagePicker(_ imagePicker: ImagePicker, didSelect image: UIImage)
    func cancelButtonDidClick(on imageView: ImagePicker)
}

class ImagePicker: NSObject {

    private weak var controller: UIImagePickerController?
    weak var delegate: ImagePickerDelegate? = nil

    func dismiss() { controller?.dismiss(animated: true, completion: nil) }
    func present(parent viewController: UIViewController, sourceType: UIImagePickerController.SourceType) {
        let controller = UIImagePickerController()
        controller.delegate = self
        controller.sourceType = sourceType
        self.controller = controller
        DispatchQueue.main.async {
            viewController.present(controller, animated: true, completion: nil)
        }
    }
}

// MARK: Get access to camera or photo library

extension ImagePicker {

    private func showAlert(targetName: String, completion: ((Bool) -> Void)?) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            let alertVC = UIAlertController(title: "Access to the \(targetName)",
                                            message: "Please provide access to your \(targetName)",
                                            preferredStyle: .alert)
            alertVC.addAction(UIAlertAction(title: "Settings", style: .default, handler: { action in
                guard   let settingsUrl = URL(string: UIApplication.openSettingsURLString),
                        UIApplication.shared.canOpenURL(settingsUrl) else { completion?(false); return }
                UIApplication.shared.open(settingsUrl, options: [:]) { [weak self] _ in
                    self?.showAlert(targetName: targetName, completion: completion)
                }
            }))
            alertVC.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in completion?(false) }))
            UIApplication.shared.windows.filter { $0.isKeyWindow }.first?
                .rootViewController?.present(alertVC, animated: true, completion: nil)
        }
    }

    func cameraAsscessRequest() {
        if delegate == nil { return }
        let source = UIImagePickerController.SourceType.camera
        if AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized {
            delegate?.imagePicker(self, grantedAccess: true, to: source)
        } else {
            AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
                guard let self = self else { return }
                if granted {
                    self.delegate?.imagePicker(self, grantedAccess: granted, to: source)
                } else {
                    self.showAlert(targetName: "camera") { self.delegate?.imagePicker(self, grantedAccess: $0, to: source) }
                }
            }
        }
    }

    func photoGalleryAsscessRequest() {
        PHPhotoLibrary.requestAuthorization { [weak self] result in
            guard let self = self else { return }
            let source = UIImagePickerController.SourceType.photoLibrary
            if result == .authorized {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.delegate?.imagePicker(self, grantedAccess: result == .authorized, to: source)
                }
            } else {
                self.showAlert(targetName: "photo gallery") { self.delegate?.imagePicker(self, grantedAccess: $0, to: source) }
            }
        }
    }
}

// MARK: UINavigationControllerDelegate

extension ImagePicker: UINavigationControllerDelegate { }

// MARK: UIImagePickerControllerDelegate

extension ImagePicker: UIImagePickerControllerDelegate {

    func imagePickerController(_ picker: UIImagePickerController,
                               didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[.editedImage] as? UIImage {
            delegate?.imagePicker(self, didSelect: image)
            return
        }

        if let image = info[.originalImage] as? UIImage {
            delegate?.imagePicker(self, didSelect: image)
        } else {
            print("Other source")
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        delegate?.cancelButtonDidClick(on: self)
    }
}

完整使用方法

Info.plist文件

 <key>NSPhotoLibraryUsageDescription</key>
 <string>bla-bla-bla</string>
 <key>NSCameraUsageDescription</key>
 <string>bla-bla-bla</string>

视图控制器 (不要忘记粘贴解决方案代码)

import UIKit

class ViewController: UIViewController {

    private weak var imageView: UIImageView!
    private lazy var imagePicker: ImagePicker = {
        let imagePicker = ImagePicker()
        imagePicker.delegate = self
        return imagePicker
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "camera", style: .plain, target: self,
                                                           action: #selector(cameraButtonTapped))
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "photo", style: .plain, target: self,
                                                           action: #selector(photoButtonTapped))

        let imageView = UIImageView(frame: CGRect(x: 40, y: 80, width: 200, height: 200))
        imageView.backgroundColor = .lightGray
        view.addSubview(imageView)
        self.imageView = imageView
    }

    @objc func photoButtonTapped(_ sender: UIButton) { imagePicker.photoGalleryAsscessRequest() }
    @objc func cameraButtonTapped(_ sender: UIButton) { imagePicker.cameraAsscessRequest() }
}

// MARK: ImagePickerDelegate

extension ViewController: ImagePickerDelegate {

    func imagePicker(_ imagePicker: ImagePicker, didSelect image: UIImage) {
        imageView.image = image
        imagePicker.dismiss()
    }

    func cancelButtonDidClick(on imageView: ImagePicker) { imagePicker.dismiss() }
    func imagePicker(_ imagePicker: ImagePicker, grantedAccess: Bool,
                     to sourceType: UIImagePickerController.SourceType) {
        guard grantedAccess else { return }
        imagePicker.present(parent: self, sourceType: sourceType)
    }
}

图片

输入图像描述


输入图像描述


输入图像描述


输入图像描述


输入图像描述


输入图像描述


1
  • 导入 "UIKit"
- J A S K I E R
@jonye._.jin,我刚刚测试了代码,一切正常。你可以给我发送更多细节吗? - Vasily Bodnarchuk

24
import MobileCoreServices

class SecondViewController: UIViewController,UINavigationControllerDelegate, UIImagePickerControllerDelegate {

   @IBOutlet var img:UIImageView!=nil

   override func viewDidLoad() {
        super.viewDidLoad()
   }

   override func didReceiveMemoryWarning() 
   {
       super.didReceiveMemoryWarning()

   }

   @IBAction func buttonTapped(AnyObject)
   {
     if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary){
            println("Button capture")
            var imag = UIImagePickerController()
            imag.delegate = self
            imag.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            //imag.mediaTypes = [kUTTypeImage];
            imag.allowsEditing = false
            self.presentViewController(imag, animated: true, completion: nil)
        }
   }

   func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
        let selectedImage : UIImage = image
       //var tempImage:UIImage = editingInfo[UIImagePickerControllerOriginalImage] as UIImage
        img.image=selectedImage
        self.dismissViewControllerAnimated(true, completion: nil)    
   }
 }

我猜委托方法已经改为:func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { - Desert Rose
func imagePickerController didFinishPickingImage editingInfo is deprecated like from iOS 3 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerControllerDelegate_Protocol/ - Radek Wilczak

12

自从 swift 4.2xcode 10 版本发布以来,func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) 函数发生了一些变化。

函数头中的 infoKey-部分已更改为

didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any] (之前是 didFinishPickingMediaWithInfo info: [String : Any]

现在要获取原始图片(originalImage),您需要调用:

let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage

let image = info[.originalImage] as? UIImage

在此处查找其他 infoKeys:此处(编辑图像、图像URL等...)


对我来说不起作用: "Type 'UIImagePickerController.InfoKey' (aka 'NSString') has no member 'originalImage'" - Cristi Băluță

7
在Swift 5.2和iOS 14.2中。
class YourViewController: UIViewController,UINavigationControllerDelegate, UIImagePickerControllerDelegate {

@IBAction func btnTapped(_ sender: Any) {
    let imagePickerController = UIImagePickerController()
    imagePickerController.allowsEditing = false //If you want edit option set "true"
    imagePickerController.sourceType = .photoLibrary
    imagePickerController.delegate = self
    present(imagePickerController, animated: true, completion: nil)
    
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let tempImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
    imgRoom.image  = tempImage
    self.dismiss(animated: true, completion: nil)
}

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

}

4

试试这个:

func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info:NSDictionary!) {
    let tempImage = info[UIImagePickerControllerOriginalImage] as! UIImage
    imagePreview.image  = tempImage

或者你也可以使用?代替!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接