<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://dasdom.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dasdom.dev/" rel="alternate" type="text/html" /><updated>2026-05-14T11:13:07+00:00</updated><id>https://dasdom.dev/feed.xml</id><title type="html">dasdom.dev</title><subtitle>A blog about Xcode, iOS development and test-driven development.</subtitle><entry><title type="html">The 40 hour work week scam</title><link href="https://dasdom.dev/40-hour-work-week/" rel="alternate" type="text/html" title="The 40 hour work week scam" /><published>2026-05-14T06:00:00+00:00</published><updated>2026-05-14T06:00:00+00:00</updated><id>https://dasdom.dev/40-hour-work-week</id><content type="html" xml:base="https://dasdom.dev/40-hour-work-week/"><![CDATA[<p>Only few people (if any) can work 8 hours or more per day for 5 days a week and be productive, healthy and a social being over a extended period of time.
But still this is the norm and expected.
12 years ago I realized that I can only be productive and healthy when working 32 hours per week.
So I switched to “part time”.
<a href="https://theweek.com/articles/696644/why-should-work-4-hours-day-according-science">But science suggests</a> I’m still wasting about 12 hours each week.</p>

<p>“Part time” means less salary.
I’m punished for keeping me healthy and productive.
I could easily “work” 40 hours per week by jeopardizing my productivity, my health and my social life.
I choose not to do that.</p>

<p>With only 8 more hours free time I <a href="https://dasdom.dev/books/">wrote several books</a>, spoke at conferences and <a href="https://apps.apple.com/de/developer/dominik-hauser/id325836858">published some
apps</a>.
I’m spending more time with my children and I’m trying to be a better partner to my wife.</p>

<p>What could I do with 12 more hours for myself and my family?
What kind of a dad could I be with so much time?
How would our society look like if more people would only work the hours they are productive?
I guess we would be happier and <a href="https://www.businessinsider.com/the-real-reason-for-the-40-hour-workweek-2014-6">probably way worse customers</a>.</p>

<p>How about you? 
How many of your work hours per day are actually needed for your output? 
Let me know
on <a href="https://chaos.social/@dasdom">Mastodon</a>.</p>]]></content><author><name></name></author><category term="Work," /><category term="Programming," /><category term="Productivity" /><summary type="html"><![CDATA[We are lied to]]></summary></entry><entry><title type="html">Why I Hate AI (And You Should Too)</title><link href="https://dasdom.dev/why-i-still-dont-use-ai/" rel="alternate" type="text/html" title="Why I Hate AI (And You Should Too)" /><published>2026-05-05T06:00:00+00:00</published><updated>2026-05-05T06:00:00+00:00</updated><id>https://dasdom.dev/why-i-still-dont-use-ai</id><content type="html" xml:base="https://dasdom.dev/why-i-still-dont-use-ai/"><![CDATA[<p>When scrolling through the internet it seems like everyone is using AI coding assistants (“agents”) <em>AND</em> is
loving it. 
I still don’t get it.</p>

<p>I try not to use AI for coding. 
It’s getting harder every day because people believe that they can save truck loads of money when everyone is reading code instead of writing code.</p>

<p>For me there are several reasons to avoid this new kind of software development. 
Some very important, some less so. 
Here are the most important reasons for me sorted by importance.</p>

<h1 id="1-i-love-coding">1. I love coding</h1>

<p>I’m one of the few people who loves coding.
Even writing the 100th implementation of a table view or setting up a views layout in code gives me joy.
My brain rewards me with dopamine when I write boilerplate code.</p>

<p>I guess the reason for this is that occasionally while typing a boring implementation of a boring
table view <em>again</em> I have an idea what could be improved.
This is rare but when it happens I’m exited for days.
Situations like this feel awesome.
If this ever happened to you, I guess you know what I mean.</p>

<p>All this joy evaporates when an agent suggests code.
I have less good ideas when reading the code of others.
Sometimes I learn something but it’s more like learning in school or university.
It’s nice but it fails to even remotely compare to the feeling of creating something elegant by
myself.</p>

