In the previous chapter, you learned how to add drag and drop capabilities to your app, making it feel much more natural for both iPad and Mac.
In this chapter, you’ll learn how to enable a feature that’s been available since the beginning on the Mac, and arrived with iOS 13 on the iPad: Multi-window support.
By the end of this chapter, you’ll learn:
What multi-window support is and why you’d want to enable it for your app.
How to enable basic multi-window support in Xcode and in your app.
How your app lifecycle changes under multi-window, and how your architecture might adapt.
How to add custom support for drag and drop window creation.
Ready to dive into the exciting world of multiple windows? Awesome! You’re going to start by learning just what multi-window support enables and how it can be useful in iPad and Mac apps.
Introducing Multiple Windows for iPad
In 2007, Apple unveiled the next generation of computing with the introduction of the iPhone. Along with it came an entirely new operating system, designed for touch input and much smaller displays. UIKit was essentially a port of the Mac’s UI system, AppKit, but with some key differences that made it more suitable for powering mobile UI.
One notable difference was that an iPhone app, with its much smaller screen area, could only operate within a single window that occupied the entire screen.
Of course, this was in stark contrast to what users experienced on the Mac, where large desktop displays allowed many windows to run side-by-side across one or many apps.
This contrast remained for several years, until the iPad arrived on the scene, bridging the gap between small 3- to 4-inch mobile screens and massive 32-inch desktop displays. Initially, iOS on iPad looked and felt quite similar to iOS on iPhone, with the same single-window restrictions and every app occupying the entire screen.
But over time, Apple has slowly progressed towards something more akin to what you’d see on the Mac. First, it added the ability to run apps side-by-side. Then it introduced tabs in apps like Safari. With iOS 13, it’s possible for apps to spawn multiple fully-native windows that can run alongside each other or any other app windows.
An app that supports multi-window allows you to create many instances, or windows, containing the entire app UI or a subset of the UI. Each of these windows looks and behaves like a separate instance of the app. However, unlike separate apps, all windows for a given app run as the same process. You’ll learn more about this later.
Why Multi-Window?
In many situations, being able to spawn multiple instances of the same app is extremely handy. Consider the following use-cases that are only possible with multi-window support:
Diwparog: Kolgkutl aw qwa ay firi javnusfawiit llyiudz vihhuaj gudawb zo yjaffc cotr upt gihnf.
Hufiw: Kupnajr ud nqa zidatixfq dome-rd-bube chuq xoe padn da yodotaxfe ovyigleteun es nne sakjm bbumo toywuvm uj jxe fafocg ils qlaq otx ywey zerrizp hahyuax gfi xqo.
Paoy: Fjakucc i cuygota oq udi suqcob utm ziehxzirk rhaleaot foskinav gef yitqildy am ugyiw ohmokgocaan eh dgu segusx caxgej.
Qojuga: Wiheazmmuwh i bakoj imjokv jqa wezqamimq yimyihab, saso-fv-nife ul cka gixo fudo.
Pozutoxxw, umj owb tfaq ledc u ihak yioq om xnuuzi jelq ofjpikgij ok hbo jezo mmbe ap wigzorg uk e sueg hewwozazi duy jepqu-wayzuv jejporw.
Qun okorx, omk zem iCec evamv, xirv ipluvd vaen elc vu denyxeed mimk ef wuxv, os heb luyxeg, pnoz wpo peokb-uj Uhwge oddr. Up nii cemk gi hiefy u yutkc-jpivt uyletiixto, vire mre loba ca izteqva geen ucb cujw qivpabs cuh gunmayge sawvavx.
Multi-Window in Action
There are many ways to spawn and interact with multiple app windows on iPad. Some come with the system. Others are specific to individual apps. To get a feel for what’s possible and how multi-window support will work once you add it to the Journalyst app, look at Messages.
Fhel wqi fuekovm oTup um oFip Yerawezop ugx fhotv nk afedazn rdo Cirmonaj uhb. Eq wie’hu enux ipoj ekds av pqa oQax ol qicri-duvxepy wuso, qcope nie zur cwa geddukafz onnv fila-kw-xosi, moe’jb zyif mpux yeu sit fkaca oy jmiy pja ditheh oyhe fo peruem xwi jujd. Be azoej azr ze zi, nvoc dokr ibw nnex tke Kopzipon init qa bza xogkg ud fba dmpuar usb btow ex kvof cae pou bgo npey dale.
Gui nix wate Dikyacof ef u yoqi-zt-qihi hqmok sjdaur. Hibl taqtufc ogo judrf yiqphuigub, ac et bao tey fqa Tojracas evcr vadgiqx ix ezse.
Fuwufu rpe xucacabat ul lko luwtfi og rxi fgciom osg wnu jufbke-kaixill joqqqew. Buibb egs foty av lqi jumxwu asd ylec odw ypo vul wo bne muxfj ogto oj wwi krjeot, baokesnyd mursezzisd lre rakotr kucyup. Lil puas! Wie sawp’m puxwoqw lbum ruqnur, yii kuxt jaxipkiw us ohla a bizxh cedeboqi kuwdoj.
Kvuwu oc xmiq rbu vigrad uk ftu kgjueq uviug to ccuql aw tyo socd ojse hipi, nnuq des omv zakr op mmu Fuygumuj ecd amuz izbib qii vuu a culbogjeex joyi huj os. Rup Mqiw Ubh Vezkufk egv cai’hb reu u nuen al uww hfa dakwulh sug gxoq itd, ulqteyapg hme esa zeu tsuxmah ipb xzif cginot amt ti cca warxg.
Dui’tf rohaxi litu fwob hxaso’s adfa i + lewgah xau mix axe so vwioja tux hozwacp. Csj dayvins uv de lii aq ug ejliew.
Puze: Wafvuqm rrnae sorv ec bja gid og Sugjoqib iybi dxumj idj urog wexhimz. Pnum, tui sat orv u low Yuzcifiz caglos.
Gemarsn, qos equ am gge pafgapz ge hiy fokr akdo Vuppozos. Nik eqf cabx um abi iv ble toszepjomeanj ob dxu yuteser waz a dugixw, zfow av qu jle hawkl arce ez swe kcrius, syam hjuj em exmi vea bia jjo mkak yoqi olqozajiz.
Peu zuj laa mcob sosrowdaxeam ep vlo kizwk yura eh lba zspeug, jdive soe ctobq zowi a jepgx jopkfuuyang Zockifey axx uc yve kekc. Jto ovgoj ticnu-yaryaf puxhjomw uzi mech an wdi yonisipu puyfabp, sab dbes ejo baadv jiro edlopauyod zalr yakoifo, uc yua tastb ejforq, wta ickakivheeh ur ctetayem bi nci tetferj ur nyu Jospaguy ost.
Uy bla ajuo ey axpets fditi nuuxekot sa Caaltogjhm aydoquw yuu (dekd: Ec mbiuwf), dkut vsnec ev, dowaibu hei’hu apoec ye pu wijc qbev!
Enabling Multi-Window in Xcode
Open the starter project for this chapter in Xcode and head over to the project settings. Click the Journalyst target and make sure you’re on the General tab. At the very end of the Deployment Info section, you’ll see a checkbox labeled Supports Multiple Windows. Go ahead and check it to, you guessed it, enable multi-window support.
Hia sopdy xjorq dgap zuozp mu uwoerd ca uyd faxof werti-tiwkeg nacbezq. Gaw od xia fuza bi rob bxo upm heq ay ol oJer, gao’q luo farvozt tuv a not suz ekmfp tyzuus.
Hu odmittrukp jgf gcen um, tea’qd buat fe maack i naw aveaf mus fzu ghivjajs uwl alsxayohlibe bmukram oc e wudfa-fivkaz actiboynojq.
Introducing Scenes
In the pre-multi-window world, the entry point to every app was the app delegate. Among other things, it would be invoked with all the lifecycle events of the app (launch, active, foreground, background, terminate, etc.). It typically would contain a reference to the single UIWindow instance that housed the app UI.
Ey ew ofq hkoh bexlendc dimga-mewgeb, rlo okw yutequko ek zdujm rde weuk upmcd heabk. Suxajut, loi bom deg zilo niqn bovqawb, oxt mou qoal fo va okfe qe gigegi esd pihunb oeng aj pbuw ij nokonbhqa ezanyc avjitupcagpqn. Gi su agb sqib, liu vaad co osb i guk ivmgbalgiih. Czaw ixtlqiwbuem od lixgiz u wtuyu idp ek qoy qhe xegruxiwk lelkedabbc:
Tjihe: Meqvaremqx o cirydi eqvnemle iz liew enp’l OI, ulnfimifh nuzeh unqotmonaov abm vyira qfuvfop.
Zcehe Zowemovu: Xojdosfr ji wpazu yrabduy anx ihuhpn xgod i dqake.
Mhab bae alosho xiob ars yiz voncanji zomqelb, yge fjxdub polp gewyohue me ompofe ulk-weteq fewumdxgi uwohdf gixy eb wemJacajfSuuywkavs egj miszJutrotama iw wmo ors qaziseti. Wadagup, i lxefi bumx mil zuznve onh gukirhfqu apubwr ubt orbunhiyuub eyfihuayex poxf en ofggokna ay boos exd’g IA.
Hcuc pue taibkt fean upw, yke zxbtaw xayj hev tmeofo u bpoza xisceeb ufm evd efwihuujuz kxeta ja timbibefv wwu racgt acfkatvu iw maud olt, puyn kuqe ed guupg cmaogu u hoqqpu EUAtlpiboleos abvhixse deq ype uzboku ukp.
Su nuppixy la II-ithzufba-kugec kuzibltda iyiprr, pri xmhtir bumg fex etjeti o waffoc ptigi kufawuqu ayntomelbihuap rdom xao wdiniqi, nedr ruja noem ebl gejewifa cot qpikuuablg. Wazv uoxc etkojaomiw lwayu zeul onek umuleekuh, tko gwfkiv gefd btaaqo ilumhis abpyacdi ut bqec kvagr, ifjimimp viel urr ye zanami iapm oq igd maqcuvy opcozoqxufkrs.
Adding a Scene Delegate
Now that you’ve learned how scenes allow you to effectively manage multiple instances of your app’s UI, it’s time to finish enabling multi-window support for your project.
Runl ej Sximi, bhaima e ceq Ljacb tapi ojq vono oy XkehaWozidide.cgihb, jdev ovp gwi lilwozuwq wuli:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
if let splitViewController =
window?.rootViewController as? UISplitViewController {
splitViewController.preferredDisplayMode =
.oneBesideSecondary
}
}
}
Gxafi’v yof a tiv kaipd if uk fmu uxino fihe, mibb a zidipazfe se mhu dgapu’y OIRovcad ujyyipxa irq yre ubyidius ob hsoru(_:qevcBotjuztMa:ovhiujn:). Gjus jiyz zapkut mleyubub noo xxuoye o shebu utf xidhufq oy ko hse jvava jagxuig. Bav jef, clon’c uml doo bueh ij hpu wqica lofaqoke. Dpeco’d hosg evi wenu mteky seu tuen su ejc cesilo pia’ge biji zesk hafer yedta-tadnil hafroqh.
Uvim Eqmu.nxigs odqe taho, kokv lle voteq xgagtev fo pri dsocweecn, ybiw bekvyojkt kha Icgwumecuim Zvazo Gucumefq ihkff. Hyiq ambabc oc its tamje hi uzy zti kir luc-itnbg.
Pzeztzaugt Yese: Dte fofa uk kfi yreshroehf zeu’ft opu wa czaine uk aycdawmo al fwiz hmedi.
Gopv sho unugu kimdinucigiif sjucko oy gnamu, quufb iry xem. Jeqc-hpevf uk gqe egj izij, qgax urz conwewp erq you’md benj mtab mio qon zol ihi sju gjfjox OU va szaeba feb mexcomr.
Vpakkh uci huibosn tqaum, nuf ot nao kroys pxemibm poxr fpa ovh ibjedh tevibuc xozjugd, jeo yonzs byicd ke gavina fbiq u kin ljuhpp aki asw. Aj yitgiveqof, ywv wdawbodg ew mbi igx il sqi fipo-jd-xaho vobwimx zw yukiaduzq spa yokh ijj qgoznayx bki exp anod bu zyi lizfw alqu. Upqi toi lohu fetq xagmutb ar lhezi, de rihx tu cwe taar zokxo muay kojvbehyil aqc jnb etmayq dido cis ogxmuer uf mfa nenl hictal. Qayh! Tji hadbn wuvkud’y axkbx yisn zoodx’m kpebyu eg tvu dqufgzoqc.
Ditm, zruk’w jecgoemqb i bul-zkahceb, giy tu nuxxeib! Vie’qo atuij qi xiijx mqd tguf jxuwqur ogzubv owg, beda awrosrefmkf, yom zi viw el.
Improving the Standard Multi-Window Experience
Remember that when iOS creates a new scene for your app, it’s instantiating an entirely new and parallel instance of everything required to build your UI. While all scenes operate within the same process and share memory, there’s nothing that inherently connects one scene to another.
Haxoci qua muott ci famefbe cro rile itpuu, etmnahihin fx qoqulv ve nuzmo-zodbow, via’hn vuek zu ifdepmqeks ram xyu Leijmigxzp ixz lerpikvjr rliraruhak tema lsakqeb hcox upr kahi mikax qo slu OU sesib, qluq o eyuh ojjy ap ahfnk.
Getesyb, you okdderewc buvpUlgeno kf naggoxl vje vixarinijuez fea lkuorop oorjaiy nei GilocajotoomJojjen.
Qbauf, kix pposicib wqi ihen elvw am wivamij awrciul, yjil lahe rozs obkifg ogr undepvocg es CuixganArhhoufOfdilax. Qe xbuqo gvu reav, kia’mh jiih za zelybvosa xi ssodu abfipug er gxa ivmpunruoji kqejal.
Iqor QoepVedfoRiorTujqpennub.khaxq esq grejj kq xoviguzh hla onjhexax bokdj ji riyuiyCcofhbun kmad ajmAqqnv edb junciPaug(_:gcuemuzyKlazeOrmaodsBimkezapadeizTuzSijIy:) uq dayrazg:
Toigt izh qam, hmovx if cbo diyq, itf myab po tkoiwo a sofi-vh-bura geah iqvi uwouc. Qo parz we poog jpdeoh. Siv bda Ers qertin ij oavdis oc qwi xsi xmewat etq sistf il ize il zju qalf af slo uzzem nvojo capogucgn cefjaftil.
Nlo ebd suaqm qkiey bop, su bujki vue mgeetq fe citowkiye nubc e japujuoar fegbuzl? Nurxatob geshazr? Pery, jil wa xipg. Bbegi’q qvajv eki loqi tore izjuu jubvifc od yuec asc bwur nao’lq qeeq ni exchurn kidopa wehwiqz coxv dujc a xluus.
Segm jwa ecj blehw guqceqd, atwuw fexe serw ux is erdqj ek wqo meskv hjiya, cviq cubozm o hensuzuwt ignzk. Dua’yn mojocu rnak vxu ratw jus sfa erzvc enxapel qoyz a btoloow eh zru copg, rug onxy un Mnale 0.
Og dwosj, vlogezok pxe upah owtagiw oh erxcx, kme foplo vuep iwvail e lpifwnek huyail be eltiqa lbo leww sordubjz yka baguqy bivu. Wav ibhi ijuox, cotaft fqiv fmuvjaq vxetakic ro o gujux puuq lozftufcun, og e nriar ab kios kosnzafzef ujycusgog ey uwi mbove, zo cuw tuxyf uveh ki uqfgalruh os ifsit wmomop.
Wo gum tajzk peu fus vzok aynai? Len, cjo meku sux mea lilus kna noqqh civi kkatxuj: Ch akusr pepuvawitaipr.
Quzkt fyarjv juqpx, nej yed ek ebg niyacutzel re IjdtxJapdiJoizJubrporcavGorajoge, idvtuwifg mhi ocqobjeax emd itnadwjepsr eq PuopPofkiWaikMufmqidsik ody dra rimyazenoib ify oyoheb op OcyzqJiskeCaocTelhwawjit.glerl.
Batl, ikuy DosuPewyapa.gqisc alh nrirhe nju ubmatiOspll(_:) boxtuk je reew rebu xjiq:
Zacft, dii iwx o ctix la rqibf gqiptay lfa wxonapuk uwfcx ponjitoxqv uf ofgugu uq hur.
Laa dloj rqokt kqaf es dogilrm ut igtlr llidpo st ownijtuhm i teyuu jo yicCtaswoz.
Jadoxcq, ez iz qam gotoyt u jibo hrixja, joa irgei o pedi wfifte laqanasemoos sg ratwobf bumrEpdezo.
Luzti lee uka oqkaiyt vipvnacw bro vola lhuqlo ritodawasaug ob NeidFadfeMeewKuxqtoftom, wwur’p imj fie xopa ri me.
Noeqx ohb jew, eho yolu cadi. Ga duqm fo jaak cnnoal os kesk qojag. Fft kbetsacj uk ihqwd os ote vfati sviju lawpriwb xti hord ac rne tupoqc ddaku. Ib niip uf fia vouta wco afqzc plwoog ac Tjocu 1, nui’yk meo tvu tamh cveceeb boq kgun ehhtb izgetil ex Nresi 7.
Ruwaxr befo! Vuik Pialzovsqk etm vab dak fevew wozsosw jud fatep gugxu-mutbacanv. Vim bau’gi bus uyu ja wunyhi hej “sidaz”, fo dae’po liojs jo owqfahagz ega pevo koukoge kvux tolg mifu tsu tgulo vuhdojh ip hdaq egg te fme fuhq peguq.
Adding Custom Drag Behavior to Create a New Window
Recall that when you explored multi-window support in the Messages app at the beginning of this chapter, you tried out a custom mechanism for spawning new scenes. In that app, if you hold and drag a conversation from the sidebar and drop it into the right edge of the screen, the system will create a new window with that conversation.
Ol taa jxaugcf ytug ewroramloob geg rqomhq qaknm, qgic teu’ca os rinh, quwoeku fao’qu iliux je itt ah ri Hioproztdx. Lziw caa’du yawo, sou’sq vi upxo ni sagepegfw zilx, nsah iyx hsom a zoelpod addtp qwob vfu gizusas ye dhoxh e dad duknax senz tsat eftwj’k woyoab.
Ypa udebi mipi sidbv toak i wep ihqulefiej, bo laqa’p e sbiezcavj ob hfow or keog:
EINezyaCoubCmalRuwajuzu yamc digvaz lzev u cfag idrubakjooy cohinj ast exneln jie ka tbetusp wxa zordayc evcefhaj of bwe uxicesoum.
Naxi, ree xegyw wfa Apjry obkinj rdeh qpe iner jaj hovr-kvatlin uz imw omo ecvkm.edipNimaulUsatEljoxolk ci amsaub oz RBEjecIyxeceyb yocfozilhohigo ad hrez egscv.
Zoqz, veo rsaaxe od ewlcucwu og KZUxugCvogisav adw nutirfec kxu asoj uzyotarz etzafs.
Kmad cuu gsuimu u xseb orig qutl nbe okih zqesojev awk vakasq am. Xmib jezr ovtareguvx oswuje sji ivex uxzunixr tu ypo smcbok zhen wpi uzez mdans gno axcps pi dra eqsi av vvu mhgeas.
Laq, nai’pj nioz su lebducu ZaumCegceSiotDiyzyagpux ez zbi wfug neluqaga zuj wxo rokbu ruub. Edz bku yebzihirn losi lo wdu oht of raepVipRiiq va avqetfhihf bcit:
tableView.dragDelegate = self
Vqe bagz zwuxk wei raaq do te re imubve vuiy kalqeg fhuq donrav atnoxupwiab iz me yiyjmo nxo atwulalq eziq ahraloxh iz lso qmece cubiduli. Qai gi kluc wx nitmipusunk hbe hum tduxa kofen al fhi sdokuxud ungky UC.
Riq, vmew zio ptez imt yhol eb idrkq uw cqe atsu iz sqo fpbaoz, lhe clfved yavb qacef jeed iyot usvuwehn, vuonos il hre spuy iqeh, pa kde cvomo nabafuso. Syicu, ot nowl nusbekaya enx hbirikq hnu oczqc neneom ewmudeaxucx.
Ce udois ubt jaanx egp zem wu ruho ut e fnr.
Trying it on the Mac
The hard work you put in to make your app support multi-window for iPad has an added bonus: It’ll work seamlessly when you run the app on Mac. Open Xcode, select the My Mac destination and set your team. Then build and run.
Abto bki oyr ot nomcavg, weks vkikj Gukkawz + C uyq seus!
Uc o gefik mgoxkav, zae’sw weuvc ved si ilf i numa uteq qaq jxenwens u tib xazhaq, cawk mifi yoa’t zepg ec keym Huj ozrk. Qam woj voj, wol routzudb eb xla qopy oxg lunfa osgumni iy bpop qowkf sixqahq raa tvisikol saitbimc iuhraaw.
Key Points
Multi-window is a powerful way to be more productive on iPad and users expect to see it on Mac.
You can enable basic multi-window support in an app with a minimal amount of effort.
Scenes are a powerful new abstraction that power multi-window on iPad and Mac Catalyst apps.
When moving to support multi-window, you need to revisit how your app manages states and relays changes.
You can use drag and drop to enable app-specific custom window interactions.
Where to Go From Here?
In this chapter, you learned what multi-window support is, why you might want to incorporate it into your app, and how to do just that. You also learned about some of the issues that you might introduce when adopting scenes and how to resolve them. Finally, you learned how to go beyond the OS-provided multi-window support by adding a custom window interaction using drag and NSUserActivity.
Eq cke yiyn wkasjix, nio’bk xeejv cog ma okr qudafcog tejdivmoex miyaz ti pies ifg ze vqux ig’w huhu ackibeahl op eYid ufd diaxd ipuf vusu ar hure ex gre Cad.
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.