The FAQ Provider delivers cached, searchable FAQs to your iOS app with automatic sync and offline support.
Initialization
Important: FAQProvider must be initialized separately from StringProvider.
FAQProvider.shared.initialize(
cacheSize: 200,
apiToken: "YOUR_API_TOKEN",
baseURL: "https://api.stringboot.com"
)
// Setup auto-sync (recommended)
Task {
let locale = StringProvider.shared.deviceLocale()
// Preload FAQs from cache for instant access
await FAQProvider.shared.preloadFromDatabase(lang: locale, maxFAQs: 100)
// Sync latest FAQs from server in background
await FAQProvider.shared.refreshFromNetwork(lang: locale)
}
The preload step ensures FAQs are available immediately when your app opens, while the background sync fetches the latest updates.
Usage
Fetching FAQs
Task {
// Get FAQs for a specific tag
let faqs = await FAQProvider.shared.getFAQs(tag: "payments")
for faq in faqs {
print("Q: \(faq.question)")
print("A: \(faq.answer)")
}
}
// Get FAQs with specific subtags
let faqs = await FAQProvider.shared.getFAQs(
tag: "payments",
subTags: ["refunds", "disputes"],
lang: "en"
)
SwiftUI Integration
You can easily build an FAQ view in SwiftUI.
struct FAQListView: View {
@State private var faqs: [FAQ] = []
var body: some View {
List(faqs) { faq in
VStack(alignment: .leading) {
Text(faq.question).font(.headline)
Text(faq.answer).font(.body).foregroundColor(.secondary)
}
}
.task {
faqs = await FAQProvider.shared.getFAQs(tag: "general")
}
}
}
Manual Refresh
Manually refresh FAQs from the server (e.g., on pull-to-refresh):
Button("Refresh FAQs") {
Task {
let success = await FAQProvider.shared.refreshFromNetwork(lang: "en")
if success {
// FAQs updated successfully
faqs = await FAQProvider.shared.getFAQs(tag: "payments")
}
}
}
Reactive Updates with Combine
Use Combine to automatically update your UI when FAQs change:
import Combine
class FAQViewModel: ObservableObject {
@Published var faqs: [FAQ] = []
private var cancellables = Set<AnyCancellable>()
func subscribe(tag: String) {
FAQProvider.shared.observeFAQs(tag: tag, lang: "en")
.receive(on: DispatchQueue.main)
.sink { [weak self] updatedFAQs in
self?.faqs = updatedFAQs
}
.store(in: &cancellables)
}
}