РозробкаБудь-який рівень

iOS / Swift

iOS — це один вендор, один інструментарій, один набір правил — і взамін платформа, де залізо, ОС і мову проєктують разом. Swift — сучасна строго типізована мова без збирача сміття, тож пам’ять тут — те, про що ви міркуєте, а не те, що з вами стається. На цій сторінці — підрахунок посилань, SwiftUI проти UIKit, паралельність і той процес релізу, що дивує команди, які прийшли з вебу.

Пам’ять
Підрахунок, не збирання
Інтерфейс
SwiftUI, під ним UIKit
Реліз
Через рев’ю

Хто володіє цим об’єктом

У Swift немає збирача сміття. Кожен екземпляр класу несе лічильник того, скільки сильних посилань на нього вказує; компілятор сам вставляє збільшення й зменшення, і щойно лічильник доходить до нуля, об’єкт звільняється — негайно й детерміновано. Ця детермінованість — справжня перевага: немає пауз на збирання, пам’ять звільняється тієї ж миті, коли перестає бути потрібною, а deinit виконується в передбачуваній точці.

Swift звільняє об’єкт, коли ним більше ніхто не володіє, і компілятор вставляє цей підрахунок за вас — збирача сміття немає, пауз теж. Збій тут не в забутому звільненні, а в парі об’єктів, які тримають одне одного живими: лічильник ніколи не доходить до нуля, і жоден не звільняється. Розірвати цикл означає, що одне з двох посилань має відмовитися від володіння, — саме це роблять `weak` і `unowned`, і саме це робить `[weak self]` у замиканні, яке тримає сам об’єкт.

Ціна в тому, що підрахунок посилань не бачить циклу. Якщо два об’єкти тримають сильні посилання один на одного, кожен тримає лічильник іншого вище нуля назавжди, і жоден ніколи не звільняється — навіть після того, як усе решта в програмі забуло про їхнє існування. Нічого не падає; пам’ять просто росте. Три місця, де це трапляється стабільно: делегат, що вказує назад на власника; батько й дитина, що тримають одне одного; і замикання, яке захоплює self, тоді як об’єкт тримає це замикання.

Дві звички не дають цьому перетворитися на фольклор. Ставте print або точку зупину в deinit на екранах, які вас турбують, поки розробляєте: якщо він не спрацьовує, коли ви йдете з екрана, — у вас цикл, і ви знайшли його за десять секунд, а не в графі пам’яті через три місяці. І запускайте інструменти Leaks та Allocations перед релізом: відладник графа пам’яті в Xcode намалює вам цикл напряму, зі стрілками й усім іншим.

SwiftUI чи UIKit

На платформі два UI-фреймворки, і чесна позиція така: читати треба вміти обидва. UIKit імперативний: ви створюєте в’ю, тримаєте посилання й змінюєте їх у відповідь на події. SwiftUI декларативний: ви описуєте, який вигляд має мати інтерфейс для заданого стану, а фреймворк сам вираховує зміни — та сама розумова модель, що й у React, до якої дійшли незалежно.

SwiftUI

  • Значно менше коду на той самий екран і живі прев’ю просто під час набору.
  • Один фреймворк на iPhone, iPad, Mac, Watch і TV.
  • Кожен реліз додає можливостей, тож ваша мінімальна версія iOS вирішує, чим можна користуватися.
  • Складна власна розкладка й тонкий контроль досі відкочуються до UIKit через обгортку.

UIKit

  • П’ятнадцять років відповідей, бібліотек і поведінки, яку нікому не треба вгадувати.
  • Повний контроль над розкладкою, переходами й кожним крайнім випадком.
  • Те, на чому написано кожен наявний застосунок, — тож читати його ви будете так чи інакше.
  • Більше коду, більше стану, який треба синхронізувати руками, більше місць помилитися.

