DatabaseKit (DBKit) Usage Example
This example demonstrates how to use the DB
environment object to interact with the database in your app.
Features
- Create a Post: Create a new post with a title and description. Anonymously or with a shared User ID.
- Browse Posts: See posts created by all other users.
- Delete Posts: Delete your posts or posts of other users.
- AnalyticsKit Integration: If AnalyticsKit is selected during project generation, events and errors regarding user
interacting with the DBKit Example will automatically be tracked with
db
as the source.
Demo
Here's a demo of the DBKit example in action:
Deep Dive
Definitions
The example defines a bunch of functions and parameters that are used to interact with the database.
Posts Collection
An array that contains fetched posts from the database.
@MainActor
public class DB: ObservableObject {
@Published var posts: [PostData] = []
}
Is of type PostData
:
struct PostData: Codable, Identifiable, Equatable {
@DocumentID var id: String?
let title: String
let content: String
let creationDate: Date
let postUserID: String?
}
Fetching Posts
The fetchPosts()
function fetches all posts from the database and sets the posts
array.
extension DB {
@MainActor
public func fetchPosts() async { }
}
Creating a Post (Anonymously)
The addPost()
function creates a new post with a title and content. The resulting postUserID
in the post
is set to Anonymous
. Returns a bool
value depending on the success of the operation.
extension DB {
public func addPost(title: String, content: String) async -> Bool { }
}
Creating a Post (With User ID)
The addSignedPost()
function creates a new post with a title and content.
The resulting postUserID
in the post is set to currently logged in user (see AuthKit).
extension DB {
public func addSignedPost(title: String, content: String) async -> Bool { }
}
Deleting a Post
The deletePost()
function deletes a post with a given id
.
Returns a bool
value depending on the success of the operation.
Note that any user can delete any post. (But we actually prevent doing that in the
UI using the executeIfSignedIn
function. See below).
extension DB {
public static func deletePost(id: String) async { }
}
Usage
In the DatabaseExampleView
, we use the DB
object and its variables and functions (defined above)
to interact with the database.
- When the view appears, we fetch all posts from the database using the
fetchPosts()
function. - We show each post in a
List
, by passing thedb.posts
array to theForEach
loop. - We have a
Button
to delete a post by callingdb.deletePost()
. We pass it to theexecuteIfSignedIn
function to prevent deleting posts of other users. This function is used to execute a block of code only if the user is signed in. After that we fetch all posts again. - In the toolbar we have a navigation link that opens the
PostCreationView
to create a new post. After creating a post, we fetch all posts again.
public struct DatabaseExampleView: View {
@EnvironmentObject var db: DB
// ...
public var body: some View {
NavigationStack(path: /* ... */) {
List {
// ...
ForEach(db.posts) { post in
// Below is a single post view
Section(
// Post Creation Date and User ID ("Anonymous" if nil)
footer: Text(
"\(post.creationDate.description) | by \(post.postUserID ?? "Anonymous")")
) {
HStack {
Text(post.title)
// ...
Button(role: .destructive) {
Task {
await db.executeIfSignedIn(withUserID: post.postUserID) {
await db.deletePost(id: post.id!)
}
await db.fetchPosts()
}
} label: {
Image(systemName: "trash")
}
}
Text(post.content)
}
}
}
// ...
// Fetch Data when View Appears
.onAppear {
// ...
await db.fetchPosts()
// ...
}
// ... pull down to refresh
.toolbar {
// ...
NavigationLink(value: DBExamplePath.postNew) {
Image(systemName: "square.and.pencil")
}
}
.navigationDestination(for: /* ... */) { path in
// ...
PostCreationView {
// ...
await db.fetchPosts()
// ...
}
}
}
}
}