<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kurt Frey</title>
    <description>The latest articles on Forem by Kurt Frey (@nitricware).</description>
    <link>https://forem.com/nitricware</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F40725%2F16cc7778-9e7a-446a-a968-9d3f3698ee5d.png</url>
      <title>Forem: Kurt Frey</title>
      <link>https://forem.com/nitricware</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nitricware"/>
    <language>en</language>
    <item>
      <title>Writing and Running Swift Code without Xcode on Mac and Windows</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Sun, 31 Dec 2023 08:14:22 +0000</pubDate>
      <link>https://forem.com/nitricware/writing-and-running-swift-code-without-xcode-on-mac-and-windows-4lpk</link>
      <guid>https://forem.com/nitricware/writing-and-running-swift-code-without-xcode-on-mac-and-windows-4lpk</guid>
      <description>&lt;p&gt;Swift has quickly become my favourite programming language. Its sleek syntax and fail safe features (&lt;code&gt;guard&lt;/code&gt; and &lt;code&gt;if let&lt;/code&gt;) are beautiful. My first steps with Swift were a few years back when I made my first iOS app. I knew that Objective-C was too different from what I knew at that time and I heard good things about Swift's learning curve.&lt;/p&gt;

&lt;p&gt;But now I wanted something more light-weight than Xcode for quick, un-sandboxed scripts. And so I looked into Visual Studio Code and Swift.&lt;/p&gt;

&lt;p&gt;Turns out, writing a command line swift App can easily be done on macOS, Linux and Windows with VS Code, some extensions and just a few dependencies. Follow along to see how it's done.&lt;/p&gt;

&lt;h2&gt;
  
  
  macOS
&lt;/h2&gt;

&lt;p&gt;Firstly, install Xcode or the Xcode command line tools. I recommend installing the package manager &lt;code&gt;brew&lt;/code&gt; (&lt;a href="https://brew.sh/"&gt;homebrew&lt;/a&gt;). It installs Xcode command line tools for you and comes in handy when you install software that's not in the App Store (and even if it is!).&lt;/p&gt;

&lt;p&gt;Now, install Visual Studio Code (if you haven't already) and the executable SwiftLint (which is used by the extension we'll install in a second) with i.e. &lt;code&gt;brew install visual-studio-code swiftlint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In VS Code, install the following extensions (via GUI or &lt;a href="https://stackoverflow.com/questions/34286515/how-to-install-visual-studio-code-extensions-from-command-line"&gt;command line&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=sswg.swift-lang"&gt;Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb"&gt;CodeLLDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vknabel.vscode-swiftlint"&gt;SwiftLint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=cgrevisse.swift-project-creation"&gt;Swift Project Creation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After that open a folder,  and create a new swift project in VS Code. That's easy, because you installed the Swift Project Creation extension. In the Sources directory, there's a &lt;code&gt;main.swift&lt;/code&gt;. Happy Coding. Once your code is ready to run, run it with a touch on the play button (or the play button with the critter for debugging) in your Touch Bar or with &lt;code&gt;Run &amp;gt; Start Debugging (F5)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;p&gt;On Windows, things are a bit more involved but still straight forward once you know the culprits.&lt;/p&gt;

&lt;p&gt;First, you'll need Visual Studio Community (at the time of writing this blogpost, Visual Studio 2022 is the most recent version). Get it via &lt;code&gt;winget install --id=Microsoft.VisualStudio.2022.Community  -e&lt;/code&gt; , or directly via &lt;a href="https://visualstudio.microsoft.com/vs/community/"&gt;Visual Studio Community&lt;/a&gt; if you don't have &lt;code&gt;winget&lt;/code&gt; installed. &lt;code&gt;winget&lt;/code&gt; (&lt;a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/"&gt;winget&lt;/a&gt;) is a package manager for Windows like chocolatey and scoop. They have been &lt;a href="https://dev.to/bowmanjd/chocolatey-vs-scoop-package-managers-for-windows-2kik?comments_sort=top"&gt;compared&lt;/a&gt; numerous times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't worry, you'll still be using Visual Studio Code but Visual Studio must be installed!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you hadn't have the chance to install the "Desktop Development with C++" component with the IDE itself, install it in Visual Studio Community, install  as described &lt;a href="https://learn.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=msvc-170"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, install Swift for Windows. Also, you'll need Python 3.9 for the Swift Toolchain to work. LLDB is very picky about the Python version. Install both by using &lt;code&gt;winget install Swift.Toolchain Python.Python.3.9&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, you'll need the following Visual Studio Code extensions (via GUI or &lt;a href="https://stackoverflow.com/questions/34286515/how-to-install-visual-studio-code-extensions-from-command-line"&gt;command line&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=sswg.swift-lang"&gt;Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb"&gt;CodeLLDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=cgrevisse.swift-project-creation"&gt;Swift Project Creation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: SwiftLint - the executable required by the extension - is not available on Windows. So we omit the extension as well.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Windows, you have to check &lt;code&gt;Swift &amp;gt; Debugger: Use Debug Adapter From Toolchain&lt;/code&gt; in the Settings of the Swift VS Code Extension.&lt;/p&gt;

&lt;p&gt;After that open a folder,  and create a new Swift project in VS Code. That's easy, because you installed the Swift Project Creation extension. In the Sources directory, there's a &lt;code&gt;main.swift&lt;/code&gt;. Happy Coding. Once your code is ready to run, run it with &lt;code&gt;Run &amp;gt; Start Debugging (F5)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux
&lt;/h2&gt;

&lt;p&gt;Help me, make this blog post complete: What are your instructions for making Swift and VS Code work on Linux?&lt;/p&gt;

&lt;h2&gt;
  
  
  Target Platform
&lt;/h2&gt;

&lt;p&gt;For targeting the most recent macOS you have to add or change the code in &lt;code&gt;Package.swift&lt;/code&gt; to include this snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nv"&gt;platforms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;macOS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise there will be errors if you use a language feature that is not available in the macOS version set in &lt;code&gt;Package.swift&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remarks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Swift Versions on macOS
&lt;/h3&gt;

&lt;p&gt;One disadvantage of Swift is how Apple decided to deploy new versions. They only come bundled with new versions of their operating systems. However, with &lt;code&gt;swiftenv&lt;/code&gt; (&lt;a href="https://github.com/kylef/swiftenv"&gt;kylef/swiftenv&lt;/a&gt;) other versions than the bundled one can be installed. So maybe that adds a possibility to run more modern swift versions on older hardware?&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code Sync
&lt;/h3&gt;

&lt;p&gt;VS Code can sync settings and installed extensions. If you're running this setup on both, a macOS and a Windows machine, you'll run into troubles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CodeLLDB has a setting that points to the lldb library. Don't sync this setting.&lt;/li&gt;
&lt;li&gt;SwiftLint is not available on Windows. Don't sync this extension.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>swift</category>
      <category>windows</category>
      <category>vscode</category>
      <category>mac</category>
    </item>
    <item>
      <title>Transition from App Delegate to SwiftUI life cycle</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Sun, 11 Sep 2022 11:00:53 +0000</pubDate>
      <link>https://forem.com/nitricware/transition-from-app-delegate-to-swiftui-life-cycle-4i79</link>
      <guid>https://forem.com/nitricware/transition-from-app-delegate-to-swiftui-life-cycle-4i79</guid>
      <description>&lt;p&gt;Apple introduced the new SwiftUI life cycle some years ago. I still had some apps that used UIKit and the App Delegate life cycle.&lt;/p&gt;

&lt;p&gt;Transitioning from one to the other seems trivial at first, makes you scratch your head shortly later only to realise that it actually is quite trivial.&lt;/p&gt;

&lt;p&gt;Before you start you should redesign your views in &lt;code&gt;SwiftUI&lt;/code&gt; and create a &lt;code&gt;YourSwiftUIView&lt;/code&gt; which serves as the first view your users are presented with.&lt;/p&gt;

&lt;p&gt;Firstly, remove &lt;code&gt;@UIUIApplicationMain&lt;/code&gt; from your AppDelegate class.&lt;/p&gt;

&lt;p&gt;Secondly, create a SwiftUI &lt;code&gt;App struct&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;SwiftUI&lt;/span&gt;

&lt;span class="kd"&gt;@main&lt;/span&gt;
&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="nv"&gt;yourAppName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Relevant if you use CoreData&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;persistenceController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PersistenceController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;WindowGroup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;YourSwiftUIView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="c1"&gt;// Relevant if you use CoreData&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;managedObjectContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;persistenceController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thirdly, remove &lt;code&gt;UIApplicationSupportsMultipleScenes&lt;/code&gt; key from your InfoPlist. This key will have quite an entourage. Remove it all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIApplicationSupportsMultipleScenes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;false/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneConfigurations&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIWindowSceneSessionRoleApplication&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneConfigurationName&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Default Configuration&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneDelegateClassName&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;$(PRODUCT_MODULE_NAME).SceneDelegate&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneStoryboardFile&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Main&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally you can remove all the Storyboard Files and accompanying ViewControllers.&lt;/p&gt;

</description>
      <category>swiftui</category>
      <category>swift</category>
      <category>appdelegate</category>
    </item>
    <item>
      <title>Adding Sexual Activity to Apple Health via HealthKit</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Fri, 26 Aug 2022 12:40:51 +0000</pubDate>
      <link>https://forem.com/nitricware/adding-sexual-activity-to-apple-health-via-healthkit-356k</link>
      <guid>https://forem.com/nitricware/adding-sexual-activity-to-apple-health-via-healthkit-356k</guid>
      <description>&lt;p&gt;There are many examples on how to add heart rate or step counts to Apple Health via HealthKit. I made an &lt;a href="https://apps.apple.com/us/app/aphrodite/id1449414335"&gt;app&lt;/a&gt; that lets you track your sexual activity. And now I'd like to add HealthKit support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;After creating the app in Xcode, add the HealthKit capability and add the string to your Info.plist. &lt;/p&gt;

&lt;p&gt;For clarity and better practice we'll create a class that'll handle the connection to HealthKit. You could add this to a view too. It would be ugly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample vs. Object
&lt;/h2&gt;

&lt;p&gt;A sample is what is written to &lt;code&gt;HKHealthStore&lt;/code&gt; and an object is what is read from &lt;code&gt;HKHealthStore&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;HealthConnector&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The custom &lt;code&gt;HealthConnector&lt;/code&gt; class facilitates interaction with &lt;code&gt;HKHealthStore&lt;/code&gt;. It currently has two three functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;requestAuthorization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;saveSample&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deleteObject&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Request authorization
&lt;/h3&gt;

&lt;p&gt;Before any interaction with &lt;code&gt;HKHealthStore&lt;/code&gt; we must ask for permission. It's not enough to ask once. The user could revoke permission when we're not looking.&lt;/p&gt;

&lt;p&gt;You have to specifically ask for the Sample Types you'd like to read from and write to. Since my app only writes samples but won't retrieve anything, &lt;code&gt;requestAuthorization&lt;/code&gt;'s &lt;code&gt;read&lt;/code&gt;-parameter is &lt;code&gt;nil&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// This function requests permission to read and/or write to a specific&lt;/span&gt;
&lt;span class="c1"&gt;/// `HKObjectType`.&lt;/span&gt;
&lt;span class="c1"&gt;/// - Parameter completion: Completion handler must be able to handle boolean return.&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;requestAuthorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;@escaping&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if `HKHealthStore` is available to the user of the app.&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="kt"&gt;HKHealthStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isHealthDataAvailable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if category type `.sexualActivity` is available to the user.&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sexualActivityType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;HKObjectType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;categoryType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sexualActivity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a set containing the category types we'd like to access.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;writeTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;sexualActivityType&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;// Finally request authorization.&lt;/span&gt;
    &lt;span class="kt"&gt;HKHealthStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAuthorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;toShare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;writeTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Save a sample
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// This function saves a new sample to `HKHealthStore`. It adds all neccessary meta date.&lt;/span&gt;
&lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
&lt;span class="c1"&gt;///   - protection: Was protection used?&lt;/span&gt;
&lt;span class="c1"&gt;///   - date: When was the date of sexual acitivty?&lt;/span&gt;
&lt;span class="c1"&gt;///   - identifier: A UUID that allows to delete the sample later.&lt;/span&gt;
&lt;span class="c1"&gt;///   - completion: Completion handler must be able to handle boolean return.&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;saveSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;protection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;@escaping&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if category type `.sexualActivity` is available to the user.&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sexualActivityType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;HKObjectType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;categoryType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sexualActivity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     Create the sample.
     `value` must be 0. Otherwise the app will crash.
     `metadata` must contain all three keys. `HKMetadataKeySyncIdentifier` requires `HKMetadataKeySyncVersion`. Version number is 
     */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;HKCategorySample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sexualActivityType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="kt"&gt;HKMetadataKeySexualActivityProtectionUsed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;protectionUsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="kt"&gt;HKMetadataKeySyncIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuidString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="kt"&gt;HKMetadataKeySyncVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kt"&gt;HKHealthStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Delete an object
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Deletes the sample with the specified identifier.&lt;/span&gt;
&lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
&lt;span class="c1"&gt;///   - identifier: The UUID used to save the sample.&lt;/span&gt;
&lt;span class="c1"&gt;///   - completion: Completion handler must be able to handle boolean return.&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;deleteObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;@escaping&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Narrow down the possible results.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;predicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;HKQuery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predicateForObjects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;withMetadataKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;HKMetadataKeySyncIdentifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;allowedValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuidString&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Delete all the objects that match the predicate, which should only be one.&lt;/span&gt;
    &lt;span class="kt"&gt;HKHealthStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteObjects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;HKCategoryType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sexualActivity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="nf"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modify a sample
&lt;/h3&gt;

&lt;p&gt;You'll have to delete the old object and save a new sample.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>healthkit</category>
      <category>sexual</category>
      <category>activity</category>
    </item>
    <item>
      <title>Wrapping my head around CoreData and CloudKit</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Thu, 25 Aug 2022 13:01:45 +0000</pubDate>
      <link>https://forem.com/nitricware/wrapping-my-head-around-coredata-and-cloudkit-4obn</link>
      <guid>https://forem.com/nitricware/wrapping-my-head-around-coredata-and-cloudkit-4obn</guid>
      <description>&lt;p&gt;&lt;em&gt;This blog post was also published on &lt;a href="https://www.nitricware.com"&gt;https://www.nitricware.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If I got anything wrong, please leave a comment!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I like to understand things that wrapper and APIs like to obfuscate. CoreData especially in combination with CloudKit was very overwhelming for me. And it still is. However I could clear some things up for me.&lt;/p&gt;

&lt;p&gt;Since I preferred Apple doing some heavy lifting, posts and tutorials that "built the whole Core Data Stack from scratch" confused me. I wanted to understand and expand what was already there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare your app for CoreData in iCloud
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a new application and check "use CoreData" &lt;strong&gt;and&lt;/strong&gt; "host in iCloud"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;OR &lt;em&gt;(assuming the app already uses CoreData, because if not you'd have to add the whole &lt;code&gt;PersistenceController&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replace &lt;code&gt;NSPersitentContainer&lt;/code&gt; in &lt;code&gt;PersistenceController&lt;/code&gt; with &lt;code&gt;NSPersitentCloudKitContainer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;container.viewContext.automaticallyMergesChangesFromParent = true&lt;/code&gt; in &lt;code&gt;PersistenceController.init()&lt;/code&gt; as the last line&lt;/li&gt;
&lt;li&gt;In "Signing &amp;amp; Capabilities" add &lt;em&gt;for each target&lt;/em&gt;:

&lt;ol&gt;
&lt;li&gt;Background Modes: Remote Notifications&lt;/li&gt;
&lt;li&gt;iCloud: CloudKit and activate the checkbox next to the container for your app (create a new one with &lt;code&gt;+&lt;/code&gt; if needed) - you could also use an existing one and share data between apps.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You're done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Attention&lt;/em&gt;&lt;/strong&gt;: iCloud sync in simulator is wonky at best. Use physical devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an iCloud container?
&lt;/h2&gt;

&lt;p&gt;An iCloud container simply put is like a directory in iCloud where all the cloud stuff of your app reside. You're using an &lt;code&gt;NSPersitentCloudKitContainer&lt;/code&gt;? It's synced to the iCloud container. Using multiple? A single one with multiple configurations? They're all there.&lt;/p&gt;

&lt;p&gt;The iCloud container is like the sandbox of the app on the device but in the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a &lt;code&gt;NSPersistentContainer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;NSPersistentContainer&lt;/code&gt; is a class that handles all your interaction with a database (or multiple database files, see: configurations).&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; also handles all your interaction with a local database and it also handles syncing it to and from the cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple persistent container
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What?
&lt;/h4&gt;

&lt;p&gt;Usually there's a file called &lt;code&gt;Persistence.swift&lt;/code&gt; in your project. Or your &lt;code&gt;PersistenceController&lt;/code&gt; class is created elsewhere.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;PersistenceController&lt;/code&gt; instantiates a persistent container that connects to a &lt;code&gt;.sqlite&lt;/code&gt;-database (which is defined by a &lt;code&gt;.xcdatamodeld&lt;/code&gt; file) in your project. You reference it by name: &lt;code&gt;NSPersistentContainer(name: "MyDataModel")&lt;/code&gt; - you need a &lt;code&gt;MyDataModel.xcdatamodeld&lt;/code&gt; for that to work.&lt;/p&gt;

&lt;p&gt;You could copy the whole code and instantiate a second container referencing another file.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; would then sync both persistent containers (read: files) to your iCloud container (read: sandbox).&lt;/p&gt;

&lt;p&gt;Conveniently it would simply sync it to the first iCloud container in the list of iCloud containers checked in the iCloud capability.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why?
&lt;/h4&gt;

&lt;p&gt;You could want to separate topics in different databases not just different tables. For clarity or so. I.e. an app that stores your refrigerator content and your car parts. Similar database structure but different enough that two database files make sense.&lt;/p&gt;

&lt;p&gt;If you'd want to access a private and a public part of database in an iCloud container, you'd have to use &lt;code&gt;NSPersistentCloudKitContainerOptions&lt;/code&gt; and configurations.&lt;/p&gt;

&lt;p&gt;Of course you could use could use configurations for that silly use case above too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use &lt;code&gt;NSPersistentCloudKitContainerOptions&lt;/code&gt; and configurations
&lt;/h3&gt;

&lt;p&gt;Say you want to connect a &lt;code&gt;NSPersistentCloudKitContainer&lt;/code&gt; to a different iCloud container than the first in the list you marked with a checkmark.&lt;/p&gt;

&lt;p&gt;Or you'd like to connect the public and private records in the first (or any other) iCloud container in said list.&lt;/p&gt;

&lt;p&gt;That's what &lt;code&gt;NSPersistentCloudKitContainerOptions&lt;/code&gt; is for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// point to the database file&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;publicDescription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentStoreDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="nf"&gt;appendingPathComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"public.sqlite"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// point to the container in the cloud&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;publicOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentCloudKitContainerOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;containerIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"iCloud.com.nitricware.Aphrodite"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// point to the section of the container in the cloud&lt;/span&gt;
&lt;span class="n"&gt;publicOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;databaseScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;

&lt;span class="c1"&gt;// link the NSPersistentCloudKitContainerOptions to NSPersistentStoreDescription&lt;/span&gt;
&lt;span class="n"&gt;publicDescription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cloudKitContainerOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;publicOptions&lt;/span&gt;

&lt;span class="c1"&gt;// point to the configuration in your .xcdatamodeld&lt;/span&gt;
&lt;span class="n"&gt;publicDescription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Public"&lt;/span&gt;

&lt;span class="c1"&gt;// enable uploading already existent entries in your database&lt;/span&gt;
&lt;span class="n"&gt;publicDescription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;forKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentHistoryTrackingKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// this option enables auto refresh&lt;/span&gt;
&lt;span class="n"&gt;publicDescription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;forKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentStoreRemoteChangeNotificationPostOptionKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Further Reading: &lt;a href="https://patmalt.medium.com/end-to-end-encryption-and-cloudkit-with-coredata-part-1-67bfbe467bc"&gt;https://patmalt.medium.com/end-to-end-encryption-and-cloudkit-with-coredata-part-1-67bfbe467bc&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Applying it to Core Data without cloud sync
&lt;/h4&gt;

&lt;p&gt;Simply use a &lt;code&gt;NSPersistentContainer&lt;/code&gt; and omit the lines below from the code above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;publicOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSPersistentCloudKitContainerOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;containerIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"iCloud.com.nitricware.Aphrodite"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;publicOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;databaseScope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Is there more to it?
&lt;/h2&gt;

&lt;p&gt;Yes. Loads. It's a highly complex topic. I don't understand all of it yet.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>coredata</category>
      <category>cloudkit</category>
    </item>
    <item>
      <title>Adding CarPlay to a SwiftUI Life Cycle App</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Fri, 10 Sep 2021 09:56:31 +0000</pubDate>
      <link>https://forem.com/nitricware/adding-carplay-to-a-swiftui-life-cycle-app-h9h</link>
      <guid>https://forem.com/nitricware/adding-carplay-to-a-swiftui-life-cycle-app-h9h</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a crosspost from &lt;a href="https://www.nitricware.com/blogpost.php?id=1631267488"&gt;nitricware.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Apple makes it really easy for any developer with a Mac to create basic iOS apps. However, more complex topics sometimes require the developer to do lots of research. This is a blog post about adding a CarPlay Delegate to a SwiftUI Life Cycle App.&lt;/p&gt;

&lt;p&gt;Currently, apps for iOS can either have the AppDelegate Life Cycle or the SwiftUI Life Cycle. While the latter poses many restrictions upon the developer, working with it is very smooth for the most part and - as you will soon see - very versatile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Info.plist
&lt;/h2&gt;

&lt;p&gt;Searching for tutorials about adding a CarPlay Delegate to an app leads to many results for AppDelegate based apps. A simple addition to &lt;code&gt;Info.plist&lt;/code&gt; allows adding CarPlay to your SwiftUI life cycle app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIApplicationSceneManifest&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIApplicationSupportsMultipleScenes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneConfigurations&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CPTemplateApplicationSceneSessionRoleApplication&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UISceneDelegateClassName&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;YourAppName.CarPlaySceneDelegateName&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By pointing to &lt;code&gt;YourAppName.CarPlaySceneDelegateName&lt;/code&gt;, CarPlay knows what to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  CarPlaySceneDelegate
&lt;/h2&gt;

&lt;p&gt;Of course, you actually need a class called &lt;code&gt;CarPlaySceneDelegateName&lt;/code&gt;. It must look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;protocol&lt;/span&gt; &lt;span class="kt"&gt;CarPlaySceneDelegateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIResponder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;CPTemplateApplicationSceneDelegate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;interfaceController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CPInterfaceController&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;templateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;templateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CPTemplateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;didConnect&lt;/span&gt; &lt;span class="nv"&gt;interfaceController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CPInterfaceController&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;templateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;templateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CPTemplateApplicationScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;didDisconnect&lt;/span&gt; &lt;span class="nv"&gt;interfaceController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CPInterfaceController&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>swift</category>
      <category>ios</category>
      <category>carplay</category>
    </item>
    <item>
      <title>Help me clarify things: Developing for the Oculus Go with Unity on Windows</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Tue, 03 Mar 2020 18:11:53 +0000</pubDate>
      <link>https://forem.com/nitricware/help-me-clarify-things-developing-for-the-oculus-go-with-unity-on-windows-1p18</link>
      <guid>https://forem.com/nitricware/help-me-clarify-things-developing-for-the-oculus-go-with-unity-on-windows-1p18</guid>
      <description>&lt;p&gt;I wanted to make a simple VR app for my Oculus Go and had to setup my environment beforehand. This tutorial tries to simplify the mentioned &lt;a href="https://scriptable.com/blog/oculus-go-unity-setup-quick-start"&gt;reference tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;⁉️ &lt;em&gt;Some sections of this tutorial are not exactly clear to me because I had to try things out. They are marked with this symbol: ⁉️. Please, help me improve those sections with comments.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You own an Oculus Go&lt;/li&gt;
&lt;li&gt;You own a Windows PC&lt;/li&gt;
&lt;li&gt;Unity installed (In this case: 2019.3.3f1)&lt;/li&gt;
&lt;li&gt;Chocolatey installed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Chocolatey installations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;choco install -y adb android-sdk&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Manual installations
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Android SDK
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;When I first followed the reference tutorial, this step was not necessary to deploy to the Oculus Go. Since the reference tutorial considers it crucial, I will include those two steps, because nothing broke once I did it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;⁉️ &lt;em&gt;I‘m not sure if performing the following steps makes &lt;code&gt;choco install adb&lt;/code&gt; obsolete.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;C:\Android\android-sdk\tools\bin\sdkmanager.bat platform-tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;C:\Android\android-sdk\tools\bin\sdkmanager.bat "extras;google;usb_driver"&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Oculus drivers
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Browse [&lt;a href="https://developer.oculus.com/downloads/package/oculus-adb-drivers/"&gt;https://developer.oculus.com/downloads/package/oculus-adb-drivers/&lt;/a&gt;] and download the ZIP&lt;/li&gt;
&lt;li&gt;unzip&lt;/li&gt;
&lt;li&gt;goto &lt;code&gt;usb_driver&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Right-click on &lt;code&gt;android_winusb.inf&lt;/code&gt; &amp;gt; Install&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Plug in your Oculus Go
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Since the "allow file access" dialog did not appear once the developer account was enabled, I left it diasabled until the last step.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Plug in your Oculus Go&lt;/li&gt;
&lt;li&gt;Allow file access on the Oculus Go&lt;/li&gt;
&lt;li&gt;Enable developer mode via the Oculus app&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;add devices&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Allow access on the Oculus Go&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up Unity
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;When installing Unity via the Hub, make sure to also install the Android tools. If it didn't work - and in my case it didn't - download via the link in File &amp;gt; Build Settings and install them.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new 3D Project&lt;/li&gt;
&lt;li&gt;In Edit &amp;gt; Preferences &amp;gt; External Tools disable built-in JDK and built-in Android SDK ⁉️&lt;/li&gt;
&lt;li&gt;Click browse next to JDK and Android SDK and either search for your JDK and Android SDK or accept the path Unity found (recommende if Unity actually found something) ⁉️&lt;/li&gt;
&lt;li&gt;Go To File &amp;gt; Build Settings&lt;/li&gt;
&lt;li&gt;Click on Android and "Switch Platform" if necessary&lt;/li&gt;
&lt;li&gt;Go To Edit &amp;gt; Project Settings &amp;gt; Player&lt;/li&gt;
&lt;li&gt;Enter your Company Name, scroll to XR Settings and activate "Virtual Reality Support"&lt;/li&gt;
&lt;li&gt;Add Oculus via the plus symbol to the right under "Virtual Reality Support"&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Building
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to File &amp;gt; Build Settings&lt;/li&gt;
&lt;li&gt;Click Build and Run&lt;/li&gt;
&lt;li&gt;Enjoy the VR app&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  And now?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use the Oculus Utilities from the asset store and implement all it‘s features.&lt;/li&gt;
&lt;li&gt;Make a 360 degree image the skybox like here: [&lt;a href="https://www.youtube.com/watch?v=LXUoQ7VnLDc"&gt;https://www.youtube.com/watch?v=LXUoQ7VnLDc&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Make a Raycast like here: [&lt;a href="https://www.youtube.com/watch?v=_yf5vzZ2sYE"&gt;https://www.youtube.com/watch?v=_yf5vzZ2sYE&lt;/a&gt;]&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://scriptable.com/blog/oculus-go-unity-setup-quick-start"&gt;Reference Tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>vr</category>
      <category>oculus</category>
      <category>windows</category>
    </item>
    <item>
      <title>Developing for the Oculus Go with Unity on Mac</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Tue, 03 Mar 2020 18:07:22 +0000</pubDate>
      <link>https://forem.com/nitricware/developing-for-the-oculus-go-with-unity-on-mac-1f8c</link>
      <guid>https://forem.com/nitricware/developing-for-the-oculus-go-with-unity-on-mac-1f8c</guid>
      <description>&lt;p&gt;I wanted to make a simple VR app for my Oculus Go and had to setup my environment beforehand. This tutorial tries to translate &lt;a href="https://scriptable.com/blog/oculus-go-unity-setup-quick-start"&gt;reference tutorial&lt;/a&gt; to Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You own an Oculus Go&lt;/li&gt;
&lt;li&gt;You own a Mac&lt;/li&gt;
&lt;li&gt;Unity installed (In this case: 2019.3.3f1)&lt;/li&gt;
&lt;li&gt;Homebrew installed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Homebrew installations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;brew cask install android-platform-tools&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Plug in your Oculus Go
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Since the "allow file access" dialog did not appear once the developer account was enabled, I left it disabled until later.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Plug in your Oculus Go&lt;/li&gt;
&lt;li&gt;Allow file access on the Oculus Go&lt;/li&gt;
&lt;li&gt;Enable developer mode via the Oculus app&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;add devices&lt;/code&gt; on the Mac&lt;/li&gt;
&lt;li&gt;Allow access on the Oculus Go&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up Unity
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;When installing Unity via the Hub, make sure to also install the Android tools and Open JDK.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new 3D Project&lt;/li&gt;
&lt;li&gt;In Edit &amp;gt; Preferences &amp;gt; External Tools make sure to use the built-in SDK and JDK.&lt;/li&gt;
&lt;li&gt;Go To File &amp;gt; Build Settings&lt;/li&gt;
&lt;li&gt;Click on Android and "Switch Platform" if necessary&lt;/li&gt;
&lt;li&gt;Go To Edit &amp;gt; Project Settings &amp;gt; Player&lt;/li&gt;
&lt;li&gt;Enter your Company, scroll to XR Settings and activate "Virtual Reality Support"&lt;/li&gt;
&lt;li&gt;Add Oculus via the plus symbol to the right under "Virtual Reality Support"&lt;/li&gt;
&lt;li&gt;Still in Edit &amp;gt; Project Settings &amp;gt; Player go to Other Settings and find Graphic APIs.&lt;/li&gt;
&lt;li&gt;Remove Vulkan&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Building
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to File &amp;gt; Build Settings&lt;/li&gt;
&lt;li&gt;Click Build and Run&lt;/li&gt;
&lt;li&gt;Enjoy the VR app&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  And now?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use the Oculus Utilities from the asset store&lt;/li&gt;
&lt;li&gt;Make a 360 degree image the skybox like here: [&lt;a href="https://www.youtube.com/watch?v=LXUoQ7VnLDc"&gt;https://www.youtube.com/watch?v=LXUoQ7VnLDc&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Make a Raycast like here: [&lt;a href="https://www.youtube.com/watch?v=_yf5vzZ2sYE"&gt;https://www.youtube.com/watch?v=_yf5vzZ2sYE&lt;/a&gt;]&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://scriptable.com/blog/oculus-go-unity-setup-quick-start"&gt;Reference Tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vr</category>
      <category>oculus</category>
      <category>unity3d</category>
      <category>mac</category>
    </item>
    <item>
      <title>My first Steps in Wordpress Theme Development</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Sun, 05 Jan 2020 13:33:38 +0000</pubDate>
      <link>https://forem.com/nitricware/my-first-steps-in-wordpress-theme-development-2ai</link>
      <guid>https://forem.com/nitricware/my-first-steps-in-wordpress-theme-development-2ai</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclaimer: This is a cross-post from my dev-blog at &lt;a href="https://www.nitricware.com"&gt;nitricware.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For my new project "Geriatrie2Go.eu" - a blog about health care in geriatrics - I tried to find the perfect Wordpress theme. However, I couldn't find one that satisfied my needs. So I built one myself using Docker.&lt;/p&gt;

&lt;p&gt;For easy development without the hassle of either installing a wordpress blog locally or shoveling my theme files after every change onto a server, I decided to use Docker. Luckily, someone created a &lt;a href="https://davidyeiser.com/tutorial/docker-wordpress-theme-setup"&gt;very neat blogpost&lt;/a&gt; that guides you thru this process.&lt;/p&gt;

&lt;p&gt;Creating a full fledged WordPress theme which supports all of the CMS' features can be quite exhaustive. However, WordPress is built in a way, that makes most of the work optional. For example: Once you created an &lt;code&gt;index.php&lt;/code&gt; page you're somewhat done. Except, of course, you want page templates to look different, or single post templates or search results or...&lt;/p&gt;

&lt;p&gt;There are great &lt;a href="https://developer.wordpress.org/themes/"&gt;resources&lt;/a&gt; on how to build a WordPress theme out there. Especially the ones from the creators of WordPress;&lt;/p&gt;

&lt;p&gt;Another topic that can make creating WordPress themes challenging for a novice like me are modern web features and the devices out there. A theme should be responsive. The simpler your theme, the simpler it is to make it responsive. I even managed to include support for dark mode.&lt;/p&gt;

&lt;p&gt;At the end of the day, I managed to release v0.1 of &lt;code&gt;wp-latex-theme&lt;/code&gt;, a very simple wordpress that resembles the LaTeX layout. It can be found over at &lt;a href="https://github.com/nitricware/wp-latex-theme"&gt;Github&lt;/a&gt;. Please help me improve it (i.e. by adding support for comments or other post types or by localizing it). Also check out the &lt;a href="https://www.geriatrie2go.eu"&gt;project&lt;/a&gt; I made the theme for.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>latex</category>
      <category>theme</category>
      <category>responsive</category>
    </item>
    <item>
      <title>Adding Spotify's missing features and learning about JS, (S)CSS, PHP, APIs, Skeuomorphic Design and Documentation</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Sat, 23 Jun 2018 08:56:27 +0000</pubDate>
      <link>https://forem.com/nitricware/adding-spotifys-missing-features-and-learning-about-js-scss-php-apis-skeuomorphic-design-and-documentation-56b</link>
      <guid>https://forem.com/nitricware/adding-spotifys-missing-features-and-learning-about-js-scss-php-apis-skeuomorphic-design-and-documentation-56b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the TL;DR section of a much - much!! - longer article over on my dev-blog. Feel free to visit the &lt;a href="https://www.nitricware.com/2018/06/23/spotifys-missing-feature/"&gt;original article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When suddenly songs in my Spotify playlists were not available anymore but an alternative version (remastered album, best-of album) could still be found, I had to add a missing feature to Spotify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nitricware/SpotifyUpdater"&gt;My software&lt;/a&gt; would find "unavailable" tracks and search for alternatives. The user could then add one of the search results to a "revived" playlist.&lt;/p&gt;

&lt;p&gt;In the process of writing the software, I learned a lot about writing software in a very general term but also about language-specific topics, benefits of IDEs and how to design user interfaces.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I added a huge amount of comments to my code, documenting how things are done and what the code does. This does not only help myself when I review the code later on but also contributors who want to improve my software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Knowing how paralyzing it can be when there are no responses to your questions confirmed me in my thinking that communication with other developers is a crucial tool to make your software accessible to more users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;During the process of making the application I learned about new aspects of languages familiar to me. Those aspects included type hinting in PHP, adding event listeners and dispatching events in JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing JavaScript code without frameworks proved to be simple. Of course frameworks like jQuery simplify some tasks but is it worth all the required bandwidth?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type hinting is a great tool to improve the readability of code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sass enables a developer to easily prototype the design of a software because of variables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Skeuomorphic design is harder (but in my opinion more beautiful when done right) and requires you to think about your design more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release early or you might not release at all.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>api</category>
      <category>php</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I learned the most about using XML with PHP</title>
      <dc:creator>Kurt Frey</dc:creator>
      <pubDate>Sat, 13 Jan 2018 08:50:32 +0000</pubDate>
      <link>https://forem.com/nitricware/why-i-wrote-my-own-database-system-ci9</link>
      <guid>https://forem.com/nitricware/why-i-wrote-my-own-database-system-ci9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; &lt;em&gt;The software in question that used this solition was only used by two people - one of which was me. Only one of those two had write access - also me. This solution never was a business solution and was never used in production.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Quite some time ago, I was writing some PHP software for the web that would need to use a database. I wanted to design the software as portable as possible so that it wouldn't be too much hassle to migrate to another provider. MySQL was too big for what I wanted and while SQLite is powerful itself, I figured it would better suit my needs.&lt;/p&gt;

&lt;p&gt;Sometimes when writing software, you run into a problem. Usually, there are multiple ways to solve it. My problem was, that I could not use SQLite in my PHP application, since my hosting provider did not allow me to install it and wouldn’t install it themselves.&lt;/p&gt;

&lt;p&gt;Solution 1 would be to switch to another hosting provider which supports SQLite and run the program there. Solution 2 would be to search for another database system which does not require any installation at all. And solution 3 was what I chose to do: Write my own database solution.&lt;/p&gt;

&lt;p&gt;While this has some very clear disadvantages like costing time, it has two main advantages. Firstly, you can control how the system behaves since you write it from scratch. Secondly, you gain a lot of experience by writing something you have never written before.&lt;/p&gt;

&lt;p&gt;And that's how &lt;a href="https://github.com/nitricware/NWDataBase"&gt;NWDatabase&lt;/a&gt;, a database system that comes with a PHP library and creates files with an XML syntax, was born. A software created while learning about XML, classes and much more. Surely not the best idea for production but not all that terrible for learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.:&lt;/strong&gt; &lt;em&gt;This post was slightly altered after the first 24h, reacting on some comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>library</category>
      <category>sql</category>
      <category>database</category>
    </item>
  </channel>
</rss>