Для нового застосунку у 2026 році починайте зі SwiftUI і спускайтеся в UIKit там, де треба: взаємодія працює в обидва боки й це нормальна практика, а не визнання поразки. Для наявного UIKit-застосунку додавання SwiftUI екран за екраном — добре протоптаний шлях і значно безпечніший за переписування. А те, що насправді визначає, чи доступний вам SwiftUI, — це ваша мінімальна підтримувана версія iOS, бо більшість серйозних можливостей фреймворк здобув уже після першого релізу.

Паралельність без колбеків

Swift додав структуровану паралельність, і вона замінила десятиліття вкладених обробників завершення на async / await, що читається за порядком. Важливіше за синтаксис тут актор: тип, який захищає власний стан, пускаючи всередину лише одну задачу водночас, і перевіряє це компілятор, а не ваша дисципліна із замками. Гонки за даними перестають бути класом помилок, на які полюють, і стають помилкою компіляції.

Єдине правило, що на цій платформі не змінюється ніколи: робота з інтерфейсом відбувається в головному потоці. @MainActor каже це в системі типів — позначте ним модель в’ю, і компілятор гарантує, що її методи виконуються саме там. Оновлення в’ю з фонового потоку — це невизначена поведінка, яка зазвичай ніби працює й час від часу псує екран або валить застосунок, а це найгірший можливий профіль збою, бо він переживає тестування.

Як це виявляється в реальній поставці

Те, що дивує команди з вебу, — постачання тут не є деплоєм. Реліз проходить рев’ю App Store, яке триває від годин до днів і може бути відхилене: найчастіше через рядки дозволів, які нічого не пояснюють; через видалення акаунта, яке застосунок зобов’язаний пропонувати, якщо пропонує реєстрацію; через платежі, що обходять систему Apple; або через декларації приватності, що не збігаються з тим, що застосунок реально збирає. Нічого з цього не є свавіллям, але все це треба закладати в графік, а не виявляти в день релізу.

Дві звички вкорочують цей цикл. Віддавайте кожну збірку в TestFlight: це швидко, дає справжні пристрої й справжні звіти про падіння — і саме там знаходяться проблеми, які знайшло б рев’ю. І тримайте кількість підтримуваних версій iOS свідомою: нову версію тут приймають швидко, тож відмова від найстарішої щороку зазвичай не викликає суперечок — і саме вона відмикає можливості фреймворків, що прибирають код.

Де це вироджується

  • Цикли утримання через делегати й замикання течуть тихо й ніколи не валять застосунок.
  • unowned там, де мався на увазі weak, перетворює витік на падіння вже на справжньому пристрої.
  • Контролери в’ю, що ростуть, доки мережа, розбір і навігація не опиняться в одному файлі.
  • Інтерфейс, оновлений із фонового потоку: зазвичай ніби працює й час від часу псує стан.
  • Continuation, не відновлений на кожному шляху, лишає викликача призупиненим без жодної помилки.
  • Запити дозволів на старті замість моменту, коли вони справді потрібні фічі.
  • Вимоги рев’ю — видалення, приватність, платежі — виявлені в день, коли реліз мав вийти.

Коли це застосовувати

Застосовуйте, коли

  • Продукти, де досвід на iOS і є продуктом: продуктивність, вилизаність і конвенції платформи.
  • Усе, що спирається на можливості, які Apple випускає першими: віджети, live activities, моделі на пристрої, нове залізо.
  • Застосунки, де детермінована пам’ять і відсутність пауз збирання справді важать.
  • Команди, здатні добре підтримувати одну платформу, а не приблизно дві.

Уникайте, коли

  • Продукти, яким потрібні обидві платформи з однією командою й одним бюджетом, — для цього й є кросплатформні інструменти.
  • Усе, що потребує виправлень у той самий день без черги рев’ю: оновлювати код «по повітрю» тут не дозволено.
  • Бізнес-моделі, що конфліктують із правилами платежів магазину, — вирішуйте це до написання коду.
  • Команда без техніки Mac і без ресурсу вивчити інструментарій: Xcode обійти неможливо.

Було корисно?

Поділіться з тим, хто працює над тією ж задачею.