<p>I get (even more) grumpy if I don’t write code regularly.
Then my wife asks me to write some code to brighten my mood.
I’m not making this up!</p>

<blockquote>
  <p>“Grumpy. Angry. Stupid. How long since last <del>sleep</del> code, question?”</p>
</blockquote>

<h1 id="2-environmental-impact">2. Environmental impact</h1>

<p>Coding agents need lots of energy and water.
This energy and water consumption has a huge negative impact on the environment.
What use has a boring and bad application or service on a planet where nothing grows anymore?
We have to solve very demanding and complex problems <em>before</em> we can use AI for coding.</p>

<p>I have two children and even before everyone stopped caring about the environment because they are to
lazy to write code themselves, I has afraid of their future.</p>

<h1 id="3-modern-colonialism">3. Modern colonialism</h1>

<p>All current models have been trained with stolen data and labor.
All profits flow to the rich and wealthy.
People have been and are right now exploited by AI companies to make the wealthy richer.</p>

<p>This is wrong and by using these agents trained with stolen data and labor I am wrong as well.</p>

<h1 id="4-the-end-of-learning">4. The end of learning</h1>

<p>I learn by doing.
When I stop coding, I stop learning about code.
Learning is slow.
It took me years to become an acceptable coder.
And I need constant practice to keep my skills.</p>

<p>A few years ago I realized that creating table view using diffable data sources was hard.
I had to look up the same thing each and every time.
So I forced myself to do lots and lots of table views with diffable data sources.
After a while I got it.
I was able to use this API without opening the documentation.
And this was the moment when I developed my own ideas how to improve the API for diffable data
sources.
I was able to create helper extensions to make the usage easier.
Without doing the hard work I would never achieved this understanding.</p>

<h1 id="5-bad-results">5. Bad results</h1>

<p>Over the last few weeks I used coding agents.
Results are underwhelming.
Sometimes the agents tells me that I could improve my code.
Sometimes the results are trash.
At best the result is what I would have written but without the joy.</p>

<p>As always with conmen if you experience problems like this it’s either your fault or the next <a href="https://en.wikipedia.org/wiki/Snake_oil">snake
oil</a> (model) will fix all your problems.
Just keep using it.</p>

<h1 id="6-good-ideas-arent-quick">6. Good ideas aren’t quick</h1>

<p>Our brains need time to come up with good solutions.
And often we need to make mistakes and figure out the problems ourselves to come up with even better
solutions.
Without this slow process the solutions can’t be good.</p>

<h1 id="7-future-costs">7. (Future) costs</h1>

<p>At the moment all AI usage is heavily
<a href="https://popularaitools.ai/blog/ai-tool-pricing-getting-expensive">subsidised</a>.
Anthropic, GitHub and OpenAI are gambling, that we are soon not able or willing anymore to write 
code ourselves.
They will have to charge 10x or even 20x when the VC money runs out.
OpenAI already started and failed to add ads into ChatGPT.</p>

<p>Why should I buy myself into addiction?</p>

<h1 id="8-last-but-not-least-its-against-the-natural-order-of-things">8. Last but not least: It’s against the natural order of things.</h1>

<blockquote>
  <p>I’ve come up with a set of rules that describe our reactions to technologies:</p>

  <ol>
    <li>Anything that is in the world when you’re born is normal and ordinary and is just a natural part of the way the world works.</li>
    <li>Anything that’s invented between when you’re fifteen and thirty-five is new and exciting and revolutionary and you can probably get a career in it.</li>
    <li>Anything invented after you’re thirty-five is against the natural order of things.</li>
  </ol>
</blockquote>

<p>– Douglas Adams</p>]]></content><author><name></name></author><category term="Xcode," /><category term="iOS," /><category term="AI," /><category term="LLM" /><summary type="html"><![CDATA[The future nobody asked for.]]></summary></entry><entry><title type="html">I was wrong</title><link href="https://dasdom.dev/i-was-wrong-kind-of/" rel="alternate" type="text/html" title="I was wrong" /><published>2025-06-19T06:00:00+00:00</published><updated>2025-06-19T06:00:00+00:00</updated><id>https://dasdom.dev/i-was-wrong-kind-of</id><content type="html" xml:base="https://dasdom.dev/i-was-wrong-kind-of/"><![CDATA[<p>In a recent <a href="https://chaos.social/@dasdom/114683426476942144">post on Mastodon</a> I expressed my
frustration that user interfaces Apple engineers build with SwiftUI tend to be so bad, they could be
from a very old Windows version.</p>

