A Swift implementation of TanStack Query for SwiftUI applications, providing powerful asynchronous state management with caching, synchronization, and infinite queries.
Inspired by TanStack Query - This library brings the beloved patterns and features of TanStack Query (formerly React Query) to the Swift ecosystem, adapted for SwiftUI and Swift's concurrency model.
- π Swift 6 Compatible - Full strict concurrency support
- π Automatic Refetching - On mount, focus, reconnect
- π± iOS 16+ Support - Built with Perception library for broad compatibility
- β‘οΈ Request Deduplication - Automatic request optimization
- ποΈ Garbage Collection - Smart memory management
- π Infinite Queries - Built-in pagination support
- π§ Type Safe - Full Swift type safety
- π± Multi-Platform - iOS, macOS, tvOS, and watchOS
- Swift 6.0+
- iOS 16.0+ / macOS 13.0+ / tvOS 16.0+ / watchOS 9.0+
Add SwiftUI Query to your Package.swift file:
dependencies: [
.package(url: "https://github.com/muzix/SwiftUIQuery.git", from: "0.2.0")
]Or add it through Xcode:
- File β Add Package Dependencies
- Enter the repository URL:
https://github.com/muzix/SwiftUIQuery.git - Select the version
import SwiftUI
import SwiftUIQuery
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.queryClient() // Add QueryClient to environment
}
}
}import SwiftUI
import SwiftUIQuery
struct ContentView: View {
var body: some View {
UseQuery(
queryKey: "todos",
queryFn: { _ in
try await fetchTodos()
}
) { result in
switch result.status {
case .loading:
ProgressView("Loading...")
case .error:
Text("Error: \(result.error?.localizedDescription ?? "Unknown error")")
case .success:
List(result.data ?? []) { todo in
Text(todo.title)
}
}
}
}
func fetchTodos() async throws -> [Todo] {
// Your API call here
}
}struct PokemonListView: View {
var body: some View {
UseInfiniteQuery(
queryKey: "pokemon-list",
queryFn: { _, pageParam in
let offset = pageParam ?? 0
return try await PokemonAPI.fetchPokemonPage(offset: offset)
},
getNextPageParam: { pages in
let currentTotal = pages.reduce(0) { total, page in
total + page.results.count
}
return pages.last?.next != nil ? currentTotal : nil
},
initialPageParam: 0
) { result in
ScrollView {
LazyVStack {
// Render all pages
ForEach(result.data?.pages ?? []) { page in
ForEach(page.results) { pokemon in
PokemonRow(pokemon: pokemon)
}
}
// Load more button
if result.hasNextPage {
Button("Load More") {
Task {
await result.fetchNextPage()
}
}
.onAppear {
// Auto-load on scroll
Task {
await result.fetchNextPage()
}
}
}
}
}
.refreshable {
try? await result.refetch()
}
}
}
}- Clone the repository
- Install development tools:
brew bundle
This project uses SwiftLint and SwiftFormat to maintain code quality and consistency.
make help # Show all available commands
make lint # Run SwiftLint
make lint-fix # Auto-fix SwiftLint issues
make format # Format code with SwiftFormat
make format-check # Check if formatting is needed
make check # Run all checks (lint + format)
make fix # Fix all issues (lint + format)
make build # Build with strict concurrency
make test # Run tests
make ci # Run full CI suiteTo ensure code quality before commits:
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
make check
EOF
chmod +x .git/hooks/pre-commitRun tests with strict concurrency:
make testThe project follows TanStack Query's architecture. Key documentation:
CLAUDE.md- Development guide and instructionsprinciples.md- Core principles and Swift 6 complianceapi-design.md- API patterns and usage examplesroadmap.md- Development roadmapfeature-parity.md- TanStack Query feature comparison
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Run
make checkto ensure code quality - Commit your changes
- Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is heavily inspired by TanStack Query (formerly React Query), created by Tanner Linsley and maintained by the TanStack team. We aim to bring the same powerful patterns, architectural principles, and developer experience to the Swift ecosystem.
- β Query Caching - Automatic request deduplication and intelligent caching
- β Background Refetching - Stale-while-revalidate pattern
- β Automatic Retries - Configurable retry logic with exponential backoff
- β Infinite Queries - Built-in pagination and infinite scrolling support
- β Lifecycle Management - Automatic refetch on mount, focus, and reconnect
- β Garbage Collection - Smart cleanup of unused query data
- β DevTools Integration - Built-in debugging and inspection tools
Special thanks to the TanStack Query team for creating such an excellent library that has transformed how developers handle server state management. This Swift implementation follows the same core principles while embracing Swift's type system and concurrency model.