我有2个问题。
这是我的代码:
import SwiftUI
struct ImagePicker: View {
@State var isShowingImagePicker = false
@State var imageInBlackCircle = UIImage()
var body: some View {
VStack {
Button(action: {
self.isShowingImagePicker.toggle()
}) {
Image(uiImage: imageInBlackCircle)
.renderingMode(.original)
.resizable()
.scaledToFill()
.clipShape(Circle())
.overlay(Circle() .stroke(Color.black, lineWidth: 1))
.shadow(color: .black, radius: 3, x: 0, y: 3)
.frame(width: 60.0, height: 70.0)
.padding(.trailing, 20)
.sheet(isPresented: $isShowingImagePicker, content: {
ImagePickerView(isPresented: self.$isShowingImagePicker, selectedImage: self.$imageInBlackCircle)
})
}
}
}
struct ImagePickerView: UIViewControllerRepresentable {
@Binding var isPresented: Bool
@Binding var selectedImage: UIImage
func makeUIViewController(context:
UIViewControllerRepresentableContext<ImagePickerView>) ->
UIViewController {
let controller = UIImagePickerController()
controller.delegate = context.coordinator
return controller
}
func makeCoordinator() -> ImagePickerView.Coordinator {
return Coordinator(parent: self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent: ImagePickerView
init(parent: ImagePickerView) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let selectedImageFromPicker = info[.originalImage] as? UIImage {
print(selectedImageFromPicker)
self.parent.selectedImage = selectedImageFromPicker
}
self.parent.isPresented = false
}
}
func updateUIViewController(_ uiViewController: ImagePickerView.UIViewControllerType, context: UIViewControllerRepresentableContext<ImagePickerView>) {
}
}
struct ImagePicker_Previews: PreviewProvider {
static var previews: some View {
ImagePicker()
}
}
}
答案 0 :(得分:0)
因此,您现在知道@State
的用法。它们是特殊类型的属性,可以帮助SwiftUI
视图重新加载,以防其值发生任何更改。这样可以确保同步。因此,如果您还需要将此属性链接到其他位置,则需要传递该属性,对吗?但根据设计:
@State
非常适合属于特定视图且从不在该视图之外使用的简单属性,因此,将这些属性标记为私有很重要,以强化这种状态是专门为避免脱离其观点而设计的。
那我们有什么?注意:
对于更复杂的属性-当您要使用可能具有多个属性和方法的自定义类型时,或者可能在多个视图之间共享 –您应改用
@ObservedObject
。
您可以从What’s the difference between @ObservedObject, @State, and @EnvironmentObject?
阅读更多内容以上内容有意义吗?如果是,则需要此@ObservedObject
。让我们看看我们如何实现这一目标。
您声明一个符合ObservableObject
的对象。您用@Published
包装器标记了这些属性,以便使所说的ObservableObject
的任何实例都收到对该属性所做的更改的通知。
import Combine
import UIKit
class UserViewModel: ObservableObject {
@Published var image = UIImage()
}
现在,您需要在某处此对象的实例,以便可以观察其状态。那就是您将使用@ObservedObject
包装器的地方。
struct ImagePicker: View {
@State private var isShowingImagePicker = false // make this private
@State private var isShowingDetailView = false // make this private
@ObservedObject var viewModel = UserViewModel() // either you initialize this here,
// or inject this from somewhere else
}
然后,当您初始化其他视图以进行显示/演示时,只需绕过@ObservedObject
属性。喜欢:
NavigationLink(destination: DetailView(userViewModel: viewModel), isActive: $isShowingDetailView) {
Text("Detail")
}
您的DetailView
类似于:
struct DetailView: View {
var userViewModel: UserViewModel // you may need to declare this as @ObservedObject as well if you are required to manipulate state of UserViewModel from this view
var body: some View {
Image(uiImage: userViewModel.image)
.navigationBarTitle(Text("Detail"), displayMode: .inline)
}
}
对于您的简单情况,这应该足够了。但是,如果需要从视图层次结构中的任何位置访问有状态对象,则可能需要查看@EnvironmentObject
。