Skip to content

iOS Build Optimization Guide

This guide covers optimization techniques for reducing app size and improving performance when integrating the Squad SDK.

App Size Optimization

App Thinning

Enable App Thinning in Xcode to reduce the app's size for different devices:

  1. Slicing
// In your project settings:
// Build Settings > Build Options
ENABLE_BITCODE = NO // Since Xcode 14
STRIP_STYLE = all
DEPLOYMENT_POSTPROCESSING = YES
  1. On-Demand Resources Configure in Xcode:
<!-- Info.plist -->
<key>NSBundleResourceRequest</key>
<dict>
    <key>NSBundleResourceRequestTag</key>
    <string>initial-resources</string>
</dict>
  1. Asset Catalog Optimization
// Enable optimization in Build Settings
ASSETCATALOG_COMPILER_OPTIMIZATION = space
COMPRESS_PNG_FILES = YES
STRIP_PNG_TEXT = YES

Framework Optimization

  1. Link Squad SDK Dynamically
# Podfile
use_frameworks! :linkage => :dynamic
  1. Enable Link-Time Optimization
// Build Settings
LLVM_LTO = YES // Aggressive

Build Settings Optimization

Release Configuration

// Build Settings for Release
SWIFT_COMPILATION_MODE = wholemodule
SWIFT_OPTIMIZATION_LEVEL = -O
GCC_OPTIMIZATION_LEVEL = s

Dead Code Stripping

// Enable dead code stripping
DEAD_CODE_STRIPPING = YES
STRIP_SWIFT_SYMBOLS = YES

Resource Optimization

Image Optimization

  1. Asset Catalog Settings
// Enable compression
COMPRESS_PNG_FILES = YES
STRIP_PNG_TEXT = YES

// Enable on-demand resources
ENABLE_ON_DEMAND_RESOURCES = YES
  1. SVG Asset Usage
// Use PDF vectors when possible for resolution independence
// Asset Catalog: Preserve Vector Data = YES

String Optimization

// Enable string encryption
SWIFT_OBFUSCATE_STRINGS = YES // Custom build setting

// Enable constant folding
SWIFT_OPTIMIZATION_LEVEL = -O

Memory Optimization

WebView Memory Management

class SquadViewController: UIViewController {
    private func configureWebView() {
        let config = WKWebViewConfiguration()
        config.processPool = WKProcessPool()
        config.websiteDataStore = .nonPersistent()

        // Configure cache
        let cache = URLCache(
            memoryCapacity: 10 * 1024 * 1024,  // 10MB
            diskCapacity: 50 * 1024 * 1024,    // 50MB
            directory: nil
        )
        URLCache.shared = cache
    }
}

Memory Warning Handling

extension SquadViewController {
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

        // Clear image caches
        URLCache.shared.removeAllCachedResponses()

        // Clear WebView cache
        WKWebsiteDataStore.default().removeData(
            ofTypes: [.memoryCache],
            modifiedSince: .distantPast
        ) { }
    }
}

Network Optimization

Caching Strategy

let cachingConfig = URLSessionConfiguration.default
cachingConfig.requestCachePolicy = .returnCacheDataElseLoad
cachingConfig.urlCache = URLCache(
    memoryCapacity: 10 * 1024 * 1024,
    diskCapacity: 50 * 1024 * 1024
)

Image Loading

class ImageOptimizer {
    static func optimizedImage(_ image: UIImage) -> UIImage? {
        let data = image.jpegData(compressionQuality: 0.7)
        return data.flatMap(UIImage.init)
    }
}

Debug Optimization

Development vs Release

#if DEBUG
// Development-only code
#else
// Release-only optimizations
#endif

Logging Control

struct OptimizedLogger {
    static func log(_ message: String) {
        #if DEBUG
        print(message)
        #endif
    }
}

Measurement & Verification

Size Analysis

  1. Check app size:
xcrun devicespacecraft -size "App.ipa"
  1. Analyze binary:
xcrun size -m "YourApp.app/YourApp"

Performance Metrics

class PerformanceMonitor {
    static func measureMemory() {
        var info = mach_task_basic_info()
        var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4

        let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
            $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
                task_info(
                    mach_task_self_,
                    task_flavor_t(MACH_TASK_BASIC_INFO),
                    $0,
                    &count
                )
            }
        }

        if kerr == KERN_SUCCESS {
            print("Memory used: \(info.resident_size / 1024 / 1024) MB")
        }
    }
}

Best Practices

  1. Build Settings

  2. Enable optimization flags

  3. Configure proper architecture settings
  4. Enable dead code stripping

  5. Resource Management

  6. Optimize image assets

  7. Enable App Thinning
  8. Configure caching properly

  9. Memory Management

  10. Handle memory warnings

  11. Implement proper cleanup
  12. Monitor memory usage

  13. Network Optimization

  14. Configure proper caching
  15. Optimize request handling
  16. Monitor network usage

Troubleshooting

Common Issues

  1. Large App Size

  2. Check embedded frameworks

  3. Analyze resource usage
  4. Verify optimization settings

  5. Memory Issues

  6. Monitor memory warnings
  7. Check for leaks
  8. Verify cleanup implementation