Як створити мости між рамками в додатку для iOS

Якщо код вашої програми виглядає приблизно так ...

"Я хочу експортувати ту частину свого додатка, але вона прив'язана до решти програми, як тарілка для спагетті!"

Спроби експортувати невелику частину програми, яка занадто залежна

Коли я починав модулювати частину програми, над якою працював, я наткнувся на стіну.

Я хотів експортувати послугу (насправді це була послуга відстеження) в окрему рамку. Проблема полягала в тому, що ця послуга була надто важко пов'язана з додатком. Він використовував інший сервіс, який сам використовував інший, глибоко закріплений у додатку.

Для того, щоб експортувати послугу відстеження, мені довелося б переробити і переробити весь набір послуг у нових рамках!

Але справа в тому, що я не мав часу це робити, і тест регресії був би кошмаром, і з багатьох інших причин, які ви могли мати у будь-якій компанії (процес, бюджет, термін).
Тож мені довелося з’ясувати, як експортувати цю частину свого додатка, не рефактуючи все.

Почнемо з конкретного прикладу!

Ось ми, найкращий спосіб вчитися і розуміти, як все працює - це практикувати! (Я збираюся надати репортаж Github для цього прикладу в кінці цієї публікації)
Тож дозвольте мені встановити контекст, у нас є невеликий додаток із лише 2 екранами:

  • Домашній екран
  • Екран платежів (ми хочемо експортувати цей екран у рамки)

Сторінка платежу містить TextField для введення номера картки та кнопку Pay. При натисканні на кнопку оплату слід запустити.
Але! Проблема полягає в способі оплати. Припустимо, ми просто не можемо експортувати платіжну послугу з якихось причин, які я викликав трохи раніше.

Домашній екран і екран оплати

Отже, у нас є ці два екрани, оголошені у двох різних цілях. Головний екран оголошується в головній цілі програми, а екран оплати оголошується в іншому модулі під назвою PaymentModule. Також у нас є основний платіжний сервіс, задекларований у головній цілі програми:

Метод оплати - це метод, який ми не можемо отримати з програми, оскільки він занадто залежний. Але ми хочемо використовувати його з платіжного модуля.

У нас є модуль PaymentViewController, визначений в модулі платежу, якщо ми спробуємо викликати PaymentService, ми будемо мати помилку, оскільки ця послуга відсутня в модулі. Ви не можете імпортувати головну ціль у модулі (це була б дурниця)

Тож як ми будемо використовувати цей метод від PaymentViewController?

Визначте протокол у модулі

Це буде наш міст. Ви повинні визначити протокол у модулі методом, який описує те, що ви хочете використовувати в головній цілі програми.

Тож давайте визначимо протокол з назвою PaymentServiceProtocol методом оплати:

Реалізація протоколу в додатку

Тепер ми повинні сказати нашій службі платежів, щоб відповідати цьому протоколу. Нам просто потрібно додати це:

"Чому метод, оголошений у протоколі, не реалізований у цьому розширенні?"

Ви маєте рацію, відповідаючи протоколу, ви повинні реалізувати його властивості та методи. Підступність тут полягає в тому, що ім'я методу в протоколі точно таке ж, як ім'я методу в PaymentService, про який ми заявили трохи раніше. Таким чином система знатиме, що їй доведеться використовувати метод оплати, оголошений у класі PaymentService, під час доступу до методу протоколу.

З’єднання двох частин

Тепер ми повинні з'єднати дві частини разом.
Коли ви натискаєте кнопку «Перейти на сторінку платежів», ми натискаємо кнопку «HomeViewController», яка створює миттєвий спосіб PaymentViewController. У той час ми передамо йому посилання на клас PaymentService, але контролер платежу в модулі буде сприймати його як тип PaymentServiceProtocol.

Ось хитрість:

Ми передаємо PaymentService.self і код у модулі бачить тип PaymentServiceProtocol.Type.
Тепер ми можемо використовувати метод оплати дзвінків, визначений у додатку, з модуля!

Використання мосту

Зараз дуже просто використовувати міст, який ми створили:

Метод didTapPayButton викликається кожен раз, коли ви натискаєте кнопку Pay (звучить правильно, правда?). Перевірте у рядку 23: ми називаємо спосіб оплати за посиланням на протокол, який ми отримали від програми.

Оскільки PaymentService відповідає цьому протоколу, система виконає код всередині методу pay, який визначений у PaymentService.swift.

Іншими словами, ми використовуємо метод, який ми не могли викликати з модуля на початку! Зараз встановлений міст.

Ось як це виглядає, коли натискаєте кнопку оплати.

Використовуючи спосіб оплати, що міститься в основній цілі, з платіжного модуля

Висновок

На закінчення, цей метод з'єднання може бути використаний, якщо ви хочете експортувати компонент свого додатка в рамки.

Ця методика дозволить вам вирізати локшину з чаші, якщо ви змушені експортувати цю частину програми в рамки, але не можете експортувати все це з будь-якої причини.

Я думаю, що це тимчасове рішення, перш ніж виходити з цілого компонента в рамки, коли у вас буде час, наприклад. (У цьому сценарії колись вам доведеться експортувати спосіб оплати всередині модуля платежу)

Я визнаю, що в ідеальному світі, з єдинорогами та вигадливими штуками, ми б не робили щось подібне. Ми швидше експортуємо весь компонент, але, як я вже говорив багато разів, це не завжди можливо.

Ви можете знайти репортаж Github цього проекту тут, не соромтеся перевірити, як виконаний міст і спробувати його самостійно.
Я сподіваюся, що цей пост може допомогти, не соромтесь задавати будь-яке питання, яке ви маєте на увазі!

Ця історія опублікована в найбільшій підприємницькій публікації "Середній бізнес", де перебувають +442 678 осіб.

Підпишіться, щоб отримувати наші основні історії тут.