İçeriğe geç
Educora
İleri22 dk8 / 14

Protokoller, hatalar ve SwiftUI

Protokoller ve uzantılarla türlere ortak kurallar ve yeni yetenekler kazandır, `throws` ve `do-try-catch` ile hataları yönet, ardından SwiftUI ile ilk ekranın nasıl kurulduğunu gör.

Kendini test et
Bu derste öğreneceklerin
  • Protokol tanımlamak, ona uyan türler oluşturmak ve uzantılarla yeni metotlar eklemek
  • throws, throw, try ve do-catch ile hata fırlatmak ve yakalamak
  • Basit bir SwiftUI görünümünü okumak ve @State'in rolünü açıklamak

Bir elektrik prizini düşün: telefon şarj aleti, su ısıtıcısı, lamba birbirinden farklı cihazlardır, ama fişleri aynı kurala uygun yapılmıştır; bu yüzden her prize takılırlar. Swift'te böyle bir kurala protokol denir. Bu derste protokolleri ve hata yönetimini öğrenecek, sonunda da bildiğin her şeyi bir araya getiren bir SwiftUI ekranıyla tanışacaksın.

Protokoller ve uzantılar

Tanım
Protokol

Bir türün hangi özelliklere ve metotlara sahip olması gerektiğini tanımlayan kurallar bütünü. Protokolün kendisinde kod yoktur; ona uyan (İngilizcesiyle conform) her tür bu gereksinimleri kendisi karşılar.

Aşağıda Shape protokolü her şeklin bir adı ve alanı olmasını istiyor. Rectangle ve Square tamamen farklı yapılardır, ama ikisi de protokole uyduğu için tek bir dizide tutulabilir. Protokolün uzantısı (extension) ise uyan tüm türlere hazır bir summary() metodu verir.

Swift
protocol Shape {
    var name: String { get }
    func area() -> Double
}

extension Shape {
    func summary() -> String {
        "\(name): area \(area())"
    }
}

struct Rectangle: Shape {
    let width, height: Double
    var name: String { "Rectangle" }
    func area() -> Double { width * height }
}

struct Square: Shape {
    let side: Double
    var name: String { "Square" }
    func area() -> Double { side * side }
}

let shapes: [any Shape] = [Rectangle(width: 4, height: 2.5), Square(side: 3)]
for shape in shapes {
    print(shape.summary())
}
Beklenen çıktı
Rectangle: area 10.0
Square: area 9.0

Uzantıyla var olan türlere, hatta Swift'in kendi Int ve String türlerine bile yeni özellikler ve metotlar ekleyebilirsin. Uzantının içinde self, değerin kendisidir.

Swift
extension Int {
    var isEven: Bool {
        self % 2 == 0
    }

    func times(_ action: () -> Void) {
        for _ in 0..<self {
            action()
        }
    }
}

print(7.isEven)
print(10.isEven)
3.times {
    print("Swift!")
}
Beklenen çıktı
false
true
Swift!
Swift!
Swift!

Hata yönetimi

Bazı işlemler başarısız olabilir: hesapta yeterli para yoktur, dosya bulunamaz, internet kesilir. Swift'te böyle bir fonksiyon throws ile işaretlenir ve bir sorun çıktığında throw ile hata fırlatır. Hata genellikle Error protokolüne uyan bir enum'dur. Hata fırlatan fonksiyon çağrılırken önüne try yazılır, hata da do-catch bloğunda yakalanır.

Swift
enum WithdrawError: Error {
    case invalidAmount
    case insufficientFunds(needed: Int)
}

func withdraw(_ amount: Int, from balance: Int) throws -> Int {
    guard amount > 0 else {
        throw WithdrawError.invalidAmount
    }
    guard amount <= balance else {
        throw WithdrawError.insufficientFunds(needed: amount - balance)
    }
    return balance - amount
}

