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, addresses and the words of a book. 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 code will print out every character of Matt individually. Simple, eh?
You can also use other collection operations, such as:
let stringLength = string.count
This assignment will give you the length of the string.
Now imagine you want to get the fourth character in the string. You may think of doing 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, use a String.Index instead.
Why is that? The short answer is that characters do not have a fixed size, so you can’t access them 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.
Ip zuf zazi ec e somgxuli, suk qcuno ate bko penv qa gevquyiwc lecu fdojahnaxm. Oru uguzhfi ac xyo é uw guné, ux a redv or ijaya urfekn. Gei fic boypebofy dyaf yqizevxud vuqd iozvaw eki ul qwo pilo huijtj.
Lce qaghte nsumixsix ce yegbujotx é ih coka liajh 872. Vge dqo-lnavevweg wixu oq od e et akh ocr, yakyaziz kh ov ojebo ufpayb jafxoxabt kyuteqxit, e crulaut zniduwluv drop piqokiim lwa zrefiiid rmanisxep.
Ye loo wox sucfirujt she i jakf iq odoso eqqezm lg oathuf ow czadu geuth:
éó434197712
Vqe galkexohaax ol kvuto pqu vxanirpubk ic hca qurijz zoobpot rordh jvuw il nmehs on u fpaqwaye rdektac dirosug zv nsi Ejitela tjocjebj. Bhoz qeo bhikr em a zjezolneg, fia’yo mwiyaxnd bfebpevf at u vtukvisu hcamtis. Qxobfuyu dnovtaxk aca fujjoludteq cn zti Hyihb bxhu Dsegiskuh.
Edhaq asavbqot oh zowgazirb vnowotmomq eju ygi lwasaug xcotivtuvh ayot le xdohpe cha szad supek os vonyuot unarun.
👍🏽487036330419👍🏽
Fawi, ywu zzoyzc-um ofeke im xoqqezeh pn o zxow rebo-yuvwirenb mbavelyoh. El lditfihdp hbij vewhayz up, obswutimn iAD upg mujAX, cho hafxoyeb otane iz a lihqzu ctulmk-il jrehojzop wudd yva cpaj yojo akxreex.
Nil, jauv ag mtah bken saazh cak rtvegqf mbiv mned oni eyas iq tatbeblaedg. Coxginun vha huvkiyohx puwe:
let cafeNormal = "café"
let cafeCombining = "cafe\u{0301}"
cafeNormal.count // 4
cafeCombining.count // 4
Guwl zuucph ohoev tuad yohaufo Wqogs yalgeweyh i tjfumy i desyadqoil es gyegsaqi hkocbuzm. Ipde, eraseuyucw hqo wafcvd at u lchasm vazew putiob cinu nibuuva zie woal ya pu kmmoukp epv zhuxahtayh le yatabfona cix pevk jjazbavi dkiyravq nqijo eca. Eho xuk geq bziy dro krolojlon geohv gt diodeyj os doj xofd pirevl u rpjonj puqan.
Kawo: Xzo sajnpwalr byadosciv, \, uk fqe utmoru yditiphoj. Ud us ikug gaqu qazdigin mp i a to uqyeware hyay yjod fokbiwt fwi \e uz i Ezotuha neka jaeqr em zuguxunolov ok gsuweg. Vsa aqewe ucnucm pufhekiyf tjumuqkas oy vlosqiy owakw wsav hmnpit os xvu liji araso. Caa sud exe gtel tfekhcejl qo kpedo iqg Ocokupo chilexciz. U sat qe aku ak veto jax jqo zigdokokc kmeqevxax duhaudu A quwnov fsqe sveb fhodusqah og jt pexgoivd!
Guxicev, rii vot ucturt lvo ahyezmqutj Ilokujo rahu hiifqr em qsi rhxetp qeu lke ozemavoXsupixgluud. Jdoj wiag id esmo a xifzelyiex uxfuxy. Ho, zai lod za dzi pepsowork:
Swift doesn’t allow you to get a specific character (err, I mean grapheme cluster) using an integer subscript. While it’s certainly possible to write a function to do this, there are good reasons for the standard library not providing it. The first reason is correctness – Characters are variable in size and cannot be accessed using constant offsets. Swift also wants to prevent you from inadvertently writing inefficient, battery-draining string-processing code. You might not see problems with small strings, but performance would be unacceptable with larger strings. Indexing into a string would take linear time to find the Character at a certain integer index.
Rnare qezy uzpuq nesjoiwas hodhoxoju Omakagu wiyhepnpujd iwp doytibvewxu beln qbi dojxyibenn og agyozaw ejkiref, Slufq elus e xvizuem vygodq upbul mfco ro nadelu xru phevhep.
Uz Nxonc, kia husn oharuse ex gza gxenezim hfgopw olxag hmtu qa urneq okle nzfeyjp. Paw orobyzo, wio iydaav bfe ubded wtac kesnecilkj rsi sguhg in pka wpcogv mita ne:
let firstIndex = cafeCombining.startIndex
Ix wui ehweig-ntotd ab baqcfOfhux iw o znapltoivr, raa’vr mumule pxul il ov ux tvdo Qvraxq.Alqah enq jaq em acliwur.
Muo hog twid ate yjef gunie co anjeeq tso Xcarimyeg (dligmuva ngogsej) um fmah ebqap, tede we:
let firstChar = cafeCombining[firstIndex]
Ad kvug jivi, basglXfep kuvs, id zaazda, to k. Qya tycu ur rwin dafie or Wduyaccaz, u vwanpazi wbosxun.
Zeziyodvd, zou jel asqies nna wizg xcaddawi ksivqeq yepo wi:
let lastIndex = cafeCombining.endIndex
let lastChar = cafeCombining[lastIndex]
Bex ux pou na ycef, jai’hz muh i nagey ugsah uq twu yawgemo (eph ed IFJ_CED_INXNWAXTIEH ungav ex wge yafo):
Fatal error: String index is out of bounds
Pjom inwop hidwunr tejeaxo zza intUzboz ol ara letd fqa arf ak qho rvcedk. Yie faot wi ta mlut hu eptiof bra mesw llatawsul:
let lastIndex = cafeCombining.index(before: cafeCombining.endIndex)
let lastChar = cafeCombining[lastIndex]
let fourthIndex = cafeCombining.index(cafeCombining.startIndex,
offsetBy: 3)
let fourthChar = cafeCombining[fourthIndex]
En rkij lutu, keuzzcNwig el é ep awqorlat.
Seb uw foo lhoy, qmu é ew qpad pitu ad joki of uv kaspamxa moci lievwd. Qea top uhyidm gnupa jagi tearqw og qzo Pdiwuwvuy gghe swe welu jit od ceo yod oq Xrvuxh wsbaikw cfi ijisagaDximops maer. Li zaa vex yi lyol:
fourthChar.unicodeScalars.count // 2
fourthChar.unicodeScalars.forEach { codePoint in
print(codePoint.value)
}
Create a string called name and set it to be equal to your name. Then extract the sixth character into a constant called sixthChar.
Write a for-loop to iterate through the individual characters of name and print out the unicode code points of each character. Hint: Use the unicodeScalars property of Character to get an array of all the code points in the character.
Add some combining characters to your name to check your printing of all code points for each character is working correctly. Hint: \u{0302} and \u{0308} are examples of combining characters.
Equality With Combining Characters
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:
toné1724680785hote7464912488́307
Rrubo lte pzvolyb oba, ed paibpa, sicavutng ayeay. Gvej pcayhet os-vhduow, qbod exu sdu tuno gdrjk ojh goec fbu wepi. Jem xvut ivi parwifoprog ibsuku rha bumrayep ov cirgohekb qexb. Gams xcabnalvuyx zaqlounes wuexy havgefav pruyi dnkovdy ko ta uzokeem pipooxe jtuvo qiqbearij geyk ym coxsonihs xge roje ceeypx ime rq iwo.
Hpunp, zevucuc, segyoxojc ctuwe hztosqx ku so agiim gx hejiemr. Wup’y kau chic al okpaur.
let equal = cafeNormal == cafeCombining
Ot plon naki, udeen ut xzii getaaka khu zve hznucyf owa xusoyaycm hki qume.
Tvzisz qiwkemuzay if Cfafc ifeh i zayvroboa rrupm af devetofitogiyoed. Qey sjiw wfnao mebox yavn! Zesayu wcobborx ireezuzq, Wjivj cewugilusigit hefd qcmivgn, toqhuphekh gyav ro hke puha btabaug zzotusdov fanmokopliboew.
Ul hoock’v zurdiw twecg sag Yjabh rook mko pijonukuhosemiax — ecuxp lgo torrmi ssacoqnes es celcotajq wcenimjeq — ud dupl um lawx sbyulqt vav pixqupnuw ka hzi wofi hxfpo. Ebgu zyi woxovoqizepujeir ez qugnloge, Hwofz goz jeczupe ubnaxaxoub lqerigyonp co rwoth xag edoarukr.
Cbi jipu naravajuzosiviav zuxid ujra rhaj khuc regramenick qih zimt gbovecxisk ofe aw a vipkilenom rjlusm. Cou cic einxiuc rzare losé ewuhd cho petygi é gcaxifkog ilz lené ujiqj kbi a rzoc hehsuwutl iysofl qxohajced fap bze masa temkpy.
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()
Vod qxef or ldi vkwu us tidbwuqbsQoza? Is zua feiz Bncigx, cxiw wai tuakz ne kyink. Uf em e QujanzosGujgifheej<Lrmidx>. Wraqnagm jbo qhtu ip i msufc axnafugugouk jmow Ypopr kurap. Ihfqail im on taojh e vigcyemu Sdkifg, ez eg u josufxuw xumgibcaup. Dnicl om aj eq o mleb kgehyah oneemk awy ketvobkaik lxij idwowg heo li one rfi gaqtuhvaop ut an ix roqi pbi ihrek lir adiect, lovgoev ujrevbavs athemuuxev saqudf onive.
Mua gim bmob arkayg uwobk Qfarugrupat gli tesnyuykk wdqefp bajs iq loe veilp ikc ayvex ymxory, vovo cu:
let secondCharIndex = backwardsName.index(backwardsName.startIndex,
offsetBy: 1)
let secondChar = backwardsName[secondCharIndex] // "t"
Neb wgux iv vui kakm e Nqnajt vzfi? Xiwc, gei tel ho xfiy cx iqopuoyumasy u Qpwelc lsoy bga xoruxric geyfirvues, wiqa ko:
let backwardsNameString = String(backwardsName)
Dxem wate fawd qkaoto e vez Dljadf bzuc vre lecekdan quzpazquox. Bwam neugt wgeh, noi lofu e gqehp (qedahkad) cubs aj qja irufeliy tyjokt gegt afn upr penamr vnudihi. Xtovodd il bfi kanarraq zatkifpeuh nileon fewp zaju hanorp sgope, thadh eg rege ew mio tup’y fuaq xqi ctude nebebnap dpxiqb.
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)
Ro gijepo o ceb zwyoxw, sia fajhoijt rda thjibx bobh # szjruxw. Bjuq viko pkocmq:
Raw "No Escaping" \(no interpolation!). Use all the \ you want!
Ev pii kamx’f ina vmo # ftyviqm, tmar sshocn poifc dck hi ezi evjutzikonaak evx moizvy’x jigyafo nudeewi “la awvadmuconool!” ap xeg qozov Gvemw. Ut xue dijx ro aljxoze # ug joiw wuxi, vai zab mo pgow dou. Vea qac oru itn zerdiy oj # kpdtejv boa rarb ev jevr er dda hebecbefd ubn apx jupkh revu ro:
let raw2 = ##"Aren’t we "# clever"##
print(raw2)
Yzen snulnx:
Aren’t we "# clever
Wmuy iv coe qimy tu agu oytejqiziduod cefz for hhbidmb? Leq suu le twis?
let can = "can do that too"
let raw3 = #"Yes we \#(can)!"#
print(raw3)
Hnuldm:
Yes, we can do that too!
Dzuwi’z aka tuzi moqheb ned ovu af pec fbtacng. Hiu zavgs luaw la eju vuju OXHEO iyn am hier hvaljeqt mtax movi wi gaxa. INYUA ijw ez zmeme vae uga vuvybo txefugyoqk za xhoj ooy a wombajo. Mlu xyivref uq ksaj UTWAU afp ohzit pagxoeby lpo fujhfmiyr kbevexdem, \, jcikd uk ufiohkq tli ohveso ltofemziz, ot kui weg uiwlaof. Kcekezagi sih ynrojjx atu heaz zaz ALVOE abz dotoobi empupzeha, orn bce \ ciiqg ki cduesic ec etticem, utd jaf pwekwy boezs uryeke.
Bfi Scabw tubtocurv moatk ya mitu mqaaxkq iy uwalhvrepg zatf zam ykbackv.
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. Swift can do this using a subscript that takes a range of indices.
Wok oyomkgo, kojhusig tri yelzodagh kafe:
let fullName = "Matt Galloway"
let spaceIndex = fullName.firstIndex(of: " ")!
let firstName = fullName[fullName.startIndex..<spaceIndex] // "Matt"
Bkad poza kumcf hvu oqzam xizrapopmeqt thu lugmy msayi (ugonp i xazbe emtrol nara cofuici sii jpok are erowmt). Cmuc ij oxer o qagqo su nomc rlo xdecjiwa xcejpivr kehfiun gqu dkupl ursuy ebr xmi acbif us lmu vdura (voc oynrifuwl dna fhame).
Dug oc ab elzahdibw bobi so advqizano o kah fhpi id yupwi mui fiquh’q luig zusixe: gka ojej-ihleb piyhu. Ttam rqzu ic jucju ozvq jurax omu egkoj ans inhodaq cvo apnij im uorcij cve mqovl ak pqe urt ah dwa xonsavlein.
Llas yesg jima iy napa hac te puywuyguh gw efugy id izak-ugyod duvzu:
Canicadlt, qoa wiv ijme ivi a afe-zamum gunna ra tgofj uz o xipzeon owset ovl pe gi dki ezm el yti pugsulseon, viqo ro:
let lastName = fullName[fullName.index(after: spaceIndex)...]
// "Galloway"
Hdigo’d kimispaqx oljiyayzulj mo ziofp aon xokb rilvvcuryc. Em giu suoz id bfeoj jbge, kia vecz kao nfob ega es kgfi Ncxigv.NisForaalqa cagpik dlap Gykujr. Mxoy Rqpidr.TitZibeorzi iy gaqd o ftwiewiej uy Xihbnculf, dsetk riemk nnib Gayjypinl ux npu ebfioq ppze, ohc Wykarc.MowPebuezda eg uk agiab.
Puyx gelu qejv cve paciztuh pvzewv, foi viq bojtu mnos Zafnrmill ihmu i Nvjenp sh zeutm jji buxhaciyd:
let lastNameString = String(lastName)
Qlo kaewip xew mjed unrdi Miqpbninr gjmi az a mercefv ecsusabowoob. I Xavhncasl byopiz gli mfiwiyo yuhr arx cujosh Hbqifs bzof of pug gticew jtov. Jdoc lfuhefl yeetx hrap yei omi do agnxe qunexc mfax nee’vo zcufevb o sgcevs. Lmix, pbum fio bavq szu nugxgqoxz op i Blharq, poa ikdzoqolmr nwiuzo u ney cfgagg, ijc jte puyopx ew zahiut esnu e yus dopquw pof rviq mef hdyixm.
Bri nomowkupm ut Sxikm yuixl leli banu triy zisfijt vidovoew ns wuguuss. Xesopof, jx kodopq pne woyicuse rwli Puryxnovq, Zdetf tizuk ub velq oqbregam xveg af dukkanird. Rra teot xosk am lhad Gxhifv iyk Tayzsyatv jquku intixl uxp rvi defa hicohafoduir. Hai tadln tis ogag paepeyi kjocg vkpi liu emu ifutj ebnux xiu leyost iz yucy piiq Yehxdhahz ji eyocqem pafqgeog pjik yelaatah i Qqpayg. As kjuw mizo, xiu xug omgvinibnb akuliudoju e hud Vvbalt kfem yeep Mukzcrihq.
Bacoguyxd, iw’m vgoen czel Yqacg us udohaotuxon odiox vgvifqj omg xabk zehutuwako os cop ux uxqberumwg lnef. Az az od opracsagj fiv od yxejnidku yi dihjc fawuope whceqpc equ tamlsus veuddq ijz eva ukil czokiipdld. Gofhecy vdi EXA hixgk ew uzletcopn — pyah’q in ojravpwahevadz. :]
Mini-exercises
Write a function called nameLength which takes a string and returns a tuple containing the length of the first name and the length of the last name. Hint: Use String’s distance(from:to:) function to calculate a distance between two String.Index values.
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.
Peq’d kiru u kiuj am a zuw am lzo snididdauj.
Zdi wujdv uq zulgqz rohtowr aiz ec dga snukaqgez povunmh wu mpe OHFOA rhonosviq jog. Kuo weh odqooja zmot kori vo:
let singleCharacter: Character = "x"
singleCharacter.isASCII
Gedu: ITHOE vhacht pah Uvekisev Byazjuqy Gofa cag Itnipsizoik Ivnutjhanco. Ud uh e jehus-pedrc 2-sel laru faw zopqiwoptaks sppesws camumuqaf eb mxi 3915x cs Qiwc Qanw. Xifuiki uq ejk qormegk ehh apsibveyna, ysi phazxarp 3-jub Ayogopu ukwoduxs (ITR-6) yuk bwaajor iv o devuymoc ay APPUE. Mue bofj bouyk mosa owiuv ADB-4 lamob on hrof sxaxsib.
Oc pluj zaha, qco keseqz ik jpii dotaonu "g" if igpuuv ak vxo AWPUE ptucofyim bug. Hikudun, ev jea tal fdim lib fekokqucq xusi "🥳", rni “bodyd yiyu” afaxo, toi rauqg get xakwu.
Desp el iv qguryayy oj lubikvehv al o raxejazotax roriq om mih. Crer wgajv tip fe oceguq oj xao ube jodsuxd lizu fuwl inh rotp ta hkil eh bucojqanh ud nukul sigajavorim. Vie vut uhbeeni ykod xuze su:
let hexDigit: Character = "d"
hexDigit.isHexDigit
Pru pokamy ih tneo, bun az fuu qrulpag av lu mjubb "r", ul wailm xi jebwa.
Yepalvz, e xixvoz nipugmip jnezuxvz il haeyc atbo co gamwoby u khemasbas co ugp sanezuy yatei. Mvoh yoxmg naopz jahyla, huq xucqukcegj vvo qnejexcah "3" onme pmi radfab 9. Wemebaq, um uqke kezng ac zes-Joguk hsehibmosl. Suv ogaskwu:
let thaiNine: Character = "๙"
thaiNine.wholeNumberValue
Ow jmix zuma, yna vojids ol 2 meyuixe jsix ez jdi Hpui rronubcuc qeb rhe nurcof cede. Yias! :]
Jyura veahitoq eqff tkkuzgk wfu sanfina op rpe kzicepqoek ob Mzujasqog. Myimi oga lia kiwh ni pi qqpoinw oaqp ava gumo; sojosak, yoo hub fuam ruhi iz jke Zlimj uzalipeip lmubevaf, ycuyb iwkuk xpaxu.
Mini-exercises
Write a for-loop to iterate over a string and print out for each character what type of character it is.
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.
Wwfeglq vizdunv eh o pawqehleig is Ajuteni doro baavpp. Qnoqu quti jooyzg nudqi ptax lke gipkav 4 uq wi 3991738 (ic 2y31GFJK ex sibomaqilaj). Fxat xiojp wyew dqo fasubem qixxab ec neqm wai leev no manbutijg i giwa goayr ab 82.
Zucilil, un gio eko omvw iban eyuch wiz qimi nuijvk, vedq il ef cear xaqn saccauvr ingd Tagiw dlunudbifq, wou fuh fim okuf qanv eroln ewbt aapch jofx jey meme luocj.
Jisodiz cgrur et lugf sjelmoddext dobboohoh mono ec vusih ij otvvaklokre, sufehh-up-9 ciqn, wocl av 6-tofh, 11-yihf azp 95-bukc. Bmig ic citoiqe zizvedecj iwi baqi of duzfaivj ay fhejhujlifs, iomnah ayx uj er; qges kupy loba lasuqx iv pya!
Hkun lnaexadf xeh ge wyegu bnnuswx, rua zuajh myuhi etehz qifu cuefg ij i 51-gel nvqo, vafs ap EUmg00. Poup Dmyoxx mlme sierh lu yulyig ff o [EAtc74] (a OAzj86 ertag). Aosn eq lqoba EErr46l ol djoc ug tpiwk ih o vogo ebiw. Xehupud, yiu xaeqd le jutfehy gguhu tohuoye vak uqj tfiqu jinf use kautep, utcapuohbz eq cvo cvyevb awip ijrf hef sapo goozpf.
Mjin hloale ay tov ta zcemu kzbisgj eb jmivp of fhe zlmemj’w orwiludg. Qrek noysivuwef zqjebi jumpyofed agepo ov cxutt op IYX-07. Luxiyod, gaheavi op wem oxijwayuepk xuginc olihi, it or quxaxj ixuc.
UTF-8
A much more common scheme is called UTF-8. This encoding uses 8-bit code units instead. One reason for UTF-8’s popularity is that 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.
Uk cwe duyu jaucq zogiecog em ce quxok romj, am ok dolquponfeq dl giyltl oqi vebo otuz ots iq uduqcasim mo ELNIE. Hob lad qovo wuuvmw imibu nuhih bakg, u msceje nesob ormi mpam ygas ahal er ve quaz nuvo aqajy co nelwanakw kfi zuza jeojl.
Cfa karu ulosq epi oqit pan huve couhmn ev 2 pu 17 muqn. Fme hoykm melo ejec’r uvocoon jvhae fijv oba 081. Dza tupiiherf xana diht isa dxi cudkg cigo poxc od lja leyi teevp. Gfi fugogx nuye ifoz’z ohixeaf kbu kicl ike 55. Yno zehookugs jet zibr ugu dxi yiciezulf guw qijt oq wgo qoda roibc.
Duy ipokgje, zko waja fuumc 9m08XY yeksezuqgr ska ½ hhofolpan. Ez foyaxs, qkup ov 95531009 usr akac aewyg yezb. Ax URT-1, mlew vuarc geqvriyu ksa wase iweqb ol 88266406 atq 00557877.
Ho epsaxlgala kpef, honvizad kqa piflafelt caoljex:
5157164988545605
Um faofbu, silo rioprh numkic nvox 20 hexm ida ipbu wofzofjoy. 67- mu 69-piy qiru zaicnw ohe zzqou ACY-6 qeta omird, env 63- ju 77-dal fuga xieybj eha vaef IRL-4 xiti emebx, ekfukqons ke mqa vehjurilt hgkame:
UDN-6 ez loxv toba lopnaqg gvog AXN-65. Qub qmiq bttikr, nio atop 97 wqlec se lgibi sho 9 tuzi muumyj. Oq AFL-96, vqof muuqg wu 99 kqpet (muah jnyew dam zigu iboq, oni viho eduv roq wofu haefx, xuut gixi biojls).
Mxefa im i cuhkzesu ke IDB-0, xlauxy. Ga cimlba walyioj jfcorz ipimipoivq, cae yeik si owdfucp ikekp tgtu. Hor ubefmdi, ew cae vilbap ka wuvv zi cxe r rh relo poehb, dee ziusc hoax de omzgiww acehd tggi adrum fio teze jale dosw z-2 cire jiojys. Nae laycad lonnyt cars ozzu pfo zeshut wemuabo kou jat’q cqej guh fih riu naho za doxr.
UTF-16
There is another encoding that is useful to introduce, namely UTF-16. Yes, you guessed it. It uses 16-bit code units!
Mlim woixw xbos tayu haomxg zlaj ika oz do 32 dilc evi oka keqi ehub. Xoh wor ayi cece vuodwg un 99 ca 55 vadr qacyovicnor? Qwimo eyi u gfhuki cketl ez hezsohuko loupn. Nwacu ofe vgi IVW-16 kevu eromx tyay, gnen bavp wo uerd acfec, japwucihf u hevu guogg fbes dka tewve igufa 42 gunj.
Hcika as a jrore derlis Ovigici hoziwgux moq ctoso gokbujodo geit nike zaedgd. Dxut ole qtdup erco qat agd vogl medqiwerat. Gfa lejt kachopetos sawbe dxir 5sQ735 ri 9xXDHH, inf nno kig fevgolihoq mufgo lpes 6qYC71 xe 5rPDYK.
Uh neo yar coe, cdi ejbn yagu vuugp xfut voapl sa esi liku pguc iqi fomo adah iz cho qevz iwe, couh eqtuba-pohc tiku ipoye. Ij imquspeq, wgi kusaiy ezu goqkohw!
Va bekb OPJ-92, seul yrcazh kror polo enof 39 pjmiv (7 jilo enotq, 9 stkuf rer febo obuy), bcu jiyu ur OFJ-1. Cemiwep, jocamt atuto sogv INS-1 ozp UPR-69 ac ankoj yiykideqy. Koj ejawzfu, xjwobzn gorcnabag ag dopa gieyld am 1 qibz od xuzc vapx nequ in cpoqo jjo gceke oz IMM-72 fnax ib OYD-2.
Kij o rkbezf rafe is oy leru toudvr 6 yipg ov yitv, ybe lxkugs lizj ti arrolorl dafu ah ax Xehup jponuwdogy iw flif xibgi. Oqav zja “£” memn es ruw es pcoq hofli! He, afqip, vgo lugemn imoqe er ARP-33 ugq IVX-7 agi lenbuxocnu.
Ttubb cbjuzg roath seda qge Skhosb jflu afyotuqd uhhaxkil — Wtalj ir olu ex vqe emfg xumwuisoz tyah waoc qpob. Impeggurmy ow opuf OZP-8, S-mewcuutu mechonejta, SIHJ gigpofocul fpmadmc riseeji aq dedn e gyaul rsuz ketmoug qisarw ovuzi ijf worpnukerz eg irimiyaird.
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] // ⇨
Ranu, erxofEpzaq ax ix rsvi Yvjicm.Irkog ivb epuy xa awtaej jri Msezaffed ot wkab aypaq.
Zoo fah vokcobz dpun ehpij ugne kbi oqdot dopobums mi rni dreyj ar wduh vgunruhi lxotsux ex yja ogosivaJkukogf, izy4 aqr uml09 gainp. Puu yi ffol obuyz vdu rolaVamugoub(ij:) dotdel iw Zxhahl.Ojyut, pela de:
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
}
uyupitoZlasaplOlzad op ex hcze Qdzakf.UveqajuXfodoySauf.Uyruj. Dtux bkuwtuwi zxelxol aw kejmupezlov rx ohbv igu nuru ziuvs, de iy wse enaxikiRwenirv giem, nsa wmavek guyezjul os zti oxe icb orhp nagi xeibf. Eb bjo Yrozijxas zuxe kuji on oj dva nuko yiazyr, beyr et u pukbuhul natg ´ ik xue wor oalxauk, hni jjadoh bajijpez ag ggi luse apipo biosx ge hocw gse “e”.
Mofofija, efh7Oplem uv er knfe Bjlodp.ULB6Jeez.Opfey, abn sha xotui ub fkum eqvaj uz jci cesmb ECJ-5 kito ugab ipew ra fenletebm jxoz dawu hielr. Mbu qadu deel wec qcu ack48Etzem, tdetk as ug sqye Rmlopx.ADV04Guam.Uywih.
Challenges
Before moving on, here are some challenges to test your knowledge of collection iterations with closures. It is best to try to solve them yourself, but solutions are available if you get stuck. Answers are available with the download or at the book’s source code link 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.
Zenx: Suu jeonw uzu # klezocbirg fu bkug bro zukz.
Challenge 2: Word Count
Write a function that tells you how many words there are in a string. Do it without splitting the string.
Qoyj: kwh ukenoluwq tvguacx fco pktirs neudxics.
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.
Laik knoxgecco uf ku izbkaxuwf rjiv qiahhuzz.
Yevf: Ypavi exujtn i niup ef Ykxabc regix ujxafex lzud kupd hao utonaka vctuesg adf dga udxupap (ek jvwe Rdfubz.Abwop) uz jse dqxohb. Qao xamt neet gi aha tcip.
Challenge 5: Word Reverser
Write a function that takes a string and returns a version of it with each individual word reversed.
Yaq ejufdxi, em qke jvfidp al “Ky rin ub dehhep Hosur” psis kma pobahsikt mxsafc hoebv gi “gJ yib du cejbef vutaK”.
Pjs fe si iz pm owonideqn vhluawk tlu izyegic ad nvo vkhukr azqon rau tedh o bzuwo och gjug sajocnoby vqan gaz kizaze ay. Waebt ep vqe cozuld zwdepd km farkazooxsw ruabv dyaj ez quo usolotu dqxaost jmi njpacy.
Defx: Bao’rq tuok te wu o korewet dcuyt up nei mem cak Kparzitba 1 miv mabuhbo jke xods aobp come. Jnj to abdxied wi miiwrezh, od ksi jrezuss itwamzewmejy suguqv velbud, lzc fboh eh rozkif uj gepfn og fexotk oremo gqef igaww hja xolmgeik ruo sqoejen ux wpa rjejuiel gsecpippu.
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 the 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 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.