提问人:Nathen Antony 提问时间:7/26/2023 更新时间:7/26/2023 访问量:50
在 SwiftUI 中使用 TOCropViewController 选取图像时关闭图像选取和裁剪视图时出错
Error dismissing image picking and cropping views when using TOCropViewController to pick images in SwiftUI
问:
我的 Swift 应用程序使用 TOCropViewController 来选取图像。处理图像拾取和裁剪的结构称为 ImagePicker。
从中调用 ImagePicker 的视图是工作表视图。当我调用 ImagePicker 时,一切正常,图像拾取屏幕出现,我按下取消按钮,图像拾取屏幕被很好地关闭。
当我选择图像时,我会转到裁剪视图。从这里开始,如果我按取消,一切都会按我想要的方式工作,但是如果我按完成,我选择和裁剪的图像不会被发送回我想要的调用 ImagePicker 的视图。
除了我的图像没有被发回的问题外,我的 ImagePicker 视图,包括裁剪视图和图像选取视图,它们都不能很好地解决。
由于我调用 ImagePicker 的视图是工作表,因此当我单击“完成”时,工作表会升起,并且我可以看到工作表视图下方的内容。屏幕上的所有内容都变得无法点击。
这是我从中调用 ImagePicker 的工作表视图在我单击完成后的样子
请帮我解决这个问题。
这是ImagePicker.swift文件:
import SwiftUI
import UIKit
import TOCropViewController
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@Binding var image: UIImage?
var didFinishPicking: () -> Void
var aspectRatioPreset: TOCropViewControllerAspectRatioPreset
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate, TOCropViewControllerDelegate {
var originalPicker: UIImagePickerController?
@Binding var image: UIImage?
var didFinishPicking: () -> Void
var aspectRatioPreset: TOCropViewControllerAspectRatioPreset
var presentingViewController: UIViewController?
init(image: Binding<UIImage?>, didFinishPicking: @escaping () -> Void, aspectRatioPreset: TOCropViewControllerAspectRatioPreset, presentingViewController: UIViewController?) {
_image = image
self.didFinishPicking = didFinishPicking
self.aspectRatioPreset = aspectRatioPreset
self.presentingViewController = presentingViewController
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.originalImage] as? UIImage else {
picker.dismiss(animated: true, completion: nil)
return
}
let cropViewController = TOCropViewController(image: image)
cropViewController.delegate = self
cropViewController.aspectRatioPreset = aspectRatioPreset
cropViewController.aspectRatioLockEnabled = true
originalPicker = picker
picker.present(cropViewController, animated: true, completion: nil)
}
func cropViewController(_ cropViewController: TOCropViewController, didCropTo croppedImage: UIImage, withRect cropRect: CGRect, angle: Int) {
self.image = croppedImage
cropViewController.dismiss(animated: true) {
self.originalPicker?.dismiss(animated: true, completion: {
self.didFinishPicking()
})
}
}
func cropViewController(_ cropViewController: TOCropViewController, didFinishCancelled cancelled: Bool) {
if cancelled {
cropViewController.dismiss(animated: true) {
self.originalPicker?.dismiss(animated: true, completion: {
self.didFinishPicking()
})
}
}
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(image: $image, didFinishPicking: didFinishPicking, aspectRatioPreset: aspectRatioPreset, presentingViewController: UIApplication.shared.windows.first?.rootViewController)
}
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
}
struct ImagePicker_Previews: PreviewProvider {
static var previews: some View {
ImagePicker(image: .constant(UIImage()), didFinishPicking: {}, aspectRatioPreset: .presetSquare) // Specify aspectRatioPreset here
}
}
下面是调用 ImagePicker 的结构:
struct ImageView: View {
@State private var showingImagePicker = false
@State private var linkImage: UIImage? = UIImage(named: "defaultLinkImage")
@State private var linkImageURL: String = ""
@State private var previousLinkImageURL: String = ""
@State private var showAlert = false
let defaultLinkImage = UIImage(named: "defaultLinkImage")
let selectedDate: String
let selectedGender: String
let selectedPreference: String
var body: some View {
GeometryReader { geometry in
ZStack {
Color.black
.ignoresSafeArea()
VStack {
Text("Add a great picture of you.")
.font(.custom("Futura-Bold", size: geometry.size.width * 0.1))
.foregroundColor(.white)
.multilineTextAlignment(.center)
.lineLimit(2)
.minimumScaleFactor(0.5)
.layoutPriority(1)
.padding()
Button(action: {
HapticManager.shared.triggerHapticFeedback()
self.showingImagePicker = true
}) {
Image(uiImage: linkImage!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 400)
.clipShape(RoundedRectangle(cornerRadius: 25))
.overlay(RoundedRectangle(cornerRadius: 25).stroke(Color.white, lineWidth: 4))
.shadow(color: .gray, radius: 10, x: 5, y: 5)
.shadow(color: .white, radius: 10, x: -5, y: -5)
.padding(.bottom, 20)
}
if linkImage == defaultLinkImage {
Button(action: {
HapticManager.shared.triggerHapticFeedback()
self.showAlert = true
}) {
Text("Continue.")
.font(.custom("Futura-Bold", size: 20))
.padding()
.background(Color.gray)
.foregroundColor(.white)
.clipShape(Capsule())
.alert(isPresented: $showAlert) {
Alert(title: Text("Error"), message: Text("Please choose a picture before proceeding."), dismissButton: .default(Text("Gotcha.")))
}
}
.padding()
} else {
NavigationLink(destination: CompleteView(date: self.selectedDate, gender: self.selectedGender, preferences: selectedPreference, imageURL: URL(string: linkImageURL))) {
Text("Continue.")
.font(.custom("Futura-Bold", size: 20))
.padding()
.background(Color.accentColor)
.foregroundColor(.white)
.clipShape(Capsule())
}
.padding()
.onTapGesture {
uploadData()
}
}
}
}
}
.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
ImagePicker(image: self.$linkImage, didFinishPicking: {
self.showingImagePicker = false
}, aspectRatioPreset: .preset4x3)
}
.navigationBarBackButtonHidden(true)
}
func loadImage() {
guard let inputImage = linkImage else { return }
// Delete previous profile picture if exists
if !previousLinkImageURL.isEmpty {
deletePreviousLinkPicture(previousURL: previousLinkImageURL)
}
// Create a unique file name
let fileName = UUID().uuidString
let folderPath = "Link_Pictures/"
let storageRef = Storage.storage().reference().child(folderPath + fileName)
guard let imageData = inputImage.jpegData(compressionQuality: 0.5) else { return }
// Metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
// Upload the file to Firebase Storage
storageRef.putData(imageData, metadata: metadata) { _, error in
if let error = error {
print("Error uploading: \(error.localizedDescription)")
return
}
// After the file is uploaded, get the download URL.
storageRef.downloadURL { (url, error) in
guard let downloadURL = url else {
print("An error occurred while getting the download URL")
return
}
self.linkImageURL = downloadURL.absoluteString
self.previousLinkImageURL = downloadURL.absoluteString // Store the current profile image URL as the previous URL
// Call the uploadData method after getting the image URL
uploadData()
}
}
}
func deletePreviousLinkPicture(previousURL: String) {
// Get the storage reference from the previous URL
let storageRef = Storage.storage().reference(forURL: previousURL)
// Delete the file from Firebase Storage
storageRef.delete { error in
if let error = error {
print("Error deleting picture: \(error.localizedDescription)")
} else {
print("Previous picture deleted successfully")
}
}
}
func uploadData() {
// Call the LinkRegLogic uploadData method
LinkRegLogic.uploadData(date: self.selectedDate, gender: self.selectedGender, preferences: self.selectedPreference, imageURL: linkImageURL)
}
}
非常感谢您的帮助,我是 SwiftUI 的初学者,我真的很感激。
我尝试在 ChatGPT 的帮助下在 ImagePicker 中重写我的函数,但我一无所获。
此外,如果您可以使用 TOCropViewController 以外的其他图像拾取和裁剪框架来完成这项工作,同时确保我可以在调用 ImagePicker 时将裁剪叠加的大小更改为参数,那也很棒,我不是特别依恋 TOCropViewController。
P.S. 我还使用 ImagePicker 在不是工作表的视图中挑选图像。
答: 暂无答案
评论