How to correctly fetch data using SwiftData

Hi there! I'm making an app that stores data for the user's profile in SwiftData. I was originally going to use UserDefaults but I thought SwiftData could save Images natively but this is not true so I really could switch back to UserDefaults and save images as Data but I'd like to try to get this to work first. So essentially I have textfields and I save the values of them through a class allProfileData. Here's the code for that:

import SwiftData
import SwiftUI

@Model
class allProfileData {
    var profileImageData: Data?
    var email: String
    var bio: String
    var username: String
    
    var profileImage: Image {
        if let data = profileImageData,
           let uiImage = UIImage(data: data) {
            return Image(uiImage: uiImage)
        } else {
            return Image("DefaultProfile")
        }
    }
    
    init(email:String, profileImageData: Data?, bio: String, username:String) {
        self.profileImageData = profileImageData
        self.email = email
        self.bio = bio
        self.username = username
    }
}

To save this I create a new class (I think, I'm new) and save it through ModelContext

import SwiftUI
import SwiftData
struct CreateAccountView: View {
@Query var profiledata: [allProfileData] 
@Environment(\.modelContext) private var modelContext

 let newData = allProfileData(email: "", profileImageData: nil, bio: "", username: "")
 var body: some View {
       Button("Button") {
                newData.email = email 
                modelContext.insert(newData)
                try? modelContext.save()
                print(newData.email)
      }
  }
}

To fetch the data, I originally thought that @Query would fetch that data but I saw that it fetches it asynchronously so I attempted to manually fetch it, but they both fetched nothing

import SwiftData
import SwiftUI
 @Query var profiledata: [allProfileData] 
    @Environment(\.modelContext) private var modelContext
let fetchRequest = FetchDescriptor<allProfileData>()
let fetchedData = try? modelContext.fetch(fetchRequest)
print("Fetched count: \(fetchedData?.count ?? 0)")
if let imageData = profiledata.first?.profileImageData,
  let uiImage = UIImage(data: imageData) {
   profileImage = Image(uiImage: uiImage)
} else {
  profileImage = Image("DefaultProfile")
   }

No errors. Thanks in advance

please I need help don't get buried in all the other posts

  1. I would look into @Attribute(.trasformable) macro to save images (haven't tried it myself, but I think that's the direction worth investigating.
  2. I don't see any view in you last code, but I think in your pattern data is being fetched on init, but you actually can access it no earlier than in .onAppear modifier. So I would try something like:
@State var count: Int = 0
....
var body: some View {
    Text("\(count)")
    .onAppear {
        count = fetchedData?.count ?? 0
    }
}

And put the fetching part in init method of your view.

I find the question a bit confusing. Firstly, are you talking about saving and fetching objects in general or is it the specific image property of type Data you mean when you write “data” in the question? Secondly it’s very hard to understand the last segment of code.

My code for the last block:

import SwiftUI
import SwiftData
struct HomeView: View {
    @Query var profiledata: [allProfileData] //get all profiledata
    @Environment(\.modelContext) private var modelContext
    @State private var profileImage: Image = Image("DefaultProfile")
    var body: some View {
VStack {
	profileImage
	}
 .onAppear() {
            let fetchRequest = FetchDescriptor<allProfileData>()
            let fetchedData = try? modelContext.fetch(fetchRequest)
            print("Fetched count: \(fetchedData?.count ?? 0)")

            if let imageData = profiledata.first?.profileImageData,
               let uiImage = UIImage(data: imageData) {
                profileImage = Image(uiImage: uiImage)
            } else {
                profileImage = Image("DefaultProfile")
            } //yes, I realize that I could use profiledata.first?.profileImage but I was just checking if profileImageData would save or not
				}
		}
}

Do you get any error message in the console when you save?

Could you replace try? with try when saving to see if any error is thrown

do {
    try modelContext.save()
} catch {
    print(error)
}

How is your model container declared and used?

Sorry got confused with all the code.

import SwiftUI
import SwiftData
@main
struct fbla_appApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(for: allProfileData.self)
    }
}

It may be that you don't really have any image data being saved. An an indication, the following code has nil image data:

let newData = allProfileData(email: "", profileImageData: nil, bio: "", username: "")
var body: some View {
    ...
}

If you can provide a minimal runnable project that reproduces the issue. Folks here may be able to help more effectively.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

How to correctly fetch data using SwiftData
 
 
Q