I am currently following the tutorial from Hacking with swift url: (https://www.hackingwithswift.com/books/ios-swiftui/introduction-to-swiftdata-and-swiftui) to integrate SwiftData into a SwiftUI project. The code generated based on the tutorial is provided below. However, an error occurs upon launching the app: SwiftData/ModelContainer.swift:144: Fatal error: failed to find a currently active container for Student.
I am seeking assistance in resolving this issue.
import SwiftUI
import SwiftData
@Model
class Student {
var id: UUID
var name: String
init(id: UUID, name: String) {
self.id = id
self.name = name
}
}
@main
struct project8App: App {
var body: some Scene {
WindowGroup {
VStack {
ContentView()
}
}
.modelContainer(for: Student.self)
}
}
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@Query var students: [Student]
let allStudents = [
Student(id: UUID(), name: "John"),
Student(id: UUID(), name: "Paul"),
Student(id: UUID(), name: "George"),
Student(id: UUID(), name: "Ringo"),
]
var body: some View {
VStack {
ForEach(students) { student in
Text("\(student.name)")
}
Button(action: {
// random student
let student = allStudents.randomElement()!
modelContext.insert(student)
}) {
Text("Add/Change name")
}
}
}
}
P.S. It appears that the problem may be related to the container not being initialized by .modelContainer(for: Student.self). I have managed to resolve the error with the modified version below. However, I am still curious about the reasons behind the original version's malfunction and the differences between the two implementations.
// version 2, which is ok to run
@main
struct project8App: App {
let modelContainer: ModelContainer
init() {
do {
modelContainer = try ModelContainer(for: Student.self)
} catch {
fatalError("Could not initialize ModelContainer")
}
}
var body: some Scene {
WindowGroup {
VStack {
ContentView()
}
}
.modelContainer(modelContainer)
}
}
Post
Replies
Boosts
Views
Activity
In SwiftUI, I have a class Notebook that contains an id property. I am encountering a compilation error when I attempt to initialize a Query filter using notebook.id. However, when I assign notebook.id to a local constant id and use that in the filter, the code compiles successfully.
Here is the code snippet:
@Query var wordNotes: [WordNote]
init(notebook: Notebook) {
self.notebook = notebook
let id = notebook.id
_wordNotes = Query(filter: #Predicate<WordNote> { ** in
**.notebookId == notebook.id // fails to compile
**.notebookId == id // compiles successfully
}, sort: \.createTime)
}
The compilation error I receive when using notebook.id directly is: Cannot convert value of type 'PredicateExpressions.Equal<PredicateExpressions.KeyPath<PredicateExpressions.Variable<WordNote>, String>, PredicateExpressions.KeyPath<PredicateExpressions.Value<Notebook>, String>>' to closure result type 'any StandardPredicateExpression<Bool>'.
It appears that the failing code is being converted into a PredicateExpressions.Equal<> object, while the successful code is converted into a StandardPredicateExpression<Bool>.
Github Copilot said:
In Swift, closures capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables, hence the name "closures".
In your case, when you're using notebook.id directly inside the closure, Swift tries to capture the notebook object itself. However, because notebook is a complex object, Swift has trouble determining the exact type of the comparison expression, leading to the error you're seeing.
But, I have already define notebook: Notebook which means the notebook is a exact type of Notebook. Why the swift still can't determining the type?
I have also expand the macro in XCode shows:
Foundation.Predicate<WordNote>({ ** in // only <WordNote>
PredicateExpressions.build_Equal(
lhs: PredicateExpressions.build_KeyPath(
root: PredicateExpressions.build_Arg(**),
keyPath: \.notebookId
),
rhs: PredicateExpressions.build_KeyPath(
root: PredicateExpressions.build_Arg(notebook), // doesn't know what type is notebook
keyPath: \.id
)
)
})
Seems swift only declare that ** is type WordNote by <WordNote>, but why not declare notebook by another generic type?
Is uncomplished work of swiftui? Or any obstacle that I don't know?
Could you please explain the underlying reason for this behavior?
In SwiftData, what is the order of insertion for dependent and parent instances? In the snippet below, it works when the dependent instance is inserted before the parent. However, it fails when the order is reversed. Why is this the case?
//
// DebugView.swift
// gogodict
//
// Created by djzhu on 2024/1/13.
//
import Foundation
import SwiftData
import SwiftUI
struct DebugView: View {
@Query var parent: [ParentClass]
@Query var dept: [DependentClass]
var body: some View {
Text("parent cnt:\(parent.count), dept cnt:\(dept.count)")
}
}
@Model
class ParentClass {
@Relationship(deleteRule: .cascade)
var deps: DependentClass
init(deps: DependentClass) {
self.deps = deps
}
}
@Model
class DependentClass {
var id: String
init(id: String = UUID().uuidString) {
self.id = id
}
}
#Preview {
do {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try ModelContainer(for: ParentClass.self, configurations: config)
let context = ModelContext(container)
var dept = DependentClass()
var parentClass = ParentClass(deps: dept)
/* ok to insert dept before parent. View shows: "parent cnt:1, dept cnt:1" */
context.insert(dept)
context.insert(parentClass)
/* ok to insert only parent, swiftData will insert dept too. View shows: "parent cnt:1, dept cnt:1" */
// context.insert(parentClass)
/* failed to insert dept after parent, error list below */
// context.insert(parentClass)
// context.insert(dept)
return DebugView()
.modelContainer(container)
} catch {
return Text("Failed to create container: \(error.localizedDescription)")
}
}
The error log insert dept after parent:
Date/Time: 2024-01-13 14:10:10.3694 +0800
Launch Time: 2024-01-13 14:10:09.9932 +0800
OS Version: macOS 14.1.1 (23B81)
Release Type: User
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001929f3938
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [51868]
Triggered by Thread: 0
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libswiftCore.dylib 0x1929f3938 _assertionFailure(_:_:file:line:flags:) + 248
1 SwiftData 0x1c42fc454 0x1c42d1000 + 177236
2 SwiftData 0x1c4315aac 0x1c42d1000 + 281260
3 SwiftData 0x1c42fd4e0 0x1c42d1000 + 181472
4 DebugView.1.preview-thunk.dylib 0x10161ae10 closure #1 in static $s39gogodict_PreviewReplacement_DebugView_133_20B25209EACDFA98A88DFB5B90B26E4CLl0B0fMf_15PreviewRegistryfMu_.makePreview() + 840 (@__swiftmacro_39gogodict_PreviewReplacement_DebugView_133_20B25209EACDFA98A88DFB5B90B26E4CLl0B0fMf_.swift:18)
5 PreviewsInjection 0x1d6aaa0ec 0x1d6a6f000 + 241900
6 PreviewsInjection 0x1d6aab060 0x1d6a6f000 + 245856
7 libswift_Concurrency.dylib 0x1e450b738 static MainActor.assumeIsolated<A>(_:file:line:) + 144
8 PreviewsInjection 0x1d6aa9e48 0x1d6a6f000 + 241224
9 PreviewsInjection 0x1d6aadfb8 0x1d6a6f000 + 257976
10 PreviewsInjection 0x1d6aaea88 0x1d6a6f000 + 260744
11 PreviewsInjection 0x1d6a9c89c 0x1d6a6f000 + 186524
12 PreviewsInjection 0x1d6a9f5c8 0x1d6a6f000 + 198088
13 PreviewsInjection 0x1d6a87c90 0x1d6a6f000 + 101520
14 PreviewsInjection 0x1d6a88128 0x1d6a6f000 + 102696
15 PreviewsInjection 0x1d6aa0fa0 0x1d6a6f000 + 204704
16 PreviewsInjection 0x1d6a777b8 0x1d6a6f000 + 34744
17 PreviewsInjection 0x1d6a77004 0x1d6a6f000 + 32772
18 PreviewsFoundation 0x1d69b4630 0x1d691c000 + 624176
19 libdispatch.dylib 0x18016b4f4 _dispatch_call_block_and_release + 24
20 libdispatch.dylib 0x18016cd3c _dispatch_client_callout + 16
21 libdispatch.dylib 0x18017bb24 _dispatch_main_queue_drain + 1272
22 libdispatch.dylib 0x18017b61c _dispatch_main_queue_callback_4CF + 40
23 CoreFoundation 0x1803f1a30 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
24 CoreFoundation 0x1803ec148 __CFRunLoopRun + 1936
25 CoreFoundation 0x1803eb5a4 CFRunLoopRunSpecific + 572
26 GraphicsServices 0x18e9fbae4 GSEventRunModal + 160
27 UIKitCore 0x1852f02e4 -[UIApplication _run] + 868
28 UIKitCore 0x1852f3f5c UIApplicationMain + 124
29 SwiftUI 0x1c51fc1b0 0x1c4371000 + 15249840
30 SwiftUI 0x1c51fc050 0x1c4371000 + 15249488
31 SwiftUI 0x1c4f02fa4 0x1c4371000 + 12132260
32 gogodict 0x1009f03b0 static GOGODictApp.$main() + 40
33 gogodict 0x1009f0474 main + 12 (GOGODictApp.swift:12)
34 dyld_sim 0x100bfd544 start_sim + 20
35 dyld 0x100ce60e0 start + 2360
It seems perplexing to someone new like me. Is there any documentation or article that explains the underlying logic of the engine?
I'm encountering a crash in my SwiftUI app when it is opened via an AppIntent. The app runs perfectly when launched by tapping the app icon, but it crashes when opened from an intent.
Here is a simplified version of my code:
import AppIntents
import SwiftData
import SwiftUI
@main
struct GOGODemoApp: App {
@State
private var state: MyController = MyController()
var body: some Scene {
WindowGroup {
MyView()
//.environment(state) // ok
}
.environment(state) // failed to start app, crash with 'Dispatch queue: com.apple.main-thread'
}
}
struct MyView: View {
@Environment(MyController.self) var stateController
var body: some View {
Text("Hello")
}
}
@Observable
public class MyController {
}
struct OpenIntents: AppIntent {
static var title: LocalizedStringResource = "OpenIntents"
static var description = IntentDescription("Open App from intents.")
static var openAppWhenRun: Bool = true
@MainActor
func perform() async throws -> some IntentResult {
return .result()
}
}
Observations:
The app works fine when launched by tapping the app icon.
The app crashes when opened via an AppIntent.
The app works if I inject the environment in MyView instead of in WindowGroup.
Question:
Why does injecting the environment in WindowGroup cause the app to crash when opened from an intent, but works fine otherwise? What is the difference when injecting the environment directly in MyView?
I have a simple SwiftUI application that sends a URLRequest as shown in the code snippet below:
import SwiftUI
@main
struct GOGODemoApp: App {
var body: some Scene {
WindowGroup {
MyView()
}
}
}
struct MyView: View {
var body: some View {
Button("Click") {
sendHTTPRequest(to: "https://www.google.com") { code, err in
print("Finished, code: \(code ?? -1), err: \(String(describing: err))")
}
}
}
}
func sendHTTPRequest(to urlString: String, completion: @escaping (Int?, Error?) -> Void) {
guard let url = URL(string: urlString) else {
completion(nil, NSError(domain: "InvalidURL", code: 0, userInfo: nil))
return
}
let task = URLSession.shared.dataTask(with: url) { _, resp, error in
if let httpResponse = resp as? HTTPURLResponse {
completion(httpResponse.statusCode, error)
} else {
completion(-1, error)
}
}
task.resume()
}
However, Xcode prints the following warning messages:
nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint
Finished, code: 200, err: nil
What does the warning 'Connection has no local endpoint' mean?
Thank you for your assistance!