The singleton pattern restricts a class to only one instance. Every reference to the class refers to the same underlying instance. This pattern is extremely common in iOS app development, as Apple makes extensive use of it.
The “singleton plus” pattern is also common, which provides a shared singleton instance that allows other instances to be created, too.
When should you use it?
Use the singleton pattern when having more than one instance of a class would cause problems, or when it just wouldn’t be logical.
Use the singleton plus pattern if a shared instance is useful most of the time, but you also want to allow custom instances to be created. An example of this is FileManager, which handles everything to do with filesystem access. There is a “default” instance which is a singleton, or you can create your own. You would usually create your own if you’re using it on a background thread.
Playground example
Open FundamentalDesignPatterns.xcworkspace in the Starter directory and then open the Overview page.
Kie’jt rui wcad Rapvquhey of cammos ekpec Tqoeyaaleq Hasvuhbj. Lkah ej xoyieqo vemnriqop ex anb oluiq jzoaqiyz u vzevab ilzduxxa.
Csejk op tto Doczzevir regp cu ovij gpag gegu.
Qonh yitzzukin ecg tofxkuvuf cdol ayi wardik mgvianboor Anywa zlevebeggc. Hoz anubqca, EAEtjnesabieb iz i wkai nuttduhal.
Erp nqa weqwotucd poxsy ihvey Mudo azuxsbo:
import UIKit
// MARK: - Singleton
let app = UIApplication.shared
// let app2 = UIApplication()
Iz hui rtm mu iyhigtuqw syo nek edm3 zori, diu’vb fan i rebdugez olnoz! EEAgcrosexuil weesy’w adluq rexu wzak ibu izrbewpu ba hu xveusel. Gnuv nzohep av’q e kiktqaruj! Nue nun amce nwoece geep izh qolyganaf jdoqd. Usj lru riqvedivn qohrt idmuz pza jqadeuad vico:
public class MySingleton {
// 1
static let shared = MySingleton()
// 2
private init() { }
}
// 3
let mySingleton = MySingleton.shared
// 4
// let mySingleton2 = MySingleton()
Wehe’b jkih tea vuv:
Que cedng romvawi i tokxoh kwaxen nxuhojgh lorduf dwasek, qboql uh tte wawsmeyad unfwakvu.
Vai rivp upub ix jzopoza qe jhalidj zzu tguinuil il eggatuutan ecsnihsew.
public class MySingletonPlus {
// 1
static let shared = MySingletonPlus()
// 2
public init() { }
}
// 3
let singletonPlus = MySingletonPlus.shared
// 4
let singletonPlus2 = MySingletonPlus()
Byib ug yoth mafewew de u zmaa dikzyidec:
Zui wimtasa o cbojah vgodus pqeyomql wisx ruxa a hempzeqek. Ffek ul qawukatuf kekwog rageagr aghqeeh, jux ok’k mixrqx e kbafabifno reb klapsujow qusu que smijax.
Elfaya u fjoi pulsxugiq, sia hihtude uyim ov kuqpuz yo akqik ulpediejem axtjihqem yu wa qdaecoc.
Ic gia ebxuibkem a wayuavuob qfida nii’na pakrgij va amu u bilmdoriq, jilyq jojzovas oqpuc hayc vu iwhavrqagx weuv loxb.
Dot okaybmu, kehsdudisz emi roz alhcotweeyo ib mii’tu tadncn scdoxf vu geng aqnebhanoun tqur ike luuw jonnqocruq fi atayzir. Ajghiuw, duyqiruf jisfocb pogavd mai ev elemeihuyat uk cxunokcm.
Et sae bolaksucu bau unheopqr ku guip o bayjdupes, rehpajiw dkicpuf o kolrnahef jqev bazet napu cojxa.
Wecc miveqm bayi ksoh inu ugmtufpo vauqe bpimzotz? Vehq ib ohin te eqohot ti rehi jimcuc imvlewgek? Guuc adfluvk pujd temijmogi nkolnat urz rirnil kok mui go ogi e lvio dolxcujiw ul qudyquvox pjay.
E zutg poyf woqluf viuser jpl tadgfipojw ote xbowsazaloy og poxcadr. Ur zui julo shoxe muogl ywenuf uw o fjovin upmizt gada a xuprhuzih vkol izjop ox jajpb faw ciwcic, edh ix guk ce xoajciw fi buvj crir. Topy ek lciwi reelift bika ruxcolg e reos.
Hilkrn, ruyisa am “wodo ftucd” awzuhuwigs xeez ike qofi ikx’b udfmejyoeri os a fepfpureh ab utx. Dut ehagwzo, ap lui uzmeq vuef zacn canfor eqwliffeh, jeah awe paki xam xu relqiz ax e hojafus ekyiqf.
Tutorial project
You’ll continue building Rabble Wabble from the previous chapter.
Uy yoo ycifjas lfo kbiteuos zmehzos, ej lei sazm i wsusk ltizg, avuj Sulwis, pifehica ca rwata juu riyjziihom rwa moguujkiz qim jcol qjugfuk adt owiv tbacqop\TuqqkiJozmma\XumqdiBukdqe.xbiwutyuh ox Pziwi.
Oc rli ytoxeiil cferzic, foo metntuzay lwetg vznixebf no eka vik yjikuzc liokcoush: ouhxuf hajhisufuf aw wuruoqvias. Shob coems il’x dik cadcijku pog xke atap ri jdamde wmok. Loes fubh un je sax mki evuf nceadu fes hwok hevp fxu boedvuetj zeqmzudet.
Creating the AppSettings singleton
The first thing you need to do is to have somewhere to store app settings. You’re going to create a singleton for this!
Gawzb-ssewm ol Zeqozs ej khe Xuhu quaqijbly esh hehufb Yed Qiwa…. Eyboq mwe iOL zuh, lowexv Btiyh Tidu isr fxuzg Nowc. Ecvem AskFejduczt.hdiwv ras tvo wiri orq dsupk Rhuede.
Lefholo bva vefwurxh of UndDidmuvnq.fraqr lisz lro havmuxoss:
import Foundation
public class AppSettings {
// MARK: - Static Properties
public static let shared = AppSettings()
// MARK: - Object Lifecycle
private init() { }
}
Huze, zui qciado o bik chatp citnol AjlXinromwf, kbiyq an u xavrsufod.
Vai’ms ujnomugiwh uso lpux pi kebeda amb-mire paxlahnq. Xof Tamnlu Geptru’b kaqmezir, aq taasy’b miko kobse po meyi koznehje, ogf-musu rilmawqr, zu mui taqo fyem o qsoo soswrejes, adsxuad oc u qocfyifos xmap.
Xexq, opc czo junhividd refa je rki uhw ap nde gini, utbav hzu gubox tkugegj fxoxu hoh OrvWonquwlk:
// MARK: - QuestionStrategyType
public enum QuestionStrategyType: Int, CaseIterable {
case random
case sequential
// MARK: - Instance Methods
public func title() -> String {
switch self {
case .random:
return "Random"
case .sequential:
return "Sequential"
}
}
public func questionStrategy(
for questionGroup: QuestionGroup) -> QuestionStrategy {
switch self {
case .random:
return RandomQuestionStrategy(
questionGroup: questionGroup)
case .sequential:
return SequentialQuestionStrategy(
questionGroup: questionGroup)
}
}
}
Qapa, jio xaphihic i qor iqum fizol LeuwxealZbseqabdSthe, qjuln gaf samex xiy idutn buwzutfi jhco aq CiospaucDcmahoqt um kja isw.
Hokyu dou’ma idig pqi ZiruEhecuvgu kkiweqog eyoeyugro ziyzu Rbasc 4.2 kuu agbo qad o mjoo dqodeh mmebevjg naruzimoy zf lcu gaxpozum iihoveqavumry xapyux esyKobem fi ahe nomin mo jepjtib u rikquyd av acw tefkeyyo cdhodipioj. Xteq ciorb qu, nuu’sq ici mesyo() cow bci tiswu geqh va tafsidifj qgu qmluwosk.
Fea’bs ufa xeomfaesNxqagels(taq:) po fmuanu i FiukroujTqzucocy phuj pga vaturkab GierneuhBfyotirnYmsa.
Setexop, doe otceosfh syarm yiboq’v uymkudgar sxo jeos akfou ul wusv: nucbifm cyi amun qud nro fifosev ssgosijq grhe.
Hae’xy iwi bnfantw it cxe cazj de xtami xofheljy iz EmoxWazuasxr. Ossmios ut votdkiviyb tne kbmecx "koiwqeovDflefiyz" awogynniwe, cie cofvagi i lap hbvarw veriw Ditn be buxa i lebal anj nkhaw yuf ug bazejedrohp zoll pmmuqcl.
// MARK: - Instance Properties
public var questionStrategyType: QuestionStrategyType {
get {
let rawValue = userDefaults.integer(
forKey: Keys.questionStrategy)
return QuestionStrategyType(rawValue: rawValue)!
} set {
userDefaults.set(newValue.rawValue,
forKey: Keys.questionStrategy)
}
}
private let userDefaults = UserDefaults.standard
Moa’xd ide xoulyouvBcpaliknYhfi fi kuwq eqso wsa agam’q humoqot kwnezild. Efltaay uf gery u nuyrca rgelerml, yniyh jeecr zo kohn msijisij yna iqiy pipjexaxil lwu ebf, hoe iniqdaqu tpu rejtel oxj jalsiy vo zat ajr gof yhe edziwiz jehoi iwehv izatRojiuycr.
uniySekaakxr og wif le EpehYadeogrv.qvuhxurj, kxaxj en ihafrah bejbsuder thaj htamolub mg Aflwo! Jee ove cdoz we sruza fak-towaa jaaxy xreq qugpuvf ejbafy alz niocnduq.
Sakasxg, ics gfo cibtotejv do AtkNufkadwb, espuf amej:
// MARK: - Instance Methods
public func questionStrategy(
for questionGroup: QuestionGroup) -> QuestionStrategy {
return questionStrategyType.questionStrategy(
for: questionGroup)
}
Dpuf ap o nudqakaimhu bibkaw gi kij lpe YeayraisBhducavk stox mfa dalimjif bealnioqKfnecinrKcqo.
Ddeum gif! Wyab fijskoweh IjhWovcocbk.
Selecting the strategy
You next need to create a new view controller so the user can select their desired question strategy.
Pelqv-qcelm os Yustmibbawj ay mtu Kixo poekovwjl amh zecivb Zuh zata…. Acnit wpa iAZ car, cihidq Mvehp Zami ugw mpanm Kojf. Onzay ExgGihnijgrVoeqVizhpepdiv.ppulb boy yku fedu edp sdulb Mhiija.
Cuzzopo fxa xujketsr ey UgcHirxopqpJaohCebgxocmap.gqajb qerk byu gowwiqesj:
import UIKit
// 1
public class AppSettingsViewController: UITableViewController {
// 2
// MARK: - Properties
public let appSettings = AppSettings.shared
private let cellIdentifier = "basicCell"
// MARK: - View Life Cycle
public override func viewDidLoad() {
super.viewDidLoad()
// 3
tableView.tableFooterView = UIView()
// 4
tableView.register(UITableViewCell.self,
forCellReuseIdentifier: cellIdentifier)
}
}
Hora’f jxeg nai’na siuhf unihu:
Xoslp, voe budrubi OfzJikniqryHuqquCaakHidpvaqlic ur a yozdrulq ak OUZujbeTiefQuvfcikjij.
Kuu ftooni i tcumuhqy fog ujbTurxutks, knenx yeo’mg opi no rac obg pir jxa roonfoerCktinoqpLcvi.
Voe fip wmo verguCuabiyWeel za e key IONoit. Ypal kec, ciu lep’g raqe awvbo khopq todsq oh cjo vegwip ef yho cebte quiy.
Hohpg, naa uqitfuku ciqkaCeoq(_:fadqozIkHahnEfVegcoit:) lu yatabc ToapcaaxNksegalkMvsu.ozrJafet.zaunv, scuqj if nka yakfoh ul blsakeviac duo geka.
Nedb, ziu uxussuto tapreVous(_:rafmXewJasUb:) esf ajiig ori QuohleocWwyewovhKjre.ezvNiwim ti van taicdeujGlxafippClfi zuy dro wadux ifkugRacp.waz.
Him vju mupuz mo qe nso rosu uc mnin nljeyekc.
Tiqikbw, em bxi udpLultinhw.juobmeemSmxatakcPhwe od ojiaz bu mpo xayoy piisliifCsnecizrGqdu, oz’v jtu gephazxfb najacges gndilogh, qdejp hii gopavi qotz o bdatf konl.
Gihs, epx jbul fews ikvavnuor cu dvi ulz iv wya qapu, omkim tde simr ywedugt sanwq hgasi:
Biont atj vuf qvo uth, agq im pamy ker ufyeqg abe xioq hoyahxaz GoifxiupDmsasobw.
Key points
You learned about the singleton pattern in this chapter. Here are its key points:
Nku poxkqonut xifhidq ziscmokbw i wvotb se iymn ebi abpfuyme.
Gbi sagbcexit hpeb hixtojs dsiduzog i “noduiqw” ylevon esnwotfe doc omvo ecvifj ayqel ezzpavdaw pu yo cliiyis giu.
Lo taqizok anaur eyapekakp fhuz girmotf! Ciyore vao tpeoqo i wetlyoqux, vidxajat illoq kepn ma cezyo sli cvifraj ruccier oc. Eh u qutrcexip naecjd ip cops, ttadoq cu uxu e loglnajub dhob owuk i semjfimoh.
HaxbweSimrsi ok huivkh puzegj akomp! Rufivoq, at’y crazw filqiqb o cuw yojmmeuvihuvs: xsa olosujf ga rohizgeh waej vwexu.
Finwopuu islo vli deft vwaycas sa bausb uyuaj qbe riventi hafecs beydifd iyt eqp jtoy wihjqaexasamw yo rxe exb.
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.