Cum se creează punți între cadre într-o aplicație iOS

Dacă codul aplicației dvs. arată așa ...

"Vreau să export acea parte a aplicației mele, dar este legată de restul aplicației ca o placă de spaghete!"

Încercați să exportați o mică parte a aplicației, care este prea dependentă

Când începeam să modularizez o parte a aplicației la care lucram, am intrat într-un perete.

Am vrut să export un serviciu (de fapt, a fost serviciul de urmărire) într-un cadru separat. Problema era că acest serviciu era prea greu legat de aplicație. Se folosea un alt serviciu care folosea el însuși un alt ancorat profund în aplicație.

Pentru a exporta serviciul de urmărire, ar fi trebuit să refactorizez și să refațez întregul set de servicii în noul cadru!

Cert este însă că nu am avut timp să fac asta și testarea de regresie ar fi fost un coșmar și din multe alte motive pe care le-ați putea avea în orice companie (proces, buget, termen limită).
Așa că a trebuit să aflu cum pot exporta această parte a aplicației mele fără să refactorizez totul.

Să începem cu un exemplu concret!

Iată-ne, cel mai bun mod de a învăța și de a înțelege cum funcționează lucrurile este să practici! (Voi furniza repoziția Github pentru acest exemplu la sfârșitul acestui post)
Așadar, permiteți-mi să stabilesc contextul, avem o aplicație mică cu doar 2 ecrane:

  • Un ecran de pornire
  • Un ecran de plată (vrem să exportăm ecranul într-un cadru)

Pagina de plată conține un TextField pentru a introduce un număr de card și un buton de plată. Când apăsați butonul, plata ar trebui să fie lansată.
Dar ! Provocarea rezidă în metoda de plată. Să presupunem că nu putem exporta serviciul de plată din anumite motive pe care le-am evocat un pic mai devreme.

Ecran de pornire și Ecran de plată

Avem deci aceste două ecrane, declarate în două ținte diferite. Ecranul de pornire este declarat în ținta principală a aplicației, iar ecranul de plată este declarat într-un alt modul numit PaymentModule. De asemenea, avem un serviciu de plată declarat în ținta principală a aplicației, după cum urmează:

Metoda de plată este metoda pe care nu o putem extrage din aplicație, deoarece este prea dependentă. Vrem însă să-l folosim din modulul de plată.

Avem un ControlViewController definit în modulul de plată, dacă încercăm să apelăm la Serviciul de plată vom avea o eroare, deoarece acest serviciu nu se află în modul. Nu puteți importa ținta principală într-un modul (care ar fi un nonsens)

Deci, cum vom folosi această metodă din PaymentViewController?

Definiți un protocol în modul

Acesta va fi podul nostru. Trebuie să definiți un protocol în modul cu o metodă care descrie ce doriți să utilizați în ținta principală a aplicației.

Deci, să definim un protocol numit PaymentServiceProtocol cu ​​o metodă de plată:

Implementarea protocolului în aplicație

Acum trebuie să-i spunem serviciului nostru de plată să se conformeze acestui protocol. Trebuie doar să adăugăm acest lucru:

"De ce metoda declarată în protocol nu este implementată în această extensie?"

Aveți dreptate, atunci când vă conformați unui protocol, trebuie să implementați proprietățile și metodele acestuia. Trucul aici este că numele metodei din protocol este exact același cu numele metodei din Serviciul de plată pe care l-am declarat puțin mai devreme. În acest fel, sistemul va ști că va trebui să utilizeze metoda plătită declarată în clasa PaymentService atunci când accesați metoda protocolului.

Legarea celor două părți

Acum trebuie să unim cele două părți.
Din HomeViewController, atunci când atingem butonul „Accesați pagina de plată”, inițiem un PaymentViewController. În acel moment, o să-i transmitem o referință la clasa PaymentService, dar controlorul de plată din modul îl va vedea ca un tip PaymentServiceProtocol.

Iată trucul:

Trecem PaymentService.self și codul din modul vede un tip de PaymentServiceProtocol.Tip.
Acum putem folosi metoda de plată definită în aplicație din modul!

Folosind podul

Acum este foarte ușor să folosiți podul creat de noi:

Metoda didTapPayButton este apelată ori de câte ori apăsați pe butonul Pay (sună corect, nu?). Verificați la linia 23: apelăm la metoda de plată pe referința de protocol pe care am primit-o din aplicație.

Deoarece PaymentService este conform cu acest protocol, sistemul va executa codul în cadrul metodei de plată, care este definit în PaymentService.swift.

Cu alte cuvinte, folosim metoda la care nu am putut apela de la modul la început! Podul este acum setat.

Iată cum arată când apăsați pe butonul de plată.

Folosind metoda de plată conținută în ținta principală, din modulul de plată

Concluzie

În concluzie, această metodă de conectare poate fi utilizată dacă doriți să exportați o componentă a aplicației într-un cadru.

Această tehnică vă va permite să tăiați tăița din vas, dacă sunteți forțați să exportați acea parte a aplicației într-un cadru, dar nu puteți exporta totul, din orice motiv pe care l-ați putea avea.

Cred că aceasta este o soluție temporară, înainte de a ieși întreaga componentă din cadru, când vei avea timp, de exemplu. (În acest scenariu, într-o zi va trebui să exportați metoda de plată în modulul de plată)

Recunosc că într-o lume ideală, cu unicorni și lucruri fanteziste, nu am face așa ceva. Mai degrabă am exporta întreaga componentă, dar așa cum am spus de multe ori, acest lucru nu este întotdeauna posibil.

Puteți găsi repoziția Github a acestui proiect aici, nu ezitați să verificați cum se face podul și să încercați singur.
Sper că această postare vă poate ajuta, nu ezitați să puneți orice întrebare pe care o aveți în minte!

Această poveste este publicată în „Startup”, cea mai mare publicație de antreprenoriat mediu, urmată de +442.678 de persoane.

Abonați-vă pentru a primi poveștile noastre de top aici.