在一个位置更改图像时,如何使其反映SwiftUI中其他位置的更改?
我有两个问题在一个位置更改图像时,如何使其反映SwiftUI中其他位置的更改?,swiftui,Swiftui,我有两个问题 我有一个图像作为按钮,所以当你点击它时,你可以从你的图像卷中选择一个图像。当我转到另一个视图,然后返回时,图像消失了。当我在SwiftUI中更改视图时,如何防止它消失 如何将其链接到应用程序中的其他UIImages,以便当您更改某个位置的图像时,它会反映其他位置的更改?现在顶部的图像是硬编码的,但我希望它能反映较小的图像显示的内容。我已经在下面添加了一张图片来展示我正在谈论的内容,或者你可以查看它的视频 这是我的密码: import SwiftUI struct ImagePi
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()
}
}
}
导入快捷界面
结构图像选择器:视图{
@状态变量isShowingImagePicker=false
@状态变量imageInBlackCircle=UIImage()
var body:一些观点{
VStack{
按钮(操作:{
self.isShowingImagePicker.toggle()文件
}) {
图像(uiImage:imageInBlackCircle)
.renderingMode(.original)
.可调整大小()
.scaledToFill()
.clipShape(圆())
.overlay(圆圈().stroke(颜色.黑色,线宽:1))
.阴影(颜色:黑色,半径:3,x:0,y:3)
.框架(宽度:60.0,高度:70.0)
.padding(.training,20)
.sheet(显示:$isShowingImagePicker,内容:{
ImagePickerView(显示:self.$isShowingImagePicker,选择图像:self.$imageInBlackCircle)
})
}
}
}
结构ImagePickerView:UIViewControllerRepresentable{
@显示绑定变量:Bool
@绑定变量SelecteImage:UIImage
func makeUIViewController(上下文:
UIViewControllerRepresentableContext)->
UIViewController{
let controller=UIImagePickerController()
controller.delegate=context.coordinator
返回控制器
}
func makeCoordinator()->ImagePickerView.Coordinator{
退货协调员(家长:本人)
}
类协调器:NSObject、UIImagePickerControllerDelegate、UINavigationControllerDelegate{
让父对象:ImagePickerView
初始化(父项:ImagePickerView){
self.parent=parent
}
func imagePickerController(picker:UIImagePickerController,didFinishPickingMediaWithInfo:[UIImagePickerController.InfoKey:Any]){
如果让我们选择dImageFromPicker=info[.originalImage]作为?UIImage{
打印(从选择器中选择图像)
self.parent.selectedImage=selectedimagefromfrompicker
}
self.parent.isPresented=false
}
}
func updateUIViewController(uUIViewController:ImagePickerView.UIViewControllerType,上下文:UIViewControllerRepresentableContext){
}
}
结构ImagePicker\u预览:PreviewProvider{
静态var预览:一些视图{
图像选择器()
}
}
}
因此,您现在知道了@State
的用法。它们是特殊类型的属性,这些属性有助于SwiftUI
视图在其值发生任何更改时重新加载。这确保了同步。所以,如果你需要把这个财产和其他地方联系起来,你需要绕过这个财产,对吗?但出于设计:
@State
非常适合于属于特定视图的简单属性,并且永远不会在该视图之外使用,因此,将这些属性标记为私有非常重要,以重新强化这样一种理念,即这种状态是专门设计的,永远不会脱离其视图
那么我们有什么?注意: 对于更复杂的属性–当您要使用的自定义类型可能具有多个属性和方法,或者可能在多个视图中共享时–您应该使用
@ObservedObject
你可以从中读到更多
上述说法有意义吗?如果是,则需要此@ObservedObject
。让我们看看我们是如何做到这一点的
您声明的对象符合observeObject
。您使用@Published
包装器标记这些属性,以便所述observeObject
的任何实例都会收到对该属性所做更改的通知
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
是一个与您的配置稍有不同的演示实现。您可以去看看我得到了什么。当您点击profile选项卡并在那里更改图像时,我希望它在同一屏幕上以及在home选项卡上更改。此外,我希望它能保持不变,而不是在你更改标签或关闭应用程序时消失。我尝试了你的建议,但我无法让它对我起作用。还有你的评论,我希望它保持不变,而不是在你改变标签时消失。如果你已经研究了我对你的简单案例的最后一行所说的话,这应该足够了。但是,如果您需要从视图层次结构的任何位置访问有状态对象,您可能需要查看@EnvironmentObject
。一旦你找到了我之前评论的解决方案