<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Coredata on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/coredata/</link><description>Recent content in Coredata on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Sat, 26 Nov 2022 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/coredata/index.xml" rel="self" type="application/rss+xml"/><item><title>FriendFace 61 Feedback</title><link>https://blog.iankulin.com/friendface-61-feedback/</link><pubDate>Sat, 26 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/friendface-61-feedback/</guid><description>&lt;p&gt;As usual after a challenge, I compare my efforts to Paul&amp;rsquo;s model solution. Just to quickly recap the app, it sucks up some data (Users who have multiple friends) and displays it. The change in this challenge was to convert it to add that data to a Core Data store so that if a future network error prevented accessing new data, it could still display the old.&lt;/p&gt;
&lt;h4 id="merge-policy"&gt;Merge Policy&lt;/h4&gt;
&lt;p&gt;The first difference is that Paul adds a merge policy. A Merge policy tells Core how to deal with any constraints defined in the data model. In this app, I&amp;rsquo;d defined the CachedUser.id as a constraint. The purpose of this is that under normal conditions the app would be picking up mostly the same data each time it started up. We don&amp;rsquo;t want scabs of duplicate data, so constraining users based on their unique id is smart.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-11-23-at-4.07.02-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://developer.apple.com/documentation/coredata/nsmergepolicy/merge_policies"&gt;merge policy&lt;/a&gt; tells Core Data how to deal with these conflicts. The policy Paul uses is mergeByPropertyObjectTrump - basically the memory version of an object (in this case the one just provided by the JSON) writes over a previously stored version.&lt;/p&gt;
&lt;p&gt;For testing, I had commented out my &lt;code&gt;try? moc.save()&lt;/code&gt; otherwise I might have been reminded to do this one. First round to Paul, again.&lt;/p&gt;
&lt;h4 id="data"&gt;Data&lt;/h4&gt;
&lt;p&gt;The data model and additions to the managed object source files were all pretty similar to mine, except that Paul left his id&amp;rsquo;s as UUID and it seemed to be happy with these being written to, so I need to look into that to understand what I was doing wrong,&lt;/p&gt;
&lt;p&gt;As far as copying the data over, Paul did it all in a function in the ContentView - I preferred my concept of having these as methods in CachedUser and CachedFriend. He mentions this, and it sounds like he agrees with me, but it&amp;rsquo;s a tiny project so no matter.&lt;/p&gt;
&lt;h4 id="mainactor"&gt;MainActor&lt;/h4&gt;
&lt;p&gt;When outlining the challenge, Paul went to a bit of trouble to explain the way to avoid a clash between updating the view (based on the data) and updating the data using &lt;code&gt;await MainActor.run&lt;/code&gt;. Without really knowing what I was doing, I put this call after the fetch for the JSON. In Paul&amp;rsquo;s version he has this inside the fetch when it&amp;rsquo;s complete. This actually makes more sense - with my version I might be building the Core Data copy before (or even while) it&amp;rsquo;s being fetched.&lt;/p&gt;</description></item><item><title>Core Data basics – Part Three</title><link>https://blog.iankulin.com/core-data-basics-part-three/</link><pubDate>Thu, 24 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/core-data-basics-part-three/</guid><description>&lt;p&gt;If you&amp;rsquo;re just stumbling across this, perhaps have a look at Part 1 where I layout a simple master/detail app with the data held as arrays of structs, and Part 2 where I convert that into the simplest possible Core Data version. In this post, I&amp;rsquo;m going to add the mechanics for the one:many relationship - Each Garden can be associated with multiple Plants.&lt;/p&gt;
&lt;p&gt;I should also mention I figured out some of this with help from &lt;a href="https://www.youtube.com/watch?v=xgPlJXTfiNA"&gt;this video&lt;/a&gt; from &lt;a href="https://www.youtube.com/channel/UCxnCA5FBYRCFgIZWD0CKCVg/about"&gt;Jonathan Rasmusson&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-11-21-at-6.41.46-am.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;First step is another Paul hack. If you look in the &lt;code&gt;Garden+CoreDataProperties.swift&lt;/code&gt; file where the Garden properties are defined, you&amp;rsquo;ll see that the &lt;code&gt;plants&lt;/code&gt; variable has the type &lt;code&gt;?NSSet&lt;/code&gt; which is not straightforward to work with. We&amp;rsquo;d prefer it to be an array of Plant so we can easily turn it into a list in SwiftUI ways.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;extension Garden &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;nonobjc public &lt;span style="color:#81a1c1;font-weight:bold"&gt;class&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; fetchRequest&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&amp;gt;&lt;/span&gt; NSFetchRequest&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; NSFetchRequest&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;entityName&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Garden&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; address&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt;&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; UUID&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt;&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; plant&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; NSSet&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; wrappedName&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name &lt;span style="color:#bf616a"&gt;??&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; wrappedAddress&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; address &lt;span style="color:#bf616a"&gt;??&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; plantArray&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let set &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; plant as&lt;span style="color:#bf616a"&gt;?&lt;/span&gt; Set&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Plant&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#bf616a"&gt;??&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; set&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;sorted &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;&lt;span style="color:#b48ead"&gt;0.&lt;/span&gt;wrappedName &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;&lt;span style="color:#b48ead"&gt;1.&lt;/span&gt;wrappedName
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using a computed variable (in this case plantArray), Paul likes to turn it into a Set of Plants, then convert that into an array by sorting it. We have to provide the predicate, but it&amp;rsquo;s a small price to pay to get the array back. I have concerns about this for a 100K array, but it&amp;rsquo;s no problem for this app.&lt;/p&gt;
&lt;p&gt;Back in our Garden DetailView, it&amp;rsquo;s now a simple matter to show the plants for a garden in a list under the other garden details.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct DetailView&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; garden&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Garden
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; body&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; some View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; VStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wrappedName&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;font&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;headline&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wrappedAddress&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plantArray&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; \&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;self&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;plant &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;plant&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wrappedName&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, in the button press to create our sample data, we need to create each of the plant instances then call a method on a garden to add them to that garden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Button(&amp;#34;Sample Data&amp;#34;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let garden1 = Garden(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.id = UUID()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.name = &amp;#34;White Lodge&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.address = &amp;#34;72 Anderson Street \nRothwell QLD 4022&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let plant1 = Plant(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plant1.name = &amp;#34;Rose&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.addToPlant(plant1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let plant2 = Plant(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plant2.name = &amp;#34;Palm Tree&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plant2.garden? = garden1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.addToPlant(plant2)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let plant3 = Plant(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plant3.name = &amp;#34;Lawn&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plant3.garden? = garden1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.addToPlant(plant3)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The .addToPlant() accessor method is a Swift wrapper for some internal Objective C that was generated for us in the same file as the Garden properties. The bad name &amp;lsquo;AddToPlant&amp;rsquo; rather than &amp;lsquo;AddToPlants&amp;rsquo; is my bad. When I defined the relationship in Garden (in the data model) I should have called it &amp;lsquo;plants&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/core-data-basics-part-one/"&gt;Part 1&lt;/a&gt;, &lt;a href="https://blog.iankulin.com/core-data-basics-part-two/"&gt;Part 2&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Core Data basics - Part Two</title><link>https://blog.iankulin.com/core-data-basics-part-two/</link><pubDate>Wed, 23 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/core-data-basics-part-two/</guid><description>&lt;p&gt;Yesterday I roughed out a master/detail app with a list of gardens, and for each garden a detail screen including some plants. It used arrays of structs for the data. Today I&amp;rsquo;m going to convert that app to use Core Data, and explain my understanding of each step. This won&amp;rsquo;t be the entire app - I&amp;rsquo;m going to include the plants in my data structure, but not actually use them in this version. I&amp;rsquo;ll save that 1:many relationship stuff for another post.&lt;/p&gt;
&lt;p&gt;Once again I need to acknowledge Paul Hudson&amp;rsquo;s 100 Days of SwiftUI for most of my knowledge of Core Data - much of the code below is lifted directly from his examples. The explanations of what is going on, and any errors, are mine.&lt;/p&gt;
&lt;p&gt;Just to remind you, here&amp;rsquo;s what our working app should look like by the end of this post.&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/simulator-screen-shot-iphone-14-pro-2022-11-19-at-19.40.30-1.png" width="433" alt=""&gt;
&lt;p&gt;The &amp;ldquo;Sample Data&amp;rdquo; button creates the gardens to display. The list above displays them.&lt;/p&gt;
&lt;p&gt;The first thing we need to do is to create the data model. This is the description of our data structures - &lt;em&gt;Garden&lt;/em&gt; and &lt;em&gt;Plant&lt;/em&gt; which in the previous version were structs. In this version they will become classes, but we don&amp;rsquo;t just write the classes, we define them in an XCode &lt;em&gt;data model&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-11-20-at-4.48.49-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s slightly different language. Instead of structs we have &lt;em&gt;Entities&lt;/em&gt; for Garden and Plant, and instead of properties they have &lt;em&gt;Attributes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While we&amp;rsquo;re editing the data model, there&amp;rsquo;s another couple of little jobs to do here. We define the relationship between Gardens and Plants (each Garden can have many Plants, each Plant only belongs to a single garden). We also need to turn Codegen to Manual/None. To see this setting, you need to View|Inspectors|Data Model. If it&amp;rsquo;s left on &amp;ldquo;Class Generation&amp;rdquo; XCode creates a secret file in the build folder that contains the class definitions for Garden and Plant. In this app, I want to change them so we need to have them as part of our project source, which is the next step.&lt;/p&gt;
&lt;p&gt;We are going to get XCode to explicitly generate the Managed Object code for our entities, and add it to our project so we can edit it - Editor | Create NSManagedObject. Select both entities and XCode will generate four files and add them to the project navigator. – Each entity has a file with an empty class definition, and a file with an extension containing the @NSManaged property definitions and the fetchRequest method.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-11-20-at-5.56.58-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Since the properties are (a slightly different to Swift version of) optionals, this file is a good place to make any computed properties to return safely unwrapped versions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;extension Garden &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;nonobjc public &lt;span style="color:#81a1c1;font-weight:bold"&gt;class&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; fetchRequest&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&amp;gt;&lt;/span&gt; NSFetchRequest&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; NSFetchRequest&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;entityName&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Garden&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; address&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt;&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; UUID&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt;&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;NSManaged public &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; plant&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; NSSet&lt;span style="color:#bf616a"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; wrappedName&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name &lt;span style="color:#bf616a"&gt;??&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; wrappedAddress&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; address &lt;span style="color:#bf616a"&gt;??&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s our classes for the individual bits of data - analogous to the structs - taken care of. But what about the analog for the array? What&amp;rsquo;s our container?&lt;/p&gt;
&lt;p&gt;For this, we need an NSPersistentContainer. The way Paul does things, this is a property of a data controller obect. It links to the data model we defined before.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;class&lt;/span&gt; DataController&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; ObservableObject &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let container &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; NSPersistentContainer&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;DataDemo&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; init&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; container&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;loadPersistentStores &lt;span style="color:#eceff4"&gt;{&lt;/span&gt; _&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; error &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; let error &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; error &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Core Data failed to load: \(error.localizedDescription)&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deinit &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the app definition, instantiate the dataController as an @StateObject, then insert its viewcontext into the Environment. The view context is what we’ll use elsewhere in the app to manipulate the data.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bf616a"&gt;@&lt;/span&gt;main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct DataDemoApp&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; App &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;StateObject private &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; dataController &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; DataController&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; body&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; some Scene &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WindowGroup &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ContentView&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;environment&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;\&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;managedObjectContext&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; dataController&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;container&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;viewContext&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the view where we want to access our data, extract the managed object context from the environment and express it as a property of the view. Also in the view, we need a property to access our collection of Gardens. This is another property, with the @FetchRequest property wrapper.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct ContentView&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;&lt;span style="color:#bf616a"&gt;Environment&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;\&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;managedObjectContext&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; moc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;FetchRequest&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;sortDescriptors&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SortDescriptor&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;\&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;])&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gardens&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; FetchedResults&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To add data - new gardens, instantiate a new garden with the “context:” initialiser and pass in our managed object context – this is the link to all the persistence code – the data model and so on. When you’re ready for these to be committed to “disk” (so far they are in the collection, but only in memory) call the managed object context’s save() method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Button(&amp;#34;Sample Data&amp;#34;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let garden1 = Garden(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.name = &amp;#34;White Lodge&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden1.address = &amp;#34;72 Anderson Street \nRothwell QLD 4022&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; let garden2 = Garden(context: moc)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden2.id = UUID()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden2.name = &amp;#34;Gordon Terrace&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; garden2.address = &amp;#34;95 Learmouth St\nTahara Vic 3301&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; try? moc.save()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that we are dealing with objects now – reference types – so we have to keep creating new objects to add them to the collection. This is contrasted with when I was loading up the sample data with the struct, I could keep recycling it and when I added it to the array each time it was value copied.&lt;/p&gt;
&lt;p&gt;To access our data, it’s identical to accessing any collection, except that I’ll use the unwrapped computed properties from earlier.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;FetchRequest&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;sortDescriptors&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SortDescriptor&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;\&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;])&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gardens&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; FetchedResults&lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt;Garden&lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; body&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; some View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NavigationView &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; VStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;gardens&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; \&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;id&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;garden &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wrappedName&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Spacer&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wrappedAddress&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s covered the &lt;em&gt;very&lt;/em&gt; basics. &lt;a href="https://github.com/IanKulin/DataDemo/releases/tag/v0.2"&gt;Here&amp;rsquo;s the source for this version&lt;/a&gt;. The next step will be to deal with the one-to-many relationship between the gardens and plants.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/core-data-basics-part-one/"&gt;Part 1&lt;/a&gt;, &lt;a href="https://blog.iankulin.com/core-data-basics-part-three/"&gt;Part 3&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Core Data basics - Part One</title><link>https://blog.iankulin.com/core-data-basics-part-one/</link><pubDate>Tue, 22 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/core-data-basics-part-one/</guid><description>&lt;p&gt;To help me get clear on the Core Data basics (&lt;a href="https://blog.iankulin.com/tough-day/"&gt;so I can master one of the #100Days challenges&lt;/a&gt;), I&amp;rsquo;ll write a simple master/detail app with arrays of structs, then convert it to Core Data listing out of the steps. Almost everything I know about Core Data, I learned from Paul Hudson&amp;rsquo;s &lt;a href="https://www.hackingwithswift.com/100/swiftui"&gt;100 Days of SwiftUI&lt;/a&gt; course - of which I&amp;rsquo;m up to day 61. So shout out to him. I highly recommend that course, and most of the code you&amp;rsquo;ll see in this post is either inspired by, or directly copied from 100 Days, except of course the errors - those are mine. This post - Part One - just describes the app and shows the struct/array version.&lt;/p&gt;
&lt;h3 id="app-overview"&gt;App Overview&lt;/h3&gt;
&lt;p&gt;The opening screen is a navigation view of the list of gardens, and a button. There’s a navigation link from each garden item to a detail view which shows the garden details, including a list of plants.&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/simulator-screen-shot-iphone-14-pro-2022-11-19-at-19.40.30.png" width="138" alt=""&gt;
&lt;img src="https://blog.iankulin.com/images/simulator-screen-shot-iphone-14-pro-2022-11-19-at-19.40.40.png" width="138" alt=""&gt;
&lt;h3 id="struct-version"&gt;Struct version&lt;/h3&gt;
&lt;p&gt;First the data. Two structs, Plant, and Garden. Garden contains a list of plants. The gardens state variable lives in the main contentview and is an array of Gardens.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct Plant &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; id &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct Garden &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; id &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; name &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; address &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; plants&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct ContentView&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#bf616a"&gt;@&lt;/span&gt;State private &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gardens&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;Garden&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To create the sample data, a button creates the struct instances and adds them to the array.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bf616a"&gt;Button&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Sample Data&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; someGarden &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; Garden&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;White Lodge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;address &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;72 Anderson Street &lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;Rothwell QLD 4022&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plants&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Rose&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plants&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Palm Tree&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plants&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Lawn&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;id &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Gordon Terrace&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;address &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;95 Learmouth St&lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;Tahara Vic 3301&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plants &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The main display of the data is a list in a navigation view. With a link to a detail page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;struct&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;ContentView&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;@&lt;/span&gt;State &lt;span style="color:#81a1c1;font-weight:bold"&gt;private&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gardens&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[&lt;/span&gt;Garden&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; body&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; some View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NavigationView &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; VStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;gardens&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#bf616a"&gt;\&lt;/span&gt;&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;id&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;garden &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NavigationLink &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; DetailView&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; garden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt; label&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; HStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Spacer&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;address&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Button&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Sample Data&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; someGarden &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; Garden&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;name &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;White Lodge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;address &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;72 Anderson Street &lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;Rothwell QLD 4022&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;plants&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Rose&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;plants&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Palm Tree&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;plants&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;Plant&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Lawn&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;id &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;name &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Gordon Terrace&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;address &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;95 Learmouth St&lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;Tahara Vic 3301&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;plants &lt;span style="color:#eceff4"&gt;=[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;id &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;name &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Powlett Cottage&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;address &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;11 Bayfield Street&lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;White Beach 7184&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;id &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; UUID&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;name &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;Adams Garden&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; someGarden&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;address &lt;span style="color:#eceff4"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;71 Swanston St&lt;/span&gt;&lt;span style="color:#ebcb8b"&gt;\n&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;Kanya Vic 3381&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gardens&lt;span style="color:#eceff4"&gt;.&lt;/span&gt;append&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;someGarden&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;.&lt;/span&gt;navigationTitle&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;Data Demo&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The DetailView is passed the selected garden. It shows a couple of details from the garden, and a list of plants if there are any.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;struct DetailView&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; garden&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Garden
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; body&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; some View &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; VStack &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;font&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;headline&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;address&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ForEach&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;garden&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;plants&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; \&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;id&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;plant &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Text&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;plant&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So that&amp;rsquo;s our app. &lt;a href="https://github.com/IanKulin/DataDemo/releases/tag/v0.1"&gt;Source is on github&lt;/a&gt; here. Really, I could/should have done add/delete/edit but I just wanted something basic as a starting point for the Core Data stuff tomorrow.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/core-data-basics-part-two/"&gt;Part 2&lt;/a&gt;, &lt;a href="https://blog.iankulin.com/core-data-basics-part-three/"&gt;Part 3&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Tough Day</title><link>https://blog.iankulin.com/tough-day/</link><pubDate>Sun, 20 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/tough-day/</guid><description>&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/bad-day-at-sea-uspaceken.jpg" alt=""&gt;
&lt;em&gt;&lt;a href="https://www.reddit.com/r/Art/comments/7i7crd/bad_day_at_sea_ii_30_x_40_oil/"&gt;Bad Day at Sea - reddit u/SpaceKen&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Day 61 of &lt;a href="https://www.hackingwithswift.com/100/swiftui/61"&gt;#100DaysOfSwiftUI&lt;/a&gt; is a tough day. It&amp;rsquo;s the first real big test of Core Data understanding, and I&amp;rsquo;m finding I didn&amp;rsquo;t actually understand how the code for Core Data works. For the first time, I&amp;rsquo;m thinking of going back and redoing the days leading up to it.&lt;/p&gt;
&lt;p&gt;To try and get it straight in my mind, here&amp;rsquo;s how I think Core Data works:&lt;/p&gt;
&lt;p&gt;1. it&amp;rsquo;s a way of persisting instances of objects - not a relational database (even though that&amp;rsquo;s what&amp;rsquo;s lying underneath it). I&amp;rsquo;m sure this is part of what is obstructing my thinking. Relational databases were my bread and butter for many years.&lt;/p&gt;
&lt;p&gt;2. Core Data won&amp;rsquo;t just persist any old objects, you need to define these objects in the Data Model. They will be &amp;ldquo;NSManagedObjects&amp;rdquo;&lt;/p&gt;
&lt;p&gt;3. In the Data Model you can specify the &amp;ldquo;CodeGen&amp;rdquo;. If it&amp;rsquo;s left on the default &amp;ldquo;Class Definition&amp;rdquo; a hidden source file you can&amp;rsquo;t access is generated deep in the build file so the objects exist - and therefore you can use them.&lt;/p&gt;
&lt;p&gt;4. If you set CodeGen to &amp;ldquo;Manual/None&amp;rdquo;, it is now your responsibility to create that file. You usually select this, then tell XCode to generate them for you and add them to your project navigator by going in to Editor | Create NSManagedObject subclass. This then allows you to edit those files.&lt;/p&gt;
&lt;p&gt;5. To do anything these objects, you need a managaged object context. I&amp;rsquo;m not real clear on what this is. You create it in the App file, from a data controller that contains an NSPersistantObject. Then you save it to some super global called the environment.&lt;/p&gt;
&lt;p&gt;6. To add objects to the collection, you instantiate them using an initialiser that accepts the managed object context as an argument. Then to really persist them (as opposed to just the memory version) you call save() on the object context.&lt;/p&gt;
&lt;p&gt;7. To access the objects, you build a fetch request access a collection of them.&lt;/p&gt;
&lt;p&gt;8. It gets tricky when there are relationships between the objects.&lt;/p&gt;
&lt;p&gt;My plan is to work through my own example of arrays of items vs a Core Data version of the same thing to ensure I&amp;rsquo;ve got it all straight in my head before coming back to the Day 61 challenge. I don&amp;rsquo;t feel too bad about this - Paul makes a point that its a tough challenge, and I don&amp;rsquo;t want to just &amp;ldquo;get it working&amp;rdquo; and move on with that uneasy feeling I might have code with errors I just haven&amp;rsquo;t discovered yet.&lt;/p&gt;</description></item><item><title>CoreData and the Preview</title><link>https://blog.iankulin.com/coredata-and-the-preview/</link><pubDate>Fri, 04 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/coredata-and-the-preview/</guid><description>&lt;p&gt;I&amp;rsquo;ve noticed Paul is inclined to ignore the preview and run his code in the simulator to check its operation. That&amp;rsquo;s valid, but it seems quicker, and reassuring, to see it in the preview as I type.&lt;/p&gt;
&lt;p&gt;This led to a small problem with &lt;a href="https://www.hackingwithswift.com/books/ios-swiftui/how-to-combine-core-data-and-swiftui"&gt;Day 53&lt;/a&gt; that uses CoreData. When I added a student in the preview, it looked like this, and was immediately followed with a crash report.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-10-30-at-11.32.07-am.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;It ran fine in the simulator, and in the text for Day 53 there was a comment about adding the managed object context to the preview, but without a hint about how.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-10-30-at-11.34.07-am.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I tried a few things - it felt like I should be able to get it from the @Environment somehow, but ended up using &lt;a href="https://www.hackingwithswift.com/forums/100-days-of-swiftui/day-53-question-how-to-set-up-a-managed-object-context-in-xcode-s-swiftui-previews/16686"&gt;this&lt;/a&gt; solution from fellow HWS student &lt;a href="https://www.hackingwithswift.com/users/Fly0strich"&gt;@Fly0strich&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-10-30-at-11.47.51-am.jpg" alt=""&gt;&lt;/p&gt;</description></item></channel></rss>