UIImagePickerController可以用于拍摄照片、录制视频以及在相册或者图库中选择照片和视频数据。
使用步骤
通过isSourceTypeAvailable(_:)方法判断当前设备是否支持你期望的sourceType (camera 用于拍照和录像, photoLibrary和savedPhotosAlbum用于从相册或者图库中选择图片)。
通过调用availableMediaTypes(for:)来查看你使用的sourceType可用的媒体类型,这可用于区分可以录像的相机和仅可用于拍照的相机。
通过设置 mediaTypes 属性来告诉UIImagePickerController你要处理的媒体类型。
设置其他属性。
设置代理。
弹出UIImagePickerController。
在完成和取消的代理方法中进行相应的处理。
代码
Demo
判断当前的设备是否支持相应的SourceType:
if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
// 相应处理...
}
if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
// 相应处理...
}
判断相机是否支持录像
if let availableTypes = UIImagePickerController.availableMediaTypes(for: .camera) {
if !availableTypes.contains(kUTTypeMovie as String) {
showAlert(title: "错误", msg: "相机不支持录像")
return
}
}
获取相机或者相册访问权限
注意需要在Info.plist中设置(Privacy - Camera Usage Description...)
相册只需要在plist中设置即可
let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch status {
case .restricted, .denied:
let alertViewController = UIAlertController(title: "不能访问相机", message: "请在设置->隐私->相机中设置允许此程序访问相机", preferredStyle: .alert)
let okAction = UIAlertAction(title: "确定", style: .default, handler: { (_) in
if let url = URL(string: UIApplicationOpenSettingsURLString) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
})
let cancel = UIAlertAction(title: "取消", style: .cancel, handler: { (_) in
})
alertViewController.addAction(okAction)
alertViewController.addAction(cancel)
self.present(alertViewController, animated: true, completion: nil)
case .notDetermined:
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: {[weak self] (allow) in
if allow {
self?.showImagePicker(sourceType: .camera, from: sender)
}
})
case.authorized:
showImagePicker(sourceType: .camera, from: sender)
}
初始化UIImagePickerController以及设置属性、展示
func showImagePicker(sourceType: UIImagePickerControllerSourceType, from: UIBarButtonItem, isMovie: Bool = false) {
let imagePickerController = UIImagePickerController()
imagePickerController.modalPresentationStyle = .currentContext
// 设置sourceType UIImagePickerControllerSourceType枚举
imagePickerController.sourceType = sourceType
// 是否允许编辑 操作完成后会进入编辑页面
imagePickerController.allowsEditing = false
// 设置代理 需要实现(UIImagePickerControllerDelegate & UINavigationControllerDelegate)协议
imagePickerController.delegate = self
if sourceType == .camera {
imagePickerController.modalPresentationStyle = .fullScreen
if isMovie {
// 录制视频相关设置...
// 设置媒体类型 这里设置为仅可以录像
imagePickerController.mediaTypes = [kUTTypeMovie as String]
// 视频质量
imagePickerController.videoQuality = .typeMedium
// 将相机设置为录像模式 默认是photo
imagePickerController.cameraCaptureMode = .video
// 设置为后置摄像头
imagePickerController.cameraDevice = .rear
// 视频录制时间
imagePickerController.videoMaximumDuration = 10
// .... 其他属性参照API
}
} else {
imagePickerController.modalPresentationStyle = .popover
// 默认只显示照片...
imagePickerController.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
}
let presentationController = imagePickerController.popoverPresentationController
presentationController?.barButtonItem = from
presentationController?.permittedArrowDirections = .any
// 使用自定义的相机页面
if isUseCustomOverlayView.isOn {
if sourceType == .camera {
// 不显示默认的控件 使用自定义的
imagePickerController.showsCameraControls = false
// 加载自定义的cameraOverlayView
Bundle.main.loadNibNamed("OverlayView", owner: self, options: nil)
delayStep.addTarget(self, action: #selector(delayChange), for: .valueChanged)
timerStep.addTarget(self, action: #selector(timeChange), for: .valueChanged)
// load overlayView
if let frm = imagePickerController.cameraOverlayView?.frame {
overlayView.frame = frm
}
// cameraOverlayView设置为自定义的View
imagePickerController.cameraOverlayView = overlayView
overlayView = nil
}
}
// 展示
self.imagePickerViewController = imagePickerController
self.present(imagePickerController, animated: true, completion: nil)
}
处理代理方法
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaW
if let mediaType = info[UIImagePickerControllerMediaType] as? String {
var isVideo = false
if mediaType == kUTTypeImage as String {
// 获取选择或者拍摄的照片
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
captureImages.append(image)
}
if timer?.isValid == true {
return
}
if let dict = info[UIImagePickerControllerMediaMetadata] as? NSDictionar
print(dict)
}
} else if mediaType == kUTTypeMovie as String {
// 获取选择或者录制的视频
if let url = info[UIImagePickerControllerMediaURL] as? URL { //视频路径
videoUrl = url
isVideo = true
}
}
finishAndShowImages(isVideo: isVideo)
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
保存相片或者视频到相册
// 保存到相册
func saveToRollAlbum(_ sender: UIBarButtonItem) {
if let url = videoUrl {
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.path) {
// 如果是视频的话直接保存
UISaveVideoAtPathToSavedPhotosAlbum(url.path, self, #selector(ViewController.video(videoPath:didFinishSavingWithError:contextInfo:)), nil)
}
} else {
var image: UIImage? = imageView.image
if let ig = imageView.animationImages?.first {
image = ig
}
if image != nil {
UIImageWriteToSavedPhotosAlbum(image!, self, #selector(ViewController.image(image:didFinishSavingWithError:contextInfo:)), nil)
}
}
}
func video(videoPath: String, didFinishSavingWithError: Error?, contextInfo: UnsafeMutableRawPointer?)
if didFinishSavingWithError != nil {
showAlert(title: "失败", msg: didFinishSavingWithError!.localizedDescription)
} else {
showAlert(title: "成功", msg: "保存视频成功")
}
}
func image(image: UIImage, didFinishSavingWithError: Error?, contextInfo: UnsafeMutableRawPointer?) {
if didFinishSavingWithError != nil {
showAlert(title: "失败", msg: didFinishSavingWithError!.localizedDescription)
} else {
showAlert(title: "成功", msg: "保存照片成功")
}
}
官方API地址
UIImagePickerController