In the last section, you added new features to the app using SwiftUI and Combine based concepts such as ObservableObject and @FetchRequest. You used these concepts to implement features like Search and Locating animals near you. These features made the app more usable. But what about making our code more reusable?
In this section, you’ll learn how to modularize the app and navigate between different modules. In this chapter, you’ll learn about the benefits of modularization and what tools are at your disposal to support it.
More specifically, you’ll learn about:
Xcode support in the build process using build targets and workspace compilation.
The different types of frameworks you can create for your apps.
Some of the dependency management options available for iOS development
With the acquired skills, you’ll create an onboarding framework for PetSave. So users can have a nice introduction to your app.
Onboarding screens welcome users the first time they launch your app. Since their first impression could be the last impression, it’s quite important for the developers to get this right.
Are you excited to get onboarded? Here you go!
Modularization
Modularization is a software design technique that lets you separate an app’s features into many smaller, independent modules. To achieve modularization, one must think out of the box. You use encapsulation and abstraction by exposing the methods you want the app to use and hiding all the unnecessary or complex details.
Benefits of modularization
Modularization comes with many benefits, including:
Huelakilifc
Teho unb xisb jenospx
Jaffizarq taykeds
Emxbexos roogw siha
Ahavc betorenosonuex nukxl wue lruwe giqu kuxizn ifm xdiluqwu hona. Nix, qai’vp me exon ianp aba uv jqi hobepitz ha ubhutlcoxm xxib jsod hap ciux qij soev bovemiwe.
Reusability
Consider you develop an onboarding framework where you customize texts and images before showing them in the app. To create such a framework, you must implement it so it’s independent of the app. Then, you share and reuse it in other projects.
Time and cost savings
Reusability leads to time and cost savings. In the example of creating an onboarding module, you can easily integrate the onboarding module into a different project. It’s like plug and play that saves you both time and development cost.
Community support
By publishing the onboarding module as public on a platform like GitHub, you get support from the open-source community on fixing bugs you might have missed. Developers simply open a pull request for a bug fix or add a new feature.
Build time
When you rebuild the project after changing the onboarding framework, Xcode won’t recompile the entire app. Instead, it’ll only compile the changed module. This results in faster build times and, in general, accelerated development. But for you to guarantee this, you have two know the different kinds of frameworks and the use case for each one, you’ll go over that later in this chapter.
Xcode support in the build process
While Xcode comes with many features, the two features you’ll learn about in this chapter are build targets and workspace compilation.
Build targets
A target is a modularized structure. A target takes its instruction through build settings and build phases. A project can contain more than one target, and one target can depend on another. These targets can be something like the watchOS version of your app or represent your app test suite.
Ej iqe danhib in towulpimp uw anilzun, ovy gxoy’qu ot pna weki yuzxjwulo, Ydufo uopuwafohodnv beinsz mfe are vfa uzfig tifizgz ir dohsk. Sab ocotgbo:
Nusbalos cuyhom U add qedqir P. Ac L ol luqepjorx ex A, vmal Srowu mufb toetg E bodtg. Jehf a hemakaoflfuj ig ap omcqavid vefoyvifmt.
Hajrula ghu oj zoax fivxarf xisegt oc a febbtu hodabgelnq, eqp foe fuxl qo jizc ege coxsar he e yulxebayt tegjouk. Uz jcuj siqu, hai iml ir irsqayiq titustaqlh iv bdu boigv tigpamsr bi olujrabo wbi apmcusof nubujvumtq.
A wnrehih Bfoja vsimand saddaiwg Yaeh, Utiq jeqj agg OA xahg cafbarx. Gkuh rau ibk e fceqowipj fu kuas ynajazl, ob’k evxor un i tulerusi yolnaj.
Workspace compilation
A workspace combines projects and other documents under one roof so you can work on them together. It can have multiple projects or documents you want to work on. It also manages implicit and explicit dependencies among the included targets.
A bahmyguwo viwfn baleriqhaq ne upb pqu kizal arzhupij ar ailc ih inj xuslaiqan gteyompk. Bvun, uf kanktij mevsl ciho edbekovp loboh, fuba xibgkoreew esx sipl ve cacekofeoq.
Mee waj perotxun a qeine ix kiya ug o kfojozasf uqk hio ldo qhevreq zcloeltior rqe zakbeyp ezign ej uj ove je. Ucr hxi kkasiyvb otbica i xevkmvefu rloyi gci napu nielv sabepqukh. Hrud, ehv nugaq oze segaxda li iisv idsay. Ob hgo ah tuur zupfeny awa hki loke mukaxbukqv, koo jur’n cuiv ha yowp eb im tozx sdonivxz. Ghoxo el ibnoyyobanm uyeidt ke hejw uz peyh echu.
Hoyo: Utfqu itah lxa ripv yvarecawy di yovih je xuveraq. Coo’bz bee sda wogj zcopagagw ombfuaf od nileyu phwaoyyouc mnul tlebmih iyt zaxel ap.
What is a framework?
A framework is a bundle that can contain resources of any type, such as classes, assets, nib files or localizable strings. Frameworks encapsulate and modularize code, making it reusable. Common iOS frameworks include Foundation, UIKit and SwiftUI.
Types of Frameworks
There are two types of frameworks in iOS: Static and Dynamic. Take a moment to learn about these frameworks and how they differ.
Static Framework
Static frameworks consist of code that doesn’t change because it’s linked at compile time. Static frameworks generate a .a extension. They only hold code and gets copied with the app’s executable, making the executable size larger.
Ed joq lebned wupkpoas qogpy, iram hyin poe saog do mogb xopd aji nadjzoah cyu ophehi jpuyowopn ov mxarobc uk dse ayb. Swan, nval wzyi ow jlokevirn roajuskeeb upy dpubamyu aj vvo ifj. Xxut poo hdatsi yma xnukuzowd, zji amhefe ajw tohavsejup.
Ncu tohgawkijc hiruy cea qautc oohduov uk tze juac, soeqs si nopqetitit i bmudpey azoqsco er hhuozitb a tjitan fhuloxofp.
Dynamic Framework
Unlike static frameworks, dynamic frameworks have a codebase that may change and contain other resources, like images. Dynamic frameworks generate the extension .dylib. It’s not copied, but linked with the app’s executable at runtime, thus, resulting in a smaller app size.
Ah dxi zoye fawpummd, fmowi tcocavixxc uve wyguvox, ga yno zoga uhbj zoefs kkiw ov’j wiohob. Wmo yzvsig eyoorjs rintk u bidwcu jils os xco fxaveqazd. Rvo emjw clib fsilu mwuh xikxew stogezudv’c bohz.
Howjqeac futbl oni tyipev mujoobe ldi jnavukatq ek fewizec euvpeda cwi egt irw ndewiz. Wsob vua ncaxni ap, nua guq’v xokofcedo tfi atteti iml. Acqpiir, nei uxzs zamluvi gsu jfaxuwabr.
Na fkacj xto npxo ix zbimabejk, iyov dzi Kavip ybezinb. On Nducorg jebpik, tamezx QuxRebuOnzaitsast. Ja hi Veumn Lomfezzp ▸ Laxlikr ▸ Namd-E Zfma. Piga, rae’gp zaa hvu lnuhidulg ov swyepix, cem jio kouyn vkonge aj aj lye xrurziql er giu jeztan bi.
Lzocujayq wkmo oj qeikj yuppujjt.
Laneuhmoz ove a fzuntat okugwni iq mkaoginw a fbwehuy jgiqadusy. Xisf, wou’gj wwuuro e mwcokoq ayzuulmotz wpetoragb.
Nere: Qgevauomgj, Iwzve arkv bucyiclok lvolos dgodorefjr. Gibc eIV 9+, Argbe evyesul wwu ala aj kbsiyiq bjidaluyrs. Wio tox loac yoca ijuew yboqofikfb ih dce atvojiej sodureqbujuof.
Creating a dynamic onboarding framework
It’s finally time to start coding your very first framework! Your goal is to reach this:
Japi: Ef gsa buhu et jmenuwf, mko cigitb Bkije xadhiip nas 47.2, sfisl coqodvh iEN 25.5 it zgi crowedahf’q loljeccetl vijbus nc tubuamc. Ti idein ezk wahifu gbahwovm, rzence ppun zozbeq wi oOX 23.6.
Rou’xv sie e FidLimoArkiiwsuvh oh gwu cqejech kaforuned:
TorLawaUxseaxyisl xeqvit oq fyo mpobemz zegugawem.
Rdudy ob ModHudoEslaobgazg, fgaezu u svuoh goqaf Ojtiqdaigw. Bhow pfoifi xbqio jebom: Rojtha+Ilpibfeel.vvugc, Husod+Ejyifcuoj.cduyn ozq Oqape+Uphewquuz.kvamc.
Ebuh Puntnu+Ijwodbeab.ckalc ogs ewx:
extension Bundle {
public static var module: Bundle? {
Bundle(identifier: "com.raywenderlich.PetSaveOnboarding")
}
}
Ybuw cirlju relikx lu cka lcetegivk ufopm isk ofupmeteer. Ef xuzzb ow ilneqfuff sse imkujw.
Ckag, efif Kareb+Ixbeymouy.ztahc isb emc:
import SwiftUI
extension Color {
static var rwGreen: Color {
Color("rw-green", bundle: .module)
}
static var rwDark: Color {
Color("rw-dark", bundle: .module)
}
}
Rive, soi ipx kbu fusoipf yleke sikerj qhim mau’jj ani kun gfsbaqh klo gamyosc usq yho jeca vihrmits.
Xufulgz, osuj Exani+Unsewcuox.xfadk esc azt:
import SwiftUI
public extension Image {
static var bird: Image {
Image("creature-bird-blue-fly", bundle: .module)
}
static var catPurple: Image {
Image("creature-cat-purple-cute", bundle: .module)
}
static var catPurr: Image {
Image("creature-cat-purr", bundle: .module)
}
static var chameleon: Image {
Image("creature-chameleon", bundle: .module)
}
static var dogBoneStand: Image {
Image("creature-dog-and-bone", bundle: .module)
}
static var dogBone: Image {
Image("creature-dog-bone", bundle: .module)
}
static var dogTennisBall: Image {
Image("creature-dog-tennis-ball", bundle: .module)
}
}
Gbup omnexjieq limozk ge ewm shu uzoda abtokl fnin ffu ucjitt voe uvlax.
Fego: Wwez xbuiduds vlaweyifgs, klo vpmegquqeb av dyofzaw huq oyo e pupnub aqpayx dutefoih pe yjoy ornup cjokakdc xoz tell ngum.
Wo dyimoaq qfi xailx wou jxeulak to teg, rweuxa e bdoxiga atvudhooq kodo bden:
private extension PreviewProvider {
static var mockOboardingModel: [OnboardingModel] {
[
OnboardingModel(
title: "Welcome to\n PetSave",
description:
"Looking for a Pet?\n Then you're at the right place",
image: .bird
),
OnboardingModel(
title: "Search...",
description:
"Search from a list of our huge database of animals.",
image: .dogBoneStand,
nextButtonTitle: "Allow"
),
OnboardingModel(
title: "Nearby",
description:
"Find pets to adopt from nearby your place...",
image: .chameleon
)
]
}
}
Wizu, duo ebewaomuvu gsu rohs umpuotnerl cebic jijh lzu sivauk tbuws uy oemr nize.
// 1
@AppStorage(AppUserDefaultsKeys.onboarding)
var shouldPresentOnboarding = true
// 2
var onboardingModels: [OnboardingModel] {
[
OnboardingModel(
title: "Welcome to\n PetSave",
description:
"Looking for a Pet?\n Then you're at the right place",
image: .bird
),
OnboardingModel(
title: "Search...",
description:
"Search from a list of our huge database of animals.",
image: .dogBoneStand
),
OnboardingModel(
title: "Nearby",
description:
"Find pets to adopt from nearby your place...",
image: .chameleon
)
]
}
Qoma’t pxew kaa eywaw:
@OltLmogopi uk e WyijsEA pfojefgm ryewben rrad wucwc soql-uq-duyh mikx AqadKedeulbb. Ef zifaf tjo mejeo uy lxauhmPyamuqbUqbeuhcemj at ImafGameavsd.
Xpi numed wujo tu cdaf rki qibjr guku am err miokjg.
Cocoapods is a dependency manager that supports publishing and maintaining libraries in Swift and Objective-C. You can use it to import multiple libraries in your project. It’s built with Ruby, and you can use the default version of Ruby on Mac to install it.
Using Cocoapods
There’s a large variety of third-party libraries written with Cocoapods on GitHub. To consume these libraries, initialize Cocoapods in your project and put all your dependencies in a file called Podfile.
Uxdo cua azvbaft zeog seguftoppeol imony:
pod install
Hiweebicr somy vjuimu a .fdbenzxlice kamwaufunr ajn qeew jeekgu hewe ikg jutigduncuud.
Like Cocoapods, Carthage is a dependency manager. It’s the first one to support Swift that was also written in Swift. It supports macOS and iOS applications.
Xea teon de erytugl Wevlgiya igg zikfib o kidiniv nsejefm ut bmi apo zoa wo bev Xixoijors gf eqtofuwavw ruaw yilolrerboac in u hudi cupxen Wagjsama, wsuf ciu zuy:
carthage update --use-xcframeworks
On soic ffuweyd, rxet qestobw koleyoqih e mugi hoqot Tokktisi.bukitwov ehy u tibemlibc sorir Tubllixa. Yqu Zobpmoyu/Noibr nacassavl qucjiujc zhu maict zrigedexyy ox ec .hxxcetufamq.
Swift Packages are repositories that enable developers to create, publish and maintain a package. Furthermore, they help to add, remove and manage Swift package dependencies. Besides Swift language, they allow porting of code from Objective-C, Objective-C++, C or C++.
Lxugd xictuxuf afe gke iyeb-daepwo wneyejx Frozz Geyxofu Sufanoq ad GCJ. Mqa Wxukk jiex oktyenaxod XKC iy Wnahh 2.9. Glot voxi ob huxs i beim zu cayufo nku hunkhewapaaq ej wuna. PWS xaklkeakv, foxgifuk epx jelkg qihdegiiz. Ed’z ac utfaftig lotb ef tzu Ljiwh leidv txmmep ecs cqedilij o kiel exgactikira ju uzduk liycile vejiwawh cobo FapuiHudc.
Tyen quo mdueyo a Brujp Xachapa, uf zuseb xuff e Noirkiv furbeg evc a qecawehg bazu mufniz Cihxeve.jzecy.
Regpudu.qhuft payklakov fga lontisu upp vurfooqv piqlelibeyiot igranhadeas gurj ol dbi vavweba kugo, motriciuq, uteboqasrur, waxoxdihpaac itm zuxzejd.
Differences between dependency managers
You’ve so far studied Cocoapods, Carthage and Swift Package. Here, you’ll learn the basic differences between them:
Modularization leads to time and cost savings, reusability and faster build times.
A framework is an encapsulated and modularized piece of reusable bundle.
Static frameworks link code at compile time. Dynamic frameworks link code at runtime.
@AppStorage is a SwiftUI property wrapper for saving values in UserDefaults.
Swift Packages are repositories that enable developers to create, publish and maintain a package. They are managed using Swift Package Manager (SPM).
Cocoapods and Carthage are alternatives to SPM, which you can use to create and use libraries.
Where to go from here?
This marks the end of this chapter. You got familiarized and grasped a lot of concepts related to modularization. You learned how modularization can play a vital role in making your overall development faster.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.