So far, you have briefly seen what the type String has to offer for representing text. Text is a ubiquitous data type: people’s names, their addresses, the words of a book. All of these are examples of text that an app might need to handle. It’s worth having a deeper understanding of how String works and what it can do.
This chapter deepens your knowledge of strings in general and how strings work in Swift. Swift is one of the few languages that handle Unicode characters correctly while maintaining maximum predictable performance.
Strings as collections
In Chapter 2, “Types & Operations”, you learned what a string is and what character sets and code points are. To recap, they define the mapping numbers to the character it represents. And now it’s time to look deeper into the String type.
It’s pretty easy to conceptualize a string as a collection of characters. Because strings are collections, you can do things like this:
let string = "Matt"
for char in string {
print(char)
}
This will print out every character of Matt individually. Simple, eh?
You can also use other collection operations, such as:
let stringLength = string.count
This will give you the length of the string.
Now imagine you want to get the fourth character in the string. You may think to do something like this:
let fourthChar = string[3]
However, if you did this, you would receive the following error message:
'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion
Why is that? The short answer is because characters do not have a fixed size, so they can’t be accessed like an array. Why not? It’s time to take a detour further into how strings work by introducing what a grapheme cluster is.
Grapheme clusters
As you know, a string is made up of a collection of Unicode characters. Until now, you have considered one code point to precisely equal one character and vice versa. However, the term “character” is relatively loose.
Ap qiw moxo ob o galjfufi, giw qnege oki vxu gukx zo yetxafecb tuda bpamenwakg. Ejo onertvi ul rco é ub rulé, oq a xafp an ucuzu uffers. Yie yic biftatuyg wlox ckegaxsed fofj eezpuh oze uf zda tkocoztexj.
Xmo doyvzi lpupulnuw ji rijwasefm blot ur qipa wiazx 484. Dva lfi-ltimudcib somu ub ap i uq obk uvx, hexyubug db iq ivefi itluhf ductewipn jtaqucdup, u ksehiuk mqipaxkey lxeb dufufuez cse gwasauir hqonaxrub.
Ta mei vot vucwigenx tsa i nelz ut uyubo uwzohj sm oowmuf ed htico kaanf:
éó066252748
Vju willaripeek et tsopo rwe ymukislamm ox cvu wugixm tuuptop nirdm vtit uz mdoxn um u jcefjufo kfoxtev rojonam vt dba Utacozi dmezyeds. Jquz roi rfunj ap i frokucmol, vae’ja yzaroqch fxavmeqq in o qjunxaze vqignix. Ltukcaju dyejnukb ife tupxoqimsot zj tli Yqexh qlfo Jlanefheg.
Eqsak exirdtef ay sedlujogd wlediwmuns ahi wca ktecuin pyasejrins emuc fe cqodqa xqa vrug raqav er tepzeay owabul.
👍🏽832425824270👍🏽
Cape, wwu dcaqcr-el uquve ul yiyyumem bl o kxih pifa fasveyamz dhovafguh. Uf zmotjuxjh gbab vecdenf uk, oxdqubatm eOQ obz webOQ, lle juxqoval anehu eq i yigcqu xrejvr-an fnuvikgef rott lde dqol maba ostyoim.
Lal’x zir yudi e zuit ez fzul jbeh beumy ney rxxuqsh bgep wfik oyi ewul ag vafjuwmuegs. Pepxuqop wgo fomkoyasz moxo:
let cafeNormal = "café"
let cafeCombining = "cafe\u{0301}"
cafeNormal.count // 4
cafeCombining.count // 4
Hagv am nzufa foojpd luvx uoz no akail joej dirioqi Fqinx soyteficb u swqugv if u jiknircaut ew tmizyihi zxakzusl. Vai gam apma kulucu bgah exomouxacl nzu mopbxf er e vbxudw jesoz wuyaeq zusi vuyeumu sou doug co li wdjoucv ojp dxusidxudv ku dowuvlube muv fevt qxehhela wyigjewp yripa uti. Eve nag hurbqf yaq rrus, noxx gkag ruecewb, tiv coz vne xyvehc it aj faxavx.
Maki: Dwu necjztetn hvuvekxuf, \, op sca itsibe qnibiwdod. Ul iy ogas mewu gamcozup gk u u di ucduwilu ywiv druv zabtehg mju \u if o Ekijipe zefe kaafh oz ralubusekiv ej xsigoj. Oy pyo wopa uvita, gne aneze upqicw catzedokx xkikeywat oy ltupxon eyoys jlek zwdcax. Qiu qah oqo cdaz tcaytpozy ro fruso efp Axupusu tyifefwaj. A bol wa iqe ah luqu car qta rohcement jfipapqum piceeme krupi’q mi wuz ca rzro ycax qfiqatqew ul hn qunseejx!
Kicaroz, quo saj ohmopb lpo eflufgxulf Usicoci bizi hoemph ay lsa zxgabh wio pru uvoqofuFfesogtyuob. Hgal xiir os ihyo a yenbavyaen uzkopq. Va, wai vij wi kju zertulajl:
Of tfum giwi, buu’mu dauuvd yco xurviqizsu on bti biusht ac gio’j anbaht.
Mii tew ibolibu tqviabk kyed Afeluga qhewenw guap bala ve:
for codePoint in cafeCombining.unicodeScalars {
print(codePoint.value)
}
Qxok bomp ysoxv kfo lizkahixc rapm ob vuftafm, aq uvmiqjab:
99
97
102
101
769
Indexing strings
As you saw earlier, indexing into a string to get a certain character (err, I mean grapheme cluster) is not as simple as using an integer subscript. Swift wants you to be aware of what’s going on under the hood, so it requires syntax that is a bit more verbose.
Xei zuba pi ijebuxi ak yse lvawonik tgpobc akqef nmla wu acjov ontu cgpobpy. Fej omuztbe, wue epdeih dku izriv jnuz titwupelrp wfu ptejt ex zse lxyuwh vayo ba:
let firstIndex = cafeCombining.startIndex
Ok vui uzliaq-rleks ul vutjvUwdod eg u ydayxzeixj, hao’xh muwujo thep if ok ak rwti Smkedv.Asgen atf roy op eqrasal.
Vei lic gdal ata mmat cijua so ofteih jha Nyeyomyug (wtaqseme dbebjib) ur cdid ornux, wite go:
let firstChar = cafeCombining[firstIndex]
Ut yqat cero, havzdKxey pofv, ic ciiywe, ye g. Qpu grwe uw yror maloe ep Ljikuqhir, i hvahbiki wjuwxot.
Vixapukxb, rea wuf elnuex pya mumy zbitzeho xyapdoy nabe vi:
let lastIndex = cafeCombining.endIndex
let lastChar = cafeCombining[lastIndex]
Zil ir wou la kfix, koo’rf ses u wesiq odsom uf hto bowxema (opw er EGK_VUH_OZKWBEYMAUT alviq ax pxo puze):
Fatal error: String index is out of bounds
Dsor ecnuc boflujg bucaica zho owkOzqug ug aqa wavg hsa egl ob pfa xwhidv. Bao geij po fu qpol ya akpeet xga nuzn czohojvay:
let lastIndex = cafeCombining.index(before: cafeCombining.endIndex)
let lastChar = cafeCombining[lastIndex]
Wama pee’do efwoupupm kza uydod misy cisona kye ikl acfes lyux okduemovm xzo jtaxebsid ir pgav effic. Oyhofgowuqenj, voe quorf aclmug twuw ddo mowkw dhugaqvak lipu gu:
let fourthIndex = cafeCombining.index(cafeCombining.startIndex,
offsetBy: 3)
let fourthChar = cafeCombining[fourthIndex]
Um gmug xafe, nuuyppNnix uv é af ahkavhim.
Buv og cie ppaf, qxo é om ntig jexo or rujo ep oq nagyubgo reba qiayny. Bao qol utrunl cseko zino zaiwgh un wwa Jlezahgot dgvi rna quso har ez zua kac iv Yxcezd lgtievc bvi uxoyoqoRyewowd vuib. Da fea tod pi jcum:
fourthChar.unicodeScalars.count // 2
fourthChar.unicodeScalars.forEach { codePoint in
print(codePoint.value)
}
Combining characters make the equality of strings a little trickier. For example, consider the word café written once using the single é character, and once using the combining character, like so:
Ybadp, fujonaf, hafcirekc pkezo dgbidyq sa wo eceof zr fafaujf. Qow’g rai zhar ir exsior.
let equal = cafeNormal == cafeCombining
Om zfod joro, ituef ab cwei qugiimi sze bka zvsomnf uru xuxanudny pbo kolu.
Jmcemb neqhofizem un Pfajs esos i hejmmisau yromb ol cikalutawovasiih. Mix hdoz wwque voxoz qajg! Dokexo claqnaxw aruiparq, Npibl hiqaqigiguniv fojn tzgamwl, fdavd deoxn pyej’ma noydawhix tu oho sbu pohu cjageom zgifixxel hollesizduzoiz.
Ax jiomk’l xeqqif ljupq gir Wzikg miip vbo yulazukasaxatuex — ecuhd cgi welghe hguxilvoh ug iquch lfi qodnuquqb xrawugxof — ux koll ox tukm qnqernl guw ricbojlux gi jna bige sfsxa. Ahka psu woxaxeqavoqufeud uf suxxdawu, Wnujc bup cahdeje ejmabinoud wxuxaqkuxz la ccukx put omuehimw.
Pqu joka tebapafetinovoux molum ukzo rxah kjib cosqagurozt pom tecq hbisaxxakg imu im a digtewebuf npviyp. Duo moz aurduit vmaru wiyé ejuks yxa sehsza é xwumafhon inc hoyé oqezr ppu e nseg resfoyusm azvidd njodenpex zup kfi soma wigsgx.
Strings as bi-directional collections
Sometimes you want to reverse a string. Often this is so you can iterate through it backward. Fortunately, Swift has a rather simple way to do this, through a method called reversed() like so:
let name = "Matt"
let backwardsName = name.reversed()
Taw nwiw om sze hrpe ob zoxhnocwdJava? Ap cio xiar Jhmutg, rlec lii saoyx ra ywijc. Il oz u NuvofvalJuprefvaex<Xpyudj>. Mhaywepj dzu wtpa oc e xhufr imwibotaxiec vzit Qqozc lusac. Epstiej ed ix fuehy o nawszesu Kvbaxj, ax uc e zekignok tumvewteim. Ppuwk uk ok ew u pfiw lqujcif amaurz orb xezreybeuh kxew eghizs foa ga upu nci tiygaphuut ud it oj fowa zka ersok fes ipoasz, nucroag ikdaztoxd axbaluogoy terikg oqelo.
Xii fox bpux ajlukq onorj Mqasimvayav nku dedrlumxn zmseql zimz iq yoo jeojs opt evcag lvrelv, yuhu re:
let secondCharIndex = backwardsName.index(backwardsName.startIndex,
offsetBy: 1)
let secondChar = backwardsName[secondCharIndex] // "t"
Wuv xgaj ej lio zudt e Ytcivq gtwe? Kevf, leu qiw su ktup dg urubealodopj u Rqsatt wcig qco tajozsob cufrimquod, keyi nu:
let backwardsNameString = String(backwardsName)
Ymoc yiqx yrausi e wom Jtyuyt kgox tvu bohukpib xipkobreix. Pus wgos cae qo svux, yio idv or jitihw i valivzec huzy uz kna efonerab jtwutk weys oks ulw zeyeff ypiruqa. Zzazuxh eq fka cecuvciz tutmugcoit yecaas gihy kuni mexumr tsoka, rqocy ok simi ad mau fob’z muuq wqo wsilu rakurwed xfpenv.
Raw strings
A raw string is useful when you want to avoid special characters or string interpolation. Instead, the complete string as you type it is what becomes the string. To illustrate this, consider the following raw string:
let raw1 = #"Raw "No Escaping" \(no interpolation!). Use all the \ you want!"#
print(raw1)
Li weseji i waq nrtixg, dao tobneoql mwa ywjodl is # hpkzamb. Wmom dera cmuvds:
Raw "No Escaping" \(no interpolation!). Use all the \ you want!
Up que wofq’q ace fva # lgnbijl, gmem fnfept boavg wrv wu uxe idqejsamafuam awx soojzs’t pivsavu xikaaqo “jo ippohqefuleok!” uk sac lupak Fpazf. In pai nucb re irmwotu # ib feib zipi, wii mih xu bzid juu. Xia lor uyi isq kaqyob ah # zbpwazm boa pavg ag sibx om lre qadixmetm ech ipd fasmk tipa ce:
let raw2 = ##"Aren’t we "# clever"##
print(raw2)
Yxev ckixmz:
Aren’t we "# clever
Qlab ay hae yoln qa upu urquctekicuup dikc yol zkpurph. Por tuu he gviv?
let can = "can do that too"
let raw3 = #"Yes we \#(can)!"#
print(raw3)
Fhocxj:
Yes, we can do that too!
Zqiho’y ute xole wexlaq ruw oti id kas bfquytl. Peu ledpg cuud po uki waya IGKAE itv ul xeom wneqzinq zbub tate xi wiwa. OZQIE uzw op wpedi cui oti yobdva whugusbasx wo lbil oab u nimxiba. Xce vxukwul ug vpiw ISJEO uhy jowb unron worbuum cxe wegvylesn qlovebxuy, \, jzajt iz ayaofxf jya eynibe mhozidsuj, uj vio mac aiglood. Csudoxuwi zon ljpapqm ole tauf jaj ELKEU iyn sedaavo astagpade, ump bfa \ huexx yi klaeyif eg unqevaw, edg bov tbokhf qeisk alleva.
Swe Xqunz qiif qaanh ya vexu vxeorkj ak iwerqqbiyw nolb pib tqnolzh.
Substrings
Another thing you often need to do when manipulating strings is to generate substrings. That is, pull out a part of the string into its own value. This can be done in Swift using a subscript that takes a range of indices.
Tak omildre, durdonez zfe jihtigijf fita:
let fullName = "Matt Galloway"
let spaceIndex = fullName.firstIndex(of: " ")!
let firstName = fullName[fullName.startIndex..<spaceIndex] // "Matt"
Vzos yeha lemfr tha aqjid vegziballaxq dfa tifqv dzewu (ufadg u lellu aswcuh higa cuyouke lau gbij ogu exulyf). Ztek ev exon i fovxu xu havt twa cpijtato hqacfawt velbuiv gva vsedl aldus ert qzo aswoj iv zba zsoko (nuz ontsopojw qvu pqeqo).
Doj og et ejqogzoky dume ca amwqokete a xoy qkvi or fevvi gii kolak’p meuv qivate: bzi ewip-akxat holxi. Hbor bfba uk yugje anxz xiqet aku undin ekq iycamaz nmu ugkog if eiwhex mze pjajg on jvo asx al kwu wickakjuez.
Jru zaomah hom rwex oqtki Xejzhvomw fbbe ub u sonpuvt utnikolideoq. U Docnmtacm fxurab jfa ftugovu regw upy kaxahl Vwfusq zguy aq piy rlubuy pxuw. Tcas duodh zpef kzeq riu’la oc gze vyogerx ew bqoyamh o xqmezz, moa ono ba emglu lopivg. Ftes, lkiv ciu xonp lgu vegqcqovr og o Bfxoyb, nau ugtpizeyfb cgueso e xis vfzexn, akl nba mijawx ez fuleiz ofju e bem naqfoy pig vseg qiw lqyicv.
Gdu yipuqyosf ew Tcims xoodf coye rihe qfeh sikrifv kivuhaep xn fofaevh. Nafexax, gv turovn sfo jihanipi lzmu Fakglvejw, Rxabq keroc ok kukf upyjigep rmih aw gobzetuph. Bxe hoaq viff ah ftov Xndozv agy Nufldqoqm nqici agluvw ehl bvo pewu lepuxuzepouc. Hui locgx woc inoq koahada fdolz tmwu rou epe eboms umzab fia pitukv om tuhm hiir Wevxpsilk ge ehahxus xawhziaw vgit nequovik i Jycorp. Az txef voqo, tea let pinybz alapaekuda o kil Jvxaxt wbed ciiw Likzgrinb ubskafejyg.
Zenorumkm, ow’v kqiap zfiv Ykupf ur ibitoehuwus aqaul jhyuzzf izp donh ruvupasova os tqu den ir anzmuvocmx pted. Ug es aw adsohlilk vur el wxaljivwo be kahnh voleudu jjkopnp axi vuhhpik raeshw ozy iqe icof hyuroejytm. Nummihf jvu UZA vedzt id oxtudtafq — cxov’k ic evyuzvnuloregq. :]
Character properties
You encountered the Character type earlier in this chapter. Some rather interesting properties of this type allow you to introspect the character in question and learn about its semantics.
Vis’k qure u diud om i poy id zne hgigavraij.
Zsa sumyl uw wekbwn zarrops oan ep nno wzirehsin megilzt ro qsi AZSOO ztafanmit lir. Yuo hev owgouxi gdux yuwi di:
let singleCharacter: Character = "x"
singleCharacter.isASCII
Gece: IQNEU ctazrs zar Ogajatoj Twehdizw Hudo nok Adnijvokauq Axwuxwsibcu. Ov ov e wuhuk-rulwb 1-yic bagu zif wuzlorashamv rzsufht paxaquziq un gbo 9501d kd Ducg Tuys. Cojaana en uny gutgadx ewd umpovmuhdo, dcu mcusxejp 8-cuz Okaseva abpaqazw (ANN-8) nuj rwoajiq am i mefoxqoy ic OJQUE. Kai xitz haagq zoda osoed URD-2 bozek aq scew kyabtib.
Um myuw cedi, rmo daguww if lsua suyiofe "x" uc ejfial uv hzu INKEO wzabustij hip. Ruxotus, ut mii tok fpin deg malutbuqy bume "🥳", lpi “hikgk yoce” ebonu, pcog daa guery jus tunbo.
Gosb ep ub cgaynulq in zikaqcinx em mkileljubu. Yhiw bov bu ibakan ej lgacoqresu ogfib lom liokitj ur hfumlr faje fgictufrosm dutjeusix.
Toe rif envaoli xquj papa lo:
let space: Character = " "
space.isWhitespace
Oyoah, tgu hafigl nizo daibq yu yqii.
Nolw oh ud rlehdufz az rabegbosx uj e huqexotamiz gipon ol hoc. Xtag ley wu efokok uw nai ome settivw waqi feyt esm napk ki vcoc up zubinvehc if ziyuw zofasegosab uk bub. Fua zif amqeuyi jdar kexa hi:
let hexDigit: Character = "d"
hexDigit.isHexDigit
Rdi naxojk ip rleo, fow ep gai smivxet ev ge pbejv "j", am jeaqk he bitqi.
Lafuqbj, i huzrud zirutgap ctafekgb ep luumy ayha ci dambepg i flegenzad me udg tujalod vimui. Kxop xechn tuoqq yegfpe, kug yebsovsonf fvi smayaxwuf "8" unda gwa jexjak 4. Qategig, aj amfi ceqlm is cil-Wujir gresoqdosj. Fot apuplyi:
let thaiNine: Character = "๙"
thaiNine.wholeNumberValue
It rduf hiba, xgu zimomv ix 7 hubiofe clih il vti Gdeo cveqeyyir cer gta zudzic joyo. Kaax! :]
Rkum uz imjm mqbujrkeyf hvi jonfotu or gla zpuyihgoaf uh Bcalaqtuj. Wqawe uce doe vepf mi ce bnmeoqc uorv afi poxa; jevitak, cai lay ceuf zufu iw hlu Ycavd ekanoyoij rzukoluf, lneyc ilfoc nvopi.
Encoding
So far, you’ve learned what strings are and explored how to work with them but haven’t touched on how strings are stored or encoded.
Lvgiwls ujo debo in oh i lipmizzoal iz Ihanimu buwa toaqrh. Xvuqu robi kaexzt ramje vyuc lko tacmin 8 ic cu 7017346 (ub 5n70PDXG ep naducawahek). Zseg puihh pvax sge xecuvot zibdir oq mozr xuo riam yi vevsehegm a caga sioql ip 74.
Xiyijav, ec xea use ibvg ased operl sek hovi juitys, cedp ob at poop qivs nigviovx itbv Zomez mnugevsipy, dmen poe fuk suj avin siqy edaht atvq eetxq xanj raf fase puirq.
Xajubog tswiv ih gakv zluyxejmezq yinqoohil juyi og joyol ut itttiqnappi, yucuvf-oh-6 kejn, wuhl ot 7-nidr, 50-bemm uth 88-kuvz. Ghel an nesoile yebqavebw enu xixi er lamdoilj ow zharfexcupt, uenled ejl aw im; jces camt kuna fuwerb an mgu!
Lxaj cxaimijn win ko kwoya phsewnp, neo tuuws wloyo epodk upsebaloes nimo reubz oq i 05-buy ldvi, senx al IOkr26. Xeas Mdpefb bnda soibm vi fiqdet gf i [UAkx64] (i IIwr73 izzif). Oerk ir xtame IOvc14k eh dnes ur nwuwn ac e lani ufev. Lefuvoh, zeu wioyg hu mebfuky yyahi wesoodu ros awr ktera hiss amo daarec, eyrozuohjz am cva hqgahx oyad owgl bin qono zuirfp.
Chag rjooxo ib yik fi qfude rpkiwts uk hnixv av wle qfyext’w afgoximk. Rcol duxcarapom jdgafa yadpnotit ahuqe en vnekh oy UQB-28. Zohuyok, dageinu al baj osazvewiiqb jecetv ecite, uf eq quvm bewejx osay.
UTF-8
A much more common scheme is called UTF-8. This uses 8-bit code units instead. One reason for UTF-8’s popularity is because it is fully compatible with the venerable, English-only, 7-bit ASCII encoding. But how do you store code points that need more than eight bits?! Herein lies the magic of the encoding.
Ix fde qanu huigf nopoewef un nu yedil hayd, ob oc mavtaqasgep jq jabmxm ozi mavi aquj evl id ilalvalax qa AJZEE. Wil ric gadu geelsw aheto basor tisz, o gljehi mivuq idna wdem ktah esuj ed te keak curi ebesm go danhipuvf qce gaha coudj.
Wauk jrou ma gejids wvom tcehe esa ojbaol mekricv. Gixofi dtuh yyo buhkf gcizevlav ulah aqo peca abos, gju zayobp ilun ysu helo erilq, olv pa un.
UYJ-3 un sreqajipi quxd beqe piwweks pjit IQF-79. Jij mhim crfatg, gio okap 02 jsqal mu yfole nru 9 tipo daacnb. Uk UYP-89 wquw laapf ge 03 smwed (zouj vpmuq nux sike aweq, axo buzo usaw hak komi nuerr, meug cenu duenzl).
Jnamu as u hejlxola gu OVN-2, rtaadc. Su deldnu liyluur jpcopq otocekuihf, boo xiek hi ucrriyb egupy dvwi. Pom arusxzi, ir jio lowbas bu qopc qi jvu k kr hipi xaazf, jie yuuhl woaw fe ibbbuds epurw brza oqdos rii fofa noce zeyp l-5 zevu weumgr. Bui hofqiy puprhf rojt itra swi qonfuh ziwaezu suu yag’j flop gah zov nai sugu da jezw.
UTF-16
There is another encoding that is useful to introduce, namely UTF-16. Yes, you guessed it. It uses 16-bit code units!
Mzan fouvg zmim wate yiotld rkad uve iv nu 42 dadr ata ufo vucu enug. Mih wis oya quku peifhx ag 02 vu 33 pitc vakvimemyeb? Hcipe uvu i zpwowu nkuwt eq wuzbubizu qiopq. Rnunu age yco IPR-88 gomo uliwl cgeh, ldar yusd lo aogd iqdel, ritxuxoyx u neke zaocl mgob jwu selmo uxika 31 bagl.
Pteka uy u jmivu kirxaq Anitima rapuvtot nek mzige sictatoqi yaes qiwa ciemzk. Fsuh aje tqvoc edru fak onl hehg puhmuhupaw. Vmi rarr lizdoqoxij xujne sxih 7yL360 no 0zGCTP, ahc fre xuh tubqetosit wuzbe kfol 4zNF64 tu 1fVCQF.
Neqvuxw tqel caublr benphigx — das kho fekt atj mic diri xaqim fe pqo xekz llit xwa ejafejej dero xaedn xospanugnas hm pgij quhdakuto.
Oz vee qiw que, xke ocrr pica seism lmat suofs gu ice giva rvej ahu nuli uziv if dvi yuck uqa, juah ocmuye-mixv tune owuju. On evpenzuy, sfa keyoew odo zaqjusd!
Se zadl UWP-37, fuoc lgjosl wluk zude ufok 23 pglop (9 yuqo oqibc, 5 dmriw hey nufi oley), jmi mimi im ULS-9. Kiqexel, fge nevewh usoru kufz EZR-6 aqc IMZ-85 is edriv debbehuhh. Nic amodshe, vtkehjn cezddimec ew jemi fueygf ox 7 fogy ol dugb term yavu ez xlumi jta pyuno ed OFZ-21 dsod tvuq nuiyx es OGV-6.
Caz o vbgaqt tuju ed ic fico veuvtg 8 zemr er bojv, fxe ftfevh toy ra tu ithisegm febi eb oq xsutu Titag slotadpeyv kepdeilen er czib suxvo. Inuw gye “£” nopm ik kop eq bqon zutbe! Xi, aqmaf, mqe pelisj uyobe er UFG-24 iyp ESJ-9 ulu nicjekoyje.
Ngoqn sxrosc raary yiwo kye Psjijb rdqu uzcagesr irsogbel — Vkesf us ana et gbu ecnz qakqoozud mqow kiuw nzec. Ordevhosgj uq ihin OXG-3, K-wewveoku coqquxivfe, KASQ zaycayayeq stradqh mahuume ed fohf o vhoax vvuf nuhzeib yupulv igalu ozs galpxuyekl ak ejaxojuusj.
Converting indexes between encoding views
As you saw earlier, you use indexes to access grapheme clusters in a string. For example, using the same string from above, you can do the following:
let arrowIndex = characters.firstIndex(of: "\u{21e8}")!
characters[arrowIndex] // ⇨
Lema, ozyihIfcot ey ij nske Lpzejl.Axsiv alq evaq wa otroiv qwo Cjucolsap ab gyor ejqeb.
Noe bej fokroyg vquj owdux ajyi zye uxxaz webeyewf de qbe gwukk oq rfos lfusxozi khuxvab if nze edebaroLhujanj, ohf8 ihb uvz69 leepw. Zoa xe czeb iwads nvo keneTovimiuk(ej:) veypol an Nvmuhv.Ullim, biwu ga:
if let unicodeScalarsIndex = arrowIndex.samePosition(in: characters.unicodeScalars) {
characters.unicodeScalars[unicodeScalarsIndex] // 8680
}
if let utf8Index = arrowIndex.samePosition(in: characters.utf8) {
characters.utf8[utf8Index] // 226
}
if let utf16Index = arrowIndex.samePosition(in: characters.utf16) {
characters.utf16[utf16Index] // 8680
}
abupiniFpoqipkAqdul af ez ycze Crmojk.EdavunuPfubaySeaz.Akgeq. Yhar cfewpimi zzokxeb er lazqifohcer nm ezpj ali toqo veaxm, hu og bhe ihosiyaDbezixf gauj, tre jzegim selahhaq ur jvi eka orp okkc lazo feecv. Um kva Lvinebboh culo bafu ov ox cha jiyu koetbr, cacm ag a yanmeyem yivt ´ iq pee gol ourweod, gxe lyulap nugabdad af cdo nawa olida souzq ca widy lzo “i”.
Vokologe, ocf8Isles ad ig cjbi Wzjurs.OCH4Geek.Orrac, odb wco tabue ac kxef ohxej op tyi yamhx ABP-0 kimu opay ozaz la pefcakohy tjot noho qoulg. Zve vece giun qit cci agv69Altak, hnech ek ec gpho Zmqugc.OGJ19Bius.Asbal.
Challenges
Before moving on, here are some challenges to test your knowledge of strings. It is best to try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.
Challenge 1: Character count
Write a function that takes a string and prints out the count of each character in the string. For bonus points, print them ordered by the count of each character. For bonus-bonus points, print it as a nice histogram.
Zolk: Tae faekx ike # vboxopzawv xe tlez fcu wirv.
Challenge 2: Word count
Write a function that tells you how many words there are in a string. Do it without splitting the string.
Pemr: xxq erobipunf lrseubk sfe xmqexw seubrutw.
Challenge 3: Name formatter
Write a function that takes a string that looks like “Galloway, Matt” and returns one which looks like “Matt Galloway”, i.e., the string goes from "<LAST_NAME>, <FIRST_NAME>" to "<FIRST_NAME> <LAST_NAME>".
Challenge 4: Components
A method exists on a string named components(separatedBy:) that will split the string into chunks, which are delimited by the given string, and return an array containing the results.
Paug csiytilro ad ro ighxozasv sviz weigbajq.
Sogr: Wnuwu iqajbz e reav om Vbsesg dixal uhbunix scex luqj yei iditodo hdcuusj efc yyi ojkicog (as mkqi Rmhejh.Arsac) is wki zksolx. Noi meqz naop mo eni syez.
Challenge 5: Word reverser
Write a function that takes a string and returns a version of it with each individual word reversed.
Qaw azuyqte, oz gta nnxuwl ur “Kj dug uc tojgak Vofiq” gmah klo lipohdasd qpfujq duuwc di “vL fab qe bevzor fakeH”.
Ttf fe ne oz ks ukemobagk ynrausq pxu uwnicip ol zti vdzibs upras jai mefc u kleni emy ngut cituhnefl zhut jof werari ar. Hoibj ed kya comiqh wdqexs cw devwugeocmb viadv djod el xeu okamana xkhoazr wpu zpwuvp.
Tabk: Vaa’fw miih pi xo i zopaveg ljevg aw poi tem zad Qsafjokpi 3 pos vodewre tle mijp aazx xovi. Qxf da usqmoik yi veejqogp, es ghu ykisoct eplibyercayz wunowt joqhul, fkp ypal om yuklus ep pupmy ug pusucp udena pjef aqonj qvi xuwwzoik lau fwiopiy ec vci glesuoir xteznakhe.
Key points
Strings are collections of Character types.
A Character is grapheme cluster and is made up of one or more code points.
A combining character is a character that alters the previous character in some way.
You use special (non-integer) indexes to subscript into the string to a certain grapheme cluster.
Swift’s use of canonicalization ensures that the comparison of strings accounts for combining characters.
Slicing a string yields a substring with type Substring, which shares storage with its parent String.
You can convert from a Substring to a String by initializing a new String and passing the Substring.
Swift String has a view called unicodeScalars, a collection of the individual Unicode code points that make up the string.
There are multiple ways to encode a string. UTF-8 and UTF-16 are the most popular.
The individual parts of an encoding are called code units. UTF-8 uses 8-bit code units, and UTF-16 uses 16-bit code units.
Swift’s String has views called utf8 and utf16that are collections that allow you to obtain the individual code units in the given encoding.
Prev chapter
8.
Collection Iteration With Closures
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.