<p><img src="../../../assets/2025-06-19/initial_post_on_mastodon.png" height="300" /></p>

<p>This new user interface is garbage.
It gets worse when you realize that this had to be implemented by a person working on Xcode.
This poor person had to build a user interface that is clearly designed for a bad toy software into a
software they have to use every day.</p>

<p>So <a href="https://chaos.social/@dasdom/114702314515072133">I assumed</a> the reason has to be that it’s easier to build bad user interfaces in SwiftUI on the Mac.
To proof me wrong I build the Behavior settings user interface from Xcode 16 myself using SwiftUI.</p>

<p>It turned out, <strong>I indeed was wrong.</strong> <br />
Kind of.</p>

<p>It is very easy to build the user interface from Xcode 16 using SwiftUI.
Even a person like me, who hates and avoids SwiftUI with a passion can build a usable user interface
with it.</p>

<p>(I ignored data handling and there is a bug that the selection of the table on the left side isn’t
shown, but apart from that, this seems to work.)</p>

<figure>
    <img src="../../../assets/2025-06-19/xcode_16_demo_swiftui.png" height="400" />
    <figcaption>My experiment for a usable Behaviors setting build with SwiftUI.</figcaption>
</figure>

<p>So the question is, why did Apple choose to build such a horrible user interface?</p>

<figure>
    <img src="../../../assets/2025-06-19/behaviors_settings_xcode26.png" height="400" />
    <figcaption>The Behavior setting in Xcode 26..</figcaption>
</figure>

<p>What do you think?</p>

<p>Let me know on <a href="https://chaos.social/@dasdom">Mastodon</a>.</p>

<p>Apple, if you need that code, my DM are open. ;)</p>

<p>(No AI was used to write this post.)</p>]]></content><author><name></name></author><category term="Xcode," /><category term="SwiftUI," /><category term="UX," /><category term="UI" /><summary type="html"><![CDATA[Kind of]]></summary></entry><entry><title type="html">Frames in the iOS simulator in landscape</title><link href="https://dasdom.dev/frames-in-the-ios-simulator-in-landscape/" rel="alternate" type="text/html" title="Frames in the iOS simulator in landscape" /><published>2025-06-02T06:00:00+00:00</published><updated>2025-06-02T06:00:00+00:00</updated><id>https://dasdom.dev/frames-in-the-ios-simulator-in-landscape</id><content type="html" xml:base="https://dasdom.dev/frames-in-the-ios-simulator-in-landscape/"><![CDATA[<p><a href="https://dasdom.dev/building-a-dev-tool/">I might be building a developer tool for iOS developers.</a>
Recently I encountered yet another problem.
In landscape the frames of the user interface elements are all wrong.
It looks like they are the frames of the elements in portrait.</p>

<p><img src="../../../assets/2025-06-02/wrong_frames_in_landscape.png" height="400" /></p>

<p>To me it looks like landscape on iOS simulator (or maybe even on the real device) is some kind of hack.
First I tried to rotate and shift the frames but this didn’t work.
It turned out that the elements would have to be shifted by different amounts.</p>

<p>Next I tried to check how Apple solved this in their demo project.
They didn’t.
The demo project had the same problem.</p>

<p>OK, next idea: Accessibility Inspector.
Turns out, if the source is set to the host Mac, I see the same problem.</p>

<p><img src="../../../assets/2025-06-02/wrong_frame_in_accessibility_inspector.png" height="400" /></p>

<p>But if I change the source to the iOS simulator, the frames are correct.</p>

<p><img src="../../../assets/2025-06-02/correct_frame_in_accessibility_inspector.png" height="400" /></p>

<p>OK…</p>

<p>At the moment I have no idea how I could change the host in my tool to get the same behavior.
I might still release the app with this little flaw.</p>

<p>If you know how to fix this, hints would be highly appreciated!</p>

<p>Until next time, have a nice day, week and month.</p>

<p>(No AI was used to write this post.)</p>]]></content><author><name></name></author><category term="iOS," /><category term="iOS-simulator," /><category term="dev-tool," /><category term="AppKit," /><category term="Objective-C" /><summary type="html"><![CDATA[They are wrong]]></summary></entry><entry><title type="html">Building A Dev Tool</title><link href="https://dasdom.dev/building-a-dev-tool/" rel="alternate" type="text/html" title="Building A Dev Tool" /><published>2025-05-25T06:00:00+00:00</published><updated>2025-05-25T06:00:00+00:00</updated><id>https://dasdom.dev/building-a-dev-tool</id><content type="html" xml:base="https://dasdom.dev/building-a-dev-tool/"><![CDATA[<p>From time to time I switch off my external trackpad to force myself to use keyboard shortcuts in Xcode.
In principle I know <a href="https://xcode.tips">many useful shortcuts</a> but I often forget to use them
because I need to think to much about them.
The easiest way to make using them more natural is to use them more.</p>

<p>But when the external trackpad is switched off, I need to use the trackpad of my MacBook to
control the iOS simulator.
I tried apps like <a href="https://www.homerow.app">Homerow</a> or <a href="https://shortcat.app">Shortcat</a> but
these do not find all elements in the iOS simulator.
In addition, as they need accessibility access to my Mac I might not be able to use them on my
work Mac (because they can work like keyloggers).</p>

<p>I’m a developer.
So the natural conclusion could be that I have to build such a tool myself.
And this is what I tried.
I’m not done yet and it’s still not clear if I will succeed.
Especially as I face some strange problems right now.
But these will be discussed in a later post.
This post is about how I build the tool and what it can do at the moment.</p>

<h2 id="demo">Demo</h2>

<p><img src="../../../assets/2025-05-25/simclicker_demo.gif" height="400" /></p>

<h2 id="swiftui-or-appkit">SwiftUI or AppKit?</h2>

<blockquote>
  <p>SwiftUI is a scam. <br />
– Dominik Hauser</p>
</blockquote>

<p>I don’t like SwiftUI.
So I use AppKit.
This comes with another advantage.
I can write the code in Objective-C.
This is a good thing because I like and miss Objective-C a lot.</p>

<p>In addition the Accessibility API is C-based.
Such APIs are easier to use in Objective-C than in Swift.</p>

<h2 id="how-this-works">How this works</h2>

<p>Most Mac apps have some kind of accessibility support.
For example native controls like buttons or text fields expose themselves to the accessibility
system.
Screenreaders or other accessibility tools can find those user interface elements.
Apps can hook into this system.</p>

<p>In the accessibility API the user interface elements have different roles.
For example an <code class="language-plaintext highlighter-rouge">NSButton</code> has the role <code class="language-plaintext highlighter-rouge">AXButton</code>.
Elements can be grouped into <code class="language-plaintext highlighter-rouge">AXGroup</code>s.
A tool can ask the accessibility system for the <code class="language-plaintext highlighter-rouge">AXChildren</code> of a accessibility element.
And this is what I tried first.</p>

<p>Here is the process.
First the app searches for running iOS simulators and takes the first it finds.
(I might improve that in the future and let the user select from a list of simulators.)</p>

<pre><code class="language-Objective-C">- (void)findSimulators {
    NSArray&lt;NSRunningApplication *&gt; *applications = [[NSWorkspace sharedWorkspace] runningApplications];
    NSMutableArray&lt;NSString *&gt; *names = [[NSMutableArray alloc] init];
    NSMutableArray&lt;NSRunningApplication *&gt; *simulators = [[NSMutableArray alloc] init];
    for (NSRunningApplication *application in applications) {
        if ([application.bundleIdentifier isEqualToString:@"com.apple.iphonesimulator"]) {
            NSLog(@"simulator: %@", application);

            [simulators addObject:application];

            [names addObject:application.localizedName];
        }
    }

    NSRunningApplication *simulator = simulators.firstObject;
    self.simulatorRef = AXUIElementCreateApplication(simulator.processIdentifier);
    self.simulator = simulator;
    NSLog(@"applicationRef: %@", self.simulatorRef);

    [simulator addObserver:self forKeyPath:@"ownsMenuBar" options:NSKeyValueObservingOptionNew context:nil];
}
</code></pre>

<p>Then the app searches for the <code class="language-plaintext highlighter-rouge">NSWindow</code> (role <code class="language-plaintext highlighter-rouge">AXWindow</code>) and asks it for it’s children.
To find the children of an <code class="language-plaintext highlighter-rouge">AXElement</code> (in this case an <code class="language-plaintext highlighter-rouge">AXWindow</code>) I use methods from a demo 
project provided by Apple.</p>

<pre><code class="language-Objective-C">+ (NSArray&lt;NSValue *&gt; *)childrenOfUIElement:(AXUIElementRef)element {
    CFArrayRef children = nil;

    children = (__bridge CFArrayRef)([UIElementUtilities valueOfAttribute:NSAccessibilityChildrenAttribute ofUIElement:element]);

    return (__bridge NSArray&lt;NSValue *&gt; *)(children);
}

+ (id)valueOfAttribute:(NSString *)attribute ofUIElement:(AXUIElementRef)element {
    CFTypeRef result = nil;
    NSArray *attributeNames = [UIElementUtilities attributeNamesOfUIElement:element];

    if (attributeNames) {
        if ( [attributeNames indexOfObject:(NSString *)attribute] != NSNotFound
                &amp;&amp;
        	AXUIElementCopyAttributeValue(element, (CFStringRef)attribute, &amp;result) == kAXErrorSuccess
        ) {
        }
    }
    return (__bridge id)(result);
}
</code></pre>

<p>Unfortunately there is a bug in the Accessibility API.
If the app recursively asks the <code class="language-plaintext highlighter-rouge">AXElement</code>s for their children it does not find all elements.
For example in the following screenshot the navigation bar items (back button and the button
on the right) are missing.</p>

<p><img src="../../../assets/2025-05-25/missing_elements.png" width="400" /></p>

<p>After some digging and debugging I found out that the navigation bar is exposed as an <code class="language-plaintext highlighter-rouge">AXGroup</code> but
with no children.
To make sure it’s not a bug in my code I used Shortcat with the same result.</p>

<p><img src="../../../assets/2025-05-25/missing_elements_shortcat.png" width="400" /></p>

<h2 id="a-different-approach">A different approach</h2>

<p>The I tried to define a grid and ask accessibility to find all the elements on the grid cross
sections.
This worked but took significantly longer.
First I was willing to accept the worse performance but then I had an idea.
What if I use the quick method first and for all the <code class="language-plaintext highlighter-rouge">AXGroup</code> with zero children I then use
the grid method.
This worked.
The tool now quickly finds all user interface elements.
Hooray!</p>

<h2 id="more-problems">More problems</h2>

<p>The tools works well unless the simulator is in landscape.
For some strange reason the frames of the elements are all wrong in this case.
I’ll discuss that in a future post.</p>

<p>Until then, have a nice day, week and month.</p>

<p>(No AI was used to write this post.)</p>]]></content><author><name></name></author><category term="iOS," /><category term="iOS-simulator," /><category term="dev-tool," /><category term="AppKit," /><category term="Objective-C" /><summary type="html"><![CDATA[Controlling the iOS simulator with the keyboard.]]></summary></entry><entry><title type="html">Why I don’t use AI</title><link href="https://dasdom.dev/why-i-dont-use-ai/" rel="alternate" type="text/html" title="Why I don’t use AI" /><published>2025-05-08T06:00:00+00:00</published><updated>2025-05-08T06:00:00+00:00</updated><id>https://dasdom.dev/why-i-dont-use-ai</id><content type="html" xml:base="https://dasdom.dev/why-i-dont-use-ai/"><![CDATA[<blockquote>
  <p>I’ve come up with a set of rules that describe our reactions to technologies:</p>

  <ol>
    <li>Anything that is in the world when you’re born is normal and ordinary and is just a natural part of the way the world works.</li>
    <li>Anything that’s invented between when you’re fifteen and thirty-five is new and exciting and revolutionary and you can probably get a career in it.</li>
    <li>Anything invented after you’re thirty-five is against the natural order of things.</li>
  </ol>
