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()
:
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
:
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. 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()
. Remove @Published property wrapper too. 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. 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(..). 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.