Context-aware routing to Swift/iOS development patterns, architecture, and best practices...
Context-aware routing to iOS development patterns, code style, and architecture guidelines. This skill provides critical rules and points you to comprehensive documentation.
.swift files// Generated using Sourcery/SwiftGenLoc.*)Before completing any task:
Loc constants)SwiftUI views have three key qualities:
Key insight: Views are VALUE TYPES (structs), not long-lived objects. They are descriptions of current UI state. Breaking views into subviews doesn't hurt performance - SwiftUI maintains efficient data structures behind the scenes.
// Declarative: describe the result, not the steps
List(pets) { pet in
HStack {
Text(pet.name)
Spacer()
Text(pet.species)
}
}
// No need to manually add/remove rows - SwiftUI handles it
For detailed SwiftUI patterns, see swiftui-patterns-developer skill.
@MainActor
final class ChatViewModel: ObservableObject {
@Published var messages: [Message] = []
@Injected(\.chatService) private var chatService
func sendMessage(_ text: String) async {
// Business logic here
}
}
@MainActor
final class ChatCoordinator: ObservableObject {
@Published var route: Route?
enum Route {
case settings
case memberList
}
}
extension Container {
var chatService: Factory<ChatServiceProtocol> {
Factory(self) { ChatService() }
}
}
// Usage in ViewModel
@Injected(\.chatService) private var chatService
Keep ViewModel init() cheap - defer heavy work to .task:
// Init assigns parameters only
init(id: String) {
_model = State(wrappedValue: ViewModel(id: id))
}
// Heavy work in .task
.task { await model.startSubscriptions() }
For expensive init, defer creation entirely:
@State private var model: ViewModel?
.task(id: id) { model = ViewModel(id: id) }
Prefer AsyncStandardButton over manual loading state management for cleaner code:
// ā AVOID: Manual loading state
struct MyView: View {
@State private var isLoading = false
var body: some View {
StandardButton(.text("Connect"), inProgress: isLoading, style: .secondaryLarge) {
isLoading = true
Task {
await viewModel.connect()
isLoading = false
}
}
}
}
// ā
PREFERRED: AsyncStandardButton handles loading state automatically
struct MyView: View {
var body: some View {
AsyncStandardButton(Loc.sendMessage, style: .primaryLarge) {
try await viewModel.onConnect()
}
}
}
// ViewModel can throw - errors are handled automatically
func onConnect() async throws {
guard let identity = details?.identity, identity.isNotEmpty else { return }
if let existingSpace = spaceViewsStorage.oneToOneSpaceView(identity: identity) {
pageNavigation?.open(.spaceChat(SpaceChatCoordinatorData(spaceId: existingSpace.targetSpaceId)))
return
}
let newSpaceId = try await workspaceService.createOneToOneSpace(oneToOneIdentity: identity)
pageNavigation?.open(.spaceChat(SpaceChatCoordinatorData(spaceId: newSpaceId)))
}
Benefits of AsyncStandardButton:
inProgress state internally@Published var isLoading needed)async throws - use try await and let errors propagate naturallyAnytype/Sources/
āāā ApplicationLayer/ # App lifecycle, coordinators
āāā PresentationLayer/ # UI components, ViewModels
āāā ServiceLayer/ # Business logic, data services
āāā Models/ # Data models, entities
āāā CoreLayer/ # Core utilities, networking
TypeName+Feature.swiftFull Guide: Anytype/Sources/IOS_DEVELOPMENT_GUIDE.md
For comprehensive coverage of:
NEVER commit without explicit user request - Committing is destructive
Used rm -f .../PublishingPreview*.swift - deleted main UI component
ls firstRefactored dependencies but forgot MockView.swift
rg "oldName" --type swiftLOCALIZATION_GUIDE.md - Localization systemCODE_GENERATION_GUIDE.md - Feature flags, make generateDESIGN_SYSTEM_MAPPING.md - Icons, typographyNavigation: This is a smart router. For deep technical details, always refer to IOS_DEVELOPMENT_GUIDE.md.