为每个操作表按钮添加不同的修饰符
Posted
技术标签:
【中文标题】为每个操作表按钮添加不同的修饰符【英文标题】:Add a different modifier to each Action Sheet button 【发布时间】:2021-04-26 17:33:50 【问题描述】:这可能是一个很简单的问题,但我找不到答案。
我正在尝试构建一个带有两个按钮(以及一个取消按钮)的 ActionSheet:
-
“从图库中选择”按钮打开一个
imagePicker
,其中sourceType
设置为.photoLibrary
。
“拍一张新照片”按钮打开一个imagePicker
,sourceType
设置为.camera
。
我已经成功地制作了 ActionSheet 和 imagePicker,但是无法确定在哪里添加修饰符来告诉每个按钮应该使用哪个 sourceType。我设法将它添加到 ActionSheet 之外的 sheet()
修饰符中的普通按钮中,一切正常:
Button(action:
self.show.toggle()
)
Text("Take a new picture")
.sheet(isPresented: self.$show, content:
ImagePicker(sourceType: .camera, show: self.$show, image: self.$imageTemp)
)
但是,我看不到在 ActionSheet 中的何处包含此信息。非常感谢任何可以提供帮助的人,我希望这很清楚:-)
这是我的代码:
struct ContentView: View
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View
NavigationView
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture
self.showingActionSheet = true
.actionSheet(isPresented: $showingActionSheet)
ActionSheet(title: Text("Image selector"), message: Text("Select an image"), buttons: [
.default(Text("Select from Gallery"))
self.show.toggle()
,
.default(Text("Take new picture"))
self.show.toggle()
,
.cancel()
]
)
而且,以防万一,这是我的 imagePicker 的代码,尽管我认为这可能没有必要。
struct ImagePicker: UIViewControllerRepresentable
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var show: Bool
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>)
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate
var child : ImagePicker
init(child1: ImagePicker)
child = child1
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
self.child.show.toggle()
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any])
let image = info[.originalImage]as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.show.toggle()
【问题讨论】:
【参考方案1】:您的问题几乎可以归结为“我怎样才能呈现多张纸?”,所以this thread 可能会有所帮助。
-
定义一个新的
enum
以包含可能的工作表类型(图库/拍照)
声明一个@State
属性来保存当前的工作表类型。它是可选的,因为当它为 nil 时,将不会显示任何工作表。
将属性设置为您想要的类型
使用sheet(item:onDismiss:content:)
而不是sheet(isPresented:onDismiss:content:)
。 isPresented
最适合静态表。 item
适用于您有多种工作表类型时,这是您想要的。
enum PhotoSheetType: Identifiable /// 1.
var id: UUID
UUID()
case gallery
case picture
struct ContentView: View
/// 2.
@State private var showingType: PhotoSheetType?
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View
NavigationView
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture
self.showingActionSheet = true
.actionSheet(isPresented: $showingActionSheet)
ActionSheet(
title: Text("Image selector"),
message: Text("Select an image"),
buttons: [
.default(Text("Select from Gallery"))
showingType = .gallery /// 3.
,
.default(Text("Take new picture"))
showingType = .picture /// 3.
,
.cancel()
]
)
/// 4.
.sheet(item: $showingType) type in
if type == .gallery
ImagePicker(sourceType: .photoLibrary, showingType: $showingType, image: self.$imageTemp)
else
ImagePicker(sourceType: .camera, showingType: $showingType, image: self.$imageTemp)
您还需要修改您的ImagePicker
,以便Binding
接受PhotoSheetType?
而不是Bool
。要关闭工作表,只需将 showingType
设置为 nil。
struct ImagePicker: UIViewControllerRepresentable
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var showingType: PhotoSheetType?
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>)
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate
var child : ImagePicker
init(child1: ImagePicker)
child = child1
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
self.child.showingType = nil /// set to nil here
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any])
let image = info[.originalImage] as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.showingType = nil /// set to nil here
【讨论】:
这是一个很棒的答案!超级清晰,解释清楚。你也是对的,它与另一个问题相似,我认为将代码放在 ActionSheet 中让我有点失望。唯一的事情是,当我尝试它时,我在控制台上收到消息“应用程序试图以模态方式呈现一个视图控制器 已经由 呈现”。看起来某个地方的“showingActionSheet”太多了,但我太菜鸟了,看不到确切的位置。 @FPL 上面的代码是否会出现消息?当我测试它很好时,问题可能在你的代码中的其他地方 你说得对,我在别处发现了这个错误。非常感谢!以上是关于为每个操作表按钮添加不同的修饰符的主要内容,如果未能解决你的问题,请参考以下文章