👨💻 How to: оптимизировать производительность iOS-приложения
Вот 10 практических хаков для повышения производительности iOS-приложения, проверенных на производственных проектах.
1️⃣ Безжалостно профилируйте с помощью инструментов.
Инструменты: в Xcode есть Time Profiler, Allocations и Energy Log (Xcode -> Open Developer Tool -> Instruments).
Что делать: выявляйте узкие места, анализируя использование процессора, памяти и энергии. Например, используйте Time Profiler, чтобы выявить неэффективные циклы или чрезмерную нагрузку на DispatchQueue.
Профессиональный совет: отсортируйте трейсы по «тяжелому весу», чтобы найти самые затратные функции.
Почему это важно: 80% проблем с производительностью связаны с 20% вашего кода.
2️⃣ Оптимизируйте Auto Layout с помощью isActive.
Проблема: сложные иерархии ограничений приводят к тому, что проходы компоновки резко увеличивают нагрузку на процессор.
Решение: активируйте/деактивируйте ограничения массово, а не добавляйте/удаляйте их по отдельности:
NSLayoutConstraint.activate([ view.topAnchor.constraint(equalTo: parent.topAnchor), view.leadingAnchor.constraint(equalTo: parent.leadingAnchor) ])
Бонус: используйте UIStackView для более простых макетов и меньшего количества ограничений.
3️⃣ Сокращайте динамическую диспетчеризацию с помощью final и private.
Хак Swift: помечайте классы как final, а методы как private, чтобы обеспечить оптимизацию компилятора:
final class NetworkManager { private func fetchData() { ... } // Static dispatch for faster execution }
Зачем: динамическая диспетчеризация (например, переопределение методов) увеличивает накладные расходы во время выполнения.
4️⃣ Кешируйте дорогостоящие операции.
Пример: хранение декодированных изображений, ответов сети или вычисленных значений:
let imageCache = NSCache() func loadImage(url: URL) -> UIImage? { if let cachedImage = imageCache.object(forKey: url.absoluteString as NSString) { return cachedImage } // Decode and cache... }
Пример использования: избегайте повторения тяжелых задач, таких как декодирование изображений или разбор JSON.
5️⃣ Используйте CALayer.shouldRasterize для сложных представлений.
Когда: рендеринг сложных теней, трансформаций или анимаций.
Как: растеризуйте статичные слои в bitmap изображение один раз:
layer.shouldRasterize = true layer.rasterizationScale = UIScreen.main.scale
6️⃣ Выгружайте работы в фоновые потоки.
Золотое правило: держите основной поток свободным для обновления пользовательского интерфейса.
DispatchQueue.global(qos: .userInitiated).async { let processedData = parseLargeJSON() DispatchQueue.main.async { self.updateUI(with: processedData) } }
Избегайте: блокирования основного потока синхронными вызовами или тяжелыми вычислениями.
7️⃣ Используйте UILabel.preferredMaxLayoutWidth для ячеек.
Проблема: неправильная ширина меток заставляет выполнять лишние проходы по макету.
Исправление: установите preferredMaxLayoutWidth, чтобы избежать двусмысленных ограничений:
label.preferredMaxLayoutWidth = UIScreen.main.bounds.width — 32
Результат: более быстрая прокрутка UITableView/UICollectionView.
8️⃣ Выбирайте UIImage(named:) вместо UIImage(contentsOfFile:).
Почему: UIImage(named:) автоматически кэширует изображения в памяти, а contentsOfFile: — нет.
Лучше всего подходит для: часто используемых ресурсов (иконок, графики пользовательского интерфейса).
9️⃣ Минимизировать drawRect: переопределения.
Издержки: кастомное рисование требует больших затрат процессора.
Альтернатива: используйте предварительно отрисованные изображения или свойства слоя (например, cornerRadius, borderWidth).
🔟 Лениво загружайте невидимое содержимое.
Стратегия: отложите загрузку внеэкранных представлений, данных или медиа.
lazy var analyticsManager: AnalyticsManager = { return AnalyticsManager() // Initialize only when first accessed }()
Применяйте: для тяжелых объектов, баз данных или SDK сторонних разработчиков.
Библиотека мобильного разработчика #свежак