SwiftUI projelerinde derleme süresini ölçmeyi, type checker darboğazlarını bulmayı ve modüler bağımlılık grafiğiyle incremental build maliyetini düşürmeyi öğrenin. Bu xcode eğitimi, CI ölçümlerini de içerir.
SwiftUI Eğitiminde Derleme Süresi: Xcode Build Ayarları ve Modülerlik
Xcode Eğitimi: Önce Clean ve Incremental Build Süresini Ölçün
Bir ios eğitimi içinde derleme süresini sadece Xcode'daki genel ilerleme çubuğundan değerlendirmek yanıltıcıdır. Aynı commit için clean build ile incremental build farklı problemleri gösterir: clean build modül derleme maliyetini, incremental build ise tek dosya değişikliğinin bağımlı target'lara yayılımını ölçer. Sabit bir simulator hedefi kullanın, her senaryoyu en az 5 kez çalıştırın ve ilk çalıştırmayı Swift Package çözümleme maliyeti nedeniyle istatistiğe dahil etmeyin.
# Clean build: derlenen modullerin toplam maliyetini olcer
xcodebuild clean build -workspace StoreApp.xcworkspace -scheme StoreApp -configuration Debug -destination 'generic/platform=iOS' -derivedDataPath "$PWD/.derived-data" -showBuildTimingSummary CODE_SIGNING_ALLOWED=NO | tee clean-build.log
# Incremental build: once onemsiz bir implementation degisikligi yapin,
# sonra clean komutu olmadan ayni build komutunu calistirin.
grep -E 'CompileSwift|SwiftCompile|Ld ' clean-build.logXcode Build Timeline ile terminaldeki -showBuildTimingSummary çıktısını birlikte inceleyin. Örneğin FeatureCatalog target'ındaki 20 saniyelik SwiftCompile kaydı, tek bir satır değişikliğinden sonra da tekrar oluşuyorsa compiler dosyayı yeniden derlemek zorunda kalıyordur. Bunun yaygın nedeni, sık değişen bir dosyada public API, global sabit veya extension tanımlamaktır. Swift'in bağımlılık takibi public arayüz değiştiğinde modül tüketicilerini de invalid eder; sorun cihaz hızı değil, derleme grafiğidir.
iOS MVVM Mimarisi İçin Feature Modülleri ve Dar Public API
ios mvvm mimarisi içinde her ViewModel'i tek bir dev target'a koymak, küçük değişikliklerde bile tüm presentation katmanını yeniden derletebilir. Catalog, Checkout ve Account gibi feature'ları Swift Package hedeflerine ayırın; App target yalnızca feature composition ve uygulama yaşam döngüsünü içersin. Bu yaklaşım iPhone uygulama geliştirme sürecinde çalışma zamanı modül sayısını artırmak için değil, derleme bağımlılıklarını açık hale getirmek için kullanılır.
// Packages/AppFeatures/Package.swift
import PackageDescription
let package = Package(
name: "AppFeatures",
platforms: [.iOS(.v16)],
products: [
.library(name: "CatalogFeature", targets: ["CatalogFeature"])
],
targets: [
.target(
name: "CatalogFeature",
dependencies: ["CatalogDomain", "DesignSystem"]
),
.target(name: "CatalogDomain")
]
)Feature'ın dışarı açtığı yüzeyi bir factory veya route tipiyle sınırlandırın. Örneğin public struct CatalogFeatureFactory yalnızca makeRoot() yayınlasın; repository implementasyonu, DTO'lar ve yardımcı SwiftUI view'ları internal kalsın. Public bir protocol'e üçüncü taraf SDK tipi sızarsa, SDK sürümündeki değişiklik modül arayüzünü gereksiz yere invalid eder. Bu durumda @_implementationOnly import VendorAnalytics kullanılabilir, fakat bu import edilen tip hiçbir public imzada, public stored property'de veya @inlinable gövdede yer almamalıdır; aksi halde module interface üretimi ya da istemci derlemesi kırılır.
Dinamik framework sayısını refleks olarak artırmayın. Swift Package target'larının mantıksal modüllere bölünmesi derleme izolasyonu sağlar; iOS'ta gereksiz dynamic framework kullanımı ise uygulama açılışında dyld'nin yükleme ve binding işini büyütebilir. Xcode Build Timeline'da çok sayıda Ld ve CodeSign adımı görüyorsanız, feature sınırlarını korurken ürün bağlantı türünü ve embed edilen framework listesini ayrıca denetleyin.
SwiftUI Eğitimi: Type Checker Darboğazını Kaynak Dosyasına İndirin
Bir swiftui eğitimi sırasında en pahalı dosya çoğu zaman algoritması karmaşık olan değil, tek bir body ifadesinde çok sayıda generic modifier ve koşul taşıyandır. Swift type checker, zincirdeki her modifier için generic kısıtları çözer; iç içe if, ForEach, closure ve overloaded initializer kombinasyonları aday tip sayısını hızla büyütür. Geçici teşhis için target'ın OTHER_SWIFT_FLAGS alanına aşağıdaki bayrakları ekleyin ve CI logunda eşik aşan ifadeleri görün.
// Debug konfigürasyonunda OTHER_SWIFT_FLAGS
-Xfrontend -warn-long-expression-type-checking=200
-Xfrontend -debug-time-function-bodies
// Terminalde uzun type-check kayitlarini ayiklamak icin
xcodebuild build -scheme StoreApp -configuration Debug -destination 'generic/platform=iOS' 2>&1 | grep -E 'type-checking|body' Aşağıdaki refactor, AnyView ile type erasure yapmak yerine compiler'ın çözmesi gereken ifadeyi küçük generic sınırlara ayırır. AnyView bazı durumlarda SwiftUI identity ve diff davranışını da belirsizleştirdiği için yalnızca gerçekten heterojen view koleksiyonlarında tercih edilmelidir.
struct ProductRow: View {
let product: Product
let isFavorite: Bool
let onFavorite: (Product.ID) -> Void
var body: some View {
HStack(spacing: 12) {
thumbnail
metadata
favoriteButton
}
.contentShape(Rectangle())
}
private var thumbnail: some View {
AsyncImage(url: product.imageURL) { image in
image.resizable().scaledToFill()
} placeholder: {
Color.secondary.opacity(0.15)
}
.frame(width: 56, height: 56)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
private var metadata: some View {
VStack(alignment: .leading) {
Text(product.name).font(.headline)
Text(product.price.formatted(.currency(code: "TRY")))
.font(.subheadline)
}
}
private var favoriteButton: some View {
Button { onFavorite(product.id) } label: {
Image(systemName: isFavorite ? "heart.fill" : "heart")
}
}
}Önce ProductRow.swift için logdaki type-check süresini, sonra aynı dosyanın incremental build süresini karşılaştırın. Bayrakları release build'de açık bırakmayın: -debug-time-function-bodies log hacmini ciddi biçimde artırır ve yalnızca teşhis amaçlıdır. Bir swift eğitimi veya swift kursu örneğinde bu bayrakların kalıcı ayar gibi verilmesi sık hatadır; bunlar performans testi enstrümantasyonudur.
Swift Kursu Projelerinde Derleme Ayarlarını Konfigürasyona Göre Ayırın
Debug konfigürasyonunda SWIFT_COMPILATION_MODE=incremental, release archive sürecinde ise genellikle wholemodule kullanın. Incremental mod, dosya bağımlılık grafiğini kullanarak yerel geliştirmede yeniden derlenen dosya sayısını azaltır. Whole-module optimization ise release'te optimizer'ın modül çapında analiz yapmasına izin verir, ancak küçük bir kod değişikliğiyle hızlı geri bildirim beklenen debug döngüsü için uygun değildir.
// Config/Debug.xcconfig
SWIFT_COMPILATION_MODE = incremental
SWIFT_OPTIMIZATION_LEVEL = -Onone
// Config/Release.xcconfig
SWIFT_COMPILATION_MODE = wholemodule
SWIFT_OPTIMIZATION_LEVEL = -O
// Her target icin Build Settings'te base configuration olarak
// ilgili .xcconfig dosyasini atayin.Bu ayrımı doğrulamak için aynı feature değişikliğiyle Debug incremental build'i ve Release archive'ı ayrı ölçün; archive süresinin düşük olması beklenen hedef değildir. Release ayarını Debug'a kopyalamak, her düzenlemede tüm modülün yeniden optimize edilmesine neden olabilir. Tersine, release'te yanlışlıkla debug optimizasyonu kullanmak binary boyutu, inlining ve sıcak kod yolları açısından üretim profilini temsil etmez. Bu ayrım özellikle ekipteki ios kursu katılımcılarının 'lokalde hızlı derleniyor' sonucunu archive süresiyle karıştırmasını önler.
App Store Yayınlama Öncesi CI'da Tekrarlanabilir Build Metrikleri
app store yayınlama hattında derleme süresi regresyonunu fark etmek için CI job'ı her merge request'te aynı macOS imajı, aynı Xcode sürümü ve sabit bağımlılık çözümlemesiyle çalışmalıdır. Yalnızca Swift Package kaynak önbelleğini saklayın; DerivedData'yı körlemesine paylaşmak mutlak path, build setting veya compiler değiştiğinde eski object dosyalarını taşır ve ölçümü kirletir. SourcePackages çözümlemesini proje klasörü altında tutmak cache anahtarını açıkça yönetmenizi sağlar.
# CI asamalari
xcodebuild -resolvePackageDependencies -workspace StoreApp.xcworkspace -scheme StoreApp -clonedSourcePackagesDirPath "$CI_PROJECT_DIR/.spm"
xcodebuild build -workspace StoreApp.xcworkspace -scheme StoreApp -configuration Debug -destination 'generic/platform=iOS' -clonedSourcePackagesDirPath "$CI_PROJECT_DIR/.spm" -derivedDataPath "$CI_PROJECT_DIR/.derived-data" -disableAutomaticPackageResolution -showBuildTimingSummary -resultBundlePath "$CI_PROJECT_DIR/build.xcresult" CODE_SIGNING_ALLOWED=NOCI, Package.resolved hash'ini ve Xcode sürümünü cache key'e katmalıdır. Ayrıca build.xcresult dosyasını artifact olarak saklayın; Xcode Organizer veya xcresulttool ile başarısız build'in hangi CompileSwift adımında uzadığını sonradan inceleyebilirsiniz. Haftalık olarak main branch üzerinde 5 clean build çalıştırıp medyanı kaydedin; örneğin medyan 180 saniyeden 225 saniyeye çıktıysa, tek bir yavaş run yerine yüzde 25'lik tekrarlanabilir regresyona göre issue açabilirsiniz. Bu, iphone uygulama geliştirme ekibinin derleme maliyetini PR birleşmeden önce görünür kılar.
İlgili Eğitim
YTÜSEM İlgili Eğitim
Sık Sorulan Sorular
SwiftUI eğitimi projesinde hangi Xcode aracı derleme süresini bulur?
Önce Xcode Build Timeline ile en uzun target ve CompileSwift adımını bulun. Ardından terminalde xcodebuild komutuna -showBuildTimingSummary ekleyin. Clean ve incremental senaryoları ayrı çalıştırın; sadece clean build sonucu, günlük geliştirme döngüsündeki invalidation sorununu göstermez.
iOS MVVM mimarisi için her feature'ı dynamic framework yapmak gerekir mi?
Hayır. Feature'ı ayrı Swift Package veya target yapmak derleme bağımlılıklarını izole eder, fakat onu dynamic framework'e çevirmek zorunlu değildir. Gereksiz dynamic framework'ler uygulama başlatılırken ek yükleme ve symbol binding maliyeti çıkarabilir. Build Timeline'daki Ld ve CodeSign adımlarını ölçerek karar verin.
Swift kursu uygulamasında long expression type checking uyarısı nasıl çözülür?
OTHER_SWIFT_FLAGS içine -Xfrontend -warn-long-expression-type-checking=200 ekleyip problemli ifadeyi logdan bulun. Uzun SwiftUI modifier zincirlerini private some View bileşenlerine bölün, karmaşık closure'lara ara değişken veya açık tip ekleyin. AnyView'i yalnızca heterojen view saklama ihtiyacı varsa kullanın.
App Store yayınlama öncesi iOS build süresi CI'da nasıl izlenir?
xcodebuild ile -resultBundlePath ve -showBuildTimingSummary kullanın, xcresult artifact'ını saklayın ve Package.resolved hash'iyle SourcePackages cache'i oluşturun. Ana branch'te aynı runner üzerinde 5 clean build'in medyanını kaydedin; PR sonrasında yüzde bazlı regresyon eşiği tanımlayın.
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.


