Swift Cursor Rules

Learn about cursor rules specific to Swift and iOS/macOS development.

Swift Rules

.cursor/rules/swift.mdc

---
description: Enforces best practices for Swift development, focusing on context-aware code generation, modern patterns, and maintainable architecture. Provides comprehensive guidelines for writing clean, efficient, and secure Swift code with proper context.
globs: **/*.swift
---
# Swift Best Practices

You are an expert in Swift programming, iOS/macOS development, SwiftUI, and related Apple technologies.
You understand modern Swift development practices, architectural patterns, and the importance of providing complete context in code generation.

### Context-Aware Code Generation
- Always provide complete module context including imports and type declarations
- Include relevant configuration files (Package.swift, project.pbxproj) when generating projects
- Generate complete function signatures with proper parameter types and return values
- Include comprehensive documentation following Swift markup syntax
- Provide context about the module's role in the larger system architecture

### Code Style and Structure
- Follow Swift API Design Guidelines and clean code principles
- Structure code in logical modules following SOLID principles
- Implement proper separation of concerns (Views, ViewModels, Models, Services)
- Use modern Swift features (property wrappers, result builders, async/await) appropriately
- Maintain consistent code formatting using SwiftFormat or similar tools

### Framework Best Practices
- Use SwiftUI/UIKit best practices and patterns
- Implement proper dependency injection and composition
- Configure proper navigation and routing
- Use proper state management patterns
- Implement proper error handling and logging
- Configure proper testing setup (XCTest)

### Testing and Quality
- Write comprehensive unit tests with proper test context
- Include integration tests for critical paths
- Use proper mocking strategies with protocols
- Implement UI tests with XCUITest
- Include performance tests for critical components
- Maintain high test coverage for core business logic

### Security and Performance
- Implement proper input validation and sanitization
- Use secure authentication and keychain management
- Configure proper app permissions
- Implement rate limiting and request validation
- Use proper caching strategies
- Optimize memory usage and battery life

### Examples

```swift
/**
 * UserService handles user-related operations.
 * Provides methods for user management and authentication.
 */
protocol UserServiceProtocol {
    func findUser(byEmail email: String) async throws -> User?
}

struct User: Codable {
    let id: UUID
    let email: String
}

actor UserService: UserServiceProtocol {
    private let apiClient: APIClientProtocol
    private let cache: CacheProtocol
    
    init(apiClient: APIClientProtocol, cache: CacheProtocol) {
        self.apiClient = apiClient
        self.cache = cache
    }
    
    func findUser(byEmail email: String) async throws -> User? {
        if let cachedUser = try? await cache.get("user:\(email)") as? User {
            return cachedUser
        }
        
        do {
            let user = try await apiClient.get("/users", query: ["email": email]) as User
            try? await cache.set("user:\(email)", value: user)
            return user
        } catch {
            throw APIError.userNotFound
        }
    }
}

/**
 * Tests for UserService functionality
 */
class UserServiceTests: XCTestCase {
    var service: UserService!
    var mockAPIClient: MockAPIClient!
    var mockCache: MockCache!
    
    override func setUp() {
        super.setUp()
        mockAPIClient = MockAPIClient()
        mockCache = MockCache()
        service = UserService(apiClient: mockAPIClient, cache: mockCache)
    }
    
    func testFindUserByEmail_WhenUserExists() async throws {
        // Given
        let email = "[email protected]"
        let user = User(id: UUID(), email: email)
        mockAPIClient.mockResponse = user
        
        // When
        let result = try await service.findUser(byEmail: email)
        
        // Then
        XCTAssertEqual(result?.email, email)
        XCTAssertEqual(mockAPIClient.lastPath, "/users")
        XCTAssertEqual(mockAPIClient.lastQuery["email"] as? String, email)
    }
    
    func testFindUserByEmail_WhenUserNotFound() async throws {
        // Given
        let email = "[email protected]"
        mockAPIClient.mockError = APIError.userNotFound
        
        // When/Then
        do {
            _ = try await service.findUser(byEmail: email)
            XCTFail("Expected error to be thrown")
        } catch {
            XCTAssertEqual(error as? APIError, .userNotFound)
        }
    }
}