简体   繁体   English

我的视图在 SwiftUI 中不断渲染

[英]My View keeps rendering over and over in SwiftUI

Here is my view:这是我的看法:

struct EditProfile: View {
    @State var bio = UserDefaults.standard.string(forKey: "bio") ?? "Edit your bio"
    @ObservedObject var storage = FirebaseStorage()
    @State var text = ""
    let photos = ["img1", "img2", "img3"]
    var body: some View {
        VStack {
            Text("Photos")
            .font(Font.system(size: 21))
            .fontWeight(.bold)
            HStack {
                ForEach(photos, id: \.self){ img in
                    EditableCircleImage(kfImage: self.storage.makeCircleImage(str: img))
                }
            }
            .background(
                RoundedRectangle(cornerRadius: 10)
                    .fill(Color.white)
                    .shadow(color: .gray, radius: 1, x: 0, y: 1)
            )

            Text("Bio")
                .font(Font.system(size: 21))
                .fontWeight(.bold)
            MultiTextField(txt: $text)
                .padding(10)
                .cornerRadius(20.0)
                .background(
                    RoundedRectangle(cornerRadius: 10)
                        .fill(Color.white)
                        .shadow(color: .gray, radius: 1, x: 0, y: 1)
                )
                .border(Color.gray.opacity(0.5), width: 1)

        }.padding(20).background(Color.gray.opacity(0.1))
    }
}

Here is the EditableCircleImage() :这是EditableCircleImage()

struct EditableCircleImage: View {
    let kfImage: KFImage
    var body: some View {
        ZStack {
            kfImage
                .resizable()
            .scaledToFit()
            .frame(height: 200)
                .clipShape(Circle())
                .overlay(Circle().stroke(Color.orange, lineWidth: 2))
            Button(action: {}){
                Image(systemName: "pencil.circle.fill")
                    .resizable()
                    .scaledToFit()
                    .frame(height: 40)
                .foregroundColor(.gray)

            }.offset(x: 40, y: 50)
        }
    }
}

Here is the model which returns the image: FirebaseStorage.swift :这是返回图像的 model: FirebaseStorage.swift

class FirebaseStorage: ObservableObject {
    let storage = Storage.storage()
    let uid = UserAuth().uid ?? "<uid>"
    @Published var img1 = UserDefaults.standard.string(forKey: "img1") ?? "<img1>"

    func makeCircleImage(str: String) -> KFImage {
        if let url = UserDefaults.standard.string(forKey: str) {
            print("not nil: \(str)")
            return KFImage(URL(string: "http://app-23c8s.appspot.com.storage.googleapis.com/users/\(uid)/\(url)"))
        }
        else {
            print("is nil: \(str)")
            return KFImage(source: nil)
        }

    }
}

The print statements in the model above print over and over, even though no values have changed after the initial render.上面 model 中的打印语句一遍又一遍地打印,即使在初始渲染后没有任何值发生变化。 Any idea why?知道为什么吗?

Constantly prints:不断打印:

not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3
not nil: img1
is nil: img2
is nil: img3

UPDATE:更新:

I changed:我变了:

ForEach(photos, id: \.self){ img in
    EditableCircleImage(kfImage: self.storage.makeCircleImage(str: img))
}

to

EditableCircleImage(kfImage: self.storage.makeCircleImage(str: "img1"))

and now it prints:现在它打印:

not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1
not nil: img1

Remove conformance of FirebaseStorage class to ObservableObject and remove the property wrapper @ObservedObject from @ObservedObject var storage = FirebaseStorage() .删除 FirebaseStorage class 与 ObservableObject 的一致性,并从@ObservedObject var storage = FirebaseStorage()中删除属性包装器 @ObservedObject。 Remove @Published property wrapper too.也删除 @Published 属性包装器。 Run it and let me know if the issue persists.运行它并让我知道问题是否仍然存在。 By the way it is unclear to me as to why you have made the class conform to ObservableObject and why you have used the property wrapper in this specific use case.顺便说一句,我不清楚您为什么使 class 符合 ObservableObject 以及为什么在这个特定用例中使用属性包装器。 If I am missing something, do let me know.如果我遗漏了什么,请告诉我。 Assumed that this post includes the entire code for the problem you are talking about.假设这篇文章包含您所讨论问题的完整代码。 Hopefully this helps you out.希望这可以帮助你。

It seems that看起来

func makeCircleImage(str: String) -> KFImage { ... }

is an asynchronous function, in particular KFImage(..).是一个异步 function,特别是 KFImage(..)。 You use this in:您可以在以下情况下使用它:

ForEach(photos, id: \.self){ img in
     EditableCircleImage(kfImage: self.storage.makeCircleImage(str: img))
}

This is probably the source of the problem.这大概就是问题的根源。 You really should wait until you have all you images before using them, especially in a View.您真的应该等到拥有所有图像后再使用它们,尤其是在视图中。

Changing my code to this:将我的代码更改为:

struct EditProfile: View {
    @State var bio = UserDefaults.standard.string(forKey: "bio") ?? "Edit your bio"
    @ObservedObject var storage = Storages()
    @State var text = ""
    let uid = UserAuth().uid ?? "<uid>"
    let photos: [String:String] = [
        "img1": UserDefaults.standard.string(forKey: "img1") ?? "",
        "img2": UserDefaults.standard.string(forKey: "img2") ?? "",
        "img3": UserDefaults.standard.string(forKey: "img3") ?? "",
    ]
    var body: some View {
        VStack {
            Text("Points")
            .font(Font.system(size: 21))
            .fontWeight(.bold)
            HStack {
                ForEach(photos.sorted(by: <), id: \.key){ (key,val) in
                    EditableCircleImage(
                        kfImage: KFImage(
                            URL(string: "http://app-23c8s.appspot.com.storage.googleapis.com/users/\(self.uid)/\(val)")
                        ),
                        key: key
                    )
                }
            }

struct EditableCircleImage: View {
    let kfImage: KFImage
    let key: String
    var body: some View {
        ZStack {
            kfImage

fixed the problem.解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM