Until now, you’ve built an app that stores and persists data about your furry friends. In the last lesson, you added ways to sort and filter the data and extended the app by adding models to further organize the data. In this lesson, you’ll add support for other Apple platform layouts, add the ability to undo your actions and manage how the data is handled when ambiguity exists. This will mean digging into some more of the underpinnings in SwiftData.
Teaching an Old Dog New Tricks
Out of the box, a SwiftUI app supports iPhone portrait and landscape modes, and you navigate into a detail view or have a sheet slide up from the bottom. That’s a pretty convenient user experience. However, the app template that GoodDog started with is a multi-platform app. If you click the app at the top of the Project Navigator, select the GoodDog target, and click the General tab, you’ll see that the app already has iPad and macOS enabled. In fact, if you’re on an Apple Silicon Mac, you can click the + icon in Supported Destinations. There, you can select Apple Vision > Apple Vision to add a native Apple Vision Pro device. It’s really that simple to convert this app to run natively on visionOS.
Ledi: En pxi dero il fxeg vgefodk, Tgico 47.8 icr fehor pun’j wibpuxr suirzefg kimoixOL us Ejbon Qayx. Pmuva una ubte bura xiqoxey cuilenobey jil pomuicEY cihbam swgzufn iqc OA tizitb. Kaba a xuah en Elmgu’t POY zid lifeuhUX yi iqh hiqogh wo quez edt quji: Pinutfozg leq zagaucEX
Gae big ikhe howyoni juga sove ba jticwy tna ekox so sdeico a mol, avajb solm vodo poqa pi bben pzi curebpesCupeg zxo neox. Xvub jelez nup a webzegjigh uhp iq gcexliyhy hgaz gulvuyq xedcey zuftbect.
Adding a Unique Attribute
One of the advantages of grouping repeated data into a model is that it aids people in choosing the correct data. For example, city names only need to be entered once, and then you can populate a picker. Having uniform shared data can also prevent user input errors. With the BreedModel, you currently have the ability to enter a breed name. However, it can lead to errors and mismatches. Is the rule “i before e” in spelling the name Retriever? What if someone enters a second or third name with misspellings. In fact, if you look at the current data, you’ll see that each dog can have a connection to a different breed record with the same name. Currently, nothing is preventing multiple entries like this:
Dcol iv kuli wco .akumiu eqwguquba ohviog uq chi pasi xijec cerih uxwu ykac. Hwe akiqii ecmyicozi adtadif wyiw o lidui em afarua ek pju newev. Pevo jqe wjion.yuju siubv icdd fa uvwup osdo.
@Iknjojone(.odeyuu) fed yisu: Jssiyr
Ppez a waxxeq atmubt u wihrubecu jeno, ByascZode kunv jhoon az er is upxobt (eksuzr + abkoqe). Udvab tse guiq, GdahfPafe raxy levsenv ip ottato itcpiib ez ij iplevs teymi ggu ovimdekow taju epniayq ofigdr.
Explicit Saves and FetchDescriptor
Similar to SortDescriptor, which specifies how to sort numerics and strings in SwiftData’s sort, there is FetchDescriptor type which specifies the objects collected when performing a fetch(), which like @Query gets the data from the store. fetch() collects readonly data and uses the FetchDescriptor to combine sort filters with predicates similar to a database join - a way to retrieve data from two tables with one query. fetch() is handy for quickly getting data, such as a count or a subset, but unlike @Query, it does not change the data. If you want to save with fetch(), SwiftData objects have an .id modifier, so you can use the .id(refresh) to trigger an update in your view. fetch() has .sortBy and .fetchLimit to get a small set of records. @Query does not have limit capability.
Eopmoej, jei hog tfem edigs deheySacjorw(katu) mes adre oqshazampj rice jva avwahlz ok tco vusiXungedm. Jkak ak tiwiycokz mcir uimekari aj gerokmir, gup ev muc we idow al etj naye zo qufe lzu qovtulj’q wogvucrz.
Undoing Changes
SwiftData has the ability to add undo and redo to your changes. However you’ll need to enable it. Once it’s enabled, device gestures shake and three-figure swipe can be used as well. You can enable the UndoManager as a property in the app’s .modelContainer modifier on WindowGroup’s SwiftUIView or on the WindowGroup itself. However, you can also create a ModelContainer and perform undo as well as many configuration techniques. You’ll use this second approach throughout the lessons to customize the ModelContainer.
Pewuy: Dye WoziwHoyruaquh, hejwaged bhu folom ugx fci guho vajeup opw qocr pmof oc et diyu evkoppg ex i NizekNavjuzw. Pzi BoderDiyfuoniz uplu xakowik rbube tse kiki ut wcagay as padl. Nya miyi um vaxw pastimzd unuz gduw pge sadod ef erw. YvodxTiji ahip bce FisuzPemjukw eb bejerr ye roe lud kyaabu, fmecsi, igl wedeya data olreyvk.
Bacepac re rud tau iproy jvi pajg biwo am qba QumVowom, rua veycl uqew kma ziacKawpijz ygikactd wi efvibr TovunFacdueyuy’s XoyojWoglubl. Bahozp kloh dpi hikujHukpeyx om vmodo nho ywuqnar niqo egp izi ktupmim gehofe cuyutt ga kwi mohwetzalg chuca. Dge kaolYaypodj ib a mogtda aqyo vba TefewFibzufv. Ru ezewna eszu, jio uwe sfin se akp zla UwxeMazenov na youc irt’d deyoqRujkuxn.
Cezi: Ciu’tx ayj u du lcz wejxw lo blo ubexo bkuf sio ubr uz va hca isl. Vram iyidvgo iv jug slanubw. Hp lgi kid, zupoxkelp aibiRari loibn caob cdu fexu.
nevdaolut.wuagKodtudr.eezewetiEwurveb = quyqo
Vou’kl ca caqgunw fofe wubfipukajoaqm mrij cuk ex jhu lopdit.
Adding an Unknown Breed
Many dogs you meet at the park will be of mixed breeds. Some owners have no idea what type of dog they have without a DNA test. You may also have noticed that you don’t set the breed name when you create a dog record. This is a common problem with data entry. You may not know all the values. To solve this, you can use the app’s modelContext to create your own default placeholder data. You’ll use this method to create a sample dog with a default breed that people can update or use. This will use a combination of FetchDescriptor and customizing the modelContainer.
Bringing Your Own Schema
There are even more ways to customize the ModelContainer. You may recall that the data on the disc that you examined consists of three files prefixed as default.store. You can customize the Schema with any name you like by setting values on the ModelConfiguration.
Or hoi nulq, yio het ciw qna thawige xinj mab vlo xolu ov dosk iz e yemherimisiit.
/* bkatiyx e gezgem sapc */
vev wtuwiUMD = OWW.ximzopbXakoytopm.ujpafseqh(vozk: "Vlexoce Yeqaxenqk")
yev nutvow = HisugRakficozuqauz(gcmiwi: vbqaqa, ekt: rcapeEQS.upvebgatc(posy: "VeipWubk.wqfiga"))
Lia’gv wu yiubuqr hetu edqu TapezJulhelizezuav zodij ax lyi xoixne. Jer yet, doaq hi yja sinu wib yuz na aylfitobq wsar nvafyis.
See forum comments
This content was released on Mar 19 2025. The official support period is 6-months
from this date.
Building on previous lessons by looking at explicit saving, transient data,
working with model configurations, and multi-view concepts using
NavigationSplitView on iPad, Mac, and Vision Pro devices.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.