Orbit background info
We are on a mission to empower every university student the ability to find and approach other people who share similar interests. Ultimately helping each one of us create lifelong friendships. At its core, Orbit is an iOS consumer social app that addresses the isolation people feel despite living in a highly connected world. Its goal is to create a community where users—referred to as “astronauts”—can explore social connections, make friends, and feel a sense of belonging. It targets first-year univeristy students seeking to meet new people and build genuine relationships in a safe, personalized, and engaging environment.
Development
Architecture: MVVM + Services
The project uses the MVVM architecture with Services for backend calls where:
- Model (M): Enforces data types for data coming in and going to the database.
- View (V): Is the frontend graphic user interface (GUI/screen) the user interacts with.
- ViewModel (VM): Connects the Model to View ensuring the screens are redrawn with the data loaded in the ViewModel changes.
- Service: Are backend calls to the Appwrite database.
Example
Model
struct UserModel {
let accountId: String
let name: String
init(accountId: String, name: String){
self.accountId = accountId
self.name = name
}
}
typealias UserDocument = AppwriteModels.Document<UserModel>
View
struct UserView: View {
// The ViewModels are declared at the App.swift level as follows:
// @StateObject var userVM = UserViewModel()
// To use a ViewModel in a screen add the following line
@EnvironmentObject private var userVM: UserViewModel
var body: some View {
VStack {
Text(userVM.currentUser.name)
Button("Update Name") {
userVM.updateUser("New Name")
}
}
}
}
ViewModel
class UserViewModel {
@Published var currentUser: UserModel?
private var userService = UserService()
@MainActor
func updateUser(accountId: String, updatedUser: UserModel) async {
guard let updatedUserDocument = try await userService.updateUser(
accountId: accountId, updatedUser: updatedUser)
else {
throw NSError(domain: "User not found", code: 404, userInfo: nil)
}
if id == currentUser?.accountId {
// Update the currentUser
self.currentUser = updatedUser
}
}
}
Service
import Appwrite
class UserService {
func getUser(_ accountId: String) async throws -> UserDocument? {
let query = Query.equal(
"accountId",
value: accountId
) // Query by accountId
let response = try await appwriteService.databases.listDocuments<
UserModel
>(
databaseId: appwriteService.databaseId,
collectionId: collectionId,
queries: [query],
nestedType: UserModel.self
)
// Check if any document was found
if let document = response.documents.first {
return document
} else {
throw NSError(domain: "User not found", code: 404, userInfo: nil)
}
}
func updateUser(accountId: String, updatedUser: UserModel) async throws -> UserDocument?
{
// Step (1): Find the documentId based on accountId
guard let userDocument = try await getUser(accountId) else {
print("Cannot update user")
return nil
}
let documentId = userDocument.id
// Step (2): Perform update using the documentId
let updatedDocument = try await appwriteService.databases
.updateDocument<UserModel>(
databaseId: appwriteService.databaseId,
collectionId: collectionId,
documentId: documentId,
data: updatedUser.toJson(),
permissions: nil,
nestedType: UserModel.self
)
return updatedDocument
}
}