<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="https://padraig.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://padraig.org/" rel="alternate" type="text/html" /><updated>2023-10-24T21:58:08+00:00</updated><id>https://padraig.org/feed.xml</id><title type="html">Pádraig on the Computer</title><subtitle>Notes from a Swift programmer</subtitle><entry><title type="html">SwiftSyntax Code Generation Notes</title><link href="https://padraig.org/swift-format/2023/10/17/swift-format-tips.html" rel="alternate" type="text/html" title="SwiftSyntax Code Generation Notes" /><published>2023-10-17T22:00:25+00:00</published><updated>2023-10-17T22:00:25+00:00</updated><id>https://padraig.org/swift-format/2023/10/17/swift-format-tips</id><content type="html" xml:base="https://padraig.org/swift-format/2023/10/17/swift-format-tips.html">&lt;p&gt;I used &lt;a href=&quot;https://github.com/apple/swift-syntax&quot;&gt;SwiftSyntax&lt;/a&gt; in my &lt;a href=&quot;https://padraig.org/godot/2023/10/17/scene-gen&quot;&gt;SceneGen&lt;/a&gt; tool. The syntax code can easily get messy and hard to follow, so I’ve been following these patterns in my &lt;a href=&quot;https://github.com/PadraigK/SceneGen/blob/main/Sources/SceneGen/Rendering.swift&quot;&gt;renderer code&lt;/a&gt; to keep it neat and simple:&lt;/p&gt;

&lt;h3 id=&quot;prepare-the-data-first&quot;&gt;Prepare the Data First&lt;/h3&gt;

&lt;p&gt;Process any data that the renderer functions will need separately from any code that touches SwiftSyntax. Any fetching, parsing, mapping should be done outside the renderer. The renderer functions should just take a model with everything neatly arranged for it and output the rendered code.&lt;/p&gt;

&lt;p&gt;This helps keep this code simpler, because it’s only about the structure of the source code you’re building.&lt;/p&gt;

&lt;h3 id=&quot;use-extensions-to-simplify&quot;&gt;Use Extensions to Simplify&lt;/h3&gt;

&lt;p&gt;If you find you have a few lines of SwiftSyntax code just to do something very simple, then extract it into an extension, especially if it’s repeated in a few places.&lt;/p&gt;

&lt;p&gt;Make these extensions private, they should be specific to your implementation here and won’t usually be re-usable in the rest of the project.&lt;/p&gt;

&lt;p&gt;When writing extensions consider using concrete types for the arguments, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeSyntax&lt;/code&gt;, instead of protocols like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeSyntaxProtocol&lt;/code&gt;. This will allow you to leverage &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExpressibleByStringLiteral&lt;/code&gt; so you can just pass a string at the call-site.&lt;/p&gt;

&lt;p&gt;Here’s an example — I often want to tag a struct as conforming to a protocol, so I added this extension, and now I can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExtensionDeclSyntax.conform(&quot;MyStruct&quot;, to: &quot;Equatable&quot;)&lt;/code&gt; to do it in one line of easily understood code.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;/// Adds a conformance to a type&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;/// Usage: `ExtensionDeclSyntax.conform(&quot;MyStruct&quot;, to: &quot;Equatable&quot;)`&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExtensionDeclSyntax&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;conform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TypeSyntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;conformType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TypeSyntax&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExtensionDeclSyntax&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;ExtensionDeclSyntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;leadingTrivia&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;extendedType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;inheritanceClause&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;InheritanceClauseSyntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;inheritedTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;InheritedTypeSyntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conformType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;isolate-swiftsyntax-to-one-file&quot;&gt;Isolate SwiftSyntax to One File&lt;/h3&gt;

&lt;p&gt;Keep your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftSyntax&lt;/code&gt; quarantined. For public functions, don’t use any SwiftSyntax types as parameters or return values. I have &lt;a href=&quot;https://github.com/PadraigK/SceneGen/blob/main/Sources/SceneGen/Rendering.swift&quot;&gt;a single ~250 line file&lt;/a&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import SwiftSyntax&lt;/code&gt; in my project and it contains everything I need to understand how rendering is working.&lt;/p&gt;

