5 ключових помилок iOS-розробника-початківця
І як їх уникнути
IOS-розробка всіяна дрібними деталями, які легко пропустити. Деякі з них — мінорні, а деякі переростають у звички, яких складно позбутися.
В цій статті підкреслюємо наш курс із Мобільної розробки на Flutter і розповідаємо про поширені помилки новачків в iOS-розробці. Для зручності ділимо їх на дві групи — ті, що відносяться до хард- і до софт-скілів. Перші часто повʼязані з тим, що розробник може не знати особливостей iOS або підходів до написання коду (SOLID/DRY). Другі — зі страхом погано проявити себе у новій команді.
Hard skills
Помилка №1: Не додали модифікатор weak під час використання патерну делегування
Ця помилка — найпоширеніша на старті, але водночас і найлегша для виправлення. Розгляньмо приклад.

Під час рев’ю коду легко не помітити, що делегат в UserDetailsViewController оголошений без модифікатора weak. На перший погляд здається, що нічого страшного не відбувається — застосунок працює, екрани відкриваються. Але проблема ховається глибше.
Уявімо простий застосунок із двома екранами:
- Перший екран — список користувачів
- Другий екран — деталі конкретного користувача, де можна відредагувати його дані.
Користувач відкриває список, натискає на людину, переходить на екран деталей, потім повертається назад. І так багато разів — наприклад, адміністратор переглядає та редагує десятки користувачів за одну сесію.
В коді ж усе відбувається так:
Перший екран (UsersListViewController) створює другий екран (UserDetailsViewController) і зберігає на нього посилання. Це нормально — так система знає, який екран зараз відкритий.
Але в UserDetailsViewController є делегат, який вказує назад на UsersListViewController. І якщо цей делегат оголошений без weak, виходить така ситуація:
- UsersListViewController сильно тримає UserDetailsViewController
- UserDetailsViewController сильно тримає UsersListViewController
Вони наче тримаються один одного і не дозволяють системі видалити себе з пам’яті.
На практиці ж це означає ось що:
Коли користувач закриває екран деталей та повертається до списку, UserDetailsViewController не звільняється з пам’яті, хоча вже не потрібен. Це і є витік пам’яті.
Якщо користувач відкрив 10 різних профілів — у пам’яті залишаться 10 непотрібних об’єктів UserDetailsViewController. З часом таких об’єктів стає все більше, застосунок починає споживати забагато пам’яті — і в підсумку може просто впасти. В цей момент фонові процеси зупиняються, і частина даних може не встигнути синхронізуватися з сервером.
Саме тому делегати майже завжди потрібно оголошувати як weak: це дозволяє системі коректно звільняти пам’ять і уникати подібних проблем.
Помилка №2: Один Storyboard для всіх екранів застосунку
Використовувати storyboard з кількома екранами — це нормально, особливо в середніх та великих застосунках. Так ми зберігаємо пов’язані користувацькі сценарії в одному місці, і кодову базу простіше підтримувати.
Проблеми починаються тоді, коли в одному storyboard намагаються зберігати всі екрани застосунку одразу. Уявімо, що в storyboard уже є 2–3 складних екрани, і ви додаєте ще один. Що відбувається далі?
Кожного разу, коли ви відкриваєте storyboard, Xcode змушений прочитати його XML-код і зібрати інтерфейс для всіх екранів усередині файлу. І хоча Xcode інколи кешує відкриті раніше storyboard, цей кеш легко може очиститися.
В результаті чим більше екранів у storyboard, тим складніші в них UI-ієрархії — і тим довше Xcode відкриває файл. Ви просто сидите і чекаєте, поки інтерфейс прогрузиться і відмалюється. З часом робота зі storyboard перетворюється на біль.
При цьому Apple вже давно дала інструменти, які дозволяють уникати такої ситуації.
Як розв’язати проблему
- Виносьте складні UI-блоки в окремі UIView
Замість того щоби будувати великий екран із десятків вкладених елементів прямо в storyboard, краще створювати окремі компоненти, що наслідуються від UIView, та використовувати їх як готові блоки. Так екран у storyboard стає простішим, а підтримувати код — легше. Маленькі незалежні компоненти набагато зручніші за одну величезну і заплутану ієрархію.
- Розбивайте складний екран на кілька UIViewController
Якщо екран настільки складний, що простіше мислити не UIView, а цілими контролерами, його можна зібрати з кількох UIViewController. У такому випадку один контролер виступає контейнером, а інші — його дочірніми.
- Діліть один великий storyboard на кілька менших
Якщо користувацький сценарій містить 10–15 екранів (наприклад, довгий онбординг — що трапляється дуже часто), не варто тримати їх усі в одному storyboard. Хороша практика — мати окремі storyboards для екранів входу в застосунок (логін, реєстрація), для онбордингу і для основної частини застосунку.
Для переходів між такими storyboards в Xcode є спеціальний інструмент — Storyboard Reference. Він дозволяє з’єднувати різні storyboards між собою без хаосу та перевантажених файлів.
Помилка №3. Порушення принципів SOLID
Знати назви принципів SOLID — ще не означає розуміти, де і навіщо їх застосовувати. Саме тому на співбесідах розробників будь-якого рівня часто просять пояснити принципи SOLID своїми словами або виправити код, у якому ці принципи порушені.
Розберемо приклад і подивимось, у чому помилка та як правильно її виправити.

