Files
Code-Agents/macOS_Development_Rules.md
2026-01-11 16:21:23 +03:00

8.3 KiB
Raw Blame History

RULESET: macOS App Development with SwiftUI (Based on 'macOS by Tutorials')

Bu dosya, "macOS by Tutorials" (Ray Wenderlich / Kodeco) kitabındaki best practice'lere dayanarak yüksek kaliteli, native hissettiren bir macOS uygulaması geliştirmek için gerekli kuralları, mimari desenleri ve kod standartlarını içerir.

GÖREV: Bir macOS uygulaması geliştirirken aşağıdaki kurallara kesinlikle uy. iOS alışkanlıklarını (NavigationLink vb.) macOS'e aynen kopyalama. Mac kullanıcılarının beklentilerine (Menü çubuğu, Çoklu Pencere, Klavye Kısayolları) öncelik ver.


1. TEMEL FELSEFE VE MİMARİ (Core Philosophy)

iOS Portu Değil, Mac Uygulaması

  • Kural: Uygulamayı sadece "büyük ekranlı bir iPad uygulaması" gibi tasarlama. Mac kullanıcıları fare/trackpad kullanır, pencereleri boyutlandırır ve klavye kısayollarına bağımlıdır.
  • Kural: SFSafariViewController macOS'te yoktur ve kullanılmamalıdır. Kullanıcıyı tarayıcıya (Link veya NSWorkspace.open) yönlendirmek Mac kültürüne daha uygundur.

Uygulama Yaşam Döngüsü (App Lifecycle)

  • Yapı: @main struct'ı App protokolüne uymalıdır.
  • WindowGroup: Ana arayüzü WindowGroup içine al. Bu, macOS'in otomatik olarak çoklu pencere (multi-window) ve sekme (tab) desteği sunmasını sağlar.
    @main
    struct MyApp: App {
        @StateObject var appState = AppState() // Global state
    
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .environmentObject(appState)
            }
            .commands { 
                // Menü komutları buraya
                SidebarCommands() 
                ToolbarCommands()
            }
        }
    }
    

2. PENCERE YÖNETİMİ (Window Management)

Pencere Boyutlandırma (Sizing)

  • Kural: iOS'in aksine, Mac'te pencereler serbestçe boyutlandırılabilir. Ancak mantıklı sınırlar koymalısın.
  • Kod: ContentView'un en dış katmanına .frame() modifier ekle.
    • minWidth / minHeight: UI'ın bozulmayacağı en küçük boyut.
    • maxWidth / maxHeight: Genellikle .infinity olmalı.
    • idealWidth / idealHeight: Uygulama ilk açıldığında önerilen boyut.
    .frame(minWidth: 700, idealWidth: 1000, maxWidth: .infinity,
           minHeight: 400, idealHeight: 800, maxHeight: .infinity)
    

Pencere Başlıkları (Titles)

  • Kural: Çoklu pencerelerde her pencerenin içeriğine göre dinamik başlığı olmalıdır.
  • Kod: .navigationTitle(_:) kullan. Eğer sidebar'da bir seçim varsa başlık ona göre değişmeli, yoksa varsayılan uygulama adı görünmelidir.

3. NAVİGASYON VE SIDEBAR (Navigation)

NavigationView Yapısı

  • Kural (KRİTİK): NavigationLink kullanma. macOS'te "push" navigasyonu (bir ekranın diğerinin üzerine kayması) nadirdir.
  • Desen: Sidebar + Detail (Split View) yapısını kullan.
  • Uygulama: NavigationView içine tüm panelleri (Sidebar, Detail) en baştan koy. Görünürlük, bir @Binding selection değişkeni ile yönetilir.
    NavigationView {
        SidebarView(selection: $selection) // Sol Panel
        DetailView(selection: selection)   // Sağ Panel
    }
    

Sidebar Tasarımı

  • List Style: .listStyle(.sidebar) kullan. Bu, satırların hafif transparan olmasını ve seçimin sistem rengiyle (AccentColor) vurgulanmasını sağlar.
  • Selection: List(selection: $selection) bağlamasını kullan. Tag yapısını NavigationLink yerine tercih et.
  • Kategoriler: Listeyi Section'lara böl. Başlıkları büyük harfle yazma (iOS gibi değil), Mac standartlarına uy.

4. UI BİLEŞENLERİ (UI Components)

Grid (Izgara) Görünümü

  • Kullanım: Çok sayıda öğe gösterirken LazyVGrid kullan.
  • Sütunlar: Sabit sütun sayısı yerine .adaptive(minimum:maximum:) kullanarak pencere genişletildiğinde sütun sayısının artmasını sağla.
    let columns = [GridItem(.adaptive(minimum: 250, maximum: 250), spacing: 20)]
    

