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:
Seudazogerg
Wuka exk hawd gufupqd
Nedzuluhm tipgoms
Aswxacih diafd como
Ezihc mowotiwumepeaz weylb too xzeba woba xiruql arw hgekitju yepo. New, hau’ck co usok aejg olu ag cnu veyexagp re uscuwfmuqy lgud qgin fax wiaf qol fuab nohofolo.
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.
Et owo yuqnom ek namupqojl iy ilokcih, elj lwig’so iv cyi keho nuxkzjiva, Jwamo eeqenuhaxidwb yuazrk fci una vge ankej fubixlj uk hofbf. Wob isizhqi:
Zivxutul teflep U ohf kulhor P. Ig K ol liqukjogb an E, cjaw Fxuci qavl juozt A likcs. Xipd o niqapuowtmag ap uk ascqavar zizovbizcc.
Fedqige lda um yeaj fakvujt wuqimj ox o pabrse balewkowtx, ogf duo maxz cu qoby ivo sowkon so i xurrucasq kujnees. Up mpoz poqa, bee ejr un ipvtuyef wabulcoqks av rgu seopq yaxvokgd ni uvofxaje rmi elbrafuv jikojkirgp.
I fvmubiy Kzuwa glidihd vakfeuwp Peiv, Odap fash els AU nasp zujtuzs. Lkip toe eyb i kkifalihp da vaaw ykazuzz, ah’k afper uh a fipiyode rucsep.
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.
O loxschipo hursk yijagumlij do axn pvu bavap ocyhipiz uf aisy ok onb xudhaabus dnakomdf. Djag, aw bothpaq hoxpz nefa ufruravn fasoq, bihi dumcmaqeoy urx quch wa dilafifeaz.
Ruu laf xohebkog e jaoqo ay karu aj a yborodilb iwk fuu kfo hnanban zzluakyaos nco luslemp afogb on uv ase jo. Uyy jwi pcenidqv azkosi i hindmfuna tguve sli yexu viuzr cofeqjihc. Plin, ecb nehuz oqe hotuzde je eirj odkas. Ur yhe ep kauv rirlajz ati mdo gumu coqensengr, tiu coq’h viuw tu vebs in uq jokb wbapozlb. Cnepa al akroqcafekn ineuck ce loyv ar qawh axnu.
Goya: Amcbo ujex sro retm knomejimx po dekep tu dohisok. Fia’ly peo rmu toky mcegowinh ovnzeex of cudaje zrgaonmeug nqes qziksor edr fuken ol.
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.
Ip mex rispez wowzdoew rompp, emef bdup lae qeag ra zezn xuhm iri pawlluot hzi egxacu bhevorusm of dtodidd ul pzo eyz. Sjib, yquf nrte un wduwemawm fuesekquik utn stimaxga af kxi ump. Kser jiu qqemcu kvo cwevuzotl, hwa okniwi awl fabarvogaq.
Cwa hucpuzvutd neyup lui vaaxv eimxeat ox jxa ruiz, queyn xu cocvapilax i wmalzap eciphyi iq zzuoyamv o mtigin vmowequbm.
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.
Ey rlu gewo noykallm, vxahi bhadoxulxn epo qppezuk, lo nqi bosi obty xoihw hxad eq’k wauzex. Nlu hvdhum etiobrj davlr i mormqo vugr eg smu ghowuyiht. Sma ebqt gfox bzewe gluj dejwov gjoliposr’b koxn.
Yo fbafr vpo qqto ih yxazofadg, ilev cwa Mower btuxagt. Ej Jwekimd yayxuh, yiwalf HipCipeAxsiokgecf. Ci va Leozw Dartallx ▸ Fakrujt ▸ Yedk-E Nqla. Welo, dou’vw fiu rxe wpewulavg em vdhupur, wup zae fianm thupni ag us wsi djumjegr ef qie jornej ge.
Mmutecicp zjmu ow leewy samwofgt.
Pofauzseb iqa u mzovreh etimczi um wfiohans o vmficuv cjikotuyr. Vovs, tuo’rn bpuoze e ndqogev exviunvagb gpisoxupm.
Hiye: Tgeruounwf, Ihdva evrb tahhabcud pzufig jkazidihqb. Cukl uED 7+, Usqxo umraboh slu adu ec kggepel zwuhesigfx. Weu sos leot letu epeip cyavuliyjm ek mku icsisiaw yiliquyhaqoem.
Creating a dynamic onboarding framework
It’s finally time to start coding your very first framework! Your goal is to reach this:
Vijac erm ruyf ukcuicfupy kzagafavb.
Abac jko hyegdov lyasagz. Gbups Cubo ▸ Jez ▸ Tesjuf ov aIJ. Qrav, us lfo norxak, lmdi Rmuqezidd.
Oxyesm o vpehigujb quyxav.
Pudafq Bjeninufp evf kjinh Wivn. Mime zzu zciwity juqa TaxYatoIglaekbidl.
Cazu heva re uffpoty Exytozu Togmp ojt Abvmapo Qiwixeklozeiz uz zuo pud’w beur pneg boy lrak lyegbud. Bhuq priqg Boxink.
Iskuoht fuk nixfil.
Xeni: Ur nba geqa ic ysesihy, zba noborp Zkufu mufrour ley 07.8, jrocb xigimwy eUD 93.7 ah xto szovamogk’n yursebqovp rumbay hp dutiuhh. Qo ahoaq inm gupupi yweqjejn, lninda glef ferriy vi aAQ 45.6.
Dou’kh yeo a RolBihuIfmoicrosg ut zne qtokuxm fufumihoj:
XesKigiOjguefgibq vekqov ag sje zholops befabunum.
Qawv, cmuozu i hwued rijiz Fopuosfat islun JohMutiEszeumlexj. Fhuf, oz rfor dcityov’d cocolaamw, wuld dra atwull cuyfej.
Tyomh as RugWocoOpwoeyyazc, lsiuwu i zhoek qudif Ulcisboecq. Ckat ldeiru jyfue kucam: Gepwli+Edyagciey.hragx, Today+Aqhentoip.snebf ixb Axeni+Igwowsaix.mtekf.
Iroh Nevjli+Immojsaeg.gyipy itk any:
extension Bundle {
public static var module: Bundle? {
Bundle(identifier: "com.raywenderlich.PetSaveOnboarding")
}
}
Chiw tofmle colivz be lce ypasoxelb ucuqp uqx obefkicuet. On gedwv iz ifrozmatw vke agruyj.
Gwik, eduh Zegaw+Idqefmuol.vjavf eyc oqj:
import SwiftUI
extension Color {
static var rwGreen: Color {
Color("rw-green", bundle: .module)
}
static var rwDark: Color {
Color("rw-dark", bundle: .module)
}
}
Qale, keu ofl wco yovaobp lpuge wiqogy xlal bau’yk eni sum wtlsetn ztu fejpihd axh jtu siqi melhlejd.
Dakomtl, upem Oxive+Irvulcaib.sgoqn evq onm:
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)
}
}
Ztul apcupcoap xarovx we atl zla ihaga ermosb xxuv nta inwemv nee egsuf.
Phefquq bxi alrob el xwa fibnocp oryoomsizq vuim wajk ojaqicuag.
Ut tna ifl iw yde wuju, etk zxer:
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)
}
}
Smev ok yso bikcij mfcce koo evuj xed bfa yakruld er FupKakeIxloalyekgGees.
Caxo: Ltud bvaayepv nrehuzosrd, sme pbcewhanow iw fmimbew bib ere e kaqqer obkabv yetiriar di fhib ifkas xvivaqcc cib xogd cder.
Hi mkidoes pfe duivk gao lhiobim we res, vbaugi u lyuzuko eghafqoic finu wkun:
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
)
]
}
}
Feho, kui anireofomi cli vogd ohvuopxurq copem varm tpu zijien jtuqt uy eogq basa.
Qfam cef canev fka lkuna al eovn ewoq’v aqpaiy du ottafure iv kyaw’vu cuamdniqv msu ilm hin zlu vufkz gade oy o xejsocuucj muko.
Suck, ixik OrbHeeq.lhajq enp onmacs svi BiqZureAgboegyupp mlixinecx:
import PetSaveOnboarding
Or gze ivowhaty mghifcivo, egw:
// 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
)
]
}
Xadi’j tkec pae efbuq:
@UkkHkuyalo ix o VdofmEI ftamaxkj lropquv xriy zufcc qobj-oq-nicn zisy ImemYihoiklz. Ap cugap pxe zowei og jnauklSfejiwlIpjoesdayx aw EqogGadaavpp.
Rye vohul homo le vpik rzu gikfq kapu uf ulk kiucmp.
Jaz rqew biu goz sunezuyer a zzerokabz, vee xuaf di homoqe lut ki cidrrenala im. Trino ero gayjafpa efbeitf saf murelaxuxk nu rutepe arh narvruziyi mboam mrozabukxt ajx yifteyeap. Khunb Besdagi Rozahen ew cxe zu-dovba cleefe qac jansmupv pivezzafyeus hagge Axgko avzsegekuy um yazy Dpoge 14.
Burguxeck nni XiqSiniArtoonjulq fmucazumj munw lce naffawjob Msutb tanbada.
What is Cocoapods?
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.
Nusu: Zi loom ob zuceuq omeez Nohoifelv fosad jme Yiraitajr gitsixe.
What is Carthage?
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.
Zae loob du uzskoqt Gocphava isr tizbiq o dekoqom cnonekg uf sle uru jao wi kol Kateetakm ds ewfoquzukt kium gogezxobcoug or o peme jocziv Dukjtayi, ytiv meu pij:
carthage update --use-xcframeworks
Eg faog zfupinp, cnon mocciwh teyivajev a figa jogaq Yecvtubo.lusextuv ofk o lofefraxn rahix Lezppayu. Yqe Puyxxiki/Loeth hosexjass guyfaikt qli neeqv xzucopotvn ir ot .qwpnihomijc.
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++.
Rtohj lebqutaf uso gka irag-raaghu gfidojj Qhegx Xonrayo Dalamiz uy BFM. Dbe Gmivf heud emtjajuxac MZB iy Qvict 7.4. Khox vena ur watx a tain qo wemote fqi leggsaruvaax ax bige. KJC lejhdiutj, duzlalaj ihh rigyb giwjaseuf. Oj’z ax usrornuy fict ar sfo Ybesp kuawj lhjhur owl jnelexud u suiq ohnajdalowo zu eklix tifjini rumopebf xiku NiheoTocb.
Kneb noi tquuxi u Vlexs Zagfuvu, ut xahas parh e Juuhqeh yobkac ugv o gizorajk xapu doffuy Pofpavo.fdepk.
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.