&lt;h3 id=&quot;find-a-balance-when-specifying-syntax&quot;&gt;Find a Balance when Specifying Syntax&lt;/h3&gt;

&lt;p&gt;Don’t go to extremes to specify everything as granularly as possible. When rendering a utility function with no interpolation in it, favour using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeclSyntax()&lt;/code&gt; with a block string.&lt;/p&gt;

&lt;p&gt;Conversely, if you have big block string with a lot of interpolation happening, consider breaking it up into more explicit pieces of syntax.&lt;/p&gt;</content><author><name>Pádraig Ó Cinnéide</name></author><category term="swift-format" /><summary type="html">I used SwiftSyntax in my SceneGen tool. The syntax code can easily get messy and hard to follow, so I’ve been following these patterns in my renderer code to keep it neat and simple:</summary></entry><entry><title type="html">SceneGen for SwiftGodot</title><link href="https://padraig.org/godot/2023/10/17/scene-gen.html" rel="alternate" type="text/html" title="SceneGen for SwiftGodot" /><published>2023-10-17T20:00:25+00:00</published><updated>2023-10-17T20:00:25+00:00</updated><id>https://padraig.org/godot/2023/10/17/scene-gen</id><content type="html" xml:base="https://padraig.org/godot/2023/10/17/scene-gen.html">&lt;p&gt;I’ve been enjoying tinkering with &lt;a href=&quot;https://godotengine.org/&quot;&gt;Godot&lt;/a&gt; and &lt;a href=&quot;https://github.com/migueldeicaza/SwiftGodot&quot;&gt;SwiftGodot&lt;/a&gt; lately. Following tutorials while translating all the GDScript parts into Swift has a nice side-effect of keeping my attention more focused, so I am not just zoning out and copying everything from the tutorial.&lt;/p&gt;

&lt;p&gt;This week I &lt;a href=&quot;https://github.com/PadraigK/SceneGen&quot;&gt;released a code generation tool&lt;/a&gt; that lets me leverage Swift’s type safety when referencing objects in Godot that are usually referenced using raw strings.&lt;/p&gt;

&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;Godot game designers build scenes in the Godot editor. A scene is a tree of nodes with some properties that are configured in the editor. A node could be a sprite, a collision detector, or a path to follow. Nodes are built up into scenes that represent each game object, so maybe a spaceship for the player, a level map, or the heads-up-display interface.&lt;/p&gt;

&lt;p&gt;Most scenes in a game need some behaviour; e.g. when a bullet scene collides with a rock scene, the bullet should disappear and the rock should explode. To add behaviour to a scene, the programmer must write some code.&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Lets say a game programmer wants to handle when the game ends; they want to make the player disappear.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;gameEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getNodeOrNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Node/PlayerSprite&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sprite2D&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;didn't find a player node :(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	
  &lt;span class=&quot;n&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getNodeOrNull&lt;/code&gt; to get the node at path “Node/PlayerSprite” in the scene tree. It then attempts to cast it to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sprite2D&lt;/code&gt; object. This is very brittle and will break if the programmer:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Moves the PlayerSprite to have a different parent node in the tree&lt;/li&gt;
  &lt;li&gt;Renames PlayerSprite.&lt;/li&gt;
  &lt;li&gt;Mistypes the name.&lt;/li&gt;
  &lt;li&gt;Changes the type of Sprite2D to something else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s common to do all of these when making a game. These problems are particularly bad because they occur at &lt;em&gt;run time&lt;/em&gt;. Since paths are just strings even our IDE can’t help us by suggesting the correct spelling of node names.&lt;/p&gt;

&lt;p&gt;So I wrote a tool to make this better! &lt;a href=&quot;https://github.com/PadraigK/SceneGen&quot;&gt;SceneGen&lt;/a&gt; will generate strongly typed descriptions of all the nodes in each scene, so now, you can do:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;gameEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;playerSprite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.playerSprite&lt;/code&gt; is a reference to a generated struct that knows the path to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;Node/PlayerSprite&quot;&lt;/code&gt; and knows that it is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sprite2D&lt;/code&gt; type object, so there’s no longer a need to supply these at the call-site.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node()&lt;/code&gt; function is scoped tightly to only the nodes on the scene you’re working on so IDE suggestions will provide the exact names.&lt;/p&gt;

