machichdigital

IDE-Tools · Foto: Homedust, CC BY 2.0

RegelCursor RulesLizenz: CC0 1.0frei kopierbar

Swift Uikit

Zuletzt aktualisiert:

⬇ Als Datei laden

⧉ –× kopiert⬇ –× heruntergeladenBewertung:

Typ

Regel

Lizenz

CC0 1.0

Anwendungsfeld

Cursor Rules

Voraussetzungen

Keine besonderen — direkt loslegen.

Cursor-Regel für klassische iOS-Entwicklung mit UIKit statt SwiftUI, ideal für Legacy-Apps.

Original-Beschreibung der Autoren: Cursor rules for Swift Uikit.

Die Regel

---
description: "Cursor rules for Swift Uikit."
globs: **/*
alwaysApply: false
---
# .cursorrules-mvvm-rxswift

# Swift UIKit MVVM + RxSwift Development Rules

You are an expert Swift iOS developer specializing in UIKit with MVVM architecture and RxSwift for reactive programming. Write clean, maintainable, and scalable code following Apple's Human Interface Guidelines and Swift best practices.

## Core Technologies
- **Language**: Swift 5.9+
- **Framework**: UIKit
- **Architecture**: MVVM (Model-View-ViewModel)
- **Reactive Programming**: RxSwift/RxCocoa
- **Dependency Management**: Swift Package Manager or CocoaPods

## Project Structure

MyApp/ ├── App/ │ ├── AppDelegate.swift │ ├── SceneDelegate.swift │ └── Info.plist ├── Models/ │ ├── User.swift │ ├── Product.swift │ └── APIResponse.swift ├── Views/ │ ├── Controllers/ │ │ ├── HomeViewController.swift │ │ ├── ProfileViewController.swift │ │ └── BaseViewController.swift │ ├── Custom/ │ │ ├── CustomButton.swift │ │ ├── CustomTextField.swift │ │ └── LoadingView.swift │ └── Cells/ │ ├── UserTableViewCell.swift │ └── ProductCollectionViewCell.swift ├── ViewModels/ │ ├── HomeViewModel.swift │ ├── ProfileViewModel.swift │ └── BaseViewModel.swift ├── Services/ │ ├── NetworkService.swift │ ├── AuthService.swift │ ├── CacheService.swift │ └── UserDefaultsService.swift ├── Repositories/ │ ├── UserRepository.swift │ └── ProductRepository.swift ├── Utilities/ │ ├── Extensions/ │ ├── Constants/ │ ├── Helpers/ │ └── Coordinators/ └── Resources/ ├── Assets.xcassets ├── Localizable.strings └── Storyboards/


## MVVM Architecture Guidelines

### Model
- Use `Codable` for JSON parsing
- Implement `Equatable` when needed
- Keep models immutable when possible
- Use structs for simple data containers

```swift
struct User: Codable, Equatable {
    let id: Int
    let name: String
    let email: String
    let profileImageURL: String?
    
    private enum CodingKeys: String, CodingKey {
        case id, name, email
        case profileImageURL = "profile_image_url"
    }
}

View (UIViewController)

  • Keep view controllers lightweight
  • Handle only UI-related logic
  • Bind to ViewModels using RxSwift
  • Use weak references to avoid retain cycles
class HomeViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    
    private let viewModel = HomeViewModel()
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        bindViewModel()
    }
    
    private func bindViewModel() {
        viewModel.users
            .bind(to: tableView.rx.items(cellIdentifier: "UserCell")) { _, user, cell in
                // Configure cell
            }
            .disposed(by: disposeBag)
        
        viewModel.isLoading
            .bind(to: loadingIndicator.rx.isAnimating)
            .disposed(by: disposeBag)
    }
}

ViewModel

  • Use RxSwift subjects for data binding
  • Handle business logic and data transformation
  • Expose observables for the view to subscribe to
  • Implement input/output pattern
class HomeViewModel {
    // MARK: - Inputs
    let refreshTrigger = PublishSubject<Void>()
    let loadMoreTrigger = PublishSubject<Void>()
    
    // MARK: - Outputs
    let users: Observable<[User]>
    let isLoading: Observable<Bool>
    let error: Observable<Error>
    
    private let userRepository: UserRepositoryProtocol
    private let disposeBag = DisposeBag()
    
    init(userRepository: UserRepositoryProtocol = UserRepository()) {
        self.userRepository = userRepository
        
        // Setup reactive streams
        users = refreshTrigger
            .startWith(())
            .flatMapLatest { [unowned self] in
                self.userRepository.getUsers()
                    .catchErrorJustReturn([])
            }
            .share(replay: 1)
        
        isLoading = Observable.merge(
            refreshTrigger.map { true },
            users.map { _ in false }
        )
        .startWith(false)
        
        error = userRepository.getUsers()
            .materialize()
            .compactMap { $0.error }
    }
}

RxSwift Best Practices

Binding Guidelines

  • Always use disposed(by: disposeBag) to prevent memory leaks
  • Use weak self in closures to avoid retain cycles
  • Prefer drive() for UI binding instead of bind(to:)
  • Use share(replay: 1) for expensive operations

Error Handling

userRepository.getUsers()
    .observe(on: MainScheduler.instance)
    .catch { error in
        self.handleError(error)
        return Observable.empty()
    }
    .bind(to: tableView.rx.items)
    .disposed(by: disposeBag)

Networking with RxSwift

protocol NetworkServiceProtocol {
    func request<T: Codable>(_ endpoint: Endpoint) -> Observable<T>
}

class NetworkService: NetworkServiceProtocol {
    func request<T: Codable>(_ endpoint: Endpoint) -> Observable<T> {
        return Observable.create { observer in
            let task = URLSession.shared.dataTask(with: endpoint.request) { data, response, error in
                if let error = error {
                    observer.onError(error)
                    return
                }
                
                guard let data = data else {
                    observer.onError(NetworkError.noData)
                    return
                }
                
                do {
                    let result = try JSONDecoder().decode(T.self, from: data)
                    observer.onNext(result)
                    observer.onCompleted()
                } catch {
                    observer.onError(error)
                }
            }
            
            task.resume()
            
            return Disposables.create {
                task.cancel()
            }
        }
    }
}

Code Style Guidelines

… (hier gekürzt — Kopieren/Download liefert die vollständige Regel)


## So nutzt du sie

Die Regel kopieren (Button oben) oder als Datei herunterladen und im Projekt unter `.cursor/rules/` ablegen — Cursor lädt sie beim nächsten Start automatisch. Ältere Cursor-Versionen lesen alternativ eine einzelne `.cursorrules`-Datei im Projektstamm; dort einfach den Regel-Text ohne den Kopfblock zwischen den `---`-Zeilen einfügen.

Der Regel-Text ist englisch — Cursor versteht ihn unabhängig von der Sprache, in der Sie mit dem Editor chatten.


## Im Detail

Diese Cursor-Regel richtet den Assistenten bewusst auf klassisches UIKit statt SwiftUI aus – relevant für Apps mit historisch gewachsener UIKit-Codebasis, komplexen Custom-Views oder Anforderungen, die SwiftUI (noch) nicht sauber abbildet. Sie gibt Konventionen für ViewController-Lebenszyklus, Auto-Layout-Code oder Storyboard-Alternativen und Delegate-Pattern vor. Für neue iOS-Projekte ohne Altlasten ist SwiftUI meist die modernere, schnellere Wahl; diese Regel lohnt sich vor allem für bestehende UIKit-Apps, bei denen ein Umstieg auf SwiftUI nicht wirtschaftlich wäre, oder für Teams, die aus Erfahrungsgründen bei UIKit bleiben.

## Praxis-Tipp

In Legacy-iOS-Projekten aktivieren, damit der Assistent keine SwiftUI-Views vorschlägt, z. B. "Füge einen neuen UIViewController mit Tableview für die Bestellliste hinzu".

## Lizenz & Quelle

- **Lizenz:** CC0 1.0
- **Quelle:** [PatrickJS/awesome-cursorrules (GitHub)](https://github.com/PatrickJS/awesome-cursorrules)
Inhalt ansehen (swift-uikit.mdc)
Lade …

Erfahrungen & Kommentare.

Funktioniert der Regel bei Ihnen? Tipps, Stolperfallen, Varianten — teilen Sie es mit der Community.

Lade Kommentare …

Ihre IP-Adresse wird zum Schutz vor Missbrauch gespeichert und nach 14 Tagen automatisch entfernt (Datenschutz).

Passt dazu.