İçeriğe geç

HandySwiftUI View Modifier'lar: SwiftUI Kodunu Sadeleştirmek

Akıllı renk kontrastından kolaylaştırılmış hata yönetimine, basitleştirilmiş silme akışlarından platforma özel stillemeye kadar -- yaygın kalıp kodları ortadan kaldıran ve daha bakımı kolay uygulamalar oluşturmana yardımcı olan SwiftUI modifier'larını keşfet.

HandySwiftUI View Modifier'lar: SwiftUI Kodunu Sadeleştirmek

Bu API’leri kendi uygulamalarımda 4 yıl boyunca geliştirdikten sonra, HandySwiftUI’ın ilk etiketli sürümünü paylaşmaktan mutluluk duyuyorum. Bu paket, yalnızca geçen yıl 10 uygulama yayınlamamda büyük rol oynayan çeşitli yardımcı araçlar ve kolaylık API’leri içeriyor. HandySwift paketimin Foundation için sunduğu kolaylıklara benzer şekilde, SwiftUI geliştirme için pratik çözümler sunuyor.

Bu yazıda, TranslateKit, FreemiumKit ve CrossCraft gibi uygulamalarımda günlük geliştirme sürecinde en değerli bulduğum view modifier’ların bir seçkisini paylaşacağım. HandySwiftUI çok daha fazla yardımcı araç içerse de, bu modifier’lar gerçek dünya uygulamalarında defalarca kendini kanıtladı ve senin SwiftUI projelerinde de işine yarayabilir.

Akıllı Renk Kontrastı

foregroundStyle(_:minContrast:) modifier’ı, renk kontrastını otomatik olarak ayarlayarak metnin her zaman okunabilir kalmasını sağlar. Dinamik renkler veya belirli renk şemalarında zayıf kontrasta sahip olabilen .yellow gibi sistem renkleri için kullanışlıdır:

struct AdaptiveText: View {
    @State private var dynamicColor: Color = .yellow

    var body: some View {
        HStack {
            // Kontrast ayarı olmadan
            Text("Maybe hard to read")
                .foregroundStyle(dynamicColor)

            // Otomatik kontrast ayarıyla
            Text("Always readable")
                .foregroundStyle(dynamicColor, minContrast: 0.5)
        }
    }
}

Yellow with contrast

TranslateKit’teki bu uyarı göstergesi .yellow kullanıyor ama okunabilir olması için açık modda bile iyi bir kontrast sağlıyor. Karanlık modda sarı kalıyor.

minContrast parametresi (0 ile 1 arasında), parlaklık değerini (algılanan parlaklık) kullanarak beyaza (açık modda) veya siyaha (karanlık modda) karşı minimum kontrast oranını belirler. Bu sayede metin, mevcut renk şemasından bağımsız olarak her zaman okunabilir kalır.

Hata Yönetimli Task’lar

throwingTask modifier’ı, SwiftUI view’larında asenkron hata yönetimini kolaylaştırır. SwiftUI’ın manuel do-catch blokları gerektiren yerleşik .task modifier’ının aksine, throwingTask ayrı bir hata işleme closure’u sunar:

struct DataView: View {
    @State private var error: Error?

    var body: some View {
        ContentView()
            .throwingTask {
                try await loadData()
            } catchError: { error in
                self.error = error
            }
    }
}

Task, .task ile benzer şekilde davranır – view göründüğünde başlar ve kaybolduğunda iptal edilir. catchError closure’u isteğe bağlıdır, yani hataları ele almana gerek yoksa atlayabilirsin. Bu, task modifier’ının bıraktığı boşluğu dolduruyor.

Platforma Özel Stilleme

Platform modifier’larının tam seti, çoklu platform UI’ı üzerinde hassas kontrol sağlar:

struct AdaptiveInterface: View {
    var body: some View {
        ContentView()
            // Sadece macOS'te padding ekle
            .macOSOnlyPadding(.all, 20)
            // Platforma özel stiller
            .macOSOnly { $0.frame(minWidth: 800) }
            .iOSOnly { $0.navigationViewStyle(.stack) }
    }
}

Örnek, platforma özel stilleme için modifier’ları sergiliyor:

  • .macOSOnlyPadding, Form gibi konteynerların varsayılan padding’e sahip olmadığı macOS’te padding ekler

  • .macOSOnlyFrame, macOS’te gereken minimum pencere boyutlarını ayarlar

  • Platform modifier’ları (.iOSOnly, .macOSOnly, .iOSExcluded, vb.) iOS, macOS, tvOS, visionOS ve watchOS için mevcut olup belirli platformlarda seçici view değişiklikleri uygulamana olanak tanır

Bu modifier’lar, kodu temiz ve bakımı kolay tutarken platforma uygun arayüzler oluşturmana yardımcı olur.

Köşe Yuvarlatmalı Kenarlık

SwiftUI, köşe yuvarlatması olan bir view’a kenarlık eklemenin doğrudan bir yolunu sunmuyor. Standart yaklaşım, hatırlanması zor olan ayrıntılı overlay kodu gerektirir:

Text("Without HandySwiftUI")
    .padding()
    .overlay(
        RoundedRectangle(cornerRadius: 12)
            .strokeBorder(.blue, lineWidth: 2)
    )

