20. Apr 2023
iOSNáš iOS toolbox - Spracovanie sieťových požiadaviek vo Swifte
Hoci Swift poskytuje vstavané funkcie na prácu so sieťou, ich použitie prináša niektoré nevýhody, ako napríklad nedostatočnú štandardizáciu, obmedzenú flexibilitu a problémy s údržbou a aktualizáciou kódu v čase, najmä pri narastajúcom počte endpointov. Existuje teda efektívnejší spôsob, ako riešiť tento problem?
Máme pre teba skvelú správu! S našim Swift package s názvom GoodNetworking sa môžeš pohodlnejšie vysporiadať so sieťovými požiadavkami. Poďme si ukázať, ako na to.
Príprava API & Endpointov
V tomto príklade si ukážeme, ako môžeme pomocou bezplatného rozhrania Star Wars API získať informácie o postavách zo Star Wars.
Na začiatku potrebujeme definovať base URL pre ApiServer
, typu String
. Ďalej potrebujeme definovať endpoint, ktorý zodpoveda protokolu GREndpointManager
.
Tento endpoint nám určí path, method, parametre, headers, encoding a URL pre sieťovú požiadavku.
V rámci aplikácie môžeme definovať viacero endpointov pre rôzne sieťové požiadavky.
import GoodNetworking
import Combine
import Alamofire
// define the base url of the api server
enum ApiServer: String {
case base = "<https://swapi.dev/api/>"
}
// define Endpoint for fetching the StarWars heroes
// later on you can add edpoints for StarWars Planets or Starships
enum Endpoint: GREndpointManager {
case hero(id: Int)
var path: String {
switch self {
case .hero(let id):
return "people/\\(id)"
}
}
var method: HTTPMethod { .get }
var parameters: EndpointParameters? { nil }
var headers: HTTPHeaders? {nil}
var encoding: ParameterEncoding { JSONEncoding.default }
func asURL(baseURL: String) throws -> URL {
var url = try baseURL.asURL()
url.appendPathComponent(path)
return url
}
}
Príprava API response
Ďalej musíme špecifikovať očakávanú odpoveď z API. Podľa StarWars API očakávame odpoveď s atribútom name
typu String
. Štruktúru s týmto atribútom môžeme definovať takto:
// define the request response
struct HeroResponse: Decodable {
let name: String
}
Teraz máme takmer všetko pripravené, môžeme nastaviť našu GRSession na zadávanie požiadaviek.
Zadanie sieťovej požiadavky
Keď máme zadefinovaný endpoint, môžeme vytvoriť inštanciu GRSession
.
GRSession
je založená na Alamofire Session
triede a umožňuje spravovať sieťové požiadavky v aplikáciách pomocou vlastného URLSession.
Pre správne fungovanie vyžaduje dva generické parametre:
- jeden, zodpovedajuci protokolu
GREndpointManager
- Endpoint, ktorý sme predtým definovali - druhy, zodpovedajuci protokolu
RawRepresentable
sRawValue
typuString
- náš ApiServer.
Tu je ukážka, ako môžeme využiť triedu GRSession
na vytvorenie sieťovej požiadavky:
// Create a GRSession object
let session: GRSession<Endpoint, ApiServer> = GRSession(
baseURL: ApiServer.base
configuration: .default
)
// fetch a hero with specified ID
func fetchHero(heroId: Int) -> AnyPublisher<HeroResponse, Never> {
return session.request(endpoint: .hero(id: heroId))
.goodify()
.replaceError(with: HeroResponse(name: "unknown"))
.eraseToAnyPublisher()
}
Funkcia fetchHero() vracia publisher, ktorý môžeme ďalej reťaziť pomocou funkcií z Combine frameworku.
Ak chceme zobraziť meno postavy zo StarWars, môžeme jednoducho zavolať túto funkciu a použiť metódy sink
alebo assign
z Combine.
// define heroLabel to show hero Name
let heroLabel = UILbel()
// define subscriber
var cancellable: AnyCancellable?
// subcribe to result of network request
cancellable = fetchHero(heroId: Int.random(1...66))
.map { response in response.name }
.removeDuplicates()
.assing(to: \\.text, on: heroLabel, ownership: .weak)
Gratulujem!
Po úspešnom vytvorení sieťovej požiadavky pomocou balíka GoodNetworking sa možno zaujímaš o to, ako presne funguje v rámci aplikácie.
Našťastie, balík obsahuje ukážkový kód, ktorý môžeš preskúmať a lepšie porozumieť jeho funkciám.
Ak bol pre teba tento balík užitočný, určite sa pozri aj na naše ďalšie balíky. Kto vie, možno nájdeš ďalší, ktorý ti pomôže posunúť tvoju appku na vyššiu úroveň!