Table (Tablo) Görünümü (macOS Exclusive)

  • Kural: Veri yoğunluklu listeler için List yerine SwiftUI Table görünümünü kullan.
  • Özellikler: Sıralama (sortOrder), Çoklu seçim (selection: Set<ID>), ve Sütun genişlikleri (width(min:ideal:max)) mutlaka eklenmeli.
  • Alternatif Satır Renkleri: Table, varsayılan olarak satırları alternatif renklerle (zebra stripe) boyar. Bunu koru.

Kart Tasarımı ve Hover Efektleri

  • Kural: Mac kullanıcıları "tıklanabilir" alanları anlamak için fare imlecini kullanır.
  • İpucu: Tıklanabilir alanlarda imleci değiştirmek için .onHover ve NSCursor kullan.
    .onHover { inside in
        inside ? NSCursor.pointingHand.push() : NSCursor.pop()
    }
    
  • Bug Fix: Kartlara gölge (shadow) eklerken .clipped() kullanmayı unutma, aksi takdirde gölge iç elementlere de uygulanabilir (SwiftUI bug workaround).

5. MENÜLER (Menus)

Command Protocol

  • Yapı: Menüleri View dosyalarından ayır ve Commands protokolüne uyan ayrı bir dosyada (örn. Menus.swift) tut.
  • Hazır Gruplar: Apple'ın hazır menü gruplarını mutlaka ekle:
    • SidebarCommands(): View menüsüne "Toggle Sidebar" ekler.
    • ToolbarCommands(): View menüsüne Toolbar özelleştirme seçeneklerini ekler.

Özel Menü Öğeleri

  • Yerleşim: CommandGroup(before: .help) veya CommandGroup(after: .newItem) gibi yerleşimler kullan.
  • Klavye Kısayolları: .keyboardShortcut(_:modifiers:) ile her önemli aksiyona kısayol ata.
    • Not: Menülerde kısayollar otomatik olarak büyük harf görünür, ekstra Shift eklemene gerek yoktur.
  • Picker Entegrasyonu: Ayarlar için (örn. Tema seçimi) menü içine Picker koy. Otomatik olarak alt menü (submenu) ve tik işareti (checkmark) oluşturur.

6. ARAÇ ÇUBUĞU (Toolbar)

Yapı ve Özelleştirme

  • Kural: ToolbarItem veya ToolbarItemGroup kullan.
  • Customizable: Kullanıcının sağ tıkla toolbar'ı düzenleyebilmesi için toolbar'a ve öğelere .id() ver.
    .toolbar(id: "mainToolbar") {
        ToolbarItem(id: "refresh", placement: .primaryAction) { ... }
    }
    
  • Placement: * .navigation: Sol taraf (Sidebar toggle vb.)
    • .primaryAction: Sağ taraf (En önemli buton)
    • .automatic: Sistem karar verir.
  • Kullanım: .searchable(text: $searchText) modifier'ını NavigationView'a ekle. Bu, toolbar'a otomatik olarak native bir arama çubuğu yerleştirir.

7. VERİ VE STATE YÖNETİMİ (Data Persistence)

Sandboxing & Network

  • Kritik: macOS uygulamaları varsayılan olarak internete çıkamaz. "Signing & Capabilities" altından Outgoing Connections (Client) tikini açmalısın.

Ayarların Saklanması (Persistence)

  • Global Ayarlar: Uygulama geneli ayarlar (örn. Tema, "Show Totals") için @AppStorage kullan (UserDefaults wrapper).
  • Pencere Bazlı Ayarlar: Her pencerenin kendi durumunu hatırlaması için (örn. Seçili sekme, Arama metni) @SceneStorage kullan.
    @SceneStorage("viewMode") var viewMode: ViewMode = .grid
    

8. SWIFTUI & APPKIT ENTEGRASYONU

Ne Zaman AppKit Kullanılmalı?

  • SwiftUI'ın yetersiz kaldığı durumlarda (örn. Sidebar'ı kod ile açıp kapatmak, Window odağını değiştirmek, First Responder yönetimi) NSApp, NSWindow veya NSCursor'a erişmekten çekinme.
  • Örnek (Sidebar Toggle):
    func toggleSidebar() {
        NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
    }
    

9. CHECKLIST FOR AGENTS

Bir özellik eklerken şu soruları sor:

  1. Pencere: Bu özellik yeni bir pencerede açıldığında nasıl davranacak? (@SceneStorage kullanıldı mı?)
  2. Menü: Bu aksiyonun Menü çubuğunda bir karşılığı ve klavye kısayolu var mı?
  3. Mouse: Hover efektleri var mı? Tıklanabilir alanlar belli mi?
  4. Platform: Bu bir iOS davranışı mı (örn. Bottom Sheet, Navigation Push)? Eğer öyleyse macOS karşılığını (Sheet, Split View değişimi) kullan.
  5. Boyut: Pencere küçüldüğünde veya büyüdüğünde (GridItem.adaptive, Table sütunları) arayüz uyum sağlıyor mu?