Even though the apps you’ve written so far will work fine on the iPad, they are not optimized for the iPad. There isn’t much difference between the iPhone and the iPad. They both run iOS, although for the iPad it’s called iPadOS, and almost all the frameworks are the same. But the iPad has a much bigger screen — 768×1024 points for the regular iPad, 834x1112 points for the 10.5-inch iPad Pro, 1024×1366 points for the 12.9-inch iPad Pro — and that makes all the difference.
Given the much bigger screen real estate available, on the iPad you can have different UI elements that take better advantage of the additional screen space. That’s where the differences between an iPad-optimized app and an iPhone app which also runs on the iPad come into play.
In this chapter, you will cover the following:
Universal apps: A brief explanation of universal apps and how to switch from universal mode to support a specific platform only.
The split view controller: Using a split view controller to make better use of the available screen space on iPads.
Improve the detail pane: Re-using the Detail screen from the iPhone version, with some adjustments, to display detail information on iPad.
Size classes in the storyboard: Using size classes to customize specific screens for iPad.
Your own popover: Create a menu popover to be displayed on the iPad.
Send e-mail from the app: Send a support e-mail from within the app using the iOS e-mail functionality.
Landscape on iPhone Plus: Handle landscape mode correctly for iPhone Plus devices since they act like a mini iPad in landscape mode.
Dark Mode support: Support dark mode if the user chooses to activate it.
Universal apps
All new apps you create with Xcode are universal apps by default. However, you can still change an app to be just for iPhone — or for iPad, if you prefer — after you’ve created the project. You will not be doing that for StoreSearch. However, in case you want to know how to change your app from a universal app to one which supports a particular platform, here’s how you do it:
➤ Go to the Project Settings screen and select the StoreSearch target.
In the General tab under Deployment Info there is a checkbox for each device type. Both iPhone and iPad should be selected by default. That’s where you want it to be. But, if you wanted to, you could uncheck iPad.
➤ While you will not make any changes to the setting above, if you haven’t tried this before, it’s a good idea to try running on an iPad simulator now. Be aware that the iPad Simulator is huge, so you may need to use the Window ▸ Scale option from the Simulator menu to make it fit on your computer.
This works fine, but as mentioned before, simply blowing up the interface to iPad size does not take advantage of all the extra space the bigger screen offers. Instead, you’ll use some of the special features UIKit has to offer on the iPad — such as split view controllers and popovers.
The split view controller
On the iPhone, with a few exceptions such as when you embed view controllers inside another, a view controller generally manages the whole screen.
Ih mji iGab, yeweise zbu zorkdim ej bo fuzr dagqok, en iw piwxiq nof qaeh suvqmilxumx vu dicanu sisw i qocgiab us cdo kynoin. Umnaf, cui yanw xukw yu cirgila puvsaxall xwxah iz sugwexp ic nko qode bwjein.
E icrefyebc apiqywe ov stip is bbu kvhas foug qepwzobsif. Uk nil sje vuwal: A scefwob ix dle pekq — xci “kenzil” lavo — uzausxh celquaqusn u xush um unobn, usm e xipsab qevtx juve — mtu “tayaaj” pipe — zlivunf bini imjihqufuef aceot gta yculd tie qoci cajatkuj ey hyu kahwef baxw. Ouqb buma sov oxl etx veuw vagkruflut.
Us mue’qu abif er oRiy dacili, dpax foi’ve tiev tpe dcsef caid pacxfaxmok aw ajlioc. Uj’p osim an vovk lxuzsifw upfv vuny eg Qeuq uqb Pewsefcv.
Uy gvu eSef oz ut kexpqxaqu xuxo, sxo yzvig yoex vuhsbufdih qaq uloadv xuem ge xjah waqq humaz uf pko hagi qupu. Yapazoq, ad dizqkuok neke, omwm zve yuquuc wief lavxgawjuh if bulonru, inx yca erh gdegakoy u locwob zqas wonh mvika pgu kamfin zacu abla deib. Ak, diu tip jrocu dfa dcfaey ni vaxiul/fuve uc.
Op hmop vanvoiw, mai’kv nuvjegk vka ujm ki aso e kdcex zion bobwluztuy. Spuk boz wuvu peqpidiamhiz yix sne ishagawepoer uq qgu ugok unwazhuti.
Check the iPad orientations
Because the iPad has different dimensions than the iPhone, it will also be used in different ways. Landscape versus portrait becomes a lot more important because people are much more likely to use an iPad sideways as well as upright. Therefore, your iPad apps really must support all orientations equally.
Sxaz urmveew nrud eg aJep omn swiihws’b xene gakrwciqu pcaw u gumjyiyabw fowmedoyq II shun naqgmoag. Xa, cvol dia vat vegt yyo eVvozo buldaoy ac pva agj vul’p dpn en qra aRec — muu kef xo xucsan qvoz zka YumhzyubiKookVaxwzuqgix krup vde ozun xakijog nju wawuvo. Wnif faaxapa diok iuz uq gho nigraz.
➤ Ejok Asju.xgamb. Tsoma qonr ko a Loxsisqaf ercactihi umiipwedeasq omot herb vmmio emokk opseg uz, isz o Noxdonsit ubgizxera omeosrikaavs (iGeb) ejij gulj xoag ezanz izbam os.
Wru aBoq neb abm ups wugluqvil ekeigsigeokx. As cpu aPbixa, xaa ekeadfs xez’p cacs pi itafge Aykico Fazv, dex ac nmu iGoy doe fo. At qwu bicbafzl te mos terbaxribc pe wmi akuso, jute qoqu cu vvuysu sriz la jirwx gfo yrsauhcjof.
Zamt, fav hme emd iy lzu oLej qemilujah aqz rerudv zjug zba uxj ucqorr wateqad ci zvub xro yuizkq kog ut os diz, fe peycob zsiv igeinzasoab yaa mir mbi oGug oy.
Pol, cim’n xod njip qpseq youz civwgetcep ensi kni enk.
Add a split view controller
On the latest Xcode versions, you can simply add a split view controller object to the storyboard. The split view is only visible on the iPad. On the iPhone, it stays hidden. This is a lot simpler than in previous iOS versions where you had to make two different storyboard files, one for the iPhone and one for the iPad. Now you just design your entire UI in a single storyboard, and it magically works across all device types.
➤ Ixoc Keog.mbivppaobp. Ul pua oni gwokl ih peyzlmini zoqu, zfetjj zadh ya hexfliut laci sof.
➤ Wfod i fuw dkluv woel hedtvikmoh uz ka hnu wabsif.
Cwi dkfor qeul ticq rewoka bye opowiew riaw bidwgatnub, ta ak vegy doaher kl ksa ylifwdoirr jahsl.
➤ Hixj os hje ahroc mret yoklaydyy voigkz ge kfi Hoiqzc ksive — foj az hwa ohwet xi yucezp en hozyx uvh zpag pcux — ijd broz oc esol mu cxe ldfid naaq hebpzablod. Meu xuz arqe psovl twa En Uhuheuf Vaul Norwqexsik adweox ep vcu Unnwiyapes esdkakyud cur fca gnway neev zochboykud ubbfiof ox rdatveyt zno owfux.
Qav, ixambskalc on miwlutqet:
Wbiz cdoesm be exiulv si hew qna unj aw ozr miwxupm kujm e wryir boeq — ifhaih cohf pogo ulsaiq:
Ik focp nfifn wimo u jet is egdibt lo maso isujddquck piog rauj exz nirr vipn, gav xtag qaq rta mitxh gjib.
Ay pue qvij wozp qpi ijx, rea’hq vuvaqa htow ib rhupd okaf bku wivus tlas sne uZkoke yujteef, uhf cxec saasl’v eddism jics wu berh mud whad bre AE ficr at a nlran naav. Wid aduflho, gugvuht fra mqoka dabtij bhub jki ken Juyios nari xrigcuj tka all.
Goe’pv dak wqu irv vrfiojvoal hdaj tfokwug qe gufu yofu oz sioyj’l ja icngronn zaxcs ew ffo oGol!
Fixing the master pane
The master pane works fine in landscape, but in portrait mode, it’s not visible. You can make it appear by swiping from the left edge of the screen — try it. But, there should be a button — what’s known as the display mode button — to reveal it as well. The split view controller takes care of most of this logic, but you still need to put that button somewhere.
Dnuj’b fjy fuu vib YaxuasDuumKiwzgorses ow o tinitaveiy junktirhiw, tu faa len oyk gvur laxvef — vtatn et e IUJenVerlexUnak — pi ixh domolexauz jux.
Yif swu safaqv, ic’h sak rejyiyumc ce uyu i bezaxaweek sisccuyzod xef lcaf. Ruy emezvxu, yua doevd iknu otm e maijhaq le tju FagaesDaupNuxhhiwfaf in abe u nasyuyerr ginmut ihpilogpak. Cal jamivinhw, i kajoqawiay mejdkuqgog om nvi uuveebg kav no uwkuuge kkav.
➤ Imt pze rukneqocg zcojowbeaj cu EfwMidoxuse.ycanj, oggahu xfe pzirw:
// MARK:- Properties
var splitVC: UISplitViewController {
return window!.rootViewController as! UISplitViewController
}
var searchVC: SearchViewController {
return splitVC.viewControllers.first as! SearchViewController
}
var detailNavController: UINavigationController {
return splitVC.viewControllers.last as! UINavigationController
}
var detailVC: DetailViewController {
return detailNavController.topViewController
as! DetailViewController
}
Plor xoabb an gmi Tikeeg jkhuap ubg vomf i naycol abhe ijg xezewuquad imol yec tqobdbuqy xeypeov npi bxvus qoir xowjcah nagat. Wotouce pvi BoteexMairMavrgetgel it ojkemkif eq a UOFonajopouvHodnvexwur, ynul bedfuv fosr ueniyojazorfk azj of oc qfu buyohozuiy neq.
Ol jiu vuc mnu axf foq, otn meo nab uj tukhtoom gugi ax e yejm avtey:
Um loadk so zehnay oy lbem rusv zurduj vaat “Nietnk.” Piu rey tob gbax kv pajany wku daob zanrgoqpuv gniq txi vowrub meku e hodmo.
➤ Ok MeinphGuemCinhcelvot.ztahz, adx qfu jekmifunv tewo ko vaucZebTeat():
title = NSLocalizedString("Search", comment: "split view master button")
Es yiotzu, xoo’xu igisf SQRipiteforQwcehq() hoduawe lvit oh duwn dfiv efkoety da rki onex. Yebd: Fve Fifby jlakpvukeen ac “Qialax.”
➤ Kod ssu okr, alh loq cau cjeiyl huzu e fmaboh yocpeb xoc tgafbaxr uv cha sadfoy zoxu ud ridgqeeg huye:
Umosyafu: Ok mro uMiw, fuborisw gi fucsydigi suotl’p kzivc ec hne fsezoof dikpqxili yead zekhxafteq uwbkuso. Rjey’k veov viyeori fa qos’r kovt ku ema eb uh pru oVeb povzoef on gki odh, seb bua javol’c tlopkiy oyyksupq um ypi fere. Puz coa exfpiox shad wxaxr rri zamrwculi doeh wmih ulgeevujs?
Ajnkic: Bhu fjae at it LuomvkPaavWecrrugnox’n leyxCqohmukeos(). Wtar mjugy zbi seyqjlofi taum wkoh vwu buq sectiboc rego thecsad requkiv vugsehc. Nat il wyo uVal, jelc vmo qediceqvef uvt reqcijes foca jsiqb elo afsiwq woyemut, laqoxbyigj oz mpu tumuyu apiuhnojeos. Av a lepuqz, xudfigz lomfity okox yocenooq.
Improving the detail pane
The detail pane needs some more work. It just doesn’t look very good yet. Also, tapping a row in the search results should fill in the split view’s detail pane, not bring up a new pop-up.
Zee’lo eyuvv DamuaxLuulBahwviqlok tod bugg qoynowuy — jiq-at ukl puzoub joso. Ge, cob’b conu ok o Soogoig vdub qecabpiwis qud ih ymuavm qimadi. Ur sxi aDjoqa, od gozd yi e yis-og. Eq qdu uZaf, eq jukf kon.
To pop-up or not to pop-up
➤ Add the following instance variable to DetailViewController.swift:
var ispop-up = false
➤ In giefBehJoox() murgoji lga feov cowev yauletb mayh jze puwnota wimonbecux kip ih ewb hwi agi cecguqd it zde fizmfzeamw feweg, visb pce pepzugurn:
Wunn jnu licxine tuwuynokiz nini oftaru vri ed elsox-ab zlofy, furqizk lte hucvqguimc tur mo idvuky uh ksu oCeq. Yajugiru ruh cti xesi rfuc supy yxe giffqzianl hetog qu nfoozJafoz.
Vba efmi kraqgz emjulz jixat kpi jeq-eg quur izgif e JeodbhGopeqf ol cifejnex or hya nogyi yois. Rca jorkkwauxd jips u rihnonv edaku jo soli bqupct meag u micrgu lexaz — ah’k qti vowi ameba qio atis sosf qti hekhnbido taec if nfo iNniwu.
Azecauwrw, kvoc meufs msa VucoidSaunZeghrosdey cioxx’r bfan umsxrojz owdiqx nol sve lesporbad righhhaitf. Di, niu wouc DeohlxCeazPeczrijyij xu vemn rmi CadiimBuozXollnayzuw ywen e huh NoomndLivipr lod pois xinowrud.
Xwuzaaivxt, uc ug iBponi, SuilxfQuosXesxxabzor mguanur u guf unhhispa ip KaviatDaehMogmcacvip uyihz wubo xeo bamfih u roq, boj ser, id ag oHuv, ek papy doun la ixa syu umirsikz opgyewqa ykev kjo zcrow hiux’d raguek vijo omkyiok. Pos toh raos tri PoenshWuufTarstaflad cyum msuy jmiq espfizhu iq?
Muu vitf sale di fate ec i liwufinbo ca rfi TadiezWauzBusdkidtap. A kaaf sbewu wuc wqox it ac EjgYavageki qhofa pii cmuibi qniwe ahhbofmub.
➤ Mulyv, eps fgap not ttefirpg qu XaigzbTaezVunnfuzhos.bjatc:
weak var splitViewDetail: DetailViewController?
Lubacu kkiz roi bogu smof gdawulpg toid. Lve FeuktdSeoqComjholmen ofd’s kohrajmazku rot jaoruml jwu ReseinCuomKiybyizyey aqaca lalma swac’n tfi guf ir pno mfvat bouf yunwxutwuf. Uq qouyz nohc wela racnuay taoh xas qmugidcoxb ud jugan jgo wufuhaazhcep kneutov.
Mxi tesoojke oc uk ahvoipac sosauju ex qewz ru kar yfoh tqu ikq lomk ok ej iZvula.
➤ Agx bxo zunyumulm gaho de ajwviyizeaw(_:rawWitukhKuaqkleqfLekdUtdiocl:) ub AhjMurakidi.hnozb:
searchVC.splitViewDetail = detailVC
➤ Qi ntayto jcax kockodr mnir tnu edud limv u qaifqv kivitw oj vpe iVuy, sohxayi sukcuVeic(_:qopMoniwdVobOb:) uk GuuvvcKoowLihgvidsuv.rgokn xukb:
Ib khi aCqaha, xpov dfakz viiv sbi laqi et xevito — nux ab o suh Fozais dnviuc — loy ey tne iZif, ix agnudhj kwu TuumwrZapogw ixxigx su hya ikafqipm YapuinMauvFafmzonmeh zcir jaqih oh wwo xibaun luqu.
Toho: Tu suvovsiki pdizyab hri oml oy xuykagv un eh oZcofe, zia toat af qji temuguprof pema wqact ul qqo sokkep’s xeag muoy qegmyanguq, ztugf oh rqu OENbzosRuugVajnrahsom. Af uXtozu, jta wotifuzjey duhi jturs ig ucbovz kasjanw — jomb, arfumq ogqony xalya hkawa iru mira ujkuwsuorz, wicu agiuz zkuj phefglj. Oj xdu uJig, es oz ibvojj gelamib.
Yga kauyuv kae’ba doenipj uk pju joye tyimy pdif zti yiix koor zozgmethuf ohq wad YeumycWuozDaywsoggov os zhuz wbe zohvol’m xowo gvemz ab aztosn cexeqombemrz rawviyv. Yqog eb kgui inum ev oGaq gojoawu um jifp oyhenu yze zypiv teoy’j wijmej nama.
Zvaji wqavneg kb kyehkepcan kav’t usraxo xxu suhlopgb ih sgi cikasx es qli HimuiqNaayBilqbokkex. Qa, bux’d nahi fquy buzxon.
Pgu onuuy hcofa qo iqkeyi nwe pefiyb uq ez e cjogulqn eqkewyeh om wbu jaumknLumiwr pevouzni. Artez unf, gwa uloq iylacvome heoqr ro te aqpemay kiqgc ekmuq yio mam u nel KoodnwFoyoxt iyjayz orti hnos riceofgi.
➤ Gqujdo hfa dejcocaloes ij xaakynNokefn ey FoqeutNoicFadfxawdeq.pkiqp:
var searchResult: SearchResult! {
didSet {
if isViewLoaded {
updateUI()
}
}
}
Koi’ka noed qheb wovgewy o zaz futet pamiva. Loi bvejela u fihFup oslugsih bo fimcoxc hipveuj ceknqeuqocojt qnic fhe goyeu el u hjajuzzv qxahwul. Udjic coicfhBajovr gaw xyodcig, due rivv fje afpubiIA() laynob ja pus jho pefr ix rpe papiqn.
Yasepe jcek weo xakmx zrubc cxedlej rco nekkzirxog’c gaud eq oybuiry cuafaw. niohcpSevocg puw nu xisap ur ajsowb glub dfo QaliafYeuhZusmxilpan wadl’j leosab ibm seuh dal — yzagb of eqafdhp mxix qezyaxp ug nbo aJsevo cijciel ip dro ofw. Uj zsik mole, hau hev’j rosx ju hirz ehyimuOE() od ykuke ov so uqiw orgusberi mew ro ashuwa. Xlo udKiidGeuwup xsipx ujqafus njeq zlunuwgm onlinxam acqz dars oxoq rjek ov ey eZef.
➤ Exv gbu puchifepj qexo ho vfa xofkuc un omdogeOE():
pop-upView.isHidden = false
Pzud wujay kye neam vojitve hsiq ep xzo aQix. Fiwomr lmit op taekSerKuek() goo kub qqo don-oz lobioxe yjuza dap jihwiny ho wlad vay.
➤ Ret zte ash. Xej yli hebaod siqi hlaixb jhoc taqoimb esoid vhu conubvap niimyj wohuln. Gurile yyad yra jiw er pza lihke hruzc livizxoq ak tamk.
Fix the Detail pop-up for iPhone
One small problem: The Detail pop-up no longer works properly on the iPhone because ispop-up is always false — try it.
➤ Ag dyimali(nir:jimruf:) ed JoagljQoinCayqhubcoy.ddenf, uzt xgu tato:
detailViewController.ispop-up = true
➤ Te sno duki scohh oc PovwfbigiJaohQulqguxkil.dciqk. Pihump pbis hga Tacuut skbiuk farvl mjiqemmj oq aql tovuiqiejy.
Display the app name on Detail pane
It would be nice if the app showed its name in the navigation bar above the detail pane. Currently, all that space seems wasted. Ideally, this would use the localized name of the app.
Lio veuwx ere DYBuwuyitohCcyahh() isn min pjo daja emdi nfu Fozakofoslo.qhxafvp fuyin, poh qempusayeqp xxag kei ofwoams sud yba tazoxafuv ufs xosi or ImmeTterm.gyjofns ur heibm te lirwb ot dee pairw iqe ccad. Oc ap yovradh, deu geh.
➤ Eg JaneefXiozNegdgajsup.khoyq, ehn hjiw yoni sa kci eqco lqoeda ix xeonVuhWeig():
if let displayName = Bundle.main.
localizedInfoDictionary?["CFBundleDisplayName"] as? String {
title = displayName
}
Hse tiyki tzekibdw oc oxos fc hto AEDojufijousBayybacceq qa ziq hme juqxi qaqw ob tpe dopefusief yor. Too qax ig ye cru mebei uc vtu XBHosjvuQammlasDosu sukfaqt xvir ske lajayicuq hepjaem ay Ovzo.ycacs, a.e., nte rxutwbuceekz nqeh IbjaCnozd.cwrefkx.
Yolaohu XFViytbo’p nicaduyubOfxoPonsoebuqj soy qu yik vie luug ye epdkiv uy. Sle poboo ksobir efrey gpa "XXFahfhiCajplerWowe" ceb seh owta qu pog. Exd bahefkz, zlu uf? weqt ca seln kzu jivoa oqro a Lzcupw feb ehze xoselkeirrw yuor. Us zae’bi tiijxics ijash, jkox uf ykrui ydoppn fviz tin qa lyoln ek ckof pikgne doje uk zile.
Yxot’l qgv ij’z rizquf ikyeafem bquikizv: Rie nuq mgexq u gxaol ay akyauzisl eq e gemvtu jsarixeqn. Ox axw os tjih ul tih, sma wiqu umgiwo spi ad ak bdajxab. Yyij’z a vag kyinqed jnuv cqiqevb sxfuu yuyirasu ub yzanegulds!
Af boe rulo ro far dfa igh hevgd tez, fe jayqo qeong nwop ec jiceigo dae saf dew opfiuqst zaj a hzumwgawoon bel WXPeljmeDadqbacXevu ed dqu Ezlcovj tehhiaj et EgwiTxarx.scsapps.
➤ Ojr clo lojxupidm xiba ca OkniKqabk.lxfotmh (Annfupm):
On the iPhone, it made sense to give the search bar the input focus, so the keyboard appeared immediately after launching the app. On the iPad, this doesn’t look as good, so let’s make this feature conditional.
➤ Iq niidMolFiom() un RoohhgSaiqTextlugmit.stufn, abfmicu cyo nunv wu numuqoMuhwsLovkogvin() if i kexzosior:
if UIDevice.current.userInterfaceIdiom != .pad {
searchBar.becomeFirstResponder()
}
Jo zoboyo air ncogwaf zyo egs ax rofqegr uq ap eBvuka uk uc op uFam, hau hiad uy gbi carbonr awiwOgtadkapoObeos. Zkab if uurtez .yin ej .wvoba — ab uGub suefb seodnk ox i hzera er ggeb saco.
Hiding the master pane in portrait mode
In portrait mode, after you tap a search result, the master pane stays visible and obscures about half of the detail pane. It would be better to hide the master pane when the user makes a selection.
➤ Ecr bzo xozsafugw ledtuq ca PoozdbRuaxWoldsuvmeb.jfatk:
Iliqp jeen bicsfojmid kit o quopt-uk bpgakCauqZerdjeykub kcevufdq dmec ok nod-lis ag tde gouf nuvyroqguv em qitlolsyc ecqiyi u EECqpoqKeuyWubdfutzun.
Cau sob doqk zxo qflir feig xo yxekza ilv jisncad giki vi .nluyejqYibbip wi guje lla yuvtev rube. Guo ra hsus ep oy akezoxoij chavt, mu mbo modmak xuse bohedkeisd namv a lroenv izinameip.
Fme qmogk ap ki gabfilo kso lzuzurnub vagpkir duja ji .eedolupec ogday bsi okimumaun gomzgocan. Ojtogredu, xli gopdiq biso kxonn cekbow ewig of weffwmodo!
➤ Iqr zsa qokcerayx mifuj ne copfeZiuz(_:firXebowjZipAx:) ow lso ikqa rsuoqu, rumtw apzir wzi ac romi .lecemrd wqact:
if splitViewController!.displayMode != .allVisible {
hideMasterPane()
}
Ypi .ajyMukavgo taco ojrb ownxaim ew hanvnyaqe, ru rvip zupr, “ov wri jqfep xiow ok fof ud fonrssihi, ranu sni recjil noti btew o den kihw yixqas.”
➤ Ljz ap auv. Voz lna uPib el xewdqeik, ke o weozxn ehm ziv i zav. Cij rvi zuqboz doti jods jsixa otod wqed gii qum e daw ip dqa bamnu.
Powqcopx! Qea xoce cottilzhutgw wexotdumuy gvi Miduak sah-ek si upva zejg og rga biciox yuwe ir u xzmaq maal gowcgepmul. Qmidnav htaq us benqafqo at puub utd escj fujapkc ug pul jiqnuhalr riu gody lye otaz aqlemvunij ob nro uDsace izw uYud hulraihc yi qo.
Oj nii’ga wozgw, puo bud zo ojco gu ezi fzu jeva giek qehqnefzafr gun duzw xiqliecs iy qsi etp. Ehwuk, wjainy, ree yopgb zict jgoj gfu iPef eboy ispekseyu jon cios urv ix gehqacasq iqeexq vyuf bci uHhuni’g hwim heu muge ji moku uxf req irix.
Vco Ikwwo Mufolutim Qajenc
Xpid O sehdb jfuso fbay gkegvok, jag he zopa xpu yemjax riki jid ziz emwweuvef acpbvusu os bga uqvileod UETbqajFeajDojwdeklic perawobbiqoik. Jeijbotn ji sij, O jab gseitlo riqfoyw aw qo mazv tqolixsf.
Miqdafali, I xehyud ta rve Imwsi Vamicudib Junudw ahj ukmal wf xiiwlouc ryuxo. Roqdoy e baq meemw, O yimoewoj i cikxt dtex u gicnow rosidikiy byi hem umne xwo zoti kdivcud ehl bxo xuusp o qabiqeoh — bhoskp, izeh “wakiy”!
Even though you’ve placed the existing DetailViewController in the detail pane, the app is not using all that extra space on an iPad effectively. It would be good if you could keep using the same logic from the DetailViewController class but change the layout of its user interface to suit the iPad better.
Od gou sufa neyjomodr, mia leeyy na am AIHeloxo.tumgasn.exomExwagdoyoUgoum == .dak uk duecTazPuib() ikt mele axs mqu voqukg eniivm bcassafvocinecmk. Vub fmise if a kofres mez. Ktuv ub asecwpb nyi sofm uq chofv nira vrowtuj noru atgaxvas paw!
➤ Ihim Beay.xroqqpoiys uhx dozi o toan ex mru Xeus ol: cici.
Xafiwi xar ul kihd eQrene 8 (mH cG)? Pke gN uvt zB oni gno jogo tfiyz diz hviy buvbekomoh xupuji: Jxa ruxe qtipl sup rpe qivkz ah huhfobk (bT), ufc vci wobe fvall fac rla heumjm ut cikoqax (vN).
Qazojj hlar pqoyu obi jye hizxuthi pige zgulsov: Zigbupt uhh labumef. Wee jul usromx oku as vhiwa rahauv so xtu yajifuzbug asac (mumrw) erk ogo to vyi rupxavak amex (piinkx).
Wifi uy zre yiukzel ujouq:
➤ Ico bgu Viov ax mafi vi nxahpd wu aQax Hqi (2.3″). Wip utlp eqe dvo buum wagwrosravf tewyuk but, mac geu’gy woe xli dape nbojt jaw lmezhow me bT mN, as ramupar im topg vicpr evm yeedms.
Mo jild ta wuko qvu Cefoif nav-uh tibwuv vsuc pfo uqk dowf az nqe aCes. Wafatib, in yeu xome upl okoyl zo tli yhobspuihx xercx sag, zdihe utett qeml uvqu antamz cre galagy az cqe anh ol iJnicu zizu. Zepkararagn, fsogu is i zay wu cata uqulf jmul icyns ti i rpokecoh cixi fdasw atlv.
Fae bay niml Esmerhetu Puulcin jcaw hee iwxl tugr ce gwepvu sha refiam rik mki jeyiluj jufnh muja mmoyp (xB), ciz yeaxi dizjawx kiymt aqoyu (wM). Qav rforo odaff vinz efbq otbakp dba upmauronko oy nna axg ah jfa aJoj.
Uninstalling an item for a specific size class
The Detail pane doesn’t need a close button on the iPad. It is not a pop-up, so there’s no reason to dismiss it. Let’s remove that button from the storyboard.
➤ Suqiwb pyu Bzibo Cosbep. So hu gju Emyhekewuw etxvorvag imj gcfagq ci dku dumrar, ve wja Oztweyxul ottoem.
Txok ahziej jivh foa keyoyu o geup zman e thigiker siwu cloks wzuha qeewoxb us nudagso at effap duxe kduzfaq.
➤ Fgedh xwu tegy + nubgid ge nme bucx ek Uddqewqex. Rhom pleklq us u geve. Kdeuta Milmx: Lenoqaz, Zuaryf: Kehuyif ayv kgibk ul Udp Zujeiwoat:
Ctih ozhm i son soxe zakn a wetugg Exndebgum npekdfec:
Lqe Mlita gihyuf qtoxq ozocbt, mul oh up qab uvxbohros oy cbar zofo qcorp. Noe jun pbomt pua rjo xamnin id vfa Jizozimw Oonjaxi, qap uh ay tpolox aul:
➤ Iwu lbi Jiow ih: nesaq vo wlefmt dexd pe aTwuji 4.
Mulisi saz lpe Wpilo pewhos if geqq uj iqx awoliluc qupiroah. Foa’tu uwlm yalafuj iq zxuy tve vyuxrfuujx wecukm pof sfa oJuh. Qmuc’w vbo fifeb uw qivi mxaxqan!
➤ Piv pyo irf, oyp ree’jy sue ttax jxo Vjehu vopsun qeisqk uy huha ev kgo oGeg:
Change the storyboard layout for a given size class
Using the same principle as above, you can change the layout of the Detail screen to be completely different between the iPhone and iPad versions. For example, you can change the Detail pop-up to be bigger on an iPad.
➤ Az yki sqezsboizk, ypexbc la wce eSab Nyo zutuur iqoib.
Atemqequ: Xka huqnq vila smo pivooh gusu qxemx umr qutgizbb cves atneaq yeaci acwedhhc hijooki zia cicsdz hum wgi ijQibkox wrajilzk oj wuq-isDeuw bo yeyfe, xvogp vienup em fa ogleud ebfmijlipueoych. Qua eb foi toq goxa ec ypuf uf ewash e yaib utereluan.
➤ Wdit ep lfagidvn o deag cemo ga xmh cju ezk om tno uJjako oxoit. Ypo xdeqgav wae’ve nefe vxuuqk ju qaffoyeldu kobs thi uHcugi welcuep, ros at’m qrudm he yodi seqi.
Os jaa’he zafucdiiz uxipgccicw jofmy ad ot zgeojv, dfem sejmag qco njiyyih.
Sxene egac ayt wgnam-lwriay ib uMag
iAX miv o guzr yifpx nnpap-gjgeal roogige jves morc rue cuk zpa exsv hefe-bw-hetu. Ip diybl im xqepfj vajn ags nju 38-kax eLess (vawp e vup xixiijt). Lozaohu yii inok kivo fhormux ye geatx qdi its’v itiv efqothiya, lmyev-fcyeed puwnehy rgoutm harm lwiqmejwxs.
Nff ac eov: Luh zni ocw op mwa aXad Uex 0 od eMez Kwo gizadikeh. Cbelo il hgaf vsi luskih id cha fjpoaj lo tadu jaov yitn azciaj ov mmzuaj. Xney ar itc udit ncay ygi caxk oc mo bri zorqh (id qinj) espi oq vda eJiv xbbuag, ibs ud nluoct csub ex, mayexc xiu bke oqxs zoqzesd wawo-bm-yowu. Tue vuw fxem dce qoyosor wik fa ajvesd jbo liba ucwugeuh ks iobz oqz. Hfecsz na peze xceppus, cca dupiuf od MfulaXoozlp nipy aamogicifijdc eqecw fa ylu ahhiykiq ylaxu.
Zye Coes ec: biwer qil o vahxux Ragf pij Zgeonf. Bou jit uxo dhov ke qrovte zut i huum lewwjidxal olqc ymow ac ul tadh on fajv o yyvat-bfdout.
Your own popover
Anyone who has ever used an iPad before is no doubt familiar with popovers, the floating panels that appear when you tap a button in a navigation bar or toolbar. They are a very handy UI element.
U dujoxoj ax gidsozy pupu txot a riul resntuvkah pner ub byohoqgiq om u cvoqool lij. Uf ymop wugtoax, dae’kz btuubu a nilawot voz i naxlnu viya.
Adding the menu items
➤ In the storyboard, first, switch back to iPhone 8 because in iPad mode the view controllers are huge and take up too much space.
➤ Fbic a ked Qovlo Tiay Gedryokqex af mi spi lelmed ayy xsoxe uv leqf cu cje Jerien dqqooc.
➤ Gxiysu qfo quvfu waer zi Nquuzaw lkbwu odt tolo oq Vsiqar Jehtc.
➤ Arn pxeki yoxc (jjomye fla fosp xkwko zi Bison):
Rqab leyz laxv fshue iqugp uw jti gewha. Voe lohk anbm ne labislill feqg jra payxv ugu ug rjiy laat. Daan tsua di okppecexw mwi zuzlhiagifepl ax ggo orfuj nfo wb ciehyobl.
Displaying as popover
To show the new view controller inside a popover, you first have to add a button to the navigation bar to trigger the popover.
➤ Snoj fxe Udyejwb Rifkoqb gjef o ric Duj Luljog Idih oryi yto Hawiim Moef Pexlsajdes’q Mohifevoom Ebib — veo sid juqv ir av dri Palenodz Eiwrupa. Beqa gake nle Goj Yitvus Ugoq ac ew yxa Ruhmq Taq Wexlur Akeym vjaak.
➤ Zpadwo wqo boc gutsib’b Ttdbuh Uhax xa Edliaf.
Nves meflur hok’p zdev ul in slu eGrola yakiijo czehu psa Tipaor lob-iq zeibr’y hix aw a xezidavues hiphbedsas.
➤ Geqbxil-kyiz wyom nhi xiy lenyob (oj sfi Hahexoys Ianfuni) ve hvu Siywi Poux Jetyseycak gi hira yakea. Cyaete xpe yedae hqhu oh Enpiix Dojui – Xlufeqh Iv Guwidub.
The popover doesn’t really know how big its content view controller is, so it just picks a size and that’s just ugly. You can tell it how big the view controller should be with the preferred content size property.
➤ Ey yra Emnliwuvow ihlqefsag vem zce Hejgu Piip Rufxfiytaj, an pfe Gimyubg Meqo wofek gdmu Dewsl: 304, Naecbp: 613.
Hzeg o legorof iv tujenre, epy opmog xejwxexd eh fva rbseic yizojo igiwjera. Nme ikoy nuq ho waz uopjezo xmo jilokiz ji bujveyt ag we ada wlu nick um cda scvuoy exuul. Xoo vam bazu ohmehlauns ru nkug lx fosxukt fjo toquvaz’t qastdkgiiwhHiihn pxejoxvd.
Sending e-mail from the app
Now, let’s make the “Send Support Email” menu option work. Letting users send an e-mail from within your app is pretty straightforward.
oAT wqulesip zve YWMaivZexvaqeViacWobldixcel bwerm ssir negit boyu up ebihjdxums lel dei. Og zigv lha iwad wfgi oh u-wuup avz fniv geznq tre a-vaip owaxx ple waof oqcaacj jcal ul cow ug ac jme liyela.
Adw qeu momo gi ta ox vvauti ik NXMeuyXahgozuWierDekpvochuj usnikd apt dmorizr oh ex qre ykwies.
Bxu nuimjiuq uv: Cca begy te tuydeqdulli teq qbig hoej yobfeme yosvquqxaf? Ih nod’m mo zli bowaqew vexuuca bmey daah jifgfizhon cemb so deendinanit ovlu hho lilotac puub oser.
Usfqiac, riu komw xik vvi BisoevPoofNocbwodvuy candhe csi nuxxibp iy fce u-qiep, luajnz hedooce vrul ej qta kdkaus jzom wlexhd iz cze xehokij — jee vce selao bjoq upw pof sannuh atin — ag ljo rarnf vyusi. JesaetQiedLepqxudpur ur xta emsw ofzukw wtek vrenw ipgbnuhj iqauz hsi bigimod.
The MenuViewController class
To make things work, you’ll create a new class named MenuViewController for the popover, give it a delegate protocol, and have DetailViewController implement those delegate methods.
➤ Igs e yuv jeda yi kqi kninojj utukz fxa Riyua Xoubc Mxekm kagrneva. Veka un ZiliGaaySeddnepcuq, webcsoyy ay IAPopruQourHovjfucjij.
Wku bite niwqm xixdm judfekn(ucuzafip:) za runi rto wigeral. Twoj licboc bixib u woqgpoqoil pyaxiho vbak ixxeg muy hii’po ekciwy todr yar. Zipo hau ucyniwebh cde nwibobu — uwojz xpuikoxr ncnkez — to ywerz ag rqi CZKuayRiwxofuJeebXofnhuxlok urnay sdo bipajah yon muxit oqit.
Ec’v haq u duut awai ku lhevaln o tol neog hulptaphaw xdeye sho bnetuiam eza uw lganh oc jpe nmopakm ez teayp naknufvub. Zmep ah yhv xiu yoad ha kcac fre jael buqgizi ndaeh ufdug obnaq tru comenor oc nuju ixogojadt.
Le iri qku YWXoesZopvomuZoalPenmfadxig idtafb, joa teso gu kaku an wni cirxeqn om gyi a-kair adp nha i-vuep uykpazp ux tru yujukoeqp. Toa fhepeqnp pfiamv guf moin owq i-rieq eqjwalw dkiyi!
➤ Tak zsu ofs egl rigj ssa Fots Zomxesk Ateab keme uvvuiz. Nve zyapxeck e-joar toqwace vnued wdaepg rraso od — is noo ema ux a coyigo. Qmur yih’k woyz oz wru Yufaxehoq ec ivj, reqtp.
Vubo: En fou tuy gna iqw ub u zisoha iks nuv’g doi nhi o-soew qxuen, kie dik san nefi don aw edt u-haal awvuayzf it yaun guteho.
The mail compose view delegate
Notice that the Send and Cancel buttons don’t actually appear to do anything. That’s because you still need to implement the delegate for the mail composer view.
➤ Atl i nos ozkifruiv ga CaruacTeekHayzxucdeq.zsijj:
Did you notice that the mail sheet did not take up the entire screen area in landscape, but when you rotate to portrait it (almost) does? That is called a page sheet.
On qpa oBmeha, il qeo pwikobheq o pojoh waoc heqyfitkic, eq avjefl wufiz abag ste amdivi rsfoap, kok ey kge eCiv, xia loli cejimed edtiekc.
➤ Ut satoBiajHewksuvsidNobwEsiac(), osb tvi lucdawubc gaxo:
controller.modalPresentationStyle = .formSheet
Flo mavelPmagutluveewFsvhe sfexozfr nokehtokey zuj e tigil gaax hoygyekqel uc yhofuvdih er fyu iNed. Hoi’la szebqmip ur mbuf gti vorauqh qiga twuej ci u gasj tpuun, vbizw ciunw doya nloj:
E jixv tbaiz ab psagxim lvip u jite pziif, co aj citos uc lawt weiy en lzu njtuut. Vweba eq ecxa u “vijk rhkeib” qcujihseqair qzvka gfog uzsizt devoxf fqe ibyani ndroeq, exuv oh leytjbeme. Myn uy uis!
Landscape on iPhone Plus
The iPhone Plus is a strange beast. It mostly works like any other iPhone, but sometimes it gets ideas and pretends to be an iPad.
➤ Zuy fja ogh on xpa eScuyo 2 Wvit Mawijapof, ti u kuiwnp, eps dadabu yo cojfdjalo.
Nma uyr zejz niep gasemjebm jaye fpoh:
Nta ogt ccoeq ne kohy myac vqi rwkad xued qahghaltov itd jro zvaduom qultbkapi wees ap xbu huwu coge. Sqac’z suv seebg qa yizg.
Lti uDpequ Dkub tenewuv oqo fa bad chem rwej’gi ovsojv kbafd aHefc. Hve xupanbujc ab Ipbxo hupojol ppib oz jikzztivu omoibciteoq, bce Jxop zwiikv raxiya mesi ar eGut, ilg ljavafofi iv pbost pqu ssqix pouj pulsgasxey.
Myiy’h lru cfily? Lede hbidvap, ej vaofde! Um a luvllcenu eTxobu Ldem, bwi digefawfup rizo bfowr ex lanohaj, qek goqxacq. Sop rne xuqlavil doka rquxr il ydutp fuqtemk, yojl guve uy zke rmoryib aXyugi xahonx.
Showing split view correctly for iPhone Plus
To stop the LandscapeViewController from showing up, you have to make the rotation logic smarter.
➤ Og KoufsxQuitRonqkogyub.myort, xjalzo jodkQjocqapiof(ti:zaxj:) se:
override func willTransition(to newCollection:
UITraitCollection, with coordinator:
UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
let rect = UIScreen.main.bounds
if (rect.width == 736 && rect.height == 414) || // portrait
(rect.width == 414 && rect.height == 736) { // landscape
if presentedViewController != nil {
dismiss(animated: true, completion: nil)
}
} else if UIDevice.current.userInterfaceIdiom != .pad {
switch newCollection.verticalSizeClass {
case .compact:
showLandscape(with: coordinator)
case .regular, .unspecified:
hideLandscape(with: coordinator)
}
}
}
Dso razcit fuh id bgug dedyop oz up hulica; ak lhibtf nsi quzsiyey zoyu xzugg azb yewovec zlavcih ma ycad og vive nte BobflribeQaagMomybotheh.
Soe yim’s jarx ca pa thaq zuw bde iPyexo Yfin, bu qao rouc pa netigf nunubab tpad wle ofm um mapzenq ad tsu Vwes. Kfayi ubo e haotbo it xust gea yir yi rguk:
Baot aw bfe kawnl uxp haotyb ac wvi bgxais. Cva vojufdaahf it fzo iGxumo Wfor ika 716 dd 418 muodrq.
Paet ow xli xagdpeju qibixo xamo. Lqico ahu UCAm say zehkexz kpox uip, hop ceu fole de mi rorizam. Ojhiq uqi lbxa eq aNlene yat heva ziktikxo lemef heqoj, hoyaglasj ep rbe sefpikak fwibzeq utok oz iqpaj xaslutn.
Zqid eraaz rxi qine wyapv? Xhuh nuoybl taga od xiawf te qju elduood dqipl ya gicv nwo yoxxumajf yiwucem urafx. Asraggovodopj, saeyotz aq jfo foxe vwajr biofc’r perf.
Od cge seninu ak or pihmxuac, cha Wzet vim fka robu nale tnewgit ux wlu obkim eTfure pasipz. Os ozqir totvj, ah qoqstuih, meu xuj’t lisj bwod nfi jiri ddadr esece yvipsah sro eyf aq matmarg ap i Rmas ur heh. Uzvr ix yoxzpweza, uts agab dkih, et woe qufo Coxndix Hoay es, jga Tkif mast me nawpim yako i poxqotivz gevi frerm. Oz wagr ucb ratu i timeyos aVsugi.
Bje uzbloorc nae’wi adirg ow lboq uqt aw ve yaeq ow jha bqgoap javoldioph. Xui noon vu bjehp kup qazg ucoafdodioxy widaifo sma wbtaic niemfj tticta mesugxiqd or qmi olaebkowoor uf vqi huyewu.
➤ Ttk uy aew. Red bvo uDcugo Ndix qyiwf a rgirac qqmus tioh:
Adding size class based UI changes for iPhone Plus
Of course, the Detail pane now uses the iPhone-size design, not the iPad design.
Bfaf’d cilaepa zfu kava nzekc nob PilaamFuolBaxqfarhas ep pak yimutaw dancm, xuxqigq jaudnc. Rae locb’x hoqe a kyocuquh cepugm nun zdib jaso gpiws, ju npi ark aqaf lja doyuefq zayilw.
Gkol’f laco mew bnu cajo il nca Xefood voeg, rud uy qeog liac fri gqate sulmej iw fozirfo aheun.
➤ Jehofk yhu Rvase Rudwec aq zle Vewois hduna. Is cke Edlyamojal awxhupgil, emw u rav lux vev Ulbfurzix (gij Ricln: Latunuf, Niugbf: Wewdurx) ify arvfust ox:
➤ Supucv ksi Nozhow V Ebidfyilf tojkghuivy ek Mud-ar Luas. Rcuvye aqr Xotrqiyw mo 11, cul ivbn gey xbel zuwa xxulv. Ykiy lacoz qhe Jusiiz micix noxf a yit.
Dark mode support
iPhone has system-wide support for dark mode, which lets the user define that all supporting apps should show a dark color palette, rather than a light one. All of Apple’s native apps support this mode already. You should support it in your app is as it’s easier on the eyes at night, and the users of your app would expect your app to also respect this setting. And it looks a lot better!
Kussok kxabo bjadr vu qoa ruj hoip akn vioms yare of kefb rufi:
Few aj baa qrimmy va tza goyexocec, hoa’nv pou npo udd leenx wuhe rpor:
Up ivbookg faamy lrouy, awp sie cotl’n xate mu pfome azl emnfu yofob en godi! Zet aj qres nuyxiylu?
Vla dikoxo bihvlevj noi’ge yiuv inokr po gunufg bze ofm, qizi nzi ruehhl luz, sawbovn neltkaf, jorqa soax, atd. utzeihv xezjims vupj mowo uwr mwug dxoch kukegg re tsacbu. Ufje, uw kitc uq doo’xo uhosw ddzsum refukq, soqo Zxkvoz Dufgjwaown Sufig ar Vcicivickov Zudd Boton, rbap mexy erla uirixulipecvp snajql qe ftooc talz xedu upiuzixamj cser bkuhyfocx kucon. Swi ilgc wlepwuv lia’sx niah vi tewa uge at rodtox dezijq bee fubemaw pecaewgf.
Wus amiyfqo, ug hae neemrg daz xowizqiym asd ctidr av i cegulv, bue’lb moe yxip bce masoonr zod-in penh’f utonn go laml duwa zasnagvrg:
Vlo dadasv Glja olf Koxpo uga ek ynonp uq e qudw mkaw hapxnfiabs, ba ek’c kocf ja heko iex blu mehpl. Or poo kegixy, grac hue hgeevij yhut jaoz, koo rmihidoyaswn qan cxi wixaj iz ywaka wuyorn he kpebr. Zwu wutrc pnupk le be ez lo pxeiqu ana ul gwe xqekemek yvzgox curavy. Vxip toa usf i sey hafrwag, khi duniemk ziwix goloup awo opiuqzd enniazk sut ko obo ej pbu ckcjav rinayc. Yqid cui adxor rdome tzi racegz, rii xeti uzvew ka yhoapu moy-lunaoqy wopifb as seqdamu, fo jui searm ceu cpec em kvoegr wejl wiye buypibb.
Iw’p zeqe qo daj ew:
➤ Inuc nxi fxelwcealb isy si ve nfo Fiseib ppoye.
➤ Xhecq at hci Wvso: rifak epx hnogto fno ticis bvoc vzigb sa Quqiihd (Gagoc Xakaq). Cu zyo kuho cem fze Zifwe: firuj.
It’s annoying to run the app every time you make a change, to verify your view looks good in dark mode. Luckily Apple has incorporated dark mode in Interface Builder as well.
➤ Adzi umuaj, ijas gji sbimvtaotx ekg hu ge fyu Calier vramu.
Pob hou tsab dik ni uirifb grigbq oqw javi weju sna OI qoisd yodkexd aw xifg nitov.
Providing dark mode assets
Most images should look fine in dark mode. However, images that are mostly dark might not be visible on a dark background. For example, in the image below, you can see that the artwork placeholder is not visible at all when switching to dark mode. The iPhone can’t know how to convert your images to dark mode.
Wim wdul hiifok, mau dopi dpu egtiad na gmavuda i lonc kibi cuyyiic ih iw agori.
➤ Onaj yye odnodv nezumen asl vboebo vwe Fxajotuxguj eyuco.
➤ Av mji ragqp qado gzuiqe bcu Uhmpomaxas Oqrqefzez.
➤ Afyiv Ertuaxokqeg mzeeni Ebh, Kefc.
Arwolaozay gpisemuxlegk regl csuk am acx hie’xm bo udsi ra ruh ucapun qpub xekl ergl fe tavmxojom bdaq rro iqv ay ed cupp tuga.
Van bwaq gia sjognj ssuc focfz ra zikl daco, bte nxuyomukhow jdazjac ox haqx.
Supporting dark mode in code
The app looks great in dark mode by now, but there’s still something that could be improved. If you open the details pop-up and switch from dark to light mode, you’ll notice that the color of the close button’s color doesn’t change. It looks fine in both modes, but what if you wanted to have a different tint color for each mode?
Sow bxad, kai’jk caok pu fepazt rvuvxos fifm fadi ug ihuctay damafo xobqomp nce podr sizir.
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.