Skip to main content

iOS (SwiftUI)

This sample shows a SwiftUI app that uses Concurrency APIs to interact with AFCore.

Replace placeholders like Your-API-Key and Your-Base-Url with your real values.

iOS (Swift)

iosApp.swift

import SwiftUI
import AFCore

@main
struct iOSApp: App {
init() {
do {
let config = AFCoreConfig.Builder()
.authKey(value: "[Your_API_Key]")
.baseUrl(value: "[Your_Base_Url]")
.swAuthKey(value: "[Your_SW_API_Key]")
.swBaseUrl(value: "[Your_SW_Base_Url")
.enableLogging(value: true)
.logLevel(value: AFLogLevel.debug)
.build()

try AFCore.shared.initialize(config: config)
} catch {
print("Error initializing AFCore")
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

ContentView.swift

import SwiftUI

struct ContentView: View {
@StateObject private var viewModel = AFCoreSampleViewModel()

var body: some View {
NavigationView {
ScrollView {
VStack(spacing: 16) {
Text("AFCore iOS Sample")
.font(.largeTitle)
.padding(.top)

ResultBoxView(result: viewModel.resultText)

if viewModel.isLoading {
ProgressView().padding(.bottom)
}

if viewModel.isLoggedIn {
MainSectionsView(viewModel: viewModel)
} else {
LoginView(viewModel: viewModel)
}
}
.padding()
}
}
}
}

LoginView.swift

import SwiftUI

struct LoginView: View {
@ObservedObject var viewModel: AFCoreSampleViewModel
@Environment(\.openURL) var openURL

private let forgotPasswordURL = URL(string: "https://api.activefitplus.com/recoverpassword")!

var body: some View {
VStack(spacing: 20) {
Spacer()

VStack(spacing: 8) {
Text("Sign in to continue")
.font(.subheadline)
.foregroundColor(.secondary)
}

VStack(spacing: 16) {
TextField("Username", text: $viewModel.username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.autocapitalization(.none)

SecureField("Password", text: $viewModel.password)
.textFieldStyle(RoundedBorderTextFieldStyle())

HStack {
Spacer()
Button("Forgot Password?") {
openURL(forgotPasswordURL)
}
.font(.footnote)
}

Button(action: {
Task { await viewModel.login() }
}) {
if viewModel.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
.frame(maxWidth: .infinity)
} else {
Text("Login")
.frame(maxWidth: .infinity)
.padding()
.background(Color.accentColor)
.foregroundColor(.white)
.cornerRadius(8)
}
}
}
.padding(.horizontal)

Spacer()
}
.padding()
}
}

MainSectionsView.swift

import SwiftUI
import AFCore

struct MainSectionsView: View {
@ObservedObject var viewModel: AFCoreSampleViewModel

var body: some View {
VStack(alignment: .leading, spacing: 16) {
Group {
Text("🔋 HealthKit Actions")
.font(.headline)

Button("🔗 Connect to Apple Health") {
Task { await viewModel.connectToHealthKit() }
}

Button("🚶 Sync SmartWalking Profile") {
Task { await viewModel.fetchSmartWalkingProfile() }
}

Button("🚶 Sync SmartWalking Steps") {
Task { await viewModel.syncSmartWalkingSteps() }
}

Divider()
}

Group {
Text("📍 Geofencing Actions")
.font(.headline)

Button("🟢 Start Geofencing") {
Task { await viewModel.startGeofencing() }
}

Button("🔴 Stop Geofencing") {
Task { await viewModel.stopGeofencing() }
}

Divider()
}

Group {
Text("📡 API Sample Calls")
.font(.headline)

Button("👟 Fetch My Activities") {
Task { await viewModel.fetchActivities() }
}

Button("💳 Fetch Payments History") {
Task { await viewModel.fetchPayments() }
}

Button("⚙️ Load Application Settings") {
Task { await viewModel.fetchApplicationSettings() }
}

Button("🔥 Get Firebase Token") {
Task { await viewModel.fetchFirebaseToken() }
}

Button("🧠 Fetch Mental Fitness Data") {
Task { await viewModel.fetchMentalFitnessResources() }
}

Button("🏃‍♂️ Get Movement Health Status") {
Task { await viewModel.fetchMovementHealthStatus() }
}

Button("📲 Get MyCarePath URL") {
Task { await viewModel.fetchMyCarePathTasks() }
}

Button("👤 Fetch Profile Info") {
Task { await viewModel.fetchProfileInfo() }
}

Button("🎯 Fetch Programs") {
Task { await viewModel.fetchPrograms() }
}

Button("📝 Get Self-Report Data") {
Task { await viewModel.fetchSelfReports() }
}

Button("🧩 Load Custom UI Items") {
Task { await viewModel.fetchUserInterfaceItems() }
}

Button("🎥 Check VirtualFitness (NEOU)") {
Task { await viewModel.fetchVirtualFitnessClasses() }
}

Divider()
}

Group {
Text("🔐 Request Permissions")
.font(.headline)

Button("📍 Location (When In Use)") {
Task { await viewModel.requestPermission(.fineLocation) }
}

Button("📍 Location (Always)") {
Task { await viewModel.requestPermission(.backgroundLocation) }
}

Button("🔵 Bluetooth LE Access") {
Task { await viewModel.requestPermission(.bluetoothLe) }
}

Button("🏋️ Motion & Fitness Access") {
Task { await viewModel.requestPermission(.physicalActivity) }
}

Divider()
}

Group {
Text("🔓 Session")
.font(.headline)

Button("🚪 Logout") {
Task { await viewModel.logout() }
}
}
}
.padding(.bottom, 24)
}
}

ResultBoxView.swift

import SwiftUI

struct ResultBoxView: View {
let result: String

var body: some View {
if !result.isEmpty {
Text(result)
.padding()
.background(Color.secondary.opacity(0.1))
.cornerRadius(8)
.multilineTextAlignment(.center)
}
}
}

AFCoreSampleViewModel.swift

import Foundation
import AFCore
import UIKit

final class AFCoreSampleViewModel: ObservableObject {
@Published var username = "600009"
@Published var password = "12345"
@Published var isLoading = false
@Published var resultText = ""
@Published var isLoggedIn: Bool = AFCore.shared.isLoggedIn()
@Published var authMessage: String?

// MARK: - Auth

func login() async {
isLoading = true
defer { isLoading = false }

do {
_ = try await AFCore.shared.authentication().login(username: username, password: password)
authMessage = "Login success"
isLoggedIn = true
} catch {
authMessage = "Login failed: \(error.localizedDescription)"
}
}

func refreshToken() async {
isLoading = true
defer { isLoading = false }

do {
_ = try await AFCore.shared.authentication().refreshSession()
authMessage = "Token refreshed"
} catch {
authMessage = "Refresh failed: \(error.localizedDescription)"
}
}

func logout() async {
isLoading = true
defer { isLoading = false }

do {
try await AFCore.shared.authentication().logout()
authMessage = "Logged out"
isLoggedIn = false
} catch {
authMessage = "Logout failed: \(error.localizedDescription)"
}
}

// MARK: - HealthKit / Permissions

func connectToHealthKit() async {
isLoading = true
defer { isLoading = false }


do {
let vendorIdentifier = await UIDevice.current.identifierForVendor?.uuidString ?? ""

try await AFCore.shared.smartWalking().connectAppleHealthKit(deviceId: vendorIdentifier)
self.resultText = "HealthKit permissions granted"
} catch {
self.resultText = "HealthKit error: \(error.localizedDescription)"
}
}

func requestPermission(_ permission: Permission) async {
do {
try await AFPermissions.shared.requestPermission(permission: permission)
self.resultText = "\(permission) granted"
} catch {
self.resultText = "\(permission) error: \(error.localizedDescription)"
}
}

// MARK: - API Calls

func startGeofencing() async {
isLoading = true
defer { isLoading = false }

do {
try await AFCore.shared.facilities().startMonitoring()
self.resultText = "Geofencing started"
} catch {
self.resultText = "Geofencing error: \(error.localizedDescription)"
}
}

func stopGeofencing() async {
isLoading = true
defer { isLoading = false }

do {
try await AFCore.shared.facilities().stopMonitoring()
self.resultText = "Geofencing stopped"
} catch {
self.resultText = "Geofencing error: \(error.localizedDescription)"
}
}

func fetchActivities() async {
await wrap {
let result = try await AFCore.shared.activities().get(month: 7, year: 2025)
self.resultText = "Fetched \(result.activities.count) activities"
}
}

func fetchPayments() async {
await wrap {
let payments = try await AFCore.shared.payments().get()
self.resultText = "Fetched \(payments.count) payments"
}
}

func fetchApplicationSettings() async {
await wrap {
_ = try await AFCore.shared.applicationSettings().getActiveFitSettings()
self.resultText = "App Settings loaded"
}
}

func fetchFirebaseToken() async {
await wrap {
let token = try await AFCore.shared.messaging().getToken()
self.resultText = "Firebase Token: \(String(describing: token))"
}
}

func fetchMentalFitnessResources() async {
await wrap {
let res = try await AFCore.shared.mentalFitness().getSpotItTechniqueData()
self.resultText = "Mental Fitness: \(res.situations.count) Situations"
}
}

func fetchMovementHealthStatus() async {
await wrap {
let status = try await AFCore.shared.movementHealth().isMovrProfileRegistered()
self.resultText = "Movement Health: \(status)"
}
}

func fetchMyCarePathTasks() async {
await wrap {
let url = try await AFCore.shared.myCarePath().getMyCarePathAccessUrl(redirect: nil)
self.resultText = "MyCarePath Access URL: \(url)"
}
}

func fetchProfileInfo() async {
await wrap {
let profile = try await AFCore.shared.profile().get()
self.resultText = "Profile: \(profile.firstName)"
}
}

func fetchPrograms() async {
await wrap {
let programs = try await AFCore.shared.programs().getAvailablePrograms()
self.resultText = "Programs: \(programs.count)"
}
}

func fetchSelfReports() async {
await wrap {
let reports = try await AFCore.shared.selfReport().get()
self.resultText = "SelfReports: \(reports.selfReportMonths.count)"
}
}

func fetchSmartWalkingProfile() async {
await wrap {
_ = try await AFCore.shared.smartWalking().getProfile()
self.resultText = "SmartWalking: Synced (check logs)"
}
}

func syncSmartWalkingSteps() async {
await wrap {
_ = try await AFCore.shared.smartWalking().syncSteps()
self.resultText = "SmartWalking: Synced (check logs)"
}
}

func fetchUserInterfaceItems() async {
await wrap {
let items = try await AFCore.shared.userInterface().getMenuItems()
self.resultText = "UI Items: \(items.count)"
}
}

func fetchVirtualFitnessClasses() async {
await wrap {
let registered = try await AFCore.shared.virtualFitness().isMemberRegisteredToNeou()
self.resultText = "Registered to NEOU: \(registered)"
}
}

// MARK: - Helper

private func wrap(_ action: @escaping () async throws -> Void) async {
isLoading = true
defer { isLoading = false }

do {
try await action()
} catch {
resultText = "Error: \(error.localizedDescription)"
}
}
}