В моем приложении пользователь может либо открыть рулон камеры, чтобы выбрать снимок, либо открыть камеру, чтобы сделать один снимок.
В обоих случаях выбранное / сделанное изображение также будет сохранено локально для дальнейшего использования.
Недостатком является то, что операция сохранения обычно останавливает экран до его завершения.
Я нашел анимацию в этом посте и хочу показать ее перед imagePickerController
, но мне не удается это сделать.
class SinglePageViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate, UINavigationBarDelegate {
var spinner: UIActivityIndicatorView?
lazy var showCameraImagePickerController: UIImagePickerController = {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
return imagePicker
}()
lazy var showPhotoImagePickerController: UIImagePickerController = {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
return imagePicker
}()
@IBOutlet weak var photoButton: UIButton!
@IBAction func onPhotoButton(_ sender: Any) {
self.present(self.showCameraImagePickerController, animated: true, completion: nil)
}
@IBOutlet weak var galleryButton: UIButton!
@IBAction func onGalleryButton(_ sender: Any) {
self.present(self.showPhotoImagePickerController, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
//start animation
let screenSize: CGRect = UIScreen.main.bounds
spinner = UIActivityIndicatorView(frame: CGRect(x: screenSize.width / 2 - 150, y: screenSize.height / 2 - 150, width: 300, height: 300))
spinner?.isHidden = false
spinner?.startAnimating()
spinner?.color = UIColor.red
switch picker {
case showCameraImagePickerController:
// snap pic, save to doc, save to album
self.showCameraImagePickerController.view.addSubview(spinner!)
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false, block: { _ in
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
if self.saveImage(imageName: "\(self.titleLabel.text!).png", image: image) {
// additionally save to photo album
UIImageWriteToSavedPhotosAlbum(image!, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
print("saved \(self.titleLabel.text!).png")
self.imageView.image = image
}
})
case showPhotoImagePickerController:
//switch pic, save to doc. no album
self.showPhotoImagePickerController.view.addSubview(spinner!)
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false, block: { _ in
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
if self.saveImage(imageName: "\(self.titleLabel.text!).png", image: image) {
print("saved new \(self.titleLabel.text!).png")
self.imageView.image = image
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
self.showPhotoImagePickerController.dismiss(animated: true, completion: nil)
} else {
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
self.showPhotoImagePickerController.dismiss(animated: true, completion: nil)
}
})
default:
return
}
}
@objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
spinner?.stopAnimating()
spinner?.removeFromSuperview()
spinner = nil
self.showCameraImagePickerController.dismiss(animated: true, completion: nil)
}
func saveImage(imageName: String, image: UIImage?) -> Bool {
//create an instance of the FileManager
let fileManager = FileManager.default
//get the image path
let imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imgDir + imageName)
print(imagePath)
//get the image we took with camera
let image = rotateImage(image: image!)
//get the PNG data for this image
let data = UIImagePNGRepresentation(image)
//store it in the document directory
if fileManager.createFile(atPath: imagePath as String, contents: data, attributes: nil) {
newItem?.image = true
return true
} else {
print("error while saving")
return false
}
}
}
как видите, я пытался играть с bringSubView(toFront:)
, а также с zPosition
, но безрезультатно.
следующий этот похожий вопрос Я посмотрел документацию для cameraOverlayView , но он говорит, что он работает только тогда, когда imagePicker представлен в режиме камеры, что не распространяется на случай, когда Я открываю фотобиблиотеку
Я также недавно пытался использовать обходной путь, то есть я уволил imagePickerController как можно скорее и впоследствии обновил изображение, но это больше не оптимально из-за некоторых изменений в структуре приложения.
EDIT
, чтобы сделать себя более ясным, я еще раз заявлю, что мне нужно: показать анимацию вращения перед в ImagePicker, как только я коснусь фотографии, чтобы выбрать ее, и пока я не закончу сохранение, затем отклонить imagePicker.
Я не хочу сначала свернуть сборщик, а затем сохранить его, показывая вертушку на главном экране.
EDIT2
обновил код с новым из ответа. Единственная проблема заключается в том, что, если я не установлю таймер, блесна покажет себя только в конце процесса сохранения на короткое время (проверяется с помощью точек останова).
Это приводит к отсутствию анимации в течение пары секунд процесса сохранения и только к краткому появлению вращателя в конце, перед тем как закрыть ImagePicker.
Просто установив задержку в 0,1 с, вы сразу же запускаете счетчик, и я получаю ожидаемое поведение (анимация при сохранении).
Понятия не имею, почему