Tüm Yazılar
KategoriPerformance
Okuma Süresi
19 dk
Yayın Tarihi
...
Kelime Sayısı
1.823kelime

Kahveni hazırla - bu içerikli bir makale!

App Store'da 200MB limiti mi aşıyorsun? Binary size, asset optimization, App Thinning ve on-demand resources ile uygulamanı küçült.

iOS App Size Optimization: Binary'den Asset'e Her Byte Önemli

"Uygulamanız 200MB'ı aştığı için cellular download yapılamıyor." Bu mesajı gördüğün an, kullanıcıların yarısını kaybettin demektir.

App size, kullanıcı ediniminde kritik bir faktör. Araştırmalar gösteriyor ki her 10MB artış, download oranını %2.5 düşürüyor. Bu rehberde, uygulamanı nasıl küçülteceğini öğreneceksin.

İçindekiler

  1. Neden App Size Önemli?
  2. App Size Raporu Oluşturma
  3. Asset Optimization
  4. Binary Size Azaltma
  5. App Thinning
  6. On-Demand Resources
  7. Dynamic Library Stratejileri
  8. Build Settings Optimizasyonu
  9. Continuous Monitoring
  10. Gerçek Dünya Case Study
  11. Sonuç ve Öneriler

Neden App Size Önemli? {#neden-onemli}

Apple'ın koyduğu sınırlar:

Limit
Değer
Sonuç
**Cellular Download**
200 MB
Üstü sadece WiFi
**App Store Limit**
4 GB
Upload red
**Executable Limit**
500 MB
Her slice için
**watchOS Limit**
75 MB
Daha katı

İstatistikler

  • %50: kullanıcı 100MB+ uygulamaları indirmekten kaçınıyor
  • %20: kullanıcı WiFi beklemek yerine vazgeçiyor
  • Her 10MB azalma = +2.5% conversion rate
⚠️ Dikkat: App Store'da gördüğün boyut, thinned boyut değil!

App Size Raporu Oluşturma {#size-raporu}

Xcode'un built-in araçlarıyla analiz başla:

Archive ve Export

bash
1# Archive yap
2xcodebuild -scheme MyApp -archivePath MyApp.xcarchive archive
3 
4# Export with app thinning report
5xcodebuild -exportArchive \
6 -archivePath MyApp.xcarchive \
7 -exportPath ./Export \
8 -exportOptionsPlist ExportOptions.plist

Binary Size Analizi

bash
1# Binary'nin segment dağılımını gör
2size -l -m MyApp.app/MyApp
3 
4# Symbol bilgisi
5nm -S MyApp.app/MyApp | sort -k 2 -r | head -50

Asset Optimization {#asset-optimization}

Genellikle app size'ın %60-80'i asset'lerden gelir:

Image Compression

bash
1# PNG optimization
2pngquant --quality=65-80 --speed 1 --output optimized.png original.png
3 
4# WebP conversion (iOS 14+)
5cwebp -q 80 image.png -o image.webp
6 
7# JPEG optimization
8jpegoptim --max=80 --strip-all image.jpg

Asset Catalog Optimization

Build Settings'de:

  • ASSETCATALOG_COMPILER_OPTIMIZATION = space

Asset Catalog'da:

  • Sadece gerekli scale'leri ekle (@2x, @3x)
  • PDF yerine PNG kullan
  • Unused image'ları sil

Vector vs Raster Karar Ağacı

Görsel basit ve tek renk mi?

  • EVET → SF Symbol veya PDF kullan

Fotoğraf mı?

  • EVET → HEIC/JPEG kullan
  • HAYIR → PNG kullan, WebP'ye çevir (iOS 14+)

Binary Size Azaltma {#binary-size}

Dead Code Elimination

swift
1// Build Settings
2DEAD_CODE_STRIPPING = YES
3STRIP_INSTALLED_PRODUCT = YES
4 
5// Swift-specific
6SWIFT_OPTIMIZATION_LEVEL = -Osize // Release için
7 
8// Link-Time Optimization
9LLVM_LTO = YES

Symbol Stripping

swift
1// Build Settings
2STRIP_STYLE = all // Release için
3DEBUG_INFORMATION_FORMAT = dwarf-with-dsym

Generics Specialization

swift
1// ❌ Her generic kullanımı binary'de duplicate oluşturur
2func process<T: Numeric>(_ value: T) -> T {
3 return value * 2
4}
5 
6// ✅ Protocol-based yaklaşım
7protocol Processable {
8 static func process(_ value: Self) -> Self
9}

App Thinning {#app-thinning}

App Thinning, Apple'ın otomatik optimizasyon sistemi:

Slicing

Asset Catalog'da otomatik:

  • Sadece hedef cihaza uygun @2x veya @3x
  • Sadece hedef architecture (arm64)
  • Sadece hedef cihaz özellikleri

Bitcode

swift
1// Build Settings
2ENABLE_BITCODE = YES

Bitcode, App Store'un binary'yi yeniden optimize etmesine izin verir.


On-Demand Resources {#on-demand-resources}

Kullanıcının hemen ihtiyaç duymadığı içerikleri sonra indir:

swift
1class LevelManager {
2 private var resourceRequest: NSBundleResourceRequest?
3
4 func loadLevel(_ levelTag: String) async throws -> LevelData {
5 // Önce cache'i kontrol et
6 if Bundle.main.preservationPriority(forTag: levelTag) > 0.5 {
7 return try loadLocalLevel(levelTag)
8 }
9
10 // İndir
11 let request = NSBundleResourceRequest(tags: [levelTag])
12 self.resourceRequest = request
13
14 try await request.beginAccessingResources()
15
16 let levelData = try loadLocalLevel(levelTag)
17
18 // Cache priority ayarla
19 Bundle.main.setPreservationPriority(0.8, forTags: [levelTag])
20
21 return levelData
22 }
23
24 func unloadLevel(_ levelTag: String) {
25 resourceRequest?.endAccessingResources()
26 resourceRequest = nil
27 Bundle.main.setPreservationPriority(0.0, forTags: [levelTag])
28 }
29}

Dynamic Library Stratejileri {#dynamic-library}

Static vs Dynamic

Özellik
Static
Dynamic
**Load Time**
Daha uzun app launch
Lazy load edilebilir
**Binary Size**
Tek binary, daha büyük
Ayrı .dylib dosyaları
**Update**
Tüm app güncellenmeli
Sadece library güncellenebilir

CocoaPods / SPM Optimization

ruby
1# Podfile
2use_frameworks! :linkage => :static # Static linking

Build Settings Optimizasyonu {#build-settings}

Release Build Settings

swift
1// Optimization
2SWIFT_OPTIMIZATION_LEVEL = -Osize
3GCC_OPTIMIZATION_LEVEL = s
4 
5// Dead Code
6DEAD_CODE_STRIPPING = YES
7STRIP_INSTALLED_PRODUCT = YES
8STRIP_STYLE = all
9COPY_PHASE_STRIP = YES
10 
11// Link-Time Optimization
12LLVM_LTO = YES
13 
14// Bitcode
15ENABLE_BITCODE = YES
16 
17// Asset Optimization
18ASSETCATALOG_COMPILER_OPTIMIZATION = space
19 
20// Swift
21SWIFT_COMPILATION_MODE = wholemodule

Continuous Monitoring {#continuous-monitoring}

Size regression'ları erken yakala:

yaml
1# CI/CD size check
2- name: Check Size Limit
3 run: |
4 SIZE=$(stat -f%z Export/MyApp.ipa)
5 MAX_SIZE=200000000 # 200 MB
6 if [ $SIZE -gt $MAX_SIZE ]; then
7 echo "App size exceeds limit!"
8 exit 1
9 fi

Gerçek Dünya Case Study {#case-study}

Bir e-ticaret uygulamasını 180MB'dan 65MB'a nasıl düşürdük:

Başlangıç Durumu

  • Total: 180 MB
  • Assets: 120 MB (67%)
  • Binary: 45 MB (25%)
  • Other: 15 MB (8%)

Uygulanan Optimizasyonlar

Optimizasyon
Kazanç
WebP'ye geçiş
-40 MB
Unused asset temizliği
-25 MB
On-demand videos
-15 MB
System fonts kullanımı
-8 MB
LTO etkinleştirme
-5 MB
Dead code stripping
-12 MB
Static linking
-8 MB
Unused frameworks
-2 MB

Son Durum

  • Total: 65 MB (%64 azalma!)

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?


Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Swift Package Manager Size Impact Analizi {#spm-size-impact}

SPM bağımlılıkları binary size'ı ciddi şekilde şişirebilir. Her package'ın etkisini ölçmek kritik önem taşır.

Package Size Ölçüm Script'i

bash
1# Her SPM dependency'nin binary'ye etkisini ölç
2# 1. Tüm bağımlılıklar dahil build
3xcodebuild -scheme MyApp -configuration Release build
4FULL_SIZE=$(stat -f%z Build/Products/Release-iphoneos/MyApp.app/MyApp)
5 
6# 2. Şüpheli paketi kaldır, tekrar build et
7# Package.swift'ten paketi comment'le
8xcodebuild -scheme MyApp -configuration Release clean build
9REDUCED_SIZE=$(stat -f%z Build/Products/Release-iphoneos/MyApp.app/MyApp)
10 
11# 3. Farkı hesapla
12echo "Package impact: $(( (FULL_SIZE - REDUCED_SIZE) / 1024 )) KB"

Popüler Kütüphanelerin Size Impact'i

Kütüphane
Yaklaşık Binary Etkisi
Alternatif
Alternatif Etkisi
**Alamofire**
~1.2 MB
URLSession wrapper
~50 KB
**Kingfisher**
~800 KB
SDWebImage (lighter)
~500 KB
**SnapKit**
~300 KB
NSLayoutConstraint ext
~20 KB
**SwiftyJSON**
~200 KB
Codable (native)
0 KB
**Realm**
~8 MB
Core Data / SwiftData
0 KB (system)
**Firebase Analytics**
~3.5 MB
Custom analytics
~100 KB
**Lottie**
~1.5 MB
Core Animation
0 KB (system)

Lightweight Alternatif Stratejisi

swift
1// ❌ Alamofire (1.2 MB binary impact) - basit API call'lar için overkill
2import Alamofire
3AF.request("https://api.example.com/data").responseDecodable(of: MyModel.self) { response in
4 // ...
5}
6 
7// ✅ Native URLSession extension (50 KB) - aynı iş, minimal overhead
8extension URLSession {
9 func decode<T: Decodable>(
10 _ type: T.Type,
11 from url: URL
12 ) async throws -> T {
13 let (data, response) = try await self.data(from: url)
14 guard let httpResponse = response as? HTTPURLResponse,
15 (200...299).contains(httpResponse.statusCode) else {
16 throw URLError(.badServerResponse)
17 }
18 return try JSONDecoder().decode(T.self, from: data)
19 }
20}
21 
22// Kullanım
23let data = try await URLSession.shared.decode(MyModel.self, from: apiURL)

Image Format Karşılaştırma ve Seçim Rehberi {#image-format}

Doğru image format seçimi, asset boyutunu %50-70 azaltabilir.

Format Benchmark Sonuçları

Format
1000x1000px Fotoğraf
1000x1000px Illustration
Transparency
iOS Desteği
**PNG**
2.1 MB
450 KB
Evet
iOS 2+
**JPEG (q80)**
180 KB
120 KB
Hayır
iOS 2+
**WebP (q80)**
130 KB
85 KB
Evet
iOS 14+
**HEIC (q80)**
110 KB
90 KB
Evet
iOS 11+
**AVIF**
95 KB
70 KB
Evet
iOS 16+

Otomatik Asset Dönüştürme Script'i

bash
1#!/bin/bash
2# Tüm PNG asset'leri WebP'ye toplu dönüştür
3ASSET_DIR="./Assets.xcassets"
4SAVINGS=0
5 
6find "$ASSET_DIR" -name "*.png" -type f | while read file; do
7 PNG_SIZE=$(stat -f%z "$file")
8 WEBP_FILE="$(echo "$file" | sed 's/.png$//').webp"
9 
10 cwebp -q 80 -m 6 "$file" -o "$WEBP_FILE" 2>/dev/null
11 WEBP_SIZE=$(stat -f%z "$WEBP_FILE")
12 
13 SAVED=$(( (PNG_SIZE - WEBP_SIZE) / 1024 ))
14 echo "$(basename "$file"): $SAVED KB saved"
15 SAVINGS=$(( SAVINGS + SAVED ))
16done
17 
18echo "Toplam tasarruf: $SAVINGS KB"

Karar Matrisi

Fotoğraf veya gerçekçi görsel mi?

  • iOS 16+ hedefliyorsan → AVIF
  • iOS 14+ hedefliyorsan → WebP
  • iOS 11+ hedefliyorsan → HEIC
  • Eski iOS desteği → JPEG

Icon veya basit illustration mu?

  • Tek renk, vektörel → SF Symbol (0 KB ek maliyet)
  • Çok renkli, küçük → WebP veya PNG (asset catalog optimize eder)
  • Animasyonlu → Lottie yerine APNG veya Core Animation

Sonuç ve Öneriler {#sonuc-ve-oneriler}

App size optimization sürekli bir süreç. İşte yol haritası:

  1. Ölç - Mevcut durumu analiz et
  2. Önceliklendir - En büyük kazancı verecek alanları belirle
  3. Uygula - Bir seferde bir optimizasyon
  4. Doğrula - Her adımda boyutu kontrol et
  5. Otomatize - CI/CD'ye entegre et

Kaynaklar


*Her byte önemli. Kullanıcıların WiFi beklemesine gerek yok.* 📦

Etiketler

#Performance#iOS#Optimization#App Size#Binary#Swift
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz