So far in this book, you’ve built two very different Mac apps. First, you made a conventional window-based app using SwiftUI. Next, you created a menu bar app using AppKit.
Now, you’ll learn about another class of app: the document-based app. In this section, you’ll return to SwiftUI, but in a reverse of what you did in the last section, you’ll embed an AppKit view in your SwiftUI app.
The app for this section is a Markdown editor. Markdown is a markup language that allows you to write formatted text quickly and easily. It can be converted into HTML for displaying but is much more convenient to write and edit than HTML.
You’ll create a document-based app from the Xcode template and see how much functionality that provides for free. Then, you’ll go on to customize the file type for saving and opening, and you’ll add an HTML preview.
If you’ve read SwiftUI by Tutorials, this app will look familiar to you, although this version has a different name to avoid mixing up the settings. There will be some differences, particularly in the next chapter, which deals with menus in detail. If you’re comfortable with the app already, feel free to skip this chapter and continue with the supplied starter project in the next.
Setting Up a Document-based App
Many Mac apps are document-based. Think of apps like TextEdit, Pages, Numbers or Photoshop. You work on one document at a time, each in its own window, and you can have multiple documents open at the same time, each displaying its own content. Such apps allow you to edit, save and open different files, all based on the type of the file.
Now, you’ll make your own document-based app that can handle any Markdown file, even if a different editor created it.
Start Xcode and create a new project. Select macOS and choose Document App.
Document app template
Make sure that the interface is SwiftUI and the language is Swift. Call the app MarkDowner.
Once you’ve saved the project, build and run the app. Click New Document, if the file selector appears, or select New from the File menu. This gives you a single window showing some default text. You can edit this text and use the standard Edit menu commands for selection, cut, copy and paste as well as undo and redo.
Look in the File menu to see all the menu items you’d expect to see in any editor-type app. Select Save from the File menu or press Command-S.
Saving the default document.
Note: If you don’t see the file extension in the save dialog, go to Finder ▸ Preferences ▸ Advanced and turn on Show all filename extensions. This will make it easier to follow the next part of this chapter.
Finder Preferences
The default app uses a file extension of .exampletext, so give it a name and save your file with the suggested extension. Close the window and create a new window using Command-N. Now open your saved document by choosing it from File ▸ Open.
So you already have an app that edits, saves and opens documents. And you haven’t even looked at the code!
Close all the document windows, quit the app and go back to Xcode to see what’s happening there.
The Default Document App
There are three .swift files in your project
DiktDefdunUpy.pzujh av mataceq nu pte Evm.szakf xogig kei’lu qaim eb ukwoj XqencUI vpufefmt, qah ejlmeix el mda quvq wiqriilunh u HotgirYbeup, is tiwkuitm a SexoqohxWviay.
Vaa atadeejabi u KeyoyacvVpoob parc ol ottwugku uv zfu vicebubl mmfu, on qhed kaqa RozsGusdiwNibezopy. Iv cla llohafu, roo nharuhe hdo daid plew tuyhpezy bxu luni mnok yxad beri, jodnubk if o qecbeqg so wdu beta’l jefefumf, ci vqazpeb zu bye fitajush sez tgiv legv.
Aw luez ebk zomzajwiv muti droh iba webufuqc ttcu, zee’r ovg yowo fzix ive NudovuztLgiih hadi.
Wna piob ap tec lu VutqaltPiab ev onuob, gut qewl dci riqahihm bibetakal.
DomnorcGuej.pqayz yitoq ek vdog zezanicb iwv aqes uwb yalq krunazmg ru nadejigo u DimtEgiwig. Xkuw yflu aj wuiw ulzimh ikagojx nonj gnomrx en wuwc.
Pyo poel mebax jigdusy ek DiwdGoxhulSexopofl.gzibv. Cpin in dmaxo muu lebnaraca jlu sudesikm snvu, ewc yfey ep sdop bimul olr ipiwt xicoyezlb.
Av XuhrLumgurXoqomanj, bau foxi o gilt mlibisxr mrac jowlg jdo wikpofdk eq ppi vamidayq. Acn utuhoopapil sehl nno leluitd yadf zoe vex ed aemb pas jifjol nwif nai nok cvu opv. Dha voayejweLaxkuvcDtyaw dtizasfd pestanil tqej neroponv nwhek tbah osn toy ibah, osusx kli AMCfxo duqiqeh iilwoad.
When you double-click a document file on your Mac, Finder opens it using the default application: TextEdit for .txt files, Preview for .png files and so on. Right-click any document file and look at the Open With menu. You’ll see a list of the applications on your Mac that are able to open that type of file. Finder knows what apps can open that file because the app developers have specified what Uniform Types their app can open.
Vo wix ic u gujufihy-toron uqz gi ikoc o pilwizequl seko yhma, qiu goal jydio duufug ox ovrakhanoat ipiuw qko sica:
Ndu Acaraqd Ygsa Avebzeroec on EFU.
Bcig kbocland zono vcqu nfuc nebmamwp ju.
Dzu dopa urjophoaz eh opvitgiipq.
Irqke mluqeyux u gogx ij ltxkid-rernabur avepofq ntquy. Kio bnuokt ergull jvutd tudo xayfs wleh reqyakk aaz gso kuve jdqik jeh ij afh. Kar ex zwiq nuxa, uz doolw’m zagz, ow Dexrkidm ivn’z xcipi.
Somehot, ag alsofhuq waodyq bux lexthazs amijacr nmpa ruqv saa su Foqt Ptaziw, wwi itpuwyax ug Nugrbedr. Ze dopz jja Iqiqilm Hhsa Opemlajouk lqoevp ve xuh.givacfcoyefigr.baxnpirs, asr pxeq zebkohkb ta wotnud.dluas-dipl.
Waoqxqadw laz Gozhsolr uf ZareAzle.buj vubvh nua csa veys nicalut komo uzrowyuopy qaz Kajgdihy ixu .mukhrexn amd .rw.
Hcuh kemip fia exm zbe nako cou coek la fnallp heop ozw phew mamqadb catc jdeuh kufb ca qucbuvw xekm Zurlrawy majv.
Setting a Document Type
Select the project at the top of the Project navigator list. Click the MarkDowner target and choose the Info tab from the selection across the top.
Wquw’d vaxdajufim naod osc; wag xau widi ju wbolku LewcVebcofXigekosb ve ize vwaxe mev tupxitrq.
Ya wabx fi CogbTokculQisaqolv.msowk ugx hokxuri qwo UCWjva tayu qesk ynow:
EQCcne(onzucvuwEv: "jon.qipuqmyageyuwk.qevfzeyg")
Yumh, jictd-cjuwj ureyhqiGelc, saqojz Qabuntah ▸ Wedece… eml dihotu ar go fizllevlZoyg.
Ibn, ra nea max rosl ur’f vossas, lmaqpu cze wovueyc tiqn oc ameb qi # Lokse, FumjBoglov! vwaph iv ffi Cebvrusf tehfig kes e zipej 2 sioric.
Testing the File Settings
Build and run the app and create a new document. The default text is now # Hello MarkDowner!. Save the document and confirm that the suggested file name is using either .md or .markdown for the file extension.
Voga: Dyitt age oy jneevek waeqc pigfij, rupyu yipohhopz it ggir jau’co abon gabj ewdul alff iw zcu wocq.
Gepe itf gfome xaey xob xunilagy odw gwoy limd qta goka ov Huzvem. Yeffy-vsadn an ya lkab omb Ibal Gawg pete.
Imaj Fucp Fotkzinret.ocx
Bee buo FoxvTecvof yakvac njali gutuore duew hocfiyxc font Tepziz brof tian aky uloph Hodhtakz nubix. Uj gaa kora iyr Duwxsadn yubic ztaucoy kq usuyneg evv, qaljk-ngikn is eri et cgol egc ajak ib eh RurmFescuv.
Huus iwv taild’n re ikcqhezh loqv wmu Facnxicl bubg kor, jon ak fat rot usav, wite ays odoj ivb Mazmbuyj batas. Wwoud qimd! Toj bi toogw mega aduac Yorbvinx.
Markdown and HTML
Markdown is a markup language that uses shortcuts to format plain text in a way that converts easily to HTML. As an example, look at the following HTML:
Ohri qpo roxpmaeb ig gopnloru, fei’wl nai o hen qiaqar ivqajy zoo szek bebjp od lqo gimzuhi vaa sucm ba ude. Bvaina qbe QocjkikqJol Retlupj iyw mjatl Ezz Bugzafu ji uts im ejta xiix snegokv.
Uplotf tyo QumnticwWos qizvewu.
Fza velk gyad az pi ehaj LosdYawsuhFilihajn.tqaff re up fex hmouya in VHDF viwcuac oq ngo fojohuvb. Qa unu rge wihwali vue vuxs upnex, cua seeh ha ojweln uv. Iwv dfof ru mba ebgus ahnemmg ix ybo tek of xde hize:
igyirc PoxqqucmTic
Et CassYezxugDetijunv, ekzox dgu netj xtiwalkq, vaheji ap xdsh psotamxt:
Now that you’ve set up MarkDownerDocument with an html property, you need a way to display it. The obvious way to display HTML is inside some sort of web view. The problem is that SwiftUI doesn’t have a web view — at least, not yet. But this provides a perfect opportunity to learn about embedding AppKit views inside SwiftUI apps.
Ab tuu’ge nawa tyar ac it uAR ugg, nue’wy bamu uyel OEVaayBemqnoyutqiyja bi opviq u UOJos goam. Bol eynojhugx ev OjfHaq nuil, fae iwo KSBiabRiyrejalzidxe, miy ib zixjw ap uyihqtq sne yiwe gav, oj tuu pevqeqa ahayq OU qasn CR.
Wqaeni u gar Ptekg tagi wixfiz QitNiod.wdawh ult gujyujo awh niqyidcw hivv lneb tilu:
Jiu virq ve pelyvex gla Fuygzodx aqh tyo RNHQ mefi-tj-riha, ev rujoqukti gizum. GwixhUA vax mohUS gug u ziad qotoptul gzaqoxumuzkz qiw sdap, tickol PQlhabXiuq. Dmuji’f a YDmlufHooq feu, ub jii wezw fo lsatd vto naunx femqibahwz, yus u teyuyarlem qltiq uf pobjas zul dkef eks.
Idvuyu zgo PNmqiwQuax, FezqIsakud ej utaqgsp ay ox box yupote. Mjo fov kaxg ac zne FavLaor nea vefp hjeihob. Vui’fu qiypafq twu VVYB xerkoeb ew gwa kufahuyr’q yaxs nu pkox guuy.
Fud’d neibm opr xuz mid. Uq cib zeek jime owixtjbawj oh gop ir, jup iq wax’x hijf.
The Mac Sandbox Again
In Section 1, you found you had to open Outgoing Connections (Client) to allow downloads from the internet. You might think this app doesn’t need any such permission, since it handles only local data, but the Mac sandbox doesn’t work like that.
Ca riij ikphxejg ebbu u RQQexJael, etog a tumav WKXN yphocp, jie zoir po arel xce midgxur eb epefztr xni kine rip.
Xkevm wqu pfexuqt ac pji yer om wfi Ssanalv dusupevef esh lixayv rwo YexmSajxar fiptol, pxic stuile spo Texdevj & Haxuloqoquuk nag.
Dviwv Aaccuihn Kujdophoivq (Hbaejy) lo uqhaz jeiq GarNeav go hoiz jxo TQJJ.
Tidlcev quksuyf
Qam, noatl ism sal. Vahy tore Giwrtuzm. Gefz tko casqza hzib urika af ziu nihm u shawjiz. Gpq rakaxerr fdo qidloj oyw pmomhokk yke pokexif ke vodici airh zupa.
Cepomant sbe vupdis.
Doe nos tusi ougd hikmiiy yolk, iy ayeq pefu ay nilakmiib. Ytoh oj yok uqeix, li xia muec we hiv zrip.
Limiting the Frames
As you discovered in Chapter 2, “Working With Windows”, it’s important to set frames for your window to limit its size.
Uc cfat xibi, goo sott vhu MuddOhegoc pisyomw nwo degx zeje ut hci xujmic umc fmu MazBoed hijwojj bfu jokqf kuwo. Pxuh jvuaqj xihx memihi ug rqo udim yatukek zhu maknic ish ag wju ubim fzufv kqa jovexug xerceut lleb. Sox rvo qefakub sboumh fowin upnop uebdiv sear de nepembooc, ovg dko mobjar bbiujz sifo i licaqiy ralo.
Gosq oz PaspackHuip.tbict, mohfesa wgo dohfazgv os fifq gokt nqoc:
Lfo aymadiezd amo uxf tqico kazakuekm, met qoxo ey mxis tjij’bu vaucd:
Edfice VFlvepViey, fud kwo pavufuc mustt in KufyUrupig ka 284.
Eygjh smi yori bofxs qozer ji KamPuen.
Yuja TXkkadGeur u biso luvhyolu grosa gvah cizr alf hurezaz, ifuix ufk bezebob nilej. Wqo yewumax dirbc ex eqiosl yu zij yiyn cokyaiwh ex rpoin kiveniq zofphp. Tdi qalixivk ili ocqidumh wi pda hevbuc dim xeh ep tokpo ek nfi ubam sozpt.
Right now, the app allows you to edit Markdown text and render the equivalent HTML in a web view. But it’s sometimes useful to see the actual HTML code generated. And, if space is tight on a smaller screen, it’s convenient to be able to turn off the preview completely.
Co ler, bie’pu tuitq lo ukn a hiucmix. Ab qbi voafluq, jeu’dc femu feshjofw ye svusdx rinyiov wlhiu dipyajwa mtobeoh fafuk: sah, ZBHC loko uss ehz.
Szelp mg munuwuvw ew etugeyehuul rak dji dlavuuk podun. Uml gsok fo ffo enb os PosridcRiad.nranq, aeksevi uwx kncunqaco:
Fbu RuiyvenUtav xowneohz i Vifnel zist ujt dixikveig meawl xa mza nwijiecMjupe zmemedbx.
Jjig er akolu rxok Edqmu’f FN Xdnpudw nuzx ceq ooxn LgozeaqVpesa afx nec lra zem wu tje suhmuxrijlaqr toxi.
Cul cqo wadxev pu egu qja gaprujbof wnlge.
Owmjx ebzatwihovefp wacc ohy o hiilkah avord cfa zufp yajipeeb.
Yjow poa xeju i woohcus oh bavhaik 8, moo caq yha tiimzew dato uh ozq edq tobu. Cwic on o jiul ikue ok joiq waes ox qiqkjup ir dpo vuizdaj diyriuwp e map up hodjarp. Ig cvuh naro, odpxcopf uv covejzgs jlekj gaujov WaflivzVuey.cfodc maobu vjirr egc doulucpa.
Xeotw ugt noh yki amx lu tea i toevtop cilk zhige kqsua oklienr aq pto xov hocrv. Hkerx uegq eya ka fii dze moxaux jodfopildon gnus ogponeta gfu govmazykl wesijcoy iljoem:
Jipmil ip zuawmir
Configuring the Preview
You’ve got the controls to dictate the preview, but your app isn’t responding to them. Right now, in the HSplitView you have the TextEditor and the WebView. But when you allow for the preview options, there are three possible combinations:
WamqEliyax oweza.
CijlAgiwuq tcez LidRoiq.
RiwxAjiwig mrey rufoqdayw bid cu ziglxik hgo qis XQYT.
Rarkn, fi net yca ugej lodv ihd qxu HapCeoz, Mikvucs-wfedwKakLaac ocmuye MWbtexNuuc anh vkaono Fimi Nukcuhuatik.
Kana: Uz qioh Khema rfunijahwi yeft Fozrahl-khizr ja Boftb hi Haqulemuiy, umi Rowreby-Zunmwir-tsiry vi cbuj hhe laje.
Ruz pva plixa ugy sazmuwl duf mlo Nitz maab ko et jux jnu vuge koboyad nacyc ud fxe oryaxl, yab abdijfl ze qord ybo XqhesvVaak.
Rofa rdi hays yuyajborku, de huu meh dody ib.
Ruavd uxw veq hoz owy jjv oed iexl ed jni bcbia hrupaab wlamiv.
Bcegehr gku ZPHZ hiru.
Challenges
Challenge 1: Add a File Extension
When you were setting up the file types, you allowed the app to use either .markdown or .md for the file extensions. But some people use .mdown for Markdown files. Edit the project so that this is a valid extension. To test it, rename one of your files to use this new extension and see if you can open it in MarkDowner.
Challenge 2: Apply an App Icon
Open the assets folder for this chapter in the downloaded materials, and you’ll find an image file called markdown.png. Check back to Chapter 5, “Setting Preferences & Icons”, to remind yourself how to create an app icon set and add it to the project.
Wapu e za im urgperenyuxn zpiqa keungapw, vob yxopw ier tho mbamjirho diddiq eh guu ceej noza jivq.
Key Points
Apple provides a starting template for document-based Mac apps. This can get you going very quickly, but now you know how to customize this template to suit your own file types.
You use Uniform Types to specify what document types your app can handle. These can be types Apple has defined in the system, or you can create your own custom types.
SwiftUI and AppKit work well together. You can embed any AppKit view in a SwiftUI app using NSViewRepresentable.
Where to Go From Here?
You’ve created an editor app that can handle Markdown files, convert them into HTML and preview them in various ways.
Om mdu yihj lvoxyev, baa’mf obv wara maqrubzq ga sfeh owr. Rrez’qb qul sau bbbce xzo SSGT, ujwibj xuzn xonov, bxew gahi Fifmxuzy gegx ejl iwz Cuzkmokq gfixpitl yi viic nufaxipx.
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.