I'm really excited about this new feature of building full SwiftUI app.
However, as a big user of CoreData, I would like to know if there was an easy way to use it with this new lifecycle management.
Xcode grays out the coredata option when a new project is created using App lifecycle.
Should we simply put all the Coredata setup inside one ObservableObject or is there any good practices to use?
Post
Replies
Boosts
Views
Activity
I just saw the available video according SwiftData and wanted to convert a project of mine.
Both documentation and video mention this:
By default, SwiftData includes all noncomputed properties of a class as long as they use compatible types. The framework supports primitive types such as Bool, Int, and String, as well as complex value types such as structures, enumerations, and other value types that conform to the Codable protocol.
I tried to model an enum but I always get an error regarding the conformance to PersistentModel
I made different type of enum all implementing RawRepresentable but I always get an error
For example:
enum Simple: Int16 {
case one, two
}
@Model
class Item {
var simple: Simple = .one
}
I got those errors:
No exact matches in call to instance method 'getValue'
Candidate requires that 'Simple' conform to 'PersistentModel' (requirement specified as 'Value' : 'PersistentModel')
Candidate requires that 'Simple' conform to 'Sequence' (requirement specified as 'Value' : 'Sequence')
Did I miss something here?
Using SwiftData, I have a model that uses an enum as a property and a custom Codable type
import SwiftData
import CoreLocation
// MARK: - Main Model
@Model
class Cache {
var size: CacheSize?
var coordinates: CLLocationCoordinate2D
}
// MARK: - CacheSize Enum
enum CacheSize: CaseIterable, Codable {
case nano
case micro
case small
case regular
case large
case veryLarge
case notChosen
case virtual
case other
}
// MARK: - Codable for CLLocationCoordinate2D
extension CLLocationCoordinate2D: Codable {
enum CodingKeys: String, CodingKey {
case lat, lng
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.latitude, forKey: .lat)
try container.encode(self.longitude, forKey: .lng)
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let latitude = try container.decode(CLLocationDegrees.self, forKey: .lat)
let longitude = try container.decode(CLLocationDegrees.self, forKey: .lng)
self.init(latitude: latitude, longitude: longitude)
}
}
When I fetch the object from the ModelContext and try to access the property corresponding to this enum, I have a fatal error raised in BackingData.swift:
SwiftData/BackingData.swift:197: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(iGeo.CacheSize, Swift.DecodingError.Context(codingPath: [], debugDescription: "Invalid number of keys found, expected one.", underlyingError: nil))
When I try to read the CLLocationCoordinates2D property, I have also a crash in the Decodable init(from decoder: Decoder implementation when trying to read the first value from the container.
Did I miss something here or did something wrong?
Previously, it was recommended to use the @MainActor annotation for ObservableObject implementation.
@MainActor
final class MyModel: ObservableObject {
let session: URLSession
@Published var someText = ""
init(session: URLSession) {
self.session = session
}
}
We could use this as either a @StateObject or @ObservedObject:
struct MyView: View {
@StateObject let model = MyModel(session: .shared)
}
By moving to Observation, I need to the @Observable macro, remove the @Published property wrappers and Switch @StateObject to @State:
@MainActor
@Observable
final class MyModel {
let session: URLSession
var someText = ""
init(session: URLSession) {
self.session = session
}
}
But switching from @StateObject to @State triggers me an error due to a call to main-actor isolated initialiser in a synchronous nonisolated context.
This was not the case with @StateObject of @ObservedObject.
To suppress the warning I could :
mark the initializer as nonisolated but it is not actually what I want
Mark the View with @MainActor but this sounds odd
Both solutions does not sound nice to my eye.
Did I miss something here?
Using a NavigationStack and manipulating the NavigationPath “too fast” compared to the animation of the screen can leed visual artifacts and invalid state.
For example, let's create simple stack and create a custom back button.
struct StepView: View {
let value: Int
let action: () -> Void
var body: some View {
VStack {
Text("\(value)")
Button("Next", action: action)
}
}
}
struct ContentView: View {
@State var navigationPath: [Int] = []
var body: some View {
VStack {
if !self.navigationPath.isEmpty {
Button("Back customg") {
self.navigationPath.removeLast()
}
}
Divider()
NavigationStack(path: self.$navigationPath) {
Text("Root")
Button("Next") {
self.navigationPath.append(1)
}
.navigationDestination(for: Int.self) { integer in
StepView(value: integer) {
self.navigationPath.append(integer + 1)
}.navigationBarBackButtonHidden()
}
}
}
.padding()
}
}
Clicking fast on the custom back button will displays some blank screens and may leed to a crash.
Is something missing the API usage ? 🤔