</blockquote>

<p>– Douglas Adams</p>

<p>I try to avoid AI where ever I can.
I ecpecially don’t use it for development tasks.
And here is why.</p>

<h1 id="im-older-than-thirty-five">I’m older than thirty-five</h1>

<p>So, AI is against the natural order of things.</p>

<h1 id="good-solutions-need-time">Good solutions need time</h1>

<p>The AI can’t come up with good solutions. 
It just presents one solution it figured out by adding strings to other strings. 
I have to figure out if it is a good solution. 
To figure that out, I need time. 
I need to think. 
I need to wrap my head around the problem I try to solve. 
Figuring out if something works is way harder if I didn’t come up with the solution myself. 
Most people use just the solution the AI presents and don’t care if it’s a good solution.
I don’t like that.</p>

<h1 id="the-joy-of-using-my-brain">The joy of using my brain</h1>

<p>I like using my brain.
Figuring something out gives me a dopamine kick.
Finally finding a good solution for a problem is the reason why I love coding.
Why should I let the AI have all the fun.</p>

<h1 id="selling-cheap">Selling cheap</h1>

<p>Each input trains the AI.
By using AI I help it to finally replace me in my job.
I don’t like that.</p>

<h1 id="environment">Environment</h1>

<p>AI is destroying the planet faster than my brain does.</p>

<h1 id="society">Society</h1>

<p>AI helps rich people to get free labor from poor people.
In this scenario I’m on the side of the poor people.
The rich are too rich already.
I’m not willing to help make them richer.
More than I do already.
(Written on a MacBook…)</p>

<h1 id="you">You</h1>

