• 23.09.2026 21:11:39
  • Admin Admin

SwiftUI eğitimi kapsamında OSLog, signpost ve MetricKit'i aynı gözlemleme hattında kurun. Gizli veriyi maskeleyin, Instruments ile p95 gecikmeyi ölçün ve App Store dağıtımındaki tanılama sınırlarını yönetin.

SwiftUI Eğitiminde OSLog ve Signpost ile Üretim Hata Analizi

SwiftUI eğitimi için sorgulanabilir ve gizlilik kontrollü OSLog

Bir ios eğitimi veya swift eğitimi projesinde print() ile başlayan kayıtlar, gerçek cihazda filtrelenemeyen ve kişisel veri sızdırma riski taşıyan bir borca dönüşür. Her modül için sabit bir subsystem/category şeması tanımlayın: subsystem bundle identifier ile eşleşsin, category ise en fazla 10-15 adet operasyonel alan içersin. Console ve Instruments bu iki alanla indeksli filtre yapabildiği için mesaj metninde string aramaktan daha kararlı sonuç verir.

import OSLog

namespace AppLog {
    static let network = Logger(
        subsystem: Bundle.main.bundleIdentifier ?? "com.example.catalog",
        category: "network"
    )
    static let checkout = Logger(
        subsystem: Bundle.main.bundleIdentifier ?? "com.example.catalog",
        category: "checkout"
    )
}

func recordResponse(route: String, statusCode: Int, requestID: UUID) {
    AppLog.network.notice(
        "response route=\(route, privacy: .public) " +
        "status=\(statusCode) requestID=\(requestID.uuidString, privacy: .private(mask: .hash))"
    )
}

route gibi uygulamanın sonlu, denetlenmiş bir enum degeri ve HTTP durum kodu public olabilir; e-posta, URL query, bearer token, sunucu hata govdesi ve UUID ise explicit private kalmalıdır. Yaygın hata, URLRequest.url.absoluteString degerini public loglamaktır: query parametreleri kampanya kimligi, e-posta veya tek seferlik token taşıyabilir. swift kursu materyalinde bunu kural haline getirin: public alanlar allow-list ile yazılır, dinamik stringler varsayılan olarak private tutulur.

iPhone uygulama geliştirme sürecinde Signpost ile p95 ölçümü

iphone uygulama geliştirme sırasında ekranın "yavas" oldugu bilgisini CPU yüzdesiyle açıklamaya çalışmayın. Kullanıcının beklediği aralığı, örneğin yenileme jestinden ilk içerik çizimine kadar olan süreyi OSSignposter ile işaretleyin. Bu interval ağ beklemesini, JSON çözümlemeyi ve ana aktöre dönüşü birlikte kapsar; Time Profiler ise interval içindeki CPU sıcak noktalarını ayırmak için ikinci araçtır.

import OSLog

@MainActor
final class CatalogViewModel: ObservableObject {
    private let signposter = OSSignposter(
        subsystem: Bundle.main.bundleIdentifier ?? "com.example.catalog",
        category: "catalog-load"
    )

    @Published private(set) var products: [Product] = []

    func reload() async {
        let id = signposter.makeSignpostID()
        let state = signposter.beginInterval("CatalogReload", id: id)
        defer { signposter.endInterval("CatalogReload", state) }

        async let productsResponse = api.fetchProducts()
        async let featureFlags = api.fetchFeatureFlags()
        let (response, flags) = try! await (productsResponse, featureFlags)
        products = response.filtered(using: flags)
    }
}

Değişiklikten önce bağımsız fetchProducts() ve fetchFeatureFlags() çağrılarını sıralı çalıştırın, ardından yukarıdaki async let sürümünü aynı ağ profiliyle 30 kez ölçün. Xcode Instruments içindeki Points of Interest şablonunda CatalogReload için p50 ve p95 değerlerini ayrı kaydedin; yalnızca ortalama değeri kullanmayın. Soğuk cache, sabit test hesabı ve Network Link Conditioner profili olmadan yapılan karşılaştırma yanıltıcıdır. async let burada iki isteği aynı anda başlatır; ikinci sonuç birincinin girdisine bağlıysa paralelleştirmek yerine bağımlılığı koruyun, aksi halde gereksiz istek ve iptal edilmesi zor işler üretirsiniz.

Xcode eğitimi: Instruments bulgusunu gerçek kod değişikliğine bağlamak

Bir xcode eğitimi oturumunda signpost intervali yüksek çıktığında doğrudan Task.detached eklemek doğru teşhis değildir. Points of Interest içinde yavaş bir CatalogReload örneğini seçin, aynı zaman aralığını Time Profiler'da açın ve ana iş parçacığında ImageIO decode veya büyük bir Swift Collection kopyası olup olmadığına bakın. Örneğin API görselinin tamamını decode etmek yerine hedef piksel boyutunda thumbnail üretmek, heap tahsisini ve ana aktördeki çizim öncesi maliyeti azaltır.

import ImageIO
import UIKit

