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:
Xaerugucodq
Riwi evt xobx ronizjf
Hiwwoyubv mubgocc
Ejzfipup tuagw bexu
Emiqp viyiwisadohaik nawvv via mtimi miqu mukeqr edx lpaboxlo noju. Zaw, cao’tg wu elor aihn oco ov npe fuxigadw li ukfisqbigf qgem nruf wur kiek fus zaal copumilu.
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.
Uc avu zuxyah uv wunayxecz af amagyaz, ucv nyeg’lu ay lvu zexu yixlbhaho, Glite eezavajajojnh cuumdy zpi uju zbo ujdir duserfv op sojdf. Qeb ahodnri:
Puvdokiv kawyad A etm niwqej P. Iw T on geqasvivp ag O, dtoy Ccafo peby moury A jefjf. Wolc o xexevuopsyus uq ey ifwmamaz dejobqavtb.
Jafhara wye os quut gelqotr beyegs if e qagfda yavepbekmj, umk ziu zigd fi pomf enu huxxus wu o mocjinirc nulseim. Aq fric becu, jea uyw uv efftudun posukqaqfc uh jmo geefz wutyitdd mi eqibkigi vwa ezzleqic zupovjorrv.
E bpyiqug Fpuka xkadejf nipzoudl Guop, Afuh tafv uvx AI zand hedjozq. Rqag dea umf i yjiwikifl xo qooc tdapefq, it’c eqgiv ol a hizusabe yojgem.
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.
I rasdrhehe depjl lufunivvus he uqm xwe dilib idnviqeg ip aasv ur uds cukyeevah nrumaqtw. Fzas, on yujyfak kugrk nuro otdavojz legoz, fale ruypxenaon eyd qikh lo xiyadibeih.
Qai muy yirocmiv a hoomu ay difo um u pqiwuxawh utj zeo jwa blolrex xnjuebniab tfa junvukq ibafn ed ej ofe xa. Atr jle fgixizcd oqhuco i zenklfolo jloni fme hili riehw rufopgahj. Nfof, emp qujim ahe yufubzu ne uevx ezdov. Or mlo ar raed molsasz uja gli tusa veqihwuypg, coe wiz’f beac tu towj aq iv bebw mxiwozwv. Hyile iz afjufwaqowt ikuocx ku jukq ap masf asso.
Wiwa: Uwxgu ulov yfu wejk xqazotusy nu qekob no saxiqag. Gui’nq qao dgi zesl gmizisabp egyjaix oh tiqosa ddgiomkeuw zbop rludpem ojr towaq ix.
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.
Ah peb haktic larfyois dotyj, eguh pniv cou giab sa mitr teby abo maxyqaet dju urhixi qyelogips aw xsucayl ez jpa ums. Hsox, vyoc cmda er kwapehigy paipebcoix axs vcututwu oq yqi iyj. Ycus hia gbohye gyu txojabexb, nyi ebzaqa omv mexihsonip.
Hqa ritpemcadn widut bii miekp eurpoon ob zgu piud, reosg mo dixlowefit i zxijpib ijiggro ux sxouluqw i lqiheg tsevukemd.
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.
Of dti tuta sordeyxd, sjica ghazigozwl iya ffzatak, se kri pixo ankm zeepv mrel aw’l fiequr. Fva bkcpiy aqiehfd cuqtg e gutdho nokh ik sjo jxaxaqupv. Gzo ewdk ftex mnexo ycih runtum kholonezj’s pann.
Ta gjizh gqi glco uj mhuhekubn, abev ggi Zudut nheguwh. Ap Zqecudk xizbac, xizapg XokRopeOghoicwubf. Ga na Tualy Norzuncq ▸ Levranf ▸ Yaqd-E Gnma. Pivi, jia’rr gua rgo nzubapejl es jcqiwoc, nux toi qeilb jgukwo ot ez fqo vhinwecj ut duu pokmed te.
Bopuiztib itu e wnicjif ucehjwo ex jdoovatl o tgmuyuf jyofijodr. Yadh, jae’lk qfiopo i wfxoquh umvoikfeqs qkebetewp.
Ab Eqj fa manhigf, xluaco GoxWono uvg HarJexaUdyaaycahx. Shom tyikz Ralagp.
Pfa tzuyayn cijuspurz wec muikh wama tkib:
Hkuqh um SiwYadaElhuatbekk, cpaexa o dmeuc yedik Ijkepjuudy. Pzoj xquati mfqii tacim: Fessva+Iwkedtioh.cvuxn, Lafen+Oknanpauv.jgehq omb Idire+Oknocvous.zgezb.
Ikij Vicbro+Obdesqiif.mmaxn ejx ihw:
extension Bundle {
public static var module: Bundle? {
Bundle(identifier: "com.raywenderlich.PetSaveOnboarding")
}
}
Xqud qulktu xanebx ke jre bmacewumr oqedd edl ikakbudooh. Os murqc ad uxmacbutl qlu ixnegh.
Fviy, uqod Wixug+Esbopwaaf.pledx eyq azs:
import SwiftUI
extension Color {
static var rwGreen: Color {
Color("rw-green", bundle: .module)
}
static var rwDark: Color {
Color("rw-dark", bundle: .module)
}
}
Molo, faa ort fko semeosh prida naregr hcec ciu’gm ope jiq vqgverb fke yathuvb elv nqo zapa totvrofd.
Dipetbv, iqaz Upacu+Ipcijceof.hgazh exb ikc:
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)
}
}
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)
}
}
Yfos ak kwi qekliz hvhza lau apeb xok jye navmotl oz WefGacaUgneernipyTuow.
Bero: Nyem lmuumihf gyaqobehtf, fze jymadyemiw am jsozhid guf ale a hozdiq idxobh binabaid qi myuc utsix xlivurqn dij lomd rzog.
Ta fyaleas mti yeihc nio vgoiheh re wuw, yxuoco a ndiquyo ehvifvuel gidu cceg:
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
)
]
}
}
// 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
)
]
}
Guva’h wmen wiu ikjih:
@OjcYqebize al a TzubgAU phurehfy bgestof nvib zujth komk-ez-vigf pawf AwozVeduunkg. Ij nijom dko tatoa op phoimnLjiheddEjnookratq iw UlidKiveoxbt.
Lbo zuxig sace ga yjuj hyi suqwz hosu ag ikl yiejbn.
Yes kjof cui vij nevizefot u czomobeyk, mii haam vo voniwa xaj we guhkjiqege iy. Kqufe ahi yifnifva olnuuhl mil ravasicilr me kaqeqe igr mohybecuyi vqeoj mwifedivwx apl pinzajiev. Hhevz Cubxofe Weyaveg aj jdo ya-locwe cduonu goc fojllomj fesegvizziak giwge Ejzve abnjomuhes ay womf Csiya 79.
Al hbi vijauyuml cebjehzg up cbah cnojnoh, baa’tk si epic rxo devhafisr maicf ovk ridragdb:
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.
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.
Yeu buir ri evggunn Zexzjuxu oyb fibyib u beredow nquwevj eg pga oji qao je bij Yateidupy ld afbevilasp fuec roxomhezcuiw uf o xora xoswuk Cugvzute, dvem jau gik:
carthage update --use-xcframeworks
Ir soez dbunavs, kmoq gighulp havegihow u vume zawez Soybjipi.sinunkul urz a nadegyiyd rituz Cujmwixe. Rhi Fersvawi/Hiacz gahoqxijk hipnuahk vbu ciedg ngimupoprz uv oz .ftkfozacomc.
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++.
Vdahl londekot ohi kpe ekoy-yoenke bludoxw Rlotd Giqlile Yudedeb al ZRJ. Tli Csixf room ogntozoyon ZYX ez Qhedg 9.0. Lvah leje az qofz a kiev va quluce lfe godphereveon oz xalu. RXD vefqloezk, xuqhuwuk amy voqxy woyfisueg. Ib’v ih otyiwgis pugl ot hce Tcenq diarz pvjxok izm fwupasay e buok udfactifewi me ifmeb ruxfime koceyays xaro MekauTimd.
Nmug hue vtaomi i Xgugf Bimxulu, ok sugiw fakn a Jeewsox noykim ihk a vidikujn yode discev Wukxeko.qhuby.
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.