<p>What about you?
Do you use AI?
Why?
Why not?</p>]]></content><author><name></name></author><category term="Xcode," /><category term="iOS," /><category term="AI," /><category term="LLM" /><summary type="html"><![CDATA[Maybe because I'm old.]]></summary></entry><entry><title type="html">How I use AI as an iOS developer</title><link href="https://dasdom.dev/how-i-use-ai/" rel="alternate" type="text/html" title="How I use AI as an iOS developer" /><published>2025-04-28T06:00:00+00:00</published><updated>2025-04-28T06:00:00+00:00</updated><id>https://dasdom.dev/how-i-use-ai</id><content type="html" xml:base="https://dasdom.dev/how-i-use-ai/"><![CDATA[<p>I don’t.</p>]]></content><author><name></name></author><category term="Xcode," /><category term="iOS," /><category term="AI," /><category term="LLM" /><summary type="html"><![CDATA[How do I use AI]]></summary></entry><entry><title type="html">Hot Reloading In SwiftUI</title><link href="https://dasdom.dev/hot-reloading-in-swiftui/" rel="alternate" type="text/html" title="Hot Reloading In SwiftUI" /><published>2024-04-29T06:00:00+00:00</published><updated>2024-04-29T06:00:00+00:00</updated><id>https://dasdom.dev/hot-reloading-in-swiftui</id><content type="html" xml:base="https://dasdom.dev/hot-reloading-in-swiftui/"><![CDATA[<p>Previews in Xcode are kind of nice, when they work.
But for me they are often slow or stop working after a few minutes.</p>

<p>Fortunately for us, the amazing <a href="https://johnholdsworth.com">John Holdsworth</a> wrote a packaged that adds hot reloading to SwiftUI projects.
Even better, it’s suprisingly easy to add to your project.</p>

<h2 id="method-one-swift-package">Method One: Swift Package</h2>

<p>First, we need to add the following two Swift packages to the project:</p>

<ul>
  <li><a href="https://github.com/johnno1962/HotReloading">HotReloading</a></li>
  <li><a href="https://github.com/johnno1962/HotSwiftUI">HotSwiftUI</a></li>
</ul>

<p>When asked, only add the HotReloading package product to your target:</p>

<p><img src="../../../assets/2024-04-29/hot_reloading_target.png" alt="" /></p>

<p>Next add <code class="language-plaintext highlighter-rouge">-Xlinker -interposable</code> to ‘Other Linker Flags’ in the build settings of the target:</p>

<p><img src="../../../assets/2024-04-29/other_linker_flags.png" alt="" /></p>

<p><strong>In this method you need to remember to remove the hot reloadng package before you upload your app to App Store Connect.</strong></p>

<h2 id="method-two-injection-iii">Method Two: Injection III</h2>

<p>You still need to add the <a href="https://github.com/johnno1962/HotSwiftUI">HotSwiftUI</a> package to your project.
Again add <code class="language-plaintext highlighter-rouge">-Xlinker -interposable</code> to ‘Other Linker Flags’ in the build settings of the target:</p>

<p><img src="../../../assets/2024-04-29/other_linker_flags.png" alt="" /></p>

<p>Next load the latest release of the <a href="https://github.com/johnno1962/InjectionIII/releases">Inject III app</a> and start it.</p>

<h2 id="setup-your-view">Setup your view</h2>

<p>In the view file you are currently working on, add the following import:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@_exported</span> <span class="kd">import</span> <span class="kt">HotSwiftUI</span>
</code></pre></div></div>

<p>Next, erase the type of the root view using <code class="language-plaintext highlighter-rouge">.eraseToAnyView()</code>:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="c1">// Your SwiftUI code...</span>
  <span class="o">.</span><span class="nf">eraseToAnyView</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally add the following line to your view struct:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@ObserveInjection</span> <span class="k">var</span> <span class="nv">redraw</span>
</code></pre></div></div>

<p>Build and run your app on the Simulator, change some code and save the file.
The changes are magically compiled and injected into the running app:</p>

<p><img src="../../../assets/2024-04-29/demo.gif" alt="" /></p>

<h2 id="conclusion">Conclusion</h2>

<p>Hot reloading does not work all the time.
Sometimes you need to recompile using Xcode.
But most of the times it works suprisingly well.
Give it a try and see how amazing this is.</p>

<p>And if you like it and it helps in your daily work, consider <a href="https://github.com/sponsors/johnno1962">becomming a sponsor of the project on
GitHub</a>.</p>

<p>Thanks for reading!</p>]]></content><author><name></name></author><category term="Xcode," /><category term="iOS," /><category term="Hot" /><category term="Reloading," /><category term="SwiftUI," /><category term="How-To" /><summary type="html"><![CDATA[Add real hot reloading to a SwiftUI project]]></summary></entry><entry><title type="html">Renaming a widget extension</title><link href="https://dasdom.dev/renaming-a-widget-extension/" rel="alternate" type="text/html" title="Renaming a widget extension" /><published>2022-08-07T08:00:00+00:00</published><updated>2022-08-07T08:00:00+00:00</updated><id>https://dasdom.dev/renaming-a-widget-extension</id><content type="html" xml:base="https://dasdom.dev/renaming-a-widget-extension/"><![CDATA[<p>I’m working on an update for <a href="https://dasdom.dev/physics_plus_plus/">my formulary
app</a>.
Among other improvements, this update will add widgets.</p>

<p><img src="../../../assets/2022-08-07/widget.png" alt="" /></p>

<p>Along the way I decided to add another widget so the name of the extension
didn’t match anymore and I had to rename it.</p>

<p>First I feared that this could be as difficult as renaming a project in
Xcode.
But it turned out that I just had to replace all the occurrences of the old
name.</p>

