<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://bradyr88.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://bradyr88.github.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2023-11-15T20:36:47+00:00</updated><id>https://bradyr88.github.io/feed.xml</id><title type="html">Brady Robshaw</title><subtitle>Brady Robshaw</subtitle><author><name>Brady Robshaw</name></author><entry><title type="html">Set Tracker</title><link href="https://bradyr88.github.io/Set_Tracker/" rel="alternate" type="text/html" title="Set Tracker" /><published>2023-08-01T00:00:00+00:00</published><updated>2023-08-01T00:00:00+00:00</updated><id>https://bradyr88.github.io/Set_Tracker</id><content type="html" xml:base="https://bradyr88.github.io/Set_Tracker/">&lt;p&gt;WWDC 2023 came with a ton of interesting new functionality that I had been hoping for and I created this application to explore. Specifically, SwiftData and Swift Charts were extremely interesting. I had familiar working with the Core Data  APIs in previous applications, but found it a less than ideal integration into MVVM and SwiftUI.&lt;/p&gt;

&lt;p&gt;The application that I would explore these new features with is design to keep track of setting at a rock gym. So what dose it do? Saves all of the logistical information you need to track for commercial gym setting (SwiftData), and cleanly presents the data in a visual manner that is easily digestible (Swift Charts).&lt;/p&gt;

&lt;p&gt;Swift data is amazing, and was simultaneously the easiest and hardest part of developing this application. On the easy side, creating your models is trivial:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-Swift&quot;&gt;@Model
final class Gym {
    let id: UUID
    var name: String
    @Relationship(deleteRule: .cascade) var zones: [Zone]
    var difficultyCurve: DifficultyCurve
    
    var climbs: [Climb] {
        get {
            zones.flatMap { $0.climbs }
        }
    }
    
    init(name: String, zones: [Zone], difficultyCurve: DifficultyCurve = DifficultyCurve()) {
        self.id = UUID()
        self.name = name
        self.zones = zones
        self.difficultyCurve = difficultyCurve
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see above I just created my top level object by simply marked it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@model final class&lt;/code&gt; and &lt;strong&gt;boom&lt;/strong&gt; all the work is done, it’s now capable of being saved. You can see I’m even managing my relationships to other saved objects with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Relationship&lt;/code&gt; macro.&lt;/p&gt;

&lt;p&gt;On the hard side is the fact that it was a beta. This is my first true, deep dive, into a beta software release for Xcode, and the number of times functionality changed out from underneath me and broke my application was very annoying. However I learned a lot watching Apple and the community puzzling out the best way to handle certain features.&lt;/p&gt;</content><author><name>Brady Robshaw</name></author><category term="media" /><summary type="html">WWDC 2023 came with a ton of interesting new functionality that I had been hoping for and I created this application to explore. Specifically, SwiftData and Swift Charts were extremely interesting. I had familiar working with the Core Data APIs in previous applications, but found it a less than ideal integration into MVVM and SwiftUI.</summary></entry><entry><title type="html">Die Master</title><link href="https://bradyr88.github.io/Die_Master/" rel="alternate" type="text/html" title="Die Master" /><published>2022-11-01T00:00:00+00:00</published><updated>2022-11-01T00:00:00+00:00</updated><id>https://bradyr88.github.io/Die_Master</id><content type="html" xml:base="https://bradyr88.github.io/Die_Master/">&lt;p&gt;&lt;img src=&quot;/assets/DM_Icon.png&quot; alt=&quot;Die Master App Icon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Application I wrote and published to the &lt;a href=&quot;https://apps.apple.com/us/app/die-master/id6443835851&quot;&gt;App Store&lt;/a&gt;, which helps DM’s track encounters in role-playing games. My goals with this application was twofold. One create a robust rolling system that tracked past roles and accounted for the variety of different events types that can occur while playing a role-playing game. Second, handle JSON in such a way that the app can ingest new monsters and characters easily.&lt;/p&gt;

&lt;p&gt;The crux of making my roll system robust is my Event struct. This records any action that the user can take rolling a dice, making an attack, activating an ability, etc. What values are optional suddenly changes the way the application chooses to display the event.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/DMImage1.png&quot; alt=&quot;Image of Goblin - Scimitar&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/DmImage2.png&quot; alt=&quot;Image of Goblin - nimble escape&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/DMImage3.png&quot; alt=&quot;Image of Goblin - damage&quot; /&gt;&lt;/p&gt;

&lt;p&gt;All of the above views have the same exact Event struct providing the data, but SwiftUI treats them completely differently, providing unique displays depending on what the important information is. It’s a small thing, but I feel it shows a significant improvement from my first application, in terms of understanding and utilizing the power of SwiftUI combined with MVVM.&lt;/p&gt;

&lt;p&gt;As for the backend, the application can except JSON (like what is shown below) and converted into monsters that the app maintains in storage. This would make it much easier for users to eventually be able to share content that they have created.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-JSON&quot;&gt;[
  {
    &quot;abilaty&quot;: [
      {
        &quot;id&quot;: &quot;9ED8654D-3886-498C-B9F0-B30A92AB5247&quot;,
        &quot;name&quot;: &quot;Brute&quot;,
        &quot;discription&quot;: &quot; A melee weapon deals one extra die of its damage when the bugbear hits with it (included in the attack).&quot;
      },
      {
        &quot;discription&quot;: &quot;If the bugbear surprises a creature and hits it with an attack during the first round of combat, the target takes an extra 7 (2d6) damage from the attack.&quot;,
        &quot;id&quot;: &quot;CCA91B9A-3061-4544-8654-22231C2163E9&quot;,
        &quot;name&quot;: &quot;Surprise Attack&quot;,
        &quot;onHit&quot;: {
          &quot;numberOfDice&quot;: 2,
          &quot;numberOfSides&quot;: 6,
          &quot;toAdd&quot;: 0
        }
      },
      {
        &quot;id&quot;: &quot;A776E7A0-90D2-4DAE-8A0B-99B585CB002F&quot;,
        &quot;name&quot;: &quot;Morningstar&quot;,
        &quot;roll&quot;: {
          &quot;numberOfDice&quot;: 1,
          &quot;numberOfSides&quot;: 20,
          &quot;toAdd&quot;: 2
        },
        &quot;onHit&quot;: {
          &quot;numberOfDice&quot;: 2,
          &quot;numberOfSides&quot;: 8,
          &quot;toAdd&quot;: 2
        }
      },
      {
        &quot;discription&quot;: &quot;range 30/120 ft.&quot;,
        &quot;id&quot;: &quot;7C459A49-9710-4CB7-9BDA-DD5071C25537&quot;,
        &quot;name&quot;: &quot;Javelin&quot;,
        &quot;roll&quot;: {
          &quot;numberOfDice&quot;: 1,
          &quot;numberOfSides&quot;: 20,
          &quot;toAdd&quot;: 4
        },
        &quot;onHit&quot;: {
          &quot;numberOfDice&quot;: 1,
          &quot;numberOfSides&quot;: 6,
          &quot;toAdd&quot;: 2
        }
      }
    ],
    &quot;id&quot;: &quot;966E5EB7-BA6B-4390-B48D-9E26BD1988E6&quot;,
    &quot;isShowing&quot;: true,
    &quot;OGLContent&quot;: true,
    &quot;name&quot;: &quot;Bugbear&quot;
  }
]
&lt;/code&gt;&lt;/pre&gt;</content><author><name>Brady Robshaw</name></author><category term="media" /><summary type="html"></summary></entry><entry><title type="html">Fiber Counter</title><link href="https://bradyr88.github.io/Fiber-Counter/" rel="alternate" type="text/html" title="Fiber Counter" /><published>2022-03-01T00:00:00+00:00</published><updated>2022-03-01T00:00:00+00:00</updated><id>https://bradyr88.github.io/Fiber-Counter</id><content type="html" xml:base="https://bradyr88.github.io/Fiber-Counter/">&lt;p&gt;&lt;img src=&quot;/assets/Asbestos_Icon.jpeg&quot; alt=&quot;App Icon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is the first application I wrote and published to the &lt;a href=&quot;https://apps.apple.com/us/app/fiber-counter/id1616530799&quot;&gt;App Store&lt;/a&gt;. It was purely a learning exercise to follow an idea through from start to navigating App Store review. Undoubtedly, the most interesting part of this early project was the fact that I had to dip into UIViewControllerRepresentable in order to support emailing functionality that I wanted.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Swift&quot;&gt;struct MailView: UIViewControllerRepresentable {
  @Environment(\.presentationMode) var presentation
  @Binding var data: ComposeMailData
  let callback: MailViewCallback

  class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
    @Binding var presentation: PresentationMode
    @Binding var data: ComposeMailData
    let callback: MailViewCallback

    init(presentation: Binding&amp;lt;PresentationMode&amp;gt;,
         data: Binding&amp;lt;ComposeMailData&amp;gt;,
         callback: MailViewCallback) {
      _presentation = presentation
      _data = data
      self.callback = callback
    }

    func mailComposeController(_ controller: MFMailComposeViewController,
                               didFinishWith result: MFMailComposeResult,
                               error: Error?) {
      if let error = error {
        callback?(.failure(error))
      } else {
        callback?(.success(result))
      }
      $presentation.wrappedValue.dismiss()
    }
  }

  func makeCoordinator() -&amp;gt; Coordinator {
    Coordinator(presentation: presentation, data: $data, callback: callback)
  }

  func makeUIViewController(context: UIViewControllerRepresentableContext&amp;lt;MailView&amp;gt;) -&amp;gt; MFMailComposeViewController {
    let vc = MFMailComposeViewController()
    vc.mailComposeDelegate = context.coordinator
    vc.setSubject(data.subject)
    vc.setToRecipients(data.recipients)
    vc.setMessageBody(data.message, isHTML: false)
    data.attachments?.forEach {
      vc.addAttachmentData($0.data, mimeType: $0.mimeType, fileName: $0.fileName)
    }
    vc.accessibilityElementDidLoseFocus()
    return vc
  }

  func updateUIViewController(_ uiViewController: MFMailComposeViewController,
                              context: UIViewControllerRepresentableContext&amp;lt;MailView&amp;gt;) {
  }

  static var canSendMail: Bool {
    MFMailComposeViewController.canSendMail()
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What is this a nice thing to do to myself as a new Swift and SwiftUI developer? No.&lt;br /&gt;
Did I get the emailing functionality working? Yes.&lt;/p&gt;</content><author><name>Brady Robshaw</name></author><category term="media" /><summary type="html"></summary></entry></feed>