&lt;p&gt;If you re-arrange, rename or change the types of any of these nodes in the editor, you’ll get compile-time errors exactly at the point in your code that needs to be fixed, instead of run time crashes / failures.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Having my IDE be directly aware of my scenes has been a huge improvement. I’m spending much less time debugging crashes and more time enjoying learning how to make games.&lt;/p&gt;</content><author><name>Pádraig Ó Cinnéide</name></author><category term="godot" /><summary type="html">I’ve been enjoying tinkering with Godot and SwiftGodot lately. Following tutorials while translating all the GDScript parts into Swift has a nice side-effect of keeping my attention more focused, so I am not just zoning out and copying everything from the tutorial.</summary></entry><entry><title type="html">NSView Subviews</title><link href="https://padraig.org/appkit/2021/09/05/subviews.html" rel="alternate" type="text/html" title="NSView Subviews" /><published>2021-09-05T20:09:25+00:00</published><updated>2021-09-05T20:09:25+00:00</updated><id>https://padraig.org/appkit/2021/09/05/subviews</id><content type="html" xml:base="https://padraig.org/appkit/2021/09/05/subviews.html">&lt;p&gt;In a custom NSView, when building up a list of subviews, it is typical to call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addSubview&lt;/code&gt; function once for each subview. A neater way to do this is to just set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subviews&lt;/code&gt; array directly. The NSView internals are clever enough to do any of the extra book-keeping required, just as if you had called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addSubview&lt;/code&gt; each time.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;titleView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;detailText&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;saveButton&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;subviews&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;detailText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saveButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I like this because it’s a little more concise, and it also reminds me to think about the order of the subviews. Thanks to Jeff Nadeau for pointing this out &lt;a href=&quot;https://twitter.com/jnadeau/status/1362527144929189890&quot;&gt;on Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name>Pádraig Ó Cinnéide</name></author><category term="appkit" /><summary type="html">In a custom NSView, when building up a list of subviews, it is typical to call the addSubview function once for each subview. A neater way to do this is to just set the subviews array directly. The NSView internals are clever enough to do any of the extra book-keeping required, just as if you had called addSubview each time.</summary></entry><entry><title type="html">Autolayoutable</title><link href="https://padraig.org/appkit/2021/09/02/autolayoutable.html" rel="alternate" type="text/html" title="Autolayoutable" /><published>2021-09-02T19:09:25+00:00</published><updated>2021-09-02T19:09:25+00:00</updated><id>https://padraig.org/appkit/2021/09/02/autolayoutable</id><content type="html" xml:base="https://padraig.org/appkit/2021/09/02/autolayoutable.html">&lt;p&gt;In AppKit (or UIKit) projects where I’ve decided to implement user interfaces strictly in  code, rather than through storyboards or xibs, it gets tiresome to repeatedly type the following code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;translatesAutoresizingMaskIntoConstraints&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here’s a little snippet I’ve been using to cut down on this somewhat:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;autolayoutable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;translatesAutoresizingMaskIntoConstraints&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Example usage when creating an NSTableView&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tableView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSTableView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;autolayoutable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works for almost all views I create but occasionally I want to use some of the convenience initializers for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSButton&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSTextView&lt;/code&gt;  like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;labelWithString&lt;/code&gt;. In those cases, I don’t use the method above, I just disable autosizing manually.&lt;/p&gt;</content><author><name>Pádraig Ó Cinnéide</name></author><category term="appkit" /><summary type="html">In AppKit (or UIKit) projects where I’ve decided to implement user interfaces strictly in code, rather than through storyboards or xibs, it gets tiresome to repeatedly type the following code:</summary></entry><entry><title type="html">View Controllers without XIBs</title><link href="https://padraig.org/appkit/2020/10/25/layout-in-code.html" rel="alternate" type="text/html" title="View Controllers without XIBs" /><published>2020-10-25T22:30:25+00:00</published><updated>2020-10-25T22:30:25+00:00</updated><id>https://padraig.org/appkit/2020/10/25/layout-in-code</id><content type="html" xml:base="https://padraig.org/appkit/2020/10/25/layout-in-code.html">&lt;p&gt;Cutting down on &lt;a href=&quot;https://en.wikipedia.org/wiki/Boilerplate_code&quot;&gt;boilerplate&lt;/a&gt; is a good way to make a code base more maintainable and more pleasant to work with.&lt;/p&gt;

