Hello. I am new to swift programming and I am encountering the following problem. I have a project with several Views. Some Views query a database in sqlite, with which I have in each view the access code and query that database. My question is, how could I make a global query procedure to the database that can be called from any view. This saves me from having repeated code in each view. I've looked on various sites but can't find any information on this. Thanks .
One tool to approach that would be @Environment
from SwiftUI. It allows for the storage of a value or reference out of band of the SwiftUI view's storage.
Good morning. First of all, thanks for answering me. But I have to tell you that that is not what I am looking for, what I am looking for in SWIFT is where to create a procedure (in this case it is a call to a database where I make several queries), a general procedure that can be called from any view. (so I save having the same code to call the database in each view). Thanks.
What you may be looking for is a singleton - or rather a static instance of a class:
final class MyDatabase {
static let shared: MyDatabase = MyDatabase()
init() { }
func foo() { ... }
}
MyDatabase.shared.foo()
You may also declare a function in a global scope (just declare a function outside any type).
There are several issues.
1/ The problem is, this does not work well with SwiftUI. SwiftUI needs "a source of truth" - which in your case would be the result of a fetch query (or a result of any query in general, if you desire to present it to the user). You need to store said results somewhere, where SwiftUI can interact with the results and update itself whenever the result updates. Thats one reason why you might look at @Environment
(or @State
/@Binding
etc.)
2/ The other problem is, that using singletons (or worse - global functions) is looked upon as a bad style. One of the more valid arguments agains singletons (in my view) is, that it makes your code really hard to maintain. It goes into Dependency Injection
if you want to learn more.
Fortunately, the @Environment
API makes this really easy. Let's say we have a view called MyView
and MyDatabse
class with function update()
which is called by View in order to update Database:
final class MyDatabase: ObservableObject {
@Published public var databaseUpToDate: Bool = true // the source of truth for SwiftUI
init() {}
func update() { databaseUpToDate = updateDatabase() } // Called by SwiftUI View
private func updateDatabase() -> Bool { return true }
}
struct MyView: View {
@EnvironmentObject var database: MyDatabase // This makes your instance of database accessible to the view
var body: some View {
VStack {
Button("update") { database.update() }
Text( database.databaseUpToDate ? "Up to date" : "Error" )
}
}
}
// Consider another view for better demonstration
struct TopLevelView: View {
var body: some View { MyView() }
}
struct YourApp: App {
var body: some Scene {
TopLevelView().environmentObject(MyDatabase()) // here is the instance of the `MyDatabase` class created and propagated to all Views, that declare the `@EnvironmentObject var database: MyDatabase` variable
}
}
I haven't checked, whether this snippet builds or not (it's taken from my macOS app), but it demonstrates the usage of @Environment
well enough. I would encourage you to use this (or other more SwiftUI-like) approach.
Good morning. First of all, thanks for answering me. But I have to tell you that that is not what I am looking for, what I am looking for in SWIFT is where to create a procedure (in this case it is a call to a database where I make several queries), a general procedure that can be called from any view. (so I save having the same code to call the database in each view). Thanks.
Good morning. Thanks for the reply. Now I need time to process all the information hehehehe. Thanks for answering me.
I remember, when I was programming in C, that I created a library with an .h extension and there I could store all the procedures I wanted. Then I would import that library and in any place I could execute the functions that were in that library that I had created before. That is what I want to do in swift for my project. Thanks.
I remember, when I was programming in C, that I created a library with an .h extension and there I could store all the procedures I wanted. Then I would import that library and in any place I could execute the functions that were in that library that I had created before. That is what I want to do in swift for my project. Thanks.