{"id":46224,"date":"2024-12-19T16:07:04","date_gmt":"2024-12-19T21:07:04","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=46224"},"modified":"2025-06-20T16:47:57","modified_gmt":"2025-06-20T20:47:57","slug":"swiftuwhy","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2024\/12\/19\/swiftuwhy\/","title":{"rendered":"SwiftUWhy"},"content":{"rendered":"<p><a href=\"https:\/\/mastodon.social\/@siracusa\/113671711758284446\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113671711758284446\"><p>Welcome to my new series on things I don&rsquo;t understand about Apple&rsquo;s premier user interface framework.<\/p><p>[&#8230;]<\/p><p>To be clear, these are things I don&rsquo;t understand, not necessarily things that are &ldquo;wrong.&rdquo; They sure <em>look<\/em> wrong (or at least &ldquo;suboptimal&rdquo;) to me! But maybe there are good reasons, and I just don&rsquo;t know them yet. SwiftUI experts and historians, please tell me!<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/12\/10\/apples-use-of-swift-and-swiftui-in-ios-18\/\">Apple&rsquo;s Use of Swift and SwiftUI in iOS 18<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/07\/24\/swiftui-at-wwdc24\/\">SwiftUI at WWDC24<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/03\/11\/mac-dialog-in-auto-layout-vs-swiftui\/\">Mac Dialog in Auto Layout vs. SwiftUI<\/a><\/li>\n<\/ul>\n\n<p id=\"swiftuwhy-update-2025-01-10\">Update (2025-01-10): <a href=\"https:\/\/mastodon.social\/@siracusa\/113722603584577816\">John Siracusa<\/a> (<a href=\"https:\/\/github.com\/siracusa\/SwiftUIPickerLayout\">GitHub<\/a>):<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113722603584577816\">\n<p>Why is there (apparently?) no <code>Picker<\/code> style on macOS that can be configured with a fixed width, like <code>NSPopUpButton<\/code> in AppKit?<\/p>\n<p>For example, consider a text field for numeric input followed by a picker for units, both aligned to the right side of a System Settings-style Form. Each time you pick a different unit, the <code>Picker<\/code> changes width and moves the text field.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@siracusa\/113705834006128660\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113705834006128660\">\n<p>Q: Why is Xcode no longer able to render a preview of my SwiftUI view?<\/p>\n<p>A: <em>Sometimes<\/em>, the answer is that you&rsquo;ve got a call to a log method on a <code>Logger<\/code> object in a code path that&rsquo;s executed when rendering a preview but rarely or not at all otherwise, and this call passes a string without any values interpolated into it (e.g., <code>logger.log(\"Hello\")<\/code>). This causes an error, and this error is only visible in the big spew of output available through the stethoscope icon in the preview pane.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@siracusa\/113748804370144556\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113748804370144556\">\n<p><code>ScrollView<\/code> on macOS includes default support for swipe gestures and mouse scroll wheels, but not page up\/down, home\/end, or arrow keys?<\/p>\n<\/blockquote>\n\n<p>See also: the <a href=\"https:\/\/mastodon.social\/tags\/SwiftUWhy\">Mastodon tag<\/a>.<\/p>\n\n<p id=\"swiftuwhy-update-2025-01-17\">Update (2025-01-17): <a href=\"https:\/\/mastodon.social\/@siracusa\/113839095195631019\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113839095195631019\">\n<p>Why can&rsquo;t I find a simple way to do this?<\/p>\n<pre>.textSelection(allowSelection ? .enabled : .disabled)<\/pre>\n<\/blockquote>\n\n<p id=\"swiftuwhy-update-2025-02-11\">Update (2025-02-11): <a href=\"https:\/\/mastodon.social\/@siracusa\/113980923167276031\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@siracusa\/113980923167276031\"><p>Xcode should track the lifetime number of hours spent trying to find the error in your SwiftUI view code that is causing the &ldquo;compiler is unable to type-check this expression in reasonable time&rdquo; message to appear after the obligatory a 60-second wait.<\/p><p>To be clear, this message is almost never (directly?) related to type checking when it happens in a SwiftUI View. Instead, it&rsquo;s caused by things like a typo in the parameter name of a method call.<\/p><p>&ldquo;A typo in a parameter name? Why, that should be pinpointed instantly by the complier!&rdquo; Sure, in normal code. But in a SwiftUI view, you get to try to find it yourself, with no help! Each try costs you 60 seconds.<\/p><\/blockquote>\n\n<p id=\"swiftuwhy-update-2025-06-20\">Update (<a href=\"#swiftuwhy-update-2025-06-20\">2025-06-20<\/a>): <a href=\"https:\/\/github.com\/siracusa\/FixedSizeForm\/\">John Siracusa<\/a>:<\/p>\n<blockquote cite=\"https:\/\/github.com\/siracusa\/FixedSizeForm\/\"><p>This project demonstrates a SwiftUI layout bug. The code includes a <code>TabView<\/code> containing a <code>Form<\/code> that has <code>.fixedSize(horizontal: false, vertical: true)<\/code> set on it. This should cause the containing <code>Tab<\/code>, <code>TabView<\/code>, and (ultimately) window to allocate enough vertical space so that there is no scrolling in this view.<\/p><p>This works&#8230;until a trivial <code>NSViewRepresentable<\/code> view (<code>InnocentNSView<\/code>) is added to the <code>ZStack<\/code> that contains the <code>TabView<\/code>. The mere presence of this entirely empty <code>NSViewRepresentable<\/code> view causes the height calculation to be off by a pixel or two, which causes the <code>Form<\/code> to have a tiny bit of scrolling.<\/p><\/blockquote>","protected":false},"excerpt":{"rendered":"<p>John Siracusa: Welcome to my new series on things I don&rsquo;t understand about Apple&rsquo;s premier user interface framework.[&#8230;]To be clear, these are things I don&rsquo;t understand, not necessarily things that are &ldquo;wrong.&rdquo; They sure look wrong (or at least &ldquo;suboptimal&rdquo;) to me! But maybe there are good reasons, and I just don&rsquo;t know them yet. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2024-12-19T21:07:07Z","apple_news_api_id":"f652c6a0-9326-4c45-aa1f-48bfc4570d0e","apple_news_api_modified_at":"2025-06-20T20:47:59Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAw==","apple_news_api_share_url":"https:\/\/apple.news\/A9lLGoJMmTEWqH0i_xFcNDg","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[30,2598,71,1812],"class_list":["post-46224","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-mac","tag-macos-15-sequoia","tag-programming","tag-swiftui"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=46224"}],"version-history":[{"count":5,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46224\/revisions"}],"predecessor-version":[{"id":48175,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46224\/revisions\/48175"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=46224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=46224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=46224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}