Tüm Yazılar
KategoriPerformance
Okuma Süresi
19 dk
Yayın Tarihi
2024-03-20
Kelime Sayısı
1.824kelime

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

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

Özet

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

  • Her 10MB boyut artisi download oranini %2.5 dusuruyor; cellular limiti 200MB.
  • Ornek case study'de uygulama 180MB'dan 65MB'a (%64 azalma) dusuruldu.
  • SWIFT_OPTIMIZATION_LEVEL = -Osize performans kaybi %5'ten az, boyut kazanci %10-20.
  • Ornekte WebP'ye gecis -40MB, kullanilmayan asset temizligi -25MB kazandirdi.
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


Neden App Size Önemli?

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

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

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

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, 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

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

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

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

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

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 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

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

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ı

Lead Mobile Engineer

12+ yıllık deneyime sahip Lead Mobile Engineer. Swift, SwiftUI, Kotlin ve Flutter ile iOS, Android ve cross-platform mimarilerde uzman. Performanslı ve kullanıcı dostu mobil uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

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

Onay e-postasındaki bağlantıyı açıp “Aboneliğimi onayla” düğmesine bastığında aboneliğin başlar. Bültende açılma/tıklama istatistikleri tutulur; dilediğin an tek tıkla ayrılabilirsin. Gizlilik

Paylaş

İlgili İçerik