У чому проблема в коді?
В нас є клас UserDetailsViewController. У методі viewDidLoad() він:
- Налаштовує зовнішній вигляд екрана
- Задає header і footer для списку scrollableMenuView
- Додає підкомпоненти (addDefaultSubviews())
- Виставляє constraints (setupDefaultConstraints())
До цього моменту все виглядає нормально.
Але далі, після виклику super.viewDidLoad(), у цьому ж методі відбувається налаштування UINavigationController — тобто конфігурація навігації. Тут і з’являється проблема. Ми ніби припускаємо, що UserDetailsViewController завжди буде відкриватися через pushViewController(_:animated:). Отже, він точно знаходиться всередині UINavigationController, але це не гарантується.
Цей екран можуть показати:
- Через pushViewController — тоді navigationController існує
- Модально через present(_:animated:) — і тоді navigationController буде nil
У другому випадку код налаштування навігації або не зробить нічого, або працюватиме некоректно, або взагалі плодитиме баги.
Який принцип SOLID тут порушено?
Тут порушується D — Dependency Inversion Principle. Він передбачає, що модулі верхнього рівня не мають залежати від деталей реалізації модулів нижчого рівня.
В нашому ж випадку:
UserDetailsViewController знає занадто багато про те, як саме він буде показаний, і він напряму працює з navigationController, хоча не відповідає за навігацію.
Навігація — це інша відповідальність і вищий рівень абстракції, ніж логіка конкретного екрана. UserDetailsViewController має займатися тільки своїм UI та логікою екрана.
Тому код, який конфігурує navigationController, потрібно повністю винести з viewDidLoad() і розмістити там, де відбувається навігація.
Soft skills
Помилка №1: Прагнення зробити ідеально замість зробити вчасно
На старті кар’єри легко потрапити в пастку перфекціонізму. Хочеться писати лише правильний код, одразу з гарною архітектурою, без жодного сумнівного рішення. Це природне бажання, але воно часто грає проти початківців.
До прикладу, задача вже може працювати й виконувати бізнес-вимоги, але замість того, щоби показати результат команді або відправити на рев’ю, новачки можуть ще трохи «покращити» роботу. Далі ж починається дрібний рефакторинг, зміни архітектури та оптимізація того, що поки не є проблемою.
Де тут проблема і що важливо зрозуміти
Поки рішення доводиться до ідеалу, дедлайн підходить усе ближче, після правок з’являються нові баги, а команді складно трекати реальний статус задачі. Тому важливо розуміти, що в командній розробці «правильно» не завжди означає «ідеально». Часто пріоритети виглядають так:
- Функціонал працює
- Рішення доставлено вчасно
- Код достатньо зрозумілий для підтримки
Помилка №2: Страх проявляти ініціативу
Можна писати якісний код, але коли справа доходить до комунікації, мотивації та ініціативності, багато початківців губляться. Особливо це помітно на перших місяцях роботи в команді.
У нових командах новачкам зазвичай допомагають адаптуватися: пояснюють процеси, дають прості задачі, перевіряють результат і поступово зменшують рівень контролю. В якийсь момент це означає, що від вас очікують самостійності.
Втім, далі зʼявляється поширена помилка — сприймати задачу занадто вузько:
- «Мені дали таску — я її просто реалізую».
В реальній же розробці цього часто недостатньо. Наприклад, вам потрібно реалізувати новий екран налаштувань, де користувач може змінювати особисті дані: ім’я, прізвище, вік, email.
І тут може виникнути купа питань:
- Дизайн не дуже зрозумілий
- Які поля обов’язкові, а які — опціональні
- Немає згадки про аналітику змін
- Незрозуміло, як ці дані використовуються далі
Якщо мовчки реалізувати те, що є в описі, і нічого більше, команда може отримати екран, який формально працює, але не розв’язує бізнес-задачу.
Тому напрошується висновок, що ініціатива — це не «робити більше, ніж просили». Це вміння побачити, чого бракує, і поставити правильні запитання. Зрештою, відсутність ініціативи виглядає гірше, ніж помилки.