&lt;p&gt;The NSViewController class supports a variety of layout options. It can be used with XIBs, Storyboards or with views that define their layout in code directly. Additionally there are multiple layout systems: developers might use Auto Layout, Auto Resizing, or both. One tactic for reducing boilerplate is to choose which of these technologies you wish to use, and then simplify NSViewController’s interface down to just the parts you need.&lt;/p&gt;

&lt;p&gt;In this post, I’ll define a tiny NSViewController class that we can use as a superclass throughout the rest of a project. My choices are: We’ll write all layout in code, no XIBs or Storyboards at all. Additionally, we will use Auto Layout everywhere instead of Auto Resizing.&lt;/p&gt;

&lt;p&gt;–&lt;/p&gt;

&lt;p&gt;With these simplifying assumptions we can now mitigate the following annoyances that we’ll face for every NSViewController subclass we create:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loadView()&lt;/code&gt; override which will probably be a boilerplate-y one liner every time.&lt;/li&gt;
  &lt;li&gt;Access the &lt;em&gt;typed&lt;/em&gt; view subclass from the view controller&lt;/li&gt;
  &lt;li&gt;Gaze upon this designated initializer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?)&lt;/code&gt; in all its clunky irrelevance to our layout choices.&lt;/li&gt;
  &lt;li&gt;Add mandatory boilerplate to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init?(coder: NSCoder)&lt;/code&gt; which exists solely for decoding XIBs… which we are not using at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;–&lt;/p&gt;

&lt;p&gt;Since the type of NSViewController’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view&lt;/code&gt; property is NSView, &lt;em&gt;not&lt;/em&gt; the type of our own view subclass, accessing custom methods and properties on our specific view class will be our first problem.&lt;/p&gt;

&lt;p&gt;Swift Generics give us a nice way to solve this. We can define the view’s actual type in a new view controller superclass that we’ll use throughout the project.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;XiblessVC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loadView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;contentView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as!&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This provides strongly typed view access, and it saves us having to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loadView()&lt;/code&gt; everywhere. We can also solve the “ugly designated initializer” point with a clean custom initializer to call the designated initializer&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;  &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nibName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And finally, by annotating the NSCoder initializer using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@available&lt;/code&gt;, we won’t need to implement this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;required&lt;/code&gt; method in our subclasses.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;  &lt;span class=&quot;kd&quot;&gt;@available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unavailable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;init(coder:) has not been implemented&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here is a quick example of what a view controller might look like if we used NSViewController directly.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ClockViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clockView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ClockView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  
  &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nibName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;init(coder:) has not been implemented&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loadView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ClockView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clockView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clockView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XiblessVC&lt;/code&gt; as our view controller superclass, we can slim all of that down to something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ClockViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;XiblessVC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ClockView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;contentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, the use of this superclass gives us a considerable reduction in boilerplate on every view controller in our project, and encourages consistency with our layout decisions across the project.&lt;/p&gt;

&lt;p&gt;There are some drawbacks:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;It’s ugly to have a custom view controller superclass used everywhere, rather than using AppKit objects directly.&lt;/li&gt;
  &lt;li&gt;New developers on the codebase might take a bit longer to pick up what’s going on.&lt;/li&gt;
  &lt;li&gt;Developers may be tempted add additional features to the superclass, exacerbating the above issues.&lt;/li&gt;
  &lt;li&gt;Using Generics like this requires the views to have the same access control level as the view controller though, so developers lose the ability to keep custom views private in the same file as the view controller.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think the trade-off here is worth making though, as long as we keep the superclass simple and focused on our goals: reducing boilerplate and enforcing layout scheme consistency.&lt;/p&gt;</content><author><name>Pádraig Ó Cinnéide</name></author><category term="appkit" /><summary type="html">Cutting down on boilerplate is a good way to make a code base more maintainable and more pleasant to work with.</summary></entry></feed>