HandySwiftUI bunu kullanışlı bir kenarlık modifier’ı ile basitleştirir:

Text("With HandySwiftUI")
    .padding()
    .roundedRectangleBorder(.blue, cornerRadius: 12, lineWidth: 2)

State badges

Örneğin TranslateKit’teki rozetler yuvarlatılmış kenarlıklar için bunu kullanıyor.

Koşullu Modifier’lar

Koşullu view değişikliklerini temiz bir şekilde ele almak için bir modifier seti:

struct DynamicContent: View {
    @State private var isEditMode = false
    @State private var accentColor: Color?

    var body: some View {
        ContentView()
            // Koşula göre farklı modifier'lar uygula
            .applyIf(isEditMode) {
                $0.overlay(EditingTools())
            } else: {
                $0.overlay(ViewingTools())
            }

            // Optional varsa modifier uygula
            .ifLet(accentColor) { view, color in
                view.tint(color)
            }
    }
}

Örnek, bir boolean koşuluna göre farklı view değişiklikleri uygulayan .applyIf‘i ve Swift’in if let ifadesi gibi çalışan – closure’u içinde optional değerlere non-optional erişim sağlayan .ifLet‘i gösteriyor. Her iki modifier da SwiftUI view’larındaki kalıp kodları azaltmaya yardımcı olur.

Uygulama Yaşam Döngüsü Yönetimi

Uygulama durum değişikliklerine zarif bir şekilde yanıt ver:

struct MediaPlayerView: View {
    @StateObject private var player = VideoPlayer()

    var body: some View {
        PlayerContent(player: player)
            .onAppResignActive {
                // Uygulama arka plana geçtiğinde oynatmayı duraklat
                player.pause()
            }
            .onAppBecomeActive {
                // Uygulama aktif olduğunda durumu kontrol et
                player.checkPlaybackState()
            }
    }
}

Bu modifier’lar birlikte çalışarak daha akıcı ve bakımı kolay bir SwiftUI geliştirme deneyimi oluşturur, kalıp kodları azaltırken kullanıcı arayüzünün kalitesini ve tutarlılığını artırır.

Silme Onay Diyalogları

SwiftUI’ın onay diyalogları, silme işlemleri için tekrarlayan kalıp kodları gerektirir, özellikle bir listeden öğe silerken:

struct TodoView: View {
    @State private var showDeleteConfirmation = false
    @State private var todos = ["Buy milk", "Walk dog"]
    @State private var todoToDelete: String?

    var body: some View {
        List {
            ForEach(todos, id: \.self) { todo in
                Text(todo)
                    .swipeActions {
                        Button("Delete", role: .destructive) {
                            todoToDelete = todo
                            showDeleteConfirmation = true
                        }
                    }
            }
        }
        .confirmationDialog("Are you sure?", isPresented: $showDeleteConfirmation) {
            Button("Delete", role: .destructive) {
                if let todo = todoToDelete {
                    todos.removeAll { $0 == todo }
                    todoToDelete = nil
                }
            }
            Button("Cancel", role: .cancel) {
                todoToDelete = nil
            }
        } message: {
            Text("This delete action cannot be undone. Continue?")
        }
    }
}

HandySwiftUI bunu özel bir modifier ile basitleştirir:

struct TodoView: View {
    @State private var todoToDelete: String?
    @State private var todos = ["Buy milk", "Walk dog"]

    var body: some View {
        List {
            ForEach(todos, id: \.self) { todo in
                Text(todo)
                    .swipeActions {
                        Button("Delete", role: .destructive) {
                            todoToDelete = todo
                        }
                    }
            }
        }
        .confirmDeleteDialog(item: $todoToDelete) { item in
            todos.removeAll { $0 == item }
        }
    }
}

Confirm delete

CrossCraft’ta kazara silmeleri önlemek için onay diyaloğuyla bulmaca silme.

Örnek, .confirmDeleteDialog’un tüm silme akışını – onaydan uygulamaya kadar – tek bir modifier ile nasıl ele aldığını gösteriyor. Diyalog yaklaşık 40 dilde otomatik olarak yerelleştirilmiş ve platform tasarım kurallarına uyar. Farklı bir mesaj sağlaman gerekiyorsa isteğe bağlı bir message parametresi verebilirsin. Ayrıca liste içermeyen durumlar için boolean alan bir overload da mevcut.

Hemen Başla

Bu modifier’ları projelerinde benim kadar faydalı bulacağını umuyorum. İyileştirme fikirlerin veya SwiftUI topluluğuna katkı sağlayabilecek ek modifier’lar için GitHub’da katkıda bulunmaktan çekinme:

github.comFlineDev / HandySwiftUIHandy SwiftUI features that didn’t make it into SwiftUI (yet)

Bu yazı, HandySwiftUI’ın özelliklerini keşfeden dört makaleden oluşan serinin ikincisi. Henüz okumadıysan Yeni Tipler hakkındaki önceki makaleye göz at ve Extension’lar ile Stiller hakkındaki yaklaşan yazıları takipte kal!

Bu yazıyı beğendin mi? Swift ipuçları ve indie geliştirici güncellemeleri için Bluesky ve Mastodon üzerinden takip et.