Как да създадете мостове между рамки в iOS приложение

Ако кодът на приложението ви изглежда така ...

„Искам да експортирам тази част от приложението си, но тя е обвързана с останалото приложение като чиния за спагети!“

Опитвате се да експортирате малка част от приложението, която е твърде зависима

Когато започвах да модулирам част от приложението, върху което работех, се натъкнах на стена.

Исках да експортирам услуга (всъщност това беше услугата Проследяване) в отделна рамка. Проблемът беше, че тази услуга е твърде трудно обвързана с приложението. Използваше друга услуга, която сама използваше друга дълбоко закотвена в приложението.

За да експортирам услугата за проследяване, ще трябва да префабрикувам и преработя целия набор от услуги в новата рамка!

Но факт е, че не съм имал време да направя това и регресионното тестване би било кошмар и поради много други причини, които бихте могли да имате във всяка компания (процес, бюджет, краен срок).
Затова трябваше да разбера как да експортирам тази част от приложението си, без да рефакторирам всичко.

Да започнем с конкретен пример!

Ето ни, най-добрият начин да се научим и да разберем как работят нещата, е да практикуваме! (Ще дам репо за Github за този пример в края на този пост)
Така че нека да настроя контекста, имаме малко приложение със само 2 екрана:

  • Начален екран
  • Екран за плащане (искаме да експортираме този екран в рамка)

Страницата за плащане съдържа TextField за въвеждане на номер на карта и бутон Pay. Когато натиснете бутона, плащането трябва да започне.
Но ! Предизвикателството е в начина на плащане. Да предположим, че просто не можем да експортираме платежната услуга по някакви причини, които съм предизвикал малко по-рано.

Начален екран и екран за плащане

Така че имаме тези два екрана, декларирани в две различни цели. Началният екран се декларира в основната цел на приложението, а екранът за плащане се декларира в друг модул, наречен PaymentModule. Имаме също PayService, декларирана в основната цел на приложение, както следва:

Методът на заплащане е методът, който не можем да извлечем от приложението, защото е твърде зависим. Но искаме да го използваме от модула за плащане.

Ние имаме PaymentViewController, дефиниран в модула за плащане, ако се опитаме да се обадим на PaymentService, ще имаме грешка, тъй като тази услуга не е в модула. Не можете да импортирате основната цел в модул (това би било глупост)

И така, как ще използваме този метод от PaymentViewController?

Определете протокол в модула

Това ще бъде нашият мост. Трябва да дефинирате протокол в модула с метод, описващ какво искате да използвате в основната цел на приложението.

Така че нека да определим протокол на име PaymentServiceProtocol с метод pay:

Изпълнение на протокола в приложението

Сега трябва да кажем на нашата PaymentService да се съобрази с този протокол. Просто трябва да добавим това:

„Защо методът, деклариран в протокола, не е реализиран в това разширение?“

Прав сте, когато отговаряте на протокол, трябва да внедрите неговите свойства и методи. Номерът тук е, че името на метода в протокола е точно същото като името на метода в PaymentService, което декларирахме малко по-рано. По този начин системата ще знае, че ще трябва да използва метода заплащане, деклариран в класа PaymentService, когато има достъп до метода на протокола.

Свързване на двете части

Сега трябва да съединим двете части заедно.
От HomeViewController, когато докоснем бутона „Отиди на страницата за плащане“, създаваме инстанция на PaymentViewController. Тогава ще го препратим към клас PaymentService, но платежният контролер в модула ще го разглежда като тип PaymentServiceProtocol.

Ето какъв е трикът:

Предаваме PaymentService.self и кодът в модула вижда PayServiceProtocol.Type.
Вече можем да използваме метода за повикване на повикване, определен в приложението от модула!

Използване на моста

Вече е много лесно да използвате моста, който създадохме:

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

Тъй като PaymentService отговаря на този протокол, системата ще изпълни кода вътре в метода pay, който е определен в PaymentService.swift.

С други думи, ние използваме метода, който не можахме да извикаме от модула в началото! Мостът вече е поставен.

Ето как изглежда, когато докоснете бутона за заплащане.

Използване на метода на заплащане, съдържащ се в основната цел, от модула за плащане

заключение

В заключение, този метод за свързване може да се използва, ако искате да експортирате компонент от приложението си в рамка.

Тази техника ще ви позволи да изрежете юфката от купата, ако сте принудени да експортирате тази част от приложението си в рамка, но не можете да експортирате цялото нещо по каквато и да е причина.

Мисля, че това е временно решение, преди да излезете целия компонент в рамките, когато ще имате време например. (В този сценарий някой ден ще трябва да експортирате начина на плащане в модула за плащане)

Признавам, че в идеален свят, с еднорози и причудливи неща, не бихме направили нещо подобно. Предпочитаме да експортираме целия компонент, но както казах много пъти, това не винаги е възможно.

Можете да намерите репото на Github на този проект тук, не се колебайте да проверите как е направен мостът и да го опитате сами.
Надявам се този пост да помогне, не се колебайте да зададете всеки въпрос, който имате предвид!

Тази история е публикувана в най-голямото предприемаческо издание The Startup, последвано от +442 678 души.

Абонирайте се, за да получавате нашите топ истории тук.