<p>For now I’ll keep the names of the entitlement files as they have been.
This is a problem for future Dominik.
:)</p>]]></content><author><name></name></author><category term="Xcode," /><category term="iOS," /><category term="WidgetKit," /><category term="Widget," /><category term="How-To" /><summary type="html"><![CDATA[How to rename a widget extension]]></summary></entry><entry><title type="html">Minimize the number of test assertions</title><link href="https://dasdom.dev/minimize-number-of-test-assertions/" rel="alternate" type="text/html" title="Minimize the number of test assertions" /><published>2022-06-11T08:00:00+00:00</published><updated>2022-06-11T08:00:00+00:00</updated><id>https://dasdom.dev/minimize-number-of-test-assertions</id><content type="html" xml:base="https://dasdom.dev/minimize-number-of-test-assertions/"><![CDATA[<p>Recently I wrote a <a href="https://twitter.com/dasdom/status/1534208496018894849">tweet</a> about demo code shown by an Apple engineer in a WWDC session.</p>

<blockquote>
  <p>Demo code doesn’t need to be good. If you are wondering, this is not how to write unit tests when you are not demonstrating. Try to only have one assertion in a test method.</p>
</blockquote>

<p>I got several answers that it’s not practical to write a test for each small little detail one wants
to test and that it’s better to test several things in one test if possible.
I totally disagree.
It might be OK to have several asserts in one test but this should be an exception.
Especially in the case of the test code from the WWDC session, I would rather have several tests.</p>

<p>This is the code that was shown in the video:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func testExtractEventCount () throws {
    
    let providerClass = ServerBackedEventProvider.self 

    // Simple cases
    XCTAssertEqual(providerClass.extractEventCount(from: "0 records"), 0)
    XCTAssertEqual(providerClass.extractEventCount(from: "1 record"), 1)
    XCTAssertEqual(providerClass.extractEventCount(from: " 1 record(s)"), 1)
    XCTAssertEqual(providerClass.extractEventCount(from: "25 records"), 25)
    XCTAssertEqual(providerClass.extractEventCount(from:"50 records"), 50)
    
    // Cases we expect parsing to return nil
    XCTAssertNil(providerClass.extractEventCount(from: "NaN records") )
    XCTAssertNil(providerClass.extractEventCount(from: ""))
    XCTAssertNil(providerClass.extractEventCount(from: "jUnKdAtA"))
}
</code></pre></div></div>

<p>In the demo code is a bug and therefore this test fails in the line extracting from “0 records” and
from “50 records”.
With the information from this test, the engineer can fix the bug quickly.</p>

<p>But if this test would fail on Xcode Cloud, the engineer would only see the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>testExtractEventCount(): XCTAssertEqual failed: ("nil") is not equal to ("Optional(0)")
</code></pre></div></div>

<p>Not really helpful in my opinion.
Critical information is missing:</p>

<ul>
  <li>What was tested?</li>
  <li>What was the precondition?</li>
  <li>What did we expect?</li>
</ul>

<p>I would split the test assertions into several tests.
Testing for the extraction from “0 records” would then look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func test_extractEventCount_whenInputIs0Records_shouldExtractO() throws {
    // given
    let sut = SeverBackedEventProvider.self

    // when
    let result = sut.extractEventCount(from: "0 records")

    // then
    XCTAssertEqual(result, 0)
}
</code></pre></div></div>

<p>In case of a failure of this test we would see in the test result the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>text_extractEventCount_whenInputIs0Records_shouldExtractO(): XCTAssertEqual failed: ("nil") is not
equal to ("Optional(0)")
</code></pre></div></div>

<p>Without looking at the test code, I already know what exactly failed.
Tests should help my future self and my coworkers to find the reason for the failure as quick as
possible.
This is the main feature a test should have.
Personally I find the failure message of the second test way better and looking at the test I do
better understand its purpose and why it was written.</p>

<p>What do you think?
Which of these tests is better?
Let me know on <a href="https://twitter.com/dasdom">Twitter</a>.</p>]]></content><author><name></name></author><category term="Unit-Tests," /><category term="XCTest," /><category term="Assertions," /><category term="TDD" /><summary type="html"><![CDATA[Why you should minimize the number of test assertions in your Unit Tests.]]></summary></entry></feed>