do {
    let left = try withdraw(30, from: 100)
    print("Left: \(left) AZN")
    _ = try withdraw(200, from: left)
    print("This line is skipped")
} catch WithdrawError.insufficientFunds(let needed) {
    print("Not enough money, need \(needed) AZN more")
} catch {
    print("Other error: \(error)")
}
Beklenen çıktı
Left: 70 AZN
Not enough money, need 130 AZN more

Programın akışını izle: ilk çağrı başarılıdır ve 70 manat kalır. İkinci çağrı hata fırlatır; bu yüzden do bloğunun geri kalanı atlanır ve kontrol uygun catch'e geçer. Son catch diğer tüm hataları yakalar; onun içinde hata otomatik olarak error adını alır.

SwiftUI ile ilk ekran

SwiftUI, Apple'ın arayüz oluşturma aracıdır. Ekranı adım adım çizmezsin; yalnızca nasıl görünmesi gerektiğini tarif edersin. Buna bildirimsel (deklaratif) yaklaşım denir. Aşağıdaki kod, düğmeye her dokunuşta sayacı artan bir ekrandır. Yalnızca Xcode'da ya da Swift Playgrounds'ta çalışır, ama her satırını artık anlayabilirsin.

Swift
import SwiftUI

struct ContentView: View {
    @State private var count = 0

    var body: some View {
        VStack(spacing: 16) {
            Text("Taps: \(count)")
                .font(.largeTitle)
            Button("Tap me") {
                count += 1
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}

#Preview {
    ContentView()
}
Bu kod Xcode'da bir iPhone ekranı oluşturur; konsola hiçbir şey yazdırmaz.
  • struct ContentView: View — ekran sıradan bir yapıdır ve View protokolüne uyar. Protokol tek bir şey ister: body özelliği.
  • var body: some View — ekranda ne gösterileceğini döndüren hesaplanan özellik.
  • VStack öğeleri dikey dizer, Text metin gösterir, Button'ın sondaki closure'ı ise dokunulduğunda çalışır.
  • .font(...), .padding() gibi değiştiriciler görünümü değiştirir ve noktayla zincir hâlinde yazılır.
  • #Preview, Xcode'un tuval (canvas) panelinde ekranın canlı önizlemesini gösterir.
Tanım
@State

Bir görünümün hatırladığı, değişebilen değer. @State değeri değiştiğinde SwiftUI body'yi otomatik olarak yeniden hesaplar ve ekranı günceller; Text öğesini elle değiştirmen gerekmez.

  1. 1
    Proje oluştur

    Xcode'da File › New › Project… seç, iOS bölümünde App şablonunu al ve arayüz olarak SwiftUI'nin seçili olduğundan emin ol.

  2. 2
    Kodu yaz

    ContentView.swift dosyasını aç ve yukarıdaki kodu oraya yaz.

  3. 3
    Önizlemeye bak

    Ekran sağdaki tuvalde hemen görünür; düğmeye dokun ve sayacın arttığını kontrol et.

  4. 4
    Simülatörde çalıştır

    Üstten bir iPhone modeli seç ve Cmd+R tuşlarına bas; uygulama iPhone simülatöründe açılır.

uygulamayı derleyip çalıştırmakCmd+R
yalnızca derlemek (hataları kontrol etmek)Cmd+B
tuvali (önizlemeyi) göstermek ya da gizlemekCmd+Option+Return
derleme klasörünü temizlemekCmd+Shift+K

Önemli noktalar

  • Protokol bir türün neye sahip olması gerektiğini tanımlar; uyan türler gereksinimleri kendileri karşılar.
  • extension, var olan türlere, hatta Int'e ve protokollere yeni metotlar ekler.
  • throws fonksiyonu throw ile hata fırlatır; onu try ile çağırır, hataları do-catch ile yakalarız.
  • try? hatayı nil'e çevirir; try! ise hata olursa programı çökertir.
  • SwiftUI bir ekranı View'a uyan bir yapı olarak tarif eder; @State değişince ekran otomatik güncellenir.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
Bir tür bir protokole uymak için ne yapmalıdır?