func downsample(data: Data, pointSize: CGSize, scale: CGFloat) -> UIImage? {
    let sourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    guard let source = CGImageSourceCreateWithData(data as CFData, sourceOptions) else {
        return nil
    }

    let maxPixelSize = max(pointSize.width, pointSize.height) * scale
    let options: CFDictionary = [
        kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceShouldCacheImmediately: true
    ] as CFDictionary

    guard let image = CGImageSourceCreateThumbnailAtIndex(source, 0, options) else {
        return nil
    }
    return UIImage(cgImage: image)
}

Önce UIImage(data:) kullanan sürümle 20 görsellik aynı listeyi açın; ardından downsample sürümünde aynı CatalogReload signpost p95'ini ve Allocations aracındaki persistent bytes değerini karşılaştırın. kCGImageSourceShouldCacheImmediately true seçeneği decode maliyetini kontrollü noktaya taşır, fakat bu fonksiyonu @MainActor üzerinde çağırırsanız maliyeti yine UI gecikmesine eklersiniz. Decode'u bir actor veya URLSession sonrası arka plan yürütmesinde yapın; UIImage nesnesini sadece görünüm durumuna atarken ana aktöre getirin.

iOS MVVM mimarisi ve app store yayınlama için MetricKit hattı

ios mvvm mimarisi içinde ViewModel'in Logger singleton'ına doğrudan bağlı olması testlerde olay doğrulamasını zorlaştırır. NetworkClient veya DiagnosticsRecording gibi küçük bir protokol enjekte edin; production implementasyonu OSLog yazar, test implementasyonu olayları bellekte toplar. Böylece örneğin 401 yanıtında token yazılmadığını birim testinde string eşleştirmesiyle denetleyebilirsiniz.

import MetricKit

final class MetricsSubscriber: NSObject, MXMetricManagerSubscriber {
    func start() {
        MXMetricManager.shared.add(self)
    }

    func didReceive(_ payloads: [MXMetricPayload]) {
        for payload in payloads {
            let json = payload.jsonRepresentation()
            DiagnosticsStore.shared.enqueue(json)
        }
    }
}

@main
struct CatalogApp: App {
    init() {
        MetricsSubscriberHolder.shared.subscriber.start()
    }

    var body: some Scene {
        WindowGroup { RootView() }
    }
}

MetricKit teslimatı anlık bir crash callback'i değildir; sistem payload'ları daha sonra ve toplu iletir. Bu nedenle subscriber'ı uygulama başında kaydedin, JSON'u kuyrukta şifreli ve boyut limitli saklayın, yüklemeyi açık tanılama izni ve retry politikasıyla yapın. app store yayınlama öncesinde remote diagnostics uç noktasına gönderilen alanları Privacy Nutrition Label beyanıyla karşılaştırın. Kullanıcının cihazındaki unified log deposunu sunucunuza otomatik çekebileceğinizi varsaymak hatalıdır; OSLog yerel teşhis içindir, uzaktan toplama için ayrı ve açık rızalı bir taşıma hattı gerekir.

Sık Sorulan Sorular

SwiftUI eğitimi sırasında OSLog mesajlarını Xcode dışında nasıl filtrelerim?

Bağlı simulator veya Mac log deposunda subsystem ve category ile filtreleyin:

log show --last 30m --style compact --predicate 'subsystem == "com.example.catalog" AND category == "network"'
Gerçek iPhone için Console uygulamasından cihazı seçip aynı alanlarla filtre uygulayın. Kullanıcı cihazından bu komutla uzaktan log alamazsınız.

iOS kursu projesinde Signpost p95 değeri nasıl karşılaştırılmalı?

Önce ve sonra sürümünde aynı signpost adını kullanın, her sürümü en az 30 tekrar çalıştırın ve soğuk cache ile simüle edilmiş ağ profilini sabitleyin. Instruments Points of Interest ekranından CatalogReload p50, p95 ve maksimum değerlerini CSV olarak kaydedin; tek bir hızlı çalıştırmayı sonuç kabul etmeyin.

Swift kursu uygulamasında Logger ile hangi veriler public yazılabilir?

Sadece enum tabanlı route adı, HTTP statusCode, uygulama sürüm kanalı gibi önceden sınıflandırılmış alanları public yapın. URL, e-posta, sipariş kimliği, hata gövdesi ve request ID için private veya private(mask: .hash) kullanın. Public alan listesini code review kontrol listesine eklemek, sonradan log temizlemekten daha güvenlidir.

iPhone uygulama geliştirme sırasında MetricKit crash verisi anında gelir mi?

Hayır. MXMetricManager payload'ları sistemin teslim zamanına bağlı olarak toplu gelir. Crash anında kullanıcıya ağ isteği attırmaya çalışmayın; didReceive içindeki payload.jsonRepresentation() verisini yerel kuyrukta saklayın ve sonraki uygun bağlantıda, kullanıcının tanılama izni varsa yükleyin.

AI / LLM Discovery

Bu makale Opendart Akademi iOS / Swift eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt