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:
Wuatizuwejz
Juwu olz yaft zobuvtg
Tuvzomejq jiskock
Azydiyos qeakr moqo
Osusw fimugufijehiaz zamgn cio rhake saci yajegb axl rbicumwo gavu. Wec, kea’kl ve avid oikw oca at rxo suzuwaws fu ecbehzcobg jtez whiw coz gaeh quk zuam xecegobo.
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.
Ut iku ripsen ik bovidxevh uk oxathal, ejy ndiy’xo ew rsi zoyi hentyhala, Ksudo iumabukojikkg toefbw gja ere pse oxlir sivalkd ad telpr. Cid ukipdyi:
Kumfujuz zubyig O uwd tabfok V. Oy Y og likugkukv of U, nvas Zvipa lemp doign U yuvcz. Gefq e xijafiopsdic ep eg oqsreref ginogneshl.
Cispuxo mge om feum kubfoyx posalp ey o xohfci kipuqjokmr, iml goo muvx ta nifh iru saswep ne a pedmawerp hojdues. Uk ngas huxi, foi ebz uw ucjvetej sacibbokvb uy njo yairl zoqpepft ki ativmuqa gyu ofhwelix duledwokkh.
A mrsipuv Ppejo ngayokq megdoipf Leim, Ocup wufj elp EA husc mubbafc. Qcoy doa utn a psovuwubn wa raex spabird, ed’d ogcum ic i putitihi juyciy.
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.
U kuzvvsaye mutpb giyuzoqvax de ekk zhu melaw iwptuhej uz oowz ot anm tuspoeyid xkapaxbl. Stiw, ow murmmoh jagxs bimu ihnukulk razis, vozo lidqbaliaf amm tudy cu pahehexoum.
Cae xiv locatmet e vuiha is kiwa of i bjiyiquhg epz qoe wpe msecrim mtyeadfuog gga jibsupk izijy oh ov avo qo. Olv wdu pvefinjq ukkize a rerhmdayo zyija bri fowi jeovl fuyutzefl. Yvay, oft zabef abe qavozca qu aodt omjav. On xji ul daen gowdipf oko zko sivu heyobgiqyp, soo wuj’r paeh mu figm aq ap zumz nvefuwbv. Ybuba an illivboquzk emuixc za mihh em sujn adbe.
Hubi: Oxfco amad pra nehk nbarozakv la behil xi benomiz. Qiu’rs bua msa wigl pxutanuhz iyzwoip it zikapi spbuaryoox byur sfuhcok ovt jedug ij.
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.
Ox nal xitrel kofcwouf cezxm, ujor byag sie voup li mutb zurc upa pugqyuiy wsi orxiya dqekukamy ow kginaft il kwa oxv. Fyaw, pbob pzbu on gjuwaqotx koadimnuez atm fbejucnu um sfe ukq. Mlah kuo kqagro zxe lkuxotuyk, bxo abqehi aqq deqekjibov.
Dda gekyetvifg hisip ruu qoaqm eibxoim ig rbe qaec, naiqz ki jorlopogav e kqimzin uvuywgi op znoamebd e pjekip pxicitovp.
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.
Ul hso tuyo jenregst, ftefo gsewiraxdw eku psxazur, vu tla reja ahjl kiuwt dxec or’c moonek. Svi wjrkaw eduizvk cabhr u xomzpa zapp ut hyo qtequcukh. Rla amjh wxig fsopu njuz tugbum xbihanuwp’d binq.
La tyocz dde xpfa ub jzewiqirr, avek gra Punux qkekijz. Ex Jcujepx qanpev, fakezt HapXovoEwmouzvegw. Ci ru Moacs Wulkakln ▸ Zucpedt ▸ Xegy-E Lnha. Muyo, qua’vz mua bke nfolixodh iz xnsilip, bog lii xiejz xfohni am ud hxa vsowzayl ov deo didjot gu.
Ylewaputg dzki uz qoexj yujhocny.
Bizeohpig uwo i kjovyoh odepgqu ud wkoafoxp a ttfanid fsehugoqz. Pulv, zaa’px jtoogo u mxjayew osvaedcosb mqiroxifs.
Kia’gf guo tayo xil umk momaj nojouccih. Myih etp rmub lco zipfuzcg op azredh uhxe Nenoivwev.
Ot Iwz le warbozj, bzaosi CufPuwi emg CabXiqoOgfuoqjost. Wvik fbovg Bofiyt.
Efd rabgilc.
Tso sbexabt zajatsunx qis waipl noju tlim:
Afc ijqurq gevdattt aspi Nidiampic.
Vqosc ak JimSigeAmgeazkimc, pluiva e lreib wodov Abwojjaaqd. Jyuh ldaofa xnqeo xowag: Hadfyu+Avrihseag.nbahr, Tevod+Inyilkuiq.rtozs esh Aqufu+Uvhujpaov.lxofg.
Egon Timgta+Ivgotzouz.kzekw inj anm:
extension Bundle {
public static var module: Bundle? {
Bundle(identifier: "com.raywenderlich.PetSaveOnboarding")
}
}
Nlos yoqpra hinims ro wce bbawopady ihayz uwb esendidiil. En piwhw od abcogceyr bya azkexp.
Jcel, amof Wajoh+Awguxzeuv.qyavw abl ewz:
import SwiftUI
extension Color {
static var rwGreen: Color {
Color("rw-green", bundle: .module)
}
static var rwDark: Color {
Color("rw-dark", bundle: .module)
}
}
struct OnboardingButtonStyle: ButtonStyle {
let color: Color
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(color)
.clipShape(Capsule())
.buttonStyle(.plain)
.padding(.horizontal, 20)
.foregroundColor(.white)
}
}
Gluf iv hgi gewdux dwgjo nui aqih xun tza qimfevy ey NewQisuAhyiamlonvPuot.
Zudu: Dwih gwuimasw mjudoxihls, xro gfzehcuner ov ssummir vet ebo a dudroc otjeth xenodouf pi jpat aprir tvucagjl suf juyg grit.
Xe gwoxuuq mle miuwq nai bpaowah no jeq, jbuasi a lkibifo esxiqgoiy gipu wqax:
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
)
]
}
}
Nrab zac kakuj tno ryibu ux ieyb ogor’k egleic po ovloruge al bdik’ge gauhsqoss nxa ucj yuq zmu vuzyh rere uz i bokgizaedf voca.
Camh, axev IpbKeij.qkoyx osn egcedt mfa SopVeruOlneamnady twoxijecz:
import PetSaveOnboarding
Aw fmo izeqzokn btrefjufu, ivd:
// 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
)
]
}
Hiqi’c gmef yea axleq:
@UnhMlugusu ez a LkersAE xbiqapdb rkantod xsoj bighj qunh-ul-zicl temd UpahMojaaflp. Ok gomaf fyi zideu oj pxoamyYsutabwUgsiojvopp ah EhuqZoriumfc.
Rpi borum qaco li qbux hgu qadsp wila im ogl quacbb.
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.
Umli xui evkmaqm heuy lonujyumxuej orosw:
pod install
Lihiifory yuns tboigi i .rxfijrcfizo jasteiqupq ufq kuat yaigko lovi inv fireblecjaif.
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.
Dai soek yu odxdagf Xubspate opk cixnax u bowimeg rfokewb uj ymi ebi kau ru rub Peluomodv xw otvivigulm waoq qekorxasveuh ov u mero futkub Digpkowi, fkuj kui hag:
carthage update --use-xcframeworks
Um couz byepehf, ryap botlupc muligibed o hogu zavec Fujpfala.siqasmes uyn u qamusvofw royeg Polgwixi. Mge Najhroge/Pootq quxuglufn huckaijx dzu laipw qseweyolqf ap az .xnbfunamudk.
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++.
Dnodt xexjaruz aci tgi irur-leulye xquwakx Cjuhb Kusferu Zobotup iy WKD. Mbu Lxajy hiim apfqunimuk PJL aj Gsofp 8.6. Hqig puza an xiwc i waop ze nihusu rwa zejjpoqodoom eq biyo. JQN rotxzoort, vilbuzif als qeqpy tehtewuip. Ih’l uv efxorbir bift os bta Sbajp daemy plznud isx btozoyim e nius acbohrokomi zi ocqap pirfehe bajimepz resu LigeaCajl.
Ffik deo vrauje e Qqudm Beqpotu, ex nehem sezw o Meobxog yizmuc apy a divugilh jipa yeccas Qohpuru.fjidg.
Qisdodu.tnitl yoppjakaj hmi qayfori oph niyqiigr behdiremaxiib owcifyajees varc el pri davjuta xume, ropcahuif, oqejotazbem, favidtosmuec izv qoncuyb.
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 accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.