<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Fatbobman's Swift Weekly]]></title><description><![CDATA[Share excellent articles about Swift, SwiftUI, Core Data, SwiftData every week]]></description><link>https://weekly.fatbobman.com</link><image><url>https://substackcdn.com/image/fetch/$s_!n1kc!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bf31f26-d840-47e6-8ec9-0f656c1a96ca_1280x1280.png</url><title>Fatbobman&apos;s Swift Weekly</title><link>https://weekly.fatbobman.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 24 Sep 2026 08:40:37 GMT</lastBuildDate><atom:link href="https://weekly.fatbobman.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[fatbobman]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[fatbobman@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[fatbobman@substack.com]]></itunes:email><itunes:name><![CDATA[Fatbobman(东坡肘子)]]></itunes:name></itunes:owner><itunes:author><![CDATA[Fatbobman(东坡肘子)]]></itunes:author><googleplay:owner><![CDATA[fatbobman@substack.com]]></googleplay:owner><googleplay:email><![CDATA[fatbobman@substack.com]]></googleplay:email><googleplay:author><![CDATA[Fatbobman(东坡肘子)]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Fatbobman's Swift Weekly #154]]></title><description><![CDATA[A &#8220;Native&#8221; Debate Over SwiftUI Animation]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 21 Sep 2026 12:01:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4WJy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4WJy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4WJy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54560,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/216668352?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4WJy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@haroldjonker?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Harold Jonker</a><span> on </span><a href="https://unsplash.com/photos/yellow-and-black-pendant-lamp-cTwocNh2slg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>A &#8220;Native&#8221; Debate Over SwiftUI Animation</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-154/">Read on web &#8594;</a></p><p><span>Last week, a </span><a href="https://x.com/kzzzf/status/2099985361271144686"><span>post</span></a><span> by React Native core developer Krzysztof Magiera sparked a lively discussion across the Apple developer community. In the post, he demonstrated an example where, with the main thread blocked, a back-and-forth animation in UIKit continued to run normally while the equivalent SwiftUI animation came to a halt. He attributed this to SwiftUI not using Core Animation&#8217;s render-server animation model and instead advancing animations within the app process, raising the question of whether SwiftUI is truly &#8220;native.&#8221; He later added that, in React Native, developers can still use Core Animation to create animations that continue running even when the main thread is blocked.</span></p><p><span>SwiftUI co-creator and early core developer Kyle Macomber responded with a different </span><a href="https://x.com/kylemacomber/status/2100029347419877794"><span>perspective</span></a><span>. He explained that, from the beginning, SwiftUI deliberately moved away from server-side animation&#8212;where Core Animation advances animations on the render server&#8212;and instead chose to compute and advance animation values in the client/app process in exchange for better interruptibility and interactivity. This was not a technical regression, but a deliberate design trade-off. (SwiftUI did not abandon Core Animation itself; Core Animation still participates in the subsequent rendering process. What changed is who advances the animation.)</span></p><p><span>Ease of animation has always been one of SwiftUI&#8217;s signature strengths, and the continued evolution of its spring animations in recent years has further improved the naturalness of transitions and the expressiveness of interactive motion. For a reactive framework, I think advancing animations on the client side is entirely understandable. The trade-off, of course, is equally clear: as Krzysztof&#8217;s example demonstrates, when animation advancement depends on the app process, it becomes more susceptible to a busy main thread and also consumes more computational resources on the client side.</span></p><p><span>That said, client-side animation does not mean that all animation sampling calculations must happen on the main thread. As SwiftUI has evolved, some computationally intensive work involving animations and </span><code>Shape</code><span> can now be moved to background threads, reducing pressure on the main thread. Still, because animation advancement remains within the app process, and asynchronous computation is subject to constraints such as state updates and the rendering pipeline, animations can still stall when the main thread is completely blocked. Despite this &#8220;drawback,&#8221; starting with iOS 18, UIKit and AppKit also began adopting this client-side animation model: their new animation APIs can directly use SwiftUI&#8217;s </span><code>Animation</code><span> and are driven by the same underlying animation infrastructure rather than generating traditional </span><code>CAAnimation</code><span> objects.</span></p><p><span>This discussion presented an interesting situation: on the surface, the debate was about whether SwiftUI is truly &#8220;native,&#8221; but underneath it revealed a difference in framework design philosophies.</span></p><p><span>As Apple&#8217;s UI framework for the future, SwiftUI chose to depart from the established path, moving away from dependence on Core Animation&#8217;s render-server animation model in exchange for more flexible and expressive animation capabilities. In fact, John Harper, the creator of Core Animation, was himself one of SwiftUI&#8217;s co-creators. So this choice clearly wasn&#8217;t made out of unfamiliarity with Core Animation, but rather as an architectural decision made with an understanding of both its strengths and limitations. It also brought a less obvious advantage: some of SwiftUI&#8217;s core capabilities became further decoupled from the specific implementation details of Apple platforms. Although Apple has not open-sourced SwiftUI, architecturally, some of its core ideas are not inherently limited to Apple platforms.</span></p><p><span>From the React Native perspective, Krzysztof&#8217;s argument also has its rationale. As a cross-platform framework, one of React Native&#8217;s important goals is to make the best possible use of the capabilities each platform already provides, allowing apps to behave and perform more like &#8220;locals&#8221; on each platform.</span></p><p><span>What began as a discussion about &#8220;what counts as native&#8221; ultimately led core developers from both sides to explain how they think about UI animation architecture. As someone happily watching from the sidelines, I learned quite a bit from it as well.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-153/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-pbxproj-to-xcproj/?utm_source=fatbobman%20weekly%20issue%20154&amp;utm_medium=web"><span>From pbxproj to xcproj: Xcode Project Configuration Gets a JSON Format</span></a></strong></h3><p><span>I&#8217;ve been waiting for Xcode 27.1, hoping to test how my apps adapt in the iPhone Duo simulator. Amusingly, 27.1 never arrived &#8212; Apple shipped 27.2 beta first instead. The iPhone Duo simulator is still missing, but the new </span><code>project.xcproj</code><span> caught my eye. What it replaces is </span><code>project.pbxproj</code><span>, the build graph inside the </span><code>.xcodeproj</code><span> bundle, not the bundle itself. What&#8217;s good about it, what does it fix, and what stays the same? This article takes a look.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-01"><span>How we built Devin&#8217;s Mac</span></a></strong></h3><p><span>When an AI agent runs locally, permissions have long since been granted, the toolchain is ready, and a human can dismiss any dialog that appears. Move to the cloud and every one of those assumptions has to be rebuilt. The payoff isn&#8217;t doing something the local machine can&#8217;t &#8212; it&#8217;s turning the development environment itself into a resource you can assign to an agent: tasks run asynchronously, stay isolated from one another, pause and preserve their state when idle, resume on demand, and scale more easily to several agents working in parallel. </span><a href="https://x.com/jkelleyrtp"><span>Jon Kelley</span></a><span> walks through building Devin&#8217;s macOS cloud environment, covering virtual machines on Virtualization.framework, disk snapshots, network isolation, pre-configured environments and permissions, live streaming of the desktop and Simulator, and computer use driven by the accessibility tree. That last point is especially instructive for Apple developers: good accessibility support also gives agents a structured interface for automated verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-02"><span>iOS 27: CrashReportExtension Framework</span></a></strong></h3><p><span>Traditional crash handling has an awkward problem: by the time the signal handler runs, the process it lives in may already be unreliable &#8212; memory may be corrupted, locks may still be held, and many everyday APIs can&#8217;t be called safely. The new CrashReportExtension in iOS 27 changes that execution model. After the app crashes, the system launches a separate extension and hands it a read-only </span><code>CrashedProcess</code><span> for inspecting the crashed process.</span></p><p><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> demonstrates how to create and use the extension, along with several practical judgments. The API complements Apple&#8217;s </span><code>.ips</code><span> reports rather than replacing them, and suits teams that need their own backend, correlation with business context, or on-device pre-analysis. The extension itself should stay small, doing nothing more than generating and persisting a report; uploads and retries belong in the host app, with the two sharing storage through an App Group. For most indie developers, system crash reports plus MetricKit remain sufficient.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-03"><span>How SwiftUI animation works</span></a></strong></h3><p><span>For animation, developers only change state and specify an animation function, leaving the rest to SwiftUI. But how do those declarations become a continuous sequence of frames on screen? Starting from Transaction and AttributeGraph, and drawing on his work on OpenSwiftUI, </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> analyzes step by step how SwiftUI creates an animation context, computes intermediate states, and keeps updating views and layout as the animation runs.</span></p><p><span>Unlike the conventional approach of leaving interpolation mostly to the render server, many SwiftUI animations advance within the app process. Because interpolation happens inside the view graph, any value conforming to Animatable can be sampled, which lets layout, Shape, and much more participate in animation, while the render server mainly handles layer properties. The analysis of the </span><code>CABasicAnimation</code><span> on the asynchronous commit path is particularly worth reading: it carries only the current frame&#8217;s sampled value and is replaced on the next frame &#8212; the presence of a CA animation object on screen does not mean the animation&#8217;s clock has been handed to Core Animation. This adds useful detail to the debate over whether SwiftUI animation is &#8220;native,&#8221; discussed in this issue&#8217;s editorial.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-04"><span>SwiftUI: Some New APIs/ContainerViews Useful For Duo!</span></a></strong></h3><p><span>The many poses of iPhone Duo present new challenges for toolbars. To make full use of the wider screen while preserving vertical space for content, the system moves controls normally placed at the top and bottom to the side of the screen in certain poses. But text buttons, custom views, and other traditional toolbar content don&#8217;t always suit a vertical arrangement, and the toolbar and tab bar may have to compete for limited side space. iOS 27.1 addresses this with APIs including </span><code>ToolbarItemAxisBehavior</code><span>, </span><code>ToolbarVerticalBehavior</code><span>, </span><code>ToolbarVerticalCompressionBehavior</code><span>, and </span><code>toolbarVerticalEdge</code><span>, giving developers finer control over a toolbar&#8217;s orientation, placement, and compression strategy when space runs short. </span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> demonstrates how these new APIs behave, with code and videos.</span></p><p><span>What these APIs have in common is that they let developers declare a preference rather than dictate a result. Faced with the range of poses Duo introduces, describing the relationships between pieces of content and your layout preferences &#8212; and letting SwiftUI decide the final presentation based on the actual environment &#8212; beats writing layouts for specific device states.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-05"><span>Sheets and fold avoidance on iPhone Duo</span></a></strong></h3><p><span>When iPhone Duo is partially folded, the crease down the middle forms a region poorly suited to interaction, and buttons or other controls that land there become awkward to operate. Using sheets as his example, </span><a href="https://x.com/sarunw"><span>Sarun Wongpatcharapakorn</span></a><span> shows how a single interface adjusts its size, position, and toolbar across Duo&#8217;s closed, open, landscape, portrait, and partially folded poses. System components including sheets, alerts, and menus already avoid the fold without developer intervention. For developers, that means reaching for system components first also means inheriting this adaptive behavior across device poses for free.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-06"><span>Vapor 5 Beta Released</span></a></strong></h3><p><span>Ten years after Vapor was born and six and a half years after Vapor 4 shipped, the community finally has the first beta of Vapor 5. It amounts to a near-complete rewrite &#8212; two years of work and roughly 49,000 lines changed. The central change is saying goodbye to </span><code>EventLoop</code><span> and </span><code>EventLoopFuture</code><span> and moving fully to Swift Concurrency built on structured concurrency, with NIO now largely hidden from the public APIs.</span></p><p><span>Vapor 5 also integrates more deeply with Swift HTTP Types, Swift Configuration, and Swift Service Lifecycle, and adds the experimental </span><code>VaporMacros</code><span> for compile-time type checking of routes and authentication. It requires Swift 6.4 and remains in beta. For a fuller account of what changed, see </span><a href="https://hachyderm.io/@0xTim"><span>Tim Condon</span></a><span>&#8216;s </span><a href="https://blog.vapor.codes/posts/whats-new-in-vapor-5-beta/"><span>What&#8217;s New in Vapor 5 Beta</span></a><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-07"><span>Hinge: Set the Duo Simulator&#8217;s Fold Angle from the Command Line</span></a></strong></h3><p><span>Xcode 27.1&#8217;s Device Hub can adjust the fold angle of the iPhone Duo Simulator (hold Option to reveal it), but neither </span><code>simctl</code><span> nor </span><code>devicectl</code><span> offers a corresponding command. Hinge, from </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span>, fills the gap: it sets fold angles from 0 to 180&#176; on the command line, and supports opening, closing, half-folding, and sweeping continuously between angles. Hinge also ships an Agent Skill, letting a coding agent change Duo&#8217;s fold state itself while verifying an app.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-08"><span>Enriched Markdown: Cross-Platform Markdown Rendering and Editing Without a WebView</span></a></strong></h3><p><span>The usual way to handle Markdown on mobile is to wrap it in a WebView. Enriched Markdown, from Software Mansion, takes a more thorough route: it renders Markdown and supports rich-text editing through each platform&#8217;s native text capabilities, and can emit clean Markdown again once the content has been edited.</span></p><p><span>It offers a standalone SwiftUI SDK, rendering Markdown with TextKit 2 and md4c, and also covers React Native, Android, and the web. Rather than settling for &#8220;Markdown that displays,&#8221; Enriched Markdown emphasizes a native feel: text selects normally, links, images, and code blocks hook into system menus, and the library supports VoiceOver, TalkBack, Dynamic Type, and right-to-left writing.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#19968;&#22330;&#20851;&#20110; SwiftUI &#21160;&#30011;&#30340;&#8220;&#21407;&#29983;&#8221;&#20043;&#20105;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-154/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#21608;&#65292;React Native &#26680;&#24515;&#24320;&#21457;&#32773; Krzysztof Magiera &#30340;&#19968;&#26465; &#8288;</span><a href="https://x.com/kzzzf/status/2099985361271144686"><span>&#25512;&#25991;</span></a><span> &#22312;&#33529;&#26524;&#24320;&#21457;&#29983;&#24577;&#20013;&#24341;&#21457;&#28909;&#28872;&#35752;&#35770;&#12290;&#25512;&#25991;&#20013;&#20182;&#23637;&#31034;&#20102;&#19968;&#20010;&#31034;&#20363;&#65306;&#22312;&#20027;&#32447;&#31243;&#38459;&#22622;&#30340;&#24773;&#20917;&#19979;&#65292;UIKit &#30340;&#19968;&#20010;&#24448;&#36820;&#21160;&#30011;&#20173;&#33021;&#27491;&#24120;&#25191;&#34892;&#65292;&#32780; SwiftUI &#30340;&#21160;&#30011;&#21017;&#20572;&#28382;&#20102;&#12290;&#20182;&#35748;&#20026;&#21407;&#22240;&#22312;&#20110; SwiftUI &#27809;&#26377;&#20351;&#29992; Core Animation &#30340; render-server animation&#65292;&#32780;&#26159;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#25512;&#36827;&#21160;&#30011;&#65292;&#22240;&#27492;&#23545; SwiftUI &#26159;&#21542;&#36275;&#22815;&#8220;&#21407;&#29983;&#8221;&#25552;&#20986;&#20102;&#36136;&#30097;&#65307;&#38543;&#21518;&#21448;&#34920;&#31034;&#65292;&#22312; React Native &#20013;&#65292;&#24320;&#21457;&#32773;&#20173;&#21487;&#36890;&#36807; Core Animation &#21019;&#24314;&#19981;&#21463;&#20027;&#32447;&#31243;&#38459;&#22622;&#24433;&#21709;&#30340;&#21160;&#30011;&#12290;</span></p><p><span>SwiftUI &#20849;&#21516;&#21019;&#36896;&#32773;&#12289;&#26089;&#26399;&#26680;&#24515;&#24320;&#21457;&#32773; Kyle Macomber &#23545;&#27492;&#22238;&#24212;&#20102;&#19981;&#21516;&#30340; &#8288;</span><a href="https://x.com/kylemacomber/status/2100029347419877794"><span>&#35266;&#28857;</span></a><span>&#12290;&#20182;&#35299;&#37322;&#35828;&#65292;SwiftUI &#22312;&#35774;&#35745;&#20043;&#21021;&#23601;&#26377;&#24847;&#25918;&#24323;&#20102; Server-side Animation&#65288;&#30001; Core Animation &#22312; render server &#20013;&#25512;&#36827;&#21160;&#30011;&#65289;&#65292;&#32780;&#36873;&#25321;&#35753;&#21160;&#30011;&#20540;&#22312; client / app process &#20013;&#35745;&#31639;&#21644;&#25512;&#36827;&#65292;&#20197;&#25442;&#21462;&#26356;&#22909;&#30340;&#21487;&#20013;&#26029;&#24615;&#19982;&#20132;&#20114;&#24615;&#12290;&#36825;&#24182;&#38750;&#25216;&#26415;&#19978;&#30340;&#36864;&#27493;&#65292;&#32780;&#26159;&#19968;&#39033;&#35774;&#35745;&#21462;&#33293;&#65288;SwiftUI &#24182;&#27809;&#26377;&#25918;&#24323; Core Animation&#65292;&#23427;&#20173;&#28982;&#21442;&#19982;&#21518;&#32493;&#30340;&#28210;&#26579;&#36807;&#31243;&#65292;&#25913;&#21464;&#30340;&#21482;&#26159;&#21160;&#30011;&#30001;&#35841;&#26469;&#25512;&#36827;&#65289;&#12290;</span></p><p><span>&#21160;&#30011;&#30340;&#26131;&#29992;&#24615;&#19968;&#30452;&#26159; SwiftUI &#30340;&#26631;&#24535;&#24615;&#29305;&#33394;&#20043;&#19968;&#65292;&#36817;&#24180;&#26469;&#19981;&#26029;&#23436;&#21892;&#30340;&#24377;&#31783;&#21160;&#30011;&#65292;&#21448;&#36827;&#19968;&#27493;&#25552;&#21319;&#20102;&#21160;&#30011;&#34900;&#25509;&#30340;&#33258;&#28982;&#31243;&#24230;&#21644;&#20132;&#20114;&#34920;&#29616;&#21147;&#12290;&#20316;&#20026;&#19968;&#20010;&#21709;&#24212;&#24335;&#26694;&#26550;&#65292;&#25226;&#21160;&#30011;&#25512;&#36827;&#25918;&#22312; client &#31471;&#65292;&#25105;&#35748;&#20026;&#23436;&#20840;&#21487;&#20197;&#29702;&#35299;&#12290;&#24403;&#28982;&#65292;&#20195;&#20215;&#20063;&#24456;&#26126;&#30830;&#65306;&#27491;&#22914; Krzysztof &#30340;&#31034;&#20363;&#25152;&#31034;&#65292;&#24403;&#21160;&#30011;&#25512;&#36827;&#20381;&#36182;&#24212;&#29992;&#36827;&#31243;&#26102;&#65292;&#23427;&#26356;&#23481;&#26131;&#21463;&#21040;&#20027;&#32447;&#31243;&#32321;&#24537;&#30340;&#24433;&#21709;&#65292;&#20063;&#20250;&#21344;&#29992;&#26356;&#22810; client &#31471;&#30340;&#35745;&#31639;&#36164;&#28304;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;client-side animation &#24182;&#19981;&#24847;&#21619;&#30528;&#25152;&#26377;&#25554;&#20540;&#35745;&#31639;&#37117;&#24517;&#39035;&#21457;&#29983;&#22312;&#20027;&#32447;&#31243;&#12290;&#38543;&#30528; SwiftUI &#19981;&#26029;&#28436;&#36827;&#65292;&#37096;&#20998;&#21160;&#30011;&#20197;&#21450; Shape &#31561;&#35745;&#31639;&#23494;&#38598;&#22411;&#24037;&#20316;&#24050;&#32463;&#21487;&#20197;&#31227;&#21040;&#21518;&#21488;&#32447;&#31243;&#65292;&#20197;&#20943;&#36731;&#20027;&#32447;&#31243;&#30340;&#21387;&#21147;&#12290;&#19981;&#36807;&#65292;&#30001;&#20110;&#21160;&#30011;&#30340;&#25512;&#36827;&#20173;&#28982;&#23646;&#20110;&#24212;&#29992;&#36827;&#31243;&#65292;&#24322;&#27493;&#35745;&#31639;&#20063;&#21463;&#21040;&#29366;&#24577;&#26356;&#26032;&#21644;&#28210;&#26579;&#27969;&#31243;&#31561;&#26465;&#20214;&#30340;&#38480;&#21046;&#65292;&#22240;&#27492;&#24403;&#20027;&#32447;&#31243;&#34987;&#23436;&#20840;&#38459;&#22622;&#26102;&#65292;&#21160;&#30011;&#20381;&#28982;&#21487;&#33021;&#20572;&#28382;&#12290;&#23613;&#31649;&#23384;&#22312;&#36825;&#31181;&#8220;&#24330;&#31471;&#8221;&#65292;&#20294;&#20174; iOS 18 &#24320;&#22987;&#65292;UIKit &#21644; AppKit &#20063;&#24320;&#22987;&#37319;&#32435;&#36825;&#22871; client-side animation &#27169;&#22411;&#65306;&#26032;&#30340;&#21160;&#30011; API &#21487;&#20197;&#30452;&#25509;&#20351;&#29992; SwiftUI &#30340; Animation&#65292;&#24182;&#30001;&#21516;&#19968;&#22871;&#21160;&#30011;&#22522;&#30784;&#35774;&#26045;&#39537;&#21160;&#65292;&#32780;&#19981;&#20877;&#29983;&#25104;&#20256;&#32479;&#30340; CAAnimation&#12290;</span></p><p><span>&#26412;&#27425;&#35752;&#35770;&#21576;&#29616;&#20986;&#19968;&#20010;&#26377;&#36259;&#30340;&#22330;&#26223;&#65306;&#34920;&#38754;&#19978;&#22312;&#20105;&#35770; SwiftUI &#26159;&#21542;&#8220;&#21407;&#29983;&#8221;&#65292;&#23454;&#38469;&#23637;&#29616;&#30340;&#21364;&#26159;&#20004;&#31181;&#26694;&#26550;&#35774;&#35745;&#29702;&#24565;&#30340;&#24046;&#24322;&#12290;</span></p><p><span>&#20316;&#20026;&#33529;&#26524;&#38754;&#21521;&#26410;&#26469;&#30340; UI &#26694;&#26550;&#65292;SwiftUI &#22312;&#35774;&#35745;&#26102;&#36873;&#25321;&#36208;&#20986;&#26082;&#26377;&#36335;&#24452;&#65292;&#25918;&#24323;&#23545; Core Animation render-server animation &#27169;&#22411;&#30340;&#20381;&#36182;&#65292;&#20197;&#25442;&#21462;&#26356;&#28789;&#27963;&#12289;&#26356;&#24378;&#22823;&#30340;&#21160;&#30011;&#34920;&#36798;&#33021;&#21147;&#12290;&#20107;&#23454;&#19978;&#65292;Core Animation &#30340;&#21019;&#36896;&#32773; John Harper &#26412;&#20154;&#20063;&#26159; SwiftUI &#30340;&#20849;&#21516;&#21019;&#36896;&#32773;&#20043;&#19968;&#65292;&#36825;&#39033;&#36873;&#25321;&#26174;&#28982;&#19981;&#26159;&#22240;&#20026;&#19981;&#20102;&#35299; Core Animation&#65292;&#32780;&#26159;&#22312;&#29702;&#35299;&#20854;&#20248;&#21183;&#19982;&#23616;&#38480;&#20043;&#21518;&#20570;&#20986;&#30340;&#26550;&#26500;&#20915;&#23450;&#12290;&#36825;&#36824;&#24102;&#26469;&#20102;&#19968;&#20010;&#38544;&#24418;&#20248;&#21183;&#65306;SwiftUI &#30340;&#37096;&#20998;&#26680;&#24515;&#33021;&#21147;&#19982;&#33529;&#26524;&#24179;&#21488;&#30340;&#20855;&#20307;&#23454;&#29616;&#24471;&#20197;&#36827;&#19968;&#27493;&#35299;&#32806;&#12290;&#23613;&#31649;&#33529;&#26524;&#24182;&#26410;&#23558; SwiftUI &#24320;&#28304;&#65292;&#20294;&#20174;&#26550;&#26500;&#19978;&#30475;&#65292;&#23427;&#30340;&#19968;&#20123;&#26680;&#24515;&#24605;&#24819;&#24182;&#19981;&#22825;&#28982;&#23616;&#38480;&#20110;&#33529;&#26524;&#24179;&#21488;&#12290;</span></p><p><span>&#32780;&#20174; React Native &#30340;&#35282;&#24230;&#30475;&#65292;Krzysztof &#30340;&#34920;&#36848;&#20063;&#26377;&#20854;&#21512;&#29702;&#24615;&#12290;&#20316;&#20026;&#19968;&#20010;&#36328;&#24179;&#21488;&#26694;&#26550;&#65292;React Native &#30340;&#37325;&#35201;&#30446;&#26631;&#20043;&#19968;&#65292;&#23601;&#26159;&#22312;&#19981;&#21516;&#24179;&#21488;&#19978;&#23613;&#21487;&#33021;&#21033;&#29992;&#24179;&#21488;&#24050;&#32463;&#25552;&#20379;&#30340;&#33021;&#21147;&#65292;&#35753;&#24212;&#29992;&#22312;&#34892;&#20026;&#21644;&#24615;&#33021;&#19978;&#26356;&#20687;&#8220;&#26412;&#22320;&#20154;&#8221;&#12290;</span></p><p><span>&#19968;&#20010;&#26368;&#21021;&#22260;&#32469;&#8220;&#20160;&#20040;&#25165;&#31639;&#21407;&#29983;&#8221;&#30340;&#35752;&#35770;&#65292;&#26368;&#32456;&#24341;&#20986;&#20102;&#20004;&#36793;&#26680;&#24515;&#24320;&#21457;&#32773;&#23545; UI &#21160;&#30011;&#26550;&#26500;&#30340;&#29702;&#35299;&#19982;&#38416;&#36848;&#12290;&#20316;&#20026;&#19968;&#20010;&#21507;&#29916;&#32676;&#20247;&#65292;&#25105;&#20063;&#20174;&#20013;&#25910;&#33719;&#19981;&#23569;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-153/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-pbxproj-to-xcproj/?utm_source=fatbobman%20weekly%20issue%20154&amp;utm_medium=web"><span>&#20174; pbxproj &#21040; xcproj&#65306;Xcode &#24037;&#31243;&#37197;&#32622;&#36814;&#26469; JSON &#26684;&#24335;</span></a></strong></h3><p><span>&#26368;&#36817;&#19968;&#30452;&#22312;&#31561;&#24453; Xcode 27.1 &#30340;&#21040;&#26469;&#65292;&#20197;&#20415;&#22312; iPhone Duo &#30340;&#27169;&#25311;&#22120;&#20013;&#27979;&#35797;&#19968;&#19979;&#24212;&#29992;&#30340;&#36866;&#37197;&#24773;&#20917;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;27.1 &#27809;&#31561;&#21040;&#65292;&#33529;&#26524;&#29575;&#20808;&#21457;&#24067;&#20102; 27.2 beta&#12290;&#23613;&#31649; iPhone Duo &#27169;&#25311;&#22120;&#20381;&#28982;&#32570;&#24109;&#65292;&#20294;&#26032;&#22686;&#30340; </span><code>project.xcproj</code><span> &#20196;&#20154;&#30524;&#21069;&#19968;&#20142;&#12290;&#23427;&#26367;&#20195;&#30340;&#26159; </span><code>.xcodeproj</code><span> &#21253;&#37324;&#30340;&#37027;&#20221;&#26500;&#24314;&#22270; </span><code>project.pbxproj</code><span>&#65292;&#32780;&#19981;&#26159;&#25972;&#20010;&#24037;&#31243;&#21253;&#12290;&#23427;&#26377;&#21738;&#20123;&#20142;&#28857;&#65292;&#35299;&#20915;&#20102;&#20160;&#20040;&#38382;&#39064;&#65292;&#21448;&#26377;&#21738;&#20123;&#20107;&#24773;&#27809;&#26377;&#25913;&#21464;&#65292;&#26412;&#25991;&#23558;&#23545;&#27492;&#36827;&#34892;&#25506;&#35752;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-01"><span>&#20026; Devin &#26500;&#24314;&#20113;&#19978; Mac &#24320;&#21457;&#29615;&#22659; (How we built Devin&#8217;s Mac)</span></a></strong></h3><p><span>&#24403; AI Agent &#22312;&#26412;&#22320;&#36816;&#34892;&#26102;&#65292;&#26435;&#38480;&#26089;&#24050;&#25480;&#20104;&#65292;&#24037;&#20855;&#38142;&#24050;&#32463;&#23601;&#32490;&#65292;&#36935;&#21040;&#24377;&#31383;&#20063;&#21487;&#20197;&#20154;&#24037;&#24178;&#39044;&#12290;&#25644;&#21040;&#20113;&#31471;&#21518;&#65292;&#36825;&#20123;&#29702;&#25152;&#24403;&#28982;&#30340;&#26465;&#20214;&#37117;&#38656;&#35201;&#37325;&#26032;&#26500;&#24314;&#12290;&#25442;&#26469;&#30340;&#22909;&#22788;&#24182;&#19981;&#22312;&#20110;&#33021;&#20570;&#21040;&#26412;&#22320;&#20570;&#19981;&#21040;&#30340;&#20107;&#65292;&#32780;&#26159;&#35753;&#24320;&#21457;&#29615;&#22659;&#26412;&#36523;&#25104;&#20026;&#21487;&#20197;&#20998;&#37197;&#32473; Agent &#30340;&#36164;&#28304;&#65306;&#20219;&#21153;&#21487;&#20197;&#24322;&#27493;&#36816;&#34892;&#12289;&#24444;&#27492;&#38548;&#31163;&#65292;&#38386;&#32622;&#26102;&#26242;&#20572;&#24182;&#20445;&#23384;&#29366;&#24577;&#65292;&#38656;&#35201;&#26102;&#20877;&#24674;&#22797;&#65292;&#20063;&#26356;&#23481;&#26131;&#25903;&#25345;&#22810;&#20010; Agent &#24182;&#34892;&#24037;&#20316;&#12290;</span><a href="https://x.com/jkelleyrtp"><span>Jon Kelley</span></a><span> &#22312;&#25991;&#20013;&#20171;&#32461;&#20102;&#20026; Devin &#26500;&#24314; macOS &#20113;&#31471;&#29615;&#22659;&#30340;&#36807;&#31243;&#65292;&#28085;&#30422;&#22522;&#20110; Virtualization.framework &#30340;&#34394;&#25311;&#26426;&#12289;&#30913;&#30424;&#24555;&#29031;&#12289;&#32593;&#32476;&#38548;&#31163;&#12289;&#29615;&#22659;&#19982;&#26435;&#38480;&#39044;&#37197;&#32622;&#12289;&#26700;&#38754;&#19982; Simulator &#30340;&#23454;&#26102;&#20018;&#27969;&#65292;&#20197;&#21450;&#20511;&#21161;&#26080;&#38556;&#30861;&#26641;&#23454;&#29616;&#30340;&#35745;&#31639;&#26426;&#25805;&#20316;&#12290;&#26368;&#21518;&#19968;&#28857;&#23545;&#33529;&#26524;&#24320;&#21457;&#32773;&#23588;&#20854;&#26377;&#21551;&#21457;&#65306;&#20570;&#22909;&#26080;&#38556;&#30861;&#25903;&#25345;&#65292;&#20063;&#26159;&#22312;&#20026; Agent &#30340;&#33258;&#21160;&#21270;&#39564;&#35777;&#25552;&#20379;&#32467;&#26500;&#21270;&#25509;&#21475;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-02"><span>iOS 27: CrashReportExtension Framework</span></a></strong></h3><p><span>&#20256;&#32479;&#30340;&#23849;&#28291;&#22788;&#29702;&#26377;&#19968;&#20010;&#26840;&#25163;&#30340;&#38382;&#39064;&#65306;&#24403; signal handler &#24320;&#22987;&#24037;&#20316;&#26102;&#65292;&#23427;&#25152;&#22312;&#30340;&#36827;&#31243;&#26412;&#36523;&#21487;&#33021;&#24050;&#32463;&#22788;&#20110;&#19981;&#21487;&#38752;&#29366;&#24577;&#65292;&#20869;&#23384;&#21487;&#33021;&#25439;&#22351;&#12289;&#38145;&#21487;&#33021;&#27809;&#26377;&#37322;&#25918;&#65292;&#24456;&#22810;&#24179;&#26102;&#20351;&#29992;&#30340; API &#20063;&#26080;&#27861;&#23433;&#20840;&#35843;&#29992;&#12290;iOS 27 &#26032;&#22686;&#30340; CrashReportExtension &#25913;&#21464;&#20102;&#36825;&#19968;&#25191;&#34892;&#27169;&#22411;&#12290;&#24403; App &#23849;&#28291;&#21518;&#65292;&#31995;&#32479;&#20250;&#21551;&#21160;&#19968;&#20010;&#29420;&#31435;&#30340; Extension&#65292;&#24182;&#36890;&#36807;&#21482;&#35835;&#30340; </span><code>CrashedProcess</code><span> &#35753;&#23427;&#26816;&#26597;&#24050;&#32463;&#23849;&#28291;&#30340;&#36827;&#31243;&#12290;</span></p><p><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> &#22312;&#25991;&#20013;&#23436;&#25972;&#28436;&#31034;&#20102;&#36825;&#20010;&#25193;&#23637;&#30340;&#21019;&#24314;&#19982;&#20351;&#29992;&#65292;&#20063;&#32473;&#20986;&#20102;&#20960;&#26465;&#21153;&#23454;&#30340;&#21028;&#26029;&#12290;&#35813; API &#26159;&#23545;&#31995;&#32479; </span><code>.ips</code><span> &#25253;&#21578;&#30340;&#34917;&#20805;&#32780;&#38750;&#26367;&#20195;&#65292;&#36866;&#21512;&#38656;&#35201;&#33258;&#26377;&#21518;&#31471;&#12289;&#19994;&#21153;&#19978;&#19979;&#25991;&#20851;&#32852;&#25110;&#35774;&#22791;&#31471;&#39044;&#20998;&#26512;&#30340;&#22242;&#38431;&#12290;&#25193;&#23637;&#26412;&#36523;&#24212;&#23613;&#37327;&#31934;&#31616;&#65292;&#21482;&#36127;&#36131;&#29983;&#25104;&#24182;&#25345;&#20037;&#21270;&#25253;&#21578;&#65292;&#19978;&#20256;&#12289;&#37325;&#35797;&#31561;&#24037;&#20316;&#20132;&#32473;&#20027;&#24212;&#29992;&#65292;&#20004;&#32773;&#36890;&#36807; App Group &#20849;&#20139;&#23384;&#20648;&#12290;&#23545;&#22810;&#25968;&#29420;&#31435;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#31995;&#32479;&#23849;&#28291;&#25253;&#21578;&#21152;&#19978; MetricKit &#20381;&#28982;&#36275;&#22815;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-03"><span>SwiftUI &#21160;&#30011;&#30340;&#36816;&#20316;&#26426;&#21046; (How SwiftUI animation works)</span></a></strong></h3><p><span>&#23545;&#20110;&#21160;&#30011;&#65292;&#24320;&#21457;&#32773;&#21482;&#38656;&#25913;&#21464;&#29366;&#24577;&#24182;&#35774;&#32622;&#21160;&#30011;&#20989;&#25968;&#65292;&#21097;&#19979;&#30340;&#24037;&#20316;&#20415;&#20132;&#32473; SwiftUI&#12290;&#20294;&#36825;&#20123;&#22768;&#26126;&#26368;&#32456;&#26159;&#22914;&#20309;&#36716;&#21270;&#25104;&#23631;&#24149;&#19978;&#19968;&#24103;&#24103;&#36830;&#32493;&#21464;&#21270;&#30340;&#30011;&#38754;&#65311;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#20174; Transaction &#21644; AttributeGraph &#20986;&#21457;&#65292;&#32467;&#21512; OpenSwiftUI &#30340;&#24320;&#21457;&#32463;&#39564;&#65292;&#36880;&#27493;&#20998;&#26512; SwiftUI &#22914;&#20309;&#21019;&#24314;&#21160;&#30011;&#19978;&#19979;&#25991;&#12289;&#35745;&#31639;&#20013;&#38388;&#29366;&#24577;&#65292;&#24182;&#22312;&#21160;&#30011;&#36807;&#31243;&#20013;&#25345;&#32493;&#26356;&#26032;&#35270;&#22270;&#19982;&#24067;&#23616;&#12290;</span></p><p><span>&#19982;&#23558;&#21160;&#30011;&#25554;&#20540;&#20027;&#35201;&#20132;&#32473; render server &#30340;&#20256;&#32479;&#26041;&#24335;&#19981;&#21516;&#65292;SwiftUI &#30340;&#35768;&#22810;&#21160;&#30011;&#38656;&#35201;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#25345;&#32493;&#25512;&#36827;&#12290;&#30001;&#20110;&#25554;&#20540;&#21457;&#29983;&#22312;&#35270;&#22270;&#22270;&#20869;&#37096;&#65292;&#20219;&#20309;&#28385;&#36275; Animatable &#30340;&#20540;&#37117;&#33021;&#34987;&#37319;&#26679;&#65292;&#24067;&#23616;&#12289;Shape &#31561;&#26356;&#22810;&#29366;&#24577;&#22240;&#27492;&#24471;&#20197;&#21442;&#19982;&#21160;&#30011;&#65292;&#32780; render server &#20027;&#35201;&#22788;&#29702;&#22270;&#23618;&#23646;&#24615;&#12290;&#25991;&#20013;&#23545;&#24322;&#27493;&#25552;&#20132;&#36335;&#24452;&#20013; </span><code>CABasicAnimation</code><span> &#30340;&#20998;&#26512;&#23588;&#20854;&#20540;&#24471;&#19968;&#35835;&#65306;&#23427;&#21482;&#25215;&#36733;&#24403;&#21069;&#24103;&#30340;&#37319;&#26679;&#32467;&#26524;&#65292;&#19979;&#19968;&#24103;&#20415;&#20250;&#34987;&#26367;&#25442;&#8212;&#8212;&#23631;&#24149;&#19978;&#20986;&#29616;&#20102; CA &#21160;&#30011;&#23545;&#35937;&#65292;&#24182;&#19981;&#24847;&#21619;&#30528;&#21160;&#30011;&#30340;&#26102;&#38047;&#24050;&#32463;&#20132;&#32473;&#20102; Core Animation&#12290;&#36825;&#20063;&#20026;&#26412;&#26399;&#21608;&#35780;&#20013;&#25552;&#21040;&#30340; SwiftUI &#21160;&#30011;&#26159;&#21542;&#20026;&#8220;&#21407;&#29983;&#8221;&#20043;&#20105;&#25552;&#20379;&#20102;&#26356;&#22810;&#32454;&#33410;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-04"><span>&#20026; iPhone Duo &#20934;&#22791;&#30340;&#26032; API (SwiftUI: Some New APIs/ContainerViews Useful For Duo!)</span></a></strong></h3><p><span>iPhone Duo &#30340;&#22810;&#31181;&#20351;&#29992;&#24418;&#24577;&#32473; Toolbar &#24102;&#26469;&#20102;&#26032;&#30340;&#25361;&#25112;&#12290;&#20026;&#20102;&#20805;&#20998;&#21033;&#29992;&#26356;&#23485;&#30340;&#23631;&#24149;&#24182;&#20445;&#30041;&#32437;&#21521;&#20869;&#23481;&#31354;&#38388;&#65292;&#31995;&#32479;&#20250;&#22312;&#37096;&#20998;&#24418;&#24577;&#19979;&#23558;&#21407;&#26412;&#20301;&#20110;&#39030;&#37096;&#21644;&#24213;&#37096;&#30340;&#25511;&#20214;&#31227;&#21040;&#23631;&#24149;&#20391;&#36793;&#12290;&#20294;&#20256;&#32479; Toolbar &#20013;&#30340;&#25991;&#26412;&#25353;&#38062;&#12289;&#33258;&#23450;&#20041;&#35270;&#22270;&#31561;&#20869;&#23481;&#24182;&#19981;&#19968;&#23450;&#36866;&#21512;&#32437;&#21521;&#25490;&#21015;&#65292;Toolbar &#19982; Tab Bar &#36824;&#21487;&#33021;&#38656;&#35201;&#20105;&#22842;&#26377;&#38480;&#30340;&#20391;&#36793;&#31354;&#38388;&#12290;iOS 27.1 &#20026;&#27492;&#22686;&#21152;&#20102; </span><code>ToolbarItemAxisBehavior</code><span>&#12289;</span><code>ToolbarVerticalBehavior</code><span>&#12289;</span><code>ToolbarVerticalCompressionBehavior</code><span> &#21644; </span><code>toolbarVerticalEdge</code><span> &#31561; API&#65292;&#35753;&#24320;&#21457;&#32773;&#21487;&#20197;&#36827;&#19968;&#27493;&#25511;&#21046; Toolbar &#30340;&#26041;&#21521;&#12289;&#20301;&#32622;&#20197;&#21450;&#31354;&#38388;&#19981;&#36275;&#26102;&#30340;&#21387;&#32553;&#31574;&#30053;&#12290;&#8288;</span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> &#36890;&#36807;&#20195;&#30721;&#21644;&#28436;&#31034;&#23637;&#31034;&#20102;&#36825;&#20123;&#26032; API &#30340;&#20855;&#20307;&#34892;&#20026;&#12290;</span></p><p><span>&#36825;&#25209; API &#30340;&#20849;&#21516;&#29305;&#24449;&#65292;&#26159;&#35753;&#24320;&#21457;&#32773;&#22768;&#26126;&#20559;&#22909;&#32780;&#38750;&#25351;&#23450;&#32467;&#26524;&#12290;&#38754;&#23545; Duo &#24102;&#26469;&#30340;&#22810;&#31181;&#24418;&#24577;&#65292;&#19982;&#20854;&#38024;&#23545;&#29305;&#23450;&#35774;&#22791;&#29366;&#24577;&#32534;&#20889;&#24067;&#23616;&#65292;&#19981;&#22914;&#25551;&#36848;&#20869;&#23481;&#20043;&#38388;&#30340;&#20851;&#31995;&#21644;&#24067;&#23616;&#20559;&#22909;&#65292;&#20877;&#30001; SwiftUI &#26681;&#25454;&#23454;&#38469;&#29615;&#22659;&#20915;&#23450;&#26368;&#32456;&#21576;&#29616;&#26041;&#24335;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-05"><span>iPhone Duo &#19978;&#30340; Sheet &#19982;&#25240;&#30165;&#35268;&#36991; (Sheets and fold avoidance on iPhone Duo)</span></a></strong></h3><p><span>&#24403; iPhone Duo &#22788;&#20110;&#37096;&#20998;&#25240;&#21472;&#29366;&#24577;&#26102;&#65292;&#20013;&#22830;&#25240;&#30165;&#24418;&#25104;&#20102;&#19968;&#22359;&#19981;&#36866;&#21512;&#20132;&#20114;&#30340;&#21306;&#22495;&#65292;&#25353;&#38062;&#31561;&#25511;&#20214;&#22914;&#26524;&#24688;&#22909;&#33853;&#22312;&#36825;&#37324;&#65292;&#20250;&#21464;&#24471;&#38590;&#20197;&#25805;&#20316;&#12290;&#8288;</span><a href="https://x.com/sarunw"><span>Sarun Wongpatcharapakorn</span></a><span> &#20197; Sheet &#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#21516;&#19968;&#20010;&#30028;&#38754;&#22914;&#20309;&#22312; Duo &#30340;&#20851;&#38381;&#12289;&#23637;&#24320;&#12289;&#27178;&#23631;&#12289;&#31446;&#23631;&#20197;&#21450;&#37096;&#20998;&#25240;&#21472;&#31561;&#19981;&#21516;&#24418;&#24577;&#19979;&#35843;&#25972;&#23610;&#23544;&#12289;&#20301;&#32622;&#21644; Toolbar&#12290;Sheet&#12289;Alert &#21644;&#33756;&#21333;&#31561;&#31995;&#32479;&#32452;&#20214;&#24050;&#32463;&#20869;&#32622;&#25240;&#30165;&#35268;&#36991;&#33021;&#21147;&#65292;&#26080;&#38656;&#24320;&#21457;&#32773;&#24178;&#39044;&#12290;&#22240;&#27492;&#23545;&#20110;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#20248;&#20808;&#20351;&#29992;&#31995;&#32479;&#32452;&#20214;&#65292;&#20063;&#24847;&#21619;&#30528;&#21487;&#20197;&#30452;&#25509;&#33719;&#24471;&#36825;&#20123;&#38024;&#23545;&#19981;&#21516;&#35774;&#22791;&#24418;&#24577;&#30340;&#33258;&#36866;&#24212;&#34892;&#20026;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-06"><span>Vapor 5 Beta &#21457;&#24067;</span></a></strong></h3><p><span>&#22312; Vapor &#35806;&#29983;&#21313;&#21608;&#24180;&#12289;&#36317;&#31163; Vapor 4 &#21457;&#24067;&#20845;&#24180;&#21322;&#20043;&#38469;&#65292;&#31038;&#21306;&#32456;&#20110;&#36814;&#26469;&#20102; Vapor 5 &#30340;&#39318;&#20010; Beta &#29256;&#26412;&#12290;&#27492;&#27425;&#20960;&#20046;&#26159;&#19968;&#27425;&#24443;&#24213;&#37325;&#20889;&#8212;&#8212;&#21382;&#26102;&#20004;&#24180;&#12289;&#21464;&#26356;&#32422; 49,000 &#34892;&#20195;&#30721;&#12290;&#26368;&#26680;&#24515;&#30340;&#25913;&#21160;&#26159;&#24443;&#24213;&#21578;&#21035; </span><code>EventLoop</code><span> &#19982; </span><code>EventLoopFuture</code><span>&#65292;&#20840;&#38754;&#36716;&#21521; Swift Concurrency&#65292;&#24182;&#20197;&#32467;&#26500;&#21270;&#24182;&#21457;&#20026;&#22522;&#30784;&#65292;NIO &#20063;&#22522;&#26412;&#20174;&#20844;&#24320; API &#20013;&#38544;&#21435;&#12290;</span></p><p><span>&#21516;&#26102;&#65292;Vapor 5 &#36827;&#19968;&#27493;&#25972;&#21512; Swift HTTP Types&#12289;Swift Configuration &#21644; Swift Service Lifecycle&#65292;&#24182;&#21152;&#20837;&#23454;&#39564;&#24615;&#30340; </span><code>VaporMacros</code><span>&#65292;&#20026;&#36335;&#30001;&#21644;&#35748;&#35777;&#25552;&#20379;&#26356;&#22810;&#32534;&#35793;&#26399;&#31867;&#22411;&#26816;&#26597;&#12290;Vapor 5 &#35201;&#27714; Swift 6.4&#65292;&#30446;&#21069;&#20173;&#22788;&#20110; Beta &#38454;&#27573;&#12290;&#26377;&#20851;&#26356;&#22810;&#21464;&#21270;&#65292;&#21487;&#20197;&#26597;&#30475; &#8288;</span><a href="https://hachyderm.io/@0xTim"><span>Tim Condon</span></a><span> &#30340; &#8288;</span><a href="https://blog.vapor.codes/posts/whats-new-in-vapor-5-beta/"><span>What&#8217;s New in Vapor 5 Beta</span></a><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-07"><span>Hinge&#65306;&#21629;&#20196;&#34892;&#35843;&#33410; Duo &#27169;&#25311;&#22120;&#25240;&#21472;&#35282;&#24230;</span></a></strong></h3><p><span>Xcode 27.1 &#30340; Device Hub &#21487;&#20197;&#35843;&#25972; iPhone Duo Simulator &#30340;&#25240;&#21472;&#35282;&#24230;&#65288;&#25353;&#20303; Option &#38190;&#21487;&#35265;&#65289;&#65292;&#20294; </span><code>simctl</code><span> &#21644; </span><code>devicectl</code><span> &#24182;&#27809;&#26377;&#25552;&#20379;&#23545;&#24212;&#30340;&#25511;&#21046;&#21629;&#20196;&#12290;&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#24320;&#21457;&#30340; Hinge &#34917;&#19978;&#20102;&#36825;&#20010;&#32570;&#21475;&#65292;&#21487;&#20197;&#36890;&#36807;&#21629;&#20196;&#34892;&#35774;&#32622; 0&#8211;180&#176; &#30340;&#25240;&#21472;&#35282;&#24230;&#65292;&#20063;&#25903;&#25345;&#25171;&#24320;&#12289;&#20851;&#38381;&#12289;&#21322;&#25240;&#21472;&#20197;&#21450;&#36830;&#32493;&#25913;&#21464;&#35282;&#24230;&#31561;&#25805;&#20316;&#12290;Hinge &#36824;&#25552;&#20379;&#20102; Agent Skill&#65292;&#35753; Coding Agent &#21487;&#20197;&#22312;&#27979;&#35797;&#36807;&#31243;&#20013;&#20027;&#21160;&#25913;&#21464; Duo &#30340;&#25240;&#21472;&#29366;&#24577;&#24182;&#39564;&#35777; App&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-08"><span>Enriched Markdown&#65306;&#19981;&#20381;&#36182; WebView &#30340;&#36328;&#24179;&#21488; Markdown &#28210;&#26579;&#19982;&#32534;&#36753;&#26041;&#26696;</span></a></strong></h3><p><span>&#22312;&#31227;&#21160;&#31471;&#23454;&#29616; Markdown&#65292;&#24120;&#35265;&#26041;&#26696;&#26159;&#22871;&#19968;&#23618; WebView&#12290;Software Mansion &#25512;&#20986;&#30340; Enriched Markdown &#36873;&#25321;&#20102;&#19968;&#26465;&#26356;&#24443;&#24213;&#30340;&#36335;&#32447;&#65306;&#22522;&#20110;&#21508;&#24179;&#21488;&#30340;&#21407;&#29983;&#25991;&#26412;&#33021;&#21147;&#23436;&#25104; Markdown &#28210;&#26579;&#19982;&#23500;&#25991;&#26412;&#32534;&#36753;&#65292;&#24182;&#21487;&#20197;&#23558;&#32534;&#36753;&#21518;&#30340;&#20869;&#23481;&#37325;&#26032;&#36755;&#20986;&#20026;&#24178;&#20928;&#30340; Markdown&#12290;</span></p><p><span>&#23427;&#25552;&#20379;&#29420;&#31435;&#30340; SwiftUI SDK&#65292;&#22522;&#20110; TextKit 2 &#19982; md4c &#23454;&#29616; Markdown &#28210;&#26579;&#65292;&#21516;&#26102;&#20063;&#35206;&#30422; React Native&#12289;Android &#21644; Web&#12290;&#30456;&#27604;&#21333;&#32431;&#36861;&#27714;&#8220;&#33021;&#26174;&#31034; Markdown&#8221;&#65292;Enriched Markdown &#26356;&#37325;&#35270;&#21407;&#29983;&#20307;&#39564;&#65306;&#25991;&#26412;&#21487;&#20197;&#27491;&#24120;&#36873;&#25321;&#65292;&#38142;&#25509;&#12289;&#22270;&#29255;&#19982;&#20195;&#30721;&#22359;&#33021;&#22815;&#25509;&#20837;&#31995;&#32479;&#33756;&#21333;&#65292;&#24182;&#36866;&#37197; VoiceOver&#12289;TalkBack&#12289;&#21160;&#24577;&#23383;&#20307;&#21644;&#20174;&#21491;&#21040;&#24038;&#20070;&#20889;&#65288;RTL&#65289;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #153]]></title><description><![CDATA[The Opportunities and Challenges of iPhone Duo]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 14 Sep 2026 12:04:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!UL9K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UL9K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UL9K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 424w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 848w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1272w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" width="1456" height="852" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:852,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:403894,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/215610459?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UL9K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 424w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 848w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1272w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong><span>The Opportunities and Challenges of iPhone Duo</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-153/">Read on web &#8594;</a></p><p><span>Although some details of the iPhone Duo&#8217;s design had already leaked months ago, and Apple is a latecomer to the foldable phone market, its ability to tightly integrate hardware and software&#8212;and the interaction changes that integration enables&#8212;still managed to surprise quite a few consumers.</span></p><p><span>Different research firms have offered forecasts for the iPhone Duo&#8217;s early sales using different time frames. Counterpoint expects shipments to reach as many as 6 million units by the end of 2026, while IDC estimates that the device could reach around 10 million units in its first 12 months on the market. That would still represent only a small fraction of total iPhone sales. But compared with the hundreds of thousands of Vision Pro units sold over its first two and a half years, it is already a large enough market to support quite a few apps designed specifically for this device. Over the past few days, I&#8217;ve already seen plenty of creative ideas on social media built around the Duo&#8217;s form factor. If even a few of them turn into breakout hits, they could further drive device sales. More importantly, the Duo has far greater social visibility than Vision Pro. The sense of being &#8220;different&#8221; that comes from distinctive hardware paired with distinctive apps is exactly what many early adopters of products like this are looking for.</span></p><p><span>For most developers, however, the adaptation pressure created by the iPhone Duo&#8217;s unique form factor is very real. The Duo has both outer and inner displays, while the inner display can be used fully open, partially folded, and in other poses. It is arguably one of the most challenging devices in the iPhone family to design for. Apple does provide a number of APIs specifically for adapting to these configurations, and standard containers already handle different poses reasonably well. But those things mainly solve the UI problem. The real challenge is UX: an API can tell you how much space is available and where the hinge is, but it cannot tell you what users actually want to see when the device is partially folded. Every additional pose means another experience that needs to be designed.</span></p><p><span>For teams using third-party frameworks such as Flutter and React Native, the problem starts one step earlier: it is not just about how well you can adapt, but whether you can access the necessary information in the first place. Flutter&#8217;s </span><code>MediaQuery.displayFeatures</code><span> returns an empty list on the Duo regardless of the fold angle, while React Native still provides no official API for accessing fold state. Once the hardware itself becomes part of the interaction model, cross-platform frameworks have to make more tradeoffs between hiding platform differences and exposing platform capabilities. And those tradeoffs are difficult for a framework to absorb on its own&#8212;it will always lag behind the platform.</span></p><p><span>In fact, the trend toward reevaluating cross-platform approaches had already begun before the Duo was announced, driven by several changes happening at the same time. AI coding agents have substantially reduced the cost of native development and maintenance, while changes such as Liquid Glass and Duo continue to raise the value of taking full advantage of platform-specific capabilities. The cost-benefit equation for cross-platform development is being squeezed from both directions. Notion is migrating its Apple-platform UI from a web-based technology stack to SwiftUI. Around the same time, Shopify announced that it was moving its mobile apps from React Native back to Swift and Kotlin. One reason it cited was that advances in coding models are eroding one of the key cost advantages of cross-platform development: avoiding having to &#8220;build the same feature twice.&#8221; Alongside that transition, Shopify is also handing off its React Native open-source libraries.</span></p><p><span>For the Apple ecosystem, iPhone Duo is a product that brings genuine change. Over the past few years, most changes to Apple&#8217;s platforms have taken place in software and design language. Duo, by contrast, changes the physical form factor developers have to design for. Its significance to the ecosystem may not lie in selling a few million more devices, but in what happens when the device itself once again becomes part of application design: &#8220;using the platform&#8217;s native frameworks&#8221; is starting to shift from a matter of preference to a matter of cost.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-152/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-01"><span>Module Tracking in Swift Debug Info</span></a></strong></h3><p><span>Have you ever hit a breakpoint, typed a seemingly trivial LLDB expression, and then waited... and waited? To evaluate a computed property or call a method, LLDB sometimes has to spin up the Swift compiler and locate and load the relevant modules. In the past, that lookup couldn&#8217;t always find the exact module your code was built from, and it might even recompile some dependencies along the way, turning a simple debugging step into a long pause.</span></p><p><a href="https://github.com/adrian-prantl/"><span>Adrian Prantl</span></a><span> introduces Module Tracking, a mechanism that began in Swift 6.3 and is further refined in 6.4. The new approach lets debug info tell LLDB precisely: &#8220;these are the modules the build actually used, and here is where they live,&#8221; cutting out unnecessary searching and recompilation. Swift 6.4 also improves bridging header handling and noticeably slims down debug artifacts &#8212; dSYM bundles on Darwin no longer carry binary Swift modules, and binaries built with debug info on Windows and Linux benefit as well.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-02"><span>New Hashable conformances in Swift 6.4</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span> walks through several standard library types that gain </span><code>Hashable</code><span> conformance in Swift 6.4, coming from two proposals: SE-0514 (</span><code>Dictionary.Keys</code><span>, </span><code>CollectionOfOne</code><span>, </span><code>EmptyCollection</code><span>) and SE-0523 (</span><code>UnownedTaskExecutor</code><span>). The one closest to everyday development is </span><code>Dictionary.Keys</code><span>, which can now go straight into a </span><code>Set</code><span> or serve as a dictionary key without first being converted to another type.</span></p><p><span>The semantics are worth noting: two </span><code>Dictionary.Keys</code><span> values are equal as long as they contain the same keys &#8212; order participates in neither comparison nor hashing, which is consistent with how a dictionary&#8217;s own identity is defined. </span><code>Dictionary.Values</code><span> did not receive the same treatment, because values can repeat, and expressing that correctly would require multiset semantics that Swift doesn&#8217;t currently have. A small piece of completion work, but one that makes these types sit more naturally in generic and collection contexts.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-03"><span>How to list big models cheaply: Vein vs SwiftData</span></a></strong></h3><p><span>Two weeks ago, in </span><a href="https://fatbobman.com/en/posts/swiftdata-optimization-starts-with-modeling/"><span>SwiftData: Optimization Starts with Modeling</span></a><span>, I discussed the memory and performance pressure that &#8220;fat models&#8221; put on SwiftData lists, and tried to reduce how much data a single query actually loads by splitting the model. </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia K&#246;ring</span></a><span> took the benchmark code from that article and used it to show how </span><a href="https://github.com/amethystsoft/vein"><span>Vein</span></a><span>, the persistence framework she is building, performs with field-level lazy loading.</span></p><p><span>Vein declares models much the way SwiftData does, and by default behaves similarly too: properties are eagerly loaded, relationships lazily. The difference is that marking a property with </span><code>@LazyField</code><span> defers reading it until it is actually accessed. As a result, in a &#8220;title-only list&#8221; scenario, Vein reaches good numbers without any model splitting at all.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-04"><span>Sad But True: Localized App Store Screenshots That Verify Themselves</span></a></strong></h3><p><span>Automation keeps working its way into every stage of app development. But in practice, the hard part often isn&#8217;t implementing the automation &#8212; it&#8217;s getting it to prove that it did the right thing.</span></p><p><span>While generating localized App Store screenshots automatically, </span><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> discovered that his Spanish screenshots had quietly fallen back to English, while the entire test run still reported success. The cause turned out to be </span><code>-testLanguage</code><span> not reliably reaching the app under Xcode 27. Wesley switched to setting the simulator&#8217;s language through </span><code>simctl</code><span>, and added a check that compares the SHA-256 of the captured screenshots to catch cases where two languages, or two different screens, unexpectedly produce byte-identical images.</span></p><blockquote><p><span>Wesley&#8217;s screenshot-hashing approach transfers to any pipeline where you hand a request to a black box and then accept whatever comes back at face value.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-05"><span>Transition or ContentTransition</span></a></strong></h3><p><code>transition</code><span> and </span><code>contentTransition</code><span> have remarkably similar names, but they solve two different problems: the former animates a view being inserted into or removed from the view hierarchy, the latter applies when the view stays put and only the content it displays changes. </span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> compares them side by side using conditional views, changing numbers, and SF Symbols, and covers common content transitions such as </span><code>.numericText</code><span>, </span><code>.interpolate</code><span>, and </span><code>.symbolEffect</code><span>.</span></p><blockquote><p><span>SwiftUI has supported custom </span><code>transition</code><span> values for a long time, but that capability has never extended to higher-level scenarios like sheets or navigation changes. Those situations resemble </span><code>contentTransition</code><span>, and still rely mostly on the handful of transitions the system provides. It would be good to see SwiftUI eventually connect these different levels of the transition concept &#8212; or at least give developers more room to customize them.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-06"><span>Abstracting SwiftUI state with scopes</span></a></strong></h3><p><span>When a SwiftUI view holds several </span><code>@State</code><span> properties, we often abstract them into a single </span><code>@Observable</code><span>. But what if the view also depends on environment values or other </span><code>Observable</code><span> instances? Is there a way to organize state coming from different sources while reducing the view&#8217;s coupling to any particular one of them? </span><a href="https://twitter.com/auramagi"><span>Mike Apurin</span></a><span> proposes thinking in scopes: his library </span><a href="https://github.com/auramagi/swift-scoped-state"><span>ScopedState</span></a><span> gathers multiple state sources behind a unified access boundary, exposing to a view only the state and actions that screen genuinely needs. The view doesn&#8217;t need to know where any of it comes from, and swapping the data source in previews and tests becomes much easier. Worth noting: this isn&#8217;t an attempt to build yet another state management model along the lines of TCA or MVVM &#8212; it&#8217;s a way of organizing and abstracting existing state sources at the view layer.</span></p><div><hr></div><h3><strong><span>Before the Fold: Adapting for iPhone Duo</span></strong></h3><p><span>The arrival of iPhone Duo has consumers marveling at the new form factor, and developers facing a new set of challenges: how to make use of the extra display space, how to make existing layouts adapt across device configurations, and how to take advantage of new interaction capabilities like the fold and multiple display regions. Over the past week, a number of writers offered their perspectives.</span></p><ul><li><p><span>Apple published six Tech Talks on announcement day: </span><a href="https://developer.apple.com/videos/play/tech-talks/111466/"><span>Design for iPhone Duo</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111461/"><span>Prepare your app</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111462/"><span>Raise the bar</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111463/"><span>Strike a pose with adaptive layouts</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111464/"><span>Leverage multiple displays and scenes</span></a><span>, and </span><a href="https://developer.apple.com/videos/play/tech-talks/111465/"><span>Build a great camera experience</span></a><span>, along with a new </span><a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo"><span>Designing for iPhone Duo</span></a><span> page in the HIG.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-07"><span>Florian Schweizer</span></a><span> makes the case for not fighting the framework: don&#8217;t start by asking whether the device is an iPhone Duo, ask how much space this view has been given. He has also distilled these principles, along with Duo&#8217;s new APIs and Apple&#8217;s developer material, into a </span><a href="https://github.com/FloWritesCode/fwc-swiftui-skills/tree/main/skills/swiftui-iphone-duo"><span>SwiftUI iPhone Duo Skill</span></a><span> for coding agents working on existing apps.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-08"><span>Lee young-jun</span></a><span> approaches it from hands-on adaptation work, using </span><code>NavigationSplitView</code><span>, </span><code>sidebarAdaptable</code><span>, and Device Hub&#8217;s Resizing Mode to inspect and improve how an app behaves across iPhone Duo&#8217;s different display configurations ahead of time.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-09"><span>Sagar Unagar</span></a><span> draws on Apple&#8217;s latest HIG and developer material to summarize the main design principles for iPhone Duo: adaptive layout, system controls, the fold region, and the various display configurations.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-10"><span>Jordan Morgan</span></a><span> rounds up the changes developers should look at first &#8212; layout, system bars, safe areas, camera, and multiple display regions.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-11"><span>Artem Mirzabekian</span></a><span> introduces the new </span><code>ArrangementView</code><span>, which lets you describe the relationship between two related pieces of content and leaves it to SwiftUI to pick a suitable layout based on available space and the fold region.</span></p></li></ul><blockquote><p><span>Many of the features covered above exist only in Xcode 27.1, so experiencing them in full will take a little while yet.</span></p></blockquote><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-12"><span>SwiftMusic: Declaring Music in Swift</span></a></strong></h3><p><span>SwiftMusic, from </span><a href="https://x.com/1amageek"><span>Norikazu Muramoto</span></a><span>, is a declarative music composition framework for Apple platform developers. It borrows SwiftUI&#8217;s design sensibility, bringing familiar Swift constructs &#8212; </span><code>Music</code><span>, </span><code>Sound</code><span>, </span><code>body</code><span>, result builders, and modifiers &#8212; into music creation, so that rhythm, melody, harmony, timbre, effects, and mixing relationships can all be described by composing code.</span></p><p><span>Drums, bass, and synths, for instance, can be written as Swift code that reads musically:</span></p><pre><code><span>struct Session: Music {</span>
<span>      var body: some Sound {</span>
<span>          Track(&#8221;Drums&#8221;) {</span>
<span>              Sample(&#8221;kick&#8221;)</span>
<span>                  .rhythm(&#8221;x ~ x ~&#8221;)</span>
<span>          }</span>
<span>&#8203;</span>
<span>          Track(&#8221;Bass&#8221;) {</span>
<span>              Synthesizer(.saw)</span>
<span>                  .notes(&#8221;C2 ~ Eb2 G2&#8221;)</span>
<span>                  .gain(0.3)</span>
<span>          }</span>
<span>      }</span>
<span>  }</span></code></pre><p><span>SwiftMusic makes no sound on its own: it only compiles your declarations into beat-domain events and an ordered render plan. It neither opens an audio device nor draws an editor &#8212; actual audio rendering is the host&#8217;s responsibility. The author provides </span><a href="https://github.com/1amageek/MusicPlaygournd"><span>MusicPlaygournd</span></a><span>, a live editor for macOS, to fill that role.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-13"><span>Homebrew 7: The Release That Says Goodbye to Intel</span></a></strong></h3><p><span>Homebrew 7.0.0 is out. Alongside a range of features and internal changes, this major release brings compatibility changes worth paying attention to. On Apple Silicon Macs, macOS 15&#8211;27 currently falls within the fully supported range, while Intel Macs have all been moved down to Tier 3 &#8212; no full CI support, no new bottles, and a plan to end support entirely in or after September 2027. If you are still running Homebrew on an Intel Mac or an older version of macOS, this one deserves a closer look.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>iPhone Duo &#24102;&#26469;&#30340;&#26426;&#36935;&#19982;&#25361;&#25112;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-153/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#23613;&#31649; iPhone Duo &#30340;&#35774;&#35745;&#36164;&#26009;&#26089;&#22312;&#20960;&#20010;&#26376;&#21069;&#23601;&#24050;&#37096;&#20998;&#27844;&#28431;&#65292;&#32780;&#19988;&#33529;&#26524;&#20063;&#26159;&#25240;&#21472;&#26426;&#39046;&#22495;&#30340;&#21518;&#26469;&#32773;&#65292;&#20294;&#20973;&#20511;&#36719;&#30828;&#20214;&#25972;&#21512;&#33021;&#21147;&#65292;&#23427;&#25152;&#24102;&#26469;&#30340;&#20132;&#20114;&#21464;&#21270;&#36824;&#26159;&#32473;&#19981;&#23569;&#28040;&#36153;&#32773;&#24102;&#26469;&#20102;&#24778;&#21916;&#12290;</span></p><p><span>&#19981;&#21516;&#26426;&#26500;&#23545; iPhone Duo &#30340;&#21021;&#26399;&#38144;&#37327;&#32473;&#20986;&#20102;&#19981;&#21516;&#21475;&#24452;&#30340;&#39044;&#27979;&#65306;Counterpoint &#39044;&#35745;&#20854; 2026 &#24180;&#20869;&#20986;&#36135;&#37327;&#26368;&#39640;&#32422; 600 &#19975;&#37096;&#65307;IDC &#21017;&#39044;&#35745;&#19978;&#24066;&#21518;&#21069; 12 &#20010;&#26376;&#21487;&#33021;&#36798;&#21040;&#32422; 1000 &#19975;&#37096;&#12290;&#22312;&#25972;&#20010; iPhone &#38144;&#37327;&#20013;&#65292;&#36825;&#20173;&#28982;&#21482;&#21344;&#19968;&#23567;&#37096;&#20998;&#65292;&#20294;&#19982; Vision Pro &#19978;&#24066;&#20004;&#24180;&#21322;&#30340;&#20960;&#21313;&#19975;&#38144;&#37327;&#30456;&#27604;&#65292;&#36825;&#20010;&#25968;&#37327;&#24050;&#32463;&#36275;&#20197;&#25903;&#25745;&#19981;&#23569;&#29305;&#21035;&#38024;&#23545;&#36825;&#27454;&#35774;&#22791;&#24320;&#21457;&#30340;&#24212;&#29992;&#20102;&#12290;&#36825;&#20960;&#22825;&#65292;&#25105;&#24050;&#32463;&#22312;&#31038;&#20132;&#23186;&#20307;&#19978;&#30475;&#21040;&#19981;&#23569;&#38024;&#23545; Duo &#24418;&#24577;&#30340;&#21019;&#24847;&#65292;&#30456;&#20449;&#19968;&#26086;&#20854;&#20013;&#20986;&#29616;&#20960;&#20010;&#29190;&#27454;&#65292;&#20063;&#20250;&#36827;&#19968;&#27493;&#25512;&#21160;&#35774;&#22791;&#30340;&#38144;&#37327;&#12290;&#23588;&#20854;&#26159;&#65292;Duo &#30456;&#27604; Vision Pro &#20855;&#22791;&#26356;&#24378;&#30340;&#31038;&#20132;&#23637;&#31034;&#24615;&#65292;&#29305;&#21035;&#30340;&#30828;&#20214;&#12289;&#29305;&#21035;&#30340;&#24212;&#29992;&#25152;&#24102;&#26469;&#30340;&#8220;&#29305;&#21035;&#24863;&#8221;&#65292;&#27491;&#26159;&#19981;&#23569;&#39318;&#25209;&#36141;&#20080;&#36825;&#31867;&#20135;&#21697;&#30340;&#29992;&#25143;&#25152;&#36861;&#27714;&#30340;&#12290;</span></p><p><span>&#20294;&#23545;&#20110;&#26356;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;iPhone Duo &#29420;&#29305;&#24418;&#24577;&#24102;&#26469;&#30340;&#36866;&#37197;&#21387;&#21147;&#20063;&#26159;&#30495;&#23454;&#30340;&#12290;Duo &#21253;&#25324;&#20869;&#22806;&#20004;&#22359;&#23631;&#24149;&#65292;&#20869;&#23631;&#21448;&#21487;&#20197;&#20197;&#23637;&#24320;&#12289;&#21322;&#25240;&#21472;&#31561;&#22810;&#31181;&#23039;&#24577;&#23384;&#22312;&#65292;&#21487;&#20197;&#35828;&#26159; iPhone &#23478;&#26063;&#20013;&#36866;&#37197;&#38590;&#24230;&#26368;&#39640;&#30340;&#20135;&#21697;&#20043;&#19968;&#12290;&#33529;&#26524;&#30830;&#23454;&#25552;&#20379;&#20102;&#19981;&#23569;&#26377;&#38024;&#23545;&#24615;&#30340;&#36866;&#37197; API&#65292;&#26631;&#20934;&#23481;&#22120;&#22312;&#21508;&#31181;&#23039;&#24577;&#19979;&#20063;&#24050;&#22522;&#26412;&#33258;&#36866;&#24212;&#65292;&#20294;&#36825;&#20123;&#21482;&#35299;&#20915;&#20102; UI &#23618;&#38754;&#30340;&#38382;&#39064;&#12290;&#30495;&#27491;&#38590;&#30340;&#26159; UX&#65306;API &#33021;&#21578;&#35785;&#20320;&#21487;&#29992;&#31354;&#38388;&#26377;&#22810;&#22823;&#12289;&#38128;&#38142;&#33853;&#22312;&#21738;&#37324;&#65292;&#21364;&#26080;&#27861;&#21578;&#35785;&#20320;&#21322;&#25240;&#21472;&#26102;&#29992;&#25143;&#31350;&#31455;&#24819;&#30475;&#21040;&#20160;&#20040;&#12290;&#22810;&#19968;&#31181;&#23039;&#24577;&#65292;&#23601;&#22810;&#19968;&#27425;&#38656;&#35201;&#37325;&#26032;&#35774;&#35745;&#30340;&#20307;&#39564;&#12290;</span></p><p><span>&#23545;&#20110;&#20351;&#29992; Flutter&#12289;React Native &#31561;&#31532;&#19977;&#26041;&#26694;&#26550;&#30340;&#22242;&#38431;&#65292;&#38382;&#39064;&#36824;&#35201;&#26356;&#38752;&#21069;&#19968;&#27493;&#65306;&#19981;&#26159;&#36866;&#37197;&#24471;&#22909;&#19981;&#22909;&#65292;&#32780;&#26159;&#25343;&#19981;&#25343;&#24471;&#21040;&#20449;&#24687;&#12290;Flutter &#30340; </span><code>MediaQuery.displayFeatures</code><span> &#22312; Duo &#19978;&#26080;&#35770;&#25240;&#21472;&#21040;&#20160;&#20040;&#35282;&#24230;&#37117;&#36820;&#22238;&#31354;&#21015;&#34920;&#65292;React Native &#21017;&#33267;&#20170;&#27809;&#26377;&#20219;&#20309;&#19982;&#25240;&#21472;&#29366;&#24577;&#30456;&#20851;&#30340;&#23448;&#26041; API&#12290;&#24403;&#30828;&#20214;&#26412;&#36523;&#24320;&#22987;&#25104;&#20026;&#20132;&#20114;&#30340;&#19968;&#37096;&#20998;&#65292;&#36328;&#24179;&#21488;&#26694;&#26550;&#23601;&#24517;&#39035;&#22312;&#23631;&#34109;&#24179;&#21488;&#24046;&#24322;&#19982;&#26292;&#38706;&#24179;&#21488;&#33021;&#21147;&#20043;&#38388;&#20570;&#20986;&#26356;&#22810;&#21462;&#33293;&#65292;&#32780;&#36825;&#31181;&#21462;&#33293;&#24456;&#38590;&#30001;&#26694;&#26550;&#21333;&#26041;&#38754;&#28040;&#21270;&#8212;&#8212;&#23427;&#24635;&#26159;&#28382;&#21518;&#20110;&#24179;&#21488;&#12290;</span></p><p><span>&#20107;&#23454;&#19978;&#65292;&#22312; Duo &#21457;&#24067;&#20043;&#21069;&#65292;&#37325;&#26032;&#35780;&#20272;&#36328;&#24179;&#21488;&#26041;&#26696;&#30340;&#36235;&#21183;&#23601;&#24050;&#32463;&#20986;&#29616;&#65292;&#20854;&#32972;&#21518;&#26159;&#19968;&#32452;&#27491;&#22312;&#21516;&#26102;&#21457;&#29983;&#30340;&#21464;&#21270;&#65306;AI Coding Agent &#22823;&#24133;&#38477;&#20302;&#20102;&#21407;&#29983;&#24320;&#21457;&#19982;&#32500;&#25252;&#30340;&#25104;&#26412;&#65292;&#32780; Liquid Glass&#12289;Duo &#36825;&#26679;&#30340;&#21464;&#21270;&#21448;&#22312;&#19981;&#26029;&#25260;&#39640;&#29992;&#36275;&#24179;&#21488;&#29305;&#24615;&#30340;&#20215;&#20540;&#12290;&#36328;&#24179;&#21488;&#26041;&#26696;&#30340;&#24615;&#20215;&#27604;&#65292;&#27491;&#34987;&#36825;&#20004;&#22836;&#21516;&#26102;&#25380;&#21387;&#12290;Notion &#27491;&#22312;&#23558;&#22522;&#20110; Web &#25216;&#26415;&#26632;&#30340;&#33529;&#26524;&#31471; UI &#36801;&#31227;&#21040; SwiftUI&#65307;Shopify &#21017;&#22312;&#20960;&#20046;&#21516;&#19968;&#26102;&#38388;&#23459;&#24067;&#23558;&#31227;&#21160;&#31471;&#20174; React Native &#36801;&#22238; Swift &#19982; Kotlin&#65292;&#29702;&#30001;&#20043;&#19968;&#26159;&#32534;&#30721;&#27169;&#22411;&#30340;&#36827;&#27493;&#27491;&#22312;&#21066;&#24369;&#8220;&#36991;&#20813;&#25226;&#21516;&#19968;&#20010;&#21151;&#33021;&#36896;&#20004;&#36941;&#8221;&#36825;&#19968;&#36328;&#24179;&#21488;&#24320;&#21457;&#30340;&#37325;&#35201;&#25104;&#26412;&#20248;&#21183;&#12290;&#19982;&#20043;&#19968;&#24182;&#21457;&#29983;&#30340;&#65292;&#26159;&#23427;&#23545;&#26071;&#19979; React Native &#24320;&#28304;&#24211;&#30340;&#20132;&#25509;&#12290;</span></p><p><span>&#23545;&#20110;&#33529;&#26524;&#29983;&#24577;&#26469;&#35828;&#65292;iPhone Duo &#26159;&#19968;&#20010;&#30495;&#27491;&#24102;&#26469;&#21464;&#21270;&#30340;&#20135;&#21697;&#12290;&#36807;&#21435;&#20960;&#24180;&#65292;&#33529;&#26524;&#24179;&#21488;&#30340;&#21464;&#21270;&#26356;&#22810;&#21457;&#29983;&#22312;&#36719;&#20214;&#21644;&#35774;&#35745;&#35821;&#35328;&#19978;&#65292;&#32780; Duo &#21017;&#37325;&#26032;&#25913;&#21464;&#20102;&#24320;&#21457;&#32773;&#38754;&#23545;&#30340;&#30828;&#20214;&#24418;&#24577;&#12290;&#23427;&#30340;&#29983;&#24577;&#24847;&#20041;&#25110;&#35768;&#24182;&#19981;&#22312;&#20110;&#22810;&#21334;&#20986;&#20960;&#30334;&#19975;&#21488;&#35774;&#22791;&#65292;&#32780;&#22312;&#20110;&#24403;&#35774;&#22791;&#26412;&#36523;&#20877;&#27425;&#25104;&#20026;&#24212;&#29992;&#35774;&#35745;&#30340;&#19968;&#37096;&#20998;&#26102;&#65292;&#8220;&#20351;&#29992;&#24179;&#21488;&#21407;&#29983;&#26694;&#26550;&#8221;&#36825;&#20214;&#20107;&#65292;&#27491;&#22312;&#20174;&#19968;&#36947;&#20559;&#22909;&#39064;&#21464;&#25104;&#19968;&#36947;&#25104;&#26412;&#39064;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-152/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-01"><span>&#35843;&#35797;&#21345;&#39039;&#30340;&#26681;&#28304;&#65306;Swift &#22914;&#20309;&#36861;&#36394; Module (Module Tracking in Swift Debug Info)</span></a></strong></h3><p><span>&#20320;&#26159;&#21542;&#30896;&#21040;&#36807;&#36825;&#26679;&#30340;&#24773;&#20917;&#65306;&#19968;&#20010;&#30475;&#20284;&#31616;&#21333;&#30340; LLDB &#34920;&#36798;&#24335;&#65292;&#22312;&#26029;&#28857;&#35843;&#35797;&#26102;&#21364;&#36831;&#36831;&#27809;&#26377;&#21453;&#39304;&#65311;&#20026;&#20102;&#35745;&#31639;&#23646;&#24615;&#12289;&#35843;&#29992;&#26041;&#27861;&#31561;&#25805;&#20316;&#65292;LLDB &#26377;&#26102;&#38656;&#35201;&#21551;&#21160; Swift &#32534;&#35793;&#22120;&#65292;&#24182;&#23547;&#25214;&#21644;&#21152;&#36733;&#30456;&#20851; Module&#12290;&#36807;&#21435;&#36825;&#22871;&#36807;&#31243;&#24182;&#19981;&#24635;&#33021;&#20934;&#30830;&#25214;&#21040;&#26500;&#24314;&#26102;&#23454;&#38469;&#20351;&#29992;&#30340; Module&#65292;&#29978;&#33267;&#21487;&#33021;&#37325;&#26032;&#32534;&#35793;&#37096;&#20998;&#20381;&#36182;&#65292;&#35753;&#19968;&#20010;&#21407;&#26412;&#31616;&#21333;&#30340;&#35843;&#35797;&#25805;&#20316;&#21464;&#25104;&#38271;&#26102;&#38388;&#31561;&#24453;&#12290;</span></p><p><a href="https://github.com/adrian-prantl/"><span>Adrian Prantl</span></a><span> &#20171;&#32461;&#20102;&#19968;&#20010;&#20174; Swift 6.3 &#24320;&#22987;&#24341;&#20837;&#12289;&#24182;&#22312; 6.4 &#20013;&#36827;&#19968;&#27493;&#23436;&#21892;&#30340;&#26426;&#21046;&#65306;Module Tracking&#12290;&#26032;&#30340;&#26426;&#21046;&#35753;&#35843;&#35797;&#20449;&#24687;&#33021;&#22815;&#26356;&#26126;&#30830;&#22320;&#21578;&#35785; LLDB&#65306;&#8221;&#26500;&#24314;&#26102;&#29992;&#30340;&#23601;&#26159;&#36825;&#20123; Module&#65292;&#23427;&#20204;&#23601;&#22312;&#36825;&#37324;&#8221;&#65292;&#20174;&#32780;&#20943;&#23569;&#19981;&#24517;&#35201;&#30340;&#23547;&#25214;&#21644;&#37325;&#26032;&#32534;&#35793;&#12290;Swift 6.4 &#36824;&#20250;&#25913;&#21892; bridging header &#30340;&#22788;&#29702;&#65292;&#24182;&#35753;&#35843;&#35797;&#20135;&#29289;&#26126;&#26174;&#30246;&#36523;&#8212;&#8212;Darwin &#19978;&#30340; dSYM &#19981;&#20877;&#25171;&#21253;&#20108;&#36827;&#21046; Swift Module&#65292;Windows &#19982; Linux &#19978;&#24102;&#35843;&#35797;&#20449;&#24687;&#30340;&#20108;&#36827;&#21046;&#21516;&#26679;&#21463;&#30410;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-02"><span>Swift 6.4 &#20013;&#34917;&#40784;&#30340;&#20960;&#22788; Hashable (New Hashable conformances in Swift 6.4)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span> &#20171;&#32461;&#20102; Swift 6.4 &#20013;&#20960;&#20010;&#26032;&#22686; </span><code>Hashable</code><span> &#25903;&#25345;&#30340;&#26631;&#20934;&#24211;&#31867;&#22411;&#65292;&#23427;&#20204;&#20998;&#21035;&#26469;&#33258; SE-0514&#65288;</span><code>Dictionary.Keys</code><span>&#12289;</span><code>CollectionOfOne</code><span>&#12289;</span><code>EmptyCollection</code><span>&#65289;&#21644; SE-0523&#65288;</span><code>UnownedTaskExecutor</code><span>&#65289;&#12290;&#20854;&#20013;&#26368;&#36148;&#36817;&#26085;&#24120;&#24320;&#21457;&#30340;&#26159; </span><code>Dictionary.Keys</code><span>&#65306;&#29616;&#22312;&#21487;&#20197;&#30452;&#25509;&#25918;&#20837; </span><code>Set</code><span> &#25110;&#20316;&#20026; Dictionary &#30340; key&#65292;&#32780;&#19981;&#24517;&#20808;&#36716;&#25442;&#25104;&#20854;&#20182;&#31867;&#22411;&#12290;</span></p><p><span>&#20540;&#24471;&#30041;&#24847;&#23427;&#30340;&#35821;&#20041;&#65306;&#20004;&#20010; </span><code>Dictionary.Keys</code><span> &#21482;&#35201;&#21253;&#21547;&#30456;&#21516;&#30340;&#38190;&#23601;&#35270;&#20026;&#30456;&#31561;&#65292;&#39034;&#24207;&#19981;&#21442;&#19982;&#27604;&#36739;&#19982;&#21704;&#24076;&#8212;&#8212;&#36825;&#19982;&#23383;&#20856;&#26412;&#36523;&#30340;&#36523;&#20221;&#35748;&#23450;&#26159;&#19968;&#33268;&#30340;&#12290;</span><code>Dictionary.Values</code><span> &#27809;&#26377;&#19968;&#24182;&#33719;&#24471;&#35813;&#33021;&#21147;&#65292;&#22240;&#20026;&#20540;&#21487;&#20197;&#37325;&#22797;&#65292;&#38656;&#35201;&#30340;&#26159; Swift &#30446;&#21069;&#27809;&#26377;&#30340;&#22810;&#37325;&#38598;&#21512;&#35821;&#20041;&#12290;&#34429;&#28982;&#21482;&#26159;&#19968;&#27425;&#23567;&#24133;&#34917;&#20840;&#65292;&#20294;&#20063;&#35753;&#36825;&#20123;&#31867;&#22411;&#22312;&#27867;&#22411;&#21644;&#38598;&#21512;&#22330;&#26223;&#20013;&#30340;&#20351;&#29992;&#26356;&#21152;&#33258;&#28982;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-03"><span>Vein &#20013;&#30340;&#24816;&#20540;&#24615;&#33021; (How to list big models cheaply: Vein vs SwiftData)</span></a></strong></h3><p><span>&#20004;&#21608;&#21069;&#25105;&#22312; </span><a href="https://fatbobman.com/zh/posts/swiftdata-optimization-starts-with-modeling/"><span>SwiftData&#65306;&#20248;&#21270;&#20174;&#24314;&#27169;&#24320;&#22987;</span></a><span> &#20013;&#35752;&#35770;&#20102;&#8220;&#32982;&#27169;&#22411;&#8221;&#32473; SwiftData &#21015;&#34920;&#24102;&#26469;&#30340;&#20869;&#23384;&#21644;&#24615;&#33021;&#21387;&#21147;&#65292;&#24182;&#23581;&#35797;&#36890;&#36807;&#27169;&#22411;&#25286;&#20998;&#20943;&#23569;&#19968;&#27425;&#26597;&#35810;&#30495;&#27491;&#21152;&#36733;&#30340;&#25968;&#25454;&#12290;</span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia K&#246;ring</span></a><span> &#20351;&#29992;&#20102;&#25105;&#25991;&#31456;&#20013;&#30340;&#27979;&#35797;&#20195;&#30721;&#65292;&#23637;&#31034;&#20102;&#22905;&#24320;&#21457;&#30340; </span><a href="https://github.com/amethystsoft/vein"><span>Vein</span></a><span> &#25345;&#20037;&#21270;&#26694;&#26550;&#22312;&#23383;&#27573;&#32423;&#24816;&#24615;&#21152;&#36733;&#19979;&#30340;&#34920;&#29616;&#12290;</span></p><p><span>Vein &#37319;&#29992;&#20102;&#19982; SwiftData Model &#31867;&#20284;&#30340;&#22768;&#26126;&#26041;&#24335;&#65292;&#40664;&#35748;&#21516;&#26679;&#26159;&#23646;&#24615;&#39044;&#21152;&#36733;&#12289;&#20851;&#31995;&#24816;&#24615;&#21152;&#36733;&#65307;&#19981;&#21516;&#20043;&#22788;&#22312;&#20110;&#65292;&#32473;&#26576;&#20010;&#23646;&#24615;&#26631;&#27880; </span><code>@LazyField</code><span> &#21518;&#65292;&#23427;&#20250;&#25512;&#36831;&#21040;&#30495;&#27491;&#34987;&#35775;&#38382;&#26102;&#25165;&#21435;&#35835;&#21462;&#12290;&#22240;&#27492;&#22312;&#8220;&#21482;&#26174;&#31034;&#26631;&#39064;&#8221;&#30340;&#21015;&#34920;&#22330;&#26223;&#20013;&#65292;&#26080;&#38656;&#25286;&#20998;&#27169;&#22411;&#20063;&#33021;&#21462;&#24471;&#19981;&#38169;&#30340;&#25104;&#32489;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-04"><span>&#35753;&#33258;&#21160;&#21270;&#33258;&#24049;&#35777;&#26126;&#23427;&#20570;&#23545;&#20102; (Sad But True: Localized App Store Screenshots That Verify Themselves)</span></a></strong></h3><p><span>&#33258;&#21160;&#21270;&#34987;&#36234;&#26469;&#36234;&#22810;&#22320;&#24212;&#29992;&#21040; App &#24320;&#21457;&#30340;&#21508;&#20010;&#29615;&#33410;&#65292;&#20294;&#26377;&#26102;&#23454;&#36341;&#20013;&#30340;&#38590;&#28857;&#24182;&#38750;&#22914;&#20309;&#23454;&#29616;&#33258;&#21160;&#21270;&#65292;&#32780;&#26159;&#22914;&#20309;&#35753;&#23427;&#33258;&#24049;&#35777;&#26126;&#8220;&#25105;&#20570;&#23545;&#20102;&#8221;&#12290;</span></p><p><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> &#22312;&#36890;&#36807;&#33258;&#21160;&#21270;&#26041;&#24335;&#20026; App Store &#29983;&#25104;&#22810;&#35821;&#35328;&#25130;&#22270;&#26102;&#65292;&#21457;&#29616;&#35199;&#29677;&#29273;&#35821;&#25130;&#22270;&#24708;&#24708;&#22238;&#36864;&#25104;&#20102;&#33521;&#25991;&#65292;&#32780;&#25972;&#20010;&#27979;&#35797;&#27969;&#31243;&#20381;&#28982;&#36890;&#36807;&#12290;&#26816;&#26597;&#21518;&#21457;&#29616;&#65292;&#21407;&#22240;&#26469;&#33258; Xcode 27 &#19979; </span><code>-testLanguage</code><span> &#27809;&#26377;&#21487;&#38752;&#22320;&#24212;&#29992;&#21040; App&#12290;Wesley &#38543;&#21518;&#25913;&#29992; </span><code>simctl</code><span> &#35774;&#32622; Simulator &#30340;&#35821;&#35328;&#65292;&#24182;&#36890;&#36807;&#27604;&#36739;&#25130;&#22270;&#30340; SHA-256&#65292;&#33258;&#21160;&#26816;&#26597;&#19981;&#21516;&#35821;&#35328;&#25110;&#19981;&#21516;&#39029;&#38754;&#26159;&#21542;&#24847;&#22806;&#29983;&#25104;&#20102;&#23436;&#20840;&#30456;&#21516;&#30340;&#22270;&#29255;&#12290;</span></p><blockquote><p><span>Wesley &#22522;&#20110;&#25130;&#22270;&#21704;&#24076;&#30340;&#27604;&#36739;&#24605;&#36335;&#21487;&#20197;&#36801;&#31227;&#21040;&#20219;&#20309;&#8220;&#25226;&#35831;&#27714;&#20132;&#32473;&#40657;&#30418;&#12289;&#20877;&#25226;&#20135;&#20986;&#29031;&#21333;&#20840;&#25910;&#8221;&#30340;&#27969;&#31243;&#37324;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-05"><span>Transition or ContentTransition</span></a></strong></h3><p><code>transition</code><span> &#21644; </span><code>contentTransition</code><span> &#21517;&#23383;&#24456;&#20687;&#65292;&#20294;&#35299;&#20915;&#30340;&#26159;&#20004;&#31867;&#19981;&#21516;&#30340;&#38382;&#39064;&#65306;&#21069;&#32773;&#29992;&#20110; View &#34987;&#25554;&#20837;&#25110;&#31227;&#20986;&#35270;&#22270;&#23618;&#32423;&#26102;&#30340;&#21160;&#30011;&#65292;&#21518;&#32773;&#21017;&#29992;&#20110; View &#20173;&#28982;&#23384;&#22312;&#12289;&#21482;&#26159;&#26174;&#31034;&#20869;&#23481;&#21457;&#29983;&#21464;&#21270;&#30340;&#24773;&#20917;&#12290;</span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> &#36890;&#36807;&#26465;&#20214;&#35270;&#22270;&#12289;&#25968;&#23383;&#21464;&#21270;&#21644; SF Symbols &#31561;&#20363;&#23376;&#23545;&#20004;&#32773;&#36827;&#34892;&#20102;&#30452;&#35266;&#27604;&#36739;&#65292;&#24182;&#20171;&#32461;&#20102; </span><code>.numericText</code><span>&#12289;</span><code>.interpolate</code><span>&#12289;</span><code>.symbolEffect</code><span> &#31561;&#24120;&#29992;&#30340;&#20869;&#23481;&#36807;&#28193;&#25928;&#26524;&#12290;</span></p><blockquote><p><span>&#22312; SwiftUI &#20013;&#65292;</span><code>transition</code><span> &#24456;&#26089;&#23601;&#25903;&#25345;&#33258;&#23450;&#20041;&#65292;&#20294;&#36825;&#31181;&#33021;&#21147;&#22987;&#32456;&#27809;&#26377;&#24310;&#20280;&#21040; Sheet&#12289;&#23548;&#33322;&#20999;&#25442;&#31561;&#26356;&#39640;&#23618;&#32423;&#30340;&#22330;&#26223;&#12290;&#36825;&#20123;&#22330;&#26223;&#19982; </span><code>contentTransition</code><span> &#31867;&#20284;&#65292;&#30446;&#21069;&#20173;&#20027;&#35201;&#20381;&#36182;&#31995;&#32479;&#25552;&#20379;&#30340;&#26377;&#38480;&#20960;&#31181;&#36807;&#28193;&#26041;&#24335;&#12290;&#26399;&#24453;&#26410;&#26469; SwiftUI &#33021;&#36827;&#19968;&#27493;&#25171;&#36890;&#36825;&#20123;&#19981;&#21516;&#23618;&#32423;&#30340; transition &#27010;&#24565;&#65292;&#25110;&#32773;&#33267;&#23569;&#20026;&#24320;&#21457;&#32773;&#25552;&#20379;&#26356;&#22810;&#33258;&#23450;&#20041;&#31354;&#38388;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-06"><span>&#29992; Scope &#20026;&#35270;&#22270;&#29366;&#24577;&#21010;&#19968;&#26465;&#36793;&#30028; (Abstracting SwiftUI state with scopes)</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#65292;&#22914;&#26524;&#35270;&#22270;&#20013;&#26377;&#22810;&#20010; </span><code>@State</code><span>&#65292;&#25105;&#20204;&#21487;&#33021;&#20250;&#23558;&#23427;&#20204;&#25277;&#35937;&#21040;&#19968;&#20010; </span><code>@Observable</code><span> &#20013;&#12290;&#20294;&#22914;&#26524;&#35270;&#22270;&#36824;&#20381;&#36182;&#20854;&#20182;&#29615;&#22659;&#20540;&#25110;&#20854;&#20182; </span><code>Observable</code><span> &#23454;&#20363;&#21602;&#65311;&#26159;&#21542;&#26377;&#19968;&#31181;&#26041;&#24335;&#65292;&#21487;&#20197;&#23558;&#26469;&#33258;&#19981;&#21516;&#25968;&#25454;&#28304;&#30340;&#29366;&#24577;&#32452;&#32455;&#21040;&#19968;&#36215;&#65292;&#21516;&#26102;&#20943;&#23569;&#35270;&#22270;&#23545;&#20855;&#20307;&#25968;&#25454;&#28304;&#30340;&#32806;&#21512;&#65311;&#8288;</span><a href="https://twitter.com/auramagi"><span>Mike Apurin</span></a><span> &#25552;&#20986;&#20102; Scope &#24605;&#36335;&#65306;&#36890;&#36807;&#20182;&#24320;&#21457;&#30340; &#8288;</span><a href="https://github.com/auramagi/swift-scoped-state"><span>ScopedState</span></a><span> &#23558;&#22810;&#20010;&#29366;&#24577;&#28304;&#32452;&#32455;&#21040;&#32479;&#19968;&#30340;&#35775;&#38382;&#36793;&#30028;&#20013;&#65292;&#21482;&#21521; View &#26292;&#38706;&#24403;&#21069;&#30028;&#38754;&#30495;&#27491;&#38656;&#35201;&#30340;&#29366;&#24577;&#21644;&#25805;&#20316;&#12290;View &#26080;&#38656;&#20102;&#35299;&#36825;&#20123;&#29366;&#24577;&#23454;&#38469;&#26469;&#33258;&#21738;&#37324;&#65292;&#20063;&#26356;&#23481;&#26131;&#22312; Preview &#21644;&#27979;&#35797;&#20013;&#26367;&#25442;&#25968;&#25454;&#26469;&#28304;&#12290;&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;&#36825;&#24182;&#19981;&#26159;&#35797;&#22270;&#21019;&#24314;&#21478;&#19968;&#22871;&#31867;&#20284; TCA &#25110; MVVM &#30340;&#29366;&#24577;&#31649;&#29702;&#27169;&#22411;&#65292;&#32780;&#26159;&#19968;&#31181;&#20316;&#29992;&#20110; View &#23618;&#32423;&#12289;&#23545;&#29616;&#26377;&#29366;&#24577;&#28304;&#36827;&#34892;&#32452;&#32455;&#21644;&#25277;&#35937;&#30340;&#26041;&#24335;&#12290;</span></p><div><hr></div><h3><strong><span>&#25240;&#21472;&#20043;&#21069;&#65306;iPhone Duo &#36866;&#37197;</span></strong></h3><p><span>iPhone Duo &#30340;&#25512;&#20986;&#35753;&#28040;&#36153;&#32773;&#22312;&#24778;&#21497;&#35774;&#22791;&#24418;&#24577;&#21464;&#21270;&#30340;&#21516;&#26102;&#65292;&#20063;&#32473;&#24320;&#21457;&#32773;&#24102;&#26469;&#20102;&#26032;&#30340;&#25361;&#25112;&#65306;&#22914;&#20309;&#21033;&#29992;&#26356;&#22823;&#30340;&#26174;&#31034;&#31354;&#38388;&#65292;&#22914;&#20309;&#35753;&#29616;&#26377;&#24067;&#23616;&#36866;&#24212;&#19981;&#21516;&#30340;&#35774;&#22791;&#24418;&#24577;&#65292;&#20197;&#21450;&#22914;&#20309;&#21033;&#29992;&#25240;&#21472;&#12289;&#22810;&#26174;&#31034;&#21306;&#22495;&#31561;&#26032;&#30340;&#20132;&#20114;&#33021;&#21147;&#12290;&#19978;&#21608;&#65292;&#19981;&#23569;&#20869;&#23481;&#21019;&#20316;&#32773;&#37117;&#20174;&#19981;&#21516;&#35282;&#24230;&#32473;&#20986;&#20102;&#33258;&#24049;&#30340;&#24314;&#35758;&#12290;</span></p><ul><li><p><span>&#33529;&#26524;&#22312;&#21457;&#24067;&#24403;&#22825;&#25918;&#20986;&#20102;&#20845;&#20010; Tech Talk&#65306;</span><a href="https://developer.apple.com/videos/play/tech-talks/111466/"><span>Design for iPhone Duo</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111461/"><span>Prepare your app</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111462/"><span>Raise the bar</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111463/"><span>Strike a pose with adaptive layouts</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111464/"><span>Leverage multiple displays and scenes</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111465/"><span>Build a great camera experience</span></a><span>&#65292;&#24182;&#22312; HIG &#20013;&#22686;&#21152;&#20102; </span><a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo"><span>Designing for iPhone Duo</span></a><span> &#19968;&#39029;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-07"><span>Florian Schweizer</span></a><span> &#24378;&#35843;&#8220;&#19981;&#35201;&#19982;&#26694;&#26550;&#23545;&#25239;&#8221;&#65306;&#19981;&#35201;&#20174;&#21028;&#26029;&#8220;&#26159;&#19981;&#26159; iPhone Duo&#8221;&#24320;&#22987;&#65292;&#32780;&#24212;&#35813;&#38382;&#8220;&#36825;&#20010;&#35270;&#22270;&#25343;&#21040;&#20102;&#22810;&#23569;&#31354;&#8221;&#12290;&#20182;&#36824;&#23558;&#36825;&#20123;&#21407;&#21017;&#20197;&#21450; Duo &#30340;&#26032; API&#12289;Apple &#24320;&#21457;&#32773;&#36164;&#26009;&#25972;&#29702;&#25104;&#20102;&#19968;&#20010; &#8288;</span><a href="https://github.com/FloWritesCode/fwc-swiftui-skills/tree/main/skills/swiftui-iphone-duo"><span>SwiftUI iPhone Duo Skill</span></a><span>&#65292;&#20379; Coding Agent &#22312;&#36866;&#37197;&#29616;&#26377; App &#26102;&#20351;&#29992;&#12290;</span></p></li></ul><ul><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-08"><span>Lee young-jun</span></a><span> &#20174;&#29616;&#26377; App &#30340;&#23454;&#38469;&#36866;&#37197;&#20986;&#21457;&#65292;&#36890;&#36807; </span><code>NavigationSplitView</code><span>&#12289;</span><code>sidebarAdaptable</code><span>&#12289;Device Hub &#30340; Resizing Mode &#31561;&#26041;&#24335;&#65292;&#25552;&#21069;&#26816;&#26597;&#21644;&#25913;&#21892; App &#22312; iPhone Duo &#19981;&#21516;&#26174;&#31034;&#24418;&#24577;&#19979;&#30340;&#34920;&#29616;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-09"><span>Sagar Unagar</span></a><span> &#26681;&#25454; &#8288;Apple &#26368;&#26032;&#30340; HIG &#21644;&#24320;&#21457;&#32773;&#36164;&#26009;&#65292;&#26803;&#29702;&#20102; iPhone Duo &#22312;&#33258;&#36866;&#24212;&#24067;&#23616;&#12289;&#31995;&#32479;&#25511;&#20214;&#12289;&#25240;&#21472;&#21306;&#22495;&#20197;&#21450;&#19981;&#21516;&#26174;&#31034;&#24418;&#24577;&#19979;&#30340;&#20027;&#35201;&#35774;&#35745;&#21407;&#21017;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-10"><span>Jordan Morgan</span></a><span> &#24635;&#32467;&#20102;&#24320;&#21457;&#32773;&#39318;&#20808;&#38656;&#35201;&#20851;&#27880;&#30340;&#24067;&#23616;&#12289;&#31995;&#32479;&#26639;&#12289;safe area&#12289;&#30456;&#26426;&#20197;&#21450;&#22810;&#26174;&#31034;&#21306;&#22495;&#31561;&#21464;&#21270;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-11"><span>Artem Mirzabekian</span></a><span> &#20171;&#32461;&#20102;&#26032;&#30340; </span><code>ArrangementView</code><span>&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#25551;&#36848;&#20004;&#32452;&#30456;&#20851;&#20869;&#23481;&#20043;&#38388;&#30340;&#20851;&#31995;&#65292;&#35753; SwiftUI &#26681;&#25454;&#21487;&#29992;&#31354;&#38388;&#21644;&#25240;&#21472;&#21306;&#22495;&#33258;&#21160;&#36873;&#25321;&#21512;&#36866;&#30340;&#24067;&#23616;&#26041;&#24335;&#12290;</span></p></li></ul><blockquote><p><span>&#19978;&#38754;&#20171;&#32461;&#30340;&#21151;&#33021;&#19981;&#23569;&#37117;&#21482;&#23384;&#22312;&#20110; Xcode 27.1 &#20013;&#65292;&#24819;&#23436;&#25972;&#20307;&#39564;&#36824;&#38656;&#35201;&#19968;&#27573;&#26102;&#38388;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-12"><span>SwiftMusic&#65306;&#29992; Swift &#22768;&#26126;&#38899;&#20048;</span></a></strong></h3><p><a href="https://x.com/1amageek"><span>Norikazu Muramoto</span></a><span> &#24320;&#21457;&#30340; SwiftMusic &#26159;&#19968;&#22871;&#38754;&#21521; Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#30340;&#22768;&#26126;&#24335;&#38899;&#20048;&#21019;&#20316;&#26694;&#26550;&#12290;&#23427;&#20511;&#37492;&#20102; SwiftUI &#30340;&#35774;&#35745;&#29702;&#24565;&#65292;&#23558; </span><code>Music</code><span>&#12289;</span><code>Sound</code><span>&#12289;</span><code>body</code><span>&#12289;Result Builder &#21644; Modifier &#31561;&#29087;&#24713;&#30340; Swift &#34920;&#36798;&#26041;&#24335;&#24102;&#20837;&#38899;&#20048;&#21019;&#20316;&#65292;&#35753;&#33410;&#22863;&#12289;&#26059;&#24459;&#12289;&#21644;&#22768;&#12289;&#38899;&#33394;&#12289;&#25928;&#26524;&#22120;&#21644;&#28151;&#38899;&#20851;&#31995;&#37117;&#21487;&#20197;&#36890;&#36807;&#32452;&#21512;&#20195;&#30721;&#26469;&#25551;&#36848;&#12290;</span></p><p><span>&#20363;&#22914;&#65292;&#40723;&#28857;&#12289;&#36125;&#26031;&#21644;&#21512;&#25104;&#22120;&#21487;&#20197;&#30452;&#25509;&#20889;&#25104;&#20855;&#26377;&#38899;&#20048;&#21547;&#20041;&#30340; Swift &#20195;&#30721;&#65306;</span></p><pre><code><span>struct Session: Music {</span>
<span>      var body: some Sound {</span>
<span>          Track(&#8221;Drums&#8221;) {</span>
<span>              Sample(&#8221;kick&#8221;)</span>
<span>                  .rhythm(&#8221;x ~ x ~&#8221;)</span>
<span>          }</span>
<span>&#8203;</span>
<span>          Track(&#8221;Bass&#8221;) {</span>
<span>              Synthesizer(.saw)</span>
<span>                  .notes(&#8221;C2 ~ Eb2 G2&#8221;)</span>
<span>                  .gain(0.3)</span>
<span>          }</span>
<span>      }</span>
<span>  }</span></code></pre><p><span>SwiftMusic &#26412;&#36523;&#24182;&#19981;&#21457;&#22768;&#65306;&#23427;&#21482;&#25226;&#22768;&#26126;&#32534;&#35793;&#25104;&#33410;&#25293;&#22495;&#20107;&#20214;&#19982;&#28210;&#26579;&#35745;&#21010;&#65292;&#26082;&#19981;&#25171;&#24320;&#38899;&#39057;&#35774;&#22791;&#65292;&#20063;&#19981;&#32472;&#21046;&#32534;&#36753;&#22120;&#65292;&#23454;&#38469;&#30340;&#38899;&#39057;&#28210;&#26579;&#30001;&#23487;&#20027;&#36127;&#36131;&#8212;&#8212;&#20316;&#32773;&#21478;&#22806;&#25552;&#20379;&#20102; macOS &#31471;&#30340;&#23454;&#26102;&#32534;&#36753;&#22120; </span><a href="https://github.com/1amageek/MusicPlaygournd"><span>MusicPlaygournd</span></a><span> &#26469;&#25215;&#25285;&#36825;&#37096;&#20998;&#24037;&#20316;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-13"><span>Homebrew 7&#65306;&#19968;&#27425;&#21578;&#21035; Intel &#30340;&#22823;&#29256;&#26412;</span></a></strong></h3><p><span>Homebrew 7.0.0 &#27491;&#24335;&#21457;&#24067;&#65292;&#38500;&#20102;&#22810;&#39033;&#21151;&#33021;&#21644;&#20869;&#37096;&#23454;&#29616;&#35843;&#25972;&#65292;&#26412;&#27425;&#22823;&#29256;&#26412;&#20063;&#24102;&#26469;&#20102;&#20540;&#24471;&#20851;&#27880;&#30340;&#20860;&#23481;&#24615;&#21464;&#21270;&#12290;&#30446;&#21069; Apple Silicon Mac &#19978;&#30340; macOS 15&#8211;27 &#23646;&#20110;&#23436;&#25972;&#25903;&#25345;&#33539;&#22260;&#65292;&#32780; Intel Mac &#24050;&#20840;&#37096;&#38477;&#20026; Tier 3&#65292;&#19981;&#20877;&#33719;&#24471;&#23436;&#25972; CI &#25903;&#25345;&#21644;&#26032;&#30340; bottles&#65292;&#24182;&#35745;&#21010;&#22312; 2027 &#24180; 9 &#26376;&#25110;&#20043;&#21518;&#24443;&#24213;&#20572;&#27490;&#25903;&#25345;&#12290;&#20173;&#22312; Intel Mac &#25110;&#36739;&#26087; macOS &#19978;&#20351;&#29992; Homebrew &#30340;&#24320;&#21457;&#32773;&#38656;&#35201;&#29305;&#21035;&#30041;&#24847;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #152]]></title><description><![CDATA[When the Mac mini&#8217;s Price Is No Longer Mini]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 07 Sep 2026 12:03:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6KxT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6KxT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6KxT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:258674,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/214512423?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6KxT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@amanz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Amanz</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-an-apple-mouse-and-keyboard-oiWNsvv_oAI?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When the Mac mini&#8217;s Price Is No Longer Mini</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-152/">Read on web &#8594;</a></p><p><span>Late last month, Apple released the new Mac mini and Mac Studio. Alongside the impressive performance upgrades, the noticeably higher prices were just as striking. Rising memory and storage costs are undoubtedly a major factor, but in the AI era, developers&#8217; hardware needs are also quietly changing. More memory and more storage keep raising our idea of what counts as a &#8220;good enough&#8221; configuration&#8212;and pushing the price we actually pay even higher.</span></p><p><span>Over the past few months, one of the biggest annoyances in my development work has been the constant noise of my MacBook Pro&#8217;s fans. For years, I would only really notice them under a handful of heavy workloads. But in the age of AI agents, having the fans running has become almost routine. Limited by the space inside a laptop and the size of its fans, the noise under sustained load also tends to be more noticeable&#8212;and more irritating&#8212;than on a desktop machine like the Mac mini.</span></p><p><span>At the same time, I&#8217;ve realized that the MacBook no longer feels as indispensable to my workflow as it once did. Unless I have a specific need, a phone and a tablet are already enough for quite a few Vibe Coding scenarios on short trips. Even when I do need a laptop, a lighter and less powerful model would probably be more than sufficient. So I&#8217;ve started seriously considering moving my primary development environment from a MacBook Pro to a Mac mini or Mac Studio.</span></p><p><span>That brings up another problem: for a primary development machine, memory capacity is a hard requirement. I have almost no need to run LLMs locally, but if I&#8217;m upgrading my computer, the new machine needs to offer meaningfully more than the 64GB I already have for the upgrade to feel worthwhile. That essentially rules out the M5 Pro Mac mini, leaving me with the M5 Max and M5 Ultra Mac Studio.</span></p><p><span>Interestingly, the next memory tier above 64GB is 128GB on one and 96GB on the other, yet the final prices are remarkably close. One gives me more memory; the other, a more powerful chip. I&#8217;m not usually someone who struggles to make a choice, but this one has genuinely left me undecided.</span></p><p><span>Meanwhile, OpenClaw&#8217;s popularity has drawn the attention of many consumers who previously had little interest in the Mac mini. OpenAI has also reportedly purchased tens of thousands of Mac minis and Mac Studios for reinforcement learning and training computer-use agents. AI-driven demand at one point grew far faster than Apple had anticipated. Combined with pressure on memory supply and advanced chip manufacturing capacity, this has kept the Mac mini and Mac Studio in short supply over the past few months. Even with the new generation now available, getting the exact configuration you want quickly is still not necessarily easy.</span></p><p><span>The productivity gains brought by AI may not yet be fully visible across society, but its appetite for compute, memory, and storage resources is already showing up in the hardware market. From components to complete systems, a wide range of consumer hardware is facing new pricing pressure. The old upgrade cycle&#8212;waiting a few years and spending roughly the same amount for a substantially more powerful computer&#8212;seems increasingly difficult to sustain, at least for now.</span></p><p><span>But there&#8217;s another side to the story: we can&#8217;t blame everything on rising prices. While AI is pushing hardware costs upward, it is also changing how we develop software and quietly raising our definition of what counts as a &#8220;good enough computer.&#8221; Hardware has become more expensive, but we&#8217;ve also started asking more of it.</span></p><p><span>Hopefully, one day we&#8217;ll get back to a time when buying a Mac mini doesn&#8217;t require quite so much mental preparation.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-151/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/swiftdata-optimization-starts-with-modeling/?utm_source=fatbobman%20weekly%20issue%20152&amp;utm_medium=web"><span>SwiftData: Optimization Starts with Modeling</span></a></strong></h3><p><span>Once the dataset grows large, SwiftData lists start to lag. This is one of the performance complaints I&#8217;ve heard most often over the past few years. Developers&#8217; first instinct is usually to blame SwiftUI&#8217;s </span><code>List</code><span>. It certainly bears some responsibility, but it isn&#8217;t the main culprit. A closer look reveals that long loading times aren&#8217;t the only thing dragging down performance&#8212;massive memory consumption is just as important. In this article, I&#8217;ll explore why these problems arise in SwiftData and why optimization should start with data modeling.</span></p><blockquote><p><span>Some capabilities that appear to be missing from SwiftData may actually have been left out intentionally, reducing the learning curve by exposing fewer APIs and abstraction layers. Therefore, when optimizing SwiftData applications, it&#8217;s also worth letting go of some habits carried over from the Core Data era.</span></p></blockquote><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-01"><span>The End of Swift Talk</span></a></strong></h3><p><span>After ten years and 500 episodes, </span><a href="https://x.com/chriseidhof"><span>Chris Eidhof</span></a><span> and </span><a href="https://x.com/floriankugler"><span>Florian Kugler</span></a><span> have announced the end of Swift Talk. Since its launch in June 2016, Swift Talk has accompanied Swift through nearly its entire journey toward maturity, while also witnessing SwiftUI grow from its introduction into a core UI framework for Apple platform development. Through a long series of deep and highly experimental episodes, the two explored Swift, SwiftUI, layout, animation, concurrency, and many lower-level topics rarely covered in conventional tutorials. They hope to make the complete archive of more than 500 episodes available to the community by the end of this year.</span></p><p><span>For me, objc.io and Swift Talk have always occupied a very special place in the Swift community. Chris and Florian were rarely satisfied with simply telling developers how an API &#8220;should be used.&#8221; Instead, they would experiment, refactor, and sometimes even reimplement things to understand why a framework works the way it does. This approach to exploration has influenced many Swift developers, myself included. Thank you, Chris and Florian, for the time, knowledge, and curiosity you&#8217;ve contributed to the Swift community over all these years, and for the invaluable archive Swift Talk leaves behind.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-02"><span>What&#8217;s new in Swift: August 2026 Edition</span></a></strong></h3><p><span>Swift has published its August ecosystem update, curated by </span><a href="https://github.com/sliemeobn/"><span>Simon Leeb</span></a><span> and </span><a href="https://www.linkedin.com/in/davelester-dev/"><span>Dave Lester</span></a><span>, covering noteworthy community projects, package updates, and Swift Evolution developments. What interests me most is Swift&#8217;s progress on the Web: Simon Leeb demonstrated a </span><a href="https://cloudflare-worker.examples.elementary.codes/"><span>Full-Stack Swift on Cloudflare Demo</span></a><span>, with Swift running in the browser through ElementaryUI and WebAssembly, a backend running on an edge worker, and message types shared between the two sides. From Embedded Swift and Wasm to an increasingly capable cross-platform toolchain, Swift continues to expand its reach beyond Apple platforms.</span></p><p><span>At the language level, the recently accepted </span><a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0516-borrowing-sequence.md"><span>Iterable</span></a><span> is also worth watching. </span><code>Sequence</code><span> produces independent element values one by one during iteration, but this model doesn&#8217;t work for data structures such as </span><code>Span</code><span> and </span><code>InlineArray</code><span> that may contain non-copyable elements. </span><code>Iterable</code><span> allows elements to be borrowed rather than copied during iteration, giving these data structures a natural way to be traversed as well. It may look like just another iteration abstraction, but it is also another sign of Swift&#8217;s ownership capabilities gradually moving from the language&#8217;s lower levels into everyday API design.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-03"><span>OpenSwiftUI on ESP32-C3</span></a></strong></h3><p><span>The Swift update above showed how Swift continues to push beyond the boundaries of Apple platforms, and a recent experiment by OpenSwiftUI developer </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> provides a very tangible example of that trend. After receiving an </span><a href="https://ai-passport.folotoy.cn/"><span>ESP32-C3 development device</span></a><span> from TraeAI, Kyle completed his first Embedded Swift project: deploying an embedded version of OpenSwiftUI to this RISC-V-based microcontroller. On its 240 &#215; 320 LCD, he built interfaces using familiar APIs such as </span><code>View</code><span>, </span><code>@ViewBuilder</code><span>, </span><code>Text</code><span>, </span><code>Image</code><span>, </span><code>VStack</code><span>, </span><code>HStack</code><span>, and </span><code>ZStack</code><span>. Even </span><code>@State</code><span> can respond to physical button input and trigger UI updates.</span></p><p><span>The experiment uses Embedded Swift to compile native RISC-V code, with OpenSwiftUI handling view composition and layout before passing drawing through a thin rendering boundary to LVGL and the underlying hardware. In other words, a lean but complete UI pipeline has been established, from declarative views and layout calculation to state updates and final pixel output.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-04"><span>Multiplatform Swift, with C++ dependencies via XCFramework, apt and vcpkg</span></a></strong></h3><p><span>Whether a Swift application can truly become cross-platform often depends on whether its underlying C/C++ dependencies can make the journey as well. </span><a href="https://www.linkedin.com/in/harald-achitz/"><span>Harald Achitz</span></a><span> uses his own ZeroMQ Swift bindings as an example to show how a Swift/C++ project targeting macOS, Linux, and Windows can organize its native dependencies: XCFrameworks on Apple platforms, system packages on Linux, and vcpkg to install ZeroMQ on Windows.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-05"><span>Connecting two iOS simulators over BLE</span></a></strong></h3><p><span>CoreBluetooth is completely unavailable in the iOS Simulator, which has long made BLE app development and testing dependent on physical devices. While developing </span><a href="https://github.com/kylebrowning/BLESwift"><span>BLESwift 2.0</span></a><span>, </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> took a different approach: instead of calling CoreBluetooth, the central and peripheral devices in the Simulator forward their operations over localhost TCP to </span><code>bleswift-provider</code><span> running on the Mac, which creates a &#8220;virtual radio.&#8221; This allows two Simulators to discover, connect to, read from, write to, and receive notifications from each other much like two real BLE devices. A passthrough mode can even use the Mac&#8217;s Bluetooth hardware to communicate with real BLE devices.</span></p><blockquote><p><span>What interests me more than BLE itself is the testing pattern behind this approach: when the Simulator lacks a particular system or hardware capability, instead of scattering mocks throughout the app, we can establish a replaceable backend between system capabilities and business logic, then use a proxy process on the Mac to recreate a controllable external world. This design not only addresses missing system or hardware capabilities in the Simulator, but also makes features that once depended heavily on real-world environments much easier to bring into automated testing and CI.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-06"><span>Reorder all the things in SwiftUI</span></a></strong></h3><p><span>SwiftUI has long lacked a general-purpose API for drag-to-reorder interactions in arbitrary containers, a limitation that was finally addressed after WWDC 2026. </span><a href="https://x.com/SwiftyAlex"><span>Alexander Logan</span></a><span> introduces SwiftUI&#8217;s new reordering APIs. With APIs such as </span><code>reorderable</code><span> and </span><code>reorderableContainer</code><span>, developers can directly declare which content can be reordered and its associated data model. Reordering is no longer limited to </span><code>List</code><span>, nor do developers need to manage drop positions and data updates themselves through </span><code>DropDelegate</code><span>. More importantly, the new APIs provide a higher-level interaction semantic, separating &#8220;reordering&#8221; from drag and drop as a specific implementation mechanism. Developers describe the intent that &#8220;this content can be reordered,&#8221; while the system can take greater responsibility for whether that interaction is performed with a mouse, touch, or another input method.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-07"><span>Building a sunburst diagram in Swift Charts</span></a></strong></h3><p><span>A Sunburst Diagram is a chart that uses concentric rings to represent hierarchical data&#8212;for example, moving from &#8220;Work&#8221; to &#8220;Development&#8221; and then to a specific project, with each outward ring representing a deeper level of detail. </span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to use Swift Charts&#8217; </span><code>SectorMark</code><span> to start with a regular pie chart and gradually build a three-level sunburst diagram. The implementation also nicely demonstrates the flexibility of Swift Charts: when the framework doesn&#8217;t directly provide a particular chart type, Marks such as </span><code>SectorMark</code><span> can be treated as lower-level visualization primitives, allowing more complex charts to be constructed by calculating angular ranges and data mappings manually.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-08"><span>CoreDataBrowser: Quickly Inspect Local Data in the Simulator</span></a></strong></h3><p><span>When debugging Core Data or SwiftData apps, you typically need to locate the relevant data files buried deep within the Simulator&#8217;s directory hierarchy, then open them in a SQLite manager to inspect the data. CoreDataBrowser, developed by </span><a href="https://www.linkedin.com/in/csaba-turdesan-880182251/"><span>Csaba Turdesan</span></a><span>, aims to simplify this process: after selecting the currently running Simulator, it automatically locates Core Data, SwiftData, and UserDefaults data sources in app containers and presents them together in a native macOS interface.</span></p><p><span>CoreDataBrowser supports browsing tables and records, searching and highlighting matches, and attempting to decode certain binary data (BLOBs) as NSKeyedArchive, JSON, Property List, or UTF-8 text. The tool is tiny (2.5 MB), and its </span><a href="https://github.com/kyletaylor94/CoreDataBrowser"><span>source code is publicly available</span></a><span>.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403; Mac mini &#30340;&#20215;&#26684;&#19981;&#20877; mini</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-152/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#26376;&#24213;&#65292;&#33529;&#26524;&#21457;&#24067;&#20102;&#26032;&#30340; Mac mini &#21644; Mac Studio&#12290;&#38500;&#20102;&#24378;&#24717;&#30340;&#24615;&#33021;&#26356;&#26032;&#65292;&#26126;&#26174;&#19978;&#28072;&#30340;&#20215;&#26684;&#21516;&#26679;&#32473;&#20154;&#24102;&#26469;&#20102;&#19981;&#23567;&#30340;&#38663;&#25788;&#12290;&#20869;&#23384;&#19982;&#23384;&#20648;&#25104;&#26412;&#19978;&#28072;&#26080;&#30097;&#26159;&#26412;&#36718;&#28072;&#20215;&#30340;&#37325;&#35201;&#21407;&#22240;&#65292;&#20294;&#22312; AI &#26102;&#20195;&#65292;&#24320;&#21457;&#32773;&#23545;&#30828;&#20214;&#30340;&#38656;&#27714;&#20063;&#22312;&#24708;&#28982;&#21457;&#29983;&#21464;&#21270;&#12290;&#26356;&#22823;&#30340;&#20869;&#23384;&#12289;&#26356;&#39640;&#30340;&#23384;&#20648;&#23481;&#37327;&#65292;&#19981;&#26029;&#25512;&#39640;&#25105;&#20204;&#24515;&#30446;&#20013;&#8220;&#22815;&#29992;&#37197;&#32622;&#8221;&#30340;&#26631;&#20934;&#65292;&#26368;&#32456;&#20063;&#35753;&#23454;&#38469;&#36141;&#20080;&#20215;&#26684;&#21464;&#24471;&#26356;&#21152;&#22840;&#24352;&#12290;</span></p><p><span>&#36807;&#21435;&#20960;&#20010;&#26376;&#65292;&#24320;&#21457;&#20013;&#26368;&#35753;&#25105;&#22836;&#30171;&#30340;&#19968;&#20214;&#20107;&#65292;&#26159; MacBook Pro &#39118;&#25159;&#25345;&#32493;&#36716;&#21160;&#24102;&#26469;&#30340;&#22122;&#38899;&#12290;&#36807;&#21435;&#22810;&#24180;&#30340;&#20351;&#29992;&#20013;&#65292;&#21482;&#26377;&#22312;&#23569;&#25968;&#39640;&#36127;&#36733;&#22330;&#26223;&#19979;&#65292;&#25105;&#25165;&#20250;&#26126;&#26174;&#24847;&#35782;&#21040;&#39118;&#25159;&#30340;&#23384;&#22312;&#12290;&#20294;&#21040;&#20102; AI Agent &#26102;&#20195;&#65292;&#39118;&#25159;&#24120;&#36716;&#20960;&#20046;&#25104;&#20102;&#23478;&#24120;&#20415;&#39277;&#12290;&#21463;&#38480;&#20110;&#26426;&#36523;&#31354;&#38388;&#21644;&#39118;&#25159;&#23610;&#23544;&#65292;&#31508;&#35760;&#26412;&#22312;&#25345;&#32493;&#39640;&#36127;&#36733;&#19979;&#20135;&#29983;&#30340;&#22122;&#38899;&#65292;&#24448;&#24448;&#20063;&#27604; Mac mini &#36825;&#31867;&#26700;&#38754;&#35774;&#22791;&#26356;&#23481;&#26131;&#35753;&#20154;&#24863;&#21040;&#19981;&#36866;&#12290;</span></p><p><span>&#19982;&#27492;&#21516;&#26102;&#65292;&#25105;&#21457;&#29616; MacBook &#22312;&#33258;&#24049;&#30340;&#24037;&#20316;&#27969;&#20013;&#20284;&#20046;&#20063;&#27809;&#26377;&#20197;&#21069;&#37027;&#20040;&#19981;&#21487;&#26367;&#20195;&#20102;&#12290;&#38500;&#38750;&#26377;&#29305;&#27530;&#38656;&#35201;&#65292;&#30701;&#36884;&#20986;&#24046;&#26102;&#65292;&#25163;&#26426;&#21644;&#24179;&#26495;&#24050;&#32463;&#36275;&#20197;&#24212;&#20184;&#19981;&#23569; Vibe Coding &#22330;&#26223;&#12290;&#21363;&#20415;&#20173;&#28982;&#38656;&#35201;&#19968;&#21488;&#31508;&#35760;&#26412;&#65292;&#19968;&#21488;&#26356;&#36731;&#12289;&#37197;&#32622;&#26356;&#20302;&#30340;&#35774;&#22791;&#20284;&#20046;&#20063;&#23436;&#20840;&#22815;&#29992;&#12290;&#22240;&#27492;&#65292;&#25105;&#24320;&#22987;&#35748;&#30495;&#32771;&#34385;&#25226;&#20027;&#21147;&#24320;&#21457;&#35774;&#22791;&#20174; MacBook Pro &#36716;&#31227;&#21040; Mac mini &#25110; Mac Studio &#19978;&#12290;</span></p><p><span>&#38382;&#39064;&#38543;&#20043;&#32780;&#26469;&#65306;&#20316;&#20026;&#20027;&#21147;&#24320;&#21457;&#35774;&#22791;&#65292;&#20869;&#23384;&#23481;&#37327;&#24517;&#28982;&#26159;&#19968;&#36947;&#30828;&#38376;&#27099;&#12290;&#23613;&#31649;&#25105;&#20960;&#20046;&#27809;&#26377;&#36816;&#34892;&#26412;&#22320; LLM &#30340;&#38656;&#27714;&#65292;&#20294;&#26082;&#28982;&#26159;&#19968;&#27425;&#35774;&#22791;&#26356;&#26032;&#65292;&#26032;&#26426;&#22120;&#30340;&#20869;&#23384;&#33267;&#23569;&#24212;&#35813;&#26126;&#26174;&#39640;&#20110;&#24403;&#21069;&#30340; 64GB&#65292;&#25165;&#33021;&#35753;&#25105;&#24863;&#21463;&#21040;&#36275;&#22815;&#30340;&#21319;&#32423;&#20215;&#20540;&#12290;&#22914;&#27492;&#19968;&#26469;&#65292;&#37319;&#29992; M6 &#25110; M5 Pro &#30340; Mac mini &#22522;&#26412;&#23601;&#34987;&#25490;&#38500;&#20102;&#65292;&#21097;&#19979;&#30340;&#36873;&#25321;&#21482;&#26377; M5 Max &#21644; M5 Ultra &#30340; Mac Studio&#12290;</span></p><p><span>&#26377;&#36259;&#30340;&#26159;&#65292;&#20004;&#27454;&#26426;&#22411;&#22312; 64GB &#20043;&#19978;&#30340;&#19979;&#19968;&#26723;&#20869;&#23384;&#20998;&#21035;&#26159; 128GB &#21644; 96GB&#65292;&#32780;&#26368;&#32456;&#20215;&#26684;&#21364;&#30456;&#24046;&#26080;&#20960;&#12290;&#19968;&#20010;&#32473;&#26356;&#22810;&#20869;&#23384;&#65292;&#19968;&#20010;&#32473;&#26356;&#24378;&#33455;&#29255;&#12290;&#21363;&#20415;&#25105;&#24179;&#26102;&#24182;&#19981;&#31639;&#26377;&#36873;&#25321;&#22256;&#38590;&#65292;&#36825;&#27425;&#20063;&#30830;&#23454;&#26377;&#20123;&#29359;&#38590;&#12290;</span></p><p><span>&#19982;&#27492;&#21516;&#26102;&#65292;OpenClaw &#30340;&#39118;&#34892;&#35753;&#19981;&#23569;&#21407;&#26412;&#24182;&#19981;&#20851;&#27880; Mac mini &#30340;&#28040;&#36153;&#32773;&#24320;&#22987;&#23558;&#30446;&#20809;&#25237;&#21521;&#36825;&#21488;&#23567;&#26426;&#22120;&#12290;&#25454;&#25253;&#36947;&#65292;OpenAI &#20063;&#37319;&#36141;&#20102;&#25968;&#19975;&#21488; Mac mini &#21644; Mac Studio&#65292;&#29992;&#20110;&#24378;&#21270;&#23398;&#20064;&#21644; Computer-use Agent &#30340;&#35757;&#32451;&#12290;AI &#24102;&#26469;&#30340;&#38656;&#27714;&#22686;&#38271;&#19968;&#24230;&#36828;&#36229;&#33529;&#26524;&#30340;&#39044;&#26399;&#65292;&#20877;&#21152;&#19978;&#20869;&#23384;&#20379;&#24212;&#21644;&#20808;&#36827;&#21046;&#31243;&#20135;&#33021;&#30340;&#21387;&#21147;&#65292;&#35753; Mac mini &#21644; Mac Studio &#22312;&#36807;&#21435;&#20960;&#20010;&#26376;&#19968;&#30452;&#22788;&#20110;&#20379;&#19981;&#24212;&#27714;&#30340;&#29366;&#24577;&#12290;&#26032;&#19968;&#20195;&#20135;&#21697;&#21457;&#24067;&#20043;&#21518;&#65292;&#24819;&#35201;&#23613;&#24555;&#25343;&#21040;&#33258;&#24049;&#24515;&#20202;&#30340;&#37197;&#32622;&#65292;&#20381;&#28982;&#19981;&#26159;&#19968;&#20214;&#23481;&#26131;&#30340;&#20107;&#12290;</span></p><p><span>AI &#24102;&#26469;&#30340;&#25928;&#29575;&#25552;&#21319;&#25110;&#35768;&#36824;&#27809;&#26377;&#22312;&#25972;&#20010;&#31038;&#20250;&#20013;&#20805;&#20998;&#26174;&#29616;&#65292;&#20294;&#23427;&#23545;&#31639;&#21147;&#12289;&#20869;&#23384;&#21644;&#23384;&#20648;&#36164;&#28304;&#30340;&#20105;&#22842;&#65292;&#24050;&#32463;&#29575;&#20808;&#21453;&#26144;&#21040;&#20102;&#30828;&#20214;&#24066;&#22330;&#12290;&#20174;&#38646;&#37096;&#20214;&#21040;&#25972;&#26426;&#65292;&#22823;&#37327;&#28040;&#36153;&#32423;&#30828;&#20214;&#37117;&#22312;&#25215;&#21463;&#26032;&#30340;&#20215;&#26684;&#21387;&#21147;&#12290;&#36807;&#21435;&#37027;&#31181;&#38548;&#20960;&#24180;&#29992;&#24046;&#19981;&#22810;&#30340;&#38065;&#65292;&#23601;&#33021;&#20080;&#21040;&#19968;&#21488;&#26126;&#26174;&#26356;&#24378;&#30005;&#33041;&#30340;&#26356;&#26032;&#33410;&#22863;&#65292;&#33267;&#23569;&#22312;&#29616;&#38454;&#27573;&#20284;&#20046;&#36234;&#26469;&#36234;&#38590;&#32500;&#25345;&#20102;&#12290;</span></p><p><span>&#20294;&#26356;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#25105;&#20204;&#21448;&#19981;&#33021;&#25226;&#36825;&#19968;&#20999;&#23436;&#20840;&#24402;&#21646;&#20110;&#28072;&#20215;&#12290;AI &#22312;&#25512;&#39640;&#30828;&#20214;&#25104;&#26412;&#30340;&#21516;&#26102;&#65292;&#20063;&#25913;&#21464;&#20102;&#25105;&#20204;&#30340;&#24320;&#21457;&#26041;&#24335;&#65292;&#24182;&#24708;&#24708;&#25260;&#39640;&#20102;&#25105;&#20204;&#23545;&#19968;&#21488;&#8220;&#22815;&#29992;&#30005;&#33041;&#8221;&#30340;&#23450;&#20041;&#12290;&#30828;&#20214;&#21464;&#36149;&#20102;&#65292;&#25105;&#20204;&#24819;&#35201;&#30340;&#20063;&#26356;&#22810;&#20102;&#12290;</span></p><p><span>&#24076;&#26395;&#26410;&#26469;&#26576;&#19968;&#22825;&#65292;&#25105;&#20204;&#36824;&#33021;&#25214;&#22238;&#37027;&#20010;&#19981;&#29992;&#20570;&#22826;&#22810;&#24515;&#29702;&#24314;&#35774;&#65292;&#23601;&#33021;&#36731;&#26494;&#36873;&#36141;&#19968;&#21488; Mac mini &#30340;&#26102;&#20195;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-151/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/swiftdata-optimization-starts-with-modeling/?utm_source=fatbobman%20weekly%20issue%20152&amp;utm_medium=web"><span>SwiftData&#65306;&#20248;&#21270;&#20174;&#24314;&#27169;&#24320;&#22987;</span></a></strong></h3><p><span>&#25968;&#25454;&#38598;&#19968;&#22823;&#65292;SwiftData &#30340;&#21015;&#34920;&#23601;&#24320;&#22987;&#21345;&#12290;&#36825;&#26159;&#36825;&#20960;&#24180;&#37324;&#25105;&#21548;&#21040;&#26368;&#22810;&#30340;&#24615;&#33021;&#25265;&#24616;&#12290;&#24320;&#21457;&#32773;&#30340;&#31532;&#19968;&#21453;&#24212;&#36890;&#24120;&#20250;&#25351;&#21521; SwiftUI &#30340; </span><code>List</code><span>&#12290;&#23427;&#30830;&#23454;&#26377;&#36131;&#20219;&#65292;&#20294;&#24182;&#38750;&#26368;&#20027;&#35201;&#30340;&#38382;&#39064;&#12290;&#36827;&#19968;&#27493;&#20998;&#26512;&#20250;&#21457;&#29616;&#65292;&#30495;&#27491;&#25302;&#22446;&#24615;&#33021;&#30340;&#19981;&#21482;&#26159;&#21152;&#36733;&#26102;&#38388;&#65292;&#24040;&#22823;&#30340;&#20869;&#23384;&#21344;&#29992;&#21516;&#26679;&#19981;&#23481;&#24573;&#35270;&#12290;&#26412;&#25991;&#23558;&#32842;&#32842; SwiftData &#20026;&#20160;&#20040;&#20250;&#20986;&#29616;&#36825;&#20123;&#38382;&#39064;&#65292;&#20197;&#21450;&#20248;&#21270;&#20026;&#20160;&#20040;&#24212;&#35813;&#20174;&#25968;&#25454;&#24314;&#27169;&#24320;&#22987;&#12290;</span></p><blockquote><p><span>SwiftData &#20013;&#19968;&#20123;&#30475;&#20284;&#32570;&#22833;&#30340;&#33021;&#21147;&#65292;&#25110;&#35768;&#26412;&#23601;&#26159;&#26377;&#24847;&#20026;&#20043;&#65306;&#36890;&#36807;&#20943;&#23569;&#26292;&#38706;&#30340; API &#21644;&#36923;&#36753;&#23618;&#26469;&#38477;&#20302;&#23398;&#20064;&#26354;&#32447;&#12290;&#22240;&#27492;&#65292;&#22312;&#20248;&#21270; SwiftData &#24212;&#29992;&#26102;&#65292;&#20063;&#24212;&#35813;&#36866;&#24403;&#25918;&#19979; Core Data &#26102;&#20195;&#24418;&#25104;&#30340;&#19968;&#20123;&#24815;&#24615;&#24605;&#32500;&#12290;</span></p></blockquote><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-01"><span>&#21313;&#24180;&#32456;&#31456;&#65306;Swift Talk &#23459;&#24067;&#20572;&#26356; (The End of Swift Talk)</span></a></strong></h3><p><span>&#22312;&#24320;&#22987;&#21313;&#24180;&#12289;&#23436;&#25104; 500 &#26399;&#33410;&#30446;&#21518;&#65292;&#8288;</span><a href="https://x.com/chriseidhof"><span>Chris Eidhof</span></a><span> &#21644; &#8288;</span><a href="https://x.com/floriankugler"><span>Florian Kugler</span></a><span> &#23459;&#24067; Swift Talk &#27491;&#24335;&#32467;&#26463;&#12290;&#20174; 2016 &#24180; 6 &#26376;&#24320;&#22987;&#65292;Swift Talk &#20960;&#20046;&#23436;&#25972;&#38506;&#20276;&#20102; Swift &#36208;&#21521;&#25104;&#29087;&#30340;&#36807;&#31243;&#65292;&#20063;&#35265;&#35777;&#20102; SwiftUI &#20174;&#35806;&#29983;&#21040;&#36880;&#28176;&#25104;&#20026; Apple &#24179;&#21488; UI &#24320;&#21457;&#26680;&#24515;&#26694;&#26550;&#30340;&#36825;&#20123;&#24180;&#12290;&#20004;&#20154;&#36890;&#36807;&#19968;&#31995;&#21015;&#28145;&#20837;&#32780;&#21448;&#20805;&#28385;&#23454;&#39564;&#24615;&#30340;&#33410;&#30446;&#65292;&#25506;&#32034;&#20102; Swift&#12289;SwiftUI&#12289;&#24067;&#23616;&#12289;&#21160;&#30011;&#12289;&#24182;&#21457;&#20197;&#21450;&#22823;&#37327;&#24456;&#38590;&#22312;&#26222;&#36890;&#25945;&#31243;&#20013;&#30475;&#21040;&#30340;&#24213;&#23618;&#38382;&#39064;&#12290;&#23448;&#26041;&#34920;&#31034;&#65292;&#24076;&#26395;&#22312;&#20170;&#24180;&#24180;&#24213;&#35753;&#23436;&#25972;&#30340; 500 &#22810;&#26399;&#33410;&#30446;&#24402;&#26723;&#33021;&#22815;&#32487;&#32493;&#25552;&#20379;&#32473;&#31038;&#21306;&#12290;</span></p><p><span>&#23545;&#25105;&#32780;&#35328;&#65292;objc.io &#21644; Swift Talk &#19968;&#30452;&#26159; Swift &#31038;&#21306;&#20013;&#38750;&#24120;&#29305;&#21035;&#30340;&#23384;&#22312;&#12290;Chris &#21644; Florian &#24456;&#23569;&#28385;&#36275;&#20110;&#21578;&#35785;&#24320;&#21457;&#32773;&#19968;&#20010; API &#8220;&#24212;&#35813;&#24590;&#20040;&#29992;&#8221;&#65292;&#32780;&#26159;&#20064;&#24815;&#36890;&#36807;&#23454;&#39564;&#12289;&#37325;&#26500;&#29978;&#33267;&#37325;&#26032;&#23454;&#29616;&#65292;&#21435;&#36861;&#38382;&#26694;&#26550;&#20026;&#20160;&#20040;&#20250;&#36825;&#26679;&#24037;&#20316;&#12290;&#36825;&#31181;&#25506;&#32034;&#26041;&#24335;&#24433;&#21709;&#20102;&#35768;&#22810; Swift &#24320;&#21457;&#32773;&#65292;&#20063;&#21253;&#25324;&#25105;&#33258;&#24049;&#12290;&#24863;&#35874; Chris &#21644; Florian &#36825;&#20123;&#24180;&#26469;&#20026; Swift &#31038;&#21306;&#25237;&#20837;&#30340;&#26102;&#38388;&#12289;&#30693;&#35782;&#19982;&#22909;&#22855;&#24515;&#65292;&#20063;&#24863;&#35874; Swift Talk &#30041;&#19979;&#30340;&#36825;&#20221;&#29645;&#36149;&#26723;&#26696;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-02"><span>Swift &#23448;&#26041; 8 &#26376;&#25253; (What&#8217;s new in Swift: August 2026 Edition)</span></a></strong></h3><p><span>Swift &#23448;&#26041;&#21457;&#24067;&#20102; 8 &#26376;&#29983;&#24577;&#26376;&#25253;&#65292;&#30001; &#8288;</span><a href="https://github.com/sliemeobn/"><span>Simon Leeb</span></a><span> &#21644; &#8288;</span><a href="https://www.linkedin.com/in/davelester-dev/"><span>Dave Lester</span></a><span> &#25972;&#29702;&#65292;&#27719;&#24635;&#20102;&#36817;&#26399;&#20540;&#24471;&#20851;&#27880;&#30340;&#31038;&#21306;&#39033;&#30446;&#12289;Package &#26356;&#26032;&#21644; Swift Evolution &#36827;&#23637;&#12290;&#20854;&#20013;&#26368;&#35753;&#25105;&#24863;&#20852;&#36259;&#30340;&#26159; Swift &#22312; Web &#26041;&#21521;&#19978;&#30340;&#25512;&#36827;&#65306;Simon Leeb &#23637;&#31034;&#20102;&#19968;&#20010; &#8288;</span><a href="https://cloudflare-worker.examples.elementary.codes/"><span>Full-Stack Swift on Cloudflare Demo</span></a><span>&#65292;&#27983;&#35272;&#22120;&#31471;&#36890;&#36807; ElementaryUI &#21644; WebAssembly &#36816;&#34892; Swift&#65292;&#21518;&#31471;&#21017;&#36816;&#34892;&#22312; edge worker &#19978;&#65292;&#20004;&#31471;&#36824;&#33021;&#20849;&#20139;&#28040;&#24687;&#31867;&#22411;&#12290;&#20174; Embedded Swift&#12289;Wasm &#21040;&#36234;&#26469;&#36234;&#23436;&#21892;&#30340;&#36328;&#24179;&#21488;&#24037;&#20855;&#38142;&#65292;Swift &#30340;&#20351;&#29992;&#36793;&#30028;&#27491;&#22312;&#32487;&#32493;&#21521; Apple &#24179;&#21488;&#20043;&#22806;&#25193;&#23637;&#12290;</span></p><p><span>&#35821;&#35328;&#23618;&#38754;&#65292;&#21018;&#21018;&#33719;&#25209;&#30340; &#8288;&#8288;</span><a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0516-borrowing-sequence.md"><span>Iterable</span></a><span> &#20063;&#24456;&#20540;&#24471;&#20851;&#27880;&#12290;</span><code>Sequence</code><span> &#22312;&#36941;&#21382;&#26102;&#20250;&#36880;&#20010;&#20135;&#29983;&#29420;&#31435;&#30340;&#20803;&#32032;&#20540;&#65292;&#20294;&#23545;&#20110; </span><code>Span</code><span>&#12289;</span><code>InlineArray</code><span> &#31561;&#21487;&#33021;&#21253;&#21547; non-copyable &#20803;&#32032;&#30340;&#25968;&#25454;&#32467;&#26500;&#65292;&#36825;&#22871;&#27169;&#22411;&#24182;&#19981;&#36866;&#29992;&#12290;</span><code>Iterable</code><span> &#20801;&#35768;&#30452;&#25509;&#20511;&#29992;&#32780;&#38750;&#22797;&#21046;&#20803;&#32032;&#36827;&#34892;&#36941;&#21382;&#65292;&#35753;&#36825;&#20123;&#25968;&#25454;&#32467;&#26500;&#20063;&#33021;&#25317;&#26377;&#33258;&#28982;&#30340;&#36941;&#21382;&#26041;&#24335;&#12290;&#23427;&#30475;&#36215;&#26469;&#21482;&#26159;&#19968;&#20010;&#26032;&#30340;&#36941;&#21382;&#25277;&#35937;&#65292;&#21364;&#20063;&#26159; Swift ownership &#33021;&#21147;&#36880;&#28176;&#20174;&#35821;&#35328;&#24213;&#23618;&#36208;&#21521;&#26085;&#24120; API &#35774;&#35745;&#30340;&#21448;&#19968;&#20010;&#20307;&#29616;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-03"><span>&#22312;&#23884;&#20837;&#24335;&#35774;&#22791;&#19978;&#36816;&#34892; OpenSwiftUI (OpenSwiftUI on ESP32-C3)</span></a></strong></h3><p><span>&#19978;&#38754;&#30340; Swift &#26376;&#25253;&#23637;&#31034;&#20102; Swift &#27491;&#22312;&#19981;&#26029;&#31361;&#30772; Apple &#24179;&#21488;&#30340;&#36793;&#30028;&#65292;&#32780; OpenSwiftUI &#24320;&#21457;&#32773; &#8288;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#26368;&#36817;&#30340;&#19968;&#27425;&#23581;&#35797;&#65292;&#21017;&#32473;&#36825;&#20010;&#36235;&#21183;&#25552;&#20379;&#20102;&#19968;&#20010;&#24456;&#30452;&#35266;&#30340;&#20363;&#23376;&#12290;&#22312;&#25910;&#21040; TraeAI &#36192;&#36865;&#30340; </span><a href="https://ai-passport.folotoy.cn/"><span>ESP32-C3 &#24320;&#21457;&#35774;&#22791;</span></a><span>&#21518;&#65292;Kyle &#23436;&#25104;&#20102;&#33258;&#24049;&#30340;&#31532;&#19968;&#20010; Embedded Swift &#39033;&#30446;&#65306;&#23558; OpenSwiftUI &#30340;&#23884;&#20837;&#24335;&#29256;&#26412;&#37096;&#32626;&#21040;&#36825;&#22359;&#37319;&#29992; RISC-V &#26550;&#26500;&#30340;&#24494;&#25511;&#21046;&#22120;&#19978;&#65292;&#24182;&#22312; 240 &#215; 320 &#30340; LCD &#19978;&#20351;&#29992;&#25105;&#20204;&#29087;&#24713;&#30340; </span><code>View</code><span>&#12289;</span><code>@ViewBuilder</code><span>&#12289;</span><code>Text</code><span>&#12289;</span><code>Image</code><span>&#12289;</span><code>VStack</code><span>&#12289;</span><code>HStack</code><span>&#12289;</span><code>ZStack</code><span> &#31561; API &#26500;&#24314;&#30028;&#38754;&#65292;&#29978;&#33267; </span><code>@State</code><span> &#20063;&#33021;&#21709;&#24212;&#23454;&#20307;&#25353;&#38190;&#24182;&#35302;&#21457;&#30028;&#38754;&#26356;&#26032;&#12290;</span></p><p><span>&#36825;&#20010;&#23454;&#39564;&#21033;&#29992; Embedded Swift &#32534;&#35793;&#21407;&#29983; RISC-V &#20195;&#30721;&#65292;&#30001; OpenSwiftUI &#36127;&#36131;&#35270;&#22270;&#32452;&#21512;&#21644;&#24067;&#23616;&#65292;&#20877;&#36890;&#36807;&#19968;&#20010;&#24456;&#34180;&#30340;&#28210;&#26579;&#36793;&#30028;&#23558;&#32472;&#21046;&#20132;&#32473; LVGL &#21644;&#24213;&#23618;&#30828;&#20214;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#20174;&#22768;&#26126;&#24335; View&#12289;&#24067;&#23616;&#35745;&#31639;&#12289;&#29366;&#24577;&#26356;&#26032;&#21040;&#26368;&#32456;&#20687;&#32032;&#36755;&#20986;&#65292;&#19968;&#22871;&#31934;&#31616;&#20294;&#23436;&#25972;&#30340; UI &#38142;&#36335;&#24050;&#32463;&#24314;&#31435;&#36215;&#26469;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-04"><span>Swift &#36328;&#24179;&#21488;&#23454;&#36341;&#65306;&#22810;&#24179;&#21488;&#19979;&#30340; C++ &#20381;&#36182;&#31649;&#29702; (Multiplatform Swift, with C++ dependencies via XCFramework, apt and vcpkg)</span></a></strong></h3><p><span>&#19968;&#20010; Swift &#24212;&#29992;&#33021;&#21542;&#30495;&#27491;&#23454;&#29616;&#36328;&#24179;&#21488;&#65292;&#24456;&#22810;&#26102;&#20505;&#21462;&#20915;&#20110;&#20854;&#32972;&#21518;&#30340; C/C++ &#20381;&#36182;&#33021;&#21542;&#36319;&#30528;&#36328;&#24179;&#21488;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/harald-achitz/"><span>Harald Achitz</span></a><span> &#20197;&#33258;&#24049;&#30340; ZeroMQ Swift bindings &#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#19968;&#20010;&#21516;&#26102;&#25903;&#25345; macOS&#12289;Linux &#21644; Windows &#30340; Swift/C++ &#39033;&#30446;&#22914;&#20309;&#32452;&#32455;&#21407;&#29983;&#20381;&#36182;&#65306;Apple &#24179;&#21488;&#20351;&#29992; XCFramework&#65292;Linux &#20351;&#29992;&#31995;&#32479; package&#65292;Windows &#21017;&#36890;&#36807; vcpkg &#23433;&#35013; ZeroMQ&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-05"><span>&#22312; iOS &#27169;&#25311;&#22120;&#38388;&#23454;&#29616;&#34394;&#25311;&#34013;&#29273;&#36890;&#20449; (Connecting two iOS simulators over BLE)</span></a></strong></h3><p><span>CoreBluetooth &#22312; iOS Simulator &#20013;&#23436;&#20840;&#19981;&#21487;&#29992;&#65292;&#36825;&#35753; BLE App &#30340;&#24320;&#21457;&#21644;&#27979;&#35797;&#38271;&#26399;&#20381;&#36182;&#30495;&#26426;&#12290;&#8288;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#22312;&#24320;&#21457; &#8288;</span><a href="https://github.com/kylebrowning/BLESwift"><span>BLESwift 2.0</span></a><span> &#26102;&#25442;&#20102;&#19968;&#31181;&#24605;&#36335;&#65306;Simulator &#20013;&#30340;&#20013;&#24515;&#35774;&#22791;&#65288;Central&#65289;&#21644;&#22806;&#22260;&#35774;&#22791;&#65288;Peripheral&#65289;&#19981;&#20877;&#35843;&#29992; CoreBluetooth&#65292;&#32780;&#26159;&#36890;&#36807; localhost TCP &#23558;&#25805;&#20316;&#36716;&#21457;&#32473;&#36816;&#34892;&#22312; Mac &#19978;&#30340; </span><code>bleswift-provider</code><span>&#65292;&#30001;&#23427;&#26500;&#24314;&#19968;&#20010;&#8220;&#34394;&#25311;&#26080;&#32447;&#30005;&#8221;&#12290;&#36825;&#26679;&#65292;&#20004;&#20010; Simulator &#23601;&#33021;&#20687;&#20004;&#21488;&#30495;&#23454; BLE &#35774;&#22791;&#19968;&#26679;&#23436;&#25104;&#21457;&#29616;&#12289;&#36830;&#25509;&#12289;&#35835;&#20889;&#21644; notification&#65292;&#29978;&#33267;&#36824;&#21487;&#20197;&#36890;&#36807; passthrough &#27169;&#24335;&#20511;&#29992; Mac &#30340;&#34013;&#29273;&#65292;&#19982;&#30495;&#23454; BLE &#35774;&#22791;&#36890;&#20449;&#12290;</span></p><blockquote><p><span>&#27604; BLE &#26412;&#36523;&#26356;&#35753;&#25105;&#24863;&#20852;&#36259;&#30340;&#26159;&#36825;&#31181;&#27979;&#35797;&#33539;&#24335;&#65306;&#24403; Simulator &#32570;&#23569;&#26576;&#39033;&#31995;&#32479;&#25110;&#30828;&#20214;&#33021;&#21147;&#26102;&#65292;&#19981;&#19968;&#23450;&#35201;&#22312; App &#20869;&#21040;&#22788;&#28155;&#21152; mock&#65292;&#32780;&#26159;&#21487;&#20197;&#22312;&#31995;&#32479;&#33021;&#21147;&#19982;&#19994;&#21153;&#20195;&#30721;&#20043;&#38388;&#24314;&#31435;&#21487;&#26367;&#25442;&#30340; backend&#65292;&#20877;&#36890;&#36807; Mac &#19978;&#30340;&#20195;&#29702;&#36827;&#31243;&#37325;&#24314;&#19968;&#20010;&#21487;&#25511;&#30340;&#22806;&#37096;&#19990;&#30028;&#12290;&#36825;&#31181;&#35774;&#35745;&#19981;&#20165;&#35299;&#20915;&#20102;&#8220;Simulator &#32570;&#23569;&#26576;&#20123;&#31995;&#32479;&#25110;&#30828;&#20214;&#33021;&#21147;&#8221;&#30340;&#38382;&#39064;&#65292;&#20063;&#35753;&#21407;&#26412;&#39640;&#24230;&#20381;&#36182;&#30495;&#23454;&#29615;&#22659;&#30340;&#21151;&#33021;&#26356;&#23481;&#26131;&#36827;&#20837;&#33258;&#21160;&#21270;&#27979;&#35797;&#21644; CI&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-06"><span>&#25506;&#32034; SwiftUI &#20840;&#26032;&#30340;&#20219;&#24847;&#23481;&#22120;&#25302;&#25341;&#25490;&#24207; API (Reorder all the things in SwiftUI)</span></a></strong></h3><p><span>SwiftUI &#38271;&#26399;&#20197;&#26469;&#27809;&#26377;&#25552;&#20379;&#22312;&#20219;&#24847;&#23481;&#22120;&#20013;&#23454;&#29616;&#25302;&#25341;&#25490;&#24207;&#30340;&#36890;&#29992; API&#65292;&#36825;&#20010;&#36951;&#25022;&#22312; WWDC 2026 &#21518;&#24471;&#21040;&#20102;&#35299;&#20915;&#12290;&#8288;&#8288;</span><a href="https://x.com/SwiftyAlex"><span>Alexander Logan</span></a><span> &#20171;&#32461;&#20102; SwiftUI &#26032;&#30340; reordering API&#12290;&#36890;&#36807; </span><code>reorderable</code><span>&#12289;</span><code>reorderableContainer</code><span> &#31561;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#30452;&#25509;&#22768;&#26126;&#21738;&#20123;&#20869;&#23481;&#21487;&#20197;&#34987;&#37325;&#26032;&#25490;&#24207;&#20197;&#21450;&#23545;&#24212;&#30340;&#25968;&#25454;&#27169;&#22411;&#65292;&#35753;&#25302;&#25341;&#25490;&#24207;&#19981;&#20877;&#23616;&#38480;&#20110; </span><code>List</code><span>&#65292;&#20063;&#19981;&#24517;&#33258;&#24049;&#36890;&#36807; </span><code>DropDelegate</code><span> &#31649;&#29702;&#25302;&#25341;&#20301;&#32622;&#21644;&#25968;&#25454;&#26356;&#26032;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#26032; API &#25552;&#20379;&#20102;&#26356;&#39640;&#23618;&#30340;&#20132;&#20114;&#35821;&#20041;&#65292;&#23558;&#8220;reordering&#8221;&#20174; drag &amp; drop &#36825;&#19968;&#20855;&#20307;&#23454;&#29616;&#26041;&#24335;&#20013;&#25277;&#31163;&#20986;&#26469;&#12290;&#24320;&#21457;&#32773;&#25551;&#36848;&#30340;&#26159;&#8220;&#36825;&#20123;&#20869;&#23481;&#21487;&#20197;&#37325;&#26032;&#25490;&#24207;&#8221;&#65292;&#33267;&#20110;&#36890;&#36807;&#40736;&#26631;&#12289;&#35302;&#25511;&#36824;&#26159;&#20854;&#20182;&#36755;&#20837;&#26041;&#24335;&#23436;&#25104;&#25805;&#20316;&#65292;&#21017;&#21487;&#20197;&#26356;&#22810;&#22320;&#20132;&#32473;&#31995;&#32479;&#22788;&#29702;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-07"><span>Swift Charts &#36827;&#38454;&#65306;&#22914;&#20309;&#32472;&#21046;&#22810;&#23618;&#26093;&#26085;&#22270; (Building a sunburst diagram in Swift Charts)</span></a></strong></h3><p><span>&#26093;&#26085;&#22270;&#65288;Sunburst Diagram&#65289;&#26159;&#19968;&#31181;&#29992;&#21516;&#24515;&#22278;&#29615;&#23637;&#31034;&#23618;&#32423;&#25968;&#25454;&#30340;&#22270;&#34920;&#65292;&#20363;&#22914;&#20174;&#8220;&#24037;&#20316;&#8221;&#21040;&#8220;&#24320;&#21457;&#8221;&#65292;&#20877;&#21040;&#26576;&#20010;&#20855;&#20307;&#39033;&#30446;&#65292;&#36234;&#21521;&#22806;&#20195;&#34920;&#36234;&#32454;&#30340;&#25968;&#25454;&#23618;&#32423;&#12290;&#8288;&#8288;</span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#23637;&#31034;&#20102;&#22914;&#20309;&#21033;&#29992; Swift Charts &#30340; </span><code>SectorMark</code><span>&#65292;&#20174;&#26222;&#36890;&#39292;&#22270;&#24320;&#22987;&#65292;&#36880;&#27493;&#26500;&#24314;&#19968;&#20010;&#21253;&#21547;&#19977;&#23618;&#25968;&#25454;&#30340;&#26093;&#26085;&#22270;&#12290;&#36825;&#20010;&#23454;&#29616;&#20063;&#24456;&#22909;&#22320;&#23637;&#31034;&#20102; Swift Charts &#30340;&#28789;&#27963;&#24615;&#65306;&#24403;&#26694;&#26550;&#27809;&#26377;&#30452;&#25509;&#25552;&#20379;&#26576;&#31181;&#22270;&#34920;&#26102;&#65292;&#21487;&#20197;&#23558; </span><code>SectorMark</code><span> &#31561; Mark &#35270;&#20026;&#26356;&#22522;&#30784;&#30340;&#21487;&#35270;&#21270;&#21407;&#35821;&#65292;&#36890;&#36807;&#33258;&#34892;&#35745;&#31639;&#35282;&#24230;&#21306;&#38388;&#21644;&#25968;&#25454;&#26144;&#23556;&#26469;&#26500;&#24314;&#26356;&#22797;&#26434;&#30340;&#22270;&#34920;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-08"><span>CoreDataBrowser&#65306;&#24555;&#36895;&#26597;&#30475; Simulator &#20013;&#30340;&#26412;&#22320;&#25968;&#25454;</span></a></strong></h3><p><span>&#35843;&#35797; Core Data &#25110; SwiftData &#24212;&#29992;&#26102;&#65292;&#36890;&#24120;&#38656;&#35201;&#20808;&#22312;&#23618;&#23618;&#23884;&#22871;&#30340; Simulator &#30446;&#24405;&#20013;&#25214;&#21040;&#23545;&#24212;&#30340;&#25968;&#25454;&#25991;&#20214;&#65292;&#20877;&#29992; SQLite &#31649;&#29702;&#22120;&#25171;&#24320;&#24182;&#27983;&#35272;&#25968;&#25454;&#12290;&#30001; &#8288;</span><a href="https://www.linkedin.com/in/csaba-turdesan-880182251/"><span>Csaba Turdesan</span></a><span> &#24320;&#21457;&#30340; CoreDataBrowser &#23581;&#35797;&#25226;&#36825;&#20010;&#36807;&#31243;&#21464;&#24471;&#31616;&#21333;&#65306;&#36873;&#25321;&#24403;&#21069;&#21551;&#21160;&#30340;&#27169;&#25311;&#22120;&#21518;&#65292;&#23427;&#20250;&#33258;&#21160;&#26597;&#25214;&#24212;&#29992;&#23481;&#22120;&#20013;&#30340; Core Data&#12289;SwiftData &#20197;&#21450; UserDefaults &#25968;&#25454;&#28304;&#65292;&#24182;&#36890;&#36807;&#21407;&#29983; macOS &#30028;&#38754;&#32479;&#19968;&#21576;&#29616;&#12290;</span></p><p><span>CoreDataBrowser &#25903;&#25345;&#26597;&#30475;&#34920;&#19982;&#35760;&#24405;&#12289;&#25628;&#32034;&#24182;&#39640;&#20142;&#21305;&#37197;&#20869;&#23481;&#65292;&#20063;&#33021;&#23545;&#37096;&#20998;&#20108;&#36827;&#21046;&#25968;&#25454;&#65288;BLOB&#65289;&#23581;&#35797;&#35299;&#26512; NSKeyedArchive&#12289;JSON&#12289;Property List &#21644; UTF-8 &#25991;&#26412;&#12290;&#24037;&#20855;&#20307;&#37327;&#24456;&#23567;&#65288;2.5 MB&#65289;&#65292;&#24182;&#19988;&#8288;</span><a href="https://github.com/kyletaylor94/CoreDataBrowser"><span>&#28304;&#30721;&#20844;&#24320;</span></a><span>&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #151]]></title><description><![CDATA[Just a Few Keystrokes]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 31 Aug 2026 12:01:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!KvhQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KvhQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 424w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 848w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1272w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" width="1391" height="620" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:620,&quot;width&quot;:1391,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:379890,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/213490700?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 424w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 848w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1272w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@paws_and_prints?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">&#120161;&#120146;&#120168;&#120164; &#120146;&#120159;&#120149; &#120161;&#120163;&#120154;&#120159;&#120165;&#120164;</a><span> on </span><a href="https://unsplash.com/photos/pink-and-blue-textured-wall-divided-vertically-smHN6OX-hEQ?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Just a Few Keystrokes</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-151/">Read on web &#8594;</a></p><p><span>Last weekend, I attended an App Accelerator event hosted by Apple in Beijing. The event focused primarily on app development, operations, and business models in the age of AI. Most of the attendees were managers at tech companies or app developers. Throughout the event, enthusiasm for AI was high, with people exchanging their own perspectives on AI and sharing how they were putting it to use. I learned a great deal from those conversations.</span></p><p><span>After the event, I had dinner with a friend who works in a traditional industry. He knew almost nothing about AI. As an emerging concept, it was something he wanted to understand, but he had never really seen what tangible benefits AI could bring to his business. During dinner, he received a phone call: a client needed a proposal revised immediately. It was the weekend, and even if he assigned the task right away, it would have been difficult to get it done within a short period of time. After hearing roughly what was needed, I realized that the task happened to fall squarely within AI&#8217;s comfort zone. So I pulled out my phone and had AI handle it for him. A few minutes later, the result was ready.</span></p><p><span>He was impressed not only by how quickly AI completed the task, but also by the quality of the result. And at his company, there happened to be a team of five or six people whose work largely consisted of handling similar tasks.</span></p><p><span>He immediately started asking me for more details and calculating how much headcount he could reduce, and how much money he could save, if the company adopted AI.</span></p><p><span>The speed of that shift caught me somewhat off guard. I immediately brought up another possibility: if AI can accomplish existing work at a much lower cost, could those newly available capabilities also be used to pursue opportunities that had previously been too expensive to explore? Cutting costs is certainly one of AI&#8217;s most obvious benefits, but generating new revenue is just as much a field where AI can make a difference.</span></p><p><span>On the way home, I kept thinking about those five or six people. Right now they are probably enjoying a quiet weekend, unaware that their jobs had just been repriced over the course of a single meal. And what prompted that repricing was a demo I ran a few minutes earlier.</span></p><p><span>The next time I find myself in a similar situation, I will probably still pull out my phone and show someone what AI can do. But I think I should at least remember this: what takes just a few keystrokes on one side of the screen may mean something very different on the other.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-150/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-01"><span>Why Swift is introducing a warning for weak captures within nested closures</span></a></strong></h3><p><span>Weak captures are an important memory management mechanism in Swift. Historically, if a weak capture is used only in the inner closure of a nested closure, the Swift compiler may implicitly insert a strong capture in the parent closure. Even though this behavior can lead to a retain cycle in certain situations, the compiler previously provided no warning. Starting with Swift 6.4, the compiler will issue a warning when it detects a mismatch between a weak capture in an inner closure and an implicit strong capture in the outer closure.</span></p><p><a href="https://mastodon.social/@johnsundell"><span>John Sundell</span></a><span> explains this change and offers several solutions: depending on the situation, explicitly declare the capture semantics in the parent closure; if both closures need to manage their lifetimes independently, declare the appropriate capture semantics for each one. This may be a small update to the Swift compiler, but it helps developers express ownership relationships between nested closures that could otherwise be easily overlooked.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-02"><span>Running iOS Background Tasks Reliably</span></a></strong></h3><p><code>BGTaskScheduler</code><span> has never been cron for iOS. When a background task actually runs depends on system scheduling, device state, energy budgets, and how users interact with the app. </span><a href="https://www.linkedin.com/in/irvingpop/"><span>Irving Popovetsky</span></a><span> used telemetry from a real device to observe background task behavior over an extended period and shared a number of lessons learned along the way: frequently resubmitting tasks in an attempt to improve reliability can actually keep pushing back a task that was close to getting an execution opportunity; user behavior and system conditions such as force quitting, not opening the app for a long time, Low Power Mode, and device reboots can all affect whether background tasks get a chance to run; and a task running later than requested does not necessarily mean that scheduling has gone wrong.</span></p><p><span>For background tasks, developers should not try to precisely schedule execution. Instead, the goal should be to make the most efficient and correct use of the opportunities the system chooses to provide.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-03"><span>The Memory Remains: TipKit in a Shipping App</span></a></strong></h3><p><span>TipKit is easy to learn, but using it well in a real project is much harder. The real challenges are knowing when tips should not appear, avoiding disruptions to the user experience, and ensuring that the underlying logic remains testable and maintainable. </span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> shares lessons from using TipKit in a shipping app: </span><code>@Parameter</code><span> is better suited to current state that can be recomputed at any time, while </span><code>Tips.Event</code><span> is appropriate for historical behavior that cannot be reconstructed from current state; every tip should avoid periods when onboarding or other launch UI may still appear; and because </span><code>Tips.configure</code><span> only takes effect once per process, initialization order, debug tooling, and test environments all need to be designed around that constraint.</span></p><p><span>The essence of TipKit lies not in its visual presentation, but in its internal logic. It helps developers declaratively describe the rules that determine when tips should appear, while leaving the actual presentation entirely customizable. We can think of TipKit as a rules engine that determines whether a tip should be displayed; how those rules are visualized is up to the developer. For more discussion from this perspective, see </span><a href="https://fatbobman.com/en/posts/mastering-tipkit-advance/"><span>Mastering TipKit: Advanced</span></a><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-04"><span>Building an accessible calendar chart with Swift Charts</span></a></strong></h3><p><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to build a calendar chart similar to GitHub Contributions using Swift Charts. The more interesting part of the article, however, is its approach to accessibility. Because the same weekday across different weeks shares a normalized x value, VoiceOver groups an entire column of data together instead of allowing users to navigate day by day. The author solves this by using </span><code>accessibilityChildren</code><span> to construct a separate accessibility hierarchy for the plot area that corresponds to the visual layout.</span></p><p><a href="https://books.nilcoalescing.com/swift-charts-beyond-the-basics"><span>Swift Charts Beyond the Basics</span></a><span>, co-authored by Matthaus Woolard and </span><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>, was officially released last week. For developers looking to create advanced data visualizations with Swift Charts, it is a rare and valuable advanced guide.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-05"><span>Mac App Direct Distribution, DMG Signing &amp; Notarization Guide</span></a></strong></h3><p><span>Compared with publishing through the Mac App Store, distributing a macOS app directly requires developers to handle more of the release process themselves: Developer ID signing, DMG creation, notarization, stapling, and final Gatekeeper verification. A problem at any one of these stages can prevent users from installing the app successfully. </span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> walks through the complete release workflow, from creating an Xcode Archive and building the DMG to final signing, notarization, and verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-06"><span>Consuming SKIE Flows in SwiftUI</span></a></strong></h3><p><span>In projects that use Kotlin Multiplatform (KMP) to share business logic while building native UIs with SwiftUI, making Kotlin APIs integrate naturally into the Swift ecosystem has always been an important challenge. SKIE (Swift Kotlin Interface Enhancer) was created to improve this interoperability experience. It can convert Kotlin </span><code>Flow</code><span> into Swift </span><code>AsyncSequence</code><span>, allowing Swift code to consume data using familiar Swift Concurrency patterns.</span></p><p><a href="https://x.com/faogustavo"><span>Gustavo F&#227;o Valvassori</span></a><span> introduces a set of SwiftUI-specific APIs provided by SKIE: besides consuming data directly from an </span><code>AsyncSequence</code><span> inside </span><code>.task</code><span>, developers can use </span><code>.collect</code><span> to bind Flow updates to SwiftUI state, or use the </span><code>Observing</code><span> wrapper to hide state management and let the latest value from a Kotlin </span><code>StateFlow</code><span> directly participate in building the View.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-07"><span>Sarunw&#8217;s How-to Series Returns</span></a></strong></h3><p><a href="https://x.com/sarunw"><span>Sarunw</span></a><span>&#8217;s blog has long been an excellent resource for developers looking for practical tips on Apple platform development. However, the blog stopped receiving updates at the end of 2023. Last week, Sarunw resumed writing and published several new articles in his How-to series within just one week. It&#8217;s great to see an excellent content creator return after nearly three years away.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-08"><span>JindoKit: Preview Dynamic Island presentations in your app</span></a></strong></h3><p><span>WidgetKit&#8217;s Live Activity previews are primarily intended for development and debugging within Xcode. For apps that allow users to choose themes or customize displayed content, however, the system does not provide an equivalent way to preview those presentations directly inside the app.</span></p><p><span>Developed by </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span>, JindoKit brings WidgetKit-style Dynamic Island APIs into regular SwiftUI Views, allowing apps to directly preview expanded, compact, and minimal Dynamic Island presentations. Since its API closely mirrors WidgetKit&#8217;s structure, developers can organize content for each region in a similar way and reuse related views and data between the app&#8217;s configuration UI and its WidgetKit Extension. For more information, see the author&#8217;s introductory article: </span><a href="https://openswiftuiproject.org/blog/preview-dynamic-island-presentations-with-jindokit/"><span>Preview Dynamic Island presentations in your app with JindoKit</span></a><span>.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#20030;&#25163;&#20043;&#21171;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-151/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#20010;&#21608;&#26411;&#65292;&#25105;&#22312;&#21271;&#20140;&#21442;&#21152;&#20102;&#30001;&#33529;&#26524;&#20030;&#21150;&#30340; App &#23413;&#21270;&#22120;&#27963;&#21160;&#65292;&#26412;&#27425;&#30340;&#20027;&#39064;&#20027;&#35201;&#22260;&#32469; AI &#26102;&#20195;&#30340;&#24212;&#29992;&#24320;&#21457;&#12289;&#36816;&#33829;&#21644;&#21830;&#19994;&#27169;&#24335;&#23637;&#24320;&#12290;&#19982;&#20250;&#32773;&#22823;&#22810;&#26159; IT &#20844;&#21496;&#30340;&#31649;&#29702;&#32773;&#21644;&#24212;&#29992;&#24320;&#21457;&#32773;&#65292;&#25972;&#20010;&#27963;&#21160;&#26399;&#38388;&#65292;&#22823;&#23478;&#23545; AI &#30340;&#28909;&#24773;&#37117;&#24456;&#39640;&#65292;&#20063;&#32439;&#32439;&#35752;&#35770;&#21508;&#33258;&#23545;&#20110; AI &#30340;&#29702;&#35299;&#21644;&#24212;&#29992;&#25216;&#24039;&#65292;&#25105;&#20174;&#20013;&#25910;&#33719;&#19981;&#23569;&#12290;</span></p><p><span>&#20250;&#35758;&#32467;&#26463;&#21518;&#65292;&#25105;&#21644;&#19968;&#20301;&#20174;&#20107;&#20256;&#32479;&#34892;&#19994;&#30340;&#26379;&#21451;&#21507;&#39277;&#12290;&#20182;&#23545; AI &#22522;&#26412;&#19968;&#31373;&#19981;&#36890;&#12290;&#20316;&#20026;&#19968;&#20010;&#26032;&#20852;&#27010;&#24565;&#65292;&#20182;&#20063;&#24819;&#20102;&#35299;&#65292;&#20294;&#19968;&#30452;&#27809;&#26377;&#20999;&#23454;&#24863;&#21463;&#21040; AI &#31350;&#31455;&#33021;&#32473;&#20182;&#30340;&#20225;&#19994;&#24102;&#26469;&#20160;&#20040;&#12290;&#23601;&#39184;&#36807;&#31243;&#20013;&#65292;&#20182;&#25509;&#21040;&#19968;&#20010;&#30005;&#35805;&#65292;&#19968;&#20010;&#23458;&#25143;&#35201;&#27714;&#31435;&#21051;&#35843;&#25972;&#26041;&#26696;&#12290;&#24403;&#26102;&#27491;&#20540;&#21608;&#26411;&#65292;&#21363;&#20415;&#39532;&#19978;&#25226;&#20219;&#21153;&#23433;&#25490;&#19979;&#21435;&#65292;&#20063;&#24456;&#38590;&#22312;&#30701;&#26102;&#38388;&#20869;&#23436;&#25104;&#12290;&#25105;&#22312;&#20102;&#35299;&#22823;&#33268;&#38656;&#27714;&#21518;&#65292;&#21457;&#29616;&#36825;&#24688;&#22909;&#23646;&#20110; AI &#30340;&#33298;&#36866;&#21306;&#65292;&#20110;&#26159;&#30452;&#25509;&#29992;&#25163;&#26426;&#35753; AI &#24110;&#20182;&#22788;&#29702;&#12290;&#20960;&#20998;&#38047;&#21518;&#65292;&#32467;&#26524;&#23601;&#20986;&#26469;&#20102;&#12290;</span></p><p><span>&#20182;&#19981;&#20165;&#24778;&#21497;&#20110; AI &#23436;&#25104;&#20219;&#21153;&#30340;&#25928;&#29575;&#65292;&#20063;&#23545;&#32467;&#26524;&#30340;&#36136;&#37327;&#24863;&#21040;&#24847;&#22806;&#12290;&#32780;&#22312;&#20182;&#30340;&#20844;&#21496;&#37324;&#65292;&#24688;&#22909;&#26377;&#19968;&#20010;&#30001;&#20116;&#20845;&#20154;&#32452;&#25104;&#30340;&#37096;&#38376;&#65292;&#22823;&#37096;&#20998;&#24037;&#20316;&#23601;&#26159;&#22788;&#29702;&#31867;&#20284;&#30340;&#20219;&#21153;&#12290;</span></p><p><span>&#20110;&#26159;&#65292;&#20182;&#39532;&#19978;&#24320;&#22987;&#21521;&#25105;&#35810;&#38382;&#26356;&#22810;&#32454;&#33410;&#65292;&#24182;&#35745;&#31639;&#22914;&#26524;&#24341;&#20837; AI&#65292;&#21487;&#20197;&#32553;&#20943;&#22810;&#23569;&#20154;&#21147;&#12289;&#38477;&#20302;&#22810;&#23569;&#25104;&#26412;&#12290;</span></p><p><span>&#36825;&#20010;&#36716;&#21464;&#20043;&#24555;&#35753;&#25105;&#26377;&#20123;&#35815;&#24322;&#12290;&#25105;&#38543;&#21363;&#21644;&#20182;&#35752;&#35770;&#20102;&#21478;&#19968;&#31181;&#21487;&#33021;&#65306;&#26082;&#28982; AI &#33021;&#20197;&#26356;&#20302;&#30340;&#25104;&#26412;&#23436;&#25104;&#36807;&#21435;&#30340;&#24037;&#20316;&#65292;&#37027;&#20040;&#26159;&#21542;&#20063;&#21487;&#20197;&#21033;&#29992;&#36825;&#20123;&#26032;&#22686;&#30340;&#33021;&#21147;&#21435;&#23581;&#35797;&#20197;&#21069;&#22240;&#20026;&#25104;&#26412;&#36807;&#39640;&#32780;&#26080;&#27861;&#24320;&#23637;&#30340;&#19994;&#21153;&#65311;&#33410;&#27969;&#24403;&#28982;&#26159; AI &#26368;&#30452;&#35266;&#30340;&#20215;&#20540;&#65292;&#20294;&#24320;&#28304;&#21516;&#26679;&#26159;&#23427;&#21487;&#20197;&#26045;&#23637;&#30340;&#26041;&#21521;&#12290;</span></p><p><span>&#22312;&#21442;&#21152;&#27963;&#21160;&#26399;&#38388;&#65292;&#25105;&#20063;&#26366;&#22312;&#31169;&#19979;&#20132;&#27969;&#20013;&#34920;&#36798;&#36807;&#23545; AI &#20914;&#20987;&#23601;&#19994;&#30340;&#25285;&#24551;&#65292;&#19981;&#36807;&#26356;&#22810;&#36824;&#26159;&#20174;&#38271;&#26399;&#36235;&#21183;&#20986;&#21457;&#30340;&#19968;&#31181;&#24605;&#32771;&#12290;&#24403;&#36825;&#31181;&#8220;&#25285;&#24551;&#8221;&#31361;&#28982;&#20197;&#22914;&#27492;&#20855;&#20307;&#30340;&#26041;&#24335;&#20986;&#29616;&#22312;&#30524;&#21069;&#26102;&#65292;&#25105;&#36824;&#26159;&#24863;&#21040;&#20102;&#19968;&#20123;&#19981;&#36866;&#12290;&#19968;&#20010;&#23545;&#25105;&#32780;&#35328;&#21482;&#26159;&#20030;&#25163;&#20043;&#21171;&#30340;&#28436;&#31034;&#65292;&#22312;&#21478;&#19968;&#20010;&#20154;&#30340;&#35270;&#35282;&#37324;&#65292;&#21364;&#21487;&#33021;&#36805;&#36895;&#21464;&#25104;&#19968;&#36947;&#20851;&#20110;&#20960;&#20010;&#20154;&#26159;&#21542;&#36824;&#26377;&#24517;&#35201;&#32487;&#32493;&#30041;&#22312;&#23703;&#20301;&#19978;&#30340;&#31639;&#26415;&#39064;&#12290;</span></p><p><span>&#36820;&#31243;&#36884;&#20013;&#65292;&#25105;&#24819;&#30340;&#19968;&#30452;&#26159;&#37027;&#20116;&#20845;&#20010;&#20154;&#12290;&#20182;&#20204;&#27492;&#21051;&#22823;&#27010;&#27491;&#23433;&#31283;&#22320;&#36807;&#30528;&#21608;&#26411;&#65292;&#21364;&#24182;&#19981;&#30693;&#36947;&#33258;&#24049;&#30340;&#23703;&#20301;&#21018;&#21018;&#22312;&#19968;&#39039;&#39277;&#30340;&#26102;&#38388;&#37324;&#34987;&#37325;&#26032;&#20272;&#20215;&#12290;&#32780;&#20419;&#25104;&#36825;&#27425;&#20272;&#20215;&#30340;&#65292;&#26159;&#25105;&#20960;&#20998;&#38047;&#21069;&#30340;&#19968;&#27425;&#28436;&#31034;&#12290;</span></p><p><span>&#19979;&#19968;&#27425;&#36935;&#21040;&#31867;&#20284;&#30340;&#22330;&#21512;&#65292;&#25105;&#22823;&#27010;&#36824;&#26159;&#20250;&#25171;&#24320;&#25163;&#26426;&#28436;&#31034;&#32473;&#23545;&#26041;&#30475;&#12290;&#20294;&#25105;&#24819;&#65292;&#25105;&#33267;&#23569;&#24212;&#35813;&#35760;&#24471;&#65306;&#23631;&#24149;&#36825;&#19968;&#20391;&#30340;&#20030;&#25163;&#20043;&#21171;&#65292;&#22312;&#23631;&#24149;&#30340;&#21478;&#19968;&#20391;&#65292;&#25110;&#35768;&#26159;&#21478;&#19968;&#30058;&#22659;&#22320;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-150/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-01"><span>Swift &#23884;&#22871;&#38381;&#21253;&#24369;&#25429;&#33719;&#35686;&#21578; (Why Swift is introducing a warning for weak captures within nested closures)</span></a></strong></h3><p><span>&#24369;&#25429;&#33719;&#26159; Swift &#20013;&#37325;&#35201;&#30340;&#20869;&#23384;&#31649;&#29702;&#26426;&#21046;&#12290;&#19968;&#30452;&#20197;&#26469;&#65292;&#22914;&#26524;&#21482;&#22312;&#23884;&#22871;&#38381;&#21253;&#30340;&#20869;&#23618;&#36827;&#34892;&#24369;&#25429;&#33719;&#65292;Swift &#32534;&#35793;&#22120;&#21487;&#33021;&#20250;&#22312;&#29238;&#38381;&#21253;&#20013;&#38544;&#24335;&#25554;&#20837;&#24378;&#25429;&#33719;&#12290;&#21363;&#20415;&#36825;&#31181;&#34892;&#20026;&#22312;&#26576;&#20123;&#22330;&#26223;&#19979;&#21487;&#33021;&#23548;&#33268; retain cycle&#65292;&#32534;&#35793;&#22120;&#27492;&#21069;&#20063;&#19981;&#20250;&#32473;&#20986;&#25552;&#37266;&#12290;&#20174; Swift 6.4 &#24320;&#22987;&#65292;&#24403;&#32534;&#35793;&#22120;&#21457;&#29616;&#20869;&#23618;&#38381;&#21253;&#30340;&#24369;&#25429;&#33719;&#19982;&#22806;&#23618;&#38381;&#21253;&#30340;&#38544;&#24335;&#24378;&#25429;&#33719;&#23384;&#22312;&#24046;&#24322;&#26102;&#65292;&#23558;&#32473;&#20986;&#35686;&#21578;&#12290;</span></p><p><a href="https://mastodon.social/@johnsundell"><span>John Sundell</span></a><span> &#20171;&#32461;&#20102;&#36825;&#19968;&#21464;&#21270;&#65292;&#24182;&#32473;&#20986;&#20102;&#35299;&#20915;&#26041;&#26696;&#65306;&#26681;&#25454;&#20855;&#20307;&#22330;&#26223;&#65292;&#22312;&#29238;&#38381;&#21253;&#20013;&#26174;&#24335;&#22768;&#26126;&#24341;&#29992;&#26041;&#24335;&#65307;&#22914;&#26524;&#20004;&#23618;&#38381;&#21253;&#37117;&#38656;&#35201;&#29420;&#31435;&#25511;&#21046;&#29983;&#21629;&#21608;&#26399;&#65292;&#21017;&#21487;&#20197;&#20998;&#21035;&#22768;&#26126;&#21508;&#33258;&#30340;&#25429;&#33719;&#26041;&#24335;&#12290;&#36825;&#25110;&#35768;&#21482;&#26159; Swift &#32534;&#35793;&#22120;&#30340;&#19968;&#39033;&#23567;&#26356;&#26032;&#65292;&#20294;&#23427;&#33021;&#22815;&#24110;&#21161;&#24320;&#21457;&#32773;&#26356;&#26126;&#30830;&#22320;&#34920;&#36798;&#23884;&#22871;&#38381;&#21253;&#20043;&#38388;&#21407;&#26412;&#24456;&#23481;&#26131;&#34987;&#24573;&#30053;&#30340; ownership &#20851;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-02"><span>&#25552;&#21319; iOS &#21518;&#21488;&#20219;&#21153;&#21487;&#38752;&#24615;&#25351;&#21335; (Running iOS Background Tasks Reliably)</span></a></strong></h3><p><code>BGTaskScheduler</code><span> &#20174;&#26469;&#37117;&#19981;&#26159; iOS &#19978;&#30340; cron&#12290;&#21518;&#21488;&#20219;&#21153;&#30495;&#27491;&#20309;&#26102;&#25191;&#34892;&#65292;&#21462;&#20915;&#20110;&#31995;&#32479;&#35843;&#24230;&#12289;&#35774;&#22791;&#29366;&#24577;&#12289;&#33021;&#28304;&#39044;&#31639;&#20197;&#21450;&#29992;&#25143;&#20351;&#29992; App &#30340;&#20064;&#24815;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/irvingpop/"><span>Irving Popovetsky</span></a><span> &#36890;&#36807;&#23454;&#38469;&#35774;&#22791;&#19978;&#30340; telemetry &#38271;&#26399;&#35266;&#23519;&#21518;&#21488;&#20219;&#21153;&#30340;&#36816;&#34892;&#35268;&#24459;&#65292;&#20998;&#20139;&#20102;&#19981;&#23569;&#23454;&#36341;&#20013;&#36393;&#36807;&#30340;&#22353;&#65306;&#20026;&#20102;&#25552;&#39640;&#21487;&#38752;&#24615;&#32780;&#39057;&#32321;&#37325;&#26032;&#25552;&#20132;&#20219;&#21153;&#65292;&#21487;&#33021;&#21453;&#32780;&#25226;&#19968;&#20010;&#21363;&#23558;&#33719;&#24471;&#25191;&#34892;&#26426;&#20250;&#30340;&#20219;&#21153;&#19981;&#26029;&#21521;&#21518;&#25512;&#65307;force quit&#12289;&#38271;&#26102;&#38388;&#19981;&#25171;&#24320; App&#12289;Low Power Mode&#12289;&#35774;&#22791;&#37325;&#21551;&#31561;&#29992;&#25143;&#34892;&#20026;&#21644;&#31995;&#32479;&#29366;&#24577;&#65292;&#37117;&#20250;&#24433;&#21709;&#21518;&#21488;&#20219;&#21153;&#33719;&#24471;&#25191;&#34892;&#26426;&#20250;&#65307;&#36229;&#36807;&#39044;&#23450;&#26102;&#38388;&#20173;&#26410;&#25191;&#34892;&#65292;&#20063;&#24182;&#19981;&#24847;&#21619;&#30528;&#35843;&#24230;&#20986;&#29616;&#20102;&#24322;&#24120;&#12290;</span></p><p><span>&#23545;&#20110;&#21518;&#21488;&#20219;&#21153;&#65292;&#24320;&#21457;&#32773;&#21162;&#21147;&#30340;&#26041;&#21521;&#19981;&#24212;&#35813;&#26159;&#23581;&#35797;&#31934;&#30830;&#23433;&#25490;&#25191;&#34892;&#26102;&#38388;&#65292;&#32780;&#26159;&#22312;&#31995;&#32479;&#24895;&#24847;&#25552;&#20379;&#25191;&#34892;&#26426;&#20250;&#26102;&#65292;&#23613;&#21487;&#33021;&#39640;&#25928;&#12289;&#27491;&#30830;&#22320;&#21033;&#29992;&#23427;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-03"><span>TipKit &#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#33853;&#22320;&#23454;&#36341; (The Memory Remains: TipKit in a Shipping App)</span></a></strong></h3><p><span>TipKit &#23398;&#36215;&#26469;&#24456;&#23481;&#26131;&#65292;&#20294;&#24819;&#22312;&#23454;&#38469;&#39033;&#30446;&#20013;&#29992;&#22909;&#24182;&#19981;&#23481;&#26131;&#12290;&#30495;&#27491;&#30340;&#38590;&#28857;&#22312;&#20110;&#65306;&#20160;&#20040;&#26102;&#20505;&#19981;&#24212;&#35813;&#26174;&#31034;&#12289;&#22914;&#20309;&#36991;&#20813;&#24178;&#25200;&#29992;&#25143;&#65292;&#20197;&#21450;&#24590;&#26679;&#20445;&#35777;&#36825;&#22871;&#36923;&#36753;&#21487;&#27979;&#35797;&#12289;&#21487;&#32500;&#25252;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> &#22312;&#26412;&#25991;&#20013;&#20998;&#20139;&#20102;&#20182;&#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#20351;&#29992;&#32463;&#39564;&#65306;</span><code>@Parameter</code><span> &#26356;&#36866;&#21512;&#34920;&#31034;&#33021;&#22815;&#38543;&#26102;&#37325;&#26032;&#35745;&#31639;&#20986;&#30340;&#24403;&#21069;&#29366;&#24577;&#65292;&#32780; </span><code>Tips.Event</code><span> &#21017;&#36866;&#21512;&#35760;&#24405;&#26080;&#27861;&#20174;&#29616;&#26377;&#29366;&#24577;&#36824;&#21407;&#30340;&#21382;&#21490;&#34892;&#20026;&#65307;&#25152;&#26377; tip &#37117;&#24212;&#35813;&#36991;&#24320;&#20173;&#21487;&#33021;&#20986;&#29616; onboarding &#25110;&#20854;&#20182;&#21551;&#21160; UI &#30340;&#38454;&#27573;&#65307;</span><code>Tips.configure</code><span> &#27599;&#20010;&#36827;&#31243;&#21482;&#33021;&#29983;&#25928;&#19968;&#27425;&#65292;&#22240;&#27492;&#21021;&#22987;&#21270;&#39034;&#24207;&#12289;Debug &#24037;&#20855;&#21644;&#27979;&#35797;&#29615;&#22659;&#37117;&#38656;&#35201;&#22260;&#32469;&#36825;&#19968;&#38480;&#21046;&#35774;&#35745;&#12290;</span></p><blockquote><p><span>TipKit &#30340;&#31934;&#39635;&#19981;&#22312;&#20110;&#22806;&#22312;&#30340;&#35270;&#35273;&#25928;&#26524;&#65292;&#32780;&#22312;&#20110;&#20869;&#22312;&#30340;&#36923;&#36753;&#34920;&#36798;&#12290;&#23427;&#24110;&#21161;&#24320;&#21457;&#32773;&#20197;&#22768;&#26126;&#30340;&#26041;&#24335;&#25551;&#36848;&#25552;&#31034;&#29983;&#25104;&#30340;&#35268;&#21017;&#65292;&#32780;&#25552;&#31034;&#30340;&#20855;&#20307;&#23454;&#29616;&#23436;&#20840;&#21487;&#20197;&#33258;&#23450;&#20041;&#12290;&#25105;&#20204;&#21487;&#20197;&#25226; TipKit &#24819;&#35937;&#25104;&#19968;&#20010;&#21028;&#26029;&#25552;&#31034;&#26174;&#31034;&#38656;&#27714;&#30340;&#35268;&#21017;&#24341;&#25806;&#65292;&#33267;&#20110;&#22914;&#20309;&#21487;&#35270;&#21270;&#36825;&#20123;&#35268;&#21017;&#65292;&#21017;&#21462;&#20915;&#20110;&#24320;&#21457;&#32773;&#33258;&#24049;&#12290;&#26356;&#22810;&#20851;&#20110;&#36825;&#19968;&#35270;&#35282;&#30340;&#35752;&#35770;&#65292;&#21487;&#20197;&#21442;&#38405; &#8288;</span><a href="https://fatbobman.com/zh/posts/mastering-tipkit-advance/"><span>&#25484;&#25569; TipKit&#65306;&#36827;&#38454;</span></a><span>&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-04"><span>&#20351;&#29992; Swift Charts &#26500;&#24314;&#26080;&#38556;&#30861;&#26085;&#21382;&#22270;&#34920; (Building an accessible calendar chart with Swift Charts)</span></a></strong></h3><p><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Swift Charts &#23454;&#29616;&#31867;&#20284; GitHub Contributions &#30340;&#26085;&#21382;&#22270;&#34920;&#12290;&#19981;&#36807;&#65292;&#25991;&#31456;&#26356;&#31934;&#24425;&#30340;&#37096;&#20998;&#22312;&#20110;&#23545; accessibility &#30340;&#22788;&#29702;&#12290;&#30001;&#20110;&#19981;&#21516;&#21608;&#30340;&#30456;&#21516; weekday &#20849;&#20139;&#32463;&#36807;&#24402;&#19968;&#21270;&#30340; x &#20540;&#65292;VoiceOver &#20250;&#23558;&#25972;&#21015;&#25968;&#25454;&#32452;&#21512;&#36215;&#26469;&#65292;&#32780;&#26080;&#27861;&#36880;&#26085;&#27983;&#35272;&#12290;&#20316;&#32773;&#36890;&#36807; </span><code>accessibilityChildren</code><span> &#20026; plot area &#21478;&#22806;&#26500;&#24314;&#20102;&#19968;&#22871;&#19982;&#35270;&#35273;&#24067;&#23616;&#23545;&#24212;&#30340; accessibility hierarchy&#65292;&#20174;&#32780;&#35299;&#20915;&#20102;&#36825;&#19968;&#38382;&#39064;&#12290;</span></p><blockquote><p><span>&#30001; Matthaus Woolard &#21644; &#8288;</span><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> &#21512;&#33879;&#30340; &#8288;</span><a href="https://books.nilcoalescing.com/swift-charts-beyond-the-basics"><span>Swift Charts Beyond the Basics</span></a><span> &#19968;&#20070;&#24050;&#20110;&#19978;&#21608;&#27491;&#24335;&#21457;&#24067;&#12290;&#23545;&#20110;&#24076;&#26395;&#20351;&#29992; Swift Charts &#21019;&#24314;&#39640;&#32423;&#25968;&#25454;&#21487;&#35270;&#21270;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#26412;&#19981;&#21487;&#22810;&#24471;&#30340;&#36827;&#38454;&#25945;&#31243;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-05"><span>Mac &#24212;&#29992;&#29420;&#31435;&#20998;&#21457;&#19982; DMG &#31614;&#21517;&#20844;&#35777;&#25351;&#21335; (Mac App Direct Distribution, DMG Signing &amp; Notarization Guide)</span></a></strong></h3><p><span>&#30456;&#27604;&#36890;&#36807; Mac App Store &#21457;&#24067;&#24212;&#29992;&#65292;&#30452;&#25509;&#20998;&#21457; macOS App &#38656;&#35201;&#24320;&#21457;&#32773;&#33258;&#24049;&#22788;&#29702;&#26356;&#22810;&#21457;&#24067;&#29615;&#33410;&#65306;Developer ID &#31614;&#21517;&#12289;DMG &#21046;&#20316;&#12289;notarization&#12289;staple &#20197;&#21450;&#26368;&#32456;&#30340; Gatekeeper &#39564;&#35777;&#65292;&#20219;&#20309;&#19968;&#20010;&#27493;&#39588;&#20986;&#29616;&#38382;&#39064;&#65292;&#37117;&#21487;&#33021;&#23548;&#33268;&#29992;&#25143;&#26080;&#27861;&#27491;&#24120;&#23433;&#35013;&#12290;&#8288;</span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> &#23436;&#25972;&#28436;&#31034;&#20102;&#19968;&#22871;&#20174; Xcode Archive&#12289;&#21046;&#20316; DMG&#65292;&#21040;&#26368;&#32456;&#31614;&#21517;&#12289;notarization &#21644;&#39564;&#35777;&#30340;&#21457;&#24067;&#24037;&#20316;&#27969;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-06"><span>&#22312; SwiftUI &#20013;&#20248;&#38597;&#28040;&#36153; SKIE Flow (Consuming SKIE Flows in SwiftUI)</span></a></strong></h3><p><span>&#22312;&#37319;&#29992; Kotlin Multiplatform&#65288;KMP&#65289;&#20849;&#20139;&#19994;&#21153;&#36923;&#36753;&#12289;&#20351;&#29992; SwiftUI &#26500;&#24314;&#21407;&#29983; UI &#30340;&#39033;&#30446;&#20013;&#65292;&#22914;&#20309;&#35753; Kotlin API &#26356;&#33258;&#28982;&#22320;&#34701;&#20837; Swift &#29983;&#24577;&#19968;&#30452;&#26159;&#19968;&#20010;&#37325;&#35201;&#38382;&#39064;&#12290;SKIE&#65288;Swift Kotlin Interface Enhancer&#65289;&#27491;&#26159;&#20026;&#25913;&#21892;&#36825;&#19968;&#20114;&#25805;&#20316;&#20307;&#39564;&#32780;&#29983;&#65292;&#23427;&#21487;&#20197;&#23558; Kotlin </span><code>Flow</code><span> &#36716;&#25442;&#20026; Swift </span><code>AsyncSequence</code><span>&#65292;&#35753; Swift &#31471;&#36890;&#36807;&#29087;&#24713;&#30340; Swift Concurrency &#26041;&#24335;&#28040;&#36153;&#25968;&#25454;&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/faogustavo"><span>Gustavo F&#227;o Valvassori</span></a><span> &#20171;&#32461;&#20102; SKIE &#38024;&#23545; SwiftUI &#25552;&#20379;&#30340;&#19968;&#32452; API&#65306;&#38500;&#20102;&#30452;&#25509;&#22312; </span><code>.task</code><span> &#20013;&#36890;&#36807; </span><code>AsyncSequence</code><span> &#33719;&#21462;&#25968;&#25454;&#65292;&#36824;&#21487;&#20197;&#20351;&#29992; </span><code>.collect</code><span> &#23558; Flow &#30340;&#21464;&#21270;&#32465;&#23450;&#21040; SwiftUI state&#65292;&#25110;&#32773;&#36890;&#36807; </span><code>Observing</code><span> wrapper &#38544;&#34255;&#29366;&#24577;&#31649;&#29702;&#65292;&#35753; Kotlin </span><code>StateFlow</code><span> &#30340;&#26368;&#26032;&#20540;&#30452;&#25509;&#21442;&#19982; View &#30340;&#26500;&#24314;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-07"><span>Sarunw &#30340; How to &#31995;&#21015;&#22238;&#24402;</span></a></strong></h3><p><span>&#8288;</span><a href="https://x.com/sarunw"><span>Sarunw</span></a><span> &#30340;&#21338;&#23458;&#19968;&#30452;&#26159;&#24456;&#22810;&#24320;&#21457;&#32773;&#33719;&#21462; Apple &#29983;&#24577;&#24320;&#21457;&#25216;&#24039;&#30340;&#20248;&#31168;&#36164;&#28304;&#12290;&#19981;&#36807;&#20174; 2023 &#24180;&#24213;&#24320;&#22987;&#65292;&#21338;&#23458;&#20415;&#20572;&#27490;&#20102;&#26356;&#26032;&#12290;&#19978;&#21608;&#65292;Sarunw &#37325;&#26032;&#24320;&#22987;&#21019;&#20316;&#65292;&#24182;&#22312;&#19968;&#21608;&#20869;&#36830;&#32493;&#25512;&#20986;&#20102;&#25968;&#31687; How to &#31995;&#21015;&#25991;&#31456;&#12290;&#24456;&#24320;&#24515;&#30475;&#21040;&#19968;&#20301;&#20248;&#31168;&#20869;&#23481;&#21019;&#20316;&#32773;&#22312;&#27785;&#23490;&#36817;&#19977;&#24180;&#21518;&#37325;&#26032;&#22238;&#24402;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-08"><span>JindoKit&#65306;&#22312; App &#20869;&#39044;&#35272;&#28789;&#21160;&#23707;&#30028;&#38754;</span></a></strong></h3><p><span>WidgetKit &#25552;&#20379;&#30340; Live Activity &#39044;&#35272;&#20027;&#35201;&#26381;&#21153;&#20110; Xcode &#20013;&#30340;&#24320;&#21457;&#19982;&#35843;&#35797;&#65307;&#23545;&#20110;&#20801;&#35768;&#29992;&#25143;&#36873;&#25321;&#20027;&#39064;&#12289;&#35843;&#25972;&#23637;&#31034;&#20869;&#23481;&#30340;&#24212;&#29992;&#65292;&#31995;&#32479;&#24182;&#26410;&#25552;&#20379;&#30456;&#24212;&#30340; App &#20869;&#39044;&#35272;&#26041;&#26696;&#12290;</span></p><p><span>&#30001; &#8288;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#24320;&#21457;&#30340; JindoKit&#65292;&#23558; WidgetKit &#39118;&#26684;&#30340; Dynamic Island API &#24102;&#20837;&#26222;&#36890; SwiftUI View&#65292;&#35753; App &#33021;&#22815;&#30452;&#25509;&#39044;&#35272;&#23637;&#24320;&#12289;&#32039;&#20945;&#21644;&#26368;&#23567;&#19977;&#31181;&#28789;&#21160;&#23707;&#24418;&#24577;&#12290;&#30001;&#20110;&#20854; API &#19982; WidgetKit &#30340;&#32467;&#26500;&#39640;&#24230;&#19968;&#33268;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#29992;&#30456;&#36817;&#30340;&#26041;&#24335;&#32452;&#32455;&#21508;&#20010;&#21306;&#22495;&#30340;&#20869;&#23481;&#65292;&#24182;&#22312; App &#37197;&#32622;&#30028;&#38754;&#19982; WidgetKit Extension &#20043;&#38388;&#22797;&#29992;&#30456;&#20851;&#35270;&#22270;&#21644;&#25968;&#25454;&#12290;&#26356;&#22810;&#20449;&#24687;&#35831;&#21442;&#38405;&#20316;&#32773;&#30340;&#20171;&#32461;&#25991;&#31456;&#65306;&#8288;</span><a href="https://openswiftuiproject.org/blog/preview-dynamic-island-presentations-with-jindokit/"><span>Preview Dynamic Island presentations in your app with JindoKit</span></a><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-09"><span>&#21807;&#38899;&#36755;&#20837;&#27861;</span></a></strong></h3><p><span>&#30001; &#8288;</span><a href="https://x.com/ShikiSuen"><span>Shiki Suen</span></a><span> &#24320;&#21457;&#30340;&#21807;&#38899;&#36755;&#20837;&#27861;&#65292;&#26159;&#19968;&#27454;&#38754;&#21521; macOS &#30340;&#24320;&#28304;&#20013;&#25991;&#36755;&#20837;&#27861;&#12290;&#36817;&#26399;&#25512;&#20986;&#30340;&#12300;&#29378;&#25340;&#27169;&#24335;&#12301;&#65292;&#25552;&#20379;&#20102;&#31867;&#20284;&#20013;&#25991;&#20043;&#26143;&#26234;&#33021;&#29378;&#25340;&#12289;&#25628;&#29399;&#25340;&#38899;&#12289;&#32043;&#20809;&#25340;&#38899;&#21644;&#21319;&#38451;&#25340;&#38899;&#65288;SunPinyin&#65289;&#30340;&#20813;&#36755;&#22768;&#35843;&#25171;&#23383;&#20307;&#39564;&#65292;&#37096;&#20998;&#35789;&#35821;&#36824;&#25903;&#25345;&#26356;&#28608;&#36827;&#30340;&#19981;&#23436;&#20840;&#25340;&#20889;&#12290;</span></p><p><span>&#23613;&#31649;&#25903;&#25345;&#31867;&#20284;&#29378;&#25340;&#27169;&#24335;&#30340;&#24320;&#28304;&#25340;&#38899;&#36755;&#20837;&#27861;&#24182;&#19981;&#23569;&#35265;&#65292;&#20294;&#22823;&#22810;&#21482;&#25903;&#25345;&#27721;&#35821;&#25340;&#38899;&#12290;&#21807;&#38899;&#20511;&#21161;&#33258;&#30740;&#30340;&#12300;&#40784;&#38081;&#24680;&#65288;Tekkon&#65289;&#12301;&#27880;&#25340;&#24341;&#25806;&#65292;&#23454;&#29616;&#20102;&#23545;&#33267;&#23569;&#20116;&#31181;&#26222;&#36890;&#35805;&#25340;&#38899;&#26041;&#26696;&#30340;&#29378;&#25340;&#25171;&#23383;&#25903;&#25345;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #150]]></title><description><![CDATA[AI Wanted to Give Up. The Human Didn&#8217;t.]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 24 Aug 2026 12:03:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!tevE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tevE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tevE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 424w, https://substackcdn.com/image/fetch/$s_!tevE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 848w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1272w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" width="1456" height="723" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/562962cc-e86a-4353-a789-ce4060881555_1918x953.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:723,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213936,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/212506288?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tevE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 424w, https://substackcdn.com/image/fetch/$s_!tevE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 848w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1272w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@orhakim?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Or Hakim</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-a-wooden-door-with-writing-on-it-C9ouVi19R6E?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>AI Wanted to Give Up. The Human Didn&#8217;t.</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-150/">Read on web &#8594;</a></p><p><span>Recently, while debugging an issue in the Intel Xe GPU driver, Linus Torvalds went through what he himself called a &#8220;&#8288;</span><a href="https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/%2B/818bebeb63dd6bf5f4e07e145f6cdbace520a34c"><span>debug session from hell</span></a><span>.&#8221; The eventual fix was almost absurdly simple: changing a </span><code>round_up()</code><span> to a </span><code>round_down()</code><span>. But finding that single line took 24 debugging patches and 18 kernel boots. Much of the tedious work along the way was done with the help of AI.</span></p><p><span>The most interesting part of the story, however, isn&#8217;t that &#8220;AI helped Linus fix a Linux kernel bug.&#8221; It&#8217;s that the AI tried to give up several times along the way. At one point, it explicitly told Linus that the problem was &#8220;impossible and unsolvable&#8221; and suggested ending the investigation. Linus rejected that conclusion. At his insistence, the AI kept faithfully carrying out new tasks despite repeatedly concluding that the problem could not be solved, and together they eventually traced the cause to something that required changing just a single line of code.</span></p><p><span>This offers a revealing glimpse into the rather subtle relationship between humans and AI today. As agents become more capable, we can delegate increasingly complete pieces of work to them: reading code, forming hypotheses, writing debugging tools, running validations, and even adjusting the next step based on new evidence. Much of the repetitive work that developers once had to perform themselves is being compressed, gradually pulling humans away from the details of execution.</span></p><p><span>But that doesn&#8217;t mean the human role is shrinking at the same pace. Quite the opposite. As AI begins to participate in analysis, make recommendations, and even offer judgments such as &#8220;this problem cannot be solved,&#8221; the responsibilities that remain with humans become clearer: deciding what is worth pursuing, knowing when to trust AI, and recognizing when to reject its conclusions.</span></p><p><span>Not every instance of human persistence will end as neatly as this one did. But sometimes, the reason to keep going just a little longer should not be so easily erased by an AI saying, &#8220;impossible.&#8221;</span></p><p><a href="https://fatbobman.com/en/weekly/issue-149/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-using-ai-to-delegating-work-to-ai/?utm_source=fatbobman%20weekly%20issue%20150&amp;utm_medium=web"><span>From Using AI to Delegating Work to AI: Some Thoughts</span></a></strong></h3><p><span>When a task already has clear goals, boundaries, and acceptance criteria, how can we truly hand it over to AI? The more complex the work an Agent can handle, the more prominent this question becomes. Model outputs can vary; as context grows longer, goals and rules may gradually fade; splitting work across multiple contexts introduces information loss and handoff drift. Having another model review the result does not necessarily mean things will naturally converge. All of these issues ultimately point to the same concept: delegatability.</span></p><p><span>This article presents some of my thoughts on AI delegatability: whether the scope of execution remains stable, whether the results can be trusted, whether the required investment is predictable, and when human intervention is necessary. Rather than pursuing the best possible result from any single run, I am more interested in how clear boundaries, acceptance criteria, externalized authoritative records, and sensible human-AI division of labor can help Agents remain stable across longer and more complex tasks, while ensuring that failures can be detected and corrected. The article concludes with the Task-Driven workflow I currently use, showing how these principles can be applied in practical AI-assisted development.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-1"><span>What is a package registry?</span></a></strong></h3><p><span>After </span><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>Swift Package Index joined Apple</span></a><span>, the two announced that they would work together to build a package registry for the Swift community. But how does a package registry differ from SwiftPM, which we have used for years, and the Package Index, which helps us discover and evaluate packages? </span><a href="https://mastodon.social/@daveverwer"><span>Dave Verwer</span></a><span> starts with SwiftPM&#8217;s current Git-based dependency model: traditional dependencies require fetching source code from a Git repository and checking out the appropriate version, while a registry can distribute published source archives directly through package IDs, without carrying Git history, while also making published versions immutable.</span></p><p><span>But the significance of a registry goes beyond making package downloads more lightweight. More importantly, it introduces a formal package publishing model and raises broader questions around developer identity, package scope ownership, version publishing, and software supply chain security. This article offers both a concise introduction to how Package Registry works and useful background for understanding the Swift package infrastructure that Apple and Swift Package Index are preparing to build.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-2"><span>Handling CoreBluetooth Timeouts and Task Cancellation Correctly</span></a></strong></h3><p><span>Wrapping CoreBluetooth&#8217;s delegate APIs in async/await with </span><code>withCheckedThrowingContinuation</code><span> is not particularly difficult. The real trouble begins with the exceptional paths: What happens if the callback never arrives? After a Task is cancelled, does the underlying Bluetooth operation keep running? And when a normal result, timeout, and cancellation occur almost simultaneously, which one should resume the continuation?</span></p><p><a href="https://juejin.cn/user/1865252320578487/posts"><span>ilawsonlu</span></a><span> explores these practical problems and explains how to build a more complete timeout and cancellation mechanism for asynchronous CoreBluetooth wrappers. The article clearly distinguishes between cancelling a Swift Task and cancelling the underlying operation, while the open-source library </span><a href="https://github.com/ilawsonlu/ArcBLEKit"><span>ArcBLEKit</span></a><span> demonstrates an approach to wrapping traditional delegate APIs in more robust Swift Concurrency APIs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-3"><span>What Is CloudKit? Apple&#8217;s Backend Explained</span></a></strong></h3><p><span>CloudKit is an important yet often underestimated piece of infrastructure in the Apple ecosystem. From simple cross-device data synchronization to shared data and public databases, it allows developers to provide their apps with backend capabilities deeply integrated with Apple platforms through iCloud, without having to build and maintain their own servers. With both SwiftData and Core Data able to integrate directly with CloudKit, many developers are already using it without necessarily interacting with the CloudKit API itself.</span></p><p><span>Starting from the basic requirements of a backend, </span><a href="https://x.com/seanallen_dev"><span>Sean Allen</span></a><span> systematically introduces CloudKit&#8217;s private, shared, and public databases, along with core concepts such as Container, Record, and Schema, and compares three approaches: SwiftData, Core Data, and using the CloudKit API directly. The article does not shy away from CloudKit&#8217;s limitations, including its dependence on the Apple ecosystem and iCloud, schema migration, cross-platform support, and constraints around complex server-side logic.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-4"><span>OCR Doesn&#8217;t Give You Text. It Gives You a Map</span></a></strong></h3><p><span>Vision OCR does not return a neatly organized block of text. Instead, it gives you a collection of observations with bounding boxes: array order does not represent reading order, word boundaries do not inherently exist, and relationships between fields cannot simply be inferred from what comes before or after. While developing a record-sleeve scanning feature, </span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> encountered four bugs in a single day that appeared different but all stemmed from the same mistaken assumption. Through these real-world cases, the article shows how to use coordinates to determine reading order, reconstruct word boundaries from spacing, and associate fields through spatial proximity. Even more instructive is the author&#8217;s testing approach: saving bounding boxes exposed by real images as fixtures, using pure geometric data to lock down each layout assumption, while retaining the original photos for end-to-end tests. As the title says, OCR does not give you text&#8212;it gives you a &#8220;map.&#8221; The actual text structure has to be reconstructed from spatial relationships.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-5"><span>6 ways to promote your app without spending a penny</span></a></strong></h3><p><span>For indie developers, finishing an app is often only the first step. Getting more people to discover it can be even harder. Kickstart, created by </span><a href="https://x.com/twostraws"><span>Paul Hudson</span></a><span>, outlines six promotional strategies in this article that require little to no financial investment: submitting to channels such as Indie App Showcase, cross-promoting with other indie developers through Kickstart Exchange, participating in communities where your target users gather, building your own mailing list, building in public, and continuously improving your App Store product page.</span></p><p><span>In addition, MacStories&#8217; </span><a href="https://x.com/viticci/status/2090835901538541640"><span>Federico Viticci</span></a><span> is looking for noteworthy new apps and app updates for his annual iOS 27 Review. If you are preparing an iOS 27 release, you can recommend your app to him via DM or email at </span><code>viticci@macstories.net</code><span>.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-6"><span>Amethyst Vein: An Open-Source, Cross-Platform Local Persistence Framework with SwiftData-Style APIs</span></a></strong></h3><p><span>Developed by </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia Koring</span></a><span>, Amethyst Vein is a local-first Swift ORM built on SQLite and SQLCipher, with APIs clearly inspired by SwiftData. It aims to bring SwiftData-style @Model, @Query, relationships, and migration APIs to Apple platforms, Linux, Android, and Windows. The project uses explicit versioned migrations, an Identity Map, and field-level synchronization, while supporting both SwiftUI and SwiftCrossUI.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-7"><span>DynamicNotch: Building Polished Notch and Screen-Edge Interactions for macOS</span></a></strong></h3><p><span>Developed by </span><a href="https://x.com/kirtandopamine"><span>Govi</span></a><span>, DynamicNotch is a macOS Swift Package designed for developers to create SwiftUI interfaces attached to the edges of the screen. It can present recording status, media controls, build progress, action confirmations, and compact views similar to Dynamic Island.</span></p><p><span>It properly handles safe areas, multiple displays, and the physical notch on MacBooks, supports all four screen edges, and can transition between compact and expanded states. DynamicNotch keeps its implementation deliberately focused: it handles geometry, clipping, positioning, and window presentation without imposing product-level logic such as gestures, notifications, or state management on developers.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-8"><span>SwiftTUI: Building Terminal Interfaces the SwiftUI Way</span></a></strong></h3><p><span>Developed by </span><a href="https://x.com/adam_zethraeus"><span>Adam Zethraeus</span></a><span>, SwiftTUI is a terminal user interface framework for Swift developers. It brings SwiftUI&#8217;s declarative programming model to the terminal: developers can build interactive interfaces using </span><code>View</code><span>, </span><code>@State</code><span>, </span><code>@Observable</code><span>, layout containers, focus, gestures, and animations, while the framework handles layout, input processing, and partial updates.</span></p><p><span>What makes SwiftTUI interesting is not simply that it lets you &#8220;write TUIs in Swift.&#8221; The same view code can run in macOS, Linux, and Windows terminals, and can also be deployed to the browser, WASI, and native SwiftUI containers. The counter on its </span><a href="https://swifttui.sh/"><span>official website</span></a><span> is itself a real SwiftTUI application, compiled to WebAssembly and running directly in the browser.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>AI &#24819;&#25918;&#24323;&#20102;&#65292;&#20154;&#27809;&#26377;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-150/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;Linus Torvalds &#22312;&#35843;&#35797;&#19968;&#20010; Intel Xe GPU &#39537;&#21160;&#38382;&#39064;&#26102;&#65292;&#32463;&#21382;&#20102;&#19968;&#22330;&#34987;&#20182;&#33258;&#24049;&#31216;&#20026;&#8220;</span><a href="https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/%2B/818bebeb63dd6bf5f4e07e145f6cdbace520a34c"><span>debug session from hell</span></a><span>&#8221;&#30340;&#28459;&#38271;&#25490;&#26597;&#12290;&#26368;&#32456;&#30340;&#20462;&#22797;&#31616;&#21333;&#24471;&#26377;&#20123;&#19981;&#21487;&#24605;&#35758;&#65306;&#25226;&#19968;&#22788; </span><code>round_up()</code><span> &#25913;&#25104; </span><code>round_down()</code><span>&#12290;&#20294;&#20026;&#20102;&#25214;&#21040;&#36825;&#19968;&#34892;&#20195;&#30721;&#65292;&#20182;&#21069;&#21518;&#28155;&#21152;&#20102; 24 &#20010;&#35843;&#35797; patch&#65292;&#21551;&#21160;&#20102; 18 &#27425; kernel&#12290;&#20854;&#20013;&#22823;&#37327;&#32321;&#29712;&#24037;&#20316;&#65292;&#37117;&#26159;&#22312; AI &#30340;&#24110;&#21161;&#19979;&#23436;&#25104;&#30340;&#12290;</span></p><p><span>&#36825;&#20010;&#25925;&#20107;&#26368;&#26377;&#24847;&#24605;&#30340;&#22320;&#26041;&#24182;&#19981;&#26159;&#8220;AI &#24110; Linus &#20462;&#22797;&#20102; Linux Kernel Bug&#8221;&#65292;&#32780;&#26159; AI &#22312;&#36807;&#31243;&#20013;&#25968;&#27425;&#24819;&#35201;&#25918;&#24323;&#12290;&#23427;&#26366;&#26126;&#30830;&#21578;&#35785; Linus&#65292;&#36825;&#20010;&#38382;&#39064;&#8220;impossible and unsolvable&#8221;&#65292;&#24314;&#35758;&#20572;&#27490;&#32487;&#32493;&#35843;&#26597;&#12290;Linus &#27809;&#26377;&#25509;&#21463;&#36825;&#20010;&#21028;&#26029;&#12290;&#22312;&#20182;&#30340;&#22362;&#25345;&#19979;&#65292;AI &#34429;&#28982;&#25968;&#27425;&#35748;&#20026;&#38382;&#39064;&#24050;&#32463;&#26080;&#27861;&#35299;&#20915;&#65292;&#21364;&#20173;&#28982;&#24544;&#23454;&#22320;&#25191;&#34892;&#26032;&#30340;&#20219;&#21153;&#65292;&#26368;&#32456;&#21644;&#20182;&#19968;&#36215;&#25214;&#21040;&#20102;&#37027;&#20010;&#21482;&#38656;&#35201;&#20462;&#25913;&#19968;&#34892;&#20195;&#30721;&#30340;&#21407;&#22240;&#12290;</span></p><p><span>&#36825;&#20854;&#23454;&#24456;&#22909;&#22320;&#23637;&#29616;&#20102;&#29616;&#38454;&#27573;&#20154;&#19982; AI &#20043;&#38388;&#19968;&#31181;&#39047;&#20026;&#24494;&#22937;&#30340;&#20851;&#31995;&#12290;&#38543;&#30528; Agent &#33021;&#21147;&#19981;&#26029;&#22686;&#24378;&#65292;&#25105;&#20204;&#24050;&#32463;&#21487;&#20197;&#25226;&#36234;&#26469;&#36234;&#23436;&#25972;&#30340;&#24037;&#20316;&#20132;&#32473; AI&#65306;&#38405;&#35835;&#20195;&#30721;&#12289;&#25552;&#20986;&#20551;&#35774;&#12289;&#32534;&#20889;&#35843;&#35797;&#24037;&#20855;&#12289;&#25191;&#34892;&#39564;&#35777;&#65292;&#29978;&#33267;&#26681;&#25454;&#26032;&#30340;&#32467;&#26524;&#19981;&#26029;&#35843;&#25972;&#19979;&#19968;&#27493;&#34892;&#21160;&#12290;&#36807;&#21435;&#38656;&#35201;&#24320;&#21457;&#32773;&#20146;&#33258;&#23436;&#25104;&#30340;&#22823;&#37327;&#37325;&#22797;&#21171;&#21160;&#27491;&#22312;&#34987;&#21387;&#32553;&#65292;&#20154;&#20063;&#22240;&#27492;&#36880;&#28176;&#20174;&#20855;&#20307;&#30340;&#25191;&#34892;&#36807;&#31243;&#20013;&#25277;&#31163;&#20986;&#26469;&#12290;</span></p><p><span>&#20294;&#36825;&#24182;&#19981;&#24847;&#21619;&#30528;&#20154;&#30340;&#20316;&#29992;&#27491;&#22312;&#20197;&#21516;&#26679;&#30340;&#36895;&#24230;&#32553;&#23567;&#12290;&#24688;&#24688;&#30456;&#21453;&#65292;&#24403; AI &#24320;&#22987;&#21442;&#19982;&#20998;&#26512;&#12289;&#25552;&#20986;&#24314;&#35758;&#65292;&#29978;&#33267;&#32473;&#20986;&#8220;&#36825;&#20010;&#38382;&#39064;&#26080;&#27861;&#35299;&#20915;&#8221;&#36825;&#26679;&#30340;&#21028;&#26029;&#26102;&#65292;&#20154;&#30495;&#27491;&#38656;&#35201;&#25215;&#25285;&#30340;&#32844;&#36131;&#21453;&#32780;&#21464;&#24471;&#26356;&#21152;&#28165;&#26224;&#65306;&#20915;&#23450;&#20160;&#20040;&#20540;&#24471;&#20570;&#65292;&#21028;&#26029;&#20160;&#20040;&#26102;&#20505;&#24212;&#35813;&#30456;&#20449; AI&#65292;&#21448;&#22312;&#20160;&#20040;&#26102;&#20505;&#25298;&#32477;&#23427;&#30340;&#32467;&#35770;&#12290;</span></p><p><span>&#23613;&#31649;&#24182;&#38750;&#25152;&#26377;&#20154;&#31867;&#30340;&#22362;&#25345;&#37117;&#20250;&#33719;&#24471;&#31867;&#20284;&#26412;&#27425;&#30340;&#22278;&#28385;&#32467;&#26524;&#65292;&#20294;&#26377;&#26102;&#20505;&#65292;&#20877;&#22362;&#25345;&#19968;&#19979;&#30340;&#29702;&#30001;&#65292;&#33267;&#23569;&#19981;&#24212;&#35813;&#34987; AI &#30340;&#19968;&#21477;&#8220;&#19981;&#21487;&#33021;&#8221;&#36731;&#26131;&#25273;&#21435;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-149/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-using-ai-to-delegating-work-to-ai/?utm_source=fatbobman%20weekly%20issue%20150&amp;utm_medium=web"><span>&#20174;&#20351;&#29992; AI &#21040;&#22996;&#25176; AI&#65306;&#25105;&#30340;&#19968;&#20123;&#24605;&#32771;</span></a></strong></h3><p><span>&#24403;&#19968;&#39033;&#24037;&#20316;&#24050;&#32463;&#26377;&#26126;&#30830;&#30446;&#26631;&#12289;&#36793;&#30028;&#21644;&#39564;&#25910;&#35201;&#27714;&#26102;&#65292;&#24590;&#26679;&#25226;&#23427;&#30495;&#27491;&#20132;&#32473; AI&#65311;Agent &#33021;&#23436;&#25104;&#30340;&#24037;&#20316;&#36234;&#22797;&#26434;&#65292;&#36825;&#20010;&#38382;&#39064;&#23601;&#36234;&#31361;&#20986;&#12290;&#27169;&#22411;&#30340;&#36755;&#20986;&#23384;&#22312;&#27874;&#21160;&#65307;&#19978;&#19979;&#25991;&#21464;&#38271;&#21518;&#65292;&#30446;&#26631;&#21644;&#35268;&#21017;&#21487;&#33021;&#36880;&#28176;&#28129;&#21270;&#65307;&#25286;&#36827;&#22810;&#20010;&#19978;&#19979;&#25991;&#65292;&#21448;&#20250;&#24102;&#26469;&#20449;&#24687;&#25439;&#22833;&#21644;&#20132;&#25509;&#20559;&#31227;&#12290;&#35753;&#21478;&#19968;&#20010;&#27169;&#22411;&#22797;&#26680;&#65292;&#20063;&#19981;&#24847;&#21619;&#30528;&#32467;&#26524;&#19968;&#23450;&#20250;&#33258;&#28982;&#25910;&#25947;&#12290;&#36825;&#20123;&#38382;&#39064;&#26368;&#32456;&#25351;&#21521;&#21516;&#19968;&#20010;&#35789;&#65306;&#21487;&#22996;&#25176;&#24615;&#12290;</span></p><p><span>&#26412;&#25991;&#26159;&#25105;&#23545; AI &#21487;&#22996;&#25176;&#24615;&#30340;&#19968;&#20123;&#24605;&#32771;&#65306;&#25191;&#34892;&#33539;&#22260;&#26159;&#21542;&#31283;&#23450;&#65292;&#32467;&#26524;&#33021;&#21542;&#34987;&#20449;&#20219;&#65292;&#25237;&#20837;&#26159;&#21542;&#21487;&#20197;&#39044;&#26399;&#65292;&#20197;&#21450;&#20160;&#20040;&#26102;&#20505;&#38656;&#35201;&#20154;&#20171;&#20837;&#12290;&#30456;&#27604;&#36861;&#27714;&#26576;&#19968;&#27425;&#25191;&#34892;&#30340;&#26368;&#22909;&#32467;&#26524;&#65292;&#25105;&#26356;&#20851;&#24515;&#22914;&#20309;&#36890;&#36807;&#26126;&#30830;&#36793;&#30028;&#12289;&#39564;&#25910;&#26631;&#20934;&#12289;&#22806;&#32622;&#30340;&#26435;&#23041;&#35760;&#24405;&#20197;&#21450;&#21512;&#29702;&#30340;&#20154;&#26426;&#20998;&#24037;&#65292;&#35753; Agent &#22312;&#26356;&#38271;&#12289;&#26356;&#22797;&#26434;&#30340;&#20219;&#21153;&#20013;&#20445;&#25345;&#31283;&#23450;&#65292;&#24182;&#35753;&#22833;&#36133;&#33021;&#22815;&#34987;&#21457;&#29616;&#21644;&#32416;&#27491;&#12290;&#25991;&#31456;&#26368;&#21518;&#20063;&#32467;&#21512;&#25105;&#30446;&#21069;&#20351;&#29992;&#30340; Task-Driven &#24037;&#20316;&#27969;&#65292;&#23637;&#31034;&#36825;&#20123;&#21407;&#21017;&#22914;&#20309;&#33853;&#23454;&#21040;&#23454;&#38469;&#30340; AI &#24320;&#21457;&#36807;&#31243;&#20013;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-1"><span>&#35748;&#35782; Swift &#21253;&#27880;&#20876;&#34920; (What is a package registry?)</span></a></strong></h3><p><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>Swift Package Index &#21152;&#20837; Apple</span></a><span> &#21518;&#65292;&#21452;&#26041;&#23459;&#24067;&#23558;&#20849;&#21516;&#24314;&#35774;&#19968;&#20010;&#38754;&#21521; Swift &#31038;&#21306;&#30340; package registry&#12290;&#20294; package registry &#19982;&#25105;&#20204;&#24050;&#32463;&#20351;&#29992;&#22810;&#24180;&#30340; SwiftPM&#65292;&#20197;&#21450;&#29992;&#20110;&#21457;&#29616;&#21644;&#35780;&#20272;&#21253;&#30340; Package Index&#65292;&#31350;&#31455;&#26377;&#20160;&#20040;&#21306;&#21035;&#65311;&#8288;</span><a href="https://mastodon.social/@daveverwer"><span>Dave Verwer</span></a><span> &#20174; SwiftPM &#24403;&#21069;&#22522;&#20110; Git &#30340;&#20381;&#36182;&#26041;&#24335;&#35762;&#36215;&#65306;&#20256;&#32479;&#20381;&#36182;&#38656;&#35201;&#20174; Git &#20179;&#24211;&#33719;&#21462;&#28304;&#30721;&#24182; checkout &#23545;&#24212;&#29256;&#26412;&#65292;&#32780; registry &#21487;&#20197;&#36890;&#36807; package ID &#30452;&#25509;&#20998;&#21457;&#24050;&#32463;&#21457;&#24067;&#30340;&#28304;&#30721; archive&#65292;&#26080;&#38656;&#25658;&#24102; Git history&#65292;&#21516;&#26102;&#21457;&#24067;&#21518;&#30340;&#29256;&#26412;&#20063;&#20855;&#26377;&#19981;&#21487;&#21464;&#24615;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;registry &#30340;&#24847;&#20041;&#24182;&#19981;&#21482;&#26159;&#35753; package &#19979;&#36733;&#21464;&#24471;&#26356;&#36731;&#37327;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;registry &#36824;&#24341;&#20837;&#20102;&#19968;&#22871;&#27491;&#24335;&#30340; package publishing &#27169;&#22411;&#65292;&#24182;&#36827;&#19968;&#27493;&#28041;&#21450;&#24320;&#21457;&#32773;&#36523;&#20221;&#12289;package scope &#25152;&#26377;&#26435;&#12289;&#29256;&#26412;&#21457;&#24067;&#20197;&#21450;&#36719;&#20214;&#20379;&#24212;&#38142;&#23433;&#20840;&#31561;&#38382;&#39064;&#12290;&#36825;&#31687;&#25991;&#31456;&#26082;&#26159;&#19968;&#31687;&#23545; Package Registry &#24037;&#20316;&#26041;&#24335;&#30340;&#31616;&#26126;&#20171;&#32461;&#65292;&#20063;&#20026;&#29702;&#35299; Apple &#19982; Swift Package Index &#25509;&#19979;&#26469;&#20934;&#22791;&#24314;&#35774;&#30340; Swift &#21253;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#25552;&#20379;&#20102;&#24456;&#22909;&#30340;&#32972;&#26223;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-2"><span>&#22914;&#20309;&#27491;&#30830;&#22788;&#29702; CoreBluetooth &#36229;&#26102;&#19982; Task Cancellation</span></a></strong></h3><p><span>&#29992; </span><code>withCheckedThrowingContinuation</code><span> &#23558; CoreBluetooth &#30340; delegate API &#23553;&#35013;&#25104; async/await &#24182;&#19981;&#22256;&#38590;&#65292;&#30495;&#27491;&#40635;&#28902;&#30340;&#26159;&#20043;&#21518;&#30340;&#24322;&#24120;&#36335;&#24452;&#65306;&#22914;&#26524; callback &#36831;&#36831;&#27809;&#26377;&#36820;&#22238;&#24590;&#20040;&#21150;&#65311;Task &#34987;&#21462;&#28040;&#21518;&#65292;&#24213;&#23618;&#34013;&#29273;&#25805;&#20316;&#26159;&#21542;&#20173;&#22312;&#32487;&#32493;&#65311;&#24403;&#27491;&#24120;&#32467;&#26524;&#12289;&#36229;&#26102;&#21644;&#21462;&#28040;&#20960;&#20046;&#21516;&#26102;&#21457;&#29983;&#26102;&#65292;&#21448;&#35813;&#30001;&#35841;&#26469; resume continuation&#65311;</span></p><p><a href="https://juejin.cn/user/1865252320578487/posts"><span>ilawsonlu</span></a><span> &#22260;&#32469;&#36825;&#20123;&#23454;&#38469;&#38382;&#39064;&#65292;&#20171;&#32461;&#20102;&#22914;&#20309;&#20026; CoreBluetooth &#30340;&#24322;&#27493;&#23553;&#35013;&#24314;&#31435;&#26356;&#23436;&#25972;&#30340; timeout &#19982; cancellation &#26426;&#21046;&#65292;&#24182;&#26126;&#30830;&#21306;&#20998;&#12300;&#21462;&#28040; Swift Task&#12301;&#19982;&#12300;&#21462;&#28040;&#24213;&#23618;&#25805;&#20316;&#12301;&#65292;&#21516;&#26102;&#36890;&#36807;&#24320;&#28304;&#24211; </span><a href="https://github.com/ilawsonlu/ArcBLEKit"><span>ArcBLEKit</span></a><span> &#23637;&#31034;&#20102;&#23558;&#20256;&#32479; delegate API &#23553;&#35013;&#25104;&#26356;&#20581;&#22766;&#30340; Swift Concurrency API &#30340;&#24605;&#36335;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-3"><span>&#35814;&#35299; CloudKit&#65306;Apple &#29983;&#24577;&#30340;&#21518;&#31471;&#26381;&#21153; (What Is CloudKit? Apple&#8217;s Backend Explained)</span></a></strong></h3><p><span>CloudKit &#26159; Apple &#29983;&#24577;&#20013;&#38750;&#24120;&#37325;&#35201;&#12289;&#21364;&#24120;&#24120;&#34987;&#20302;&#20272;&#30340;&#19968;&#22359;&#22522;&#30784;&#35774;&#26045;&#12290;&#20174;&#31616;&#21333;&#30340;&#36328;&#35774;&#22791;&#25968;&#25454;&#21516;&#27493;&#65292;&#21040;&#20849;&#20139;&#25968;&#25454;&#21644;&#20844;&#20849;&#25968;&#25454;&#24211;&#65292;&#23427;&#35753;&#24320;&#21457;&#32773;&#26080;&#38656;&#33258;&#34892;&#25645;&#24314;&#26381;&#21153;&#22120;&#65292;&#23601;&#33021;&#20381;&#25176; iCloud &#20026; App &#25552;&#20379;&#19968;&#22871;&#19982; Apple &#24179;&#21488;&#28145;&#24230;&#38598;&#25104;&#30340;&#21518;&#31471;&#33021;&#21147;&#12290;&#23588;&#20854;&#38543;&#30528; SwiftData &#21644; Core Data &#37117;&#33021;&#22815;&#30452;&#25509;&#25509;&#20837; CloudKit&#65292;&#35768;&#22810;&#24320;&#21457;&#32773;&#23454;&#38469;&#19978;&#24050;&#32463;&#22312;&#20351;&#29992;&#23427;&#65292;&#21482;&#26159;&#19981;&#19968;&#23450;&#38656;&#35201;&#30452;&#25509;&#38754;&#23545; CloudKit API&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/seanallen_dev"><span>Sean Allen</span></a><span> &#20174; backend &#30340;&#22522;&#26412;&#38656;&#27714;&#20986;&#21457;&#65292;&#31995;&#32479;&#20171;&#32461;&#20102; CloudKit &#30340; private&#12289;shared &#21644; public database&#65292;&#20197;&#21450; Container&#12289;Record&#12289;Schema &#31561;&#26680;&#24515;&#27010;&#24565;&#65292;&#24182;&#27604;&#36739;&#20102; SwiftData&#12289;Core Data &#21644;&#30452;&#25509;&#20351;&#29992; CloudKit API &#19977;&#31181;&#25509;&#20837;&#26041;&#24335;&#12290;&#25991;&#31456;&#24182;&#27809;&#26377;&#22238;&#36991;&#23427;&#30340;&#36793;&#30028;&#65292;&#21253;&#25324;&#23545; Apple &#29983;&#24577;&#21644; iCloud &#30340;&#20381;&#36182;&#12289;schema migration&#12289;&#36328;&#24179;&#21488;&#33021;&#21147;&#20197;&#21450;&#22797;&#26434;&#26381;&#21153;&#31471;&#36923;&#36753;&#30340;&#38480;&#21046;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-4"><span>&#37325;&#26032;&#35748;&#35782; OCR&#65306;&#23427;&#26159;&#31354;&#38388;&#22320;&#22270;&#65292;&#32780;&#38750;&#32431;&#25991;&#26412; (OCR Doesn&#8217;t Give You Text. It Gives You a Map)</span></a></strong></h3><p><span>Vision OCR &#36820;&#22238;&#30340;&#24182;&#19981;&#26159;&#19968;&#27573;&#24050;&#32463;&#32452;&#32455;&#22909;&#30340;&#25991;&#26412;&#65292;&#32780;&#26159;&#19968;&#32452;&#24102;&#26377; bounding box &#30340; observations&#65306;&#25968;&#32452;&#39034;&#24207;&#19981;&#20195;&#34920;&#38405;&#35835;&#39034;&#24207;&#12289;&#21333;&#35789;&#36793;&#30028;&#24182;&#19981;&#23384;&#22312;&#65292;&#23383;&#27573;&#20043;&#38388;&#30340;&#20851;&#31995;&#20063;&#19981;&#33021;&#31616;&#21333;&#36890;&#36807;&#21069;&#21518;&#20301;&#32622;&#21028;&#26029;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> &#22312;&#24320;&#21457;&#21809;&#29255;&#23553;&#22871;&#25195;&#25551;&#21151;&#33021;&#26102;&#65292;&#19968;&#22825;&#20869;&#36830;&#32493;&#36935;&#21040;&#20102;&#22235;&#20010;&#30475;&#20284;&#19981;&#21516;&#12289;&#23454;&#21017;&#26469;&#33258;&#21516;&#19968;&#38169;&#35823;&#20551;&#35774;&#30340; Bug&#12290;&#26412;&#25991;&#36890;&#36807;&#36825;&#20123;&#30495;&#23454;&#26696;&#20363;&#23637;&#31034;&#20102;&#22914;&#20309;&#21033;&#29992;&#22352;&#26631;&#35745;&#31639;&#38405;&#35835;&#39034;&#24207;&#12289;&#26681;&#25454;&#38388;&#36317;&#24674;&#22797;&#21333;&#35789;&#36793;&#30028;&#65292;&#24182;&#36890;&#36807;&#31354;&#38388;&#37051;&#36817;&#20851;&#31995;&#20851;&#32852;&#23383;&#27573;&#12290;&#26356;&#20540;&#24471;&#20511;&#37492;&#30340;&#26159;&#20316;&#32773;&#30340;&#27979;&#35797;&#26041;&#24335;&#65306;&#23558;&#30495;&#23454;&#22270;&#29255;&#26292;&#38706;&#20986;&#30340; bounding box &#20445;&#23384;&#20026; fixture&#65292;&#29992;&#32431;&#20960;&#20309;&#25968;&#25454;&#22266;&#23450;&#27599;&#19968;&#39033;&#24067;&#23616;&#20551;&#35774;&#65292;&#21516;&#26102;&#20445;&#30041;&#30495;&#23454;&#29031;&#29255;&#20316;&#20026;&#31471;&#21040;&#31471;&#27979;&#35797;&#12290;&#27491;&#22914;&#26631;&#39064;&#25152;&#35828;&#65292;OCR &#32473;&#20320;&#30340;&#19981;&#26159;&#25991;&#26412;&#65292;&#32780;&#26159;&#19968;&#24352;&#12300;&#22320;&#22270;&#12301;&#65292;&#30495;&#27491;&#30340;&#25991;&#26412;&#32467;&#26500;&#38656;&#35201;&#20174;&#31354;&#38388;&#20851;&#31995;&#20013;&#37325;&#26032;&#26500;&#24314;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-5"><span>&#29420;&#31435;&#24212;&#29992;&#38646;&#25104;&#26412;&#25512;&#24191;&#30340; 6 &#20010;&#31574;&#30053; (6 ways to promote your app without spending a penny)</span></a></strong></h3><p><span>&#23545;&#20110;&#29420;&#31435;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#20889;&#23436; App &#24448;&#24448;&#21482;&#26159;&#31532;&#19968;&#27493;&#65292;&#22914;&#20309;&#35753;&#26356;&#22810;&#20154;&#30693;&#36947;&#23427;&#21487;&#33021;&#26356;&#21152;&#22256;&#38590;&#12290;&#30001; &#8288;</span><a href="https://x.com/twostraws"><span>Paul Hudson</span></a><span> &#21019;&#24314;&#30340; Kickstart &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#25972;&#29702;&#20102;&#20845;&#31181;&#20960;&#20046;&#19981;&#38656;&#35201;&#36164;&#37329;&#25237;&#20837;&#30340;&#25512;&#24191;&#26041;&#24335;&#65306;&#21521; Indie App Showcase &#31561;&#28192;&#36947;&#25237;&#31295;&#12289;&#36890;&#36807; Kickstart Exchange &#19982;&#20854;&#20182;&#29420;&#31435;&#24320;&#21457;&#32773;&#20132;&#21449;&#25512;&#24191;&#12289;&#21442;&#19982;&#30446;&#26631;&#29992;&#25143;&#25152;&#22312;&#30340;&#31038;&#21306;&#12289;&#24314;&#31435;&#33258;&#24049;&#30340;&#37038;&#20214;&#21015;&#34920;&#12289;Build in Public&#65292;&#20197;&#21450;&#25345;&#32493;&#20248;&#21270; App Store &#20135;&#21697;&#39029;&#38754;&#12290;</span></p><p><span>&#21478;&#22806;&#65292;MacStories &#30340; </span><a href="https://x.com/viticci/status/2090835901538541640"><span>Federico Viticci</span></a><span> &#27491;&#22312;&#20026;&#24180;&#24230; iOS 27 Review &#23547;&#25214;&#20540;&#24471;&#20851;&#27880;&#30340;&#26032; App &#21644; App &#26356;&#26032;&#12290;&#22914;&#26524;&#20320;&#27491;&#22312;&#20934;&#22791; iOS 27 &#29256;&#26412;&#65292;&#21487;&#20197;&#36890;&#36807; DM &#25110;&#37038;&#20214; </span><code>viticci@macstories.net</code><span> &#21521;&#20182;&#25512;&#33616;&#33258;&#24049;&#30340;&#20316;&#21697;&#12290; &#8288;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-6"><span>Amethyst Vein&#65306;&#36328;&#24179;&#21488;&#12289;SwiftData &#39118;&#26684; API &#30340;&#24320;&#28304;&#26412;&#22320;&#25345;&#20037;&#21270;&#26694;&#26550;</span></a></strong></h3><p><span>&#30001; </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia Koring</span></a><span> &#24320;&#21457;&#30340; Amethyst Vein &#26159;&#19968;&#20010;&#26412;&#22320;&#20248;&#20808;&#30340; Swift ORM&#65292;&#37319;&#29992; SQLite &#19982; SQLCipher &#20316;&#20026;&#23384;&#20648;&#22522;&#30784;&#65292;API &#21017;&#26126;&#26174;&#20511;&#37492;&#20102; SwiftData&#12290;&#23427;&#35797;&#22270;&#25226; SwiftData &#39118;&#26684;&#30340; @Model&#12289;@Query&#12289;&#20851;&#31995;&#21644;&#36801;&#31227; API &#24102;&#21040; Apple&#12289;Linux&#12289;Android &#19982; Windows&#12290;&#39033;&#30446;&#37319;&#29992;&#26174;&#24335;&#29256;&#26412;&#21270;&#36801;&#31227;&#12289;Identity Map &#21644;&#23383;&#27573;&#32423;&#21516;&#27493;&#65292;&#24182;&#21516;&#26102;&#25903;&#25345; SwiftUI &#19982; SwiftCrossUI&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-7"><span>DynamicNotch&#65306;&#24110;&#21161;&#24320;&#21457;&#32773;&#20026; macOS &#26500;&#24314;&#31934;&#33268;&#30340;&#21016;&#28023;&#19982;&#23631;&#24149;&#36793;&#32536;&#20132;&#20114;</span></a></strong></h3><p><span>&#30001; </span><a href="https://x.com/kirtandopamine"><span>Govi</span></a><span> &#24320;&#21457;&#30340; DynamicNotch &#26159;&#19968;&#20010;&#19987;&#20026;&#24320;&#21457;&#32773;&#25171;&#36896;&#30340; macOS Swift Package&#65292;&#29992;&#20110;&#21019;&#24314;&#36148;&#38468;&#20110;&#23631;&#24149;&#36793;&#32536;&#30340; SwiftUI &#30028;&#38754;&#65292;&#21487;&#21576;&#29616;&#24405;&#38899;&#29366;&#24577;&#12289;&#23186;&#20307;&#25511;&#21046;&#12289;&#26500;&#24314;&#36827;&#24230;&#12289;&#25805;&#20316;&#30830;&#35748;&#65292;&#20197;&#21450;&#31867;&#20284; Dynamic Island &#30340;&#32039;&#20945;&#35270;&#22270;&#12290;</span></p><p><span>&#23427;&#33021;&#22949;&#21892;&#22788;&#29702;&#23433;&#20840;&#21306;&#22495;&#12289;&#22810;&#26174;&#31034;&#22120;&#21644; MacBook &#23454;&#20307;&#21016;&#28023;&#65292;&#25903;&#25345;&#19978;&#19979;&#24038;&#21491;&#22235;&#20010;&#26041;&#21521;&#65292;&#20063;&#21487;&#20197;&#22312;&#32039;&#20945;&#19982;&#23637;&#24320;&#29366;&#24577;&#20043;&#38388;&#20999;&#25442;&#12290;DynamicNotch &#30340;&#23454;&#29616;&#27604;&#36739;&#20811;&#21046;&#65292;&#21482;&#36127;&#36131;&#20960;&#20309;&#12289;&#35009;&#21098;&#12289;&#23450;&#20301;&#19982;&#31383;&#21475;&#21576;&#29616;&#65292;&#24182;&#26410;&#23558;&#25163;&#21183;&#12289;&#36890;&#30693;&#12289;&#29366;&#24577;&#31649;&#29702;&#31561;&#20135;&#21697;&#36923;&#36753;&#24378;&#21152;&#32473;&#20351;&#29992;&#32773;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-8"><span>SwiftTUI&#65306;&#29992; SwiftUI &#30340;&#26041;&#24335;&#26500;&#24314;&#32456;&#31471;&#30028;&#38754;</span></a></strong></h3><p><span>&#30001; </span><a href="https://x.com/adam_zethraeus"><span>Adam Zethraeus</span></a><span> &#24320;&#21457;&#30340; SwiftTUI &#26159;&#19968;&#20010;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#32456;&#31471;&#29992;&#25143;&#30028;&#38754;&#26694;&#26550;&#12290;&#23427;&#23558; SwiftUI &#30340;&#22768;&#26126;&#24335;&#32534;&#31243;&#27169;&#22411;&#24102;&#36827;&#32456;&#31471;&#65306;&#24320;&#21457;&#32773;&#21487;&#20197;&#20351;&#29992; </span><code>View</code><span>&#12289;</span><code>@State</code><span>&#12289;</span><code>@Observable</code><span>&#12289;&#24067;&#23616;&#23481;&#22120;&#12289;&#28966;&#28857;&#12289;&#25163;&#21183;&#19982;&#21160;&#30011;&#26500;&#24314;&#20132;&#20114;&#30028;&#38754;&#65292;&#30001;&#26694;&#26550;&#36127;&#36131;&#24067;&#23616;&#12289;&#36755;&#20837;&#22788;&#29702;&#21644;&#23616;&#37096;&#21047;&#26032;&#12290;</span></p><p><span>SwiftTUI &#30340;&#26377;&#36259;&#20043;&#22788;&#65292;&#19981;&#21482;&#26159;&#8220;&#29992; Swift &#20889; TUI&#8221;&#12290;&#21516;&#19968;&#22871;&#35270;&#22270;&#20195;&#30721;&#36824;&#21487;&#20197;&#36816;&#34892;&#20110; macOS&#12289;Linux &#21644; Windows &#32456;&#31471;&#65292;&#24182;&#36827;&#19968;&#27493;&#37096;&#32626;&#21040;&#27983;&#35272;&#22120;&#12289;WASI&#65292;&#20197;&#21450;&#21407;&#29983; SwiftUI &#23481;&#22120;&#65307;</span><a href="https://swifttui.sh/"><span>&#23448;&#32593;</span></a><span>&#25552;&#20379;&#30340;&#35745;&#25968;&#22120;&#23601;&#26159;&#19968;&#20010;&#30495;&#23454;&#30340; SwiftTUI &#24212;&#29992;&#65292;&#32463; WebAssembly &#32534;&#35793;&#21518;&#30452;&#25509;&#36816;&#34892;&#22312;&#32593;&#39029;&#20013;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #149]]></title><description><![CDATA[Who Is the Slower App Review Process Actually Stopping?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 17 Aug 2026 12:03:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uzTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uzTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uzTo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 424w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 848w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1272w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" width="1456" height="753" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:753,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:240752,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/211500446?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uzTo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 424w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 848w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1272w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@worldsbetweenlines?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Patrick Hendry</a><span> on </span><a href="https://unsplash.com/photos/two-silver-swords-on-shield-6CfpUEmNWAU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Who Is the Slower App Review Process Actually Stopping?</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-149/">Read on web &#8594;</a></p><p><span>Slower App Store reviews have become something more and more developers can clearly feel. In the age of vibe coding, the cost of building and iterating on apps has dropped dramatically, so it is not hard to understand why the review system is under greater pressure. The problem is that longer review times seem to be little more than a system overwhelmed by a growing volume of submissions, without a corresponding increase in the barriers that keep scam apps out of the store.</span></p><p><span>Recently, Jeff Johnson came across a highly suspicious Safari extension in the Mac App Store: its screenshots appeared to be AI-generated, advertised a nonexistent &#8220;4.9 out of 5&#8221; rating, and some of its five-star reviews were even dated before the app itself was released. Looking further, he found that the developer behind the extension had 41 apps on the App Store and had accumulated at least 368 approved review submissions over the past year&#8212;nearly one per day on average. Meanwhile, well-known developer Marco Arment&#8217;s new app had already been sitting in the review queue for 12 days.</span></p><p><span>This creates a rather awkward situation. On one hand, suspicious and potentially fraudulent apps can make it through review and climb the charts. On the other, AI has made rapid development and frequent iteration easier than ever, sending large numbers of both legitimate and high-risk submissions through the same review system and consuming its limited resources.</span></p><p><span>An &#8288;</span><a href="https://mjtsai.com/blog/2026/08/14/tabcontrol-scam-and-the-app-review-queue/"><span>urgent question</span></a><span> is becoming difficult to avoid: Should App Review continue to treat each submission in isolation?</span></p><p><span>Johnson suggests introducing something akin to a trust system, allowing developers with a long history of following the rules and maintaining a good review record to receive faster reviews, while directing more resources toward accounts that submit at unusually high volumes, publish apps in bulk, or exhibit other suspicious patterns. Critics worry that such a system could eventually turn into preferential treatment for well-known developers or those willing to pay, further raising the barrier to entry for newcomers to the App Store.</span></p><p><span>Now that AI has dramatically reduced the cost of producing apps, a review model that treats every submission as an isolated case is becoming increasingly difficult to sustain. I see nothing unreasonable about incorporating factors such as a developer&#8217;s history, submission frequency, similarities among their apps, and metadata anomalies into risk assessment. A strong track record should not mean exemption from review, but rather fewer repetitive, low-value checks; suspicious accounts should not be barred from submitting, but should receive greater scrutiny.</span></p><p><span>Perhaps what App Review truly needs is not simply greater efficiency, but a shift from reviewing individual submissions in isolation toward evaluating patterns of developer behavior.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-148/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/contentbuilder-explained/?utm_source=fatbobman%20weekly%20issue%20149&amp;utm_medium=web"><span>ContentBuilder Explained: The Secret Behind SwiftUI&#8217;s Type-Checking Speedup</span></a></strong></h3><p><span>In the WWDC 2026 session on what&#8217;s new in SwiftUI, Apple engineers introduced a new SwiftUI feature: </span><code>ContentBuilder</code><span>. Judging by how you use it, it looks like nothing more than a </span><code>ViewBuilder</code><span> with a wider reach &#8212; APIs that previously accepted </span><code>ViewBuilder</code><span>, </span><code>ToolbarContentBuilder</code><span>, or </span><code>CommandsBuilder</code><span> separately can now share a single builder. Apple also claims the change delivers a significant improvement in type-checking performance. This article digs into what </span><code>ContentBuilder</code><span> actually is, and where that performance comes from.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-01"><span>Headless Xcode: From Prompt to Simulator with MCP</span></a></strong></h3><p><span>Xcode 27 beta 5 introduces </span><code>xcrun mcp-server</code><span>, allowing Xcode&#8217;s MCP capabilities to be exposed to external coding agents as a background service without launching the Xcode UI. </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> uses Claude Code to demonstrate a complete Headless Xcode workflow: creating an Xcode project, generating SwiftUI code, building the project and rendering previews, launching the Simulator, reading the accessibility hierarchy, performing interactions, and finally verifying app state through screenshots and OSLog. This means a complete development loop&#8212;from prompt to code, then execution and verification&#8212;is beginning to take shape without relying on the Xcode UI.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-02"><span>iOS 26: Data Detector</span></a></strong></h3><p><span>iOS 26 introduces the new </span><code>DataDetector</code><span>, providing a more modern, Swift-native alternative to the long-standing </span><code>NSDataDetector</code><span>. </span><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> walks through the new API with numerous examples: developers can obtain an </span><code>AsyncSequence</code><span> directly through </span><code>StringProtocol.dataDetectorMatches</code><span>, then use native Swift ranges and strongly typed semantic results to identify email addresses, phone numbers, dates, addresses, monetary amounts, measurements, flight numbers, shipment tracking numbers, and more. The new API not only feels more natural to use, but can also recognize a richer set of semantic objects.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-03"><span>Measuring Elapsed Time in Swift with ContinuousClock</span></a></strong></h3><p><span>Many developers still habitually use </span><code>Date()</code><span> to record start and end times, but </span><code>Date</code><span> isn&#8217;t the ideal tool for answering &#8220;how long did this operation take?&#8221; </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> explores the </span><code>Clock</code><span> system introduced in Swift 5.7 and explains two more reliable ways to measure time: </span><code>ContinuousClock</code><span> and </span><code>SuspendingClock</code><span>.</span></p><p><code>ContinuousClock</code><span> increases monotonically and continues counting while the device is asleep, making it suitable for measuring real-world elapsed time. </span><code>SuspendingClock</code><span>, by contrast, pauses while the device is asleep, making it more appropriate for measuring actual execution time. Kyle offers a simple rule of thumb: if </span><code>Date()</code><span> in your code is being used to &#8220;measure time&#8221; rather than &#8220;record a point in time,&#8221; you should probably consider replacing it with </span><code>ContinuousClock</code><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-04"><span>From XCUITest to Promo Video</span></a></strong></h3><p><span>Every change to an app&#8217;s interface can mean recreating App Store screenshots, promotional videos, and assets for different languages. </span><a href="https://x.com/No_Wham"><span>Noam Efergan</span></a><span> proposes an interesting solution: treat marketing assets as reproducible build artifacts. Using launch arguments and fixed test data, he makes the real app enter deterministic UI states on demand, then uses XCUITest to automatically capture screenshots across different locales before passing the results to Remotion to generate promotional videos. Rather than maintaining a separate mock UI for marketing, the entire workflow keeps the actual running SwiftUI interface as its source material. It also demonstrates another value of testability beyond testing: when an app can reliably and precisely reproduce a given state, the same capability can support debugging, demos, localization, and automated marketing content production.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-05"><span>Software Engineering fundamentals matter more than ever</span></a></strong></h3><p><span>As coding agents become capable of rapidly generating code, completing tests, and even independently implementing fairly complex features, &#8220;can it be built?&#8221; is gradually becoming one of the easier questions in software development. </span><a href="https://x.com/heckj"><span>Joseph Heck</span></a><span> argues that the genuinely difficult parts have not disappeared: designing clear boundaries and abstractions, making software debuggable, maintainable, and composable, and making sensible tradeoffs among competing constraints. AI can significantly reduce implementation costs, but it cannot replace the software engineering skills built on experience, judgment, and a long-term perspective. In a sense, as &#8220;writing code that works&#8221; becomes easier, software engineering fundamentals matter more than ever.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-06"><span>Why Soft Skills Matter More Than Technical Skills in the Age of AI</span></a></strong></h3><p><span>If the previous article discusses &#8220;how to build software well&#8221; in the age of AI, </span><a href="https://twitter.com/azamsharp"><span>Mohammad Azam</span></a><span> takes the question one step further: first, we need to decide &#8220;what should be built.&#8221; As AI continues to reduce the cost of implementation, understanding the business, clarifying requirements, asking the right questions, communicating and collaborating, and evaluating tradeoffs become even more important. AI can produce ten implementation approaches in seconds, but it doesn&#8217;t know why a particular business rule exists within a company, nor can it take responsibility for the final product on behalf of the developer. Technical skills have not lost their value&#8212;they remain the foundation for judging whether AI-generated results are sound. What may become scarcer in the future is not the ability to &#8220;write more code,&#8221; but the ability to understand the problem, make sound judgments, and ultimately solve the right problem.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-07"><span>GlyphKit: Precise Glyph Layout in SwiftUI with Vector Outlines</span></a></strong></h3><p><span>Displaying a character in SwiftUI is easy, but making a glyph precisely occupy a specified region is not. </span><code>Text</code><span> is designed primarily for text layout, where baselines, font metrics, and Dynamic Type can all influence the final result.</span></p><p><span>GlyphKit takes a different approach by treating glyphs as graphics: it extracts the vector outline (</span><code>CGPath</code><span>) of an individual character through Core Text and renders it with SwiftUI Canvas, providing more direct control over size and positioning. GlyphKit is not a replacement for </span><code>Text</code><span>. It is better suited to individual decorative glyphs, while complex graphemes, ligatures, and content that requires text accessibility should still be handled by a full text layout system.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#36234;&#26469;&#36234;&#24930;&#30340; App Review&#65292;&#25318;&#20303;&#20102;&#35841;&#65311;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-149/">&#32593;&#39029;&#29256;</a></strong></p><p><span>App Store &#23457;&#26680;&#21464;&#24930;&#65292;&#24050;&#32463;&#26159;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#33021;&#22815;&#26126;&#26174;&#24863;&#21463;&#21040;&#30340;&#21464;&#21270;&#12290;&#22312; Vibe Coding &#26102;&#20195;&#65292;App &#30340;&#24320;&#21457;&#21644;&#36845;&#20195;&#25104;&#26412;&#22823;&#24133;&#38477;&#20302;&#65292;&#23457;&#26680;&#21387;&#21147;&#38543;&#20043;&#22686;&#21152;&#24182;&#19981;&#38590;&#29702;&#35299;&#12290;&#20294;&#38382;&#39064;&#22312;&#20110;&#65292;&#26356;&#24930;&#30340;&#23457;&#26680;&#20284;&#20046;&#21482;&#26159;&#34987;&#19981;&#26029;&#22686;&#38271;&#30340;&#25552;&#20132;&#25968;&#37327;&#25302;&#22446;&#65292;&#21364;&#27809;&#26377;&#30456;&#24212;&#25552;&#39640;&#35784;&#39575; App &#36827;&#20837;&#21830;&#24215;&#30340;&#38376;&#27099;&#12290;</span></p><p><span>&#26368;&#36817;&#65292;Jeff Johnson &#22312; Mac App Store &#20013;&#21457;&#29616;&#20102;&#19968;&#27454;&#39047;&#20026;&#21487;&#30097;&#30340; Safari &#25193;&#23637;&#65306;&#25130;&#22270;&#30097;&#20284; AI &#29983;&#25104;&#65292;&#23637;&#31034;&#30528;&#24182;&#19981;&#23384;&#22312;&#30340;&#8220;4.9 &#20998;&#8221;&#35780;&#20998;&#65292;&#37096;&#20998;&#20116;&#26143;&#35780;&#35770;&#29978;&#33267;&#26089;&#20110; App &#30340;&#19978;&#26550;&#26102;&#38388;&#12290;&#32487;&#32493;&#35843;&#26597;&#21518;&#65292;&#20182;&#21457;&#29616;&#35813;&#25193;&#23637;&#30340;&#24320;&#21457;&#32773;&#22312; App Store &#20013;&#25317;&#26377; 41 &#27454; App&#65292;&#36807;&#21435;&#19968;&#24180;&#33267;&#23569;&#20135;&#29983;&#20102; 368 &#27425;&#33719;&#25209;&#30340;&#23457;&#26680;&#25552;&#20132;&#65292;&#24179;&#22343;&#20960;&#20046;&#27599;&#22825;&#19968;&#27425;&#12290;&#32780;&#22312;&#21516;&#19968;&#26102;&#38388;&#65292;&#33879;&#21517;&#24320;&#21457;&#32773; Marco Arment &#30340;&#26032; App &#21364;&#24050;&#32463;&#22312;&#23457;&#26680;&#38431;&#21015;&#20013;&#31561;&#24453;&#20102; 12 &#22825;&#12290;</span></p><p><span>&#36825;&#24418;&#25104;&#20102;&#19968;&#31181;&#39047;&#20026;&#23604;&#23596;&#30340;&#23616;&#38754;&#65306;&#19968;&#26041;&#38754;&#65292;&#21487;&#30097;&#29978;&#33267;&#28041;&#23244;&#35784;&#39575;&#30340; App &#33021;&#22815;&#36890;&#36807;&#23457;&#26680;&#24182;&#22312;&#25490;&#34892;&#27036;&#19978;&#39640;&#27468;&#29467;&#36827;&#65307;&#21478;&#19968;&#26041;&#38754;&#65292;AI &#21448;&#35753;&#24555;&#36895;&#24320;&#21457;&#12289;&#39057;&#32321;&#36845;&#20195;&#21464;&#24471;&#21069;&#25152;&#26410;&#26377;&#22320;&#23481;&#26131;&#65292;&#22823;&#37327;&#27491;&#24120;&#25552;&#20132;&#19982;&#39640;&#39118;&#38505;&#25552;&#20132;&#20849;&#21516;&#28044;&#20837;&#21516;&#19968;&#22871;&#23457;&#26680;&#26426;&#21046;&#65292;&#25345;&#32493;&#28040;&#32791;&#26377;&#38480;&#30340;&#23457;&#26680;&#36164;&#28304;&#12290;</span></p><p><span>&#19968;&#20010;</span><a href="https://mjtsai.com/blog/2026/08/14/tabcontrol-scam-and-the-app-review-queue/"><span>&#32039;&#36843;&#30340;&#38382;&#39064;</span></a><span>&#25670;&#22312;&#30524;&#21069;&#65306;App Review &#26159;&#21542;&#36824;&#24212;&#35813;&#23396;&#31435;&#22320;&#23545;&#24453;&#27599;&#19968;&#27425;&#25552;&#20132;&#65311;</span></p><p><span>Johnson &#24314;&#35758;&#24341;&#20837;&#31867;&#20284;&#20449;&#29992;&#20307;&#31995;&#30340;&#26426;&#21046;&#65292;&#35753;&#38271;&#26399;&#36981;&#23432;&#35268;&#21017;&#12289;&#20445;&#25345;&#33391;&#22909;&#23457;&#26680;&#35760;&#24405;&#30340;&#24320;&#21457;&#32773;&#33719;&#24471;&#26356;&#24555;&#30340;&#23457;&#26680;&#65292;&#23558;&#26356;&#22810;&#36164;&#28304;&#25237;&#20837;&#39640;&#39057;&#12289;&#25209;&#37327;&#21644;&#23384;&#22312;&#24322;&#24120;&#34892;&#20026;&#30340;&#36134;&#21495;&#12290;&#21453;&#23545;&#32773;&#21017;&#25285;&#24515;&#65292;&#36825;&#26368;&#32456;&#21487;&#33021;&#28436;&#21464;&#25104;&#23545;&#30693;&#21517;&#24320;&#21457;&#32773;&#25110;&#20184;&#36153;&#24320;&#21457;&#32773;&#30340;&#20248;&#24453;&#65292;&#36827;&#19968;&#27493;&#25260;&#39640;&#26032;&#20154;&#36827;&#20837; App Store &#30340;&#38376;&#27099;&#12290;</span></p><p><span>&#22312; AI &#22823;&#24133;&#38477;&#20302; App &#29983;&#20135;&#25104;&#26412;&#20043;&#21518;&#65292;&#20165;&#20165;&#25226;&#27599;&#19968;&#27425; submission &#24403;&#20316;&#24444;&#27492;&#23396;&#31435;&#30340;&#23545;&#35937;&#36827;&#34892;&#23457;&#26680;&#65292;&#36825;&#31181;&#27169;&#24335;&#24050;&#32463;&#36234;&#26469;&#36234;&#38590;&#20197;&#20026;&#32487;&#12290;&#23558;&#24320;&#21457;&#32773;&#21382;&#21490;&#12289;&#25552;&#20132;&#39057;&#29575;&#12289;App &#20043;&#38388;&#30340;&#30456;&#20284;&#24230;&#12289;metadata &#24322;&#24120;&#31561;&#32435;&#20837;&#39118;&#38505;&#35780;&#20272;&#65292;&#25105;&#35748;&#20026;&#24182;&#26080;&#19981;&#22949;&#12290;&#20449;&#29992;&#33391;&#22909;&#19981;&#24847;&#21619;&#30528;&#20813;&#23457;&#65292;&#32780;&#26159;&#20943;&#23569;&#37325;&#22797;&#12289;&#20302;&#20215;&#20540;&#30340;&#26816;&#26597;&#65307;&#24322;&#24120;&#36134;&#21495;&#20063;&#19981;&#26159;&#31105;&#27490;&#25552;&#20132;&#65292;&#32780;&#26159;&#25509;&#21463;&#26356;&#28145;&#20837;&#30340;&#23457;&#26597;&#12290;</span></p><p><span>&#25110;&#35768; App Review &#30495;&#27491;&#38656;&#35201;&#21319;&#32423;&#30340;&#65292;&#19981;&#21482;&#26159;&#23457;&#26680;&#25928;&#29575;&#65292;&#32780;&#26159;&#20174;&#21333;&#28857;&#8220;&#23457;&#26680;&#8221;&#36808;&#21521;&#8220;&#34892;&#20026;&#21028;&#26029;&#8221;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-147/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/contentbuilder-explained/?utm_source=fatbobman%20weekly%20issue%20149&amp;utm_medium=web"><span>ContentBuilder &#35299;&#26512;&#65306;SwiftUI &#31867;&#22411;&#26816;&#26597;&#24615;&#33021;&#25552;&#21319;&#30340;&#31192;&#23494;</span></a></strong></h3><p><span>&#22312; WWDC 2026 &#30340; SwiftUI &#26032;&#21151;&#33021; Session &#20013;&#65292;&#33529;&#26524;&#24037;&#31243;&#24072;&#20171;&#32461;&#20102; SwiftUI &#30340;&#19968;&#20010;&#26032;&#29305;&#24615;&#8212;&#8212;</span><code>ContentBuilder</code><span>&#12290;&#20174;&#20351;&#29992;&#26041;&#24335;&#30475;&#65292;&#23427;&#20284;&#20046;&#21482;&#26159;&#19968;&#20010;&#35206;&#30422;&#33539;&#22260;&#26356;&#24191;&#30340; </span><code>ViewBuilder</code><span>&#65306;&#36807;&#21435;&#20998;&#21035;&#25509;&#21463; </span><code>ViewBuilder</code><span>&#12289;</span><code>ToolbarContentBuilder</code><span>&#12289;</span><code>CommandsBuilder</code><span> &#30340; API&#65292;&#22914;&#20170;&#21487;&#20197;&#20849;&#20139;&#21516;&#19968;&#20010; builder&#12290;&#33529;&#26524;&#21516;&#26102;&#23459;&#31216;&#65292;&#36825;&#39033;&#35843;&#25972;&#33021;&#22815;&#26174;&#33879;&#25913;&#21892;&#31867;&#22411;&#26816;&#26597;&#24615;&#33021;&#12290;&#26412;&#25991;&#23558;&#35299;&#26512; </span><code>ContentBuilder</code><span> &#30340;&#26412;&#36136;&#65292;&#25506;&#32034;&#24615;&#33021;&#25552;&#21319;&#32972;&#21518;&#30340;&#22885;&#22937;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-01"><span>&#26080;&#30028;&#38754; Xcode&#65306;&#21033;&#29992; MCP &#24314;&#31435; AI &#36741;&#21161;&#24320;&#21457;&#30340;&#20840;&#33258;&#21160;&#27969;&#31243; (Headless Xcode: From Prompt to Simulator with MCP)</span></a></strong></h3><p><span>Xcode 27 beta 5 &#26032;&#22686;&#20102; </span><code>xcrun mcp-server</code><span>&#65292;&#35753; Xcode &#30340; MCP &#33021;&#21147;&#21487;&#20197;&#22312;&#19981;&#21551;&#21160; Xcode UI &#30340;&#24773;&#20917;&#19979;&#65292;&#20197;&#21518;&#21488;&#26381;&#21153;&#30340;&#24418;&#24335;&#25552;&#20379;&#32473;&#22806;&#37096; Coding Agent&#12290;&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#20197; Claude Code &#20026;&#20363;&#65292;&#23436;&#25972;&#23637;&#31034;&#20102;&#19968;&#26465; Headless Xcode &#24037;&#20316;&#27969;&#65306;&#20174;&#21019;&#24314; Xcode &#24037;&#31243;&#12289;&#29983;&#25104; SwiftUI &#20195;&#30721;&#12289;&#26500;&#24314;&#39033;&#30446;&#21644;&#28210;&#26579; Preview&#65292;&#21040;&#21551;&#21160; Simulator&#12289;&#35835;&#21462; accessibility hierarchy&#12289;&#25191;&#34892;&#20132;&#20114;&#65292;&#24182;&#26368;&#32456;&#32467;&#21512;&#25130;&#22270;&#19982; OSLog &#39564;&#35777;&#24212;&#29992;&#29366;&#24577;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;&#20174; Prompt &#21040;&#20195;&#30721;&#65292;&#20877;&#21040;&#36816;&#34892;&#21644;&#39564;&#35777;&#65292;&#19968;&#20010;&#19981;&#20381;&#36182; Xcode UI &#30340;&#23436;&#25972;&#24320;&#21457;&#38381;&#29615;&#24050;&#32463;&#21021;&#20855;&#38607;&#24418;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-02"><span>iOS 26: Data Detector</span></a></strong></h3><p><span>iOS 26 &#24341;&#20837;&#20102;&#20840;&#26032;&#30340; </span><code>DataDetector</code><span>&#65292;&#20026;&#24050;&#32463;&#26381;&#24441;&#22810;&#24180;&#30340; </span><code>NSDataDetector</code><span> &#25552;&#20379;&#20102;&#19968;&#22871;&#26356;&#31526;&#21512;&#29616;&#20195; Swift &#39118;&#26684;&#30340;&#26367;&#20195;&#26041;&#26696;&#12290;&#8288;</span><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> &#36890;&#36807;&#22823;&#37327;&#31034;&#20363;&#20171;&#32461;&#20102;&#26032; API &#30340;&#20351;&#29992;&#26041;&#24335;&#65306;&#24320;&#21457;&#32773;&#21487;&#20197;&#30452;&#25509;&#36890;&#36807; </span><code>StringProtocol.dataDetectorMatches</code><span> &#33719;&#24471; </span><code>AsyncSequence</code><span>&#65292;&#24182;&#20351;&#29992; Swift &#21407;&#29983; Range &#21644;&#24378;&#31867;&#22411;&#30340;&#35821;&#20041;&#32467;&#26524;&#35782;&#21035;&#25991;&#26412;&#20013;&#30340;&#37038;&#31665;&#12289;&#30005;&#35805;&#21495;&#30721;&#12289;&#26085;&#26399;&#12289;&#22320;&#22336;&#12289;&#37329;&#39069;&#12289;&#24230;&#37327;&#20540;&#12289;&#33322;&#29677;&#21495;&#12289;&#29289;&#27969;&#21333;&#21495;&#31561;&#20869;&#23481;&#12290;&#26032; API &#19981;&#20165;&#20351;&#29992;&#36215;&#26469;&#26356;&#21152;&#33258;&#28982;&#65292;&#33021;&#22815;&#35782;&#21035;&#30340;&#35821;&#20041;&#23545;&#35937;&#20063;&#26356;&#21152;&#20016;&#23500;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-03"><span>&#29992; ContinuousClock &#26367;&#20195; Date() &#27979;&#37327;&#25345;&#32493;&#26102;&#38388; (Measuring Elapsed Time in Swift with ContinuousClock)</span></a></strong></h3><p><span>&#24456;&#22810;&#24320;&#21457;&#32773;&#20173;&#20064;&#24815;&#20351;&#29992; </span><code>Date()</code><span> &#35760;&#24405;&#24320;&#22987;&#21644;&#32467;&#26463;&#26102;&#38388;&#65292;&#20294; </span><code>Date</code><span> &#24182;&#19981;&#26159;&#22238;&#31572;&#8220;&#36825;&#27573;&#25805;&#20316;&#25345;&#32493;&#20102;&#22810;&#20037;&#8221;&#30340;&#29702;&#24819;&#24037;&#20855;&#12290;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#22260;&#32469; Swift 5.7 &#24341;&#20837;&#30340; </span><code>Clock</code><span> &#20307;&#31995;&#65292;&#20171;&#32461;&#20102;&#20004;&#31181;&#26356;&#21152;&#21487;&#38752;&#30340;&#26102;&#38388;&#27979;&#37327;&#26041;&#24335;&#65306;</span><code>ContinuousClock</code><span> &#21644; </span><code>SuspendingClock</code><span>&#12290;</span></p><p><code>ContinuousClock</code><span> &#21333;&#35843;&#36882;&#22686;&#65292;&#24182;&#21253;&#21547;&#35774;&#22791;&#20241;&#30496;&#26399;&#38388;&#32463;&#36807;&#30340;&#26102;&#38388;&#65292;&#36866;&#21512;&#34913;&#37327;&#30495;&#23454;&#19990;&#30028;&#20013;&#30340; elapsed time&#65307;</span><code>SuspendingClock</code><span> &#21017;&#20250;&#22312;&#35774;&#22791;&#20241;&#30496;&#26102;&#26242;&#20572;&#65292;&#26356;&#36866;&#21512;&#34913;&#37327;&#23454;&#38469;&#36816;&#34892;&#26102;&#38388;&#12290;Kyle &#32473;&#20986;&#20102;&#19968;&#20010;&#31616;&#21333;&#30340;&#24314;&#35758;&#65306;&#22914;&#26524;&#20195;&#30721;&#20013;&#30340; </span><code>Date()</code><span> &#26159;&#29992;&#26469;&#8220;&#35745;&#26102;&#8221;&#32780;&#19981;&#26159;&#8220;&#35760;&#24405;&#26102;&#38388;&#28857;&#8221;&#65292;&#36890;&#24120;&#23601;&#24212;&#35813;&#32771;&#34385;&#25442;&#25104; </span><code>ContinuousClock</code><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-04"><span>&#29992; XCUITest &#33258;&#21160;&#29983;&#25104; App &#23459;&#20256;&#35270;&#39057; (From XCUITest to Promo Video)</span></a></strong></h3><p><span>&#27599;&#27425;&#20462;&#25913; App &#30028;&#38754;&#65292;&#37117;&#21487;&#33021;&#24847;&#21619;&#30528; App Store &#25130;&#22270;&#12289;&#23459;&#20256;&#35270;&#39057;&#20197;&#21450;&#19981;&#21516;&#35821;&#35328;&#29256;&#26412;&#30340;&#32032;&#26448;&#38656;&#35201;&#37325;&#26032;&#21046;&#20316;&#12290;&#8288;</span><a href="https://x.com/No_Wham"><span>Noam Efergan</span></a><span> &#25552;&#20986;&#20102;&#19968;&#20010;&#24456;&#26377;&#24847;&#24605;&#30340;&#35299;&#20915;&#24605;&#36335;&#65306;&#23558;&#33829;&#38144;&#32032;&#26448;&#20063;&#35270;&#20026;&#21487;&#20197;&#37325;&#22797;&#29983;&#25104;&#30340; build artifacts&#12290;&#20182;&#36890;&#36807; launch arguments &#21644;&#22266;&#23450;&#30340;&#27979;&#35797;&#25968;&#25454;&#65292;&#35753;&#30495;&#23454; App &#21487;&#20197;&#38543;&#26102;&#36827;&#20837;&#30830;&#23450;&#30340; UI &#29366;&#24577;&#65292;&#20877;&#20351;&#29992; XCUITest &#33258;&#21160;&#23436;&#25104;&#19981;&#21516; locale &#19979;&#30340;&#25130;&#22270;&#65292;&#24182;&#23558;&#32467;&#26524;&#20132;&#32473; Remotion &#29983;&#25104;&#23459;&#20256;&#35270;&#39057;&#12290;&#25972;&#20010;&#27969;&#31243;&#24182;&#27809;&#26377;&#20026;&#20102;&#33829;&#38144;&#37325;&#26032;&#21046;&#20316;&#19968;&#22871; mock UI&#65292;&#32780;&#26159;&#22987;&#32456;&#20197;&#23454;&#38469;&#36816;&#34892;&#30340; SwiftUI &#30028;&#38754;&#20316;&#20026;&#32032;&#26448;&#26469;&#28304;&#12290;&#36825;&#20063;&#23637;&#31034;&#20102; testability &#22312;&#27979;&#35797;&#20043;&#22806;&#30340;&#21478;&#19968;&#23618;&#20215;&#20540;&#65306;&#24403;&#24212;&#29992;&#33021;&#22815;&#31283;&#23450;&#12289;&#20934;&#30830;&#22320;&#37325;&#29616;&#26576;&#20010;&#29366;&#24577;&#26102;&#65292;&#21516;&#19968;&#22871;&#33021;&#21147;&#20063;&#21487;&#20197;&#26381;&#21153;&#20110;&#35843;&#35797;&#12289;&#28436;&#31034;&#12289;&#26412;&#22320;&#21270;&#20197;&#21450;&#33829;&#38144;&#20869;&#23481;&#30340;&#33258;&#21160;&#21270;&#29983;&#20135;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-05"><span>AI &#26102;&#20195;&#65292;&#36719;&#20214;&#24037;&#31243;&#22522;&#26412;&#21151;&#27604;&#20197;&#24448;&#20219;&#20309;&#26102;&#20505;&#37117;&#26356;&#37325;&#35201; (Software Engineering fundamentals matter more than ever)</span></a></strong></h3><p><span>&#24403; Coding Agent &#24050;&#32463;&#33021;&#22815;&#24555;&#36895;&#29983;&#25104;&#20195;&#30721;&#12289;&#23436;&#25104;&#27979;&#35797;&#65292;&#29978;&#33267;&#29420;&#31435;&#23454;&#29616;&#30456;&#24403;&#22797;&#26434;&#30340;&#21151;&#33021;&#21518;&#65292;&#8220;&#33021;&#19981;&#33021;&#20570;&#20986;&#26469;&#8221;&#27491;&#22312;&#36880;&#28176;&#25104;&#20026;&#36719;&#20214;&#24320;&#21457;&#20013;&#26356;&#23481;&#26131;&#35299;&#20915;&#30340;&#38382;&#39064;&#12290;</span><a href="https://x.com/heckj"><span>Joseph Heck</span></a><span> &#35748;&#20026;&#65292;&#30495;&#27491;&#22256;&#38590;&#30340;&#37096;&#20998;&#20381;&#28982;&#27809;&#26377;&#28040;&#22833;&#65306;&#22914;&#20309;&#35774;&#35745;&#28165;&#26224;&#30340;&#36793;&#30028;&#19982;&#25277;&#35937;&#65292;&#22914;&#20309;&#35753;&#36719;&#20214;&#20855;&#22791;&#21487;&#35843;&#35797;&#24615;&#12289;&#21487;&#32500;&#25252;&#24615;&#21644;&#21487;&#32452;&#21512;&#24615;&#65292;&#20197;&#21450;&#22914;&#20309;&#22312;&#21508;&#31181;&#32422;&#26463;&#20043;&#38388;&#20570;&#20986;&#21512;&#29702;&#30340;&#21462;&#33293;&#12290;AI &#21487;&#20197;&#26174;&#33879;&#38477;&#20302;&#23454;&#29616;&#25104;&#26412;&#65292;&#21364;&#26080;&#27861;&#26367;&#20195;&#36825;&#20123;&#24314;&#31435;&#22312;&#32463;&#39564;&#12289;&#21028;&#26029;&#21644;&#38271;&#26399;&#35270;&#35282;&#20043;&#19978;&#30340;&#36719;&#20214;&#24037;&#31243;&#33021;&#21147;&#12290;&#26576;&#31181;&#24847;&#20041;&#19978;&#65292;&#24403;&#8220;&#20889;&#20986;&#33021;&#24037;&#20316;&#30340;&#20195;&#30721;&#8221;&#36234;&#26469;&#36234;&#23481;&#26131;&#65292;Software Engineering fundamentals &#21453;&#32780;&#21464;&#24471;&#26356;&#21152;&#37325;&#35201;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-06"><span>&#20026;&#20160;&#20040;&#35828;&#22312; AI &#26102;&#20195;&#65292;&#8220;&#23450;&#20041;&#38382;&#39064;&#8221;&#27604;&#8220;&#20889;&#20986;&#20195;&#30721;&#8221;&#26356;&#37325;&#35201;&#65311;(Why Soft Skills Matter More Than Technical Skills in the Age of AI)</span></a></strong></h3><p><span>&#22914;&#26524;&#19978;&#19968;&#31687;&#35752;&#35770;&#30340;&#26159; AI &#26102;&#20195;&#8220;&#24590;&#26679;&#25226;&#36719;&#20214;&#20570;&#22909;&#8221;&#65292;</span><a href="https://twitter.com/azamsharp"><span>Mohammad Azam</span></a><span> &#21017;&#25226;&#38382;&#39064;&#21521;&#21069;&#25512;&#36827;&#20102;&#19968;&#27493;&#65306;&#25105;&#20204;&#39318;&#20808;&#38656;&#35201;&#21028;&#26029;&#8220;&#24212;&#35813;&#20570;&#20160;&#20040;&#8221;&#12290;&#24403; AI &#19981;&#26029;&#38477;&#20302;&#20195;&#30721;&#23454;&#29616;&#30340;&#25104;&#26412;&#65292;&#29702;&#35299;&#19994;&#21153;&#12289;&#28548;&#28165;&#38656;&#27714;&#12289;&#25552;&#20986;&#27491;&#30830;&#30340;&#38382;&#39064;&#12289;&#27807;&#36890;&#21327;&#20316;&#20197;&#21450;&#35780;&#20272;&#21462;&#33293;&#30340;&#37325;&#35201;&#24615;&#21453;&#32780;&#26356;&#21152;&#31361;&#20986;&#12290;AI &#21487;&#20197;&#22312;&#20960;&#31186;&#38047;&#20869;&#32473;&#20986;&#21313;&#31181;&#23454;&#29616;&#26041;&#26696;&#65292;&#21364;&#19981;&#30693;&#36947;&#20844;&#21496;&#30340;&#26576;&#26465;&#19994;&#21153;&#35268;&#21017;&#20026;&#20309;&#23384;&#22312;&#65292;&#20063;&#26080;&#27861;&#26367;&#24320;&#21457;&#32773;&#25215;&#25285;&#26368;&#32456;&#20132;&#20184;&#30340;&#36131;&#20219;&#12290;&#25216;&#26415;&#33021;&#21147;&#24182;&#27809;&#26377;&#22240;&#27492;&#22833;&#21435;&#20215;&#20540;&#8212;&#8212;&#23427;&#20173;&#28982;&#26159;&#21028;&#26029; AI &#29983;&#25104;&#32467;&#26524;&#26159;&#21542;&#21512;&#29702;&#30340;&#22522;&#30784;&#65307;&#21482;&#26159;&#26410;&#26469;&#26356;&#21152;&#31232;&#32570;&#30340;&#65292;&#25110;&#35768;&#19981;&#20877;&#26159;&#8220;&#33021;&#22815;&#20889;&#20986;&#22810;&#23569;&#20195;&#30721;&#8221;&#65292;&#32780;&#26159;&#29702;&#35299;&#38382;&#39064;&#12289;&#20570;&#20986;&#21028;&#26029;&#65292;&#24182;&#26368;&#32456;&#35299;&#20915;&#27491;&#30830;&#38382;&#39064;&#30340;&#33021;&#21147;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-07"><span>GlyphKit&#65306;&#22312; SwiftUI &#20013;&#29992;&#30690;&#37327;&#36718;&#24275;&#31934;&#20934;&#25511;&#21046;&#23383;&#24418;&#25490;&#29256;</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#26174;&#31034;&#19968;&#20010;&#23383;&#31526;&#24456;&#31616;&#21333;&#65292;&#20294;&#35201;&#35753;&#23383;&#24418;&#31934;&#30830;&#22320;&#21344;&#25454;&#25351;&#23450;&#21306;&#22495;&#65292;&#21364;&#24182;&#19981;&#23481;&#26131;&#12290;Text &#30340;&#39318;&#35201;&#30446;&#26631;&#26159;&#25991;&#26412;&#25490;&#29256;&#65292;&#22522;&#32447;&#12289;&#23383;&#20307;&#24230;&#37327;&#20197;&#21450; Dynamic Type &#37117;&#21487;&#33021;&#21442;&#19982;&#26368;&#32456;&#24067;&#23616;&#12290;</span></p><p><span>GlyphKit &#36873;&#25321;&#25226;&#23383;&#24418;&#24403;&#20316;&#22270;&#24418;&#22788;&#29702;&#65306;&#36890;&#36807; Core Text &#25552;&#21462;&#21333;&#20010;&#23383;&#31526;&#30340;&#30690;&#37327;&#36718;&#24275;&#65288;CGPath&#65289;&#65292;&#20877;&#20351;&#29992; SwiftUI Canvas &#32472;&#21046;&#65292;&#20174;&#32780;&#33719;&#24471;&#26356;&#30452;&#25509;&#30340;&#23610;&#23544;&#19982;&#20301;&#32622;&#25511;&#21046;&#12290;GlyphKit &#24182;&#38750; Text &#30340;&#26367;&#20195;&#21697;&#12290;&#23427;&#26356;&#36866;&#21512;&#21333;&#20010;&#12289;&#35013;&#39280;&#24615;&#23383;&#24418;&#65307;&#22797;&#26434;&#23383;&#32032;&#12289;&#36830;&#23383;&#21450;&#38656;&#35201;&#25991;&#23383;&#36741;&#21161;&#21151;&#33021;&#30340;&#20869;&#23481;&#65292;&#20173;&#24212;&#20132;&#32473;&#23436;&#25972;&#30340;&#25991;&#26412;&#25490;&#29256;&#31995;&#32479;&#12290;</span></p><h2><strong><span>&#27714;&#36132;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-08"><span>[&#28145;&#22323; / &#19978;&#28023; / &#21271;&#20140;] &#25238;&#38899;&#30740;&#21457; - &#23458;&#25143;&#31471;&#28210;&#26579;&#24341;&#25806;&#30740;&#21457;&#24037;&#31243;&#24072;&#65288;iOS / &#36328;&#31471;&#28210;&#26579;&#65289;</span></a></strong></h3><h4><strong><span>&#22242;&#38431;&#20171;&#32461;</span></strong></h4><p><span>&#22242;&#38431;&#20171;&#32461;&#65306;&#25238;&#38899;&#30740;&#21457;&#37096;&#38376;&#36127;&#36131;&#22810;&#27454;&#22823;&#22411;&#20135;&#21697;&#30340;&#30740;&#21457;&#65292;&#21253;&#25324;&#20294;&#19981;&#38480;&#20110;&#25238;&#38899;&#12289;&#35199;&#29916;&#35270;&#39057;&#12289;&#27773;&#27700;&#38899;&#20048;&#12290; &#21152;&#20837;&#25105;&#20204;&#65292;&#20320;&#23558;&#26377;&#26426;&#20250;&#21442;&#19982;&#20159;&#32423;&#29992;&#25143;&#22330;&#26223;&#30340;&#24320;&#21457;&#19982;&#26550;&#26500;&#24037;&#20316;&#65292;&#20351;&#29992;&#21069;&#27839;&#30340;&#25216;&#26415;&#21161;&#21147;&#19994;&#21153;&#19968;&#36215;&#19981;&#26029;&#25104;&#38271;&#12290;</span></p><h4><strong><span>&#23703;&#20301;&#25551;&#36848;</span></strong></h4><ol><li><p><span>&#36127;&#36131;&#23458;&#25143;&#31471;&#36328;&#31471;&#28210;&#26579;&#22522;&#30784;&#26694;&#26550;&#30340;&#21151;&#33021;&#36845;&#20195;&#19982;&#24615;&#33021;&#20248;&#21270;&#65292;&#25345;&#32493;&#25552;&#21319;&#22797;&#26434;&#30028;&#38754;&#30340;&#27969;&#30021;&#24230;&#19982;&#31283;&#23450;&#24615;&#65307;</span></p></li><li><p><span>&#21442;&#19982;&#22768;&#26126;&#24335; UI &#26694;&#26550;&#22312; iOS &#19978;&#30340;&#33021;&#21147;&#24314;&#35774;&#65292;&#21253;&#25324;&#26680;&#24515;&#28210;&#26579;&#33021;&#21147;&#12289;&#31995;&#32479;&#29305;&#24615;&#36866;&#37197;&#19982;&#37197;&#22871;&#30740;&#21457;&#35774;&#26045;&#65307;</span></p></li><li><p><span>&#28145;&#20837;&#28210;&#26579;&#38142;&#36335;&#24320;&#23637;&#24615;&#33021;&#20998;&#26512;&#19982;&#35843;&#20248;&#65292;&#23450;&#20301;&#24182;&#35299;&#20915;&#21345;&#39039;&#12289;&#25481;&#24103;&#12289;&#20869;&#23384;&#19982;&#21551;&#21160;&#31561;&#20851;&#38190;&#38382;&#39064;&#65307;</span></p></li><li><p><span>&#21442;&#19982;&#28210;&#26579;&#24615;&#33021;&#30417;&#25511;&#20307;&#31995;&#24314;&#35774;&#65292;&#32467;&#21512;&#30417;&#25511;&#25968;&#25454;&#25512;&#21160;&#38382;&#39064;&#30340;&#33258;&#21160;&#21270;&#20998;&#26512;&#12289;&#24402;&#22240;&#19982;&#27835;&#29702;&#65307;</span></p></li><li><p><span>&#27785;&#28096;&#36890;&#29992;&#20248;&#21270;&#26041;&#26696;&#19982;&#25216;&#26415;&#20307;&#31995;&#65292;&#23545;&#22806;&#36827;&#34892;&#25216;&#26415;&#36755;&#20986;&#65292;&#25552;&#21319;&#20844;&#21496;&#23458;&#25143;&#31471;&#25972;&#20307;&#30740;&#21457;&#25928;&#29575;&#19982;&#25216;&#26415;&#24433;&#21709;&#21147;&#12290;</span></p></li></ol><h4><strong><span>&#23703;&#20301;&#35201;&#27714;</span></strong></h4><ol><li><p><span>&#26412;&#31185;&#21450;&#20197;&#19978;&#23398;&#21382;&#65292;&#35745;&#31639;&#26426;&#21450;&#30456;&#20851;&#19987;&#19994;&#65307;</span></p></li><li><p><span>3&#24180;&#20197;&#19978; iOS/Mac &#23458;&#25143;&#31471;&#24320;&#21457;&#32463;&#39564;&#65292;&#29087;&#24713; Apple SDK&#65292;&#29087;&#32451;&#25484;&#25569; Swift/C++&#65307;</span></p></li><li><p><span>&#29087;&#24713; SwiftUI/Compose &#31561;&#22768;&#26126;&#24335;UI&#26694;&#26550;&#30340;&#28210;&#26579;&#26426;&#21046;&#65292;&#25110;&#26377;&#36328;&#31471;UI&#26694;&#26550;&#30340;&#24320;&#21457;&#12289;&#33853;&#22320;&#32463;&#39564;&#65307;</span></p></li><li><p><span>&#20855;&#22791;&#25166;&#23454;&#30340;&#24615;&#33021;&#20248;&#21270;&#33021;&#21147;&#65292;&#29087;&#32451;&#20351;&#29992; Instruments&#12289;Time Profiler&#12289;Allocations&#12289;System Trace &#31561;&#24037;&#20855;&#36827;&#34892;&#20998;&#26512;&#19982;&#35843;&#20248;&#65307;</span></p></li><li><p><span>&#20855;&#26377;&#33391;&#22909;&#30340;&#20195;&#30721;&#39550;&#39533;&#33021;&#21147;&#19982;&#25216;&#26415;&#35774;&#35745;&#33021;&#21147;&#65292;&#33021;&#29420;&#31435;&#23436;&#25104;&#27169;&#22359;&#35774;&#35745;&#19982;&#22797;&#26434;&#38382;&#39064;&#25915;&#22362;&#65307;</span></p></li><li><p><span>&#33391;&#22909;&#30340;&#27807;&#36890;&#21327;&#20316;&#33021;&#21147;&#19982;&#26381;&#21153;&#24847;&#35782;&#65292;&#36131;&#20219;&#24515;&#24378;&#12289;&#33258;&#39537;&#21147;&#24378;&#12289;&#36861;&#27714;&#21331;&#36234;&#12290;</span></p></li></ol><h4><strong><span>&#32852;&#31995;&#26041;&#24335;</span></strong></h4><p><span>&#20869;&#25512;&#32852;&#31995;&#65306;&#37038;&#31665; </span><a href="mailto:yexulei.swift@bytedance.com"><span>yexulei.swift@bytedance.com</span></a></p><p><span>&#32852;&#31995;&#26102;&#35831;&#22791;&#27880;&#12300;&#23458;&#25143;&#31471;&#28210;&#26579;&#24341;&#25806; + &#22995;&#21517; + &#24037;&#20316;&#24180;&#38480;&#12301;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #148]]></title><description><![CDATA[Apple Intelligence Has Passed Chinese Government Review and Is Coming to China]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 10 Aug 2026 12:01:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!e-3Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e-3Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32428,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/210547203?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong><span>Apple Intelligence Has Passed Chinese Government Review and Is Coming to China</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-148/">Read on web &#8594;</a></p><p><span>At WWDC 26, Apple unveiled a new Apple Intelligence architecture. Gemini was introduced on the cloud side, while Apple also confirmed that its third-generation Apple Foundation Models were built in collaboration with Google. For a while, this made me think that bringing Apple Intelligence to China might actually become even more difficult.</span></p><p><span>But things moved faster than expected. In July, Apple Intelligence appeared on the latest list of generative AI services registered with China&#8217;s Cyberspace Administration of China (CAC). Then, just two days ago, Apple confirmed that Alibaba&#8217;s Qwen would be involved in the Chinese version of Apple Intelligence, and the integration briefly appeared in Apple&#8217;s official documentation. Although the document was temporarily taken down the day after going live on August 8, its detailed setup instructions and privacy descriptions had already revealed a fairly complete picture of how the integration would work. This suggests that the official launch of Apple Intelligence in China is now entering its final countdown.</span></p><p><span>In addition to Alibaba&#8217;s Qwen, the registration information also revealed that Baidu will participate deeply as a partner in the AI search and visual search capabilities of the Chinese version of Apple Intelligence. In other words, Apple can not only adjust the underlying models and service providers by region, but also rely on more than one partner within the same market.</span></p><p><span>As countries and regions continue to strengthen their requirements around privacy, data, and AI services, regional differences are becoming almost unavoidable. China is becoming Apple&#8217;s first major example of a new approach: keeping the overall Apple Intelligence product experience and developer interfaces relatively consistent, while selecting different underlying models based on local regulations and ecosystems. This model is likely to appear in more markets over time and could become an important part of Apple Intelligence&#8217;s global expansion.</span></p><p><span>For developers using Apple Intelligence APIs, this is also good news. If Apple can continue to maintain consistency at the API layer, developers should theoretically not need to maintain completely different implementations for different markets. It would also allow apps that rely heavily on Apple Intelligence capabilities to reach a much broader audience.</span></p><p><span>Gemini and Qwen may not be the two most prominent names in the Agent scenarios I use day to day, but both perform quite well in areas such as world knowledge and language understanding. Given that Apple Intelligence is currently more focused on system-level assistance, and that these partners also bring mature model infrastructure and extensive cloud service experience, Apple&#8217;s choices seem quite reasonable.</span></p><p><span>Apple Intelligence has become one of Apple&#8217;s most important entry points into the AI era. Its current capabilities are still somewhat short of my personal expectations, but starting in 2026, it is at least beginning to reach substantially more users around the world. Rather than focusing only on how many tasks it can complete today, I am more interested in seeing how Apple will use WWDC 2027 to bring AI more deeply into its hardware, operating systems, and services ecosystem.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-147/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/controlling-orphans-in-swiftui-text/?utm_source=fatbobman%20weekly%20issue%20148&amp;utm_medium=web"><span>Controlling Orphans in SwiftUI Text: Uncovering the Undocumented avoidsOrphans</span></a></strong></h3><p><span>SwiftUI&#8217;s </span><code>Text</code><span> has a default behavior: when the last line of a paragraph contains only a single orphaned word or character, it automatically moves an entire word group from the previous line down to avoid leaving it alone. While this behavior is often helpful, it can also leave excessive whitespace on the preceding line, especially in narrow layouts or mixed Chinese&#8211;English text, disrupting the visual balance of the paragraph. UIKit allows developers to disable this behavior through </span><code>NSParagraphStyle</code><span>, but SwiftUI exposes no public API for doing so. This article uncovers an undocumented SwiftUI API that has existed for quite some time&#8212;</span><code>avoidsOrphans</code><span>&#8212;allowing developers to regain control over this behavior.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-01"><span>An Even Closer Look at Protocols and Global Actors</span></a></strong></h3><p><span>As Swift&#8217;s concurrency model continues to evolve, some engineering decisions that once felt obvious are beginning to change alongside the language itself. In this article, </span><a href="https://mastodon.social/@mattiem"><span>Matt Massicotte</span></a><span> goes beyond the familiar question of whether </span><code>@MainActor</code><span> belongs on a protocol or individual methods, using it as a starting point to explore API design in the era of Swift Concurrency. Rather than promoting a so-called &#8220;best practice,&#8221; Matt emphasizes a broader principle: isolation is a constraint, and constraints should arise from real requirements&#8212;not from habit.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-02"><span>Weekly Tuist News #1</span></a></strong></h3><p><span>As AI agents become increasingly integrated into the development workflow, engineering tools such as Tuist are becoming more important&#8212;even for independent developers.</span></p><p><span>Longtime Tuist community contributor </span><a href="https://www.linkedin.com/in/gamehelper/"><span>Lee YoungJun</span></a><span> has launched a new series, Weekly Tuist News, dedicated to tracking the Tuist ecosystem. Rather than simply summarizing release notes, the series combines community updates with the author&#8217;s hands-on experience. In its debut issue, he covers SwifterPM becoming the default dependency restoration method, new controls for target cache invalidation, and Tuist&#8217;s </span><code>auth.md</code><span> support for coding agents, along with practical observations from real-world usage.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-03"><span>Preview Multiple SwiftUI View States with #Preview(arguments:)</span></a></strong></h3><p><span>Most SwiftUI components have more than one meaningful state: empty, loading, error, permission-restricted, and so on. During development, we often end up maintaining multiple nearly identical </span><code>#Preview</code><span> declarations or placing every state into a single </span><code>VStack</code><span>. Xcode 27&#8217;s new </span><code>#Preview(arguments:)</code><span> API is designed specifically for this scenario, generating multiple independent previews from a collection of state data while allowing each one to be inspected individually in the Canvas.</span></p><p><span>In the article, </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> also shares his approach to organizing previews: </span><code>arguments</code><span> should describe business states, not environments. Even as the API evolves, this separation between application state and runtime environment remains a valuable design principle.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-04"><span>Concentric Buttons with OS 27&#8217;s SwiftUI APIs</span></a></strong></h3><p><span>WWDC26 introduced </span><code>GeometryProxy.concentricCornerRadii</code><span>, allowing SwiftUI developers to access a container&#8217;s concentric corner radius information. However, </span><code>ButtonBorderShape</code><span> remains a closed type, making it impossible to create truly custom button border shapes directly. </span><a href="https://twitter.com/_al_we"><span>Alexander Wei&#223;</span></a><span> demonstrates how to leverage this new API together with </span><code>onGeometryChange</code><span>, a custom </span><code>ViewModifier</code><span>, and method overloading to build a concentric button solution that feels almost indistinguishable from a native SwiftUI API.</span></p><blockquote><p><span>For new APIs such as </span><code>GeometryProxy.concentricCornerRadii</code><span>, it usually takes only a few seconds to understand what they do. The real challenge comes when using them in production, where implementation details and framework limitations quickly surface. Rather than serving as an API introduction, this article explores those practical considerations and the scenarios where the API can be effectively applied.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-05"><span>Swift, AI, and the future of software development</span></a></strong></h3><p><span>AI has become an indispensable part of many developers&#8217; workflows, but beyond improving productivity, it is also quietly changing the relationship between developers and their code. In this article, </span><a href="https://x.com/tiborbodecs"><span>Tibor B&#246;decs</span></a><span> candidly reflects on his own experience over the past year: embracing AI for its efficiency while missing the satisfaction of writing code and deeply understanding problems; believing that AI will continue to reshape software development while hoping it remains a tool that augments human thinking rather than replacing it.</span></p><blockquote><p><span>Over the past months, I&#8217;ve found myself struggling with many of the same questions as Tibor B&#246;decs. While AI has taken away some of the joy and created a subtle sense of distance between myself, the code, and the products I build, I&#8217;ve also been working relentlessly to gain greater control over it&#8212;to make it an extension of my own thinking, rather than allowing myself to become an extension of it.</span></p></blockquote><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-06"><span>Gitwyn: A Git Client Designed Around the Xcode Workflow</span></a></strong></h3><p><span>Although Xcode&#8217;s built-in Git support has improved significantly over the past few releases, it still falls short in both usability and functionality for many everyday workflows. Developed by </span><a href="https://www.linkedin.com/in/karthikk9828/"><span>Karthik K</span></a><span>, Gitwyn is a native Git client designed around the Xcode workflow. Press &#8984;&#8679;E in any Xcode project to review changes, organize staged files, generate commit messages, and push code&#8212;all without leaving Xcode or switching to another Git tool.</span></p><p><span>One of Gitwyn&#8217;s standout features is its ability to generate commit messages locally using on-device Apple Intelligence based on staged changes. No network connection is required, and your source code never leaves your Mac. More importantly, it streamlines the entire flow of reviewing diffs, organizing commits, generating descriptions, and pushing changes, keeping Git operations within the Xcode development context.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-07"><span>VersionedDocC: Bringing Version Management to Swift-DocC</span></a></strong></h3><p><span>For years, every WWDC I would immediately open Apple&#8217;s developer documentation and use the &#8220;API Changes&#8221; feature to compare different Xcode and SDK releases, tracking newly introduced, modified, and deprecated APIs. Unfortunately, this incredibly useful capability disappeared after the documentation website redesign in 2025. Although the old comparison URLs still exist, they no longer present complete API changes.</span></p><p><span>Developed by </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span>, VersionedDocC brings this capability back to DocC. It adds a release orchestration layer on top of the existing Swift toolchain, generating stable URLs for different versions, providing a version selector, displaying public API differences between adjacent releases based on symbol graphs, and avoiding repeated builds of historical documentation through immutable caching. The project also includes a SwiftPM plugin, GitHub Action, and GitHub Pages workflow, with support for multi-platform symbol graphs, external modules, and standalone DocC catalogs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-08"><span>Swift Subprocess 1.0</span></a></strong></h3><p><span>After a year of iteration, Swift&#8217;s official </span><code>swift-subprocess</code><span> project released version 1.0 this week. It is a cross-platform subprocess library built on Swift Concurrency, providing a unified way to launch commands, supply input, stream output, and manage process termination and cancellation across macOS, Linux, Windows, Android, and BSD.</span></p><p><span>It is particularly well suited for Swift CLIs, build systems, server applications, developer tools, and macOS automation. Note that version 1.0 requires Swift 6.2 and is not intended for regular iOS applications. It also deliberately leaves higher-level features such as sandboxing, command authorization, and pseudo-terminals (PTYs) to other layers.</span></p><p><code>swift-subprocess</code><span> also fills an important missing piece for building native AI agents in Swift: reliably executing external tools, continuously receiving their output, and properly managing subprocess lifecycles. The model decides </span><em><span>what</span></em><span> to do, while Subprocess provides a more controllable, observable, and Swifty way to execute those decisions.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>Apple Intelligence &#24050;&#36890;&#36807;&#20013;&#22269;&#25919;&#24220;&#23457;&#26680;&#65292;&#21363;&#23558;&#22312;&#20013;&#22269;&#25552;&#20379;&#26381;&#21153;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-148/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#22312; WWDC 26 &#19978;&#65292;&#33529;&#26524;&#20844;&#24067;&#20102;&#26032;&#30340; Apple Intelligence &#26550;&#26500;&#65292;&#19981;&#20165;&#22312;&#20113;&#31471;&#24341;&#20837; Gemini&#65292;&#31532;&#19977;&#20195; Apple Foundation Models &#20063;&#30830;&#35748;&#30001;&#33529;&#26524;&#19982; Google &#21512;&#20316;&#26500;&#24314;&#12290;&#36825;&#19968;&#24230;&#35753;&#25105;&#20197;&#20026;&#65292;Apple Intelligence &#36827;&#20837;&#20013;&#22269;&#24066;&#22330;&#30340;&#38590;&#24230;&#21453;&#32780;&#36827;&#19968;&#27493;&#22686;&#21152;&#20102;&#12290;</span></p><p><span>&#20294;&#20107;&#24773;&#30340;&#21457;&#23637;&#27604;&#39044;&#24819;&#20013;&#26356;&#24555;&#12290;7 &#26376;&#65292;Apple Intelligence &#24050;&#32463;&#20986;&#29616;&#22312;&#20013;&#22269;&#22269;&#23478;&#20114;&#32852;&#32593;&#20449;&#24687;&#21150;&#20844;&#23460;&#65288;CAC&#65289;&#20844;&#24067;&#30340;&#26368;&#26032;&#19968;&#25209;&#29983;&#25104;&#24335; AI &#26381;&#21153;&#22791;&#26696;&#21517;&#21333;&#20013;&#12290;&#32780;&#23601;&#22312;&#20004;&#22825;&#21069;&#65292;&#33529;&#26524;&#21448;&#30830;&#35748;&#38463;&#37324;&#24052;&#24052; Qwen &#23558;&#21442;&#19982;&#20013;&#22269;&#29256; Apple Intelligence&#65292;&#24182;&#19968;&#24230;&#20986;&#29616;&#22312;&#33529;&#26524;&#30340;&#23448;&#26041;&#25991;&#26723;&#20013;&#12290;&#34429;&#28982;&#35813;&#25991;&#26723;&#22312; 8 &#26376; 8 &#26085;&#30701;&#26242;&#19978;&#32447;&#21518;&#20110;&#27425;&#26085;&#34987;&#26242;&#26102;&#25764;&#22238;&#65292;&#20294;&#20854;&#20013;&#35814;&#32454;&#30340;&#25805;&#20316;&#25351;&#24341;&#21644;&#38544;&#31169;&#35828;&#26126;&#65292;&#24050;&#32463;&#21521;&#22806;&#30028;&#25581;&#31034;&#20102;&#30456;&#24403;&#23436;&#25972;&#30340;&#38598;&#25104;&#26041;&#24335;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;Apple Intelligence &#22312;&#20013;&#22269;&#27491;&#24335;&#25552;&#20379;&#26381;&#21153;&#24050;&#32463;&#36827;&#20837;&#20498;&#35745;&#26102;&#12290;</span></p><p><span>&#38500;&#20102;&#38463;&#37324;&#24052;&#24052;&#30340; Qwen&#65292;&#22791;&#26696;&#20449;&#24687;&#36824;&#25259;&#38706;&#65292;&#30334;&#24230;&#20063;&#23558;&#20316;&#20026;&#21512;&#20316;&#20249;&#20276;&#28145;&#24230;&#21442;&#19982;&#20013;&#22269;&#29256; Apple Intelligence &#30340; AI &#25628;&#32034;&#19982;&#35270;&#35273;&#25628;&#32034;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;&#33529;&#26524;&#19981;&#20165;&#21487;&#20197;&#26681;&#25454;&#22320;&#21306;&#35843;&#25972;&#24213;&#23618;&#27169;&#22411;&#21644;&#26381;&#21153;&#25552;&#20379;&#21830;&#65292;&#32780;&#19988;&#36825;&#26679;&#30340;&#21512;&#20316;&#20851;&#31995;&#20063;&#24182;&#38750;&#21482;&#33021;&#30001;&#19968;&#23478;&#21378;&#21830;&#25215;&#25285;&#12290;</span></p><p><span>&#38543;&#30528;&#21508;&#20010;&#22269;&#23478;&#21644;&#22320;&#21306;&#23545;&#38544;&#31169;&#12289;&#25968;&#25454;&#20197;&#21450; AI &#26381;&#21153;&#30417;&#31649;&#35201;&#27714;&#30340;&#19981;&#26029;&#21152;&#24378;&#65292;&#21306;&#22495;&#21270;&#24046;&#24322;&#20960;&#20046;&#24050;&#32463;&#19981;&#21487;&#36991;&#20813;&#12290;&#33529;&#26524;&#27491;&#22312;&#20013;&#22269;&#29575;&#20808;&#23454;&#36341;&#19968;&#31181;&#26032;&#30340;&#26041;&#24335;&#65306;&#22312;&#20445;&#25345; Apple Intelligence &#25972;&#20307;&#20135;&#21697;&#20307;&#39564;&#21644;&#24320;&#21457;&#25509;&#21475;&#30456;&#23545;&#32479;&#19968;&#30340;&#21516;&#26102;&#65292;&#26681;&#25454;&#19981;&#21516;&#22320;&#21306;&#30340;&#27861;&#35268;&#19982;&#29983;&#24577;&#36873;&#25321;&#19981;&#21516;&#30340;&#24213;&#23618;&#27169;&#22411;&#12290;&#26410;&#26469;&#65292;&#36825;&#31181;&#27169;&#24335;&#24456;&#21487;&#33021;&#36824;&#20250;&#20986;&#29616;&#22312;&#26356;&#22810;&#24066;&#22330;&#65292;&#24182;&#25104;&#20026; Apple Intelligence &#20840;&#29699;&#21270;&#36807;&#31243;&#20013;&#30456;&#24403;&#37325;&#35201;&#30340;&#19968;&#37096;&#20998;&#12290;</span></p><p><span>&#23545;&#20110;&#20351;&#29992; Apple Intelligence API &#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#21516;&#26679;&#26159;&#19968;&#20010;&#22909;&#28040;&#24687;&#12290;&#22914;&#26524;&#33529;&#26524;&#33021;&#22815;&#32487;&#32493;&#32500;&#25345; API &#23618;&#30340;&#19968;&#33268;&#24615;&#65292;&#24320;&#21457;&#32773;&#29702;&#35770;&#19978;&#26080;&#38656;&#20026;&#20102;&#19981;&#21516;&#24066;&#22330;&#32500;&#25252;&#23436;&#20840;&#19981;&#21516;&#30340;&#23454;&#29616;&#26041;&#26696;&#65292;&#20063;&#24847;&#21619;&#30528;&#37027;&#20123;&#20197; Apple Intelligence &#33021;&#21147;&#20026;&#37325;&#35201;&#29305;&#33394;&#30340;&#24212;&#29992;&#65292;&#23558;&#26377;&#26426;&#20250;&#35302;&#36798;&#26356;&#24191;&#27867;&#30340;&#29992;&#25143;&#12290;</span></p><p><span>Gemini &#21644; Qwen &#25110;&#35768;&#24182;&#19981;&#26159;&#25105;&#26085;&#24120; Agent &#20351;&#29992;&#22330;&#26223;&#20013;&#26368;&#32768;&#30524;&#30340;&#20004;&#20010;&#21517;&#23383;&#65292;&#20294;&#23427;&#20204;&#22312;&#19990;&#30028;&#30693;&#35782;&#12289;&#35821;&#35328;&#29702;&#35299;&#31561;&#26041;&#38754;&#37117;&#26377;&#30456;&#24403;&#19981;&#38169;&#30340;&#34920;&#29616;&#12290;&#32771;&#34385;&#21040; Apple Intelligence &#24403;&#21069;&#26356;&#20559;&#21521;&#31995;&#32479;&#32423;&#36741;&#21161;&#33021;&#21147;&#65292;&#32780;&#36825;&#20123;&#21512;&#20316;&#20249;&#20276;&#21448;&#25317;&#26377;&#25104;&#29087;&#30340;&#27169;&#22411;&#22522;&#30784;&#35774;&#26045;&#21644;&#20113;&#26381;&#21153;&#32463;&#39564;&#65292;&#33529;&#26524;&#36825;&#26679;&#30340;&#36873;&#25321;&#20854;&#23454;&#30456;&#24403;&#21512;&#29702;&#12290;</span></p><p><span>Apple Intelligence &#24050;&#32463;&#25104;&#20026;&#33529;&#26524;&#22312; AI &#26102;&#20195;&#26368;&#37325;&#35201;&#30340;&#20837;&#21475;&#20043;&#19968;&#12290;&#23427;&#30446;&#21069;&#30340;&#33021;&#21147;&#36317;&#31163;&#25105;&#30340;&#20010;&#20154;&#26399;&#24453;&#20173;&#26377;&#19968;&#20123;&#36317;&#31163;&#65292;&#20294;&#33267;&#23569;&#20174; 2026 &#24180;&#24320;&#22987;&#65292;&#23427;&#27491;&#22312;&#30495;&#27491;&#35206;&#30422;&#20840;&#29699;&#26356;&#22810;&#29992;&#25143;&#12290;&#30456;&#27604;&#20110;&#20170;&#22825;&#23427;&#31350;&#31455;&#33021;&#23436;&#25104;&#22810;&#23569;&#20219;&#21153;&#65292;&#25105;&#26356;&#26399;&#24453; WWDC 2027 &#19978;&#65292;&#33529;&#26524;&#20250;&#22914;&#20309;&#36827;&#19968;&#27493;&#35753; AI &#28145;&#20837;&#34701;&#20837;&#33258;&#24049;&#30340;&#30828;&#20214;&#12289;&#31995;&#32479;&#19982;&#26381;&#21153;&#29983;&#24577;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-146/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/controlling-orphans-in-swiftui-text/?utm_source=fatbobman%20weekly%20issue%20148&amp;utm_medium=web"><span>&#22312; SwiftUI Text &#20013;&#25511;&#21046;&#23396;&#34892;&#65306;&#25366;&#25496;&#26410;&#20844;&#24320;&#30340; avoidsOrphans</span></a></strong></h3><p><span>SwiftUI &#30340; </span><code>Text</code><span> &#26377;&#19968;&#39033;&#40664;&#35748;&#34892;&#20026;&#65306;&#24403;&#27573;&#33853;&#26411;&#34892;&#21482;&#21097;&#19968;&#20010;&#23396;&#35789;&#25110;&#23396;&#23383;&#26102;&#65292;&#23427;&#20250;&#20027;&#21160;&#25226;&#19978;&#19968;&#34892;&#30340;&#23436;&#25972;&#35789;&#32452;&#19968;&#24182;&#25512;&#21040;&#26411;&#34892;&#65292;&#36991;&#20813;&#8220;&#33853;&#21333;&#8221;&#12290;&#36825;&#20221;&#20307;&#36148;&#22810;&#25968;&#26102;&#20505;&#26159;&#23545;&#30340;&#65292;&#20294;&#20195;&#20215;&#26159;&#19978;&#19968;&#34892;&#21487;&#33021;&#30041;&#19979;&#19968;&#22823;&#29255;&#31354;&#30333;&#8212;&#8212;&#22312;&#31364;&#23481;&#22120;&#25110;&#20013;&#33521;&#28151;&#25490;&#30340;&#22330;&#26223;&#20013;&#65292;&#21453;&#32780;&#30772;&#22351;&#20102;&#27573;&#33853;&#30340;&#22343;&#34913;&#12290;&#40635;&#28902;&#22312;&#20110;&#65292;UIKit &#20801;&#35768;&#24320;&#21457;&#32773;&#36890;&#36807; </span><code>NSParagraphStyle</code><span> &#20851;&#25481;&#36825;&#39033;&#31574;&#30053;&#65292;SwiftUI &#21364;&#27809;&#26377;&#25552;&#20379;&#20219;&#20309;&#20844;&#24320;&#25509;&#21475;&#12290;&#26412;&#25991;&#23558;&#25366;&#25496; SwiftUI &#20013;&#19968;&#20010;&#26089;&#24050;&#23384;&#22312;&#12289;&#21364;&#22987;&#32456;&#26410;&#26366;&#20844;&#24320;&#30340; API &#8212;&#8212; </span><code>avoidsOrphans</code><span>&#65292;&#35753;&#24320;&#21457;&#32773;&#37325;&#26032;&#25343;&#22238;&#36825;&#39033;&#25511;&#21046;&#26435;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-01"><span>&#20877;&#35848;&#21327;&#35758;&#19982;&#20840;&#23616; Actor &#30340;&#35774;&#35745;&#26435;&#34913; (An Even Closer Look at Protocols and Global Actors)</span></a></strong></h3><p><span>&#38543;&#30528; Swift &#24182;&#21457;&#27169;&#22411;&#19981;&#26029;&#28436;&#36827;&#65292;&#19968;&#20123;&#36807;&#21435;&#34987;&#35270;&#20026;&#29702;&#25152;&#24403;&#28982;&#30340;&#24037;&#31243;&#21462;&#33293;&#65292;&#20063;&#24320;&#22987;&#22240;&#35821;&#35328;&#33021;&#21147;&#30340;&#22686;&#24378;&#32780;&#21457;&#29983;&#21464;&#21270;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;&#8288;</span><a href="https://mastodon.social/@mattiem"><span>Matt Massicotte</span></a><span> &#24182;&#27809;&#26377;&#20572;&#30041;&#22312;&#35752;&#35770;&#8220;</span><code>@MainActor</code><span> &#24212;&#35813;&#25918;&#22312; protocol &#19978;&#36824;&#26159;&#26041;&#27861;&#19978;&#8221;&#65292;&#32780;&#26159;&#20511;&#27492;&#36827;&#19968;&#27493;&#25506;&#35752;&#20102; Swift &#24182;&#21457;&#26102;&#20195;&#30340; API &#35774;&#35745;&#24605;&#36335;&#12290;&#30456;&#27604;&#32473;&#20986;&#19968;&#31181;&#25152;&#35859;&#30340;&#8220;&#26368;&#20339;&#23454;&#36341;&#8221;&#65292;Matt &#26356;&#24378;&#35843;&#19968;&#31181;&#35774;&#35745;&#24605;&#36335;&#65306;&#38548;&#31163;&#26159;&#19968;&#31181;&#32422;&#26463;&#65292;&#24212;&#24403;&#28304;&#20110;&#30495;&#23454;&#38656;&#27714;&#65292;&#32780;&#19981;&#26159;&#27839;&#34989;&#26082;&#26377;&#20064;&#24815;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-02"><span>Tuist &#27599;&#21608;&#21160;&#24577;&#31532;&#19968;&#26399; (Weekly Tuist News #1)</span></a></strong></h3><p><span>&#38543;&#30528; AI Agent &#36234;&#26469;&#36234;&#28145;&#20837;&#24320;&#21457;&#27969;&#31243;&#65292;Tuist &#36825;&#31867;&#24037;&#31243;&#31649;&#29702;&#24037;&#20855;&#30340;&#37325;&#35201;&#24615;&#20063;&#22312;&#19981;&#26029;&#25552;&#21319;&#65292;&#23545;&#20110;&#29420;&#31435;&#24320;&#21457;&#32773;&#32780;&#35328;&#21516;&#26679;&#22914;&#27492;&#12290;</span></p><p><span>&#20316;&#20026;&#38271;&#26399;&#27963;&#36291;&#20110; Tuist &#31038;&#21306;&#30340;&#24320;&#21457;&#32773;&#65292;&#8288;</span><a href="https://www.linkedin.com/in/gamehelper/"><span>Lee YoungJun</span></a><span> &#25512;&#20986;&#20102;&#19968;&#20010;&#19987;&#38376;&#36861;&#36394; Tuist &#29983;&#24577;&#30340;&#26032;&#31995;&#21015; Weekly Tuist News&#12290;&#19982;&#21333;&#32431;&#27719;&#24635; release notes &#19981;&#21516;&#65292;&#36825;&#20010;&#31995;&#21015;&#36824;&#20250;&#32467;&#21512;&#31038;&#21306;&#21160;&#24577;&#20197;&#21450;&#20316;&#32773;&#22312;&#23454;&#38469;&#39033;&#30446;&#20013;&#30340;&#20351;&#29992;&#20307;&#39564;&#12290;&#22312;&#21019;&#21002;&#21495;&#20013;&#65292;&#20182;&#20171;&#32461;&#20102; SwifterPM &#25104;&#20026;&#40664;&#35748;&#20381;&#36182;&#24674;&#22797;&#26041;&#24335;&#12289;Target &#32531;&#23384;&#22833;&#25928;&#26465;&#20214;&#30340;&#26032;&#25511;&#21046;&#33021;&#21147;&#65292;&#20197;&#21450; Tuist &#38754;&#21521; Coding Agent &#30340; </span><code>auth.md</code><span> &#25903;&#25345;&#65292;&#24182;&#32467;&#21512;&#23454;&#38469;&#20351;&#29992;&#20998;&#20139;&#20102;&#33258;&#24049;&#30340;&#39564;&#35777;&#36807;&#31243;&#19982;&#35266;&#23519;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-03"><span>&#20351;&#29992; #Preview(arguments:) &#36731;&#26494;&#39044;&#35272; SwiftUI &#35270;&#22270;&#30340;&#22810;&#29366;&#24577;</span></a></strong></h3><p><span>&#22823;&#22810;&#25968; SwiftUI &#32452;&#20214;&#37117;&#19981;&#21482;&#26377;&#19968;&#31181;&#29366;&#24577;&#65306;&#31354;&#25968;&#25454;&#12289;&#21152;&#36733;&#20013;&#12289;&#38169;&#35823;&#12289;&#26435;&#38480;&#21463;&#38480;&#31561;&#12290;&#24320;&#21457;&#36807;&#31243;&#20013;&#65292;&#25105;&#20204;&#36890;&#24120;&#20250;&#32500;&#25252;&#19968;&#32452;&#37325;&#22797;&#30340; </span><code>#Preview</code><span>&#65292;&#25110;&#23558;&#25152;&#26377;&#29366;&#24577;&#25918;&#36827;&#19968;&#20010; </span><code>VStack</code><span> &#20013;&#32479;&#19968;&#23637;&#31034;&#12290;Xcode 27 &#26032;&#22686;&#30340; </span><code>#Preview(arguments:)</code><span> &#27491;&#26159;&#20026;&#36825;&#19968;&#22330;&#26223;&#32780;&#35774;&#35745;&#65292;&#23427;&#33021;&#22815;&#26681;&#25454;&#19968;&#32452;&#29366;&#24577;&#25968;&#25454;&#33258;&#21160;&#29983;&#25104;&#22810;&#20010;&#29420;&#31435;&#30340; Preview&#65292;&#24182;&#25903;&#25345;&#22312; Canvas &#20013;&#21333;&#29420;&#26597;&#30475;&#27599;&#19968;&#31181;&#29366;&#24577;&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#22312;&#25991;&#20013;&#20063;&#20998;&#20139;&#20102;&#20182;&#32452;&#32455; Preview &#30340;&#24605;&#36335;&#65306;</span><code>arguments</code><span> &#24212;&#35813;&#25551;&#36848;&#19994;&#21153;&#29366;&#24577;&#65288;State&#65289;&#65292;&#32780;&#19981;&#26159;&#29615;&#22659;&#65288;Environment&#65289;&#12290;&#21363;&#20351;&#26410;&#26469; API &#32487;&#32493;&#28436;&#36827;&#65292;&#36825;&#31181;&#23558;&#19994;&#21153;&#29366;&#24577;&#19982;&#36816;&#34892;&#29615;&#22659;&#20998;&#31163;&#30340;&#35774;&#35745;&#29702;&#24565;&#20381;&#28982;&#20855;&#26377;&#38271;&#26399;&#21442;&#32771;&#20215;&#20540;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-04"><span>&#29992; iOS 27 &#26032; API &#23454;&#29616; SwiftUI &#21516;&#24515;&#22278;&#35282;&#25353;&#38062; (Concentric Buttons with OS 27&#8217;s SwiftUI APIs)</span></a></strong></h3><p><span>WWDC 26 &#20013;&#65292;&#33529;&#26524;&#32473; SwiftUI &#26032;&#22686;&#20102; </span><code>GeometryProxy.concentricCornerRadii</code><span>&#65292;&#35753;&#24320;&#21457;&#32773;&#33021;&#22815;&#33719;&#21462;&#23481;&#22120;&#30340;&#21516;&#24515;&#22278;&#35282;&#20449;&#24687;&#12290;&#19981;&#36807;&#65292;</span><code>ButtonBorderShape</code><span> &#20173;&#28982;&#26159;&#19968;&#20010;&#23553;&#38381;&#31867;&#22411;&#65292;&#26080;&#27861;&#30452;&#25509;&#23454;&#29616;&#30495;&#27491;&#30340;&#33258;&#23450;&#20041;&#25353;&#38062;&#36793;&#26694;&#12290;&#8288;</span><a href="https://twitter.com/_al_we"><span>Alexander Wei&#223;</span></a><span> &#21033;&#29992;&#36825;&#19968;&#26032; API&#65292;&#32467;&#21512; </span><code>onGeometryChange</code><span>&#12289;&#33258;&#23450;&#20041; </span><code>ViewModifier</code><span> &#19982;&#26041;&#27861;&#37325;&#36733;&#65292;&#23454;&#29616;&#20102;&#19968;&#22871;&#20351;&#29992;&#26041;&#24335;&#20960;&#20046;&#19982;&#31995;&#32479; API &#26080;&#24322;&#30340;&#21516;&#24515;&#25353;&#38062;&#26041;&#26696;&#12290;</span></p><blockquote><p><span>&#23545;&#20110; </span><code>GeometryProxy.concentricCornerRadii</code><span> &#36825;&#31867;&#26032;&#22686; API&#65292;&#25105;&#20204;&#24448;&#24448;&#21482;&#38656;&#20960;&#31186;&#38047;&#23601;&#33021;&#30693;&#36947;&#23427;&#30340;&#20316;&#29992;&#65307;&#20294;&#30495;&#27491;&#24212;&#29992;&#21040;&#39033;&#30446;&#20013;&#26102;&#65292;&#25165;&#20250;&#21457;&#29616;&#36824;&#26377;&#19981;&#23569;&#23454;&#29616;&#32454;&#33410;&#21644;&#26694;&#26550;&#38480;&#21046;&#38656;&#35201;&#32771;&#34385;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#31687; API &#20171;&#32461;&#65292;&#19981;&#22914;&#35828; Alexander &#20998;&#20139;&#20102;&#23427;&#22312;&#23454;&#38469;&#20351;&#29992;&#20013;&#30340;&#27880;&#24847;&#20107;&#39033;&#65292;&#20197;&#21450;&#20540;&#24471;&#23581;&#35797;&#30340;&#24212;&#29992;&#22330;&#26223;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-05"><span>Swift&#12289;AI &#19982;&#36719;&#20214;&#24320;&#21457;&#30340;&#26410;&#26469;&#23637;&#26395; (Swift, AI, and the future of software development)</span></a></strong></h3><p><span>AI &#24050;&#32463;&#25104;&#20026;&#35768;&#22810;&#24320;&#21457;&#32773;&#24037;&#20316;&#27969;&#20013;&#19981;&#21487;&#25110;&#32570;&#30340;&#19968;&#37096;&#20998;&#65292;&#20294;&#23427;&#22312;&#25552;&#21319;&#25928;&#29575;&#30340;&#21516;&#26102;&#65292;&#20063;&#24708;&#28982;&#25913;&#21464;&#30528;&#24320;&#21457;&#32773;&#19982;&#20195;&#30721;&#20043;&#38388;&#30340;&#20851;&#31995;&#12290;&#8288;</span><a href="https://x.com/tiborbodecs"><span>Tibor B&#246;decs</span></a><span> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#30495;&#35802;&#20998;&#20139;&#20102;&#33258;&#24049;&#36825;&#19968;&#24180;&#26469;&#30340;&#22256;&#24785;&#65306;&#19968;&#26041;&#38754;&#20139;&#21463; AI &#24102;&#26469;&#30340;&#39640;&#25928;&#29575;&#65292;&#21478;&#19968;&#26041;&#38754;&#21448;&#24576;&#24565;&#20146;&#25163;&#20889;&#20195;&#30721;&#12289;&#28145;&#20837;&#29702;&#35299;&#38382;&#39064;&#30340;&#36807;&#31243;&#65307;&#26082;&#30456;&#20449; AI &#20250;&#25345;&#32493;&#25913;&#21464;&#36719;&#20214;&#24320;&#21457;&#65292;&#20063;&#24076;&#26395;&#23427;&#22987;&#32456;&#21482;&#26159;&#24110;&#21161;&#24320;&#21457;&#32773;&#24605;&#32771;&#19982;&#21019;&#36896;&#30340;&#24037;&#20855;&#65292;&#32780;&#19981;&#26159;&#21462;&#20195;&#24605;&#32771;&#26412;&#36523;&#12290;</span></p><blockquote><p><span>&#22312;&#36807;&#21435;&#19968;&#27573;&#26102;&#38388;&#20013;&#65292;AI &#32473;&#25105;&#24102;&#26469;&#30340;&#22256;&#24785;&#19982; Tibor B&#246;decs &#24456;&#30456;&#20284;&#12290;&#23613;&#31649;&#23427;&#35753;&#25105;&#22833;&#21435;&#20102;&#19968;&#20123;&#20048;&#36259;&#65292;&#23545;&#20195;&#30721;&#12289;&#23545;&#20135;&#21697;&#20135;&#29983;&#20102;&#26576;&#31181;&#30095;&#31163;&#24863;&#65292;&#20294;&#25105;&#20063;&#19968;&#30452;&#19981;&#25032;&#22320;&#23581;&#35797;&#23545; AI &#24314;&#31435;&#26356;&#24378;&#30340;&#25484;&#25511;&#21147;&#65292;&#35753;&#23427;&#26356;&#22909;&#22320;&#20026;&#25105;&#25152;&#29992;&#65292;&#25104;&#20026;&#25105;&#30340;&#22806;&#33041;&#65292;&#32780;&#19981;&#26159;&#35753;&#25105;&#27814;&#20026;&#23427;&#30340;&#36741;&#21161;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-06"><span>Gitwyn&#65306;&#22260;&#32469; Xcode &#24037;&#20316;&#27969;&#35774;&#35745;&#30340; Git &#23458;&#25143;&#31471;</span></a></strong></h3><p><span>&#23613;&#31649;&#36817;&#20960;&#20010;&#29256;&#26412;&#20013; Xcode &#30340; Git &#21151;&#33021;&#24050;&#32463;&#26377;&#20102;&#26126;&#26174;&#25913;&#21892;&#65292;&#20294;&#26080;&#35770;&#26159;&#20351;&#29992;&#20307;&#39564;&#36824;&#26159;&#21151;&#33021;&#23436;&#25972;&#24615;&#65292;&#20173;&#38590;&#20197;&#28385;&#36275;&#37096;&#20998;&#24320;&#21457;&#32773;&#30340;&#22312;&#19981;&#21516;&#22330;&#26223;&#19979;&#30340;&#38656;&#27714;&#12290;&#30001; &#8288;</span><a href="https://www.linkedin.com/in/karthikk9828/"><span>Karthik K</span></a><span> &#24320;&#21457;&#30340; Gitwyn&#65292;&#26159;&#19968;&#27454;&#22260;&#32469; Xcode &#24037;&#20316;&#27969;&#35774;&#35745;&#30340;&#21407;&#29983; Git &#23458;&#25143;&#31471;&#12290;&#22312;&#20219;&#24847; Xcode &#39033;&#30446;&#20013;&#25353;&#19979; &#8984;&#8679;E&#65292;&#21363;&#21487;&#26597;&#30475;&#25913;&#21160;&#12289;&#25972;&#29702;&#26242;&#23384;&#20869;&#23481;&#12289;&#29983;&#25104;&#25552;&#20132;&#20449;&#24687;&#24182;&#25512;&#36865;&#20195;&#30721;&#65292;&#20840;&#31243;&#26080;&#38656;&#20999;&#25442;&#21040;&#32456;&#31471;&#25110;&#20854;&#20182; Git &#24037;&#20855;&#12290;</span></p><p><span>Gitwyn &#30340;&#19968;&#39033;&#29305;&#33394;&#21151;&#33021;&#26159;&#21033;&#29992;&#35774;&#22791;&#31471; Apple Intelligence&#65292;&#26681;&#25454;&#24050;&#26242;&#23384;&#30340;&#20195;&#30721;&#33258;&#21160;&#29983;&#25104;&#25552;&#20132;&#20449;&#24687;&#12290;&#26080;&#38656;&#32852;&#32593;&#65292;&#20063;&#19981;&#20250;&#19978;&#20256;&#28304;&#30721;&#12290;&#30456;&#27604;&#21333;&#32431;&#20943;&#23569;&#19968;&#27425;&#36755;&#20837;&#65292;&#23427;&#26356;&#24076;&#26395;&#23558;&#26597;&#30475;&#24046;&#24322;&#12289;&#32452;&#32455;&#25552;&#20132;&#12289;&#29983;&#25104;&#35828;&#26126;&#21644;&#25512;&#36865;&#20195;&#30721;&#25972;&#21512;&#20026;&#19968;&#27573;&#36830;&#32493;&#30340;&#24320;&#21457;&#27969;&#31243;&#65292;&#35753; Git &#25805;&#20316;&#23613;&#21487;&#33021;&#30041;&#22312; Xcode &#30340;&#24037;&#20316;&#19978;&#19979;&#25991;&#20013;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-07"><span>VersionedDocC&#65306;&#20026; Swift-DocC &#34917;&#19978;&#29256;&#26412;&#31649;&#29702;</span></a></strong></h3><p><span>&#36807;&#21435;&#20960;&#24180;&#65292;&#27599;&#36898; WWDC &#21484;&#24320;&#65292;&#25105;&#36890;&#24120;&#37117;&#20250;&#31532;&#19968;&#26102;&#38388;&#25171;&#24320;&#33529;&#26524;&#24320;&#21457;&#32773;&#25991;&#26723;&#65292;&#36890;&#36807;&#8220;API &#21464;&#21270;&#65288;API Changes&#65289;&#8221;&#21151;&#33021;&#27604;&#36739;&#19981;&#21516; Xcode &#19982; SDK &#29256;&#26412;&#65292;&#26597;&#30475; API &#30340;&#26032;&#22686;&#12289;&#20462;&#25913;&#19982;&#24323;&#29992;&#12290;&#36951;&#25022;&#30340;&#26159;&#65292;&#36825;&#39033;&#39047;&#20026;&#23454;&#29992;&#30340;&#21151;&#33021;&#22312; 2025 &#24180;&#30340;&#25991;&#26723;&#32593;&#31449;&#25913;&#29256;&#21518;&#28040;&#22833;&#20102;&#12290;&#21407;&#26377;&#30340;&#24046;&#24322;&#26597;&#35810;&#22320;&#22336;&#34429;&#28982;&#20173;&#21487;&#35775;&#38382;&#65292;&#21364;&#24050;&#26080;&#27861;&#21576;&#29616;&#23436;&#25972;&#30340; API &#21464;&#21270;&#12290;</span></p><p><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#24320;&#21457;&#30340; VersionedDocC&#65292;&#24688;&#22909;&#20026; DocC &#34917;&#19978;&#20102;&#36825;&#19968;&#33021;&#21147;&#12290;&#23427;&#22312;&#21407;&#26377; Swift &#24037;&#20855;&#38142;&#20043;&#19978;&#22686;&#21152;&#20102;&#19968;&#23618;&#21457;&#24067;&#32534;&#25490;&#65306;&#20026;&#19981;&#21516;&#29256;&#26412;&#29983;&#25104;&#31283;&#23450;&#22320;&#22336;&#65292;&#25552;&#20379;&#29256;&#26412;&#36873;&#25321;&#22120;&#65292;&#20381;&#25454;&#31526;&#21495;&#22270;&#23637;&#31034;&#30456;&#37051;&#29256;&#26412;&#30340;&#20844;&#24320; API &#21464;&#21270;&#65292;&#24182;&#36890;&#36807;&#19981;&#21487;&#21464;&#32531;&#23384;&#36991;&#20813;&#21453;&#22797;&#26500;&#24314;&#21382;&#21490;&#25991;&#26723;&#12290;&#39033;&#30446;&#21516;&#26102;&#25552;&#20379; SwiftPM &#25554;&#20214;&#12289;GitHub Action &#21644; GitHub Pages &#24037;&#20316;&#27969;&#65292;&#20063;&#25903;&#25345;&#22810;&#24179;&#21488;&#31526;&#21495;&#22270;&#12289;&#22806;&#37096;&#27169;&#22359;&#21450;&#29420;&#31435; DocC &#30446;&#24405;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-08"><span>Swift Subprocess 1.0</span></a></strong></h3><p><span>&#21382;&#32463;&#19968;&#24180;&#36845;&#20195;&#65292;Swift &#23448;&#26041;&#39033;&#30446; swift-subprocess &#26412;&#21608;&#21457;&#24067; 1.0 &#27491;&#24335;&#29256;&#12290;&#23427;&#26159;&#19968;&#22871;&#22522;&#20110; Swift Concurrency &#30340;&#36328;&#24179;&#21488;&#23376;&#36827;&#31243;&#24211;&#65292;&#21487;&#20197;&#22312; macOS&#12289;Linux&#12289;Windows&#12289;Android &#19982; BSD &#31995;&#32479;&#19978;&#65292;&#20197;&#32479;&#19968;&#26041;&#24335;&#21551;&#21160;&#21629;&#20196;&#12289;&#25552;&#20379;&#36755;&#20837;&#12289;&#27969;&#24335;&#35835;&#21462;&#36755;&#20986;&#65292;&#24182;&#31649;&#29702;&#36827;&#31243;&#30340;&#36864;&#20986;&#19982;&#21462;&#28040;&#12290;</span></p><p><span>&#23427;&#23588;&#20854;&#36866;&#21512; Swift CLI&#12289;&#26500;&#24314;&#24037;&#20855;&#12289;&#26381;&#21153;&#22120;&#31243;&#24207;&#12289;&#24320;&#21457;&#32773;&#24037;&#20855;&#19982; macOS &#33258;&#21160;&#21270;&#12290;&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;1.0 &#35201;&#27714; Swift 6.2&#65292;&#19981;&#38754;&#21521;&#26222;&#36890; iOS App&#65292;&#20063;&#26410;&#25552;&#20379;&#27801;&#31665;&#12289;&#21629;&#20196;&#25480;&#26435;&#25110;&#20266;&#32456;&#31471;&#65288;PTY&#65289;&#31561;&#26356;&#39640;&#23618;&#33021;&#21147;&#12290;</span></p><p><span>swift-subprocess &#20063;&#34917;&#19978;&#20102; Swift &#26500;&#24314;&#26412;&#22320; Agent &#25152;&#38656;&#30340;&#19968;&#22359;&#37325;&#35201;&#25340;&#22270;&#65306;&#21487;&#38752;&#25191;&#34892;&#24037;&#20855;&#12289;&#25345;&#32493;&#25509;&#25910;&#36816;&#34892;&#32467;&#26524;&#65292;&#24182;&#22949;&#21892;&#31649;&#29702;&#23376;&#36827;&#31243;&#29983;&#21629;&#21608;&#26399;&#12290;&#27169;&#22411;&#20915;&#23450;&#8220;&#20570;&#20160;&#20040;&#8221;&#65292;Subprocess &#21017;&#35753;&#8220;&#22914;&#20309;&#25191;&#34892;&#8221;&#21464;&#24471;&#26356;&#21487;&#25511;&#12289;&#26356;&#21487;&#35266;&#27979;&#65292;&#20063;&#26356;&#31526;&#21512; Swift &#30340;&#35821;&#35328;&#33539;&#24335;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #147]]></title><description><![CDATA[Hot Tea or Iced Coffee]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 03 Aug 2026 12:02:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YzuJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YzuJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 424w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 848w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1272w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" width="1400" height="799" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:799,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:142272,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/209575455?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 424w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 848w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1272w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@alexmeier19?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Alex Meier</a><span> on </span><a href="https://unsplash.com/photos/a-glass-of-iced-tea-next-to-a-jar-of-iced-tea-EbXSMYVOF-I?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Hot Tea or Iced Coffee</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-147/">Read on web &#8594;</a></p><p><span>Recently, the temperatures in my city have been breaking historical records. Since the end of July, we&#8217;ve been stuck in a stretch of scorching weather lasting more than ten days, with temperatures consistently above 30&#176;C. While that may not sound particularly extreme on its own, paired with humidity exceeding 80%, it leaves behind a lingering sense of heat that never quite goes away&#8212;even after spending the entire day in an air-conditioned room set to 25&#176;C.</span></p><p><span>I&#8217;ve found myself turning to tea and coffee to improve how I feel. Interestingly, only a cup of hot tea gives me the satisfying sensation of heat escaping with perspiration, while only an iced coffee brings an immediate, refreshing coolness. I suspect this isn&#8217;t simply a matter of physics. More likely, it&#8217;s a psychological association shaped by years of habit.</span></p><p><span>There&#8217;s an old Chinese saying: &#8220;A calm mind brings a cool body.&#8221; I can&#8217;t claim to have reached that level of serenity. For now, I still rely on these simple drinks to help me find a bit of balance between warmth and coolness.</span></p><p><span>Hopefully, this hot and humid summer will return to normal sooner rather than later.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-146/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/liquid-glass-a-field-guide-to-uikit-compatibility-pitfalls/?utm_source=fatbobman%20weekly%20issue%20147&amp;utm_medium=web"><span>Liquid Glass: A Field Guide to UIKit Compatibility Pitfalls</span></a></strong></h3><p><span>While Liquid Glass introduces a fresh interaction experience, it also makes UIKit compatibility significantly more complex. The same UI can behave very differently across iOS 18, iOS 26, and iOS 27, while different API combinations and implementation approaches may introduce their own compatibility pitfalls. Drawing from real-world project experience, </span><a href="https://x.com/Megabits_Studio"><span>Megabits</span></a><span> summarizes common issues involving Sheets, Navigation, Popovers, Toolbars, and other UIKit components, while also explaining lower-level behaviors such as </span><code>UIBarButtonItem</code><span>, </span><code>CABackdropLayer</code><span>, and the Scroll Edge Effect, complete with practical solutions and runnable demos.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-01"><span>The Map, Drawn Twice</span></a></strong></h3><p><span>Apple&#8217;s UI rendering stack spans Core Graphics, Core Text, Core Image, Core Animation, and SwiftUI. Although developers work with these frameworks regularly, many never fully understand the distinct responsibility of each layer. In the inaugural issue of Apple UI Insider, </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> presents a conceptual map that traces the journey from Swift code to the final pixels on screen.</span></p><p><span>Mihaela adopts a fascinating validation approach: every illustration is rendered twice from the exact same scene description&#8212;once by a custom clean-room rendering engine, and once by Apple&#8217;s Core Graphics&#8212;before being compared pixel by pixel. Although nearly half of the pixels differ, the average pixel difference is only around 0.1%, making the two images visually almost indistinguishable. This methodology of understanding system behavior through independent implementations, reproducible experiments, and quantitative measurements is arguably even more compelling than the article itself, and makes the rest of the series especially worth looking forward to.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-02"><span>Finally found a use case for .fixedSize</span></a></strong></h3><p><code>.fixedSize</code><span> is one of SwiftUI&#8217;s most overlooked modifiers. Many developers associate it only with niche use cases such as preventing text wrapping. Starting from a common layout requirement&#8212;making every card inside a horizontal </span><code>ScrollView</code><span> match the height of the tallest one&#8212;</span><a href="https://www.linkedin.com/in/engomarelsayed"><span>Omar Elsayed</span></a><span> demonstrates how </span><code>.fixedSize</code><span> provides an elegant solution.</span></p><blockquote><p><span>Perhaps </span><code>.fixedSize</code><span> has never become widely adopted because its name is rather abstract. What exactly is being &#8220;fixed&#8221;? And what does &#8220;size&#8221; actually refer to? If you&#8217;d like to better understand why it changes layout behavior, you may find my previous series, </span><a href="https://fatbobman.com/en/posts/layout-dimensions-1/"><span>SwiftUI Layout: The Mystery of Size</span></a><span>, helpful. It recreates </span><code>fixedSize</code><span> from scratch and breaks down the layout negotiation mechanism behind it.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-03"><span>Two Interesting Explorations of LazyVStack&#8217;s Layout Mechanism</span></a></strong></h3><p><span>On the Apple Developer Forums, </span><a href="https://developer.apple.com/forums/profile/alextar04"><span>alextar04</span></a><span> published two in-depth analyses of </span><code>LazyVStack</code><span>. One investigates blank screens and truncated cells during fast scrolling, while the other examines why </span><code>GeometryReader</code><span> reports multiple different sizes when used inside a </span><code>LazyVStack</code><span> (</span><a href="https://developer.apple.com/forums/thread/839688"><span>Thread 2</span></a><span>). Beyond providing minimal reproducible examples, the author combines insights from the WWDC 26 Lazy Stack session, SwiftUI logging, and experimental observations to reconstruct how SwiftUICore&#8212;including symbol resolution and </span><code>CA::Transaction</code><span> validation&#8212;might estimate sizes and validate layouts, using these hypotheses to explain the observed behavior.</span></p><blockquote><p><span>These two posts also highlight the design differences between </span><code>List</code><span> and </span><code>LazyVStack</code><span> from another perspective. The author suggests that, in order to support lazy layout, </span><code>LazyVStack</code><span> relies on size estimation under certain circumstances, which naturally leads to behavior different from </span><code>List</code><span>. This further illustrates why neither container is universally better&#8212;their strengths simply apply to </span><a href="https://fatbobman.com/en/posts/list-or-lazyvstack/"><span>different scenarios</span></a><span>.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-08"><span>Swift on Windows: A Year of Refinement</span></a></strong></h3><p><span>A year ago, Swift on Windows had already proven itself capable of supporting real production applications. But being &#8220;functional&#8221; is not the same as being predictable. Over the past year, </span><a href="https://x.com/browsercompany"><span>The Browser Company</span></a><span>, together with Apple and the Swift community, has focused on strengthening the platform&#8217;s foundations: rebuilding the runtime build system with modern CMake, introducing the Experimental Swift SDK, formalizing both static and dynamic linking models, and improving runtime selection and distribution across multi-toolchain environments.</span></p><p><span>What truly advances the maturity of a cross-platform ecosystem is often not a headline-grabbing feature, but the engineering details that are easy to overlook: whether build configurations are reproducible and auditable, whether runtimes can be bound deterministically, whether tools can be distributed independently, and whether CI and developer environments behave consistently. This article offers an excellent overview of how Swift on Windows has evolved over the past year&#8212;not through flashy new capabilities, but through continuous refinement of its engineering foundations.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-04"><span>Memo Property: Reusing More Stateful Business Logic for SwiftUI Views</span></a></strong></h3><p><span>In </span><a href="https://github.com/vanvoorden/TaskProperty"><span>TaskProperty</span></a><span>, </span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> demonstrated how custom </span><code>DynamicProperty</code><span> types can extract stateful business logic from SwiftUI views while remaining aligned with the view lifecycle. Building on that idea, this article leverages Swift&#8217;s latest Parameter Packs (Variadic Generics) to implement a React-like </span><code>useMemo</code><span> mechanism for SwiftUI: filtering, sorting, and other expensive computations are recomputed only when explicitly declared dependencies change, while cached results are reused for unrelated view updates.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-05"><span>One Model Object, Multiple Editing Flows: The Missing Layer Between Model and UI</span></a></strong></h3><p><span>Since the introduction of Observation, many developers have assumed that Combine is gradually becoming less relevant in SwiftUI. In this article, </span><a href="https://www.linkedin.com/in/sergey-tristan/"><span>Sergey Tristan</span></a><span> presents a different perspective. When multiple independent editing flows share the same model object, with each flow interested in only part of its state, Observation excels at efficiently detecting changes, while Combine is better suited for composing, transforming, and continuously synchronizing data. Rather than replacing one another, the two complement each other.</span></p><p><span>The article introduces a Projection layer between the model and the UI that transforms one or more continuously changing data sources into reactive representations tailored for different consumers. Whether or not you adopt this architecture, it raises an interesting question: as applications evolve to include increasingly independent yet interconnected editing flows, do we need an abstraction beyond DTOs, ViewModels, and Observation to organize these continuously evolving data flows?</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0147-06"><span>Apple External Display Support Lookup</span></a></strong></h3><p><span>External display support across Apple devices can be surprisingly complicated. Capabilities vary by chip generation, hardware model, and even operating system version. Created by </span><a href="https://www.linkedin.com/in/parishkhan/"><span>Parish Khan</span></a><span>, RetinaDesk provides a convenient online lookup tool that lets you quickly check how many external displays a Mac, iPad, or iPhone supports, along with maximum resolution, refresh rate, extended display support, mirroring capabilities, and more.</span></p><p><span>For developers working with multi-display setups, Stage Manager, or external display features, this is a handy reference that makes it much easier to verify device capabilities without digging through Apple&#8217;s technical specifications.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-07"><span>Agent Island</span></a></strong></h3><p><span>Agent Island is an open-source local monitoring tool created by </span><a href="https://x.com/tngzhy658431902"><span>Tristan Tang</span></a><span>. It continuously monitors the local session files generated by Claude Code and Codex, determines their current state in real time, and displays intuitive status updates and notifications through a Dynamic Island-style menu bar interface, so you no longer need to keep watching your terminal. It can also automatically execute predefined follow-up actions once your AI model usage window resets, helping long-running tasks resume seamlessly.</span></p><p><span>The project follows a local-first design, requiring no cloud services and uploading no conversation data. It also provides token usage statistics, quota reset countdowns, and weekly/monthly usage reports.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#28909;&#33590;&#36824;&#26159;&#20912;&#21654;&#21857;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-147/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#25105;&#25152;&#22312;&#30340;&#22478;&#24066;&#65292;&#27668;&#28201;&#19981;&#26029;&#21047;&#26032;&#21382;&#21490;&#32426;&#24405;&#12290;&#20174; 7 &#26376;&#26411;&#24320;&#22987;&#65292;&#20415;&#38519;&#20837;&#20102;&#25345;&#32493;&#21313;&#22825;&#20197;&#19978;&#12289;&#36229;&#36807; 30 &#25668;&#27663;&#24230;&#30340;&#39640;&#28201;&#37239;&#26257;&#12290;&#23613;&#31649;&#20174;&#32477;&#23545;&#25968;&#20540;&#19978;&#30475;&#24182;&#19981;&#31639;&#24778;&#20154;&#65292;&#20294;&#37197;&#19978;&#36229;&#36807; 80% &#30340;&#28287;&#24230;&#65292;&#21363;&#20415;&#20840;&#22825;&#24453;&#22312; 25 &#24230;&#30340;&#31354;&#35843;&#25151;&#37324;&#65292;&#20307;&#20869;&#20381;&#28982;&#33021;&#25874;&#20986;&#19968;&#32929;&#25381;&#20043;&#19981;&#21435;&#30340;&#29157;&#28909;&#12290;</span></p><p><span>&#25105;&#20250;&#36890;&#36807;&#21917;&#33590;&#12289;&#21917;&#21654;&#21857;&#26469;&#25913;&#21892;&#8220;&#20307;&#24863;&#8221;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#21807;&#26377;&#28909;&#33590;&#33021;&#24102;&#32473;&#25105;&#19968;&#31181;&#28909;&#37327;&#38543;&#27735;&#27700;&#37322;&#25918;&#30340;&#36890;&#36879;&#24863;&#65292;&#32780;&#20063;&#21807;&#26377;&#20912;&#21654;&#21857;&#33021;&#24102;&#26469;&#29255;&#21051;&#30452;&#25130;&#20102;&#24403;&#30340;&#28165;&#20937;&#12290;&#25105;&#24819;&#65292;&#36825;&#26410;&#24517;&#26159;&#39278;&#21697;&#26412;&#36523;&#30340;&#29289;&#29702;&#29305;&#24615;&#20351;&#28982;&#65292;&#25110;&#35768;&#26356;&#22810;&#26159;&#38271;&#26399;&#39278;&#39135;&#20064;&#24815;&#22312;&#24515;&#20013;&#30041;&#19979;&#30340;&#24515;&#29702;&#26263;&#31034;&#12290;</span></p><p><span>&#20013;&#22269;&#26377;&#21477;&#32769;&#35805;&#21483;&#8220;&#24515;&#38745;&#33258;&#28982;&#20937;&#8221;&#12290;&#25105;&#33258;&#35748;&#36824;&#27809;&#36798;&#21040;&#36825;&#33324;&#36229;&#33073;&#30340;&#24515;&#22659;&#65292;&#29616;&#38454;&#27573;&#20173;&#20813;&#19981;&#20102;&#20511;&#21161;&#36825;&#20123;&#26479;&#20013;&#29289;&#65292;&#22312;&#20919;&#28909;&#20043;&#38388;&#23547;&#24471;&#19968;&#28857;&#24179;&#34913;&#12290;</span></p><p><span>&#20294;&#24895;&#36825;&#20010;&#38391;&#28909;&#30340;&#22799;&#22825;&#65292;&#33021;&#26089;&#28857;&#22797;&#24402;&#24120;&#24577;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-146/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/liquid-glass-a-field-guide-to-uikit-compatibility-pitfalls/?utm_source=fatbobman%20weekly%20issue%20147&amp;utm_medium=web"><span>Liquid Glass&#65306;UIKit &#36866;&#37197;&#36393;&#22353;&#23454;&#24405;</span></a></strong></h3><p><span>Liquid Glass &#22312;&#24102;&#26469;&#20840;&#26032;&#20132;&#20114;&#20307;&#39564;&#30340;&#21516;&#26102;&#65292;&#20063;&#35753; UIKit &#30340;&#20860;&#23481;&#24615;&#21464;&#24471;&#26356;&#21152;&#22797;&#26434;&#12290;&#21516;&#19968;&#22871; UI&#65292;&#22312; iOS 18&#12289;iOS 26 &#19982; iOS 27 &#19978;&#21487;&#33021;&#34920;&#29616;&#20986;&#25130;&#28982;&#19981;&#21516;&#30340;&#34892;&#20026;&#65307;&#19981;&#21516;&#30340; API &#32452;&#21512;&#19982;&#23454;&#29616;&#26041;&#24335;&#65292;&#20063;&#21487;&#33021;&#35302;&#21457;&#21508;&#24335;&#21508;&#26679;&#30340;&#20860;&#23481;&#24615;&#38382;&#39064;&#12290;</span><a href="https://x.com/Megabits_mzq"><span>Megabits</span></a><span> &#32467;&#21512;&#30495;&#23454;&#39033;&#30446;&#32463;&#39564;&#65292;&#24635;&#32467;&#20102; UIKit &#19979; Sheet&#12289;Navigation&#12289;Popover&#12289;Toolbar &#31561;&#22810;&#20010;&#20856;&#22411;&#22330;&#26223;&#20013;&#30340;&#36866;&#37197;&#38519;&#38449;&#65292;&#24182;&#20998;&#26512;&#20102; </span><code>UIBarButtonItem</code><span>&#12289;</span><code>CABackdropLayer</code><span>&#12289;Scroll Edge Effect &#31561;&#24213;&#23618;&#34892;&#20026;&#65292;&#32473;&#20986;&#20102;&#23545;&#24212;&#30340;&#35299;&#20915;&#26041;&#26696;&#19982;&#21487;&#36816;&#34892; Demo&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-01"><span>&#20004;&#24230;&#32472;&#21046;&#30340;&#20687;&#32032;&#28210;&#26579;&#22320;&#22270; (The Map, Drawn Twice)</span></a></strong></h3><p><span>Apple &#30340; UI &#28210;&#26579;&#20307;&#31995;&#28041;&#21450; Core Graphics&#12289;Core Text&#12289;Core Image&#12289;Core Animation &#19982; SwiftUI &#31561;&#22810;&#20010;&#23618;&#27425;&#65292;&#24320;&#21457;&#32773;&#34429;&#28982;&#32463;&#24120;&#20351;&#29992;&#36825;&#20123;&#26694;&#26550;&#65292;&#21364;&#26410;&#24517;&#30495;&#27491;&#29702;&#35299;&#23427;&#20204;&#21508;&#33258;&#25215;&#25285;&#30340;&#32844;&#36131;&#12290;&#22312; Apple UI Insider &#30340;&#21019;&#21002;&#21495;&#20013;&#65292;</span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#32472;&#21046;&#20102;&#19968;&#24352;&#20174; Swift &#20195;&#30721;&#21040;&#26368;&#32456;&#20687;&#32032;&#30340;&#32844;&#36131;&#22320;&#22270;&#12290;</span></p><p><span>Mihaela &#37319;&#29992;&#20102;&#19968;&#31181;&#24456;&#26377;&#24847;&#24605;&#30340;&#39564;&#35777;&#26041;&#24335;&#65306;&#27599;&#19968;&#24352;&#25554;&#22270;&#37117;&#30001;&#21516;&#19968;&#20221;&#22330;&#26223;&#25551;&#36848;&#29983;&#25104;&#20004;&#27425;&#65292;&#19968;&#27425;&#20132;&#32473;&#33258;&#24049;&#23454;&#29616;&#30340; clean-room &#28210;&#26579;&#24341;&#25806;&#65292;&#21478;&#19968;&#27425;&#20132;&#32473; Apple &#30340; Core Graphics&#65292;&#20877;&#36880;&#20687;&#32032;&#27604;&#36739;&#20004;&#32773;&#30340;&#36755;&#20986;&#12290;&#23613;&#31649;&#32422;&#26377;&#19968;&#21322;&#20687;&#32032;&#23384;&#22312;&#24046;&#24322;&#65292;&#20294;&#24179;&#22343;&#20687;&#32032;&#24046;&#24322;&#20165;&#32422;&#20026; 0.1%&#65292;&#35270;&#35273;&#25928;&#26524;&#20960;&#20046;&#23436;&#20840;&#19968;&#33268;&#12290;&#36825;&#31181;&#36890;&#36807;&#29420;&#31435;&#23454;&#29616;&#12289;&#21487;&#22797;&#29616;&#23454;&#39564;&#21644;&#37327;&#21270;&#32467;&#26524;&#26469;&#30740;&#31350;&#31995;&#32479;&#34892;&#20026;&#30340;&#26041;&#27861;&#65292;&#27604;&#25991;&#31456;&#26412;&#36523;&#20171;&#32461;&#30340;&#20869;&#23481;&#26356;&#20540;&#24471;&#20851;&#27880;&#65292;&#20063;&#35753;&#20154;&#26356;&#21152;&#26399;&#24453;&#36825;&#19968;&#31995;&#21015;&#21518;&#32493;&#30340;&#30740;&#31350;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-02"><span>&#32456;&#20110;&#20026; .fixedSize &#25214;&#21040;&#20102;&#21512;&#36866;&#22330;&#26223; (Finally found a use case for .fixedSize)</span></a></strong></h3><p><code>.fixedSize</code><span> &#26159; SwiftUI &#20013;&#19968;&#20010;&#32463;&#24120;&#34987;&#24573;&#35270;&#30340; modifier&#65292;&#19981;&#23569;&#24320;&#21457;&#32773;&#23545;&#23427;&#30340;&#21360;&#35937;&#20173;&#20572;&#30041;&#22312;&#36991;&#20813;&#25991;&#26412;&#25240;&#34892;&#31561;&#23569;&#25968;&#22330;&#26223;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/engomarelsayed"><span>Omar Elsayed</span></a><span> &#20174;&#19968;&#20010;&#24456;&#24120;&#35265;&#30340;&#38656;&#27714;&#20986;&#21457;&#65306;&#22914;&#20309;&#35753;&#27178;&#21521; </span><code>ScrollView</code><span> &#20013;&#25152;&#26377;&#21345;&#29255;&#37117;&#19982;&#26368;&#39640;&#30340;&#37027;&#19968;&#39033;&#20445;&#25345;&#30456;&#21516;&#39640;&#24230;&#65292;&#20998;&#20139;&#20102;&#33258;&#24049;&#20511;&#21161; </span><code>.fixedSize</code><span> &#25214;&#21040;&#35299;&#20915;&#26041;&#26696;&#30340;&#36807;&#31243;&#12290;</span></p><blockquote><p><span>&#25110;&#35768; </span><code>.fixedSize</code><span> &#19968;&#30452;&#27809;&#26377;&#24471;&#21040;&#24191;&#27867;&#20351;&#29992;&#65292;&#19982;&#23427;&#30053;&#26174;&#25277;&#35937;&#30340;&#21629;&#21517;&#20063;&#26377;&#19968;&#23450;&#20851;&#31995;&#12290;&#31350;&#31455;&#22266;&#23450;&#30340;&#26159;&#20160;&#20040;&#65311;&#23545;&#24212;&#30340; size &#21448;&#26159;&#20160;&#20040;&#65311;&#22914;&#26524;&#24819;&#28145;&#20837;&#29702;&#35299;&#23427;&#20026;&#20309;&#33021;&#22815;&#25913;&#21464;&#24067;&#23616;&#32467;&#26524;&#65292;&#21487;&#20197;&#21442;&#38405;&#25105;&#20043;&#21069;&#20889;&#30340;&#12298;&#8288;</span><a href="https://fatbobman.com/zh/posts/layout-dimensions-1/"><span>SwiftUI &#24067;&#23616;&#65306;&#23610;&#23544;</span></a><span>&#12299;&#31995;&#21015;&#65292;&#20854;&#20013;&#36890;&#36807;&#23454;&#29616; </span><code>fixedSize</code><span> &#30340;&#22797;&#21046;&#21697;&#65292;&#25286;&#35299;&#20102;&#23427;&#22312; SwiftUI &#24067;&#23616;&#21327;&#21830;&#20013;&#30340;&#24037;&#20316;&#26426;&#21046;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-03"><span>&#20851;&#20110; LazyVStack &#24067;&#23616;&#26426;&#21046;&#30340;&#20004;&#27425;&#26377;&#36259;&#25506;&#32034;</span></a></strong></h3><p><span>&#22312; Apple Developer Forums &#19978;&#65292;&#8288;</span><a href="https://developer.apple.com/forums/profile/alextar04"><span>alextar04</span></a><span> &#36830;&#32493;&#21457;&#24067;&#20102;&#20004;&#31687;&#20851;&#20110; </span><code>LazyVStack</code><span> &#30340;&#20998;&#26512;&#24086;&#12290;&#20004;&#31687;&#24086;&#23376;&#20998;&#21035;&#22260;&#32469;&#24555;&#36895;&#28378;&#21160;&#26102;&#21487;&#33021;&#20986;&#29616;&#30340;&#31354;&#30333;&#21306;&#22495;&#19982; Cell &#25130;&#26029;&#65292;&#20197;&#21450; </span><code>GeometryReader</code><span> &#22312; </span><code>LazyVStack</code><span> &#20013;&#33719;&#21462;&#21040;&#30340;&#23610;&#23544;&#20026;&#20309;&#20250;&#22810;&#27425;&#21464;&#21270;&#23637;&#24320;&#65288;&#8288;</span><a href="https://developer.apple.com/forums/thread/839688"><span>&#24086;&#23376; 2</span></a><span>&#65289;&#12290;&#20316;&#32773;&#19981;&#20165;&#25552;&#20379;&#20102;&#26368;&#23567;&#22797;&#29616;&#24037;&#31243;&#65292;&#36824;&#32467;&#21512; WWDC 26 &#20851;&#20110; Lazy Stack &#30340;&#20171;&#32461;&#12289;SwiftUI &#26085;&#24535;&#20197;&#21450;&#23454;&#39564;&#32467;&#26524;&#65292;&#23581;&#35797;&#36824;&#21407; SwiftUICore &#24213;&#23618;&#65288;&#22914;&#31526;&#21495;&#35745;&#31639;&#19982; CA::Transaction &#25552;&#20132;&#39564;&#35777;&#65289;&#22312;&#20272;&#31639;&#23610;&#23544;&#12289;&#26657;&#39564;&#24067;&#23616;&#26102;&#21487;&#33021;&#37319;&#29992;&#30340;&#24037;&#20316;&#26041;&#24335;&#65292;&#24182;&#25454;&#27492;&#35299;&#37322;&#36825;&#20123;&#29616;&#35937;&#20135;&#29983;&#30340;&#21407;&#22240;&#12290;</span></p><blockquote><p><span>&#36825;&#20004;&#31687;&#24086;&#23376;&#20063;&#20174;&#21478;&#19968;&#20010;&#35282;&#24230;&#23637;&#29616;&#20102; </span><code>List</code><span> &#19982; </span><code>LazyVStack</code><span> &#22312;&#35774;&#35745;&#29702;&#24565;&#19978;&#30340;&#24046;&#24322;&#12290;&#20316;&#32773;&#25512;&#27979;&#65292;</span><code>LazyVStack</code><span> &#20026;&#20102;&#23454;&#29616;&#25042;&#24067;&#23616;&#65292;&#20250;&#22312;&#37096;&#20998;&#22330;&#26223;&#19979;&#20381;&#36182;&#23610;&#23544;&#20272;&#31639;&#31561;&#26426;&#21046;&#65292;&#22240;&#27492;&#19982; </span><code>List</code><span> &#21576;&#29616;&#20986;&#19981;&#21516;&#30340;&#34892;&#20026;&#12290;&#36825;&#20063;&#35828;&#26126;&#20102;&#20026;&#20160;&#20040;&#20004;&#32773;&#24182;&#19981;&#23384;&#22312;&#32477;&#23545;&#30340;&#20248;&#21155;&#65292;&#32780;&#26159;&#8288;</span><a href="https://fatbobman.com/zh/posts/list-or-lazyvstack/"><span>&#21508;&#33258;&#36866;&#29992;&#20110;&#19981;&#21516;&#30340;&#22330;&#26223;</span></a><span>&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-08"><span>Swift on Windows&#65306;&#19968;&#24180;&#30340;&#25171;&#30952;&#19982;&#23436;&#21892; (Swift on Windows: A year of refinement)</span></a></strong></h3><p><span>Swift on Windows &#22312;&#19968;&#24180;&#21069;&#24050;&#32463;&#33021;&#22815;&#25903;&#25745;&#30495;&#23454;&#30340;&#29983;&#20135;&#24212;&#29992;&#65292;&#20294;&#8220;&#21487;&#20197;&#36816;&#34892;&#8221;&#24182;&#19981;&#31561;&#20110;&#8220;&#36275;&#22815;&#21487;&#39044;&#27979;&#8221;&#12290;&#8288;</span><a href="https://x.com/browsercompany"><span>The Browser Company</span></a><span> &#19982; Apple &#21450; Swift &#31038;&#21306;&#23558;&#37325;&#28857;&#25918;&#22312;&#20102;&#22522;&#30784;&#35774;&#26045;&#30340;&#25171;&#30952;&#19978;&#65306;&#20351;&#29992;&#29616;&#20195; CMake &#37325;&#26500; Runtime &#26500;&#24314;&#31995;&#32479;&#65292;&#25512;&#20986; Experimental Swift SDK&#65292;&#26126;&#30830;&#38745;&#24577;&#19982;&#21160;&#24577;&#38142;&#25509;&#27169;&#22411;&#65292;&#24182;&#25913;&#21892;&#22810;&#24037;&#20855;&#38142;&#29615;&#22659;&#20013;&#30340; Runtime &#36873;&#25321;&#19982;&#20998;&#21457;&#38382;&#39064;&#12290;</span></p><p><span>&#30495;&#27491;&#25512;&#21160;&#36328;&#24179;&#21488;&#25104;&#29087;&#24230;&#25552;&#21319;&#30340;&#65292;&#24448;&#24448;&#19981;&#26159;&#26576;&#20010;&#24341;&#20154;&#27880;&#30446;&#30340;&#26032;&#29305;&#24615;&#65292;&#32780;&#26159;&#36825;&#20123;&#23481;&#26131;&#34987;&#24573;&#35270;&#30340;&#24037;&#31243;&#32454;&#33410;&#65306;&#26500;&#24314;&#37197;&#32622;&#26159;&#21542;&#21487;&#23457;&#35745;&#12289;Runtime &#33021;&#21542;&#31934;&#30830;&#32465;&#23450;&#12289;&#24037;&#20855;&#26159;&#21542;&#21487;&#20197;&#29420;&#31435;&#20998;&#21457;&#65292;&#20197;&#21450; CI &#19982;&#24320;&#21457;&#29615;&#22659;&#33021;&#21542;&#22987;&#32456;&#20445;&#25345;&#19968;&#33268;&#12290;&#36825;&#31687;&#25991;&#31456;&#24456;&#22909;&#22320;&#23637;&#31034;&#20102; Swift &#22312; Windows &#24179;&#21488;&#36807;&#21435;&#19968;&#24180;&#26368;&#37325;&#35201;&#30340;&#36827;&#27493;&#65292;&#26356;&#22810;&#26469;&#33258;&#24037;&#31243;&#33021;&#21147;&#30340;&#25345;&#32493;&#25171;&#30952;&#65292;&#32780;&#38750;&#21151;&#33021;&#19978;&#30340;&#25193;&#24352;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-04"><span>MemoProperty&#65306;&#22312; SwiftUI &#20013;&#22797;&#29992;&#26377;&#29366;&#24577;&#19994;&#21153;&#36923;&#36753; (Memo Property: Reusing More Stateful Business Logic for SwiftUI Views)</span></a></strong></h3><p><span>&#22312; </span><a href="https://github.com/vanvoorden/TaskProperty"><span>TaskProperty</span></a><span> &#20013;&#65292;</span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> &#23637;&#31034;&#20102;&#22914;&#20309;&#20511;&#21161;&#33258;&#23450;&#20041; </span><code>DynamicProperty</code><span>&#65292;&#23558;&#24102;&#26377;&#29983;&#21629;&#21608;&#26399;&#21644;&#29366;&#24577;&#30340;&#19994;&#21153;&#36923;&#36753;&#20174; View &#20013;&#25277;&#31163;&#20986;&#26469;&#12290;&#26412;&#25991;&#27839;&#30528;&#30456;&#21516;&#30340;&#24605;&#36335;&#32487;&#32493;&#21521;&#21069;&#65292;&#32467;&#21512; Swift &#26368;&#26032;&#30340;&#21442;&#25968;&#21253;&#65288;Parameter Packs / Variadic Generics&#65289;&#31561;&#21069;&#27839;&#35821;&#27861;&#65292;&#23581;&#35797;&#22312; SwiftUI &#20013;&#23454;&#29616;&#19968;&#20010;&#31867;&#20284; React </span><code>useMemo</code><span> &#30340;&#26426;&#21046;&#65306;&#21482;&#26377;&#24403;&#26174;&#24335;&#22768;&#26126;&#30340;&#20381;&#36182;&#21457;&#29983;&#21464;&#21270;&#26102;&#65292;&#25165;&#37325;&#26032;&#25191;&#34892;&#36807;&#28388;&#12289;&#25490;&#24207;&#31561;&#35745;&#31639;&#65292;&#21542;&#21017;&#30452;&#25509;&#22797;&#29992;&#27492;&#21069;&#32531;&#23384;&#30340;&#32467;&#26524;&#65292;&#36991;&#20813; View &#22240;&#26080;&#20851;&#29366;&#24577;&#21464;&#21270;&#32780;&#37325;&#22797;&#23436;&#25104;&#26114;&#36149;&#24037;&#20316;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-05"><span>&#22810;&#27969;&#32534;&#36753;&#19979;&#30340;&#29366;&#24577;&#21516;&#27493;&#65306;&#26500;&#24314;&#27169;&#22411;&#19982; UI &#20043;&#38388;&#32570;&#22833;&#30340;&#8220;&#25237;&#24433;&#23618;&#8221; (One Model Object, Multiple Editing Flows: The Missing Layer Between Model and UI)</span></a></strong></h3><p><span>Observation &#20986;&#29616;&#20043;&#21518;&#65292;&#19981;&#23569;&#24320;&#21457;&#32773;&#24320;&#22987;&#35748;&#20026; Combine &#22312; SwiftUI &#20013;&#24050;&#32463;&#36880;&#28176;&#22833;&#21435;&#20215;&#20540;&#12290;</span><a href="https://www.linkedin.com/in/sergey-tristan/"><span>Sergey Tristan</span></a><span> &#30340;&#36825;&#31687;&#25991;&#31456;&#21017;&#25552;&#20379;&#20102;&#19968;&#20010;&#19981;&#21516;&#30340;&#35270;&#35282;&#65306;&#24403;&#21516;&#19968;&#20010;&#27169;&#22411;&#23545;&#35937;&#38656;&#35201;&#34987;&#22810;&#20010;&#29420;&#31435;&#30340;&#32534;&#36753;&#27969;&#31243;&#20849;&#20139;&#65292;&#24182;&#19988;&#27599;&#20010;&#27969;&#31243;&#21482;&#20851;&#24515;&#20854;&#20013;&#19968;&#37096;&#20998;&#29366;&#24577;&#26102;&#65292;Observation &#36127;&#36131;&#39640;&#25928;&#22320;&#24863;&#30693;&#21464;&#21270;&#65292;&#32780; Combine &#26356;&#36866;&#21512;&#25215;&#25285;&#25968;&#25454;&#32452;&#21512;&#12289;&#36716;&#25442;&#19982;&#25345;&#32493;&#21516;&#27493;&#30340;&#32844;&#36131;&#65292;&#20004;&#32773;&#24182;&#38750;&#26367;&#20195;&#20851;&#31995;&#65292;&#32780;&#26159;&#21487;&#20197;&#21508;&#21496;&#20854;&#32844;&#12290;</span></p><p><span>&#25991;&#31456;&#25552;&#20986;&#20102;&#19968;&#20010;&#20301;&#20110; Model &#19982; UI &#20043;&#38388;&#30340; Projection &#27010;&#24565;&#65292;&#23558;&#19968;&#20010;&#25110;&#22810;&#20010;&#25345;&#32493;&#21464;&#21270;&#30340;&#25968;&#25454;&#28304;&#36716;&#25442;&#20026;&#19981;&#21516;&#28040;&#36153;&#32773;&#25152;&#38656;&#30340;&#21709;&#24212;&#24335;&#34920;&#31034;&#12290;&#26080;&#35770;&#26159;&#21542;&#35748;&#21516;&#36825;&#31181;&#26550;&#26500;&#65292;&#23427;&#37117;&#25552;&#20986;&#20102;&#19968;&#20010;&#20540;&#24471;&#24605;&#32771;&#30340;&#38382;&#39064;&#65306;&#24403;&#24212;&#29992;&#24320;&#22987;&#25317;&#26377;&#36234;&#26469;&#36234;&#22810;&#29420;&#31435;&#21364;&#21448;&#30456;&#20114;&#20851;&#32852;&#30340;&#32534;&#36753;&#27969;&#31243;&#26102;&#65292;&#26159;&#21542;&#38656;&#35201;&#19968;&#31181;&#19981;&#21516;&#20110; DTO&#12289;ViewModel &#25110; Observation &#30340;&#25277;&#35937;&#26469;&#32452;&#32455;&#36825;&#20123;&#25345;&#32493;&#28436;&#21270;&#30340;&#25968;&#25454;&#27969;&#65311;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0147-06"><span>Apple &#22806;&#25509;&#26174;&#31034;&#22120;&#25903;&#25345;&#26597;&#35810;</span></a></strong></h3><p><span>&#33529;&#26524;&#35774;&#22791;&#23545;&#22806;&#25509;&#26174;&#31034;&#22120;&#30340;&#25903;&#25345;&#19968;&#30452;&#27604;&#36739;&#22797;&#26434;&#65292;&#19981;&#21516;&#33455;&#29255;&#12289;&#19981;&#21516;&#26426;&#22411;&#65292;&#29978;&#33267;&#19981;&#21516;&#31995;&#32479;&#29256;&#26412;&#20043;&#38388;&#37117;&#23384;&#22312;&#26126;&#26174;&#24046;&#24322;&#12290;&#30001; </span><a href="https://www.linkedin.com/in/parishkhan/"><span>Parish Khan</span></a><span> &#21019;&#24314;&#30340; RetinaDesk &#25552;&#20379;&#20102;&#19968;&#20010;&#22312;&#32447;&#26597;&#35810;&#24037;&#20855;&#65292;&#21487;&#20197;&#24555;&#36895;&#20102;&#35299; Mac&#12289;iPad&#12289;iPhone &#31561;&#35774;&#22791;&#25903;&#25345;&#30340;&#22806;&#25509;&#26174;&#31034;&#22120;&#25968;&#37327;&#12289;&#26368;&#39640;&#20998;&#36776;&#29575;&#12289;&#21047;&#26032;&#29575;&#65292;&#20197;&#21450;&#26159;&#21542;&#25903;&#25345;&#25193;&#23637;&#26174;&#31034;&#12289;&#38236;&#20687;&#27169;&#24335;&#31561;&#20449;&#24687;&#12290;</span></p><p><span>&#23545;&#20110;&#38656;&#35201;&#27979;&#35797;&#22810;&#23631;&#26174;&#31034;&#12289;Stage Manager &#25110;&#22806;&#25509;&#26174;&#31034;&#22120;&#30456;&#20851;&#21151;&#33021;&#30340;&#24320;&#21457;&#32773;&#65292;&#36825;&#20063;&#26159;&#19968;&#20010;&#24456;&#26041;&#20415;&#30340;&#21442;&#32771;&#24037;&#20855;&#65292;&#33021;&#22815;&#24555;&#36895;&#30830;&#35748;&#19981;&#21516;&#35774;&#22791;&#32452;&#21512;&#30340;&#33021;&#21147;&#36793;&#30028;&#65292;&#32780;&#26080;&#38656;&#36880;&#19968;&#26597;&#38405; Apple &#23448;&#26041;&#25216;&#26415;&#35268;&#26684;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-07"><span>Agent Island</span></a></strong></h3><p><span>Agent Island &#26159;&#19968;&#20010;&#30001; &#8288;</span><a href="https://x.com/tngzhy658431902"><span>Tristan Tang</span></a><span> &#24320;&#21457;&#30340;&#24320;&#28304;&#26412;&#22320;&#29366;&#24577;&#30417;&#35270;&#24037;&#20855;&#65292;&#23427;&#20250;&#25345;&#32493;&#35835;&#21462; Claude Code &#19982; Codex &#22312;&#26412;&#22320;&#29983;&#25104;&#30340;&#20250;&#35805;&#35760;&#24405;&#65292;&#23454;&#26102;&#21028;&#26029;&#24403;&#21069;&#29366;&#24577;&#65292;&#24182;&#36890;&#36807;&#33756;&#21333;&#26639;&#20013;&#30340;&#8220;&#28789;&#21160;&#23707;&#8221;&#26679;&#24335;&#32452;&#20214;&#25552;&#20379;&#30452;&#35266;&#30340;&#29366;&#24577;&#26174;&#31034;&#19982;&#25552;&#37266;&#65292;&#35753;&#24320;&#21457;&#32773;&#26080;&#38656;&#19968;&#30452;&#30447;&#30528;&#32456;&#31471;&#12290;&#23427;&#36824;&#25903;&#25345;&#22312; AI &#27169;&#22411;&#39069;&#24230;&#31383;&#21475;&#37325;&#32622;&#21518;&#33258;&#21160;&#25191;&#34892;&#39044;&#35774;&#30340;&#21518;&#32493;&#25805;&#20316;&#65292;&#24110;&#21161;&#38271;&#26102;&#38388;&#36816;&#34892;&#30340;&#20219;&#21153;&#26356;&#39034;&#30021;&#22320;&#34900;&#25509;&#19979;&#21435;&#12290;</span></p><p><span>&#39033;&#30446;&#37319;&#29992; Local-first &#35774;&#35745;&#65292;&#19981;&#20381;&#36182;&#20113;&#31471;&#26381;&#21153;&#65292;&#19981;&#19978;&#20256;&#20219;&#20309;&#20250;&#35805;&#20869;&#23481;&#65292;&#21516;&#26102;&#25552;&#20379; Token &#20351;&#29992;&#32479;&#35745;&#12289;&#39069;&#24230;&#37325;&#32622;&#20498;&#35745;&#26102;&#12289;&#21608;/&#26376;&#25253;&#21578;&#31561;&#21151;&#33021;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #146]]></title><description><![CDATA[It's Not That the Models Are Slower&#8212;The Tasks Have Become Bigger]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 27 Jul 2026 12:04:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bnF_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bnF_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bnF_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 424w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 848w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1272w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" width="1456" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:209726,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/208633411?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bnF_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 424w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 848w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1272w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@wouterdepraetere?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Wouter De Praetere</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-a-snail-on-a-table-ELfMdIihkTg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>It&#8217;s Not That the Models Are Slower&#8212;The Tasks Have Become Bigger</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-146/">Read on web &#8594;</a></p><p><span>Lately, even tasks that I consider relatively simple often take AI several minutes&#8212;or sometimes even tens of minutes&#8212;to complete. It gave me the impression that as models become more capable, they somehow have to become slower.</span></p><p><span>In reality, the main reason lies with me. Although today&#8217;s AI agents let us choose different models and reasoning levels, it&#8217;s much easier&#8212;and often more reliable&#8212;to simply hand even straightforward tasks to the most capable models. At the same time, modern agents no longer limit themselves to the small change you explicitly requested. They proactively expand their search, analyze whether the modification could affect other parts of the project, and try to identify potential issues before they happen. The models may be more powerful than ever, but they&#8217;re also taking on substantially more work for every task.</span></p><p><span>There&#8217;s another factor as well. As my trust in these models has grown, so has the scope of the tasks I assign to them. What used to be &#8220;refactor a function&#8221; or &#8220;improve a screen&#8221; has gradually become &#8220;implement a feature,&#8221; &#8220;build a module,&#8221; or even &#8220;create an entire product.&#8221; Without realizing it, I&#8217;ve started treating AI agents as genuine collaborators. The pace at which model performance improves simply hasn&#8217;t kept up with the way we now use them.</span></p><p><span>In other words, developers are no longer pursuing only &#8220;writing code faster.&#8221; Increasingly, we&#8217;re using AI to </span><strong><span>write better code, even if it takes longer</span></strong><span>.</span></p><p><span>The shift from question-answering to task delivery has happened in just a single year. As we grow accustomed to waking up and reviewing completed work, the real bottleneck is quietly moving elsewhere. We used to ask whether a model was capable of completing a task. Today, the more important questions are how to define a clear, verifiable objective, and how to reduce the cost of achieving it. AI is becoming more like a teammate, and the ability to organize and decompose work effectively is becoming the next competitive advantage.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-145/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-01"><span>Bluetooth without the delegate dance</span></a></strong></h3><p><span>Delegates remain a challenge many developers continue to face years after the introduction of Swift Concurrency. Not only do they often lead to cumbersome code organization, but under Swift 6&#8217;s strict concurrency checking they also become increasingly difficult to integrate naturally with modern concurrent code. </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> leverages Swift 6.2&#8217;s Custom Executor to bind CoreBluetooth&#8217;s callback queue directly to an Actor&#8217;s execution context, allowing delegate callbacks to run naturally within Actor isolation without additional locks, thread hopping, or synchronization logic.</span></p><blockquote><p><span>Custom Executor allows an Actor&#8217;s tasks to run on a designated executor, making it a powerful tool for bridging traditional callback-based APIs with Swift Concurrency. If you&#8217;re facing similar migration or abstraction challenges, this implementation is well worth studying. I also explored this topic in depth using Core Data as an example in </span><a href="https://fatbobman.com/en/posts/core-data-reform-achieving-elegant-concurrency-operations-like-swiftdata/"><span>this article</span></a><span>, explaining how to bind traditional serial queues to Actor executors for seamless integration with Swift Concurrency.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-02"><span>Working with Xcode on CI</span></a></strong></h3><p><span>As more developers adopt self-hosted macOS runners or cloud-based CI, reliably managing Xcode, Simulator Runtimes, and code-signing environments has become an essential part of engineering infrastructure. </span><a href="https://mastodon.social/@rodionovd"><span>Dmitry Rodionov</span></a><span> shares a collection of practical techniques for using the Xcode CLI in CI, including managing multiple Xcode installations with </span><code>DEVELOPER_DIR</code><span> instead of </span><code>xcode-select</code><span>, automating the installation and cleanup of Simulator Runtimes and Metal Toolchains, and reducing unnecessary recompilation during branch switching with Compilation Caching.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-03"><span>Squeeze every last bit of value out of GitHub Actions</span></a></strong></h3><p><span>Optimizing GitHub Actions doesn&#8217;t necessarily mean more aggressive caching, more complex workflows, or additional conditional logic. Instead, this article advocates a more valuable principle: every CI run should match the actual risk introduced by a change. Starting from the investigation of an apparently ordinary flaky test, </span><a href="https://x.com/rbbtsn0w"><span>Snow</span></a><span> discusses how deterministic tests eliminate unnecessary reruns, how portable checks can be moved to Linux while leaving Xcode-dependent validation to macOS, and how Build, Test, or Build for Testing can be selected dynamically based on change risk to avoid wasting expensive runner time.</span></p><blockquote><p><span>I particularly agree with one of the article&#8217;s core ideas: the goal of CI is not to &#8220;run more,&#8221; but to &#8220;answer the right questions.&#8221; Every expensive macOS build should validate a risk that a cheaper runner cannot, and every failure should provide actionable information that helps move the project forward.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-04"><span>Building adaptive non-modal panels in SwiftUI</span></a></strong></h3><p><span>Starting with WWDC26, iPhone-only apps running through iPhone Mirroring on a Mac or on an iPad enter a resizable environment. This means relying solely on </span><code>horizontalSizeClass</code><span> for layout decisions is becoming increasingly unreliable. </span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to build an adaptive non-modal panel by recording scene size and safe-area insets at the root using </span><code>onGeometryChange</code><span>, then choosing between bottom and side presentations based on the actual available width. One particularly useful technique is preserving the resolved layout cache during dragging, preventing adaptive content from changing size due to repeated measurements.</span></p><blockquote><p><span>If your app is iPhone-only but still has users running it on iPad or macOS, layout adaptation deserves much more attention going forward. As discussed in </span><a href="https://fatbobman.com/en/posts/from-size-class-to-available-space/"><span>From Size Class to Available Space</span></a><span>, the era of resizable canvases no longer guarantees developers absolute control over interface layouts, instead giving users much greater control over how apps are presented.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-05"><span>SwiftUI @ContentBuilder - Faster Type Checking in Xcode 27</span></a></strong></h3><p><span>Xcode 27 introduces the new </span><code>@ContentBuilder</code><span>. Although it is currently just a type alias for </span><code>ViewBuilder</code><span>, Apple has begun recommending this new name in its latest SwiftUI APIs. </span><a href="https://x.com/sagarunagar_"><span>Sagar Unagar</span></a><span> explains the change and notes that, for most applications, there is no need to immediately replace every </span><code>@ViewBuilder</code><span> with </span><code>@ContentBuilder</code><span>, as existing code already benefits from the compiler improvements introduced in Xcode 27.</span></p><blockquote><p><span>I haven&#8217;t written much SwiftUI code recently, so I haven&#8217;t yet experienced firsthand whether this change significantly improves compilation performance. That said, in previous projects I often noticed Xcode struggling with type inference and code completion whenever different builder content was mixed inside a </span><code>ViewBuilder</code><span>, especially with APIs like Table and Charts. If Xcode 27 truly improves these scenarios, then this change represents much more than just a new builder name.</span></p></blockquote><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-06"><span>tswift: A Lightweight Swift Runtime Built with Rust</span></a></strong></h3><p><span>Without relying on the Swift toolchain, LLVM, code generation, or any C dependencies, tswift can parse, semantically analyze, and execute Swift source code. Developed by </span><a href="https://github.com/siuying"><span>Francis Chong</span></a><span>, tswift implements the Swift frontend entirely in Rust, handling lexical, syntactic, and semantic analysis before interpreting Swift language semantics and standard library behavior through a tree-walking runtime.</span></p><p><span>Beyond the language runtime itself, the project is also exploring framework support. SwiftUI already has a basic rendering pipeline, while Charts currently implements 58 of 60 range-related members, can render Web SVG output, and can bridge to Apple&#8217;s native Charts framework on iOS.</span></p><blockquote><p><span>Whether it&#8217;s the C-based </span><a href="https://miniswift.run/"><span>miniSwift</span></a><span>, the recent signs of the Swift compiler&#8217;s </span><a href="https://fatbobman.com/en/weekly/issue-142/"><span>self-hosting progress</span></a><span>, or the Rust-based tswift runtime, they all demonstrate that the Swift ecosystem is evolving toward a more open and diverse implementation landscape. As more implementation paths emerge, Swift&#8217;s cross-platform potential continues to grow beyond what many expected.</span></p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#19981;&#26159;&#27169;&#22411;&#21464;&#24930;&#20102;&#65292;&#26159;&#20219;&#21153;&#21464;&#22823;&#20102;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-146/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;&#21363;&#20415;&#26159;&#19968;&#20123;&#25105;&#35748;&#20026;&#24182;&#19981;&#31639;&#22797;&#26434;&#30340;&#24037;&#20316;&#65292;AI &#20132;&#20184;&#32467;&#26524;&#20063;&#24120;&#24120;&#38656;&#35201;&#20960;&#20998;&#38047;&#65292;&#29978;&#33267;&#20960;&#21313;&#20998;&#38047;&#12290;&#36825;&#35753;&#25105;&#20135;&#29983;&#20102;&#19968;&#31181;&#38169;&#35273;&#65306;&#38590;&#36947;&#38543;&#30528;&#27169;&#22411;&#33021;&#21147;&#19981;&#26029;&#22686;&#24378;&#65292;&#36895;&#24230;&#21482;&#33021;&#36234;&#26469;&#36234;&#24930;&#65311;</span></p><p><span>&#20854;&#23454;&#65292;&#30495;&#27491;&#30340;&#21407;&#22240;&#26356;&#22810;&#26469;&#33258;&#20110;&#25105;&#33258;&#24049;&#12290;&#34429;&#28982; Agent &#25552;&#20379;&#20102;&#27169;&#22411;&#21644;&#24605;&#32771;&#24378;&#24230;&#30340;&#35843;&#25972;&#36873;&#39033;&#65292;&#20294;&#20026;&#20102;&#30465;&#20107;&#65292;&#20063;&#20026;&#20102;&#36861;&#27714;&#26356;&#39640;&#30340;&#25104;&#21151;&#29575;&#65292;&#25105;&#36234;&#26469;&#36234;&#20064;&#24815;&#25226;&#19968;&#20123;&#21407;&#26412;&#24182;&#19981;&#22797;&#26434;&#30340;&#20219;&#21153;&#30452;&#25509;&#20132;&#32473;&#39640;&#32423;&#27169;&#22411;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#22914;&#20170;&#30340; Agent &#20063;&#19981;&#20250;&#20687;&#36807;&#21435;&#37027;&#26679;&#21482;&#20851;&#27880;&#20320;&#35201;&#27714;&#20462;&#25913;&#30340;&#37027;&#19968;&#23567;&#22359;&#20195;&#30721;&#65292;&#32780;&#26159;&#20250;&#20027;&#21160;&#25193;&#22823;&#25628;&#32034;&#33539;&#22260;&#65292;&#20998;&#26512;&#25913;&#21160;&#26159;&#21542;&#20250;&#24433;&#21709;&#25972;&#20010;&#39033;&#30446;&#65292;&#24182;&#23581;&#35797;&#25552;&#21069;&#21457;&#29616;&#28508;&#22312;&#38382;&#39064;&#12290;&#27169;&#22411;&#34429;&#28982;&#26356;&#24378;&#20102;&#65292;&#20294;&#23436;&#25104;&#19968;&#27425;&#20219;&#21153;&#25152;&#25215;&#25285;&#30340;&#24037;&#20316;&#20063;&#26126;&#26174;&#26356;&#22810;&#20102;&#12290;</span></p><p><span>&#38500;&#27492;&#20043;&#22806;&#65292;&#38543;&#30528;&#25105;&#23545;&#27169;&#22411;&#33021;&#21147;&#30340;&#20449;&#20219;&#19981;&#26029;&#25552;&#39640;&#65292;&#20132;&#32473;&#23427;&#30340;&#20219;&#21153;&#31890;&#24230;&#20063;&#21457;&#29983;&#20102;&#21464;&#21270;&#12290;&#20174;&#26368;&#21021;&#20462;&#25913;&#19968;&#20010;&#20989;&#25968;&#12289;&#20248;&#21270;&#19968;&#20010;&#39029;&#38754;&#65292;&#21040;&#23454;&#29616;&#19968;&#20010;&#21151;&#33021;&#12289;&#23436;&#25104;&#19968;&#20010;&#27169;&#22359;&#65292;&#29978;&#33267;&#30452;&#25509;&#24320;&#21457;&#19968;&#20010;&#20135;&#21697;&#65292;&#25105;&#24050;&#32463;&#19981;&#30693;&#19981;&#35273;&#25226; Agent &#24403;&#25104;&#20102;&#19968;&#20301;&#30495;&#27491;&#30340;&#21327;&#20316;&#32773;&#12290;&#27169;&#22411;&#36895;&#24230;&#30340;&#25552;&#21319;&#65292;&#24050;&#32463;&#36319;&#19981;&#19978;&#20351;&#29992;&#26041;&#24335;&#21464;&#21270;&#30340;&#36895;&#24230;&#12290;</span></p><p><span>&#25442;&#21477;&#35805;&#35828;&#65292;&#24320;&#21457;&#32773;&#36861;&#27714;&#30340;&#24050;&#32463;&#19981;&#20877;&#21482;&#26159;&#8220;&#26356;&#24555;&#22320;&#20889;&#20195;&#30721;&#8221;&#65292;&#32780;&#26159;&#20511;&#21161; AI&#8220;&#26356;&#24930;&#22320;&#20889;&#20986;&#26356;&#22909;&#30340;&#20195;&#30721;&#8221;&#12290;</span></p><p><span>&#20174;&#38382;&#31572;&#24335;&#65292;&#21040;&#20132;&#20184;&#24335;&#65292;&#21482;&#29992;&#20102;&#30701;&#30701;&#19968;&#24180;&#26102;&#38388;&#12290;&#24403;&#25105;&#20204;&#24320;&#22987;&#20064;&#24815;&#19968;&#35273;&#37266;&#26469;&#25509;&#25910;&#25104;&#26524;&#26102;&#65292;&#30495;&#27491;&#30340;&#29942;&#39048;&#20063;&#24708;&#28982;&#21457;&#29983;&#20102;&#21464;&#21270;&#12290;&#36807;&#21435;&#65292;&#25105;&#20204;&#20851;&#24515;&#30340;&#26159;&#27169;&#22411;&#33021;&#19981;&#33021;&#23436;&#25104;&#20219;&#21153;&#65307;&#29616;&#22312;&#65292;&#26356;&#37325;&#35201;&#30340;&#38382;&#39064;&#21464;&#25104;&#20102;&#22914;&#20309;&#23450;&#20041;&#19968;&#20010;&#28165;&#26224;&#12289;&#21487;&#39564;&#35777;&#30340;&#30446;&#26631;&#65292;&#20197;&#21450;&#22914;&#20309;&#38477;&#20302;&#23454;&#29616;&#30446;&#26631;&#30340;&#25104;&#26412;&#12290;&#27169;&#22411;&#36234;&#26469;&#36234;&#20687;&#22242;&#38431;&#25104;&#21592;&#65292;&#32780;&#39640;&#36136;&#37327;&#22320;&#32452;&#32455;&#21644;&#25286;&#35299;&#24037;&#20316;&#65292;&#20063;&#27491;&#22312;&#25104;&#20026;&#26032;&#30340;&#25928;&#29575;&#31454;&#20105;&#21147;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-145/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-01"><span>&#29992;&#29616;&#20195;&#24182;&#21457;&#25216;&#26415;&#24320;&#21457;&#34013;&#29273;&#24212;&#29992; (Bluetooth without the delegate dance)</span></a></strong></h3><p><span>Delegate &#20173;&#26159;&#24456;&#22810;&#24320;&#21457;&#32773;&#22312; Swift Concurrency &#24050;&#32463;&#25512;&#20986;&#25968;&#24180;&#21518;&#19981;&#24471;&#19981;&#38754;&#23545;&#30340;&#38382;&#39064;&#65306;&#19981;&#20165;&#20195;&#30721;&#32452;&#32455;&#32321;&#29712;&#65292;&#22312; Swift 6 &#30340;&#20005;&#26684;&#24182;&#21457;&#26816;&#26597;&#19979;&#65292;&#20063;&#36234;&#26469;&#36234;&#38590;&#19982;&#29616;&#20195;&#24182;&#21457;&#20195;&#30721;&#33258;&#28982;&#21327;&#20316;&#12290;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#21033;&#29992; Swift 6.2 &#30340; Custom Executor&#65292;&#23558; CoreBluetooth &#30340;&#22238;&#35843;&#38431;&#21015;&#19982; Actor &#30340;&#25191;&#34892;&#19978;&#19979;&#25991;&#32465;&#23450;&#65292;&#20351; Delegate &#22238;&#35843;&#22825;&#28982;&#36816;&#34892;&#22312; Actor &#38548;&#31163;&#29615;&#22659;&#20013;&#65292;&#26080;&#38656;&#39069;&#22806;&#30340;&#38145;&#12289;&#32447;&#31243;&#20999;&#25442;&#25110;&#21516;&#27493;&#36923;&#36753;&#12290;</span></p><blockquote><p><span>Custom Executor &#21487;&#20197;&#35753; Actor &#20013;&#30340;&#20219;&#21153;&#36816;&#34892;&#22312;&#25351;&#23450;&#30340;&#25191;&#34892;&#22120;&#19978;&#65292;&#26159;&#36830;&#25509;&#20256;&#32479;&#22238;&#35843; API &#19982; Swift Concurrency &#30340;&#19968;&#39033;&#37325;&#35201;&#33021;&#21147;&#12290;&#22914;&#26524;&#20320;&#20063;&#38754;&#20020;&#31867;&#20284;&#30340;&#36801;&#31227;&#25110;&#23553;&#35013;&#38382;&#39064;&#65292;&#19981;&#22952;&#21442;&#32771;&#20316;&#32773;&#30340;&#23454;&#29616;&#24605;&#36335;&#12290;&#25105;&#20063;&#26366;&#22312;&#8288;</span><a href="https://fatbobman.com/zh/posts/core-data-reform-achieving-elegant-concurrency-operations-like-swiftdata/"><span>&#36825;&#31687;&#25991;&#31456;</span></a><span>&#20013;&#65292;&#20197; Core Data &#20026;&#20363;&#65292;&#35814;&#32454;&#20171;&#32461;&#20102;&#22914;&#20309;&#21033;&#29992; Custom Executor &#23558;&#20256;&#32479;&#20018;&#34892;&#38431;&#21015;&#19982; Actor &#25191;&#34892;&#22120;&#32465;&#23450;&#65292;&#23454;&#29616;&#19982; Swift Concurrency &#30340;&#33258;&#28982;&#34701;&#21512;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-02"><span>CI &#29615;&#22659;&#19979;&#30340; Xcode &#31649;&#29702;&#23454;&#36341; (Working with Xcode on CI)</span></a></strong></h3><p><span>&#38543;&#30528;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#37319;&#29992;&#33258;&#24314; macOS Runner &#25110;&#20113;&#31471; CI&#65292;&#31283;&#23450;&#22320;&#31649;&#29702; Xcode&#12289;Simulator Runtime &#19982;&#31614;&#21517;&#29615;&#22659;&#65292;&#24050;&#25104;&#20026;&#24037;&#31243;&#32500;&#25252;&#30340;&#37325;&#35201;&#32452;&#25104;&#37096;&#20998;&#12290;</span><a href="https://mastodon.social/@rodionovd"><span>Dmitry Rodionov</span></a><span> &#22260;&#32469; Xcode CLI &#22312; CI &#20013;&#30340;&#20351;&#29992;&#65292;&#24635;&#32467;&#20102;&#19981;&#23569;&#20010;&#20154;&#24515;&#24471;&#65292;&#20363;&#22914;&#20351;&#29992; </span><code>DEVELOPER_DIR</code><span> &#26367;&#20195; </span><code>xcode-select</code><span> &#31649;&#29702;&#22810;&#29256;&#26412; Xcode&#12289;&#33258;&#21160;&#23433;&#35013;&#19982;&#28165;&#29702; Simulator Runtime &#21644; Metal Toolchain&#65292;&#20197;&#21450;&#21033;&#29992; Compilation Caching &#20943;&#23569;&#20998;&#25903;&#20999;&#25442;&#24102;&#26469;&#30340;&#37325;&#22797;&#32534;&#35793;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-03"><span>&#27048;&#24178; GitHub Actions &#30340;&#26368;&#21518;&#19968;&#28857;&#20215;&#20540;</span></a></strong></h3><p><span>GitHub Actions &#30340;&#20248;&#21270;&#65292;&#26410;&#24517;&#24847;&#21619;&#30528;&#26356;&#28608;&#36827;&#30340;&#32531;&#23384;&#12289;&#26356;&#22797;&#26434;&#30340; Workflow&#65292;&#25110;&#26356;&#22810;&#30340;&#26465;&#20214;&#21028;&#26029;&#12290;&#36825;&#31687;&#25991;&#31456;&#25552;&#20986;&#20102;&#19968;&#20010;&#20540;&#24471;&#20511;&#37492;&#30340;&#24605;&#36335;&#65306;&#35753;&#27599;&#19968;&#27425; CI &#25191;&#34892;&#37117;&#19982;&#23454;&#38469;&#39118;&#38505;&#30456;&#21305;&#37197;&#12290;</span><a href="https://x.com/rbbtsn0w"><span>Snow</span></a><span> &#20174;&#19968;&#27425;&#30475;&#20284;&#26222;&#36890;&#30340; Flaky Test &#25490;&#26597;&#24320;&#22987;&#65292;&#36880;&#27493;&#35752;&#35770;&#20102;&#22914;&#20309;&#29992;&#30830;&#23450;&#24615;&#27979;&#35797;&#28040;&#38500;&#26080;&#24847;&#20041;&#30340;&#37325;&#36305;&#12289;&#23558;&#21487;&#31227;&#26893;&#30340;&#26816;&#26597;&#36801;&#31227;&#21040; Linux&#12289;&#20165;&#25226;&#30495;&#27491;&#20381;&#36182; Xcode &#30340;&#39564;&#35777;&#30041;&#32473; macOS&#65292;&#20197;&#21450;&#26681;&#25454;&#21464;&#26356;&#39118;&#38505;&#21160;&#24577;&#36873;&#25321; Build&#12289;Test &#25110; Build for Testing&#65292;&#36991;&#20813;&#26114;&#36149;&#30340; Runner &#25191;&#34892;&#19981;&#24517;&#35201;&#30340;&#24037;&#20316;&#12290;</span></p><blockquote><p><span>&#25105;&#24456;&#35748;&#21516;&#25991;&#20013;&#30340;&#19968;&#20010;&#35266;&#28857;&#65306;CI &#30340;&#30446;&#26631;&#19981;&#26159;&#8220;&#36305;&#24471;&#26356;&#22810;&#8221;&#65292;&#32780;&#26159;&#8220;&#22238;&#31572;&#27491;&#30830;&#30340;&#38382;&#39064;&#8221;&#12290;&#27599;&#19968;&#27425;&#26114;&#36149;&#30340; macOS &#26500;&#24314;&#65292;&#37117;&#24212;&#35813;&#39564;&#35777;&#19968;&#20010;&#26356;&#20415;&#23452;&#30340; Runner &#26080;&#27861;&#39564;&#35777;&#30340;&#39118;&#38505;&#65307;&#27599;&#19968;&#27425;&#22833;&#36133;&#65292;&#20063;&#37117;&#24212;&#35813;&#25552;&#20379;&#36275;&#20197;&#25512;&#21160;&#20462;&#22797;&#30340;&#20449;&#24687;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-04"><span>&#22312; SwiftUI &#20013;&#26500;&#24314;&#33258;&#36866;&#24212;&#38750;&#27169;&#24577;&#38754;&#26495; (Building adaptive non-modal panels in SwiftUI)</span></a></strong></h3><p><span>&#20174; WWDC 26 &#24320;&#22987;&#65292;iPhone-only &#24212;&#29992;&#22312;&#36890;&#36807; iPhone Mirroring &#26174;&#31034;&#21040; Mac&#65292;&#25110;&#22312; iPad &#19978;&#36816;&#34892;&#26102;&#65292;&#23558;&#36827;&#20837;&#21487;&#21464;&#23610;&#23544;&#29615;&#22659;&#12290;&#36825;&#24847;&#21619;&#30528;&#20165;&#20381;&#36182; </span><code>horizontalSizeClass</code><span> &#21028;&#26029;&#24067;&#23616;&#24418;&#24577;&#24050;&#32463;&#36234;&#26469;&#36234;&#19981;&#21487;&#38752;&#12290;&#8288;</span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#20171;&#32461;&#20102;&#22914;&#20309;&#26500;&#24314;&#19968;&#20010;&#33258;&#36866;&#24212;&#30340;&#38750;&#27169;&#24577; Panel&#65306;&#36890;&#36807; </span><code>onGeometryChange</code><span> &#22312;&#22330;&#26223;&#26681;&#37096;&#35760;&#24405;&#31383;&#21475;&#23610;&#23544;&#19982; Safe Area&#65292;&#26681;&#25454;&#30495;&#23454;&#21487;&#29992;&#23485;&#24230;&#20915;&#23450;&#38754;&#26495;&#26174;&#31034;&#22312;&#24213;&#37096;&#36824;&#26159;&#20391;&#36793;&#12290;&#20854;&#20013;&#65292;&#22312;&#25302;&#21160;&#26399;&#38388;&#20445;&#30041;&#24050;&#32463;&#35299;&#26512;&#30340;&#24067;&#23616;&#32531;&#23384;&#65292;&#36991;&#20813;&#33258;&#36866;&#24212;&#20869;&#23481;&#22240;&#37325;&#22797;&#27979;&#37327;&#32780;&#20986;&#29616;&#23610;&#23544;&#36339;&#21464;&#65292;&#26159;&#19968;&#20010;&#30456;&#24403;&#23454;&#29992;&#30340;&#25216;&#24039;&#12290;</span></p><blockquote><p><span>&#22914;&#26524;&#20320;&#30340;&#24212;&#29992;&#26159; iPhone-only&#65292;&#24182;&#19988;&#20173;&#26377;&#29992;&#25143;&#20250;&#22312; iPad &#25110; macOS &#19978;&#20351;&#29992;&#23427;&#65292;&#37027;&#20040;&#20174;&#20170;&#24180;&#24320;&#22987;&#23601;&#38656;&#35201;&#29305;&#21035;&#20851;&#27880;&#24067;&#23616;&#30340;&#36866;&#37197;&#12290;&#8288;</span><a href="https://fatbobman.com/zh/posts/from-size-class-to-available-space/"><span>&#21487;&#21464;&#30011;&#24067;</span></a><span> &#20174;&#26576;&#31181;&#24847;&#20041;&#19978;&#26469;&#35828;&#65292;&#19981;&#20877;&#20445;&#35777;&#24320;&#21457;&#32773;&#23545;&#30028;&#38754;&#24067;&#23616;&#25317;&#26377;&#32477;&#23545;&#25511;&#21046;&#26435;&#65292;&#32780;&#26159;&#23558;&#26356;&#22810;&#30340;&#36873;&#25321;&#26435;&#20132;&#21040;&#20102;&#29992;&#25143;&#25163;&#20013;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-05"><span>SwiftUI @ContentBuilder&#65306;&#22823;&#24133;&#25552;&#21319; Xcode 27 &#32534;&#35793;&#25928;&#29575; (SwiftUI @ContentBuilder - Faster Type Checking in Xcode 27)</span></a></strong></h3><p><span>Xcode 27 &#24341;&#20837;&#20102;&#26032;&#30340; </span><code>@ContentBuilder</code><span>&#12290;&#34429;&#28982;&#23427;&#30446;&#21069;&#20173;&#21482;&#26159; </span><code>ViewBuilder</code><span> &#30340;&#31867;&#22411;&#21035;&#21517;&#65292;&#20294; Apple &#24050;&#24320;&#22987;&#22312;&#26032;&#30340; SwiftUI API &#20013;&#25512;&#33616;&#20351;&#29992;&#36825;&#19968;&#21517;&#31216;&#12290;</span><a href="https://x.com/sagarunagar_"><span>Sagar Unagar</span></a><span> &#20171;&#32461;&#20102;&#36825;&#19968;&#21464;&#21270;&#65292;&#21516;&#26102;&#25351;&#20986;&#65292;&#23545;&#22823;&#22810;&#25968;&#24212;&#29992;&#26469;&#35828;&#65292;&#24182;&#27809;&#26377;&#24517;&#35201;&#31435;&#21363;&#23558;&#25152;&#26377; </span><code>@ViewBuilder</code><span> &#26367;&#25442;&#25104; </span><code>@ContentBuilder</code><span>&#65292;&#24050;&#26377;&#20195;&#30721;&#22312; Xcode 27 &#19979;&#21516;&#26679;&#33021;&#22815;&#21463;&#30410;&#20110;&#32534;&#35793;&#22120;&#30340;&#25913;&#36827;&#12290;</span></p><blockquote><p><span>&#25105;&#26368;&#36817;&#24182;&#27809;&#26377;&#24590;&#20040;&#20889; SwiftUI &#20195;&#30721;&#65292;&#22240;&#27492;&#36824;&#27809;&#26377;&#20146;&#36523;&#20307;&#20250;&#21040;&#36825;&#20010;&#25913;&#21160;&#26159;&#21542;&#30495;&#27491;&#24102;&#26469;&#20102;&#32534;&#35793;&#25928;&#29575;&#19978;&#30340;&#25552;&#21319;&#12290;&#19981;&#36807;&#22312;&#20043;&#21069;&#30340;&#24320;&#21457;&#20013;&#65292;&#26080;&#35770;&#26159; Table &#36824;&#26159; Charts&#65292;&#24403;&#23558;&#19981;&#21516;&#30340; Builder &#20869;&#23481;&#28151;&#20889;&#21040; </span><code>ViewBuilder</code><span> &#20013;&#26102;&#65292;Xcode &#30340;&#31867;&#22411;&#25512;&#23548;&#21644;&#20195;&#30721;&#34917;&#20840;&#37117;&#20250;&#26126;&#26174;&#21464;&#24930;&#12290;&#22914;&#26524; Xcode 27 &#30830;&#23454;&#25913;&#21892;&#20102;&#36825;&#31867;&#22330;&#26223;&#65292;&#37027;&#20040;&#36825;&#27425;&#35843;&#25972;&#30340;&#24847;&#20041;&#23601;&#36828;&#19981;&#27490;&#19968;&#20010;&#26032;&#30340; Builder &#21517;&#31216;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-06"><span>tswift: &#29992; Rust &#26500;&#24314;&#36731;&#37327; Swift &#36816;&#34892;&#26102;</span></a></strong></h3><p><span>&#26080;&#38656; Swift &#24037;&#20855;&#38142;&#12289;LLVM&#12289;&#20195;&#30721;&#29983;&#25104;&#25110; C &#20381;&#36182;&#65292;&#21363;&#21487;&#35299;&#26512;&#12289;&#35821;&#20041;&#20998;&#26512;&#24182;&#25191;&#34892; Swift &#28304;&#30721;&#12290;&#8288;</span><a href="https://github.com/siuying"><span>Francis Chong</span></a><span> &#24320;&#21457;&#30340; tswift &#20197;&#32431; Rust &#23454;&#29616;&#20102; Swift &#21069;&#31471;&#65292;&#23436;&#25104;&#35789;&#27861;&#12289;&#35821;&#27861;&#19982;&#35821;&#20041;&#20998;&#26512;&#65292;&#20877;&#36890;&#36807;&#26641;&#36941;&#21382;&#36816;&#34892;&#26102;&#23454;&#29616; Swift &#30340;&#35821;&#35328;&#35821;&#20041;&#19982;&#26631;&#20934;&#24211;&#34892;&#20026;&#12290;</span></p><p><span>&#38500;&#35821;&#35328;&#36816;&#34892;&#26102;&#22806;&#65292;&#39033;&#30446;&#20063;&#22312;&#25506;&#32034;&#26694;&#26550;&#23618;&#38754;&#30340;&#25903;&#25345;&#65306;SwiftUI &#24050;&#20855;&#22791;&#22522;&#30784;&#28210;&#26579;&#33021;&#21147;&#65292;Charts &#25903;&#25345;&#35206;&#30422; 58/60 &#20010;&#33539;&#22260;&#25104;&#21592;&#65292;&#21487;&#36755;&#20986; Web SVG&#65292;&#24182;&#21487;&#19979;&#27785;&#21040; iOS &#21407;&#29983; Charts&#12290;</span></p><blockquote><p><span>&#26080;&#35770;&#26159; C &#32534;&#20889;&#30340; </span><a href="https://miniswift.run/"><span>miniSwift</span></a><span>&#12289;Swift &#32534;&#35793;&#22120;&#36817;&#26399;&#23637;&#29616;&#20986;&#30340;&#8288;</span><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>&#33258;&#20030;&#36857;&#35937;</span></a><span>&#65292;&#36824;&#26159;&#20197; Rust &#26500;&#24314;&#30340; tswift&#65292;&#37117;&#23637;&#29616;&#20986; Swift &#29983;&#24577;&#27491;&#26397;&#30528;&#26356;&#21152;&#24320;&#25918;&#12289;&#22810;&#20803;&#30340;&#23454;&#29616;&#26041;&#21521;&#21457;&#23637;&#12290;&#36234;&#26469;&#36234;&#20016;&#23500;&#30340;&#23454;&#29616;&#36335;&#24452;&#65292;&#20063;&#35753; Swift &#30340;&#36328;&#24179;&#21488;&#28508;&#21147;&#21576;&#29616;&#20986;&#36229;&#20986;&#39044;&#26399;&#30340;&#21487;&#33021;&#24615;&#12290;</span></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #145]]></title><description><![CDATA[When Inspiration Outruns the Results]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 20 Jul 2026 12:01:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kcn6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kcn6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kcn6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 424w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 848w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1272w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" width="1400" height="705" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:705,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:67124,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/207725710?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kcn6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 424w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 848w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1272w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@skyestudios?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Skye Studios</a><span> on </span><a href="https://unsplash.com/photos/low-angle-photography-of-drop-lights-NDLLFxTELrU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Inspiration Outruns the Results</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-145/">Read on web &#8594;</a></p><p><span>Over the past few months, I&#8217;ve been refining my own AI-assisted workflow. Real progress has been made, but for long-running tasks, I&#8217;ve consistently lacked any quantifiable benchmark data. Thanks to competition among AI model providers, OpenAI recently lifted its 5-hour usage cap &#8212; which finally let me test my ideas without interruption, and compare the results and performance of different approaches head to head. Last week I burned through 6 or 7 accumulated limit resets across my two Pro accounts, and genuinely got a taste of &#8220;token freedom.&#8221;</span></p><p><span>Since each test run typically takes at least several dozen minutes, I found myself flooded with ideas while waiting and observing &#8212; new optimizations and tweaks kept popping into my head. This produced a strange phenomenon: while the old version was still running its test, the new version&#8217;s code was already written. My iteration speed had completely outpaced my test results. Some of those changes did turn out to work well, but once I calmed down, I had to face an uncomfortable truth &#8212; many of my &#8220;brilliant ideas&#8221; were really just assumptions I hadn&#8217;t thought through carefully.</span></p><p><span>At the time, caught in the false &#8220;flow state&#8221; that vibe coding produces, I didn&#8217;t notice this at all. It wasn&#8217;t until the test results showed a clear regression that I slammed on the brakes and actually stopped to reflect.</span></p><p><span>AI genuinely shortens the time it takes to validate an idea &#8212; but that convenience makes it easy to fall into a blind spot, skipping the deep thinking and logical groundwork that should happen before you start coding. Cheap, exhaustive testing shouldn&#8217;t become a substitute for real thought. Looking back, the intuition and experience we&#8217;ve built up are often far more efficient than AI&#8217;s blind trial-and-error at ruling out or refining ideas that were never going to work.</span></p><p><span>AI is an extraordinarily powerful tool &#8212; but where it should really earn its keep is in assisting execution, not replacing thinking.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-144/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-01"><span>Geometry, Compositing and Drawing Groups in SwiftUI</span></a></strong></h3><p><span>SwiftUI has three similarly-named modifiers with very different jobs &#8212; </span><code>geometryGroup()</code><span>, </span><code>compositingGroup()</code><span>, and </span><code>drawingGroup()</code><span>. They&#8217;re not only easy to confuse; most people don&#8217;t fully grasp the subtlety of what each one actually does.</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> breaks them down through three concrete scenarios: </span><code>geometryGroup()</code><span> lifts the interpolation up a level, fixing the problem of child views lacking a consistent transition state during animation; </span><code>compositingGroup()</code><span> establishes a compositing boundary for the graphical effects applied above it (like opacity or blend modes), so they treat multiple sublayers as a single unit rather than acting on each layer separately; </span><code>drawingGroup()</code><span> rasterizes multiple layers into a single offscreen image, trading space for performance &#8212; at the cost of having to regenerate that image every time the content changes.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-02"><span>One TaskGroup, Two Live Streams: a Swift 6 LLM Benchmark</span></a></strong></h3><p><span>By pulling all mutable run-state into a single </span><code>actor</code><span>, </span><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> safely merges two independent async streams &#8212; model inference and system telemetry &#8212; into one ordered event stream.</span></p><p><span>Token counts, time-to-first-token latency, sample records, and all other run-time state live only inside the actor. Inside </span><code>execute</code><span>, a single </span><code>withThrowingTaskGroup</code><span> runs two things at once: a child task consumes the telemetry stream, sampling every 500ms and emitting </span><code>RunEvent</code><span>s; a parent task runs the inference loop sequentially, where every </span><code>await</code><span> is a suspension point &#8212; the child task only gets a chance to run when the parent yields. The whole actor exposes just one </span><code>AsyncThrowingStream</code><span> to the outside. Because every access goes through actor isolation, the interleaving never conflicts &#8212; zero data races isn&#8217;t a matter of discipline, it&#8217;s something the compiler proves outright.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-03"><span>Syncing SwiftData with a Custom Backend Using HistoryObserver</span></a></strong></h3><p><span>Years ago, Apple gave SwiftData a history mechanism similar to Core Data&#8217;s Persistent History Tracking, letting developers track data-change events made to the same database from different sources in real time. But without a simple entry point that fit SwiftData&#8217;s design philosophy, the feature never saw much adoption. At WWDC 2026, Apple introduced </span><code>HistoryObserver</code><span> for SwiftData, making both triggering and incremental reads dramatically simpler. </span><a href="https://x.com/azamsharp"><span>Mohammad Azam</span></a><span> shows how this plays out in a real project, building a complete custom one-way sync pipeline with </span><code>HistoryObserver</code><span>.</span></p><p><span>The article walks through a simple room-measurement app: using </span><code>withContinuousObservation</code><span> to watch a change counter and trigger sync, using a persisted </span><code>lastToken</code><span> as a bookmark for incremental reads, and using </span><code>isDeleted</code><span> soft deletes paired with </span><code>author</code><span> tags to avoid the recursive self-triggering that hard deletes would otherwise cause. Mohammad works through each of the pitfalls you&#8217;ll hit building a sync engine, one by one, with a complete runnable example on GitHub.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-04"><span>Public Asset Symbol Constants in Swift Packages</span></a></strong></h3><p><span>Xcode auto-generates typed asset constants from </span><code>.xcassets</code><span> catalogs &#8212; things like </span><code>Color(.skyBlue)</code><span> / </span><code>Image(.logo)</code><span> &#8212; but these constants are always </span><code>internal</code><span>, so other Swift packages can&#8217;t use them. Xcode offers no public option, and there&#8217;s no way to turn this generation off from </span><code>Package.swift</code><span> either.</span></p><p><a href="https://mastodon.social/@ralfebert"><span>Ralf Ebert</span></a><span> puts any assets meant for cross-package sharing into a </span><code>Public/</code><span> subfolder inside </span><code>.xcassets</code><span>, then uses a Ruby script to scan every </span><code>**/*.xcassets/Public/</code><span> and generate a </span><code>&lt;PackageName&gt;+Generated.swift</code><span> with a nested enum, re-exporting the internal symbols as </span><code>public</code><span> &#8212; so other libraries can simply call </span><code>Image(.AppCommons.logo)</code><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-06"><span>Previews and MCP</span></a></strong></h3><p><span>Xcode 27 exposes 47 tools through its MCP interface, and </span><code>RenderPreview</code><span> is the one responsible for rendering and screenshotting a SwiftUI Preview. But calling it requires the app to establish an STDIO connection via </span><code>xcrun mcpbridge</code><span>, which means the app can&#8217;t be sandboxed &#8212; a direct conflict with Mac App Store requirements.</span></p><p><a href="https://www.linkedin.com/in/amy-delves-41968418b/"><span>Amy Delves</span></a><span>&#8216;s solution is to introduce a separate, unsandboxed XPC service dedicated to talking to Xcode&#8217;s MCP, while the main app stays sandboxed; the two communicate over XPC. The rendered result is read by the helper service and shipped back inline, sidestepping the fact that the main sandboxed app can&#8217;t reach file paths outside the sandbox.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-07"><span>I Found a Workaround for an App Store Connect Bug</span></a></strong></h3><p><span>Plenty of developers have run into this App Store Connect bug: pages keep redirecting back to </span><code>/login</code><span> even while you&#8217;re already logged in. After </span><a href="https://lapcatsoftware.com/articles/2026/7/6.html"><span>getting nowhere with Apple</span></a><span>, </span><a href="https://mastodon.social/@lapcatsoftware"><span>Jeff Johnson</span></a><span> compared the HTTP cookies of two requests in Chrome and tracked down the root cause: a session cookie named </span><code>dc</code><span> (</span><code>dc=st</code><span>) &#8212; on first login, that cookie hasn&#8217;t been set yet, so the server responds with a 302 redirect to the login page. The fix was to manually turn it into a permanent cookie expiring a year out. The whole diagnosis took under an hour.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-05"><span>What&#8217;s an Icon in 2026?</span></a></strong></h3><p><span>At WWDC 2025, Apple recommended using Icon Composer to build icons, with the rationale that icons should move from static images toward &#8220;more expressive,&#8221; multi-layered artworks. As a result, an icon no longer has one fixed appearance &#8212; it only takes on a particular form once &#8220;observed&#8221; on a specific device under specific settings. Take Apple&#8217;s Phone app icon as an example: the classic green background with a white handset now splits into several separate versions across dark mode, glass mode, and various tint colors.</span></p><p><a href="https://mastodon.social/@jimniels"><span>Jim Nielsen</span></a><span> argues that an icon&#8217;s value has always rested on being simple, consistent, and memorable. The further you push toward &#8220;expressiveness&#8221; by stacking on variants, the more you dilute the icon&#8217;s core job &#8212; instant recognition.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-08"><span>ImmersiveMap: Building a Native Immersive Map with SwiftUI and Metal</span></a></strong></h3><p><span>ImmersiveMap is a native map rendering engine for Apple platforms built by </span><a href="https://x.com/BobkinArtem"><span>Artem Bobkin</span></a><span>, implemented in Swift and Metal, and exposed through </span><code>ImmersiveMapView</code><span> as a declarative interface that fits naturally into SwiftUI conventions.</span></p><p><span>The project&#8217;s standout capability is a continuous transition between a spherical globe and a flat map. Beyond that, it covers vector tile (Vector Tile Source) parsing, label layout, 3D buildings, starfield and day/night effects, map styling, camera fly-to animations, and live markers that support clustering and dynamic movement. Developers can run it out of the box with the built-in tiles, or plug in Mapbox or a custom MVT (Mapbox Vector Tile) data source.</span></p><p><span>ImmersiveMap is a thorough demonstration of how to wrap a complex Metal rendering system behind a clean SwiftUI API. For developers who want to understand how a map engine, SwiftUI, and low-level graphics rendering work together, it&#8217;s a genuinely worthwhile open-source project to study.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403;&#28789;&#24863;&#36305;&#22312;&#20102;&#32467;&#26524;&#21069;&#38754;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-145/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#36807;&#21435;&#20960;&#20010;&#26376;&#65292;&#25105;&#19968;&#30452;&#22312;&#20248;&#21270;&#33258;&#24049;&#30340; AI &#24037;&#20316;&#27969;&#12290;&#23613;&#31649;&#39047;&#26377;&#36827;&#23637;&#65292;&#20294;&#22312;&#38271;&#20219;&#21153;&#20013;&#65292;&#22987;&#32456;&#32570;&#20047;&#19968;&#20123;&#21487;&#20197;&#37327;&#21270;&#30340; benchmark &#25968;&#25454;&#12290;&#24471;&#30410;&#20110; AI &#27169;&#22411;&#20844;&#21496;&#20043;&#38388;&#30340;&#31454;&#20105;&#65292;&#19981;&#20037;&#21069; OpenAI &#35299;&#38500;&#20102; 5 &#23567;&#26102;&#30340;&#39069;&#24230;&#38480;&#21046;&#65292;&#36825;&#35753;&#25105;&#32456;&#20110;&#33021;&#22815;&#19981;&#38388;&#26029;&#22320;&#27979;&#35797;&#33258;&#24049;&#30340;&#19968;&#20123;&#24819;&#27861;&#65292;&#24182;&#27604;&#36739;&#19981;&#21516;&#26041;&#26696;&#22312;&#25928;&#26524;&#19982;&#24615;&#33021;&#19978;&#30340;&#24046;&#24322;&#12290;&#19978;&#21608;&#65292;&#25105;&#25226;&#20004;&#20010; Pro &#36134;&#25143;&#25874;&#19979;&#30340; 6&#12289;7 &#27425;&#39069;&#24230;&#37117;&#29992;&#25481;&#20102;&#65292;&#30528;&#23454;&#20307;&#39564;&#20102;&#19968;&#25226;&#8220;Token &#33258;&#30001;&#8221;&#30340;&#24863;&#35273;&#12290;</span></p><p><span>&#30001;&#20110;&#27599;&#19968;&#20010;&#27979;&#35797;&#36890;&#24120;&#37117;&#38656;&#35201;&#36305;&#19978;&#33267;&#23569;&#20960;&#21313;&#20998;&#38047;&#65292;&#22312;&#31561;&#24453;&#12289;&#35266;&#27979;&#30340;&#36807;&#31243;&#20013;&#65292;&#25105;&#32463;&#24120;&#20250;&#28789;&#24863;&#28044;&#21160;&#65292;&#33041;&#23376;&#37324;&#19981;&#26029;&#20882;&#20986;&#21508;&#31181;&#20248;&#21270;&#21644;&#35843;&#25972;&#26041;&#26696;&#12290;&#36825;&#23601;&#20135;&#29983;&#20102;&#19968;&#20010;&#22855;&#24618;&#30340;&#29616;&#35937;&#65306;&#26087;&#29256;&#26412;&#30340;&#27979;&#35797;&#36824;&#22312;&#36816;&#34892;&#26102;&#65292;&#26032;&#29256;&#26412;&#30340;&#20195;&#30721;&#24050;&#32463;&#20889;&#23436;&#20102;&#12290;&#36845;&#20195;&#36895;&#24230;&#24443;&#24213;&#36305;&#22312;&#20102;&#27979;&#35797;&#32467;&#26524;&#21069;&#38754;&#12290;&#23613;&#31649;&#20854;&#20013;&#30830;&#23454;&#26377;&#19968;&#20123;&#25913;&#21160;&#39047;&#35265;&#25104;&#25928;&#65292;&#20294;&#20919;&#38745;&#21518;&#20063;&#19981;&#24471;&#19981;&#38754;&#23545;&#19968;&#20010;&#27531;&#37239;&#30340;&#20107;&#23454;&#8212;&#8212;&#35768;&#22810;&#33258;&#20197;&#20026;&#26159;&#30340;&#8220;&#28789;&#24863;&#8221;&#20854;&#23454;&#21482;&#26159;&#24819;&#24403;&#28982;&#65292;&#24182;&#27809;&#26377;&#32463;&#36807;&#23457;&#24910;&#30340;&#24605;&#32771;&#12290;</span></p><p><span>&#28982;&#32780;&#65292;&#22312;&#37027;&#31181;&#30001;&#8220;Vibe Coding&#8221;&#20135;&#29983;&#30340;&#34394;&#20551;&#8220;&#24515;&#27969;&#8221;&#29366;&#24577;&#19979;&#65292;&#24403;&#26102;&#30340;&#25105;&#24182;&#27809;&#26377;&#24847;&#35782;&#21040;&#36825;&#19968;&#28857;&#12290;&#30452;&#21040;&#27979;&#35797;&#32467;&#26524;&#20986;&#29616;&#26126;&#26174;&#30340;&#21155;&#21270;&#65292;&#25105;&#25165;&#29467;&#22320;&#36393;&#19979;&#21049;&#36710;&#65292;&#24320;&#22987;&#35748;&#30495;&#21453;&#24605;&#12290;</span></p><p><span>AI &#30340;&#30830;&#26497;&#22823;&#22320;&#32553;&#30701;&#20102;&#25105;&#20204;&#39564;&#35777;&#19968;&#20010; Idea &#30340;&#26102;&#38388;&#65292;&#20294;&#36825;&#31181;&#20415;&#21033;&#20063;&#23481;&#26131;&#35753;&#20154;&#38519;&#20837;&#30450;&#21306;&#65292;&#24573;&#30053;&#20102;&#22312;&#21160;&#25163;&#21069;&#23545;&#26500;&#24819;&#36827;&#34892;&#28145;&#20837;&#24605;&#32771;&#19982;&#36923;&#36753;&#26803;&#29702;&#30340;&#36807;&#31243;&#12290;&#19981;&#33021;&#35753;&#20302;&#25104;&#26412;&#30340;&#8220;&#31351;&#20030;&#27979;&#35797;&#8221;&#21462;&#20195;&#30495;&#27491;&#30340;&#24605;&#32771;&#12290;&#22238;&#36807;&#22836;&#26469;&#30475;&#65292;&#25105;&#20204;&#31215;&#32047;&#30340;&#30452;&#35273;&#19982;&#32463;&#39564;&#65292;&#22312;&#21542;&#20915;&#25110;&#35843;&#25972;&#37027;&#20123;&#19981;&#20999;&#23454;&#38469;&#30340;&#26500;&#24819;&#26102;&#65292;&#25928;&#29575;&#24448;&#24448;&#36828;&#39640;&#20110; AI &#30340;&#30450;&#30446;&#35797;&#38169;&#12290;</span></p><p><span>AI &#26159;&#19968;&#20010;&#26497;&#20854;&#24378;&#22823;&#30340;&#24037;&#20855;&#65292;&#20294;&#23427;&#26368;&#35813;&#21457;&#25381;&#20316;&#29992;&#30340;&#22320;&#26041;&#26159;&#36741;&#21161;&#25191;&#34892;&#65292;&#32780;&#38750;&#20195;&#26367;&#24605;&#32771;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-144/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-01"><span>&#21400;&#28165; SwiftUI &#20013;&#30340;&#19977;&#22823;&#35270;&#22270;&#32452;&#20462;&#39280;&#31526; (Geometry, compositing and drawing groups in SwiftUI)</span></a></strong></h3><p><span>SwiftUI &#20013;&#19977;&#20010;&#21517;&#23383;&#30456;&#36817;&#21364;&#32844;&#36131;&#36837;&#24322;&#30340;&#20462;&#39280;&#31526;&#8212;&#8212;</span><code>geometryGroup()</code><span>&#12289;</span><code>compositingGroup()</code><span>&#12289;</span><code>drawingGroup()</code><span>&#65292;&#23427;&#20204;&#19981;&#20165;&#23481;&#26131;&#34987;&#28151;&#28102;&#65292;&#32780;&#19988;&#24456;&#22810;&#20154;&#20063;&#19981;&#30693;&#36947;&#23427;&#20204;&#30340;&#31934;&#22937;&#20316;&#29992;&#12290;</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> &#29992;&#19977;&#20010;&#20855;&#20307;&#22330;&#26223;&#36880;&#19968;&#25286;&#35299;&#65306;</span><code>geometryGroup()</code><span> &#36890;&#36807;&#23558;&#25554;&#20540;&#26426;&#21046;&#19978;&#25552;&#65292;&#35299;&#20915;&#23376;&#35270;&#22270;&#21160;&#30011;&#32570;&#23569;&#19968;&#33268;&#36807;&#28193;&#29366;&#24577;&#30340;&#38382;&#39064;&#65307;</span><code>compositingGroup()</code><span> &#20026;&#20854;&#19978;&#23618;&#30340;&#22270;&#24418;&#25928;&#26524;&#65288;&#22914; opacity&#12289;blend mode&#65289;&#21010;&#23450;&#21512;&#25104;&#36793;&#30028;&#65292;&#20351;&#20854;&#25226;&#22810;&#20010;&#23376;&#23618;&#32423;&#24403;&#20316;&#19968;&#20010;&#25972;&#20307;&#22788;&#29702;&#65292;&#32780;&#38750;&#36880;&#23618;&#20998;&#21035;&#20316;&#29992;&#65307;</span><code>drawingGroup()</code><span> &#21017;&#26159;&#25226;&#22810;&#20010;&#23618;&#32423;&#26629;&#26684;&#21270;&#65288;rasterize&#65289;&#20026;&#19968;&#24352;&#31163;&#23631;&#22270;&#20687;&#65288;offscreen image&#65289;&#65292;&#20197;&#31354;&#38388;&#25442;&#24615;&#33021;&#65292;&#20195;&#20215;&#26159;&#27599;&#27425;&#20869;&#23481;&#21464;&#21270;&#37117;&#35201;&#37325;&#26032;&#29983;&#25104;&#36825;&#24352;&#22270;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-02"><span>&#29992; Swift 6 &#24182;&#21457;&#26426;&#21046;&#21512;&#24182; LLM &#19982;&#36965;&#27979;&#21452;&#25968;&#25454;&#27969; (One TaskGroup, Two Live Streams: a Swift 6 LLM Benchmark)</span></a></strong></h3><p><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> &#36890;&#36807;&#23558;&#25152;&#26377;&#21487;&#21464;&#36816;&#34892;&#29366;&#24577;&#25910;&#36827;&#19968;&#20010; </span><code>actor</code><span>&#65292;&#20174;&#32780;&#23558;&#27169;&#22411;&#25512;&#29702;&#19982;&#31995;&#32479;&#36965;&#27979;&#20004;&#26465;&#29420;&#31435;&#30340;&#24322;&#27493;&#27969;&#65292;&#23433;&#20840;&#21512;&#24182;&#20026;&#19968;&#20010;&#26377;&#24207;&#20107;&#20214;&#27969;&#12290;</span></p><p><span>token &#35745;&#25968;&#12289;&#39318; token &#24310;&#36831;&#12289;&#37319;&#26679;&#35760;&#24405;&#31561;&#25152;&#26377;&#36816;&#34892;&#26102;&#29366;&#24577;&#21482;&#23384;&#22312;&#20110; actor &#20869;&#37096;&#12290;&#22312; </span><code>execute</code><span> &#20013;&#65292;&#19968;&#20010; </span><code>withThrowingTaskGroup</code><span> &#21516;&#26102;&#36305;&#20004;&#26465;&#36923;&#36753;&#8212;&#8212;&#23376;&#20219;&#21153;&#65288;child task&#65289;&#28040;&#36153;&#36965;&#27979;&#27969;&#65288;telemetry stream&#65289;&#65292;&#25353; 500ms &#33410;&#22863;&#37319;&#26679;&#24182;&#29983;&#25104; </span><code>RunEvent</code><span>&#65307;&#29238;&#20219;&#21153;&#65288;parent task&#65289;&#21017;&#39034;&#24207;&#25191;&#34892;&#25512;&#29702;&#24490;&#29615;&#65292;&#27599;&#27425; </span><code>await</code><span> &#37117;&#26159;&#19968;&#20010;&#25346;&#36215;&#28857;&#65288;suspension point&#65289;&#65292;&#29238;&#20219;&#21153;&#35753;&#20986;&#26102;&#23376;&#20219;&#21153;&#25165;&#26377;&#26426;&#20250;&#36816;&#34892;&#65292;&#25972;&#20010; actor &#23545;&#22806;&#21482;&#26292;&#38706;&#19968;&#20010; </span><code>AsyncThrowingStream</code><span>&#12290;&#22240;&#20026;&#25152;&#26377;&#35775;&#38382;&#37117;&#32463;&#36807; actor &#38548;&#31163;&#65292;&#20132;&#26367;&#25191;&#34892;&#27704;&#19981;&#20914;&#31361;&#8212;&#8212;&#38646;&#31454;&#20105;&#19981;&#26159;&#38752;&#33258;&#35273;&#65292;&#26159;&#32534;&#35793;&#22120;&#30452;&#25509;&#35777;&#26126;&#30340;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-03"><span>&#21033;&#29992; HistoryObserver &#26500;&#24314; SwiftData &#33258;&#23450;&#20041;&#21516;&#27493; (Syncing SwiftData with a Custom Backend Using HistoryObserver)</span></a></strong></h3><p><span>&#20960;&#24180;&#21069;&#65292;&#33529;&#26524;&#20415;&#32473; SwiftData &#25552;&#20379;&#20102; SwiftData History &#26426;&#21046;&#65292;&#35813;&#26426;&#21046;&#19982; Core Data &#30340; Persistent History Tracking &#31867;&#20284;&#65292;&#35753;&#24320;&#21457;&#32773;&#23454;&#26102;&#25484;&#25569;&#26469;&#33258;&#19981;&#21516;&#28304;&#23545;&#21516;&#19968;&#20010;&#25968;&#25454;&#24211;&#36896;&#25104;&#30340;&#25968;&#25454;&#21464;&#26356;&#20107;&#20214;&#65292;&#20294;&#30001;&#20110;&#32570;&#23569;&#19968;&#20010;&#19982; SwiftData &#35774;&#35745;&#29702;&#24565;&#36148;&#36817;&#30340;&#31616;&#21333;&#20837;&#21475;&#65292;&#35813;&#21151;&#33021;&#30340;&#21033;&#29992;&#29575;&#24182;&#19981;&#39640;&#12290;&#22312; WWDC 2026 &#19978;&#65292;&#33529;&#26524;&#20026; SwiftData &#24341;&#20837; </span><code>HistoryObserver</code><span>&#65292;&#35753;&#35302;&#21457;&#12289;&#22686;&#37327;&#35835;&#21462;&#21464;&#24471;&#38750;&#24120;&#31616;&#21333;&#12290;</span><a href="https://x.com/azamsharp"><span>Mohammad Azam</span></a><span> &#23637;&#31034;&#20102;&#35813;&#33021;&#21147;&#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#24212;&#29992;&#65292;&#36890;&#36807; </span><code>HistoryObserver</code><span> &#25645;&#20986;&#23436;&#25972;&#30340;&#33258;&#23450;&#20041;&#21333;&#21521;&#21516;&#27493;&#31649;&#32447;&#12290;</span></p><p><span>&#25991;&#31456;&#22260;&#32469;&#19968;&#20010;&#25151;&#38388;&#27979;&#37327;&#23567;&#24212;&#29992;&#23637;&#24320;&#65306;&#29992; </span><code>withContinuousObservation</code><span> &#30417;&#21548;&#21464;&#26356;&#35745;&#25968;&#35302;&#21457;&#21516;&#27493;&#65292;&#29992;&#25345;&#20037;&#21270;&#30340; </span><code>lastToken</code><span> &#20570;&#20070;&#31614;&#23454;&#29616;&#22686;&#37327;&#35835;&#21462;&#65292;&#20877;&#29992; </span><code>isDeleted</code><span> &#36719;&#21024;&#38500;&#37197;&#21512; </span><code>author</code><span> &#26631;&#31614;&#36991;&#20813;&#30828;&#21024;&#38500;&#24341;&#21457;&#30340;&#36882;&#24402;&#33258;&#35302;&#21457;&#12290;Mohammad &#23545;&#25171;&#36896;&#21516;&#27493;&#24341;&#25806;&#26102;&#20250;&#36393;&#30340;&#22353;&#65292;&#36880;&#19968;&#32473;&#20986;&#35299;&#27861;&#65292;&#24182;&#38468;&#24102;&#23436;&#25972;&#21487;&#36305;&#30340; GitHub &#31034;&#20363;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-04"><span>&#22312; Swift &#27169;&#22359;&#21253;&#20013;&#20849;&#20139;&#20844;&#24320;&#30340;&#36164;&#28304;&#31526;&#21495;&#24120;&#37327; (Public asset symbol constants in Swift packages)</span></a></strong></h3><p><span>Xcode &#20250;&#20174; </span><code>.xcassets</code><span> &#33258;&#21160;&#29983;&#25104;&#31867;&#22411;&#21270;&#30340;&#36164;&#28304;&#24120;&#37327;&#65292;&#27604;&#22914; </span><code>Color(.skyBlue)</code><span> / </span><code>Image(.logo)</code><span>&#65292;&#20294;&#36825;&#20123;&#24120;&#37327;&#26159; </span><code>internal</code><span> &#30340;&#65292;&#26080;&#27861;&#20379;&#20854;&#20182; Swift &#21253;&#20351;&#29992;&#65292;Xcode &#26082;&#19981;&#25552;&#20379; public &#36873;&#39033;&#65292;&#20063;&#26080;&#27861;&#22312; </span><code>Package.swift</code><span> &#37324;&#20851;&#38381;&#36825;&#22871;&#29983;&#25104;&#26426;&#21046;&#12290;</span></p><p><a href="https://mastodon.social/@ralfebert"><span>Ralf Ebert</span></a><span> &#25226;&#35201;&#36328;&#21253;&#20849;&#20139;&#30340;&#36164;&#28304;&#25918;&#36827; </span><code>.xcassets</code><span> &#20869;&#30340; </span><code>Public/</code><span> &#23376;&#30446;&#24405;&#65292;&#20877;&#29992;&#19968;&#20010; Ruby &#33050;&#26412;&#25195;&#25551;&#25152;&#26377; </span><code>**/*.xcassets/Public/</code><span>&#65292;&#25353;&#21253;&#21517;&#29983;&#25104;&#19968;&#20010;&#23884;&#22871; enum &#30340; </span><code>&lt;PackageName&gt;+Generated.swift</code><span>&#65292;&#25226;&#20869;&#37096;&#31526;&#21495;&#37325;&#26032;&#23548;&#20986;&#20026; </span><code>public</code><span>&#8212;&#8212;&#20174;&#32780;&#21487;&#20197;&#22312;&#20854;&#20182;&#24211;&#20013;&#36890;&#36807; </span><code>Image(.AppCommons.logo)</code><span> &#30340;&#26041;&#24335;&#26469;&#35843;&#29992;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-06"><span>&#31361;&#30772; Xcode &#39044;&#35272;&#19982; MCP &#30340;&#27801;&#30418;&#38480;&#21046; (Previews and MCP)</span></a></strong></h3><p><span>Xcode 27 &#25552;&#20379;&#30340; MCP &#25509;&#21475;&#19968;&#20849;&#26292;&#38706;&#20102; 47 &#20010;&#24037;&#20855;&#65292;&#20854;&#20013; </span><code>RenderPreview</code><span> &#36127;&#36131;&#23545; Preview &#36827;&#34892;&#28210;&#26579;&#19982;&#25130;&#22270;&#12290;&#20294;&#35843;&#29992;&#23427;&#30340;&#24212;&#29992;&#24517;&#39035;&#36890;&#36807; </span><code>xcrun mcpbridge</code><span> &#24314;&#31435; STDIO &#36830;&#25509;&#65292;&#36825;&#35201;&#27714;&#24212;&#29992;&#19981;&#33021;&#34987;&#27801;&#30418;&#21270;&#65288;sandboxed&#65289;&#8212;&#8212;&#30452;&#25509;&#19982;&#19978;&#26550; Mac App Store &#30340;&#35268;&#21017;&#20914;&#31361;&#12290;</span></p><p><a href="https://www.linkedin.com/in/amy-delves-41968418b/"><span>Amy Delves</span></a><span> &#30340;&#35299;&#27861;&#26159;&#24341;&#20837;&#19968;&#20010;&#29420;&#31435;&#30340;&#12289;&#26410;&#27801;&#30418;&#21270;&#30340; XPC &#26381;&#21153;&#19987;&#38376;&#19982; Xcode MCP &#23545;&#35805;&#65292;&#20027; App &#26412;&#36523;&#20173;&#20445;&#25345;&#27801;&#30418;&#21270;&#65292;&#20004;&#32773;&#36890;&#36807; XPC &#36890;&#20449;&#65307;&#28210;&#26579;&#32467;&#26524;&#30001; helper &#26381;&#21153;&#35835;&#21462;&#21518;&#20869;&#32852;&#20256;&#22238;&#65292;&#20174;&#32780;&#32469;&#24320;&#20027; App &#26080;&#27861;&#35775;&#38382;&#27801;&#30418;&#22806;&#25991;&#20214;&#36335;&#24452;&#30340;&#38480;&#21046;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-07"><span>&#25105;&#25214;&#21040;&#20102;&#35299;&#20915; App Store Connect &#30331;&#24405; Bug &#30340; workaround (I found a workaround for an App Store Connect bug)</span></a></strong></h3><p><span>&#19981;&#23569;&#24320;&#21457;&#32773;&#37117;&#36935;&#21040;&#36807; App Store Connect &#30340;&#19968;&#20010; Bug&#65306;&#22312;&#24050;&#30331;&#24405;&#29366;&#24577;&#19979;&#39029;&#38754;&#20173;&#20250;&#36339;&#36716;&#22238; </span><code>/login</code><span>&#12290;</span><a href="https://mastodon.social/@lapcatsoftware"><span>Jeff Johnson</span></a><span> &#22312;&#19982; Apple </span><a href="https://lapcatsoftware.com/articles/2026/7/6.html"><span>&#27807;&#36890;&#26080;&#26524;</span></a><span>&#21518;&#65292;&#29992; Chrome &#23545;&#27604;&#20004;&#27425;&#35831;&#27714;&#30340; HTTP Cookie&#65292;&#25214;&#21040;&#20102;&#38382;&#39064;&#26681;&#28304;&#65306;&#19968;&#20010;&#21517;&#20026; </span><code>dc</code><span> &#30340; session cookie&#65288;</span><code>dc=st</code><span>&#65289;&#8212;&#8212;&#39318;&#27425;&#30331;&#24405;&#26102;&#35813; cookie &#23578;&#26410;&#20889;&#20837;&#65292;&#26381;&#21153;&#31471;&#22240;&#27492;&#36820;&#22238; 302 &#36339;&#36716;&#21040;&#30331;&#24405;&#39029;&#12290;&#35299;&#20915;&#21150;&#27861;&#26159;&#25226;&#23427;&#25163;&#21160;&#25913;&#25104;&#19968;&#24180;&#21518;&#36807;&#26399;&#30340;&#27704;&#20037; cookie&#65292;&#25972;&#20010;&#35786;&#26029;&#36807;&#31243;&#19981;&#21040;&#19968;&#23567;&#26102;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-05"><span>&#22914;&#20309;&#23450;&#20041; 2026 &#24180;&#30340; App &#22270;&#26631;&#65311; (What&#8217;s an Icon in 2026?)</span></a></strong></h3><p><span>Apple &#22312; WWDC 2025 &#19978;&#25512;&#33616;&#29992; Icon Composer &#21046;&#20316;&#22270;&#26631;&#65292;&#29702;&#30001;&#26159;&#35753;&#22270;&#26631;&#20174;&#38745;&#24577;&#22270;&#20687;&#36208;&#21521;&#8220;&#26356;&#20855;&#34920;&#29616;&#21147;&#8221;&#30340;&#22810;&#23618;&#20316;&#21697;&#8212;&#8212;&#22270;&#26631;&#30001;&#27492;&#19981;&#20877;&#26377;&#21807;&#19968;&#30830;&#23450;&#30340;&#26679;&#23376;&#65292;&#21482;&#26377;&#22312;&#20855;&#20307;&#35774;&#22791;&#12289;&#20855;&#20307;&#35774;&#32622;&#19979;&#34987;&#8220;&#35266;&#27979;&#8221;&#26102;&#25165;&#20250;&#21576;&#29616;&#20986;&#26576;&#19968;&#31181;&#24418;&#24577;&#12290;&#20197; Apple &#30005;&#35805; App &#22270;&#26631;&#20026;&#20363;&#65306;&#32511;&#24213;&#30333;&#35805;&#31570;&#30340;&#32463;&#20856;&#24418;&#35937;&#65292;&#22914;&#20170;&#35201;&#20998;&#35010;&#25104;&#28145;&#33394;&#27169;&#24335;&#12289;&#29627;&#29827;&#27169;&#24335;&#12289;&#22810;&#31181;&#30528;&#33394;&#30340;&#22909;&#20960;&#20010;&#29256;&#26412;&#12290;</span></p><p><a href="https://mastodon.social/@jimniels"><span>Jim Nielsen</span></a><span> &#35748;&#20026;&#22270;&#26631;&#30340;&#20215;&#20540;&#26412;&#23601;&#24314;&#31435;&#22312;&#8220;&#31616;&#21333;&#12289;&#19968;&#33268;&#12289;&#26131;&#35760;&#8221;&#20043;&#19978;&#65292;&#36234;&#24448;&#8220;&#23500;&#26377;&#34920;&#29616;&#21147;&#8221;&#30340;&#26041;&#21521;&#22534;&#21472;&#21464;&#20307;&#65292;&#36234;&#26159;&#22312;&#31232;&#37322;&#22270;&#26631;&#26412;&#35813;&#25215;&#25285;&#30340;&#21363;&#26102;&#36776;&#35782;&#21151;&#33021;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-08"><span>ImmersiveMap&#65306;&#29992; SwiftUI &#19982; Metal &#26500;&#24314;&#21407;&#29983;&#27785;&#28024;&#24335;&#22320;&#22270;</span></a></strong></h3><p><span>ImmersiveMap &#26159; </span><a href="https://x.com/BobkinArtem"><span>Artem Bobkin</span></a><span> &#24320;&#21457;&#30340;&#19968;&#27454;&#38754;&#21521; Apple &#24179;&#21488;&#30340;&#21407;&#29983;&#22320;&#22270;&#28210;&#26579;&#24341;&#25806;&#65292;&#29992; Swift &#19982; Metal &#23454;&#29616;&#65292;&#24182;&#36890;&#36807; </span><code>ImmersiveMapView</code><span> &#25552;&#20379;&#31526;&#21512; SwiftUI &#20351;&#29992;&#20064;&#24815;&#30340;&#22768;&#26126;&#24335;&#25509;&#21475;&#12290;</span></p><p><span>&#39033;&#30446;&#26368;&#32768;&#30524;&#30340;&#33021;&#21147;&#65292;&#26159;&#29699;&#24418;&#22320;&#29699;&#19982;&#24179;&#38754;&#22320;&#22270;&#20043;&#38388;&#30340;&#36830;&#32493;&#36807;&#28193;&#12290;&#27492;&#22806;&#65292;&#23427;&#36824;&#28085;&#30422;&#30690;&#37327;&#29926;&#29255;&#65288;Vector Tile Source&#65289;&#35299;&#26512;&#12289;&#26631;&#31614;&#24067;&#23616;&#12289;3D &#24314;&#31569;&#12289;&#26143;&#31354;&#19982;&#26172;&#22812;&#25928;&#26524;&#12289;&#22320;&#22270;&#26679;&#24335;&#12289;&#30456;&#26426;&#39134;&#34892;&#21160;&#30011;&#65292;&#20197;&#21450;&#25903;&#25345;&#32858;&#21512;&#19982;&#21160;&#24577;&#31227;&#21160;&#30340;&#23454;&#26102;&#26631;&#35760;&#12290;&#24320;&#21457;&#32773;&#26082;&#21487;&#20197;&#30452;&#25509;&#20351;&#29992;&#20869;&#32622;&#29926;&#29255;&#36816;&#34892;&#65292;&#20063;&#21487;&#20197;&#25509;&#20837; Mapbox &#25110;&#33258;&#23450;&#20041;&#30340; MVT&#65288;Mapbox Vector Tile&#65289;&#25968;&#25454;&#28304;&#12290;</span></p><p><span>ImmersiveMap &#23436;&#25972;&#23637;&#31034;&#20102;&#22914;&#20309;&#25226;&#22797;&#26434;&#30340; Metal &#28210;&#26579;&#31995;&#32479;&#23553;&#35013;&#22312;&#31616;&#27905;&#30340; SwiftUI API &#20043;&#19979;&#12290;&#23545;&#20110;&#24819;&#29702;&#35299;&#22320;&#22270;&#24341;&#25806;&#12289;SwiftUI &#19982;&#24213;&#23618;&#22270;&#24418;&#28210;&#26579;&#22914;&#20309;&#21327;&#21516;&#24037;&#20316;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20221;&#39047;&#20855;&#21442;&#32771;&#20215;&#20540;&#30340;&#24320;&#28304;&#39033;&#30446;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #144]]></title><description><![CDATA[When Every Data Write Comes at a New Price]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 13 Jul 2026 12:04:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NmMs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NmMs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NmMs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154602,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/206785933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NmMs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@liam_1?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Liam Briese</a><span> on </span><a href="https://unsplash.com/photos/macro-shot-photo-of-a-computer-ram-lYxQ5F9xBDM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Every Data Write Comes at a New Price</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-144/">Read on web &#8594;</a></p><p><span>Recently, OpenAI&#8217;s Codex was found to have a logging issue: the program kept writing large volumes of logs to a local database, causing the files to grow continuously and generating far more disk writes than normal. Bugs like this are hardly new. A few years ago, most people would probably have deleted the files, restarted the app, and waited for the next release to fix it.</span></p><p><span>This time, however, the reaction was noticeably different. Instead of asking how much disk space remained, more people began wondering how much data had already been written to their SSDs, whether it might affect flash endurance, and how much more they would have to pay for the same amount of memory and storage when replacing their devices in the future.</span></p><p><span>The Codex bug may not be any more serious than other runaway logging incidents in the past. What has changed is that </span><strong><span>every pointless write suddenly seems to come at a price again.</span></strong></p><p><span>As demand for AI compute continues to surge, memory manufacturers are increasingly prioritizing higher-margin, higher-demand products such as HBM, server memory, and enterprise SSDs. Consumer memory and SSDs are therefore receiving a smaller share of production capacity, while their prices continue to rise.</span></p><p><span>Memory and flash have always been cyclical industries, so price increases and declines are nothing unusual. What makes the current situation unsettling is that it no longer appears to be merely another inventory cycle. It is accompanied by a longer-term shift of industry resources toward AI infrastructure.</span></p><p><span>Even if prices eventually fall, consumers may not quickly return to the old assumption that large amounts of storage are practically free.</span></p><p><span>As storage stops feeling inexhaustible, developers may also need to reconsider their attitude toward resources.</span></p><p><span>When I first encountered computers, a common Apple II configuration had only 48 KB of memory. To make use of the additional 16 KB provided by an expansion card, developers had to arrange addresses, code, and data with great care, finding ways to make every byte count.</span></p><p><span>A game spanning tens of gigabytes today inevitably offers graphics, sound, world scale, and interactive complexity that would have been unimaginable in the Famicom/NES era. Yet its enormous size does not guarantee that it will be more enjoyable than a game measured in only tens of kilobytes.</span></p><p><span>This is not to say that modern software should not grow larger. What is worth examining is how, over many years, developers have grown accustomed to storage capacities increasing naturally and networks becoming ever faster. As long as there is still room for logs, caches, and temporary data, few people stop to ask why they exist or when they will be deleted.</span></p><p><span>Expensive SSDs will not automatically produce better software, nor will memory shortages suddenly make developers smarter. But once hardware can no longer be assumed to grow without limit, engineering questions that have long been overlooked begin to resurface.</span></p><p><span>I do not miss the days when developers had to struggle within a few dozen kilobytes.</span></p><p><span>What is worth recovering is not the scarcity itself, but an engineering habit that once felt natural and has gradually faded away:</span></p><p><strong><span>knowing why every byte arrives&#8212;and when it will leave.</span></strong></p><p><a href="https://fatbobman.com/en/weekly/issue-143/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-01"><span>Swift Task lifetime when an iOS device is locked</span></a></strong></h3><p><span>This Q&amp;A comes from the Apple Developer Forums. The original poster found that a Swift Task making several sequential REST requests would sometimes complete normally after the device was locked, sometimes pause, and occasionally time out. DTS engineer Quinn &#8220;The Eskimo!&#8221; explains that Swift Concurrency runs entirely within the app process. Once iOS suspends that process, the worker threads executing the Task also stop, and the Task itself receives no additional background execution privileges.</span></p><p><span>This behavior can be especially confusing when networking is involved. If the app is suspended while a URLSession request is in progress, the request may fail because the connection becomes defunct. When the process resumes, developers may see a timeout or networking error rather than the Task continuing from where it paused and completing successfully. Quinn outlines four possible approaches: delay process suspension, stop in-flight requests before the app becomes eligible for suspension, allow requests to fail and implement retry and error recovery, or use a URLSession background session.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-02"><span>anyAppleOS in Swift 6.4</span></a></strong></h3><p><span>In the past, declaring availability for an API shared across Apple platforms required developers to list each platform and its corresponding OS version separately. Because version numbers differed across platforms for many years, these declarations were not only verbose but also prone to omissions and versioning mistakes. With Apple&#8217;s platforms adopting aligned major version numbers starting at 26, Swift 6.4 introduces </span><code>anyAppleOS</code><span>, allowing developers to describe APIs and code targeting Apple operating systems more concisely in </span><code>@available</code><span>, </span><code>#available</code><span>, and </span><code>#if os(...)</code><span>.</span></p><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; introduces the new syntax and explains how it differs from platform-specific availability, </span><code>canImport</code><span>, and the platform declarations in </span><code>Package.swift</code><span>. He also shows how more specific availability rules can be combined with </span><code>anyAppleOS</code><span> when support arrives later on certain platforms or is unavailable altogether.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-03"><span>The Anatomy of a Reusable SwiftUI View</span></a></strong></h3><p><span>More developers are trying to make the APIs of their reusable SwiftUI views feel as close as possible to Apple&#8217;s own designs, but there is often no clear methodology for putting that goal into practice. </span><a href="https://x.com/_al_we"><span>Alexander Wei&#223;</span></a><span>&#8288; shares his approach: first determine whether a component is semantic, describing a functional concept, or prescriptive, carrying a clearly defined visual form. From there, define its semantics, valid states, data flow, and interaction behavior. Components should also follow SwiftUI&#8217;s state-management conventions, use immutable values, Binding, and State appropriately, and treat accessibility, environment values, and stable view identity as part of the design rather than focusing only on the shape of the call site.</span></p><p><span>Using Card, Tag, and Rating as examples, the article demonstrates concrete implementations involving initializers, custom View Styles, and environment values. The central idea is not simply to imitate the appearance of Apple&#8217;s APIs, but to make custom components genuinely fit into the SwiftUI ecosystem through their composition model, state flow, interaction behavior, accessibility support, and environmental adaptation.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-04"><span>The hidden cost of unstable SwiftUI environment defaults</span></a></strong></h3><p><span>The </span><code>@Entry</code><span> macro makes custom environment values easier to declare, but directly using a reference-type instance as the default, such as </span><code>@Entry var logger = AppLogger()</code><span>, can cause unnecessary view updates. Whenever SwiftUI cannot find an injected value higher in the hierarchy and falls back to the default, it may create a new </span><code>AppLogger</code><span>. Although these objects behave identically, they are not the same instance, so SwiftUI may treat the environment value as changed and re-evaluate views that read it. Starting with Xcode 27, the compiler warns about this pattern, making a previously subtle issue easier to catch.</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>&#8288; uses </span><code>_printChanges()</code><span> to demonstrate the issue directly and offers two solutions: keep the default instance in stable external storage, or declare the environment value as Optional and inject it explicitly at the app entry point.</span></p><p><span>I also analyzed this issue in </span><a href="https://fatbobman.com/en/posts/swiftui-environment-concepts-and-practice/#repeated-instance-creation-with-the-entry-macro"><span>SwiftUI Environment: Concepts and Practice</span></a><span>&#8288;. The root cause lies in how the </span><code>@Entry</code><span> macro generates the default environment value, allowing the default expression to be evaluated repeatedly whenever fallback access occurs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-05"><span>Make Vertical Parallax for ScrollView in SwiftUI</span></a></strong></h3><p><span>Early 2D games created rich visual depth at very little cost by moving different image layers at different speeds. In SwiftUI, however, the difficult part of implementing scroll-based parallax is usually not calculating the offset, but continuously obtaining each view&#8217;s position within a </span><code>ScrollView</code><span>. In the past, this often required a combination of </span><code>GeometryReader</code><span>, custom coordinate spaces, and state propagation, resulting in more code and potentially causing unnecessary view updates when handled poorly.</span></p><p><span>The introduction of </span><code>visualEffect</code><span> has greatly reduced the complexity of building these effects. </span><a href="https://x.com/Codelaby"><span>codelaby</span></a><span>&#8288; demonstrates how to read a view&#8217;s geometry directly inside </span><code>visualEffect</code><span> and apply an </span><code>offset</code><span> based on its scroll position, without maintaining additional state or changing the view&#8217;s original layout.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-06"><span>swift-span-algorithms: Adding Algorithmic Capabilities to Span</span></a></strong></h3><p><span>When working with contiguous memory, Swift developers traditionally had two main choices. Types such as </span><code>Array</code><span> and </span><code>ContiguousArray</code><span> own their storage and are safe and convenient, but may involve copying, reference counting, or additional allocation. Pointer types such as </span><code>UnsafeBufferPointer</code><span> offer low overhead and greater control, but require developers to ensure that the underlying memory remains valid and that every access stays within bounds.</span></p><p><span>Introduced in Swift 6.2, </span><code>Span&lt;Element&gt;</code><span> fills the gap between these approaches. It is a non-owning view over contiguous memory: it does not retain the underlying storage, but relies on compiler-enforced lifetime tracking and bounds checks to provide safe access. In Swift 6.2, however, Span does not yet offer the same breadth of algorithms available to Collection and Sequence.</span></p><p><a href="https://www.linkedin.com/in/david-retegan-72b298261/"><span>David Retegan</span></a><span>&#8288; created swift-span-algorithms to fill that gap. The library adds searching, comparison, trimming, chunking, sliding windows, splitting, cursor-based operations, and other utilities for Span, RawSpan, MutableSpan, and InlineArray. It is designed around zero hidden allocations and constant additional space, extending Span&#8217;s algorithmic capabilities while continuing to respect its lifetime constraints.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403;&#27599;&#19968;&#27425;&#20889;&#20837;&#37117;&#26377;&#20102;&#26032;&#20215;&#26684;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-144/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;OpenAI &#30340; Codex &#34987;&#21457;&#29616;&#23384;&#22312;&#19968;&#20010;&#26085;&#24535;&#20889;&#20837;&#38382;&#39064;&#65306;&#31243;&#24207;&#20250;&#25345;&#32493;&#21521;&#26412;&#22320;&#25968;&#25454;&#24211;&#20889;&#20837;&#22823;&#37327;&#26085;&#24535;&#65292;&#23548;&#33268;&#25991;&#20214;&#19981;&#26029;&#33192;&#32960;&#65292;&#24182;&#20135;&#29983;&#36828;&#36229;&#27491;&#24120;&#27700;&#24179;&#30340;&#30913;&#30424;&#20889;&#20837;&#12290;&#31867;&#20284;&#30340; Bug &#36807;&#21435;&#24182;&#19981;&#23569;&#35265;&#12290;&#25918;&#22312;&#20960;&#24180;&#21069;&#65292;&#20154;&#20204;&#22823;&#27010;&#21482;&#26159;&#21024;&#38500;&#25991;&#20214;&#12289;&#37325;&#21551;&#24212;&#29992;&#65292;&#28982;&#21518;&#31561;&#24453;&#19979;&#19968;&#20010;&#29256;&#26412;&#20462;&#22797;&#12290;</span></p><p><span>&#20294;&#36825;&#19968;&#27425;&#65292;&#22823;&#23478;&#30340;&#21453;&#24212;&#26126;&#26174;&#19981;&#21516;&#12290;&#27604;&#36215;&#8220;&#36824;&#21097;&#22810;&#23569;&#30913;&#30424;&#31354;&#38388;&#8221;&#65292;&#26356;&#22810;&#20154;&#24320;&#22987;&#20851;&#24515; SSD &#24050;&#32463;&#32047;&#35745;&#20889;&#20837;&#20102;&#22810;&#23569;&#25968;&#25454;&#65292;&#20250;&#19981;&#20250;&#24433;&#21709;&#38378;&#23384;&#23551;&#21629;&#65292;&#20197;&#21450;&#26410;&#26469;&#26356;&#25442;&#35774;&#22791;&#26102;&#65292;&#38656;&#35201;&#20026;&#21516;&#26679;&#23481;&#37327;&#30340;&#20869;&#23384;&#21644;&#23384;&#20648;&#22810;&#20184;&#22810;&#23569;&#38065;&#12290;</span></p><p><span>Codex &#30340; Bug &#26410;&#24517;&#27604;&#36807;&#21435;&#37027;&#20123;&#22833;&#25511;&#30340;&#26085;&#24535;&#31243;&#24207;&#26356;&#21152;&#20005;&#37325;&#12290;&#30495;&#27491;&#21457;&#29983;&#21464;&#21270;&#30340;&#26159;&#65306;</span><strong><span>&#27599;&#19968;&#27425;&#26080;&#24847;&#20041;&#30340;&#20889;&#20837;&#65292;&#20284;&#20046;&#37117;&#37325;&#26032;&#26377;&#20102;&#20215;&#26684;&#12290;</span></strong></p><p><span>&#38543;&#30528; AI &#31639;&#21147;&#38656;&#27714;&#36805;&#36895;&#22686;&#38271;&#65292;&#23384;&#20648;&#22120;&#21378;&#21830;&#36234;&#26469;&#36234;&#20542;&#21521;&#20110;&#20248;&#20808;&#20445;&#38556; HBM&#12289;&#26381;&#21153;&#22120;&#20869;&#23384;&#21644;&#20225;&#19994;&#32423; SSD &#31561;&#21033;&#28070;&#26356;&#39640;&#12289;&#38656;&#27714;&#26356;&#26106;&#30427;&#30340;&#20135;&#21697;&#12290;&#28040;&#36153;&#32423;&#20869;&#23384;&#21644; SSD &#33021;&#22815;&#20998;&#37197;&#21040;&#30340;&#20135;&#33021;&#22240;&#27492;&#21463;&#21040;&#25380;&#21387;&#65292;&#20215;&#26684;&#20063;&#19981;&#26029;&#36208;&#39640;&#12290;</span></p><p><span>&#20869;&#23384;&#21644;&#38378;&#23384;&#26412;&#26469;&#23601;&#26159;&#20856;&#22411;&#30340;&#21608;&#26399;&#24615;&#34892;&#19994;&#65292;&#20215;&#26684;&#19978;&#28072;&#21644;&#19979;&#36300;&#24182;&#19981;&#32597;&#35265;&#12290;&#20294;&#36825;&#19968;&#36718;&#21464;&#21270;&#20196;&#20154;&#19981;&#23433;&#30340;&#22320;&#26041;&#65292;&#22312;&#20110;&#23427;&#20284;&#20046;&#19981;&#20877;&#21482;&#26159;&#19968;&#27425;&#31616;&#21333;&#30340;&#24211;&#23384;&#21608;&#26399;&#65292;&#32780;&#26159;&#20276;&#38543;&#30528;&#20135;&#19994;&#36164;&#28304;&#21521; AI &#22522;&#30784;&#35774;&#26045;&#38271;&#26399;&#20542;&#26012;&#12290;</span></p><p><span>&#21363;&#20351;&#20215;&#26684;&#26368;&#32456;&#20173;&#20250;&#22238;&#33853;&#65292;&#28040;&#36153;&#32773;&#24656;&#24597;&#20063;&#24456;&#38590;&#36805;&#36895;&#22238;&#21040;&#36807;&#21435;&#37027;&#31181;&#8220;&#22823;&#23481;&#37327;&#36817;&#20046;&#20813;&#36153;&#8221;&#30340;&#24515;&#29702;&#39044;&#26399;&#12290;</span></p><p><span>&#24403;&#23384;&#20648;&#19981;&#20877;&#26174;&#24471;&#21462;&#20043;&#19981;&#23613;&#26102;&#65292;&#24320;&#21457;&#32773;&#25110;&#35768;&#20063;&#24212;&#35813;&#36716;&#21464;&#23545;&#36164;&#28304;&#26102;&#30340;&#24577;&#24230;&#12290;</span></p><p><span>&#22312;&#25105;&#26368;&#24320;&#22987;&#25509;&#35302;&#30005;&#33041;&#26102;&#65292;Apple II &#24120;&#35265;&#30340;&#20869;&#23384;&#37197;&#32622;&#21482;&#26377; 48 KB&#12290;&#20026;&#20102;&#20351;&#29992;&#25193;&#23637;&#21345;&#39069;&#22806;&#25552;&#20379;&#30340; 16 KB &#31354;&#38388;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#20180;&#32454;&#23433;&#25490;&#22320;&#22336;&#12289;&#20195;&#30721;&#21644;&#25968;&#25454;&#65292;&#24819;&#26041;&#35774;&#27861;&#25226;&#27599;&#19968;&#20010;&#23383;&#33410;&#37117;&#21033;&#29992;&#36215;&#26469;&#12290;</span></p><p><span>&#20170;&#22825;&#19968;&#20010;&#25968;&#21313; GB &#30340;&#28216;&#25103;&#65292;&#24517;&#28982;&#25317;&#26377; FC &#26102;&#20195;&#26080;&#27861;&#24819;&#35937;&#30340;&#30011;&#38754;&#12289;&#22768;&#38899;&#12289;&#19990;&#30028;&#35268;&#27169;&#21644;&#20132;&#20114;&#22797;&#26434;&#24230;&#12290;&#28982;&#32780;&#65292;&#24040;&#22823;&#30340;&#23481;&#37327;&#24182;&#19981;&#33021;&#20445;&#35777;&#23427;&#24102;&#26469;&#30340;&#20048;&#36259;&#19968;&#23450;&#36229;&#36807;&#19968;&#20010;&#21482;&#26377;&#20960;&#21313; KB &#30340;&#28216;&#25103;&#12290;</span></p><p><span>&#36825;&#24182;&#19981;&#26159;&#35828;&#29616;&#20195;&#36719;&#20214;&#19981;&#24212;&#35813;&#21464;&#22823;&#12290;&#30495;&#27491;&#20540;&#24471;&#24605;&#32771;&#30340;&#26159;&#65292;&#22312;&#36807;&#21435;&#24456;&#22810;&#24180;&#20013;&#65292;&#24320;&#21457;&#32773;&#24050;&#32463;&#20064;&#24815;&#20102;&#23384;&#20648;&#23481;&#37327;&#20250;&#33258;&#28982;&#22686;&#38271;&#12289;&#32593;&#32476;&#20250;&#19981;&#26029;&#21464;&#24555;&#12290;&#26085;&#24535;&#12289;&#32531;&#23384;&#21644;&#20020;&#26102;&#25968;&#25454;&#21482;&#35201;&#26242;&#26102;&#36824;&#25918;&#24471;&#19979;&#65292;&#23601;&#24456;&#23569;&#26377;&#20154;&#36861;&#38382;&#23427;&#20204;&#20026;&#20160;&#20040;&#23384;&#22312;&#65292;&#21448;&#23558;&#22312;&#20160;&#20040;&#26102;&#20505;&#34987;&#21024;&#38500;&#12290;</span></p><p><span>&#26114;&#36149;&#30340; SSD &#19981;&#20250;&#33258;&#21160;&#21019;&#36896;&#20248;&#31168;&#30340;&#36719;&#20214;&#65292;&#20869;&#23384;&#30701;&#32570;&#20063;&#19981;&#20250;&#35753;&#24320;&#21457;&#32773;&#31361;&#28982;&#21464;&#24471;&#26356;&#21152;&#32874;&#26126;&#12290;&#20294;&#24403;&#30828;&#20214;&#19981;&#20877;&#34987;&#40664;&#35748;&#20250;&#26080;&#38480;&#22686;&#38271;&#26102;&#65292;&#37027;&#20123;&#26366;&#32463;&#34987;&#24573;&#35270;&#30340;&#24037;&#31243;&#38382;&#39064;&#20415;&#20250;&#37325;&#26032;&#28014;&#20986;&#27700;&#38754;&#12290;</span></p><p><span>&#25105;&#24182;&#19981;&#24576;&#24565;&#37027;&#20010;&#38656;&#35201;&#22312;&#20960;&#21313; KB &#20013;&#21453;&#22797;&#33150;&#25386;&#30340;&#26102;&#20195;&#12290;</span></p><p><span>&#30495;&#27491;&#20540;&#24471;&#37325;&#26032;&#25342;&#36215;&#30340;&#65292;&#24182;&#19981;&#26159;&#36164;&#28304;&#21294;&#20047;&#65292;&#32780;&#26159;&#37027;&#31181;&#26366;&#32463;&#21313;&#20998;&#33258;&#28982;&#12289;&#21518;&#26469;&#21364;&#36880;&#28176;&#28040;&#22833;&#30340;&#24037;&#31243;&#20064;&#24815;&#65306;</span></p><p><strong><span>&#30693;&#36947;&#27599;&#19968;&#20010;&#23383;&#33410;&#20026;&#20160;&#20040;&#21040;&#26469;&#65292;&#20063;&#30693;&#36947;&#23427;&#23558;&#22312;&#20160;&#20040;&#26102;&#20505;&#31163;&#24320;&#12290;</span></strong></p><p><a href="https://fatbobman.com/zh/weekly/issue-143/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-01"><span>iOS &#35774;&#22791;&#38145;&#23450;&#21518;&#65292;Swift Task &#33021;&#36816;&#34892;&#22810;&#20037;&#65311;(Swift Task lifetime when an iOS device is locked)</span></a></strong></h3><p><span>&#36825;&#26159;&#19968;&#31687;&#26469;&#33258; Apple Developer Forums &#30340;&#38382;&#31572;&#12290;&#25552;&#38382;&#32773;&#21457;&#29616;&#65292;&#19968;&#20010;&#20250;&#20018;&#34892;&#25191;&#34892;&#22810;&#20010; REST &#35831;&#27714;&#30340; Swift Task&#65292;&#22312;&#35774;&#22791;&#38145;&#23450;&#21518;&#26377;&#26102;&#33021;&#22815;&#27491;&#24120;&#23436;&#25104;&#65292;&#26377;&#26102;&#20250;&#26242;&#20572;&#65292;&#29978;&#33267;&#20986;&#29616;&#36229;&#26102;&#12290;DTS &#24037;&#31243;&#24072; Quinn &#8220;The Eskimo!&#8221; &#35299;&#37322;&#36947;&#65292;Swift Concurrency &#23436;&#20840;&#36816;&#34892;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#65307;&#19968;&#26086; iOS &#25346;&#36215;&#36827;&#31243;&#65292;&#25191;&#34892; Task &#30340;&#24037;&#20316;&#32447;&#31243;&#20063;&#20250;&#20572;&#27490;&#65292;Task &#26412;&#36523;&#24182;&#19981;&#20250;&#33719;&#24471;&#39069;&#22806;&#30340;&#21518;&#21488;&#36816;&#34892;&#33021;&#21147;&#12290;</span></p><p><span>&#36825;&#31181;&#26426;&#21046;&#22312;&#32593;&#32476;&#35831;&#27714;&#20013;&#23588;&#20854;&#23481;&#26131;&#36896;&#25104;&#22256;&#24785;&#12290;&#24212;&#29992;&#34987;&#25346;&#36215;&#26102;&#65292;&#27491;&#22312;&#36827;&#34892;&#30340; URLSession &#35831;&#27714;&#21487;&#33021;&#22240;&#36830;&#25509;&#22833;&#25928;&#32780;&#22833;&#36133;&#65307;&#36827;&#31243;&#24674;&#22797;&#21518;&#65292;&#24320;&#21457;&#32773;&#30475;&#21040;&#30340;&#21487;&#33021;&#26159;&#35831;&#27714;&#36229;&#26102;&#25110;&#32593;&#32476;&#38169;&#35823;&#65292;&#32780;&#19981;&#26159; Task &#20174;&#26242;&#20572;&#22788;&#32487;&#32493;&#24182;&#39034;&#21033;&#23436;&#25104;&#12290;Quinn &#32473;&#20986;&#20102;&#22235;&#31181;&#22788;&#29702;&#26041;&#21521;&#65306;&#35774;&#27861;&#24310;&#32531;&#36827;&#31243;&#25346;&#36215;&#12289;&#22312;&#24212;&#29992;&#21363;&#23558;&#34987;&#25346;&#36215;&#26102;&#20572;&#27490;&#35831;&#27714;&#12289;&#20801;&#35768;&#35831;&#27714;&#22833;&#36133;&#24182;&#20570;&#22909;&#37325;&#35797;&#19982;&#38169;&#35823;&#24674;&#22797;&#65292;&#25110;&#32773;&#20351;&#29992; URLSession &#30340;&#21518;&#21488;&#20250;&#35805;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-02"><span>Swift 6.4 &#20013;&#30340; anyAppleOS (anyAppleOS in Swift 6.4)</span></a></strong></h3><p><span>&#36807;&#21435;&#65292;&#20026;&#36328; Apple &#24179;&#21488;&#20849;&#20139;&#30340; API &#22768;&#26126;&#21487;&#29992;&#24615;&#26102;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#20998;&#21035;&#21015;&#20986;&#21508;&#20010;&#24179;&#21488;&#21450;&#20854;&#23545;&#24212;&#30340;&#31995;&#32479;&#29256;&#26412;&#12290;&#30001;&#20110;&#19981;&#21516;&#24179;&#21488;&#30340;&#29256;&#26412;&#21495;&#38271;&#26399;&#19981;&#19968;&#33268;&#65292;&#36825;&#31867;&#22768;&#26126;&#19981;&#20165;&#20887;&#38271;&#65292;&#20063;&#23481;&#26131;&#20986;&#29616;&#36951;&#28431;&#25110;&#29256;&#26412;&#22635;&#20889;&#38169;&#35823;&#12290;&#38543;&#30528; Apple &#21508;&#24179;&#21488;&#20174; 26 &#24320;&#22987;&#32479;&#19968;&#29256;&#26412;&#21495;&#65292;Swift 6.4 &#24341;&#20837;&#20102; </span><code>anyAppleOS</code><span>&#65292;&#20801;&#35768;&#24320;&#21457;&#32773;&#22312; </span><code>@available</code><span>&#12289;</span><code>#available</code><span> &#21644; </span><code>#if os(...)</code><span> &#20013;&#65292;&#20197;&#26356;&#31616;&#27905;&#30340;&#26041;&#24335;&#25551;&#36848;&#36866;&#29992;&#20110; Apple &#25805;&#20316;&#31995;&#32479;&#30340; API &#19982;&#20195;&#30721;&#12290;</span></p><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; &#20171;&#32461;&#20102;&#36825;&#19968;&#26032;&#35821;&#27861;&#65292;&#24182;&#26803;&#29702;&#20102;&#23427;&#19982;&#24179;&#21488;&#19987;&#23646;&#21487;&#29992;&#24615;&#12289;</span><code>canImport</code><span> &#20197;&#21450; </span><code>Package.swift</code><span> &#24179;&#21488;&#22768;&#26126;&#20043;&#38388;&#30340;&#21306;&#21035;&#65292;&#21516;&#26102;&#35828;&#26126;&#20102;&#22914;&#20309;&#32467;&#21512;&#26356;&#20855;&#20307;&#30340;&#21487;&#29992;&#24615;&#35268;&#21017;&#65292;&#22788;&#29702;&#37096;&#20998;&#24179;&#21488;&#24310;&#21518;&#25903;&#25345;&#25110;&#23436;&#20840;&#19981;&#21487;&#29992;&#30340;&#24773;&#20917;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-03"><span>&#21487;&#22797;&#29992; SwiftUI &#35270;&#22270;&#30340;&#35774;&#35745;&#21078;&#26512; (The Anatomy of a Reusable SwiftUI View)</span></a></strong></h3><p><span>&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#22312;&#26500;&#24314;&#21487;&#22797;&#29992; SwiftUI &#35270;&#22270;&#26102;&#65292;&#37117;&#24076;&#26395;&#20854; API &#23613;&#21487;&#33021;&#36148;&#36817; Apple &#23448;&#26041;&#30340;&#35774;&#35745;&#26041;&#24335;&#65292;&#20294;&#20855;&#20307;&#22914;&#20309;&#33853;&#22320;&#65292;&#24448;&#24448;&#32570;&#23569;&#19968;&#22871;&#28165;&#26224;&#30340;&#26041;&#27861;&#12290;</span><a href="https://x.com/_al_we"><span>Alexander Wei&#223;</span></a><span>&#8288; &#32473;&#20986;&#20102;&#33258;&#24049;&#30340;&#35774;&#35745;&#24605;&#36335;&#65306;&#39318;&#20808;&#21028;&#26029;&#32452;&#20214;&#23646;&#20110;&#25551;&#36848;&#21151;&#33021;&#27010;&#24565;&#30340;&#35821;&#20041;&#22411;&#32452;&#20214;&#65292;&#36824;&#26159;&#20855;&#26377;&#26126;&#30830;&#35270;&#35273;&#24418;&#24577;&#30340;&#35268;&#23450;&#22411;&#32452;&#20214;&#65292;&#20877;&#26803;&#29702;&#20854;&#35821;&#20041;&#12289;&#21512;&#27861;&#29366;&#24577;&#12289;&#25968;&#25454;&#27969;&#19982;&#20132;&#20114;&#34892;&#20026;&#12290;&#21516;&#26102;&#65292;&#32452;&#20214;&#36824;&#24212;&#36981;&#24490; SwiftUI &#30340;&#29366;&#24577;&#31649;&#29702;&#26041;&#24335;&#65292;&#27491;&#30830;&#20351;&#29992;&#19981;&#21487;&#21464;&#20540;&#12289;Binding &#19982; State&#65292;&#24182;&#23558;&#26080;&#38556;&#30861;&#25903;&#25345;&#12289;&#29615;&#22659;&#20540;&#21644;&#35270;&#22270;&#36523;&#20221;&#31283;&#23450;&#24615;&#32435;&#20837;&#35774;&#35745;&#65292;&#32780;&#19981;&#21482;&#26159;&#20851;&#27880; API &#30340;&#35843;&#29992;&#24418;&#24335;&#12290;</span></p><p><span>&#25991;&#31456;&#36890;&#36807; Card&#12289;Tag &#21644; Rating &#19977;&#20010;&#31034;&#20363;&#23637;&#31034;&#20102;&#21021;&#22987;&#21270;&#26041;&#27861;&#12289;&#33258;&#23450;&#20041; View Style &#21644;&#29615;&#22659;&#20540;&#31561;&#20855;&#20307;&#23454;&#29616;&#12290;&#36825;&#22871;&#26041;&#27861;&#30340;&#26680;&#24515;&#24182;&#38750;&#31616;&#21333;&#27169;&#20223; Apple API &#30340;&#22806;&#24418;&#65292;&#32780;&#26159;&#35753;&#33258;&#23450;&#20041;&#32452;&#20214;&#22312;&#32452;&#21512;&#26041;&#24335;&#12289;&#29366;&#24577;&#27969;&#36716;&#12289;&#20132;&#20114;&#34892;&#20026;&#12289;&#26080;&#38556;&#30861;&#25903;&#25345;&#21644;&#29615;&#22659;&#36866;&#37197;&#31561;&#26041;&#38754;&#30495;&#27491;&#34701;&#20837; SwiftUI &#20307;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-04"><span>SwiftUI &#29615;&#22659;&#40664;&#35748;&#20540;&#19981;&#31283;&#23450;&#30340;&#38544;&#24615;&#25104;&#26412; (The hidden cost of unstable SwiftUI environment defaults)</span></a></strong></h3><p><code>@Entry</code><span> &#23439;&#35753;&#33258;&#23450;&#20041;&#29615;&#22659;&#20540;&#30340;&#22768;&#26126;&#26356;&#21152;&#20415;&#25463;&#65292;&#20294;&#22914;&#26524;&#30452;&#25509;&#23558;&#24341;&#29992;&#31867;&#22411;&#23454;&#20363;&#20316;&#20026;&#40664;&#35748;&#20540;&#65292;&#20363;&#22914; </span><code>@Entry var logger = AppLogger()</code><span>&#65292;&#23601;&#21487;&#33021;&#24102;&#26469;&#19981;&#24517;&#35201;&#30340;&#35270;&#22270;&#26356;&#26032;&#12290;&#27599;&#24403; SwiftUI &#27809;&#26377;&#25214;&#21040;&#19978;&#23618;&#27880;&#20837;&#30340;&#20540;&#32780;&#22238;&#36864;&#21040;&#40664;&#35748;&#20540;&#26102;&#65292;&#37117;&#21487;&#33021;&#37325;&#26032;&#21019;&#24314;&#19968;&#20010; </span><code>AppLogger</code><span>&#12290;&#36825;&#20123;&#23545;&#35937;&#34429;&#28982;&#21151;&#33021;&#30456;&#21516;&#65292;&#21364;&#19981;&#26159;&#21516;&#19968;&#20010;&#23454;&#20363;&#65292;&#22240;&#27492; SwiftUI &#20250;&#35748;&#20026;&#29615;&#22659;&#20540;&#21457;&#29983;&#20102;&#21464;&#21270;&#65292;&#36827;&#32780;&#37325;&#26032;&#35745;&#31639;&#35835;&#21462;&#23427;&#30340;&#35270;&#22270;&#12290;Xcode 27 &#24320;&#22987;&#20250;&#38024;&#23545;&#36825;&#31181;&#20889;&#27861;&#21457;&#20986;&#35686;&#21578;&#65292;&#35753;&#36825;&#20010;&#36807;&#21435;&#19981;&#26131;&#23519;&#35273;&#30340;&#38382;&#39064;&#26356;&#26089;&#26292;&#38706;&#20986;&#26469;&#12290;</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>&#8288; &#20351;&#29992; </span><code>_printChanges()</code><span> &#30452;&#35266;&#23637;&#31034;&#20102;&#36825;&#19968;&#38382;&#39064;&#65292;&#24182;&#32473;&#20986;&#20004;&#31181;&#35299;&#20915;&#26041;&#24335;&#65306;&#23558;&#40664;&#35748;&#23454;&#20363;&#20445;&#23384;&#22312;&#31283;&#23450;&#30340;&#22806;&#37096;&#23384;&#20648;&#20013;&#65292;&#25110;&#32773;&#23558;&#29615;&#22659;&#20540;&#22768;&#26126;&#20026; Optional&#65292;&#20877;&#30001;&#24212;&#29992;&#20837;&#21475;&#26174;&#24335;&#27880;&#20837;&#12290;</span></p><blockquote><p><span>&#25105;&#22312;&#12298;</span><a href="https://fatbobman.com/zh/posts/swiftui-environment-concepts-and-practice/#entry-%E5%AE%8F%E7%9A%84%E5%AE%9E%E4%BE%8B%E9%87%8D%E5%A4%8D%E5%88%9B%E5%BB%BA%E9%97%AE%E9%A2%98"><span>SwiftUI Environment&#65306;&#29702;&#24565;&#19982;&#23454;&#36341;</span></a><span>&#12299;&#20013;&#20063;&#20998;&#26512;&#36807;&#36825;&#19968;&#38382;&#39064;&#12290;&#20854;&#26681;&#28304;&#22312;&#20110; </span><code>@Entry</code><span> &#23439;&#29983;&#25104;&#40664;&#35748;&#29615;&#22659;&#20540;&#30340;&#26041;&#24335;&#65292;&#20351;&#40664;&#35748;&#34920;&#36798;&#24335;&#21487;&#33021;&#22312;&#22238;&#36864;&#35775;&#38382;&#26102;&#34987;&#37325;&#22797;&#27714;&#20540;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-05"><span>&#20351;&#29992; visualEffect &#20026; SwiftUI ScrollView &#21019;&#24314;&#32437;&#21521;&#35270;&#24046;&#25928;&#26524; (Make Vertical Parallax for ScrollView in SwiftUI)</span></a></strong></h3><p><span>&#26089;&#26399;&#30340;&#20108;&#32500;&#28216;&#25103;&#36890;&#36807;&#35753;&#19981;&#21516;&#22270;&#23618;&#20197;&#19981;&#21516;&#36895;&#24230;&#31227;&#21160;&#65292;&#29992;&#24456;&#20302;&#30340;&#25104;&#26412;&#20415;&#33829;&#36896;&#20986;&#20102;&#23500;&#26377;&#23618;&#27425;&#24863;&#30340;&#35270;&#35273;&#25928;&#26524;&#12290;&#20294;&#22312; SwiftUI &#20013;&#23454;&#29616;&#28378;&#21160;&#35270;&#24046;&#65292;&#30495;&#27491;&#40635;&#28902;&#30340;&#36890;&#24120;&#19981;&#26159;&#35745;&#31639;&#20559;&#31227;&#37327;&#65292;&#32780;&#26159;&#25345;&#32493;&#33719;&#21462;&#27599;&#20010;&#35270;&#22270;&#22312; </span><code>ScrollView</code><span> &#20013;&#30340;&#20301;&#32622;&#12290;&#36807;&#21435;&#65292;&#36825;&#31867;&#25928;&#26524;&#24448;&#24448;&#38656;&#35201;&#32467;&#21512; </span><code>GeometryReader</code><span>&#12289;&#33258;&#23450;&#20041;&#22352;&#26631;&#31354;&#38388;&#21644;&#29366;&#24577;&#20256;&#36882;&#26469;&#23436;&#25104;&#65292;&#19981;&#20165;&#20195;&#30721;&#37327;&#36739;&#22823;&#65292;&#22788;&#29702;&#19981;&#24403;&#36824;&#21487;&#33021;&#24341;&#21457;&#39069;&#22806;&#30340;&#35270;&#22270;&#26356;&#26032;&#12290;</span></p><p><code>visualEffect</code><span> &#30340;&#24341;&#20837;&#22823;&#24133;&#38477;&#20302;&#20102;&#36825;&#31867;&#25928;&#26524;&#30340;&#23454;&#29616;&#38590;&#24230;&#12290;</span><a href="https://x.com/Codelaby"><span>codelaby</span></a><span>&#8288; &#23637;&#31034;&#20102;&#22914;&#20309;&#30452;&#25509;&#22312; </span><code>visualEffect</code><span> &#20013;&#35835;&#21462;&#35270;&#22270;&#30340;&#20960;&#20309;&#20449;&#24687;&#65292;&#24182;&#26681;&#25454;&#28378;&#21160;&#20301;&#32622;&#24212;&#29992; </span><code>offset</code><span>&#65292;&#26080;&#39035;&#39069;&#22806;&#32500;&#25252;&#29366;&#24577;&#65292;&#20063;&#19981;&#20250;&#25913;&#21464;&#35270;&#22270;&#21407;&#26377;&#30340;&#24067;&#23616;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-06"><span>swift-span-algorithms: &#32473; Span &#34917;&#19978;&#31639;&#27861;&#33021;&#21147;</span></a></strong></h3><p><span>&#22312;&#22788;&#29702;&#36830;&#32493;&#20869;&#23384;&#26102;&#65292;Swift &#36807;&#21435;&#20027;&#35201;&#26377;&#20004;&#31867;&#36873;&#25321;&#65306;&#20351;&#29992; </span><code>Array</code><span>&#12289;</span><code>ContiguousArray</code><span> &#31561;&#25317;&#26377;&#23384;&#20648;&#30340;&#23481;&#22120;&#65292;&#23433;&#20840;&#26131;&#29992;&#65292;&#20294;&#21487;&#33021;&#20276;&#38543;&#22797;&#21046;&#12289;&#24341;&#29992;&#35745;&#25968;&#25110;&#39069;&#22806;&#20998;&#37197;&#65307;&#20351;&#29992; </span><code>UnsafeBufferPointer</code><span> &#31561;&#25351;&#38024;&#31867;&#22411;&#65292;&#25104;&#26412;&#20302;&#12289;&#25511;&#21046;&#21147;&#24378;&#65292;&#21364;&#38656;&#35201;&#24320;&#21457;&#32773;&#33258;&#34892;&#20445;&#35777;&#20869;&#23384;&#20173;&#28982;&#26377;&#25928;&#65292;&#24182;&#36991;&#20813;&#36234;&#30028;&#35775;&#38382;&#12290;</span></p><p><span>Swift 6.2 &#26032;&#22686;&#30340; </span><code>Span&lt;Element&gt;</code><span> &#22635;&#34917;&#20102;&#20004;&#32773;&#20043;&#38388;&#30340;&#31354;&#30333;&#12290;&#23427;&#26159;&#19968;&#27573;&#36830;&#32493;&#20869;&#23384;&#30340;&#38750;&#25317;&#26377;&#35270;&#22270;&#65306;&#19981;&#25345;&#26377;&#24213;&#23618;&#23384;&#20648;&#65292;&#21364;&#33021;&#20511;&#21161;&#32534;&#35793;&#22120;&#36861;&#36394;&#29983;&#21629;&#21608;&#26399;&#65292;&#24182;&#36890;&#36807;&#36793;&#30028;&#26816;&#26597;&#25552;&#20379;&#23433;&#20840;&#35775;&#38382;&#12290;&#19981;&#36807;&#65292;&#22312; Swift 6.2 &#20013;&#65292;Span &#23578;&#26410;&#25317;&#26377; Collection&#12289;Sequence &#37027;&#33324;&#23436;&#25972;&#30340;&#31639;&#27861;&#33021;&#21147;&#12290;</span></p><p><a href="https://www.linkedin.com/in/david-retegan-72b298261/"><span>David Retegan</span></a><span> &#24320;&#21457;&#30340; swift-span-algorithms &#27491;&#26159;&#23545;&#36825;&#19968;&#32570;&#21475;&#30340;&#34917;&#20805;&#12290;&#23427;&#20026; Span&#12289;RawSpan&#12289;MutableSpan &#21644; InlineArray &#25552;&#20379;&#26597;&#25214;&#12289;&#27604;&#36739;&#12289;&#20462;&#21098;&#12289;&#20998;&#22359;&#12289;&#28369;&#21160;&#31383;&#21475;&#12289;&#20999;&#20998;&#21450;&#28216;&#26631;&#65288;Cursor&#65289;&#31561;&#25805;&#20316;&#12290;&#25972;&#20010;&#24211;&#38646;&#20197;&#26080;&#38544;&#34255;&#20998;&#37197;&#21644;&#24120;&#25968;&#32423;&#39069;&#22806;&#31354;&#38388;&#20026;&#35774;&#35745;&#30446;&#26631;&#65292;&#22312;&#25193;&#23637;&#31639;&#27861;&#33021;&#21147;&#30340;&#21516;&#26102;&#65292;&#20173;&#28982;&#36981;&#23432; Span &#30340;&#29983;&#21629;&#21608;&#26399;&#32422;&#26463;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #143]]></title><description><![CDATA[When Linux Becomes "Air": Containers, Agents, and a "Desktop War" That No Longer Matters]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 06 Jul 2026 12:03:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GmsY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GmsY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GmsY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:216564,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/205433093?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GmsY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@tri_gemini?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Sammy Xu</a><span> on </span><a href="https://unsplash.com/photos/a-tabby-cat-peeking-out-from-under-papers-63rXs30iJ9s?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Linux Becomes &#8220;Air&#8221;: Containers, Agents, and a &#8220;Desktop War&#8221; That No Longer Matters</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-143/">Read on web &#8594;</a></p><p><span>A week ago, Microsoft released the public preview of native Windows 11 container support that requires no Docker. Combined with Apple&#8217;s recent 1.0 release of its container manager (Apple Container), both major desktop operating systems have now deeply integrated Linux containers as first-class citizens of the system.</span></p><p><span>This has sparked an interesting debate. Some see it as Linux&#8217;s ultimate victory: it never truly won the desktop market, yet it is now everywhere. Others ask the opposite question: when both Windows and macOS can run Linux containers smoothly and with little overhead, is this really a victory for Linux &#8212; or the beginning of its complete &#8220;commoditization&#8221; and &#8220;invisibility&#8221;?</span></p><p><span>These two views may seem contradictory, but they both point to the same fact: the role of Linux is changing.</span></p><p><span>In the past, when we talked about an operating system, we were usually talking about a complete platform &#8212; one with its own desktop, applications, development model, user habits, and ecosystem boundaries. Windows is a platform, macOS is a platform, and Linux distributions are, of course, platforms too. Around these platforms, people debated market share, user experience, compatibility, and that &#8220;Year of the Linux Desktop&#8221; joke that has been recycled for decades.</span></p><p><span>But containers have changed the structure of the question.</span></p><p><span>In modern software development, Linux increasingly appears not as &#8220;the operating system you are using,&#8221; but as &#8220;the default runtime environment.&#8221; Developers rarely say &#8220;I deployed to Linux.&#8221; They are far more likely to say &#8220;I deployed to Kubernetes,&#8221; &#8220;I&#8217;m running on the cloud,&#8221; or &#8220;I used a container image.&#8221;</span></p><p><span>This shift will become even more pronounced in the age of AI agents. As agents evolve from simple chat assistants into tools that actually execute tasks, what they need is no longer just a conversational interface, but a lightweight, instantly bootable, fully isolated, and easily disposable execution environment. Containers are a natural fit for this role. And as more and more tasks are carried out through agents, the interface where humans interact directly with the operating system is quietly losing weight &#8212; the outcome of the decades-long &#8220;desktop war&#8221; matters less and less.</span></p><p><span>Linux, then, is outgrowing its identity as a &#8220;platform.&#8221; It never won the desktop market share battle, yet it has made its way into the foundation of nearly every modern computing system. It never convinced everyone to switch to Linux, yet it has compelled every platform to support the way Linux runs.</span></p><p><span>The highest form of victory is not having everyone chant your name, but having everyone depend on you &#8212; while barely remembering you&#8217;re there. This is a victory where silence speaks louder than words.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-142/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/debugging-notes-on-two-swiftui-animation-bugs/?utm_source=fatbobman%20weekly%20issue%20143&amp;utm_medium=web"><span>Debugging Notes on Two SwiftUI Animation Bugs</span></a></strong></h3><p><span>Easy-to-use animation has always been one of SwiftUI&#8217;s defining features. But the nature of a declarative framework is a double-edged sword: once an animation misbehaves, tracking down the cause is often trickier than in an imperative framework. This post records two SwiftUI animation bugs I ran into over the past two weeks&#8212;less a set of solutions than an account of the hunt itself, shared in the hope that the thought process proves useful the next time you face something similar.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-01"><span>Task Property: Reusing Stateful Business Logic for SwiftUI Views</span></a></strong></h3><p><span>When encapsulating stateful business logic in SwiftUI, what comes to mind first? Putting it in the view? Writing a modifier? </span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> offers a less common but distinctly SwiftUI-flavored perspective: using </span><code>DynamicProperty</code><span> to extract stateful business logic out of the view, encapsulating it as reusable dynamic properties and letting views return to a purer declarative expression.</span></p><p><span>The </span><code>TaskProperty</code><span> in the project is merely a helper primitive for managing the lifecycle of asynchronous </span><code>Task</code><span>s within custom dynamic properties. It is practical, but not what the README really wants to emphasize. Starting from the question of &#8220;how to reuse stateful business logic,&#8221; the author gradually demonstrates that </span><code>DynamicProperty</code><span> is not just the mechanism behind </span><code>@State</code><span>, </span><code>@Binding</code><span>, and </span><code>@Environment</code><span>&#8212;it can also serve as a way to organize and reuse stateful business logic.</span></p><blockquote><p><span>Articles about custom </span><code>DynamicProperty</code><span> are rare, and what distinguishes this one is that it does not stop at API instruction. Instead, it brings the question back to the organization of business logic itself: is there shareable stateful logic mixed into your Views? Could that logic be extracted into custom dynamic properties that sit closer to the SwiftUI lifecycle?</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-02"><span>Why My SwiftUI Map Bounced in Heading-Follow Mode?</span></a></strong></h3><p><a href="https://x.com/emrdgrmnci"><span>Emre Degirmenci</span></a><span> ran into a classic SwiftUI + MapKit boundary problem in a TCA-based map application: in heading-follow mode, the map kept jittering, the camera jumped, and the tracking state even exited unexpectedly. Interestingly, the same Map component worked fine in another app built with MVVM, which shifted the question from &#8220;an implementation mistake&#8221; to &#8220;whether the state synchronization model is sound.&#8221;</span></p><p><span>The root cause is that MapKit generates high-frequency camera updates in heading-follow mode, while the original implementation wrote those updates back to the TCA Store through two-way binding, creating a loop of &#8220;MapKit drives &#8594; state updates &#8594; state drives MapKit again&#8221; that broke the system&#8217;s own continuous animation logic. The fix was to leave camera changes under MapKit&#8217;s own control and intervene explicitly only when necessary, thereby avoiding conflicts between state and system-driven behavior.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-03"><span>SwiftUI 3D is Flat</span></a></strong></h3><p><span>In UIKit / AppKit, Core Animation&#8217;s </span><code>CATransformLayer</code><span> provides a genuinely shared 3D space with depth sorting, so many developers naturally assume that SwiftUI&#8217;s </span><code>rotation3DEffect</code><span> and </span><code>projectionEffect</code><span> are built on a similar 3D scene. But </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> shows through an experiment that SwiftUI has no unified 3D space or depth-buffering mechanism. After 3D transformations, multiple views remain &#8220;independent 2D projections,&#8221; which leads to typical occlusion errors&#8212;for example, a back face covering a front face.</span></p><p><span>This behavior is not a defect; it looks more like a deliberate design choice in SwiftUI: constraining 3D capabilities to the projection level of individual views rather than introducing a full 3D scene and hierarchy system.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-04"><span>Introducing the Safari MCP server for web developers</span></a></strong></h3><p><span>In today&#8217;s AI coding agent ecosystem, browser automation has long been dominated by the Chrome / Chromium stack as the de facto standard (Playwright, Puppeteer, CDP, etc.), with Safari mostly serving as a compatibility-verification environment.</span></p><p><span>The Safari MCP server (Safari Technology Preview 247) aims to change that: it exposes Safari&#8217;s browser session capabilities to agents, giving them direct access to the DOM, network requests, console logs, screenshots, and page state, so that debugging and analysis can happen in Safari&#8217;s real runtime environment. This moves Safari into the main path of the agent toolchain, rather than relying on indirect inference from Chromium or cross-browser switching for verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-05"><span>noUI()</span></a></strong></h3><p><span>As AI agent tools work their way deeper into development and content-production workflows, the role of UI is being reexamined. Starting from a DOS-style command interface, </span><a href="https://x.com/jordanmorgan10"><span>Jordan Morgan</span></a><span> poses a question worth pondering: when more and more operations can be performed directly by agents through natural language, does UI still need to exist in the form of an &#8220;explicit interface&#8221;?</span></p><blockquote><p><span>The part of the article that fascinated me most is the interactive terminal interface the author built with JavaScript and CSS. This design is not merely an example or a demo&#8212;it embeds the article&#8217;s argument itself into an operable UI, drawing readers into the discussion of UI&#8217;s changing form precisely through the act of &#8220;using an interface.&#8221; Here, UI is not just a vehicle of expression; it becomes part of the argument.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-06"><span>What does Activity Monitor measure?</span></a></strong></h3><p><span>Since AI agents entered everyday development workflows, many developers have had a similar experience: the Mac&#8217;s fans spin up more often and memory pressure rises noticeably, yet the CPU / Energy figures shown in Activity Monitor often fail to match that intuition.</span></p><p><span>Through controlled experiments with </span><code>powermetrics</code><span> and a variety of real workloads, </span><a href="https://x.com/howardnoakley"><span>Howard Oakley</span></a><span> shows that the CPU % in Activity Monitor is closer to a simple sum of each CPU core&#8217;s active residency than to a &#8220;utilization percentage&#8221; in the traditional sense; GPU % is likewise only an approximation of active residency; and Energy Impact mainly reflects a CPU-level power estimate&#8212;it neither includes the GPU nor captures how energy consumption changes over time particularly well.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-07"><span>Quiver: Learning Linear Algebra and Classical Machine Learning with Swift</span></a></strong></h3><p><a href="https://www.linkedin.com/in/waynebishop/"><span>Wayne Bishop</span></a><span> has long maintained </span><a href="https://waynewbishop.github.io/swift-algorithms/"><span>Swift Algorithms &amp; Data Structures</span></a><span>, an e-book on algorithms and data structures for Swift developers. In its latest fifth edition, the book has extended beyond traditional algorithms and data structures into vectors, matrices, and similarity computation; Quiver pushes that path further into numerical computing, statistics, and classical machine learning.</span></p><p><span>Quiver is a pure Swift, zero-dependency library for linear algebra, statistics, and classical machine learning. It directly extends the Swift standard library&#8217;s </span><code>Array</code><span>, emphasizing value semantics, </span><code>Codable</code><span>, </span><code>Sendable</code><span>, and lightweight on-device execution on Apple platforms. Its goal is not to replace the Python numerical ecosystem, but to give Swift developers an entry point for understanding linear algebra, training small models, and bringing the results back into an App&#8212;all in a familiar language. In the later chapters of Swift Algorithms &amp; Data Structures, Wayne uses Quiver as the companion tool for the math and machine-learning fundamentals.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-08"><span>SwipeCell v3: A Native SwiftUI Swipe Menu</span></a></strong></h3><p><span>At WWDC 2026, SwiftUI&#8217;s new </span><code>swipeActionsContainer()</code><span> finally let swipe menus step outside of </span><code>List</code><span>, serving </span><code>ScrollView</code><span>, lazy stacks, and more custom containers. Unfortunately, this capability currently requires system versions corresponding to </span><code>anyAppleOS 27</code><span>.</span></p><p><span>SwipeCell was the first third-party library I wrote six years ago, when I had just entered Swift development. The old versions were naive, but they also accompanied me through the changes in SwiftUI&#8217;s swipe interactions over the years. I recently gave it a complete rewrite and released v3: the new API is more SwiftUI-idiomatic, the configuration is more complete, the interaction feel has been re-polished, and macOS support has been added.</span></p><p><span>SwipeCell v3 is currently published on the </span><code>v3-beta</code><span> branch and remains in beta. You are welcome to try it out and report any issues you encounter.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403; Linux &#25104;&#20026;&#8220;&#31354;&#27668;&#8221;&#65306;&#23481;&#22120;&#12289;Agent &#19982;&#19981;&#20877;&#37325;&#35201;&#30340;&#8220;&#26700;&#38754;&#20043;&#20105;&#8221;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-143/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19968;&#21608;&#21069;&#65292;&#24494;&#36719;&#25512;&#20986;&#20102;&#26080;&#38656; Docker &#30340; Windows 11 &#21407;&#29983;&#23481;&#22120;&#25903;&#25345;&#30340;&#20844;&#24320;&#39044;&#35272;&#65307;&#20877;&#32467;&#21512;&#33529;&#26524;&#19981;&#20037;&#21069;&#21457;&#24067;&#30340;&#23481;&#22120;&#31649;&#29702;&#22120;&#65288;container&#65289;1.0 &#27491;&#24335;&#29256;&#65292;&#19968;&#26102;&#38388;&#65292;&#20004;&#22823;&#20027;&#27969;&#26700;&#38754;&#25805;&#20316;&#31995;&#32479;&#37117;&#23558; Linux &#23481;&#22120;&#28145;&#24230;&#38598;&#25104;&#20026;&#20102;&#31995;&#32479;&#30340;&#19968;&#31561;&#20844;&#27665;&#12290;</span></p><p><span>&#36825;&#20214;&#20107;&#24341;&#21457;&#20102;&#19968;&#22330;&#26377;&#36259;&#30340;&#35752;&#35770;&#12290;&#26377;&#20154;&#35748;&#20026;&#65292;&#36825;&#26159; Linux &#30340;&#26368;&#32456;&#32988;&#21033;&#65306;&#34429;&#28982;&#23427;&#22987;&#32456;&#27809;&#33021;&#30495;&#27491;&#36194;&#19979;&#26700;&#38754;&#24066;&#22330;&#65292;&#20294;&#23427;&#24050;&#32463;&#26080;&#22788;&#19981;&#22312;&#65307;&#20063;&#26377;&#20154;&#25552;&#20986;&#21453;&#38382;&#65306;&#24403; Windows &#21644; macOS &#37117;&#33021;&#30456;&#23545;&#39034;&#30021;&#12289;&#36731;&#37327;&#22320;&#36816;&#34892; Linux &#23481;&#22120;&#26102;&#65292;&#36825;&#31350;&#31455;&#26159; Linux &#30340;&#32988;&#21033;&#65292;&#36824;&#26159;&#23427;&#34987;&#24443;&#24213;&#8220;&#24037;&#20855;&#21270;&#8221;&#21644;&#8220;&#38544;&#24418;&#21270;&#8221;&#30340;&#24320;&#22987;&#65311;</span></p><p><span>&#36825;&#20004;&#31181;&#35828;&#27861;&#30475;&#20284;&#30456;&#21453;&#65292;&#20854;&#23454;&#37117;&#35302;&#30896;&#21040;&#20102;&#21516;&#19968;&#20010;&#20107;&#23454;&#65306;Linux &#30340;&#35282;&#33394;&#27491;&#22312;&#21457;&#29983;&#21464;&#21270;&#12290;</span></p><p><span>&#36807;&#21435;&#65292;&#25105;&#20204;&#35848;&#35770;&#25805;&#20316;&#31995;&#32479;&#26102;&#65292;&#36890;&#24120;&#26159;&#22312;&#35848;&#35770;&#19968;&#20010;&#23436;&#25972;&#30340;&#24179;&#21488;&#12290;&#23427;&#26377;&#33258;&#24049;&#30340;&#26700;&#38754;&#12289;&#24212;&#29992;&#12289;&#24320;&#21457;&#27169;&#22411;&#12289;&#29992;&#25143;&#20064;&#24815;&#21644;&#29983;&#24577;&#36793;&#30028;&#12290;Windows &#26159;&#19968;&#20010;&#24179;&#21488;&#65292;macOS &#26159;&#19968;&#20010;&#24179;&#21488;&#65292;Linux &#21457;&#34892;&#29256;&#24403;&#28982;&#20063;&#26159;&#19968;&#20010;&#24179;&#21488;&#12290;&#22260;&#32469;&#36825;&#20123;&#24179;&#21488;&#65292;&#20154;&#20204;&#35752;&#35770;&#20221;&#39069;&#12289;&#20307;&#39564;&#12289;&#20860;&#23481;&#24615;&#65292;&#20197;&#21450;&#37027;&#20010;&#24050;&#32463;&#34987;&#21453;&#22797;&#35843;&#20355;&#20102;&#20960;&#21313;&#24180;&#30340;&#8220;Linux &#26700;&#38754;&#20803;&#24180;&#8221;&#12290;</span></p><p><span>&#20294;&#23481;&#22120;&#25913;&#21464;&#20102;&#36825;&#20010;&#38382;&#39064;&#30340;&#32467;&#26500;&#12290;</span></p><p><span>&#22312;&#29616;&#20195;&#36719;&#20214;&#24320;&#21457;&#20013;&#65292;Linux &#36234;&#26469;&#36234;&#23569;&#20197;&#8220;&#20320;&#27491;&#22312;&#20351;&#29992;&#30340;&#25805;&#20316;&#31995;&#32479;&#8221;&#30340;&#24418;&#24335;&#20986;&#29616;&#65292;&#32780;&#26159;&#20197;&#8220;&#40664;&#35748;&#36816;&#34892;&#29615;&#22659;&#8221;&#30340;&#24418;&#24335;&#23384;&#22312;&#12290;&#24320;&#21457;&#32773;&#19981;&#19968;&#23450;&#20250;&#35828;&#8220;&#25105;&#37096;&#32626;&#21040;&#20102; Linux&#8221;&#65292;&#20182;&#20204;&#26356;&#21487;&#33021;&#35828;&#8220;&#25105;&#37096;&#32626;&#21040;&#20102; Kubernetes&#8221;&#12289;&#8220;&#25105;&#36305;&#22312;&#20113;&#19978;&#8221;&#12289;&#8220;&#25105;&#29992;&#20102;&#19968;&#20010;&#23481;&#22120;&#38236;&#20687;&#8221;&#12290;</span></p><p><span>&#36825;&#31181;&#21464;&#21270;&#22312; AI Agent &#26102;&#20195;&#20250;&#26356;&#21152;&#26126;&#26174;&#12290;&#38543;&#30528; Agent &#20174;&#31616;&#21333;&#30340;&#32842;&#22825;&#21161;&#25163;&#36716;&#21521;&#33021;&#22815;&#30495;&#27491;&#25191;&#34892;&#20219;&#21153;&#30340;&#24037;&#20855;&#65292;&#23427;&#20204;&#38656;&#35201;&#30340;&#19981;&#20877;&#21482;&#26159;&#19968;&#20010;&#23545;&#35805;&#30028;&#38754;&#65292;&#32780;&#26159;&#19968;&#20010;&#36731;&#37327;&#12289;&#31186;&#32423;&#21551;&#21160;&#12289;&#23436;&#20840;&#38548;&#31163;&#19988;&#26131;&#20110;&#38144;&#27585;&#30340;&#25191;&#34892;&#29615;&#22659;&#12290;&#23481;&#22120;&#22825;&#28982;&#36866;&#21512;&#25215;&#25285;&#36825;&#31181;&#35282;&#33394;&#12290;&#32780;&#24403;&#36234;&#26469;&#36234;&#22810;&#30340;&#20219;&#21153;&#32463;&#30001; Agent &#23436;&#25104;&#65292;&#20154;&#19982;&#25805;&#20316;&#31995;&#32479;&#30452;&#25509;&#20132;&#20114;&#30340;&#30028;&#38754;&#65292;&#20854;&#26435;&#37325;&#20063;&#22312;&#24708;&#28982;&#19979;&#38477;&#8212;&#8212;&#37027;&#22330;&#25345;&#32493;&#20102;&#25968;&#21313;&#24180;&#30340;&#8220;&#26700;&#38754;&#20043;&#20105;&#8221;&#65292;&#32988;&#36127;&#24050;&#32463;&#24840;&#21457;&#19981;&#37325;&#35201;&#20102;&#12290;</span></p><p><span>&#25152;&#20197;&#65292;Linux &#27491;&#22312;&#36229;&#36234;&#8220;&#24179;&#21488;&#8221;&#36825;&#20010;&#36523;&#20221;&#12290;&#23427;&#27809;&#26377;&#25104;&#20026;&#26700;&#38754;&#25805;&#20316;&#31995;&#32479;&#20221;&#39069;&#30340;&#36194;&#23478;&#65292;&#21364;&#36827;&#20837;&#20102;&#20960;&#20046;&#25152;&#26377;&#29616;&#20195;&#35745;&#31639;&#20307;&#31995;&#30340;&#24213;&#23618;&#12290;&#23427;&#27809;&#26377;&#35753;&#25152;&#26377;&#20154;&#37117;&#25913;&#29992; Linux&#65292;&#21364;&#35753;&#25152;&#26377;&#24179;&#21488;&#37117;&#19981;&#24471;&#19981;&#25903;&#25345; Linux &#30340;&#36816;&#34892;&#26041;&#24335;&#12290;</span></p><p><span>&#19981;&#26159;&#35753;&#25152;&#26377;&#20154;&#37117;&#39640;&#21898;&#20320;&#30340;&#21517;&#23383;&#65292;&#32780;&#26159;&#35753;&#25152;&#26377;&#20154;&#37117;&#31163;&#19981;&#24320;&#20320;&#65292;&#21364;&#21448;&#24819;&#19981;&#36215;&#20320;&#12290;&#36825;&#31181;&#32988;&#21033;&#26080;&#22768;&#32988;&#26377;&#22768;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-142/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/debugging-notes-on-two-swiftui-animation-bugs/?utm_source=fatbobman%20weekly%20issue%20143&amp;utm_medium=web"><span>&#20004;&#20010; SwiftUI &#21160;&#30011; Bug &#25490;&#26597;&#23567;&#35760;</span></a></strong></h3><p><span>&#26131;&#29992;&#30340;&#21160;&#30011;&#19968;&#30452;&#26159; SwiftUI &#30340;&#20027;&#35201;&#29305;&#33394;&#20043;&#19968;&#12290;&#20294;&#22768;&#26126;&#24335;&#26694;&#26550;&#30340;&#29305;&#24615;&#26159;&#19968;&#25226;&#21452;&#20995;&#21073;&#65306;&#21160;&#30011;&#19968;&#26086;&#20986;&#29616;&#24322;&#24120;&#65292;&#25490;&#26597;&#24448;&#24448;&#27604;&#21629;&#20196;&#24335;&#26694;&#26550;&#26356;&#26840;&#25163;&#12290;&#26412;&#25991;&#35760;&#24405;&#20102;&#36807;&#21435;&#20004;&#21608;&#37324;&#65292;&#25105;&#22312;&#24320;&#21457;&#20013;&#36935;&#21040;&#30340;&#20004;&#20010;&#19982; SwiftUI &#21160;&#30011;&#26377;&#20851;&#30340; Bug&#12290;&#19982;&#20854;&#35828;&#26159;&#35299;&#20915;&#26041;&#26696;&#65292;&#19981;&#22914;&#35828;&#26159;&#19968;&#27573;&#25490;&#26597;&#30340;&#24515;&#36335;&#8212;&#8212;&#24076;&#26395;&#33021;&#20026;&#20320;&#38754;&#23545;&#31867;&#20284;&#38382;&#39064;&#26102;&#24320;&#38420;&#19968;&#28857;&#24605;&#36335;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-01"><span>&#21033;&#29992;&#23646;&#24615;&#26426;&#21046;&#37325;&#26500;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753; (Task Property: Reusing Stateful Business Logic for SwiftUI Views)</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#23553;&#35013;&#24102;&#29366;&#24577;&#30340;&#19994;&#21153;&#36923;&#36753;&#65292;&#20320;&#31532;&#19968;&#26102;&#38388;&#20250;&#24819;&#21040;&#20160;&#20040;&#26041;&#24335;&#65311;&#25918;&#36827;&#35270;&#22270;&#65311;&#20889;&#25104; modifier&#65311;</span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> &#25552;&#20379;&#20102;&#19968;&#20010;&#19981;&#22826;&#24120;&#35265;&#20294;&#24456;&#26377; SwiftUI &#21619;&#36947;&#30340;&#35270;&#35282;&#65306;&#21033;&#29992; </span><code>DynamicProperty</code><span> &#23558;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753;&#20174; View &#20013;&#25277;&#31163;&#20986;&#26469;&#65292;&#23553;&#35013;&#20026;&#21487;&#22797;&#29992;&#30340;&#21160;&#24577;&#23646;&#24615;&#65292;&#35753; View &#22238;&#24402;&#26356;&#32431;&#31929;&#30340;&#22768;&#26126;&#24335;&#34920;&#36798;&#12290;</span></p><p><span>&#39033;&#30446;&#20013;&#30340; </span><code>TaskProperty</code><span> &#21482;&#26159;&#19968;&#20010;&#36741;&#21161;&#21407;&#35821;&#65292;&#29992;&#20110;&#22312;&#33258;&#23450;&#20041;&#21160;&#24577;&#23646;&#24615;&#20013;&#31649;&#29702;&#24322;&#27493; </span><code>Task</code><span> &#30340;&#29983;&#21629;&#21608;&#26399;&#12290;&#23427;&#24456;&#23454;&#29992;&#65292;&#20294;&#24182;&#19981;&#26159;&#36825;&#31687; README &#30495;&#27491;&#24819;&#24378;&#35843;&#30340;&#37325;&#28857;&#12290;&#20316;&#32773;&#20174;&#8220;&#22914;&#20309;&#22797;&#29992; Stateful Business Logic&#8221;&#36825;&#20010;&#38382;&#39064;&#20986;&#21457;&#65292;&#36880;&#27493;&#23637;&#31034;&#20102; </span><code>DynamicProperty</code><span> &#19981;&#21482;&#26159; </span><code>@State</code><span>&#12289;</span><code>@Binding</code><span>&#12289;</span><code>@Environment</code><span> &#32972;&#21518;&#30340;&#26426;&#21046;&#65292;&#20063;&#21487;&#20197;&#25104;&#20026;&#32452;&#32455;&#21644;&#22797;&#29992;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753;&#30340;&#19968;&#31181;&#26041;&#24335;&#12290;</span></p><blockquote><p><span>&#20851;&#20110;&#33258;&#23450;&#20041; </span><code>DynamicProperty</code><span> &#30340;&#25991;&#31456;&#24182;&#19981;&#22810;&#65292;&#32780;&#26412;&#25991;&#30340;&#29305;&#28857;&#22312;&#20110;&#65292;&#23427;&#27809;&#26377;&#20572;&#30041;&#22312; API &#20351;&#29992;&#25945;&#23398;&#19978;&#65292;&#32780;&#26159;&#25226;&#38382;&#39064;&#25918;&#22238;&#19994;&#21153;&#36923;&#36753;&#32452;&#32455;&#26412;&#36523;&#65306;&#20320;&#30340; View &#20013;&#26159;&#21542;&#28151;&#20837;&#20102;&#21487;&#20849;&#20139;&#30340;&#29366;&#24577;&#36923;&#36753;&#65311;&#36825;&#20123;&#36923;&#36753;&#26159;&#21542;&#21487;&#20197;&#34987;&#25277;&#21462;&#20026;&#26356;&#36148;&#36817; SwiftUI &#29983;&#21629;&#21608;&#26399;&#30340;&#33258;&#23450;&#20041;&#21160;&#24577;&#23646;&#24615;&#65311;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-02"><span>SwiftUI &#22320;&#22270;&#22312;&#33322;&#21521;&#36319;&#38543;&#27169;&#24335;&#19979;&#20026;&#20309;&#20250;&#25238;&#21160;&#65311;(Why My SwiftUI Map Bounced in Heading-Follow Mode?)</span></a></strong></h3><p><a href="https://x.com/emrdgrmnci"><span>Emre Degirmenci</span></a><span> &#22312;&#19968;&#20010;&#22522;&#20110; TCA &#30340;&#22320;&#22270;&#24212;&#29992;&#20013;&#36935;&#21040;&#20102;&#19968;&#20010;&#20856;&#22411;&#30340; SwiftUI + MapKit &#36793;&#30028;&#38382;&#39064;&#65306;&#22312; heading-follow &#27169;&#24335;&#19979;&#65292;&#22320;&#22270;&#20986;&#29616;&#25345;&#32493;&#25238;&#21160;&#12289;&#30456;&#26426;&#36339;&#21160;&#65292;&#29978;&#33267;&#23450;&#20301;&#29366;&#24577;&#24322;&#24120;&#36864;&#20986;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#21516;&#26679;&#30340; Map &#32452;&#20214;&#22312;&#21478;&#19968;&#20010; MVVM &#26550;&#26500;&#30340;&#24212;&#29992;&#20013;&#21364;&#27809;&#26377;&#38382;&#39064;&#65292;&#36825;&#20351;&#24471;&#38382;&#39064;&#20174;&#8220;&#23454;&#29616;&#38169;&#35823;&#8221;&#36716;&#21521;&#20102;&#8220;&#29366;&#24577;&#21516;&#27493;&#27169;&#22411;&#26159;&#21542;&#21512;&#29702;&#8221;&#12290;</span></p><p><span>&#26680;&#24515;&#21407;&#22240;&#22312;&#20110; MapKit &#22312; heading-follow &#27169;&#24335;&#19979;&#20250;&#20135;&#29983;&#39640;&#39057;&#30456;&#26426;&#26356;&#26032;&#65292;&#32780;&#21407;&#23454;&#29616;&#36890;&#36807;&#21452;&#21521;&#32465;&#23450;&#23558;&#26356;&#26032;&#25968;&#25454;&#22238;&#20889;&#21040; TCA Store&#65292;&#36896;&#25104;&#20102;&#8220;MapKit &#39537;&#21160; &#8594; &#29366;&#24577;&#26356;&#26032; &#8594; &#20877;&#39537;&#21160; MapKit&#8221;&#30340;&#22238;&#36335;&#65292;&#30772;&#22351;&#20102;&#31995;&#32479;&#33258;&#36523;&#30340;&#36830;&#32493;&#21160;&#30011;&#36923;&#36753;&#12290;&#20462;&#22797;&#26041;&#24335;&#20026;&#35753;&#30456;&#26426;&#21464;&#21270;&#20445;&#25345;&#30001; MapKit &#33258;&#36523;&#25511;&#21046;&#65292;&#21482;&#22312;&#38656;&#35201;&#26102;&#36827;&#34892;&#26174;&#24335;&#24178;&#39044;&#65292;&#20174;&#32780;&#36991;&#20813;&#29366;&#24577;&#19982;&#31995;&#32479;&#39537;&#21160;&#20043;&#38388;&#30340;&#20914;&#31361;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-03"><span>SwiftUI 3D is Flat</span></a></strong></h3><p><span>&#22312; UIKit / AppKit &#20013;&#65292;Core Animation &#30340; </span><code>CATransformLayer</code><span> &#25552;&#20379;&#20102;&#30495;&#27491;&#30340;&#20849;&#20139; 3D &#31354;&#38388;&#19982;&#28145;&#24230;&#25490;&#24207;&#33021;&#21147;&#65292;&#22240;&#27492;&#19981;&#23569;&#24320;&#21457;&#32773;&#20250;&#33258;&#28982;&#22320;&#35748;&#20026; SwiftUI &#30340; </span><code>rotation3DEffect</code><span>&#12289;</span><code>projectionEffect</code><span> &#20063;&#24314;&#31435;&#22312;&#31867;&#20284;&#30340; 3D &#22330;&#26223;&#20043;&#19978;&#12290;&#20294; </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#36890;&#36807;&#19968;&#20010;&#23454;&#39564;&#25351;&#20986;&#65306;SwiftUI &#24182;&#19981;&#23384;&#22312;&#32479;&#19968;&#30340; 3D &#31354;&#38388;&#25110;&#28145;&#24230;&#32531;&#20914;&#26426;&#21046;&#12290;&#22810;&#20010;&#35270;&#22270;&#22312; 3D &#21464;&#25442;&#21518;&#30340;&#32467;&#26524;&#20173;&#28982;&#26159;&#8220;&#21508;&#33258;&#29420;&#31435;&#30340; 2D &#25237;&#24433;&#8221;&#65292;&#22240;&#27492;&#20250;&#20986;&#29616;&#20856;&#22411;&#30340;&#36974;&#25377;&#38169;&#35823;&#65292;&#20363;&#22914;&#8220;&#32972;&#38754;&#35206;&#30422;&#27491;&#38754;&#8221;&#12290;</span></p><p><span>&#36825;&#31181;&#34892;&#20026;&#24182;&#38750;&#32570;&#38519;&#65292;&#32780;&#26356;&#20687;&#26159; SwiftUI &#26377;&#24847;&#30340;&#35774;&#35745;&#36873;&#25321;&#65306;&#23558; 3D &#33021;&#21147;&#38480;&#21046;&#22312;&#21333;&#20010; view &#30340;&#25237;&#24433;&#23618;&#38754;&#65292;&#32780;&#19981;&#26159;&#24341;&#20837;&#23436;&#25972;&#30340; 3D &#22330;&#26223;&#19982;&#23618;&#32423;&#20307;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-04"><span>Safari &#25512;&#20986;&#38754;&#21521; Web &#24320;&#21457;&#32773;&#30340; MCP (Introducing the Safari MCP server for web developers)</span></a></strong></h3><p><span>&#22312;&#24403;&#21069; AI coding agent &#29983;&#24577;&#20013;&#65292;&#27983;&#35272;&#22120;&#33258;&#21160;&#21270;&#38271;&#26399;&#20197; Chrome / Chromium &#20307;&#31995;&#20026;&#20107;&#23454;&#26631;&#20934;&#65288;Playwright&#12289;Puppeteer&#12289;CDP &#31561;&#65289;&#65292;Safari &#36890;&#24120;&#26356;&#22810;&#20316;&#20026;&#20860;&#23481;&#24615;&#39564;&#35777;&#29615;&#22659;&#12290;</span></p><p><span>Safari MCP server&#65288;Safari Technology Preview 247&#65289;&#35797;&#22270;&#25913;&#21464;&#36825;&#19968;&#28857;&#65306;&#23427;&#23558; Safari &#27983;&#35272;&#22120;&#20250;&#35805;&#33021;&#21147;&#26292;&#38706;&#32473; agent&#65292;&#20351;&#20854;&#21487;&#20197;&#30452;&#25509;&#35775;&#38382; DOM&#12289;&#32593;&#32476;&#35831;&#27714;&#12289;&#25511;&#21046;&#21488;&#26085;&#24535;&#12289;&#25130;&#22270;&#20197;&#21450;&#39029;&#38754;&#29366;&#24577;&#65292;&#20174;&#32780;&#22312; Safari &#30340;&#30495;&#23454;&#36816;&#34892;&#29615;&#22659;&#20013;&#23436;&#25104;&#35843;&#35797;&#19982;&#20998;&#26512;&#12290;&#36825;&#20351; Safari &#24320;&#22987;&#36827;&#20837; agent toolchain &#30340;&#20027;&#36335;&#24452;&#65292;&#32780;&#19981;&#20877;&#21482;&#26159;&#20381;&#36182; Chromium &#30340;&#38388;&#25509;&#25512;&#26029;&#25110;&#36328;&#27983;&#35272;&#22120;&#20999;&#25442;&#39564;&#35777;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-05"><span>AI &#26102;&#20195;&#19979;&#30340;&#8220;&#26080; UI&#8221;&#36235;&#21183;&#24605;&#32771; noUI()</span></a></strong></h3><p><span>&#22312;&#24403;&#21069; AI agent &#24037;&#20855;&#36880;&#28176;&#28145;&#20837;&#24320;&#21457;&#19982;&#20869;&#23481;&#29983;&#20135;&#27969;&#31243;&#30340;&#32972;&#26223;&#19979;&#65292;UI &#30340;&#35282;&#33394;&#27491;&#22312;&#34987;&#37325;&#26032;&#23457;&#35270;&#12290;</span><a href="https://x.com/jordanmorgan10"><span>Jordan Morgan</span></a><span>&#8288; &#20174; DOS &#39118;&#26684;&#30340;&#21629;&#20196;&#30028;&#38754;&#20999;&#20837;&#65292;&#25552;&#20986;&#19968;&#20010;&#20540;&#24471;&#24605;&#32771;&#30340;&#38382;&#39064;&#65306;&#24403;&#36234;&#26469;&#36234;&#22810;&#30340;&#25805;&#20316;&#21487;&#20197;&#30452;&#25509;&#30001; agent &#36890;&#36807;&#33258;&#28982;&#35821;&#35328;&#23436;&#25104;&#26102;&#65292;UI &#26159;&#21542;&#20173;&#28982;&#38656;&#35201;&#20197;&#8220;&#26174;&#24335;&#30028;&#38754;&#8221;&#30340;&#24418;&#24335;&#23384;&#22312;&#65311;</span></p><blockquote><p><span>&#25991;&#31456;&#20013;&#26368;&#21560;&#24341;&#25105;&#30340;&#37096;&#20998;&#65292;&#26159;&#20316;&#32773;&#22522;&#20110; JavaScript &#19982; CSS &#26500;&#24314;&#20102;&#19968;&#20010;&#21487;&#20132;&#20114;&#30340;&#32456;&#31471;&#30028;&#38754;&#12290;&#36825;&#20010;&#35774;&#35745;&#24182;&#19981;&#20165;&#20165;&#29992;&#20110;&#31034;&#20363;&#25110;&#28436;&#31034;&#65292;&#32780;&#26159;&#23558;&#25991;&#31456;&#30340;&#35770;&#36848;&#26412;&#36523;&#23884;&#20837;&#21040;&#19968;&#20010;&#21487;&#25805;&#20316;&#30340; UI &#20013;&#65292;&#20351;&#35835;&#32773;&#22312;&#8220;&#20351;&#29992;&#30028;&#38754;&#8221;&#30340;&#36807;&#31243;&#20013;&#36827;&#20837;&#23545; UI &#24418;&#24577;&#21464;&#21270;&#30340;&#35752;&#35770;&#20043;&#20013;&#12290;UI &#22312;&#36825;&#37324;&#19981;&#21482;&#26159;&#34920;&#36798;&#36733;&#20307;&#65292;&#20063;&#25104;&#20026;&#35770;&#35777;&#30340;&#19968;&#37096;&#20998;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-06"><span>&#37325;&#26032;&#35748;&#35782; Mac &#27963;&#21160;&#30417;&#35270;&#22120;&#30340;&#21508;&#39033;&#24615;&#33021;&#25351;&#26631; (What does Activity Monitor measure?)</span></a></strong></h3><p><span>&#22312; AI agent &#36880;&#28176;&#36827;&#20837;&#26085;&#24120;&#24320;&#21457;&#27969;&#31243;&#20043;&#21518;&#65292;&#24456;&#22810;&#24320;&#21457;&#32773;&#37117;&#20250;&#26377;&#31867;&#20284;&#30340;&#20307;&#39564;&#65306;Mac &#39118;&#25159;&#26356;&#39057;&#32321;&#21551;&#21160;&#12289;&#20869;&#23384;&#21387;&#21147;&#26126;&#26174;&#19978;&#21319;&#65292;&#20294; Activity Monitor &#20013;&#26174;&#31034;&#30340; CPU / Energy &#25968;&#20540;&#21364;&#24448;&#24448;&#19982;&#30452;&#35266;&#24863;&#21463;&#24182;&#19981;&#19968;&#33268;&#12290;</span></p><p><a href="https://x.com/howardnoakley"><span>Howard Oakley</span></a><span> &#36890;&#36807; powermetrics &#19982;&#22810;&#31181;&#30495;&#23454;&#36127;&#36733;&#23545;&#29031;&#23454;&#39564;&#25351;&#20986;&#65292;Activity Monitor &#20013;&#30340; CPU % &#26356;&#25509;&#36817;&#21508; CPU core active residency &#30340;&#31616;&#21333;&#21472;&#21152;&#65292;&#32780;&#38750;&#20256;&#32479;&#24847;&#20041;&#19978;&#30340;&#8220;&#21033;&#29992;&#29575;&#30334;&#20998;&#27604;&#8221;&#65307;GPU % &#21516;&#26679;&#21482;&#26159; active residency &#30340;&#36817;&#20284;&#34920;&#36798;&#65307;&#32780; Energy Impact &#21017;&#20027;&#35201;&#21453;&#26144; CPU &#23618;&#38754;&#30340;&#21151;&#32791;&#20272;&#31639;&#65292;&#26082;&#19981;&#21253;&#21547; GPU&#65292;&#20063;&#27809;&#26377;&#24456;&#22909;&#22320;&#21051;&#30011;&#26102;&#38388;&#32500;&#24230;&#19978;&#30340;&#33021;&#32791;&#21464;&#21270;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-07"><span>Quiver&#65306;&#29992; Swift &#23398;&#32447;&#24615;&#20195;&#25968;&#19982;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;</span></a></strong></h3><p><a href="https://www.linkedin.com/in/waynebishop/"><span>Wayne Bishop</span></a><span> &#38271;&#26399;&#32500;&#25252;&#30340;&#12298;</span><a href="https://waynewbishop.github.io/swift-algorithms/"><span>Swift Algorithms &amp; Data Structures</span></a><span>&#12299;&#26159;&#19968;&#37096;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#31639;&#27861;&#19982;&#25968;&#25454;&#32467;&#26500;&#30005;&#23376;&#20070;&#12290;&#22312;&#26368;&#26032;&#30340;&#31532;&#20116;&#29256;&#20013;&#65292;&#36825;&#26412;&#20070;&#24050;&#32463;&#20174;&#20256;&#32479;&#31639;&#27861;&#12289;&#25968;&#25454;&#32467;&#26500;&#24310;&#20280;&#21040;&#21521;&#37327;&#12289;&#30697;&#38453;&#21644;&#30456;&#20284;&#24230;&#35745;&#31639;&#65307;&#32780; Quiver &#21017;&#25226;&#36825;&#26465;&#36335;&#24452;&#32487;&#32493;&#25512;&#36827;&#21040;&#25968;&#20540;&#35745;&#31639;&#12289;&#32479;&#35745;&#21644;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;&#12290;</span></p><p><span>Quiver &#26159;&#19968;&#20010;&#32431; Swift&#12289;&#38646;&#20381;&#36182;&#30340;&#32447;&#24615;&#20195;&#25968;&#12289;&#32479;&#35745;&#19982;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;&#24211;&#12290;&#23427;&#30452;&#25509;&#25193;&#23637; Swift &#26631;&#20934;&#24211;&#30340; </span><code>Array</code><span>&#65292;&#24378;&#35843;&#20540;&#35821;&#20041;&#12289;</span><code>Codable</code><span>&#12289;</span><code>Sendable</code><span>&#65292;&#20197;&#21450;&#22312; Apple &#24179;&#21488;&#19978;&#30340;&#36731;&#37327;&#31471;&#20391;&#36816;&#34892;&#12290;&#23427;&#30340;&#30446;&#26631;&#19981;&#26159;&#26367;&#20195; Python &#25968;&#20540;&#29983;&#24577;&#65292;&#32780;&#26159;&#20026; Swift &#24320;&#21457;&#32773;&#25552;&#20379;&#19968;&#20010;&#29992;&#29087;&#24713;&#35821;&#35328;&#29702;&#35299;&#32447;&#24615;&#20195;&#25968;&#12289;&#35757;&#32451;&#23567;&#22411;&#27169;&#22411;&#65292;&#24182;&#23558;&#32467;&#26524;&#24102;&#22238; App &#30340;&#20837;&#21475;&#12290;Wayne &#22312;&#12298;Swift Algorithms &amp; Data Structures&#12299;&#21518;&#32493;&#31456;&#33410;&#20013;&#65292;&#20063;&#27491;&#26159;&#20197; Quiver &#20316;&#20026;&#25968;&#23398;&#19982;&#26426;&#22120;&#23398;&#20064;&#22522;&#30784;&#20869;&#23481;&#30340;&#37197;&#22871;&#24037;&#20855;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-08"><span>SwipeCell v3&#65306;SwiftUI &#21407;&#29983;&#30340;&#20391;&#28369;&#33756;&#21333;</span></a></strong></h3><p><span>WWDC 2026 &#19978;&#65292;SwiftUI &#36890;&#36807;&#26032;&#30340; </span><code>swipeActionsContainer()</code><span> &#32456;&#20110;&#35753;&#20391;&#28369;&#33756;&#21333;&#36208;&#20986;&#20102; </span><code>List</code><span>&#65292;&#21487;&#20197;&#26381;&#21153;&#20110; </span><code>ScrollView</code><span>&#12289;&#25042;&#21152;&#36733;&#26632;&#20197;&#21450;&#26356;&#22810;&#33258;&#23450;&#20041;&#23481;&#22120;&#12290;&#20294;&#36951;&#25022;&#30340;&#26159;&#65292;&#36825;&#39033;&#33021;&#21147;&#30446;&#21069;&#38656;&#35201; </span><code>anyAppleOS 27</code><span> &#23545;&#24212;&#30340;&#31995;&#32479;&#29256;&#26412;&#25165;&#33021;&#20351;&#29992;&#12290;</span></p><p><span>SwipeCell &#26159;&#25105;&#20845;&#24180;&#21069;&#21018;&#36827;&#20837; Swift &#24320;&#21457;&#26102;&#20889;&#19979;&#30340;&#31532;&#19968;&#20010;&#31532;&#19977;&#26041;&#24211;&#12290;&#26087;&#29256;&#26412;&#24456;&#31258;&#23273;&#65292;&#20294;&#20063;&#38506;&#25105;&#35265;&#35777;&#20102; SwiftUI &#20391;&#28369;&#20132;&#20114;&#36825;&#20123;&#24180;&#30340;&#21464;&#21270;&#12290;&#26368;&#36817;&#25105;&#23545;&#23427;&#20570;&#20102;&#24443;&#24213;&#30340;&#37325;&#20889;&#65292;&#25512;&#20986;&#20102; v3 &#29256;&#26412;&#65306;&#26032;&#30340; API &#26356; SwiftUI &#21270;&#65292;&#37197;&#32622;&#26356;&#23436;&#25972;&#65292;&#20132;&#20114;&#25163;&#24863;&#20063;&#37325;&#26032;&#25171;&#30952;&#65292;&#24182;&#21152;&#20837;&#20102; macOS &#25903;&#25345;&#12290;</span></p><p><span>&#30446;&#21069; SwipeCell v3 &#21457;&#24067;&#22312; </span><code>v3-beta</code><span> &#20998;&#25903;&#65292;&#20173;&#22788;&#20110; beta &#38454;&#27573;&#65292;&#27426;&#36814;&#35797;&#29992;&#65292;&#20063;&#27426;&#36814;&#21453;&#39304;&#20351;&#29992;&#20013;&#30340;&#38382;&#39064;&#12290;</span></p><h2><strong><span>&#27714;&#36132;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-09"><span>&#36164;&#28145; iOS / Swift &#24037;&#31243;&#24072;</span></a></strong></h3><p><strong><span>Speak</span></strong><span>&#65306;YC &#23413;&#21270;&#12289;OpenAI &#22810;&#36718;&#25237;&#36164;&#30340; AI &#35821;&#35328;&#23398;&#20064;&#29420;&#35282;&#20861;&#12290;</span></p><p><span>&#24037;&#20316;&#22320;&#65306;&#19978;&#28023;&#12290;</span></p><p><span>&#19968;&#23478;&#22312;&#28023;&#22806;&#22810;&#20010;&#24066;&#22330;&#38271;&#26399;&#39564;&#35777;&#12289;&#21830;&#19994;&#21270;&#25104;&#29087;&#30340; AI-native &#35821;&#35328;&#23398;&#20064;&#20844;&#21496;&#65292;&#27491;&#22312;&#20174; 0 -&gt; 1 &#32452;&#24314;&#20013;&#22269;&#26680;&#24515;&#24037;&#31243;&#22242;&#38431;&#12290;&#22242;&#38431;&#23567;&#32780;&#32654;&#12289;&#19981;&#20869;&#21367;&#65292;&#37325;&#24230;&#20351;&#29992; AI(Cursor / Claude Code &#31561;)&#65292;&#30475;&#37325;&#24037;&#31243; owner &#24847;&#35782;&#21644; agentic engineering &#24037;&#20316;&#26041;&#24335;&#12290;</span></p><p><span>&#20316;&#20026;&#20013;&#22269;&#22242;&#38431;&#30340;&#26089;&#26399;&#26680;&#24515; iOS&#65292;&#20320;&#23558;&#20840;&#31243;&#21442;&#19982;&#25216;&#26415;&#36873;&#22411;,&#25645;&#24314;&#22269;&#20869; iOS &#23436;&#25972;&#22522;&#24314;&#12289;&#23545;&#25509;&#26412;&#22303;&#25903;&#20184; / &#30331;&#24405; / &#21512;&#35268; SDK&#12289;&#20248;&#21270; AI &#35821;&#38899;&#23454;&#26102;&#20132;&#20114;&#20307;&#39564;,&#24182;&#19982;&#20840;&#29699;&#22242;&#38431;&#33521;&#25991;&#21327;&#20316;&#12290;</span></p><p><span>&#26399;&#24453;&#20320;&#20855;&#22791;:</span></p><ul><li><p><span>5 &#24180;&#20197;&#19978; iOS &#21407;&#29983;(Swift)&#24320;&#21457;&#32463;&#39564;,&#26377;&#19978;&#32447;&#30340;&#28040;&#36153;&#32423;&#20135;&#21697;</span></p></li><li><p><span>&#25166;&#23454;&#30340;&#21407;&#29983; iOS &#28145;&#24230;(&#24615;&#33021;&#12289;&#31283;&#23450;&#24615;&#12289;&#26550;&#26500;&#12289;&#24369;&#32593;&#20248;&#21270;&#31561;)</span></p></li><li><p><span>AI-native &#24037;&#20316;&#27969;(&#26085;&#24120;&#29992; Cursor / Claude / Copilot &#31561;)</span></p></li><li><p><span>&#20070;&#38754;&#33521;&#25991;&#32988;&#20219; PR / Slack / &#25991;&#26723;,&#21475;&#35821; B1+&#12289;&#33021;&#28165;&#26224;&#34920;&#36798;&#25216;&#26415;&#24819;&#27861;</span></p></li><li><p><span>&#26377;&#22269;&#20869; App Store &#19978;&#26550; / &#26412;&#22303; SDK &#32463;&#39564;&#32773;&#20248;&#20808;;&#38899;&#35270;&#39057; / RTC / &#35821;&#38899;&#26041;&#21521;&#21152;&#20998;</span></p></li></ul><p><span>&#128073; </span><a href="https://usespeak.notion.site/speak-ios-founding-engineer-sh"><span>&#35814;&#32454;&#21442;&#35265;</span></a></p><p><span>&#26377;&#24847;&#21521;&#32773;&#27426;&#36814;&#25237;&#36882;&#33521;&#25991;&#31616;&#21382;&#33267; </span><a href="mailto:a.suen@usespeak.com"><span>a.suen@usespeak.com</span></a></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #142]]></title><description><![CDATA[SPI Joins Apple, and Swift Moves Toward Self-Hosting]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 29 Jun 2026 12:03:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Lh7P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Lh7P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 424w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 848w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1272w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" width="1400" height="782" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:782,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:109432,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/204052037?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 424w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 848w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1272w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@alanaprilio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Alan Aprilio</a><span> on </span><a href="https://unsplash.com/photos/hands-connecting-colorful-puzzle-pieces-together-EwVWnl4Z4Wo?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>SPI Joins Apple, and Swift Moves Toward Self-Hosting</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-142/">Read on web &#8594;</a></p><p><span>A few days ago, Swift Package Index (SPI) announced that it had joined Apple. The two sides will work together to build a comprehensive package registry for Swift developers. At the same time, SPI&#8217;s existing capabilities, including package discovery, compatibility checking, and documentation hosting, will continue to be provided, and package authors will not need to adjust their current publishing workflows in the short term.</span></p><p><span>This also adds a new footnote to the observation I made in </span><a href="https://fatbobman.com/en/weekly/issue-135/"><span>#135</span></a><span>&#8288; that &#8220;SwiftPM has only just reached its second chapter&#8221;: the retreat of CocoaPods merely pushed SPM into the default position, while SPI joining Apple truly opens the next act of Swift package ecosystem infrastructure.</span></p><p><span>If SwiftPM answered the question of &#8220;whether packages can be conveniently depended on,&#8221; and SPI answered &#8220;whether packages can be found and evaluated,&#8221; then joining Apple moves the conversation further toward &#8220;whether packages can be published, identified, and distributed in a trustworthy way.&#8221; Looking at the medium term, three points are especially worth watching:</span></p><ul><li><p><span>SPI will evolve from a third-party indexing service into an important entry point for the official package registry;</span></p></li><li><p><span>The Swift package ecosystem may gradually reduce its implicit dependence on GitHub as a source of hosting, distribution, and identity;</span></p></li><li><p><span>Xcode may establish closer integration with SPI&#8217;s search, compatibility checking, and documentation capabilities.</span></p></li></ul><p><span>Another exciting development for Swift developers last week was Erik Eckstein&#8217;s announcement on the Swift forums that the Swift project will drop the requirement that the compiler &#8220;</span><a href="https://forums.swift.org/t/dropping-the-requirement-for-c-only-bootstrapping/87739/3"><span>must be buildable using only a C++ host toolchain</span></a><span>&#8288;.&#8221; In other words, starting from the </span><code>main</code><span> branch, building the Swift compiler will require an existing Swift toolchain. This also means that mandatory compiler paths that previously had to remain implemented in C++ can now gradually be written in Swift. The officially mentioned scope includes core components such as the Parser, AST, Type Checker, and mandatory SIL passes.</span></p><p><span>This does not mean that the Swift compiler has already been completely rewritten in Swift, nor does it mean that the C++ parser will disappear immediately. More precisely, this is an important threshold for the Swift compiler as it moves toward bootstrapping and self-hosting: Swift is no longer limited to peripheral tools, optional features, or individual optimization passes, but can now enter the compiler&#8217;s core paths.</span></p><p><span>Bootstrapping itself does not simply prove the strength or weakness of a language, but it does represent a form of engineering maturity: whether the language, compiler, standard library, package manager, and cross-platform build system are strong enough to support their own continued evolution. For a language that hopes to expand its influence beyond Apple platforms, this step carries both symbolic significance and practical value.</span></p><p><span>Looking at SPI joining Apple alongside the Swift compiler moving toward self-hosting, it becomes clear that they point to the same thing: Swift is filling in its ecosystem infrastructure. The former concerns package discovery, identity, signing, and trusted distribution, while the latter improves the maintainability and evolution capacity of the language toolchain itself. Whether Swift can truly break out depends not only on how much influence Apple has over it, but on whether Apple and the Swift community can continue to show an open and enterprising attitude, and whether they can make the toolchain, package ecosystem, and cross-platform experience complete enough. On these two developments, I am willing to remain optimistic.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-141/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-01"><span>Bring Swift to The APPLE II</span></a></strong></h3><p><span>The Apple II was one of Apple&#8217;s most important early products and continues to influence many developers today. Many people once used BASIC or Apple Pascal on it, but what would it feel like to write Swift on this machine? </span><a href="https://x.com/yeokm1"><span>Yeo Kheng Meng</span></a><span>&#8288; created SwiftII, a Swift-like mini development environment that allows an old machine with a 1 MHz 6502 CPU and around 64 KB of memory to write and run Swift-like programs.</span></p><p><span>What makes the article fascinating is not only &#8220;getting a Swift-like language running on the Apple II,&#8221; but also the many engineering trade-offs imposed by hardware limitations: limited memory space, conflicts between the language card and ProDOS, keyboard and display differences across Apple II models, and why the project ultimately had to be distributed as multiple disk images. The author also candidly shares the process of AI-assisted development. Even with the help of Claude Code and Codex, key architectural trade-offs, scope control, and hardware testing strategies still had to be handled by the author. This article offers both retro-computing engineering details and the compromises involved in bringing modern language design into an extremely constrained environment.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-02"><span>Building an over-the-air update system for native Swift with WebAssembly, from scratch</span></a></strong></h3><p><span>Building an OTA update mechanism for native Swift iOS apps is a controversial but valuable direction. In this article, </span><a href="https://www.linkedin.com/in/jackasolomon/"><span>Jack Solomon</span></a><span>&#8288; demonstrates a WebAssembly-based approach: compile Swift functions into WASM, load and execute them inside an iOS app through WasmKit, and then download new WASM modules from a server, allowing the app to change its runtime behavior without rebuilding or replacing the signed binary.</span></p><p><span>The article breaks down the Swift-to-WASM toolchain, WASI, </span><code>@_cdecl</code><span> exports, reactor modules, passing parameters through linear memory, and why hot-updating SwiftUI views requires dynamic replacement and a serializable view description tree. Jack also packaged this approach into a Swift SDK: </span><a href="https://github.com/patch-release/patch-swift"><span>patch-swift</span></a><span>&#8288;.</span></p><blockquote><p><span>It should be noted that this type of solution touches the boundaries of App Store Review rules around downloading and executing code, so actual usage still requires careful evaluation of the scenario and compliance risks.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-03"><span>SwiftUI Is One Graph</span></a></strong></h3><p><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span>&#8288; published two long articles about SwiftUI&#8217;s underlying mechanisms over the past week, and they are worth reading together. The first, SwiftUI Is One Graph, starts from observed behavior and Apple patents to explain that SwiftUI is not simply doing View Tree diffing, but is more like a demand-driven attribute graph: View structs themselves are disposable descriptions, while what truly persists is the attribute graph and the state, dependencies, layout, and animation propagation within it.</span></p><p><span>The second article, &#8220;</span><a href="https://l.fatbobman.com/w0142-04"><span>The SwiftUI Oracle: Measuring a Clean Room Against the Real Thing</span></a><span>,&#8221; goes further by showing how to validate this understanding. The author implements a clean-room engine called PureView that does not depend on SwiftUI, then treats real SwiftUI as an oracle and uses differential testing of layout, animation, pixel rendering, and more to validate the model.</span></p><blockquote><p><span>Mihaela&#8217;s workflow is highly inspiring for AI agents. Agents do not need to rely solely on language models to guess whether SwiftUI behavior is correct; they can generate or modify an implementation, run tests, and let real SwiftUI provide comparable results. This kind of &#8220;unit test&#8221;-like feedback loop can turn the understanding of a black-box framework into engineering signals that can be continuously verified and iterated on.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-05"><span>SwiftUI: Intercept-able Picker / Menu / Context Menu</span></a></strong></h3><p><span>In many scenarios, developers want to perform some synchronous operation before components such as </span><code>Menu</code><span>, </span><code>Picker</code><span>, or </span><code>contextMenu</code><span> are presented, such as recording how many times a menu is opened, updating state, or temporarily deciding whether presentation should be allowed. SwiftUI, however, does not provide a corresponding callback. In this article, </span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> shares an implementation approach: bridge to a native View that hosts SwiftUI content, execute </span><code>menuWillOpen</code><span> when the corresponding gesture is triggered, and then decide whether to actively present the menu using AppKit APIs such as </span><code>NSMenu.popUpContextMenu</code><span>.</span></p><blockquote><p><span>This article once again highlights a practical issue with SwiftUI: many seemingly simple interaction controls, once they go beyond what the system modifiers expose, still require understanding the underlying AppKit / UIKit layer to truly solve.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-06"><span>_UIPortalView: From Live Mirroring to Liquid Glass-Style Effects</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; shared an interesting private UIKit component, </span><code>_UIPortalView</code><span>. Backed by </span><code>CAPortalLayer</code><span>, it can project the rendered result of a </span><code>sourceView</code><span> to another location on the screen in real time, without duplicating the View hierarchy or repeatedly generating snapshots. Compared with static snapshots, Portal is more like a &#8220;live window&#8221; at the compositing layer: the source view remains the single source of state, while changes to text, animations, layout, or subviews can be reflected synchronously elsewhere.</span></p><p><span>The article also connects </span><code>_UIPortalView</code><span> with Liquid Glass-style effects: through </span><code>matchesPosition</code><span>, clipping, offsets, and 3D transforms, it can achieve real-time mirroring, reflections, lenses, shared backgrounds, edge distortion, and other effects.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-07"><span>Taking control of toolbar items in SwiftUI</span></a></strong></h3><p><span>The new SwiftUI Toolbar APIs introduced at WWDC 26 strike a better balance between system adaptivity and explicit developer control. In this article, </span><a href="https://x.com/mecid"><span>Majid Jabrayilov</span></a><span>&#8288; introduces several new control capabilities: using </span><code>visibilityPriority</code><span> to specify the display priority of toolbar items, explicitly creating collapsed menus with </span><code>ToolbarOverflowMenu</code><span>, pinning important actions to the trailing edge of the top bar with </span><code>.topBarPinnedTrailing</code><span>, and using </span><code>toolbarMinimizeBehavior</code><span> to control how the navigation bar, tab bar, bottom bar, and others minimize during scrolling.</span></p><p><span>The same set of toolbar items may be presented differently on iOS, iPadOS, and macOS. The value of the new APIs is that they do not undermine the original cross-platform adaptive nature of SwiftUI Toolbar, while still allowing developers to express more clearly which actions should be shown first, which actions can be intentionally placed into overflow, and how toolbars should respond to scrolling.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-08"><span>iOS-Simulator-Camera-Extend: Adding a &#8220;Truly Usable Camera&#8221; to iOS Simulator</span></a></strong></h3><p><span>iOS Simulator has long lacked real camera capabilities. Features involving QR code scanning, OCR, faces, video calls, or </span><code>AVCaptureSession</code><span> often require a physical device or mocked logic. Developed by </span><a href="https://x.com/GSYTech_CarGuo"><span>Shuyu Guo</span></a><span>, iOS-Simulator-Camera-Extend recreates the core idea of SimCam: through a macOS-side frame source, </span><code>DYLD_INSERT_LIBRARIES</code><span> hooks inside Simulator, and AVFoundation swizzling, the app under test can access the Mac camera, desktop, images, videos, and QR code feeds in the simulator without code changes or a different bundle id.</span></p><p><span>Even more interestingly, it also provides another path based on a CMIO System Extension, allowing macOS apps such as QuickTime, FaceTime, Zoom, and OBS to see a SimCam Virtual Camera. In other words, the same frame source can be fed both to an app running inside iOS Simulator and used as a macOS virtual camera, making it very useful for debugging, demonstrations, and automated testing of camera-related features.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>SPI &#21152;&#20837; Apple&#65292;Swift &#36808;&#21521;&#33258;&#20030;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-142/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#20960;&#22825;&#21069;&#65292;Swift Package Index&#65288;SPI&#65289;&#23459;&#24067;&#24050;&#21152;&#20837; Apple&#12290;&#21452;&#26041;&#23558;&#20849;&#21516;&#24314;&#35774;&#19968;&#20010;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#32508;&#21512; package registry&#65307;&#19982;&#27492;&#21516;&#26102;&#65292;SPI &#29616;&#26377;&#30340;&#21253;&#21457;&#29616;&#12289;&#20860;&#23481;&#24615;&#26816;&#26597;&#12289;&#25991;&#26723;&#25176;&#31649;&#31561;&#33021;&#21147;&#20173;&#20250;&#32487;&#32493;&#25552;&#20379;&#65292;&#21253;&#20316;&#32773;&#22312;&#30701;&#26399;&#20869;&#20063;&#26080;&#38656;&#35843;&#25972;&#29616;&#26377;&#30340;&#21457;&#24067;&#27969;&#31243;&#12290;</span></p><p><span>&#36825;&#20063;&#35753; </span><a href="https://fatbobman.com/zh/weekly/issue-135/"><span>#135</span></a><span>&#8288; &#20013;&#8220;SwiftPM &#25165;&#21018;&#21040;&#31532;&#20108;&#31456;&#8221;&#30340;&#21028;&#26029;&#24471;&#21040;&#20102;&#26032;&#30340;&#27880;&#33050;&#65306;CocoaPods &#30340;&#36864;&#22330;&#21482;&#26159;&#25226; SPM &#25512;&#19978;&#20102;&#40664;&#35748;&#20301;&#32622;&#65292;&#32780; SPI &#21152;&#20837; Apple&#65292;&#25165;&#30495;&#27491;&#25581;&#24320;&#20102; Swift &#21253;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#24314;&#35774;&#30340;&#19979;&#19968;&#24149;&#12290;</span></p><p><span>&#22914;&#26524;&#35828; SwiftPM &#35299;&#20915;&#30340;&#26159;&#8220;&#33021;&#19981;&#33021;&#26041;&#20415;&#22320;&#20381;&#36182;&#21253;&#8221;&#65292;SPI &#35299;&#20915;&#30340;&#26159;&#8220;&#33021;&#19981;&#33021;&#25214;&#21040;&#24182;&#35780;&#20272;&#21253;&#8221;&#65292;&#37027;&#20040;&#36825;&#27425;&#21152;&#20837; Apple &#21017;&#25226;&#38382;&#39064;&#36827;&#19968;&#27493;&#25512;&#36827;&#21040;&#20102;&#8220;&#33021;&#19981;&#33021;&#21487;&#20449;&#22320;&#21457;&#24067;&#12289;&#35782;&#21035;&#21644;&#20998;&#21457;&#21253;&#8221;&#12290;&#20174;&#20013;&#26399;&#26469;&#30475;&#65292;&#26377;&#19977;&#28857;&#23588;&#20854;&#20540;&#24471;&#35266;&#23519;&#65306;</span></p><ul><li><p><span>SPI &#23558;&#20174;&#31532;&#19977;&#26041;&#32034;&#24341;&#26381;&#21153;&#65292;&#28436;&#36827;&#20026;&#23448;&#26041; package registry &#30340;&#37325;&#35201;&#20837;&#21475;&#65307;</span></p></li><li><p><span>Swift &#21253;&#29983;&#24577;&#21487;&#33021;&#36880;&#27493;&#38477;&#20302;&#23545; GitHub &#20316;&#20026;&#25176;&#31649;&#12289;&#20998;&#21457;&#19982;&#36523;&#20221;&#26469;&#28304;&#30340;&#38544;&#24615;&#20381;&#36182;&#65307;</span></p></li><li><p><span>Xcode &#26377;&#26426;&#20250;&#19982; SPI &#30340;&#25628;&#32034;&#12289;&#20860;&#23481;&#24615;&#26816;&#26597;&#21644;&#25991;&#26723;&#33021;&#21147;&#24314;&#31435;&#26356;&#32039;&#23494;&#30340;&#38598;&#25104;&#12290;</span></p></li></ul><p><span>&#19978;&#21608;&#65292;&#21478;&#19968;&#20214;&#35753; Swift &#24320;&#21457;&#32773;&#25391;&#22859;&#30340;&#20107;&#24773;&#26159;&#65292;Erik Eckstein &#22312; Swift &#35770;&#22363;&#19978;&#23459;&#24067;&#65292;Swift &#39033;&#30446;&#23558;&#21462;&#28040;&#8220;</span><a href="https://forums.swift.org/t/dropping-the-requirement-for-c-only-bootstrapping/"><span>&#24517;&#39035;&#33021;&#22815;&#20165;&#20351;&#29992; C++ &#23487;&#20027;&#24037;&#20855;&#38142;&#26500;&#24314;&#32534;&#35793;&#22120;</span></a><span>&#8221;&#30340;&#35201;&#27714;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#20174; </span><code>main</code><span> &#20998;&#25903;&#24320;&#22987;&#65292;&#26500;&#24314; Swift &#32534;&#35793;&#22120;&#23558;&#38656;&#35201;&#24050;&#26377;&#30340; Swift &#24037;&#20855;&#38142;&#21442;&#19982;&#65307;&#36825;&#20063;&#20351;&#24471;&#32534;&#35793;&#22120;&#20013;&#37027;&#20123;&#36807;&#21435;&#24517;&#39035;&#20445;&#25345; C++ &#23454;&#29616;&#30340;&#24378;&#21046;&#36335;&#24452;&#65292;&#29616;&#22312;&#21487;&#20197;&#36880;&#27493;&#29992; Swift &#32534;&#20889;&#12290;&#23448;&#26041;&#25552;&#21040;&#30340;&#33539;&#22260;&#21253;&#25324; Parser&#12289;AST&#12289;Type Checker&#65292;&#20197;&#21450; mandatory SIL passes &#31561;&#26680;&#24515;&#37096;&#20998;&#12290;</span></p><p><span>&#36825;&#24182;&#19981;&#24847;&#21619;&#30528; Swift &#32534;&#35793;&#22120;&#24050;&#32463;&#23436;&#20840;&#29992; Swift &#37325;&#20889;&#65292;&#20063;&#19981;&#24847;&#21619;&#30528; C++ parser &#20250;&#39532;&#19978;&#28040;&#22833;&#12290;&#26356;&#20934;&#30830;&#22320;&#35828;&#65292;&#36825;&#26159; Swift &#32534;&#35793;&#22120;&#36808;&#21521;&#33258;&#20030;&#21644;&#33258;&#25176;&#31649;&#30340;&#37325;&#35201;&#38376;&#27099;&#65306;Swift &#19981;&#20877;&#21482;&#26159;&#29992;&#20110;&#22806;&#22260;&#24037;&#20855;&#12289;&#21487;&#36873;&#21151;&#33021;&#25110;&#20010;&#21035;&#20248;&#21270; pass&#65292;&#32780;&#26159;&#21487;&#20197;&#36827;&#20837;&#32534;&#35793;&#22120;&#30340;&#26680;&#24515;&#36335;&#24452;&#12290;</span></p><p><span>&#33258;&#20030;&#26412;&#36523;&#24182;&#19981;&#33021;&#31616;&#21333;&#35777;&#26126;&#19968;&#38376;&#35821;&#35328;&#33021;&#21147;&#30340;&#39640;&#20302;&#65292;&#20294;&#23427;&#20195;&#34920;&#20102;&#19968;&#31181;&#24037;&#31243;&#25104;&#29087;&#24230;&#65306;&#35821;&#35328;&#12289;&#32534;&#35793;&#22120;&#12289;&#26631;&#20934;&#24211;&#12289;&#21253;&#31649;&#29702;&#22120;&#21644;&#36328;&#24179;&#21488;&#26500;&#24314;&#31995;&#32479;&#65292;&#26159;&#21542;&#24050;&#32463;&#24378;&#22823;&#21040;&#36275;&#20197;&#25903;&#25745;&#33258;&#36523;&#30340;&#25345;&#32493;&#28436;&#36827;&#12290;&#23545;&#20110;&#19968;&#20010;&#24076;&#26395;&#22312; Apple &#24179;&#21488;&#20043;&#22806;&#32487;&#32493;&#25193;&#23637;&#24433;&#21709;&#21147;&#30340;&#35821;&#35328;&#26469;&#35828;&#65292;&#36825;&#19968;&#27493;&#30340;&#35937;&#24449;&#24847;&#20041;&#21644;&#23454;&#38469;&#20215;&#20540;&#37117;&#19981;&#23567;&#12290;</span></p><p><span>&#25226; SPI &#21152;&#20837; Apple &#19982; Swift &#32534;&#35793;&#22120;&#36808;&#21521;&#33258;&#25176;&#31649;&#25918;&#22312;&#19968;&#36215;&#30475;&#65292;&#20250;&#21457;&#29616;&#23427;&#20204;&#25351;&#21521;&#30340;&#26159;&#21516;&#19968;&#20214;&#20107;&#65306;Swift &#27491;&#22312;&#34917;&#40784;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#12290;&#21069;&#32773;&#20851;&#20046;&#21253;&#30340;&#21457;&#29616;&#12289;&#36523;&#20221;&#12289;&#31614;&#21517;&#21644;&#21487;&#20449;&#20998;&#21457;&#65292;&#21518;&#32773;&#21017;&#25552;&#21319;&#20102;&#35821;&#35328;&#24037;&#20855;&#38142;&#33258;&#36523;&#30340;&#21487;&#32500;&#25252;&#24615;&#19982;&#28436;&#36827;&#33021;&#21147;&#12290;Swift &#33021;&#21542;&#30495;&#27491;&#30772;&#22280;&#65292;&#20851;&#38190;&#24182;&#19981;&#21482;&#22312;&#20110; Apple &#22312;&#20854;&#20013;&#25317;&#26377;&#22810;&#22823;&#30340;&#24433;&#21709;&#21147;&#65292;&#32780;&#22312;&#20110; Apple &#19982; Swift &#31038;&#21306;&#26159;&#21542;&#33021;&#25345;&#32493;&#23637;&#29616;&#24320;&#25918;&#12289;&#36827;&#21462;&#30340;&#24577;&#24230;&#65292;&#24182;&#25226;&#24037;&#20855;&#38142;&#12289;&#21253;&#29983;&#24577;&#21644;&#36328;&#24179;&#21488;&#20307;&#39564;&#25171;&#30952;&#21040;&#36275;&#22815;&#23436;&#25972;&#12290;&#23601;&#36825;&#20004;&#20214;&#20107;&#32780;&#35328;&#65292;&#25105;&#24895;&#24847;&#20445;&#25345;&#20048;&#35266;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-141/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-01"><span>&#22312; Apple II &#19978;&#36305; Swift (Bring Swift to The APPLE II)</span></a></strong></h3><p><span>Apple II &#26159;&#33529;&#26524;&#26089;&#26399;&#26368;&#37325;&#35201;&#30340;&#20135;&#21697;&#20043;&#19968;&#65292;&#33267;&#20170;&#20173;&#24433;&#21709;&#30528;&#35768;&#22810;&#24320;&#21457;&#32773;&#12290;&#24456;&#22810;&#20154;&#37117;&#26366;&#22312;&#23427;&#19978;&#38754;&#20351;&#29992; BASIC &#25110; Apple Pascal&#65292;&#20294;&#22914;&#26524;&#22312;&#36825;&#21488;&#26426;&#22120;&#19978;&#20889; Swift&#65292;&#21448;&#20250;&#26159;&#20160;&#20040;&#20307;&#39564;&#65311;</span><a href="https://x.com/yeokm1"><span>Yeo Kheng Meng</span></a><span>&#8288; &#23454;&#29616;&#20102;&#19968;&#20010; Swift &#39118;&#26684;&#30340;&#36855;&#20320;&#24320;&#21457;&#29615;&#22659; SwiftII&#65292;&#35753;&#19968;&#21488;&#25645;&#36733; 1 MHz 6502 CPU&#12289;64 KB &#32423;&#21035;&#20869;&#23384;&#30340;&#32769;&#26426;&#22120;&#20063;&#33021;&#32534;&#20889;&#21644;&#36816;&#34892;&#31867;&#20284; Swift &#30340;&#31243;&#24207;&#12290;</span></p><p><span>&#25991;&#31456;&#31934;&#24425;&#30340;&#22320;&#26041;&#19981;&#21482;&#26159;&#8220;&#35753; Apple II &#36305;&#19978;&#31867; Swift &#35821;&#35328;&#8221;&#65292;&#36824;&#21253;&#25324;&#22823;&#37327;&#22260;&#32469;&#30828;&#20214;&#38480;&#21046;&#30340;&#24037;&#31243;&#21462;&#33293;&#65306;&#26377;&#38480;&#30340;&#20869;&#23384;&#31354;&#38388;&#12289;&#35821;&#35328;&#21345;&#21644; ProDOS &#30340;&#20914;&#31361;&#12289;&#19981;&#21516; Apple II &#26426;&#22411;&#30340;&#38190;&#30424;&#19982;&#26174;&#31034;&#24046;&#24322;&#65292;&#20197;&#21450;&#20026;&#20160;&#20040;&#26368;&#32456;&#35201;&#25286;&#25104;&#22810;&#24352;&#30913;&#30424;&#38236;&#20687;&#21457;&#24067;&#12290;&#20316;&#32773;&#20063;&#22374;&#35802;&#20998;&#20139;&#20102; AI &#36741;&#21161;&#24320;&#21457;&#30340;&#36807;&#31243;&#12290;&#21363;&#20415;&#26377; Claude Code &#21644; Codex &#30340;&#24110;&#21161;&#65292;&#20851;&#38190;&#30340;&#26550;&#26500;&#21462;&#33293;&#12289;&#33539;&#22260;&#25511;&#21046;&#21644;&#30828;&#20214;&#27979;&#35797;&#31574;&#30053;&#20173;&#28982;&#38656;&#35201;&#20316;&#32773;&#33258;&#24049;&#25226;&#20851;&#12290;&#26412;&#25991;&#26082;&#26377;&#22797;&#21476;&#35745;&#31639;&#26426;&#30340;&#24037;&#31243;&#32454;&#33410;&#65292;&#20063;&#26377;&#29616;&#20195;&#35821;&#35328;&#35774;&#35745;&#22312;&#26497;&#23567;&#29615;&#22659;&#20013;&#30340;&#21462;&#33293;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-02"><span>&#22522;&#20110; WebAssembly &#23454;&#29616; Swift App &#28909;&#26356;&#26032; (Building an over-the-air update system for native Swift with WebAssembly, from scratch)</span></a></strong></h3><p><span>&#20026;&#21407;&#29983; Swift iOS App &#26500;&#24314; OTA &#26356;&#26032;&#26426;&#21046;&#65292;&#26159;&#19968;&#20010;&#26377;&#20105;&#35758;&#20294;&#20063;&#24456;&#26377;&#20215;&#20540;&#30340;&#26041;&#21521;&#12290;</span><a href="https://www.linkedin.com/in/jackasolomon/"><span>Jack Solomon</span></a><span>&#8288; &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#23637;&#31034;&#20102;&#22522;&#20110; WebAssembly &#30340;&#23454;&#29616;&#24605;&#36335;&#65306;&#23558; Swift &#20989;&#25968;&#32534;&#35793;&#25104; WASM&#65292;&#20877;&#36890;&#36807; WasmKit &#22312; iOS App &#20869;&#21152;&#36733;&#25191;&#34892;&#65292;&#38543;&#21518;&#20174;&#26381;&#21153;&#22120;&#19979;&#36733;&#26032;&#30340; WASM &#27169;&#22359;&#65292;&#35753; App &#22312;&#19981;&#37325;&#26032;&#26500;&#24314;&#12289;&#19981;&#26367;&#25442;&#24050;&#31614;&#21517;&#20108;&#36827;&#21046;&#30340;&#24773;&#20917;&#19979;&#25913;&#21464;&#36816;&#34892;&#32467;&#26524;&#12290;</span></p><p><span>&#25991;&#31456;&#25286;&#35299;&#20102; Swift to WASM &#30340;&#24037;&#20855;&#38142;&#12289;WASI&#12289;</span><code>@_cdecl</code><span> &#23548;&#20986;&#12289;reactor module&#12289;&#32447;&#24615;&#20869;&#23384;&#20256;&#21442;&#65292;&#20197;&#21450; SwiftUI &#35270;&#22270;&#28909;&#26356;&#26032;&#20026;&#20160;&#20040;&#38656;&#35201; dynamic replacement &#21644;&#21487;&#24207;&#21015;&#21270;&#30340;&#35270;&#22270;&#25551;&#36848;&#26641;&#12290;Jack &#20063;&#23558;&#36825;&#22871;&#24605;&#36335;&#21253;&#35013;&#25104;&#20102; Swift SDK&#65306;</span><a href="https://github.com/patch-release/patch-swift"><span>patch-swift</span></a><span>&#8288;&#12290;</span></p><blockquote><p><span>&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;&#36825;&#31867;&#26041;&#26696;&#35302;&#21450; App Store &#23457;&#26680;&#35268;&#21017;&#20013;&#20851;&#20110;&#19979;&#36733;&#21644;&#25191;&#34892;&#20195;&#30721;&#30340;&#36793;&#30028;&#65292;&#23454;&#38469;&#20351;&#29992;&#26102;&#20173;&#38656;&#35201;&#35880;&#24910;&#35780;&#20272;&#22330;&#26223;&#21644;&#21512;&#35268;&#39118;&#38505;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-03"><span>&#29702;&#35299; SwiftUI &#30340;&#24213;&#23618;&#26680;&#24515;&#65306;&#23646;&#24615;&#22270; (SwiftUI Is One Graph)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#22312;&#36807;&#21435;&#19968;&#21608;&#36830;&#32493;&#21457;&#34920;&#20102;&#20004;&#31687;&#20851;&#20110; SwiftUI &#24213;&#23618;&#26426;&#21046;&#30340;&#38271;&#25991;&#65292;&#20540;&#24471;&#25918;&#22312;&#19968;&#36215;&#38405;&#35835;&#12290;&#31532;&#19968;&#31687; SwiftUI Is One Graph &#20174;&#23454;&#38469;&#34892;&#20026;&#21644; Apple &#19987;&#21033;&#20986;&#21457;&#65292;&#35299;&#37322; SwiftUI &#24182;&#19981;&#26159;&#31616;&#21333;&#30340; View Tree diff&#65292;&#32780;&#26356;&#20687;&#26159;&#19968;&#20010; demand-driven attribute graph&#65306;View struct &#26412;&#36523;&#21482;&#26159;&#21487;&#20002;&#24323;&#30340;&#25551;&#36848;&#65292;&#30495;&#27491;&#25345;&#32493;&#23384;&#22312;&#30340;&#26159;&#23646;&#24615;&#22270;&#65292;&#20197;&#21450;&#20854;&#20013;&#30340;&#29366;&#24577;&#12289;&#20381;&#36182;&#12289;&#24067;&#23616;&#21644;&#21160;&#30011;&#20256;&#25773;&#12290;</span></p><p><span>&#31532;&#20108;&#31687; &#12298;</span><a href="https://l.fatbobman.com/w0142-04"><span>The SwiftUI Oracle: Measuring a Clean Room Against the Real Thing</span></a><span>&#12299;&#21017;&#36827;&#19968;&#27493;&#23637;&#31034;&#20102;&#22914;&#20309;&#39564;&#35777;&#36825;&#31181;&#29702;&#35299;&#12290;&#20316;&#32773;&#23454;&#29616;&#20102;&#19968;&#20010;&#19981;&#20381;&#36182; SwiftUI &#30340; clean-room &#24341;&#25806; PureView&#65292;&#20877;&#25226;&#30495;&#23454; SwiftUI &#24403;&#20316; oracle&#65292;&#36890;&#36807;&#24067;&#23616;&#12289;&#21160;&#30011;&#12289;&#20687;&#32032;&#28210;&#26579;&#31561; differential testing &#21435;&#39564;&#35777;&#33258;&#24049;&#30340;&#27169;&#22411;&#12290;</span></p><blockquote><p><span>Mihaela &#30340;&#24037;&#20316;&#27969;&#23545; AI agent &#24456;&#26377;&#21551;&#21457;&#12290;Agent &#19981;&#38656;&#35201;&#21482;&#38752;&#35821;&#35328;&#27169;&#22411;&#21435;&#29468; SwiftUI &#34892;&#20026;&#26159;&#21542;&#27491;&#30830;&#65292;&#32780;&#26159;&#21487;&#20197;&#29983;&#25104;&#25110;&#20462;&#25913;&#23454;&#29616;&#65292;&#28982;&#21518;&#36816;&#34892;&#27979;&#35797;&#65292;&#35753;&#30495;&#23454; SwiftUI &#32473;&#20986;&#21487;&#27604;&#36739;&#30340;&#32467;&#26524;&#12290;&#36825;&#31181;&#31867;&#20284;&#8220;&#21333;&#20803;&#27979;&#35797;&#8221;&#30340;&#21453;&#39304;&#38381;&#29615;&#65292;&#33021;&#25226;&#23545;&#40657;&#30418;&#26694;&#26550;&#30340;&#29702;&#35299;&#21464;&#25104;&#21487;&#20197;&#25345;&#32493;&#39564;&#35777;&#21644;&#36845;&#20195;&#30340;&#24037;&#31243;&#20449;&#21495;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-05"><span>&#22312; SwiftUI &#20013;&#23454;&#29616;&#21487;&#25318;&#25130;&#22238;&#35843;&#30340;&#33756;&#21333;&#19982;&#36873;&#25321;&#22120; (SwiftUI: Intercept-able Picker / Menu / Context Menu)</span></a></strong></h3><p><span>&#24456;&#22810;&#22330;&#26223;&#19979;&#65292;&#24320;&#21457;&#32773;&#37117;&#24076;&#26395;&#33021;&#22312; </span><code>Menu</code><span>&#12289;</span><code>Picker</code><span>&#12289;</span><code>contextMenu</code><span> &#31561;&#32452;&#20214;&#24377;&#20986;&#21069;&#25191;&#34892;&#19968;&#20123;&#21516;&#27493;&#25805;&#20316;&#65292;&#27604;&#22914;&#32479;&#35745;&#25171;&#24320;&#27425;&#25968;&#12289;&#26356;&#26032;&#29366;&#24577;&#65292;&#25110;&#32773;&#20020;&#26102;&#20915;&#23450;&#26159;&#21542;&#20801;&#35768;&#23637;&#31034;&#12290;&#20294; SwiftUI &#24182;&#27809;&#26377;&#25552;&#20379;&#23545;&#24212;&#30340;&#22238;&#35843;&#12290;</span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span>&#8288; &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#20998;&#20139;&#20102;&#33258;&#24049;&#30340;&#23454;&#29616;&#24605;&#36335;&#65306;&#36890;&#36807;&#26725;&#25509;&#19968;&#20010;&#25215;&#36733; SwiftUI &#20869;&#23481;&#30340;&#21407;&#29983; View&#65292;&#22312;&#23545;&#24212;&#25163;&#21183;&#35302;&#21457;&#26102;&#20808;&#25191;&#34892; </span><code>menuWillOpen</code><span>&#65292;&#20877;&#20915;&#23450;&#26159;&#21542;&#20351;&#29992; </span><code>NSMenu.popUpContextMenu</code><span> &#31561; AppKit API &#20027;&#21160;&#23637;&#31034;&#33756;&#21333;&#12290;</span></p><blockquote><p><span>&#26412;&#25991;&#20877;&#27425;&#20307;&#29616;&#20102; SwiftUI &#30340;&#19968;&#20010;&#29616;&#23454;&#38382;&#39064;&#65306;&#24456;&#22810;&#30475;&#20284;&#31616;&#21333;&#30340;&#20132;&#20114;&#25511;&#21046;&#65292;&#19968;&#26086;&#36229;&#20986;&#31995;&#32479; modifier &#26292;&#38706;&#30340;&#33021;&#21147;&#65292;&#20173;&#28982;&#38656;&#35201;&#29702;&#35299;&#24213;&#23618; AppKit / UIKit &#25165;&#33021;&#30495;&#27491;&#35299;&#20915;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-06"><span>&#35299;&#26512; UIPortalView&#65306;&#20174;&#35270;&#22270;&#23454;&#26102;&#25237;&#24433;&#21040;&#27969;&#20307;&#29627;&#29827;&#29305;&#25928; (_UIPortalView: From Live Mirroring to Liquid Glass-Style Effects)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; &#20998;&#20139;&#20102; UIKit &#20013;&#19968;&#20010;&#26377;&#36259;&#30340;&#31169;&#26377;&#32452;&#20214; </span><code>_UIPortalView</code><span>&#12290;&#23427;&#30001; </span><code>CAPortalLayer</code><span> &#25903;&#25345;&#65292;&#21487;&#20197;&#25226;&#26576;&#20010; </span><code>sourceView</code><span> &#30340;&#28210;&#26579;&#32467;&#26524;&#23454;&#26102;&#25237;&#23556;&#21040;&#23631;&#24149;&#19978;&#30340;&#21478;&#19968;&#20010;&#20301;&#32622;&#65292;&#32780;&#19981;&#38656;&#35201;&#22797;&#21046;&#19968;&#20221; View &#23618;&#32423;&#65292;&#20063;&#19981;&#38656;&#35201;&#21453;&#22797;&#29983;&#25104; snapshot&#12290;&#30456;&#27604;&#38745;&#24577;&#24555;&#29031;&#65292;Portal &#26356;&#20687;&#26159;&#21512;&#25104;&#23618;&#19978;&#30340;&#8220;&#23454;&#26102;&#31383;&#21475;&#8221;&#65306;&#28304;&#35270;&#22270;&#20173;&#28982;&#26159;&#21807;&#19968;&#29366;&#24577;&#26469;&#28304;&#65292;&#32780;&#25991;&#26412;&#12289;&#21160;&#30011;&#12289;&#24067;&#23616;&#25110;&#23376;&#35270;&#22270;&#21464;&#21270;&#37117;&#21487;&#20197;&#21516;&#27493;&#21453;&#26144;&#21040;&#21478;&#19968;&#22788;&#26174;&#31034;&#12290;</span></p><p><span>&#25991;&#31456;&#36824;&#25226; </span><code>_UIPortalView</code><span> &#21644; Liquid Glass &#25928;&#26524;&#32852;&#31995;&#36215;&#26469;&#65306;&#36890;&#36807; </span><code>matchesPosition</code><span>&#12289;&#35009;&#21098;&#12289;&#20559;&#31227;&#21644; 3D transform&#65292;&#21487;&#20197;&#23454;&#29616;&#23454;&#26102;&#38236;&#20687;&#12289;&#21453;&#23556;&#12289;&#38236;&#22836;&#12289;&#20849;&#20139;&#32972;&#26223;&#21644;&#36793;&#32536;&#25197;&#26354;&#31561;&#25928;&#26524;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-07"><span>&#25484;&#25511; SwiftUI &#24037;&#20855;&#26639;&#26032; API (Taking control of toolbar items in SwiftUI)</span></a></strong></h3><p><span>WWDC 26 &#24102;&#26469;&#30340;&#26032; SwiftUI Toolbar API&#65292;&#35753;&#31995;&#32479;&#33258;&#36866;&#24212;&#21644;&#24320;&#21457;&#32773;&#26174;&#24335;&#25511;&#21046;&#20043;&#38388;&#21462;&#24471;&#20102;&#26356;&#22909;&#30340;&#24179;&#34913;&#12290;</span><a href="https://x.com/mecid"><span>Majid Jabrayilov</span></a><span> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#20171;&#32461;&#20102;&#20960;&#39033;&#26032;&#30340;&#25511;&#21046;&#33021;&#21147;&#65306;&#36890;&#36807; </span><code>visibilityPriority</code><span> &#25351;&#23450; toolbar item &#30340;&#26174;&#31034;&#20248;&#20808;&#32423;&#65292;&#29992; </span><code>ToolbarOverflowMenu</code><span> &#26126;&#30830;&#21019;&#24314;&#25240;&#21472;&#33756;&#21333;&#65292;&#20511;&#21161; </span><code>.topBarPinnedTrailing</code><span> &#23558;&#37325;&#35201;&#25805;&#20316;&#22266;&#23450;&#22312;&#39030;&#37096;&#26639;&#23614;&#37096;&#65292;&#20197;&#21450;&#20351;&#29992; </span><code>toolbarMinimizeBehavior</code><span> &#25511;&#21046;&#23548;&#33322;&#26639;&#12289;&#26631;&#31614;&#26639;&#12289;&#24213;&#37096;&#26639;&#31561;&#22312;&#28378;&#21160;&#26102;&#30340;&#26368;&#23567;&#21270;&#34892;&#20026;&#12290;</span></p><p><span>&#21516;&#19968;&#32452; toolbar items &#22312; iOS&#12289;iPadOS &#21644; macOS &#19978;&#21487;&#33021;&#20250;&#26377;&#19981;&#21516;&#30340;&#23637;&#31034;&#26041;&#24335;&#12290;&#26032; API &#30340;&#20215;&#20540;&#22312;&#20110;&#65292;&#23427;&#20204;&#27809;&#26377;&#30772;&#22351; SwiftUI Toolbar &#21407;&#26412;&#30340;&#36328;&#24179;&#21488;&#33258;&#36866;&#24212;&#33021;&#21147;&#65292;&#21364;&#35753;&#24320;&#21457;&#32773;&#21487;&#20197;&#26356;&#26126;&#30830;&#22320;&#34920;&#36798;&#21738;&#20123;&#25805;&#20316;&#24212;&#35813;&#20248;&#20808;&#26174;&#31034;&#12289;&#21738;&#20123;&#25805;&#20316;&#21487;&#20197;&#20027;&#21160;&#25918;&#36827; overflow&#65292;&#20197;&#21450;&#24037;&#20855;&#26639;&#24212;&#35813;&#22914;&#20309;&#21709;&#24212;&#28378;&#21160;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-08"><span>iOS-Simulator-Camera-Extend&#65306;&#32473; iOS Simulator &#34917;&#19978;&#8220;&#30495;&#23454;&#21487;&#29992;&#30340;&#30456;&#26426;&#8221;</span></a></strong></h3><p><span>iOS Simulator &#19968;&#30452;&#27809;&#26377;&#30495;&#27491;&#30340;&#30456;&#26426;&#33021;&#21147;&#65292;&#28041;&#21450;&#25195;&#30721;&#12289;OCR&#12289;&#20154;&#33080;&#12289;&#35270;&#39057;&#36890;&#35805;&#12289;</span><code>AVCaptureSession</code><span> &#30340;&#21151;&#33021;&#65292;&#24448;&#24448;&#21482;&#33021;&#19978;&#30495;&#26426;&#25110;&#20889;&#27169;&#25311;&#36923;&#36753;&#12290;&#30001; </span><a href="https://x.com/GSYTech_CarGuo"><span>Shuyu Guo</span></a><span>&#8288; &#24320;&#21457;&#30340; iOS-Simulator-Camera-Extend &#22797;&#21051;&#20102; SimCam &#30340;&#26680;&#24515;&#24605;&#36335;&#65292;&#36890;&#36807; macOS &#31471;&#24103;&#28304;&#12289;Simulator &#20869; </span><code>DYLD_INSERT_LIBRARIES</code><span> hook &#19982; AVFoundation swizzle&#65292;&#35753;&#34987;&#27979; App &#26080;&#38656;&#25913;&#20195;&#30721;&#12289;&#26080;&#38656;&#25442; bundle id&#65292;&#23601;&#33021;&#22312;&#27169;&#25311;&#22120;&#37324;&#25343;&#21040; Mac &#25668;&#20687;&#22836;&#12289;&#26700;&#38754;&#12289;&#22270;&#29255;&#12289;&#35270;&#39057;&#21644;&#20108;&#32500;&#30721;&#30011;&#38754;&#12290;</span></p><p><span>&#26356;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#23427;&#36824;&#25552;&#20379;&#20102;&#21478;&#19968;&#26465; CMIO System Extension &#38142;&#36335;&#65292;&#35753; QuickTime&#12289;FaceTime&#12289;Zoom&#12289;OBS &#31561; macOS &#24212;&#29992;&#20063;&#33021;&#30475;&#21040;&#19968;&#21488; SimCam Virtual Camera&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;&#21516;&#19968;&#20221;&#24103;&#28304;&#26082;&#21487;&#20197;&#21890;&#32473; iOS Simulator &#37324;&#30340; App&#65292;&#20063;&#21487;&#20197;&#20316;&#20026; macOS &#34394;&#25311;&#25668;&#20687;&#22836;&#20351;&#29992;&#65292;&#23545;&#30456;&#26426;&#30456;&#20851;&#21151;&#33021;&#30340;&#35843;&#35797;&#12289;&#28436;&#31034;&#21644;&#33258;&#21160;&#21270;&#27979;&#35797;&#37117;&#24456;&#23454;&#29992;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #141]]></title><description><![CDATA[Is Anyone Else Excited by Swift&#8217;s Progress as a Language?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 22 Jun 2026 12:02:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1E-5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1E-5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1E-5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:205812,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/203025332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1E-5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@guillealvarez?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Guille &#193;lvarez</a><span> on </span><a href="https://unsplash.com/photos/people-jumping-on-shore-front-of-golden-hour-IcI3FizU9Cw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Is Anyone Else Excited by Swift&#8217;s Progress as a Language?</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-141/">Read on web &#8594;</a></p><p><span>Last week, a Reddit post titled &#8220;</span><a href="https://www.reddit.com/r/swift/comments/1u5skay/is_anyone_else_excited_by_swift_progress_as_the/"><span>Is anyone else excited by Swift progress as the language?</span></a><span>&#8288;&#8221; sparked a lively discussion. At WWDC 2026, Apple made it clear that Swift is now being used in key WebKit components, the QUIC networking stack, font rendering, drivers, and firmware&#8212;and, as the original poster claimed, it has started making its way into the core operating system kernel beginning with the 27 releases. The original poster saw this as Apple finally delivering on the promise it made in 2014 when it introduced Swift as a &#8220;high-level systems programming language.&#8221; The discussion soon expanded beyond whether that promise had been fulfilled to topics such as cross-platform support, language governance, the tooling experience, and whether Swift is becoming too large and ambitious.</span></p><p><span>Despite its remaining shortcomings, I still appreciate the progress Swift has made over the years. This week&#8217;s recommendations happen to offer several different perspectives on that progress: Swift 6.4 continues to fill in practical gaps in the concurrency model; KernelKit reveals the infrastructure Apple is laying for Swift in the kernel; and SwiftOS demonstrates Embedded Swift taking on an entire operating system and real-world service workloads. Swift&#8217;s progress is no longer measured only by the number of language features it has gained, but also by the growing range of work it can handle&#8212;and many of those use cases are no longer merely experimental.</span></p><p><span>Personally, since Swift 6, I have tried to adopt new language features wherever possible. For new projects, I have already raised the minimum required Swift compiler version to 6.2, and as my understanding deepens, I may raise it further. Some features involving concurrency, ownership, and isolation can feel awkward at first. Once their design goals become clear, however, they often turn out not to increase cognitive load, but to reduce it: correctness that once depended on conventions, comments, and developer experience can now be expressed as constraints the compiler is able to verify. The result is code that is easier to reason about, clearer in intent, and able to prevent many safety issues before it ever runs.</span></p><p><span>In the age of AI, a language&#8217;s ergonomic advantages may no longer determine adoption as decisively as they once did. As the cost of generating code falls, the real differentiators are more likely to be the ecosystem, tooling, available deployment targets, and whether the compiler can provide consistently reliable feedback. But that does not make language design less important&#8212;it simply changes how its value appears. As AI participates in writing more of our code, strong type systems, explicit ownership semantics, and strict concurrency checking become machine-verifiable guardrails. AI can produce code faster; the language and compiler help us determine which of that code deserves to be trusted.</span></p><p><span>Swift has always occupied a somewhat contradictory position. The Apple ecosystem gives it a large, stable field of application, yet it has also caused the language to be seen for years as something that &#8220;belongs only to Apple.&#8221; That ecosystem is both the hardest boundary for Swift to cross as it expands outward and the solid foundation that ensures continued investment, steady evolution, and protection from fading into irrelevance. Today, developments such as the official Android SDK, the WebAssembly SDK, and the Windows Working Group suggest that this boundary is gradually moving outward. Of course, tooling, package ecosystems, and the overall developer experience on non-Apple platforms still have a long way to go.</span></p><p><span>Does Swift still make me feel excited? Perhaps not exactly. But I genuinely enjoy where the language is today. Compared with the grand vision of a decade ago, I prefer the current pace: turning those promises into engineering reality, one step at a time.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-140/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-size-class-to-available-space/?utm_source=fatbobman%20weekly%20issue%20141&amp;utm_medium=web"><span>From Size Class to Available Space: Is horizontalSizeClass Still Reliable?</span></a></strong></h3><p><span>Starting with WWDC 26, iPhone apps mirrored to a Mac through iPhone Mirroring will support freely resizable windows. At the same time, iPhone-only apps running on iPad will also enter a variable-size environment. The impact of this update goes far beyond simply allowing iPhone apps to resize. It is changing how many developers have long understood the layout system. Traits that were once commonly used as the basis for layout decisions, such as </span><code>horizontalSizeClass</code><span>, are no longer suitable as the primary indicator of window width. So, is this change a sudden shift in direction, or the inevitable result of Apple&#8217;s years-long evolution of its layout system? This article explores that question.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-01"><span>Swift 6.4: What&#8217;s New in Concurrency</span></a></strong></h3><p><span>In this article, </span><a href="https://x.com/twannl"><span>Antoine van der Lee</span></a><span>&#8288; reviews a series of improvements Swift 6.4 brings to concurrency, including support for asynchronous cleanup in </span><code>defer</code><span>, cancellation shields that ensure critical cleanup or rollback operations can finish, warnings for ignored throwing </span><code>Task</code><span> instances, and typed error support for </span><code>Task</code><span>. In addition, </span><code>Result</code><span> can now directly wrap asynchronous throwing operations, while </span><code>~Sendable</code><span> and the </span><code>weak let</code><span> introduced in Swift 6.3 make the modeling of </span><code>Sendable</code><span> types more precise.</span></p><p><span>Compared with the more sweeping changes made to the concurrency model before Swift 6.2, these additions introduce relatively little new cognitive overhead. Instead, they refine the existing model and address practical engineering concerns involving cleanup, cancellation, error handling, and type modeling.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-02"><span>Apple Internals: Swift in the Kernel</span></a></strong></h3><p><span>Swift has now been around for more than a decade. As the creator of the language, has Apple begun using it to develop operating system kernels? Josh Maine of </span><a href="https://x.com/calif_io"><span>Calif</span></a><span> analyzed the macOS 27 and iOS 27 kernelcaches, along with the Xcode 27 Beta toolchain, and discovered that Apple has added an internal SDK called KernelKit, separate Mach-O platform identifiers for different operating systems, and an Embedded Swift runtime statically linked into a macOS kernel extension.</span></p><p><span>However, this does not mean that XNU is being rewritten in Swift. At present, Swift appears only at the kernel-extension layer. The runtime included in macOS is not yet referenced by any other component, while iOS has so far completed only the platform and toolchain groundwork. The infrastructure looks more like Apple laying down the toolchain, runtime, and linking environment before introducing actual Swift kernel components. In any case, it brings us one step closer to seeing real kernel components written in Swift.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-03"><span>Touch to Pixels: UI Pipeline Internals on iOS</span></a></strong></h3><p><span>What exactly happens inside the system after you tap an iOS interface but before the pixels on the screen change? Starting with a single touch event, </span><a href="https://x.com/jacobtechtavern"><span>Jacob Bartlett</span></a><span>&#8288; follows the entire journey through the touchscreen hardware, XNU, IOKit, backboardd, the app&#8217;s Run Loop, UIKit, and Core Animation. He traces how the event reaches our code, and how the resulting UI update passes through the Render Server, GPU, and frame buffer before finally becoming pixels on the display. Understanding this complete journey from Touch to Pixels not only gives us a clearer mental model of the iOS UI system, but also helps when diagnosing common performance issues such as main-thread blocking, stuttering animations, and dropped frames.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-04"><span>Dynamic Text in SwiftUI</span></a></strong></h3><p><span>Imagine an app with a global preference that determines whether every screen displays a user&#8217;s full name or nickname. The most direct approach is to add a conditional check everywhere a username appears, but the entire preference breaks down as soon as one new feature forgets to handle it. </span><a href="https://mastodon.social/@DLX"><span>Robb B&#246;hnke</span></a><span> solves this by using a BCP 47 private-use subtag to encode the preference into </span><code>Locale</code><span>, then reading it through a custom </span><code>FormatStyle</code><span> when </span><code>Text</code><span> is actually rendered. This approach works around SwiftUI&#8217;s lack of a dynamic </span><code>Text</code><span> initializer and turns logic that could easily be forgotten at individual call sites into application-wide default behavior.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-05"><span>SwiftUI SensoryFeedback Cache Key Pitfall: Do Not Store Continuous Values</span></a></strong></h3><p><span>Can dynamically adjusting haptic feedback intensity with a Slider in SwiftUI really cause memory usage to grow rapidly? It sounds surprising, but the issue genuinely exists from iOS 17 through iOS 26. </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> discovered that the internal implementation in these versions included continuous values such as </span><code>intensity</code><span> in the feedback generator&#8217;s cache key. Every tiny change in intensity could therefore correspond to a new </span><code>UIImpactFeedbackGenerator</code><span> instance, causing the cache to grow continuously.</span></p><p><span>Kyle filed an FB late last year and was notified this June that the issue had been fixed. Rather than patching the problem by introducing a cache-specific key, iOS 27 redraws the model boundary: it completely separates the &#8220;stable identity&#8221; represented by </span><code>FeedbackType</code><span> from the per-play dynamic parameters stored in the new </span><code>Payload</code><span>. The public API remains unchanged, but the cache behavior is corrected at the data-model level.</span></p><blockquote><p><span>What makes this fix worth studying is not merely that it resolves the memory-growth issue, but that it demonstrates an important principle of API design: stable information describing an object&#8217;s identity should not be mixed with dynamic parameters that affect only a single operation. It also reminds us that simply conforming to </span><code>Hashable</code><span> does not make a type inherently suitable for use as a cache key. Rather than repeatedly excluding exceptional fields at the point of use, drawing clear semantic boundaries in the data model is usually the more reliable design.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-06"><span>Architecting a Conversion Engine in Swift</span></a></strong></h3><p><span>When an application needs to convert among formats such as Markdown, HTML, rich text, and PDF, how can it prevent conversion logic from growing quadratically as more formats are added? </span><a href="https://bsky.app/profile/arthurvansiclen.com"><span>Arthur Van Siclen</span></a><span> explains the solution he developed for Minimal: introduce an Intermediate Representation, or IR, so that each format only needs its own Parser and Renderer. With six formats, this reduces the number of conversion relationships from 30 to 12.</span></p><p><span>Its treatment of lossy conversion is particularly worth learning from. Different formats do not have equivalent expressive capabilities, so Minimal uses </span><code>Concession</code><span> to explicitly record formatting that was downgraded, content that was dropped, or data that was truncated during conversion, rather than pretending that every conversion can be lossless.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-07"><span>SwiftOS: Building a Real Operating System with Embedded Swift</span></a></strong></h3><p><span>SwiftOS is a 64-bit ARM operating system written almost entirely from scratch in Embedded Swift. Its author, </span><a href="https://www.linkedin.com/in/andrey-sapunov/"><span>Andrey Sapunov</span></a><span>, began with a straightforward idea: rather than learning operating-system concepts only from books, why not build one and truly understand how kernels, memory, processes, and devices work together? His choice of Swift was not merely a matter of language preference. He wanted to preserve predictable code generation and low-level control while using Swift&#8217;s type system, ownership model, and modern engineering tools to make systems code safer and easier to express.</span></p><p><span>SwiftOS follows a distinctly modern systems architecture: AArch64, MMU-based process address-space isolation, a custom syscall ABI, a capability-oriented authorization model, static linking, a signed read-only base image, and a native Swift userland. It already includes an in-kernel TCP/IP stack, can run nginx and Node.js, and is deployed on a real Hetzner Cloud ARM instance&#8212;the project&#8217;s website is hosted by SwiftOS itself.</span></p><blockquote><p><span>We may still need more time before Swift is widely used within Apple&#8217;s operating system kernels. But SwiftOS proves at least one thing: Embedded Swift is no longer limited to firmware and bare-metal examples. It is capable of supporting an operating system with process isolation, user-space programs, a network stack, and real service workloads.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-08"><span>Loupe: Giving AI Agents Runtime Evidence for Native Apple UIs</span></a></strong></h3><p><span>Loupe, created by </span><a href="https://www.linkedin.com/in/won-heo-5a0497135/"><span>Won Heo</span></a><span>, is a runtime diagnostics and E2E verification tool for Apple platforms. It is particularly useful when AI coding agents such as Codex and Claude Code participate in native UI development. Loupe does not replace xcodebuild, XCTest, or other tools responsible for building and testing an application. Instead, by injecting or linking a runtime into a debug build, it adds a runtime UI evidence layer on top of them. From the app that is actually running, it can collect UIKit and AppKit view structures, accessibility information, screenshots, logs, URLSession network activity, and state such as Defaults and Feature Flags, then expose querying and auditing capabilities through its CLI.</span></p><p><span>An agent can begin with a compact observation of the UI, inspect specific nodes in greater detail as needed, perform simulator-visible actions such as </span><code>tap</code><span>, </span><code>swipe</code><span>, </span><code>drag</code><span>, and </span><code>type</code><span>, and record before-and-after snapshots, diffs, and traces. It can also make probe-like runtime changes to selected UIKit properties and constraints, quickly verify whether an adjustment works, and then return to the source code to implement the actual fix. This turns questions such as &#8220;Does it look right?&#8221;, &#8220;Does the interaction work?&#8221;, and &#8220;Has the layout drifted?&#8221; from screenshot-driven guesswork into a reviewable and reproducible chain of evidence.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>Swift &#36824;&#35753;&#20320; Excited &#21527;&#65311;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-141/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#21608;&#65292;Reddit &#19978;&#19968;&#31687;&#39064;&#20026;&#12298;</span><a href="https://www.reddit.com/r/swift/comments/1u5skay/is_anyone_else_excited_by_swift_progress_as_the/"><span>Is anyone else excited by Swift progress as the language?</span></a><span>&#12299;&#30340;&#24086;&#23376;&#24341;&#21457;&#20102;&#19981;&#23569;&#35752;&#35770;&#12290;WWDC 2026 &#19978;&#65292;Apple &#26126;&#30830;&#34920;&#31034;&#65292;Swift &#24050;&#34987;&#29992;&#20110; WebKit &#20851;&#38190;&#32452;&#20214;&#12289;QUIC &#32593;&#32476;&#26632;&#12289;&#23383;&#20307;&#28210;&#26579;&#12289;&#39537;&#21160;&#19982;&#22266;&#20214;&#12290;&#21457;&#24086;&#32773;&#25454;&#27492;&#35748;&#20026;&#65292;Swift &#27491;&#22312;&#21521;&#26680;&#24515;&#25805;&#20316;&#31995;&#32479;&#20869;&#26680;&#36808;&#36827;&#65292;&#24182;&#23558;&#36825;&#19968;&#24149;&#35270;&#20026; 2014 &#24180;&#8221;&#39640;&#32423;&#31995;&#32479;&#32534;&#31243;&#35821;&#35328;&#8221;&#25215;&#35834;&#30340;&#20817;&#29616;&#12290;&#35780;&#35770;&#21306;&#30340;&#35752;&#35770;&#21017;&#24456;&#24555;&#20174;&#8220;&#26159;&#21542;&#20817;&#29616;&#20102;&#25215;&#35834;&#8221;&#65292;&#24310;&#20280;&#21040;&#36328;&#24179;&#21488;&#25903;&#25345;&#12289;&#35821;&#35328;&#27835;&#29702;&#12289;&#24037;&#20855;&#38142;&#20307;&#39564;&#65292;&#20197;&#21450; Swift &#26159;&#21542;&#27491;&#22312;&#21464;&#24471;&#36807;&#20110;&#24222;&#22823;&#31561;&#35805;&#39064;&#12290;</span></p><p><span>&#23613;&#31649;&#38382;&#39064;&#20381;&#28982;&#19981;&#23569;&#65292;&#25105;&#20173;&#28982;&#24456;&#27427;&#36175; Swift &#36825;&#20123;&#24180;&#30340;&#36827;&#23637;&#12290;&#26412;&#26399;&#25512;&#33616;&#30340;&#20869;&#23481;&#20063;&#24688;&#22909;&#25552;&#20379;&#20102;&#20960;&#20010;&#19981;&#21516;&#30340;&#35266;&#23519;&#20999;&#38754;&#65306;Swift 6.4 &#32487;&#32493;&#34917;&#40784;&#24182;&#21457;&#27169;&#22411;&#20013;&#30340;&#24037;&#31243;&#32454;&#33410;&#65292;KernelKit &#23637;&#31034;&#20102; Apple &#20026;&#20869;&#26680; Swift &#38138;&#35774;&#30340;&#22522;&#30784;&#35774;&#26045;&#65292;SwiftOS &#21017;&#35753; Embedded Swift &#25215;&#25285;&#36215;&#19968;&#20010;&#23436;&#25972;&#25805;&#20316;&#31995;&#32479;&#19982;&#30495;&#23454;&#26381;&#21153;&#36127;&#36733;&#12290;Swift &#30340;&#36827;&#27493;&#24050;&#19981;&#21482;&#20307;&#29616;&#20026;&#35821;&#35328;&#29305;&#24615;&#36234;&#26469;&#36234;&#22810;&#65292;&#26356;&#20307;&#29616;&#22312;&#23427;&#33021;&#22815;&#32988;&#20219;&#30340;&#24037;&#20316;&#31181;&#31867;&#19981;&#26029;&#22686;&#21152;&#65292;&#32780;&#19988;&#20854;&#20013;&#19981;&#23569;&#24050;&#32463;&#36208;&#20986;&#20102;&#23454;&#39564;&#38454;&#27573;&#12290;</span></p><p><span>&#23601;&#25105;&#20010;&#20154;&#32780;&#35328;&#65292;&#20174; Swift 6 &#24320;&#22987;&#65292;&#25105;&#20960;&#20046;&#37117;&#22312;&#23613;&#21487;&#33021;&#22320;&#20351;&#29992;&#26032;&#30340;&#35821;&#35328;&#33021;&#21147;&#12290;&#22312;&#26032;&#39033;&#30446;&#20013;&#65292;&#25105;&#24050;&#32463;&#23558; Swift &#32534;&#35793;&#22120;&#30340;&#26368;&#20302;&#29256;&#26412;&#35201;&#27714;&#35774;&#32622;&#20026; 6.2&#65307;&#38543;&#30528;&#29702;&#35299;&#19981;&#26029;&#28145;&#20837;&#65292;&#26410;&#26469;&#21487;&#33021;&#36824;&#20250;&#32487;&#32493;&#25552;&#39640;&#12290;&#19968;&#20123;&#28041;&#21450;&#24182;&#21457;&#12289;&#25152;&#26377;&#26435;&#21644;&#38548;&#31163;&#30340;&#29305;&#24615;&#65292;&#21021;&#30475;&#26102;&#30830;&#23454;&#26377;&#20123;&#25303;&#21475;&#65292;&#20294;&#30495;&#27491;&#29702;&#35299;&#20854;&#35774;&#35745;&#30446;&#26631;&#21518;&#24448;&#24448;&#20250;&#21457;&#29616;&#65306;&#23427;&#20204;&#19981;&#26159;&#22312;&#22686;&#21152;&#24515;&#26234;&#36127;&#25285;&#65292;&#32780;&#26159;&#22312;&#25226;&#36807;&#21435;&#20381;&#36182;&#32422;&#23450;&#12289;&#27880;&#37322;&#21644;&#32463;&#39564;&#32500;&#25345;&#30340;&#27491;&#30830;&#24615;&#65292;&#36716;&#21464;&#20026;&#32534;&#35793;&#22120;&#21487;&#20197;&#26816;&#26597;&#30340;&#32422;&#26463;&#12290;&#20195;&#30721;&#22240;&#27492;&#26356;&#23481;&#26131;&#25512;&#29702;&#65292;&#24847;&#22270;&#20063;&#26356;&#21152;&#28165;&#26970;&#65292;&#35768;&#22810;&#23433;&#20840;&#38382;&#39064;&#21017;&#22312;&#36816;&#34892;&#20043;&#21069;&#23601;&#34987;&#25377;&#20102;&#19979;&#26469;&#12290;</span></p><p><span>&#22312; AI &#26102;&#20195;&#65292;&#19968;&#38376;&#35821;&#35328;&#30340;&#20154;&#20307;&#24037;&#23398;&#20248;&#21183;&#65292;&#25110;&#35768;&#19981;&#20877;&#20687;&#36807;&#21435;&#37027;&#26679;&#21333;&#29420;&#20915;&#23450;&#24320;&#21457;&#32773;&#26159;&#21542;&#24895;&#24847;&#37319;&#29992;&#23427;&#8212;&#8212;&#29983;&#25104;&#20195;&#30721;&#30340;&#25104;&#26412;&#19979;&#38477;&#21518;&#65292;&#30495;&#27491;&#25289;&#24320;&#24046;&#36317;&#30340;&#26356;&#21487;&#33021;&#26159;&#29983;&#24577;&#12289;&#24037;&#20855;&#38142;&#12289;&#21487;&#37096;&#32626;&#30340;&#24179;&#21488;&#65292;&#20197;&#21450;&#32534;&#35793;&#22120;&#33021;&#21542;&#25345;&#32493;&#25552;&#20379;&#21487;&#38752;&#21453;&#39304;&#12290;&#20294;&#35821;&#35328;&#35774;&#35745;&#30340;&#37325;&#35201;&#24615;&#24182;&#26410;&#22240;&#27492;&#20943;&#24369;&#65292;&#21453;&#32780;&#25442;&#20102;&#19968;&#31181;&#26041;&#24335;&#20307;&#29616;&#65306;&#24403;&#36234;&#26469;&#36234;&#22810;&#20195;&#30721;&#30001; AI &#21442;&#19982;&#29983;&#25104;&#26102;&#65292;&#24378;&#31867;&#22411;&#31995;&#32479;&#12289;&#26126;&#30830;&#30340;&#25152;&#26377;&#26435;&#35821;&#20041;&#21644;&#20005;&#26684;&#30340;&#24182;&#21457;&#26816;&#26597;&#65292;&#37117;&#20250;&#25104;&#20026;&#21487;&#26426;&#22120;&#39564;&#35777;&#30340;&#25252;&#26639;&#12290;AI &#21487;&#20197;&#26356;&#24555;&#22320;&#20135;&#29983;&#20195;&#30721;&#65292;&#32780;&#35821;&#35328;&#21644;&#32534;&#35793;&#22120;&#36127;&#36131;&#21578;&#35785;&#25105;&#20204;&#65292;&#21738;&#20123;&#20195;&#30721;&#20540;&#24471;&#20449;&#20219;&#12290;</span></p><p><span>Swift &#30340;&#22788;&#22659;&#20063;&#22987;&#32456;&#24102;&#30528;&#19968;&#31181;&#30683;&#30462;&#12290;Apple &#29983;&#24577;&#20026;&#23427;&#25552;&#20379;&#20102;&#31283;&#23450;&#19988;&#24222;&#22823;&#30340;&#24212;&#29992;&#22330;&#26223;&#65292;&#21364;&#20063;&#38271;&#26399;&#35753;&#22806;&#30028;&#23558;&#20854;&#35270;&#20026;&#19968;&#38376;&#8220;&#21482;&#23646;&#20110; Apple&#8221;&#30340;&#35821;&#35328;&#12290;&#36825;&#20010;&#29983;&#24577;&#26082;&#26159; Swift &#21521;&#22806;&#25193;&#24352;&#26102;&#26368;&#38590;&#36328;&#36234;&#30340;&#36793;&#30028;&#65292;&#20063;&#26159;&#23427;&#33021;&#22815;&#24471;&#21040;&#38271;&#26399;&#25237;&#20837;&#12289;&#31283;&#27493;&#28436;&#36827;&#65292;&#19981;&#33267;&#20110;&#36731;&#26131;&#34987;&#26102;&#20195;&#28120;&#27760;&#30340;&#22362;&#23454;&#21518;&#30462;&#12290;&#22914;&#20170;&#65292;&#23448;&#26041; Android SDK&#12289;WebAssembly SDK &#21644; Windows &#24037;&#20316;&#32452;&#31561;&#36827;&#23637;&#34920;&#26126;&#65292;&#36825;&#26465;&#36793;&#30028;&#27491;&#22312;&#36880;&#28176;&#21521;&#22806;&#31227;&#21160;&#65307;&#24403;&#28982;&#65292;&#38750; Apple &#24179;&#21488;&#19978;&#30340;&#24037;&#20855;&#38142;&#12289;&#21253;&#29983;&#24577;&#21644;&#24320;&#21457;&#20307;&#39564;&#20173;&#26377;&#24456;&#38271;&#30340;&#36335;&#35201;&#36208;&#12290;</span></p><p><span>&#35201;&#35828; Swift &#29616;&#22312;&#26159;&#21542;&#20173;&#35753;&#25105;&#24863;&#21040; Excited&#65292;&#20498;&#20063;&#26410;&#24517;&#65307;&#20294;&#25105;&#30830;&#23454;&#24456; Enjoy &#23427;&#24403;&#21069;&#30340;&#29366;&#24577;&#12290;&#30456;&#27604;&#21313;&#24180;&#21069;&#30340;&#23439;&#22823;&#24895;&#26223;&#65292;&#25105;&#26356;&#21916;&#27426;&#20170;&#22825;&#36825;&#31181;&#25226;&#25215;&#35834;&#19968;&#28857;&#28857;&#21464;&#25104;&#24037;&#31243;&#29616;&#23454;&#30340;&#33410;&#22863;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-140/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-size-class-to-available-space/?utm_source=fatbobman%20weekly%20issue%20141&amp;utm_medium=web"><span>&#20174; Size Class &#21040;&#21487;&#29992;&#31354;&#38388;&#65292;horizontalSizeClass &#36824;&#21487;&#38752;&#21527;&#65311;</span></a></strong></h3><p><span>&#20174; WWDC 26 &#24320;&#22987;&#65292;iPhone &#24212;&#29992;&#22312; iPhone Mirroring &#21040; Mac &#26102;&#65292;&#20854;&#31383;&#21475;&#23610;&#23544;&#23558;&#25903;&#25345;&#33258;&#30001;&#35843;&#25972;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;iPhone-only &#24212;&#29992;&#22312; iPad &#19978;&#36816;&#34892;&#26102;&#65292;&#20063;&#20250;&#36827;&#20837;&#21487;&#21464;&#23610;&#23544;&#29615;&#22659;&#12290;&#36825;&#27425;&#26356;&#26032;&#24102;&#26469;&#30340;&#24433;&#21709;&#36828;&#19981;&#27490;&#8220;iPhone &#24212;&#29992;&#21487;&#20197;&#35843;&#25972;&#23610;&#23544;&#8221;&#36825;&#20040;&#31616;&#21333;&#12290;&#23427;&#27491;&#22312;&#25913;&#21464;&#35768;&#22810;&#24320;&#21457;&#32773;&#38271;&#26399;&#20197;&#26469;&#23545;&#24067;&#23616;&#31995;&#32479;&#30340;&#29702;&#35299;&#12290;&#19968;&#20123;&#36807;&#21435;&#24120;&#34987;&#29992;&#20316;&#24067;&#23616;&#20381;&#25454;&#30340; trait&#65292;&#20363;&#22914; </span><code>horizontalSizeClass</code><span> &#24050;&#19981;&#20877;&#36866;&#21512;&#20316;&#20026;&#31383;&#21475;&#23485;&#24230;&#30340;&#20027;&#35201;&#21028;&#26029;&#20381;&#25454;&#12290;&#37027;&#20040;&#65292;&#36825;&#31181;&#21464;&#21270;&#31350;&#31455;&#26159;&#19968;&#27425;&#31361;&#28982;&#20986;&#29616;&#30340;&#36716;&#21521;&#65292;&#36824;&#26159; Apple &#22810;&#24180;&#24067;&#23616;&#19979;&#30340;&#24517;&#28982;&#28436;&#36827;&#65311;&#26412;&#25991;&#23558;&#23545;&#27492;&#36827;&#34892;&#25506;&#35752;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-01"><span>Swift 6.4 &#24182;&#21457;&#26032;&#29305;&#24615; (Swift 6.4: What&#8217;s New in Concurrency)</span></a></strong></h3><p><a href="https://x.com/twannl"><span>Antoine van der Lee</span></a><span> &#22312;&#26412;&#25991;&#20013;&#26803;&#29702;&#20102; Swift 6.4 &#20026;&#24182;&#21457;&#32534;&#31243;&#24102;&#26469;&#30340;&#19968;&#31995;&#21015;&#25913;&#36827;&#65292;&#21253;&#25324;&#25903;&#25345;&#22312; defer &#20013;&#25191;&#34892;&#24322;&#27493;&#28165;&#29702;&#12289;&#36890;&#36807;&#21462;&#28040;&#23631;&#34109;&#30830;&#20445;&#20851;&#38190;&#30340;&#28165;&#29702;&#25110;&#22238;&#28378;&#25805;&#20316;&#24471;&#20197;&#23436;&#25104;&#12289;&#20026;&#34987;&#24573;&#30053;&#30340;&#21487;&#25243;&#38169; Task &#22686;&#21152;&#35686;&#21578;&#65292;&#20197;&#21450;&#20026; Task &#24341;&#20837;&#31867;&#22411;&#21270;&#38169;&#35823;&#25903;&#25345;&#12290;&#27492;&#22806;&#65292;Result &#29616;&#22312;&#21487;&#20197;&#30452;&#25509;&#23553;&#35013;&#24322;&#27493;&#21487;&#25243;&#20986;&#25805;&#20316;&#65292;~Sendable &#21644; Swift 6.3 &#24341;&#20837;&#30340; weak let &#20063;&#35753; Sendable &#31867;&#22411;&#30340;&#34920;&#36798;&#26356;&#21152;&#20934;&#30830;&#12290;</span></p><p><span>&#30456;&#36739;&#20110; Swift 6.2 &#20043;&#21069;&#23545;&#24182;&#21457;&#27169;&#22411;&#36739;&#20026;&#22823;&#20992;&#38420;&#26023;&#30340;&#35843;&#25972;&#65292;&#36825;&#20123;&#21464;&#21270;&#19981;&#20250;&#24102;&#26469;&#22826;&#22810;&#26032;&#30340;&#24515;&#26234;&#36127;&#25285;&#65292;&#26356;&#22810;&#26159;&#22312;&#29616;&#26377;&#27169;&#22411;&#20043;&#19978;&#34917;&#40784;&#32454;&#33410;&#65292;&#35299;&#20915;&#23454;&#38469;&#24037;&#31243;&#20013;&#28165;&#29702;&#12289;&#21462;&#28040;&#12289;&#38169;&#35823;&#22788;&#29702;&#21644;&#31867;&#22411;&#24314;&#27169;&#31561;&#26041;&#38754;&#30340;&#38382;&#39064;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-02"><span>&#25506;&#32034;&#33529;&#26524;&#31995;&#32479;&#20869;&#26680;&#20013;&#30340; Swift (Apple Internals: Swift in the Kernel)</span></a></strong></h3><p><span>Swift &#24050;&#32463;&#35806;&#29983;&#21313;&#20313;&#24180;&#12290;&#20316;&#20026;&#36825;&#38376;&#35821;&#35328;&#30340;&#21019;&#36896;&#32773;&#65292;&#33529;&#26524;&#26159;&#21542;&#24050;&#32463;&#24320;&#22987;&#23558;&#23427;&#29992;&#20110;&#25805;&#20316;&#31995;&#32479;&#20869;&#26680;&#30340;&#24320;&#21457;&#65311;&#26469;&#33258; </span><a href="https://x.com/calif_io"><span>Calif</span></a><span> &#30340; Josh Maine &#36890;&#36807;&#20998;&#26512; macOS 27&#12289;iOS 27 &#30340; kernelcache &#19982; Xcode 27 Beta &#24037;&#20855;&#38142;&#21457;&#29616;&#65292;Apple &#26032;&#22686;&#20102;&#21517;&#20026; KernelKit &#30340;&#20869;&#37096; SDK&#12289;&#23545;&#24212;&#19981;&#21516;&#31995;&#32479;&#30340; Mach-O &#24179;&#21488;&#26631;&#35782;&#65292;&#20197;&#21450;&#19968;&#22871;&#38745;&#24577;&#38142;&#25509;&#22312; macOS &#20869;&#26680;&#25193;&#23637;&#20013;&#30340; Embedded Swift &#36816;&#34892;&#26102;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;&#36825;&#24182;&#19981;&#24847;&#21619;&#30528; XNU &#27491;&#22312;&#34987; Swift &#37325;&#20889;&#12290;&#30446;&#21069;&#65292;Swift &#21482;&#20986;&#29616;&#22312;&#20869;&#26680;&#25193;&#23637;&#23618;&#65307;macOS &#20013;&#30340;&#36816;&#34892;&#26102;&#23578;&#26410;&#34987;&#20854;&#20182;&#32452;&#20214;&#23454;&#38469;&#35843;&#29992;&#65292;&#32780; iOS &#29616;&#38454;&#27573;&#20063;&#21482;&#26159;&#23436;&#25104;&#20102;&#24179;&#21488;&#21644;&#24037;&#20855;&#38142;&#23618;&#38754;&#30340;&#20934;&#22791;&#12290;&#25972;&#22871;&#22522;&#30784;&#35774;&#26045;&#26356;&#20687;&#26159; Apple &#22312;&#27491;&#24335;&#24341;&#20837; Swift &#20869;&#26680;&#32452;&#20214;&#20043;&#21069;&#65292;&#20808;&#34892;&#38138;&#35774;&#24037;&#20855;&#38142;&#12289;&#36816;&#34892;&#26102;&#19982;&#38142;&#25509;&#29615;&#22659;&#12290;&#26080;&#35770;&#22914;&#20309;&#65292;&#36825;&#24847;&#21619;&#30528;&#36317;&#31163;&#30495;&#27491;&#20351;&#29992; Swift &#32534;&#20889;&#20869;&#26680;&#32452;&#20214;&#21448;&#36817;&#20102;&#19968;&#27493;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-03"><span>&#20174;&#35302;&#25720;&#21040;&#20687;&#32032;&#65306;iOS &#28210;&#26579;&#31649;&#32447;&#24213;&#23618;&#25506;&#31192; (Touch to Pixels: UI Pipeline Internals on iOS)</span></a></strong></h3><p><span>&#24403;&#25163;&#25351;&#28857;&#20987; iOS &#30028;&#38754;&#21518;&#65292;&#21040;&#23631;&#24149;&#19978;&#30340;&#20687;&#32032;&#21457;&#29983;&#21464;&#21270;&#20043;&#21069;&#65292;&#31995;&#32479;&#20869;&#37096;&#31350;&#31455;&#32463;&#21382;&#20102;&#20160;&#20040;&#65311;</span><a href="https://x.com/jacobtechtavern"><span>Jacob Bartlett</span></a><span>&#8288; &#20174;&#19968;&#27425;&#35302;&#25720;&#20107;&#20214;&#20986;&#21457;&#65292;&#27839;&#30528;&#35302;&#25720;&#23631;&#30828;&#20214;&#12289;XNU&#12289;IOKit&#12289;backboardd&#12289;&#24212;&#29992; Run Loop&#12289;UIKit &#19982; Core Animation&#65292;&#19968;&#36335;&#36861;&#36394;&#20107;&#20214;&#22914;&#20309;&#25269;&#36798;&#25105;&#20204;&#30340;&#20195;&#30721;&#65292;&#20197;&#21450;&#30028;&#38754;&#26356;&#26032;&#22914;&#20309;&#32463;&#36807; Render Server&#12289;GPU &#21644;&#24103;&#32531;&#20914;&#21306;&#65292;&#26368;&#32456;&#36716;&#21270;&#20026;&#23631;&#24149;&#19978;&#30340;&#20687;&#32032;&#12290;&#20102;&#35299;&#36825;&#26465;&#20174; Touch &#21040; Pixels &#30340;&#23436;&#25972;&#38142;&#36335;&#65292;&#19981;&#20165;&#33021;&#24110;&#21161;&#25105;&#20204;&#24314;&#31435;&#23545; iOS UI &#31995;&#32479;&#30340;&#25972;&#20307;&#35748;&#35782;&#65292;&#20063;&#26377;&#21161;&#20110;&#20998;&#26512;&#20027;&#32447;&#31243;&#38459;&#22622;&#12289;&#21160;&#30011;&#21345;&#39039;&#21644;&#25481;&#24103;&#31561;&#24120;&#35265;&#30340;&#30028;&#38754;&#24615;&#33021;&#38382;&#39064;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-04"><span>SwiftUI &#21160;&#24577;&#25991;&#26412;&#28210;&#26579; (Dynamic Text in SwiftUI)</span></a></strong></h3><p><span>&#35774;&#24819;&#19968;&#20010;&#22330;&#26223;&#65306;&#24212;&#29992;&#37324;&#26377;&#19968;&#20010;&#20840;&#23616;&#24320;&#20851;&#65292;&#20915;&#23450;&#25152;&#26377;&#30028;&#38754;&#26174;&#31034;&#29992;&#25143;&#30340;&#20840;&#21517;&#36824;&#26159;&#26165;&#31216;&#12290;&#26368;&#30452;&#25509;&#30340;&#20570;&#27861;&#65292;&#26159;&#22312;&#27599;&#19968;&#22788;&#26174;&#31034;&#29992;&#25143;&#21517;&#30340;&#22320;&#26041;&#37117;&#21152;&#19978;&#21028;&#26029;&#65292;&#20294;&#21482;&#35201;&#26377;&#19968;&#20010;&#26032;&#21151;&#33021;&#24536;&#35760;&#22788;&#29702;&#65292;&#36825;&#20010;&#24320;&#20851;&#23601;&#20250;&#22833;&#25928;&#12290;</span><a href="https://mastodon.social/@DLX"><span>Robb B&#246;hnke</span></a><span> &#30340;&#35299;&#27861;&#26159;&#20511;&#29992; BCP 47 &#30340;&#31169;&#26377;&#23376;&#26631;&#31614;&#65292;&#23558;&#36825;&#39033;&#20559;&#22909;&#32534;&#30721;&#36827; </span><code>Locale</code><span>&#65292;&#20877;&#36890;&#36807;&#33258;&#23450;&#20041; </span><code>FormatStyle</code><span>&#65292;&#22312; </span><code>Text</code><span> &#30495;&#27491;&#28210;&#26579;&#26102;&#35835;&#21462;&#24182;&#36873;&#25321;&#23545;&#24212;&#30340;&#21517;&#31216;&#12290;&#36825;&#31181;&#20570;&#27861;&#32469;&#36807;&#20102; SwiftUI &#32570;&#23569;&#21160;&#24577; </span><code>Text</code><span> &#21021;&#22987;&#21270; API &#30340;&#38480;&#21046;&#65292;&#20063;&#25226;&#23481;&#26131;&#36951;&#28431;&#30340;&#35843;&#29992;&#31471;&#36923;&#36753;&#21464;&#25104;&#20102;&#24212;&#29992;&#33539;&#22260;&#20869;&#30340;&#40664;&#35748;&#34892;&#20026;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-05"><span>SwiftUI SensoryFeedback Cache Key &#32463;&#39564;&#25945;&#35757;&#65306;&#19981;&#35201;&#23384;&#20648;&#36830;&#32493;&#20540;</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#29992; Slider &#21160;&#24577;&#35843;&#25972;&#35302;&#35273;&#21453;&#39304;&#24378;&#24230;&#65292;&#31455;&#28982;&#21487;&#33021;&#23548;&#33268;&#20869;&#23384;&#24555;&#36895;&#22686;&#38271;&#65311;&#21548;&#36215;&#26469;&#19981;&#21487;&#24605;&#35758;&#65292;&#20294;&#36825;&#20010;&#38382;&#39064;&#30830;&#23454;&#23384;&#22312;&#20110; iOS 17 &#33267; iOS 26 &#20013;&#12290;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#21457;&#29616;&#65292;&#36825;&#20123;&#29256;&#26412;&#30340;&#20869;&#37096;&#23454;&#29616;&#23558; </span><code>intensity</code><span> &#36825;&#26679;&#30340;&#36830;&#32493;&#20540;&#32435;&#20837;&#20102;&#21453;&#39304;&#29983;&#25104;&#22120;&#30340;&#32531;&#23384;&#38190;&#12290;&#24378;&#24230;&#20540;&#30340;&#27599;&#19968;&#27425;&#32454;&#24494;&#21464;&#21270;&#65292;&#37117;&#21487;&#33021;&#23545;&#24212;&#19968;&#20010;&#26032;&#30340; </span><code>UIImpactFeedbackGenerator</code><span> &#23454;&#20363;&#65292;&#26368;&#32456;&#23548;&#33268;&#32531;&#23384;&#19981;&#26029;&#33192;&#32960;&#12290;</span></p><p><span>Kyle &#22312;&#21435;&#24180;&#24180;&#24213;&#25552;&#20132;&#20102; FB&#65292;&#24182;&#20110;&#20170;&#24180; 6 &#26376;&#25910;&#21040;&#38382;&#39064;&#24050;&#20462;&#22797;&#30340;&#36890;&#30693;&#12290;iOS 27 &#30340;&#35299;&#20915;&#26041;&#26696;&#24182;&#19981;&#26159;&#22686;&#21152;&#19968;&#20010;&#32531;&#23384;&#19987;&#29992; Key &#26469;&#25171;&#34917;&#19969;&#65292;&#32780;&#26159;&#37325;&#26032;&#21010;&#20998;&#27169;&#22411;&#36793;&#30028;&#65306;&#23558;&#20195;&#34920;&#8220;&#31283;&#23450;&#36523;&#20221;&#8221;&#30340; </span><code>FeedbackType</code><span>&#65292;&#19982;&#27599;&#27425;&#25773;&#25918;&#20351;&#29992;&#30340;&#21160;&#24577;&#21442;&#25968; </span><code>Payload</code><span> &#24443;&#24213;&#25286;&#24320;&#12290;&#20844;&#24320; API &#20445;&#25345;&#19981;&#21464;&#65292;&#32531;&#23384;&#36923;&#36753;&#21364;&#20174;&#25968;&#25454;&#27169;&#22411;&#23618;&#38754;&#24471;&#21040;&#20102;&#20462;&#27491;&#12290;</span></p><blockquote><p><span>&#36825;&#27425;&#20462;&#22797;&#20540;&#24471;&#20851;&#27880;&#30340;&#22320;&#26041;&#65292;&#19981;&#21482;&#26159;&#35299;&#20915;&#20102;&#20869;&#23384;&#22686;&#38271;&#38382;&#39064;&#65292;&#26356;&#20307;&#29616;&#20102; API &#35774;&#35745;&#20013;&#30340;&#19968;&#20010;&#37325;&#35201;&#21407;&#21017;&#65306;&#25551;&#36848;&#8220;&#23545;&#35937;&#36523;&#20221;&#8221;&#30340;&#31283;&#23450;&#20449;&#24687;&#65292;&#19981;&#24212;&#19982;&#21482;&#24433;&#21709;&#21333;&#27425;&#25805;&#20316;&#30340;&#21160;&#24577;&#21442;&#25968;&#28151;&#22312;&#19968;&#36215;&#12290;&#23427;&#20063;&#25552;&#37266;&#25105;&#20204;&#65292;&#19968;&#20010;&#31867;&#22411;&#21363;&#20351;&#28385;&#36275; </span><code>Hashable</code><span>&#65292;&#20063;&#19981;&#20195;&#34920;&#23427;&#22825;&#28982;&#36866;&#21512;&#20316;&#20026;&#32531;&#23384;&#38190;&#12290;&#30456;&#27604;&#22312;&#20351;&#29992;&#22788;&#19981;&#26029;&#25490;&#38500;&#29305;&#27530;&#23383;&#27573;&#65292;&#20174;&#25968;&#25454;&#27169;&#22411;&#23618;&#38754;&#21010;&#28165;&#35821;&#20041;&#36793;&#30028;&#65292;&#36890;&#24120;&#26159;&#26356;&#21487;&#38752;&#30340;&#35774;&#35745;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-06"><span>Swift &#26500;&#24314;&#25991;&#26723;&#36716;&#25442;&#24341;&#25806;&#30340;&#26550;&#26500;&#35774;&#35745; (Architecting a Conversion Engine in Swift)</span></a></strong></h3><p><span>&#24403;&#24212;&#29992;&#38656;&#35201;&#22312; Markdown&#12289;HTML&#12289;&#23500;&#25991;&#26412;&#12289;PDF &#31561;&#22810;&#31181;&#26684;&#24335;&#20043;&#38388;&#20114;&#30456;&#36716;&#25442;&#26102;&#65292;&#22914;&#20309;&#36991;&#20813;&#36716;&#25442;&#36923;&#36753;&#38543;&#30528;&#26684;&#24335;&#25968;&#37327;&#21576;&#24179;&#26041;&#32423;&#22686;&#38271;&#65311;</span><a href="https://bsky.app/profile/arthurvansiclen.com"><span>Arthur Van Siclen</span></a><span>&#8288; &#20171;&#32461;&#20102;&#20182;&#22312; Minimal &#20013;&#30340;&#35299;&#20915;&#26041;&#26696;&#65306;&#35774;&#35745;&#19968;&#22871;&#20013;&#38388;&#34920;&#31034; IR&#65292;&#35753;&#27599;&#31181;&#26684;&#24335;&#21482;&#38656;&#20998;&#21035;&#23454;&#29616; Parser &#21644; Renderer&#65292;&#20174;&#32780;&#23558;&#20845;&#31181;&#26684;&#24335;&#20043;&#38388;&#30340; 30 &#26465;&#36716;&#25442;&#20851;&#31995;&#20943;&#23569;&#20026; 12 &#26465;&#12290;</span></p><p><span>&#20854;&#20013;&#65292;&#23545;&#8220;&#26377;&#25439;&#36716;&#25442;&#8221;&#30340;&#22788;&#29702;&#23588;&#20854;&#20540;&#24471;&#20511;&#37492;&#12290;&#19981;&#21516;&#26684;&#24335;&#30340;&#34920;&#36798;&#33021;&#21147;&#24182;&#19981;&#23545;&#31561;&#65292;Minimal &#36890;&#36807; </span><code>Concession</code><span> &#26174;&#24335;&#35760;&#24405;&#36716;&#25442;&#36807;&#31243;&#20013;&#21457;&#29983;&#30340;&#26684;&#24335;&#38477;&#32423;&#12289;&#20869;&#23481;&#20002;&#24323;&#25110;&#25130;&#26029;&#65292;&#32780;&#19981;&#26159;&#20551;&#35774;&#25152;&#26377;&#26684;&#24335;&#20043;&#38388;&#37117;&#33021;&#26080;&#25439;&#36716;&#25442;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-07"><span>SwiftOS&#65306;&#29992; Embedded Swift &#20889;&#19968;&#20010;&#30495;&#27491;&#30340;&#25805;&#20316;&#31995;&#32479;</span></a></strong></h3><p><span>SwiftOS &#26159;&#19968;&#20010;&#20960;&#20046;&#23436;&#20840;&#20351;&#29992; Embedded Swift &#20174;&#38646;&#32534;&#20889;&#30340; 64 &#20301; ARM &#25805;&#20316;&#31995;&#32479;&#12290;&#20316;&#32773; </span><a href="https://www.linkedin.com/in/andrey-sapunov/"><span>Andrey Sapunov</span></a><span>&#8288; &#30340;&#20986;&#21457;&#28857;&#24456;&#26420;&#32032;&#65306;&#19982;&#20854;&#21482;&#20174;&#20070;&#26412;&#19978;&#29702;&#35299;&#25805;&#20316;&#31995;&#32479;&#65292;&#19981;&#22914;&#20146;&#25163;&#23454;&#29616;&#19968;&#20010;&#65292;&#30495;&#27491;&#24324;&#28165;&#20869;&#26680;&#12289;&#20869;&#23384;&#12289;&#36827;&#31243;&#19982;&#35774;&#22791;&#22914;&#20309;&#21327;&#20316;&#12290;&#36873;&#25321; Swift &#20063;&#19981;&#21482;&#26159;&#20986;&#20110;&#35821;&#35328;&#20559;&#22909;&#65292;&#32780;&#26159;&#24076;&#26395;&#22312;&#20445;&#25345;&#20195;&#30721;&#29983;&#25104;&#21487;&#39044;&#27979;&#21644;&#24213;&#23618;&#25511;&#21046;&#33021;&#21147;&#30340;&#21516;&#26102;&#65292;&#20511;&#21161; Swift &#30340;&#31867;&#22411;&#31995;&#32479;&#12289;&#25152;&#26377;&#26435;&#27169;&#22411;&#21644;&#29616;&#20195;&#24037;&#31243;&#24037;&#20855;&#65292;&#35753;&#31995;&#32479;&#20195;&#30721;&#26356;&#23433;&#20840;&#12289;&#26356;&#23481;&#26131;&#34920;&#36798;&#12290;</span></p><p><span>SwiftOS &#36873;&#25321;&#20102;&#19968;&#26465;&#39047;&#20026;&#29616;&#20195;&#30340;&#31995;&#32479;&#36335;&#32447;&#65306;AArch64&#12289;&#22522;&#20110; MMU &#30340;&#36827;&#31243;&#22320;&#22336;&#31354;&#38388;&#38548;&#31163;&#12289;&#33258;&#23450;&#20041; syscall ABI&#12289;&#33021;&#21147;&#23548;&#21521;&#30340;&#25480;&#26435;&#27169;&#22411;&#12289;&#38745;&#24577;&#38142;&#25509;&#12289;&#31614;&#21517;&#21482;&#35835;&#22522;&#30784;&#38236;&#20687;&#65292;&#20197;&#21450;&#21407;&#29983; Swift userland&#12290;&#23427;&#24050;&#32463;&#23454;&#29616;&#20102;&#20869;&#26680;&#24577; TCP/IP &#26632;&#65292;&#33021;&#22815;&#36816;&#34892; nginx &#21644; Node.js&#65292;&#24182;&#36816;&#34892;&#22312;&#30495;&#23454;&#30340; Hetzner Cloud ARM &#23454;&#20363;&#19978;&#8212;&#8212;&#39033;&#30446;&#23448;&#32593;&#23601;&#26159;&#30001; SwiftOS &#33258;&#24049;&#25176;&#31649;&#30340;&#12290;</span></p><blockquote><p><span>&#25110;&#35768;&#65292;&#25105;&#20204;&#36824;&#38656;&#35201;&#26356;&#22810;&#26102;&#38388;&#65292;&#25165;&#33021;&#30475;&#21040; Swift &#34987;&#22823;&#35268;&#27169;&#29992;&#20110;&#33529;&#26524;&#30340;&#31995;&#32479;&#20869;&#26680;&#12290;&#20294; SwiftOS &#33267;&#23569;&#35777;&#26126;&#20102;&#19968;&#20214;&#20107;&#65306;Embedded Swift &#24050;&#32463;&#19981;&#21482;&#33021;&#22815;&#32534;&#20889;&#22266;&#20214;&#21644;&#35064;&#26426;&#31034;&#20363;&#65292;&#23427;&#20063;&#36275;&#20197;&#25903;&#25745;&#19968;&#20010;&#25317;&#26377;&#36827;&#31243;&#38548;&#31163;&#12289;&#29992;&#25143;&#24577;&#31243;&#24207;&#12289;&#32593;&#32476;&#26632;&#21644;&#30495;&#23454;&#26381;&#21153;&#36127;&#36733;&#30340;&#25805;&#20316;&#31995;&#32479;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-08"><span>Loupe&#65306;&#20026; AI Agent &#34917;&#19978; Apple &#21407;&#29983; UI &#30340;&#36816;&#34892;&#26102;&#35777;&#25454;</span></a></strong></h3><p><span>Loupe &#26159;&#30001; </span><a href="https://www.linkedin.com/in/won-heo-5a0497135/"><span>Won Heo</span></a><span>&#8288; &#21457;&#36215;&#30340; Apple &#24179;&#21488;&#36816;&#34892;&#26102;&#35786;&#26029;&#19982; E2E &#39564;&#35777;&#24037;&#20855;&#65292;&#23588;&#20854;&#36866;&#21512; Codex&#12289;Claude Code &#36825;&#31867; AI Coding Agent &#21442;&#19982;&#21407;&#29983;&#30028;&#38754;&#24320;&#21457;&#26102;&#20351;&#29992;&#12290;&#23427;&#24182;&#19981;&#26367;&#20195; xcodebuild&#12289;XCTest &#25110;&#20854;&#20182;&#36127;&#36131;&#26500;&#24314;&#21644;&#27979;&#35797;&#30340;&#24037;&#20855;&#65292;&#32780;&#26159;&#36890;&#36807;&#21521;&#35843;&#35797;&#20013;&#30340; App &#27880;&#20837;&#25110;&#38142;&#25509;&#36816;&#34892;&#26102;&#65292;&#34917;&#19978;&#20854;&#21518;&#30340; UI &#35777;&#25454;&#23618;&#65306;&#20174;&#30495;&#27491;&#36816;&#34892;&#30340; App &#20013;&#37319;&#38598; UIKit/AppKit &#35270;&#22270;&#32467;&#26500;&#12289;&#21487;&#35775;&#38382;&#24615;&#20449;&#24687;&#12289;&#25130;&#22270;&#12289;&#26085;&#24535;&#12289;URLSession &#32593;&#32476;&#27963;&#21160;&#65292;&#20197;&#21450; Defaults&#12289;Feature Flags &#31561;&#29366;&#24577;&#65292;&#20877;&#36890;&#36807; CLI &#25552;&#20379;&#26597;&#35810;&#19982;&#23457;&#35745;&#33021;&#21147;</span></p><p><span>Agent &#21487;&#20197;&#20808;&#33719;&#21462;&#32039;&#20945;&#30340; UI &#35266;&#23519;&#32467;&#26524;&#65292;&#20877;&#25353;&#38656;&#28145;&#20837;&#26816;&#26597;&#20855;&#20307;&#33410;&#28857;&#65292;&#25191;&#34892; tap&#12289;swipe&#12289;drag&#12289;type &#31561;&#27169;&#25311;&#22120;&#21487;&#35265;&#25805;&#20316;&#65292;&#24182;&#35760;&#24405;&#25805;&#20316;&#21069;&#21518;&#30340;&#24555;&#29031;&#12289;&#24046;&#24322;&#19982; trace&#65307;&#23427;&#36824;&#21487;&#20197;&#23545;&#37096;&#20998; UIKit &#23646;&#24615;&#21644;&#32422;&#26463;&#36827;&#34892;&#36816;&#34892;&#26102;&#25506;&#38024;&#24335;&#20462;&#25913;&#65292;&#24555;&#36895;&#39564;&#35777;&#35843;&#25972;&#26159;&#21542;&#26377;&#25928;&#65292;&#20877;&#22238;&#21040;&#28304;&#30721;&#23436;&#25104;&#30495;&#27491;&#30340;&#20462;&#27491;&#12290;&#36825;&#35753;&#8220;&#30475;&#36215;&#26469;&#23545;&#19981;&#23545;&#12289;&#28857;&#36215;&#26469;&#36890;&#19981;&#36890;&#12289;&#24067;&#23616;&#26377;&#27809;&#26377;&#28418;&#31227;&#8221;&#19981;&#20877;&#21482;&#20381;&#36182;&#25130;&#22270;&#19982;&#29468;&#27979;&#65292;&#32780;&#26159;&#25104;&#20026;&#19968;&#26465;&#33021;&#22815;&#22797;&#26597;&#21644;&#30041;&#30165;&#30340;&#35777;&#25454;&#38142;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #140]]></title><description><![CDATA[WWDC 26: AI Watched It for You &#8212; Now What?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 15 Jun 2026 12:03:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XG78!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XG78!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XG78!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!XG78!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:87014,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/202066210?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XG78!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!XG78!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@zachmmalin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Zach M</a> on <a href="https://unsplash.com/photos/artificial-intelligence-concept-within-a-human-head-7F9PhBM1gFM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>WWDC 26: AI Watched It for You &#8212; Now What?</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-140/">Read on web &#8594;</a></p><p>With the rise of AI Agent workflows, many developers this year have started letting AI handle the summarizing and highlight-picking, absorbing WWDC announcements at a much faster pace. Apple has been accommodating too &#8212; releasing all Sessions, transcripts, and sample code at once, making it even easier for AI to process everything.</p><p>For me personally, what used to be a manual ritual of extracting <code>interface</code> files and comparing old and new APIs has become a single instruction in an Agent workflow. From a pure efficiency standpoint, that&#8217;s a real, tangible gain.</p><p>But information distilled at speed can&#8217;t always capture the nuance and precision that Apple engineers embed in a Session. Many Sessions are still worth sitting down with &#8212; carefully, even repeatedly.</p><p>AI accelerates how fast you acquire information. It doesn&#8217;t deepen how well you understand it. Information flowing into an AI&#8217;s context window is not the same as knowledge taking root in your own mind.</p><p>Your viewing habits can evolve with the times. Your standards for yourself shouldn&#8217;t.</p><p><a href="https://fatbobman.com/en/weekly/issue-139/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>WWDC 2026</strong></h2><h3><strong>Roundups</strong></h3><ul><li><p><strong>WWDC 26 Group Lab Q&amp;A</strong> by <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a></p><p>At this year&#8217;s Group Labs, Apple engineers answered questions from developers live on stage. Anton has compiled summaries from the <a href="https://antongubarenko.substack.com/p/wwdc26-swift-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-for-beginners-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI for Beginners</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI Advanced</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-power-and-performance-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Performance</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-visionos-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">VisionOS</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-coding-intelligence-machine?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">AI</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-icon-composer-for-beginners?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Icon Composer</a>, and <a href="https://antongubarenko.substack.com/p/wwdc26-camera-and-photo-technologies?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Camera and Photo</a> Labs.</p></li><li><p><a href="https://www.massicotte.org/blog/wwdc26-unanswered-qa/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">(Some) Unanswered Swift Group Questions</a> by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a></p><p>Time limits and voting mechanics meant not every question at the Swift Group Lab got answered. Matt picked out a selection of those that didn&#8217;t make it and offered his own take &#8212; covering Swift 6 migration, Approachable Concurrency, default MainActor isolation, <code>@preconcurrency</code>, Sendable / ~Sendable, and unstructured tasks.</p></li><li><p><a href="https://onmyway133.com/posts/whats-new-in-swift-6.4-at-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s new in Swift 6.4 at WWDC26</a> by <a href="https://x.com/onmyway133">Khoa Pham</a></p><p>A walkthrough of the Swift 6.4 changes that make code more concise and expressive.</p></li><li><p><a href="https://wadetregaskis.com/whats-coming-in-swift-6-4/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s Coming in Swift 6.4</a> by <a href="https://mastodon.social/@everything@wadetregaskis.com">Wade Tregaskis</a></p><p>Wade rounds up the Swift Evolution proposals marked as implemented in Swift 6.4, spanning concurrency, ownership, the standard library, accessors, package management, and compiler diagnostics.</p></li><li><p><a href="https://azamsharp.com/2026/06/12/whats-new-in-swiftdata.html?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s New in SwiftData for iOS 27</a> by <a href="https://x.com/azamsharp">Mohammad Azam</a></p><p>SwiftData may not have received a headline-grabbing overhaul this year, but the new enum predicates, sectioned queries, composite predicates, <code>.codable</code> attribute, and <code>ResultsObserver</code> all address real pain points and meaningfully round out the developer experience.</p></li><li><p><a href="https://swiftwithmajid.com/2026/06/08/what-is-new-in-swiftui-after-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What is new in SwiftUI after WWDC26</a> by <a href="https://x.com/mecid">Majid Jabrayilov</a></p><p>Majid surveys the SwiftUI additions from WWDC26 &#8212; many of them long-requested by the community. The one disappointment: with the exception of <code>@State</code>, most new APIs don&#8217;t offer backward compatibility.</p></li><li><p><a href="https://www.swiftjectivec.com/ios-27-notable-uikit-additions/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS 27: Notable UIKit Additions</a> by <a href="https://x.com/jordanmorgan10">Jordan Morgan</a></p><p>SwiftUI keeps moving forward, but Apple hasn&#8217;t let up on UIKit either. This year&#8217;s UIKit API updates focus mainly on adapting to new system capabilities and aligning with what&#8217;s new in SwiftUI.</p></li></ul><h3><strong>Documentation</strong></h3><ul><li><p><a href="https://wwdc.ai/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC.ai</a> by <a href="https://x.com/Superwall">Superwall</a></p><p>A site designed to help developers and AI agents quickly get up to speed on Apple&#8217;s developer updates. It offers Session summaries, an Ask AI interface, and a <a href="https://github.com/superwall/skills">Skill</a> for direct use in code assistants.</p></li><li><p><a href="https://github.com/0Itsuki0/iOS-MacOS_AppleBetaDocRetriever?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS/MacOS: Apple Beta Doc Retriever</a> by <a href="https://x.com/itsuki68391179">Itsuki</a></p><p>An open-source iOS/macOS app that lets developers browse Beta-tagged documentation and APIs, making it easy to spot what&#8217;s changed between OS versions.</p></li><li><p><a href="https://wwdc-quick-look.swiftgg.team/articles/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC Quick Look</a> by <a href="https://swift.swiftgg.team/">SwiftGG</a></p><p>A comprehensive archive of every Session from WWDC 2020 to today, with linked Sessions, video timestamps, and key code snippets. Also ships a <a href="https://github.com/SwiftGGTeam/wwdc-quick-look">Skill</a> for use with AI tools.</p></li><li><p><a href="https://askwwdc.com/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Ask WWDC</a> by <a href="https://x.com/matthew_spear">Matt Spear</a></p><p>A natural-language Q&amp;A search tool for WWDC content. Ask a question, get a concise answer along with the relevant Sessions.</p></li></ul><h3><strong>New Features</strong></h3><ul><li><p><a href="https://livsycode.com/swiftui/swiftuis-state-is-now-a-macro/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s @State is now a macro</a> by <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a></p><p><code>@State</code> was originally designed with value types in mind. Once the Observation framework arrived in iOS 17, a gap became apparent: <code>@State</code> lacked the lazy initialization behavior that <code>@StateObject</code> provided for reference types. WWDC26 finally closes that gap. What&#8217;s particularly worth noting is that Apple didn&#8217;t touch the property wrapper implementation &#8212; instead, they introduced a same-named macro to handle the change. This approach may offer a useful blueprint for managing future compatibility challenges.</p></li><li><p><a href="https://swiftuisnippets.wordpress.com/2026/06/10/wwdc26-the-evolution-of-presentation-transitions-in-swiftui/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC26: The Evolution of Presentation Transitions in SwiftUI</a> by <a href="https://x.com/Codelaby">codelaby</a></p><p>SwiftUI gains a <code>crossFade</code> transition for <code>sheet</code> and <code>fullScreenCover</code> in WWDC26. The downside: custom presentation transitions are still not on the table.</p></li><li><p><a href="https://nilcoalescing.com/blog/CustomScrollLayoutsWithSwipeActionsInSwiftUIOnIOS27/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Custom scroll layouts with swipe actions in SwiftUI on iOS 27</a> by <a href="https://x.com/natpanferova">Natalia Panferova</a></p><p>Starting in iOS 27, <code>swipeActions</code> is no longer exclusive to <code>List</code>. The new <code>swipeActionsContainer()</code> modifier brings swipe action support to <code>LazyVStack</code>, <code>LazyVGrid</code>, and custom <code>Layout</code> types inside a <code>ScrollView</code>. The new <code>onPresentationChanged</code> callback also fires when a row&#8217;s swipe actions expand or collapse &#8212; handy for tracking the active item, syncing state, or triggering additional logic.</p></li><li><p><a href="https://artemnovichkov.com/blog/using-claude-with-apple-foundation-models?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Claude with Apple Foundation Models</a> by <a href="https://x.com/iosartem">Artem Novichkov</a></p><p>WWDC26 brings a significant expansion to the Foundation Models framework: beyond Apple&#8217;s on-device model, <code>LanguageModelSession</code> can now connect to server-side models conforming to the <code>LanguageModel</code> protocol. This article demonstrates how to integrate Claude via Anthropic&#8217;s <code>ClaudeForFoundationModels</code> package.</p></li><li><p><a href="https://www.sagarunagar.com/blog/swiftui-prominent-tab-is-not-a-floating-action-button/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s New .prominent Tab in iOS 27 Is Not a Floating Action Button</a> by <a href="https://x.com/sagarunagar_">Sagar Unagar</a></p><p>iOS 27 introduces <code>Tab(role: .prominent)</code>, which gives a tab stronger visual emphasis in the system tab bar. Sagar&#8217;s reminder: this is meant to highlight the most important navigation destination in your app &#8212; not to replace a Floating Action Button, a navigation bar &#8220;+&#8221; button, or an action that opens a sheet.</p></li></ul><h3><strong>Issues &amp; Solutions</strong></h3><ul><li><p><a href="https://www.donnywals.com/installing-simulator-runtimes-from-the-command-line/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Installing simulator runtimes from the command line</a> by <a href="https://x.com/donnywals">Donny Wals</a></p><p>If you&#8217;ve installed Xcode 27 and the iOS Simulator Runtime won&#8217;t download through the Xcode UI, <code>xcodebuild</code> from the command line is your workaround.</p></li><li><p><a href="https://www.avanderlee.com/ai-development/using-xcode-27s-agent-skills-in-claude-codex-and-cursor/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Xcode 27&#8217;s Agent Skills in Claude, Codex, and Cursor</a> by <a href="https://x.com/twannl">Antoine v.d. SwiftLee</a></p><p>Xcode 27 ships with a set of official Apple-provided Agent Skills covering SwiftUI, UIKit, testing, and more. They can also be exported for use in Claude, Codex, Cursor, and other tools.</p></li></ul><h2><strong>Recent Recommendations</strong></h2><ul><li><p><a href="https://www.swift.org/blog/migrating-truetype-hinting-to-swift/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift at Apple: Migrating the TrueType Hinting Interpreter</a> by <a href="https://mastodon.social/@numist@xoxo.zone">Scott Perry</a></p><p>Apple&#8217;s team shares their experience rewriting the TrueType hinting interpreter from C to memory-safe Swift: the new implementation is pixel-identical to the original while running 13% faster on average. The article goes deep on noncopyable types, Span, and projection types as tools for system-level performance work.</p></li></ul><blockquote><p>The TrueType hinting interpreter is the bytecode engine embedded in TrueType fonts. It reads hinting instructions and adjusts glyph control points accordingly, helping text render more crisply at specific sizes and on lower-resolution pixel grids.</p></blockquote><ul><li><p><a href="https://deliveryhero.jobs/blog/scaling-ios-application-development-with-tuist/?utm_medium=LinkedIn&amp;utm_source=Employee_Advocacy_Program?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Scaling iOS application development with Tuist</a> by <a href="https://www.linkedin.com/in/mikeamike/">Michael Gerasymenko</a> and <a href="https://www.linkedin.com/in/dubeyashu/">Ashutosh Dubey</a></p><p>The Delivery Hero Logistics team shares how they used Tuist to scale a large iOS codebase &#8212; keeping their Xcode and Swift Package Manager workflow intact while adding Swift-defined project structure, explicit dependency graphs, binary caching, and selective testing. The result: local clean build time dropped from 2.5 minutes to 0.5 minutes, with CI builds and unit test runs cut by 2.5x.</p></li></ul><blockquote><p>The real point of the article isn&#8217;t &#8220;Tuist makes builds faster.&#8221; It&#8217;s about how Tuist helps teams make large iOS projects more maintainable.</p></blockquote><ul><li><p><a href="https://alejandromp.com/development/blog/keeping-up-with-swift-forums-using-codex?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Keeping Up With Swift Forums Using Codex</a> by <a href="https://x.com/alexito4">Alejandro Martinez</a></p><p>Alejandro walks through building a personal workflow that automatically tracks Swift Forums activity every day using Codex Automations and a Swift CLI: the CLI handles forum data and state sync, while Codex takes care of understanding context, generating summaries, and driving further exploration. A practical example of &#8220;AI-driven, programs as tools&#8221; automation design.</p></li><li><p><a href="https://github.com/apple/container?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Container 1.0</a></p><p>Apple officially released Container 1.0 a few days ago. As an OCI container solution built for Apple silicon, it offers stronger isolation, faster startup, and a more native macOS experience compared to Docker. That said, the ecosystem is still young, and tooling continues to mature.</p></li></ul><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>WWDC 26&#65306;AI &#24110;&#20320;&#30475;&#23436;&#20102;&#65292;&#28982;&#21518;&#21602;&#65311;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-140/">&#32593;&#39029;&#29256;</a></strong></p><p>&#38543;&#30528; AI Agent &#24037;&#20316;&#27969;&#30340;&#26222;&#21450;&#65292;&#20170;&#24180;&#19981;&#23569;&#24320;&#21457;&#32773;&#24320;&#22987;&#35753; AI &#20195;&#21171;&#27719;&#24635;&#12289;&#31579;&#36873;&#37325;&#28857;&#65292;&#20197;&#26356;&#24555;&#30340;&#33410;&#22863;&#28040;&#21270; WWDC &#19978;&#25512;&#20986;&#30340;&#26032;&#33021;&#21147;&#12290;&#33529;&#26524;&#20063;&#24456;&#37197;&#21512;&#8212;&#8212;&#19968;&#27425;&#24615;&#25918;&#20986;&#20840;&#37096; Session&#12289;&#25991;&#23383;&#31295;&#19982;&#31034;&#20363;&#20195;&#30721;&#65292;&#36827;&#19968;&#27493;&#38477;&#20302;&#20102; AI &#22788;&#29702;&#36825;&#20123;&#20869;&#23481;&#30340;&#38376;&#27099;&#12290;</p><p>&#23545;&#25105;&#20010;&#20154;&#32780;&#35328;&#65292;&#24448;&#24180;&#25163;&#21160;&#25552;&#21462; <code>interface</code> &#12289;&#36880;&#19968;&#27604;&#23545;&#26032;&#26087; API &#30340;&#25805;&#20316;&#65292;&#22914;&#20170;&#24050;&#21464;&#25104; Agent &#24037;&#20316;&#27969;&#37324;&#30340;&#19968;&#26465;&#25351;&#20196;&#12290;&#20174;&#25928;&#29575;&#35282;&#24230;&#26469;&#35828;&#65292;&#36825;&#26159;&#23454;&#23454;&#22312;&#22312;&#30340;&#36827;&#27493;&#12290;</p><p>&#20294;&#24555;&#36895;&#25552;&#28860;&#20986;&#30340;&#20449;&#24687;&#65292;&#24448;&#24448;&#26080;&#27861;&#31934;&#20934;&#12289;&#23436;&#25972;&#22320;&#36824;&#21407;&#33529;&#26524;&#24037;&#31243;&#24072;&#22312; Session &#20013;&#20256;&#36882;&#30340;&#20851;&#38190;&#32454;&#33410;&#12290;&#24456;&#22810; Session &#20173;&#20540;&#24471;&#38745;&#19979;&#24515;&#26469;&#65292;&#20180;&#32454;&#29978;&#33267;&#21453;&#22797;&#35266;&#30475;&#12290;</p><p>AI &#25552;&#21319;&#30340;&#26159;&#33719;&#21462;&#36164;&#35759;&#30340;&#36895;&#24230;&#65292;&#32780;&#38750;&#29702;&#35299;&#30340;&#28145;&#24230;&#12290;&#36164;&#35759;&#36827;&#20102; AI &#30340;&#19978;&#19979;&#25991;&#65292;&#19981;&#31561;&#20110;&#30693;&#35782;&#36827;&#20102;&#25105;&#20204;&#33258;&#24049;&#30340;&#33041;&#23376;&#12290;</p><p>&#35266;&#30475;&#20064;&#24815;&#21487;&#20197;&#19982;&#26102;&#20465;&#36827;&#65292;&#20294;&#23545;&#33258;&#24049;&#30340;&#35201;&#27714;&#65292;&#19981;&#35813;&#36319;&#30528;&#19968;&#36215;&#25171;&#25240;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-139/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>WWDC 2026</strong></h2><h3><strong>&#27719;&#24635;</strong></h3><ul><li><p><strong>WWDC 26 Group Lab Q&amp;A</strong> by <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a></p><p>&#20170;&#24180;&#30340; Group Lab &#20013;&#65292;&#26469;&#33258; Apple &#30340;&#19987;&#23478;&#22260;&#32469;&#24320;&#21457;&#32773;&#25552;&#20986;&#30340;&#21508;&#31867;&#38382;&#39064;&#36827;&#34892;&#20102;&#29616;&#22330;&#35299;&#31572;&#12290;Anton &#20998;&#21035;&#27719;&#24635;&#20102; <a href="https://antongubarenko.substack.com/p/wwdc26-swift-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-for-beginners-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI &#21021;&#23398;&#32773;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI &#36827;&#38454;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-power-and-performance-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">&#24615;&#33021;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-visionos-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">VisionOS</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-coding-intelligence-machine?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">AI</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-icon-composer-for-beginners?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Icon Composer</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-camera-and-photo-technologies?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Camera and Photo</a> &#31561;&#20027;&#39064; Lab &#30340;&#38382;&#31572;&#20869;&#23481;&#12290;</p></li><li><p><a href="https://www.massicotte.org/blog/wwdc26-unanswered-qa/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">(Some) Unanswered Swift Group Questions</a> by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a></p><p>&#30001;&#20110;&#26102;&#38388;&#21644;&#25237;&#31080;&#26426;&#21046;&#38480;&#21046;&#65292;Swift Group Lab &#20013;&#24182;&#38750;&#27599;&#20010;&#38382;&#39064;&#37117;&#33021;&#34987;&#29616;&#22330;&#22238;&#31572;&#12290;Matt &#36873;&#21462;&#20102;&#19968;&#20123;&#26410;&#33719;&#22238;&#31572;&#30340;&#38382;&#39064;&#24182;&#32473;&#20986;&#20010;&#20154;&#35299;&#35835;&#65292;&#20869;&#23481;&#20027;&#35201;&#38598;&#20013;&#22312; Swift 6 &#36801;&#31227;&#12289;Approachable Concurrency&#12289;&#40664;&#35748; MainActor &#38548;&#31163;&#12289;<code>@preconcurrency</code>&#12289;Sendable / ~Sendable&#65292;&#20197;&#21450;&#38750;&#32467;&#26500;&#21270;&#20219;&#21153;&#31561;&#26041;&#21521;&#12290;</p></li><li><p><a href="https://onmyway133.com/posts/whats-new-in-swift-6.4-at-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s new in Swift 6.4 at WWDC26</a> by <a href="https://x.com/onmyway133">Khoa Pham</a></p><p>&#36825;&#31687;&#25991;&#31456;&#26803;&#29702;&#20102; Swift 6.4 &#20013;&#35753;&#20195;&#30721;&#26356;&#31616;&#27905;&#12289;&#26356;&#20855;&#34920;&#29616;&#21147;&#30340;&#19968;&#31995;&#21015;&#21464;&#21270;&#12290;</p></li><li><p><a href="https://wadetregaskis.com/whats-coming-in-swift-6-4/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s Coming in Swift 6.4</a> by <a href="https://mastodon.social/@everything@wadetregaskis.com">Wade Tregaskis</a></p><p>&#36825;&#31687;&#25991;&#31456;&#25972;&#29702;&#20102; Swift 6.4 &#20013;&#24050;&#26631;&#35760;&#20026; implemented &#30340; Swift Evolution &#25552;&#26696;&#65292;&#35206;&#30422;&#24182;&#21457;&#12289;&#25152;&#26377;&#26435;&#12289;&#26631;&#20934;&#24211;&#12289;&#35775;&#38382;&#22120;&#12289;&#21253;&#31649;&#29702;&#21644;&#32534;&#35793;&#22120;&#35786;&#26029;&#31561;&#22810;&#20010;&#26041;&#21521;&#12290;</p></li><li><p><a href="https://azamsharp.com/2026/06/12/whats-new-in-swiftdata.html?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s New in SwiftData for iOS 27</a> by <a href="https://x.com/azamsharp">Mohammad Azam</a></p><p>&#23613;&#31649; SwiftData &#20170;&#24180;&#30475;&#36215;&#26469;&#27809;&#26377;&#29305;&#21035;&#24040;&#22823;&#30340;&#26356;&#26032;&#65292;&#20294;&#26032;&#22686;&#30340;&#26522;&#20030;&#35859;&#35789;&#12289;&#20998;&#27573;&#26597;&#35810;&#12289;&#22797;&#21512;&#35859;&#35789;&#12289;<code>.codable</code> &#23646;&#24615;&#21644; <code>ResultsObserver</code> &#37117;&#38754;&#21521;&#20855;&#20307;&#30171;&#28857;&#65292;&#36827;&#19968;&#27493;&#34917;&#40784;&#20102; SwiftData &#30340;&#20351;&#29992;&#20307;&#39564;&#12290;</p></li><li><p><a href="https://swiftwithmajid.com/2026/06/08/what-is-new-in-swiftui-after-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What is new in SwiftUI after WWDC26</a> by <a href="https://x.com/mecid">Majid Jabrayilov</a></p><p>Majid &#23545;&#20170;&#24180; WWDC26 &#19978; SwiftUI &#30456;&#20851;&#26032;&#21151;&#33021;&#20570;&#20102;&#26803;&#29702;&#65292;&#20854;&#20013;&#19981;&#23569;&#37117;&#26159;&#24320;&#21457;&#32773;&#38271;&#26399;&#26399;&#24453;&#30340;&#33021;&#21147;&#12290;&#30053;&#26174;&#36951;&#25022;&#30340;&#26159;&#65292;&#38500;&#20102; <code>@State</code> &#22806;&#65292;&#22823;&#22810;&#25968;&#26032; API &#24182;&#26410;&#25552;&#20379;&#21521;&#21069;&#20860;&#23481;&#25903;&#25345;&#12290;</p></li><li><p><a href="https://www.swiftjectivec.com/ios-27-notable-uikit-additions/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS 27: Notable UIKit Additions</a> by <a href="https://x.com/jordanmorgan10">Jordan Morgan</a></p><p>SwiftUI &#32487;&#32493;&#21457;&#23637;&#65292;&#20294; Apple &#24182;&#27809;&#26377;&#25918;&#24930;&#23545; UIKit &#30340;&#32500;&#25252;&#12290;&#20170;&#24180;&#30340; UIKit API &#26356;&#26032;&#26356;&#22810;&#22260;&#32469;&#31995;&#32479;&#26032;&#29305;&#24615;&#36866;&#37197;&#65292;&#20197;&#21450;&#19982; SwiftUI &#30340;&#26032;&#33021;&#21147;&#23545;&#40784;&#23637;&#24320;&#12290;</p></li></ul><h3><strong>&#25991;&#26723;</strong></h3><ul><li><p><a href="https://wwdc.ai/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC.ai</a> by <a href="https://x.com/Superwall">Superwall</a></p><p>&#19968;&#20010;&#24110;&#21161;&#24320;&#21457;&#32773;&#25110; AI &#20195;&#29702;&#24555;&#36895;&#20102;&#35299; Apple &#24320;&#21457;&#32773;&#26356;&#26032;&#30340;&#32593;&#31449;&#65292;&#25552;&#20379; Session &#25688;&#35201;&#12289;Ask AI &#33021;&#21147;&#65292;&#24182;&#25552;&#20379; <a href="https://github.com/superwall/skills">Skill</a>&#8288; &#26041;&#20415;&#22312;&#20195;&#30721;&#21161;&#25163;&#20013;&#30452;&#25509;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://github.com/0Itsuki0/iOS-MacOS_AppleBetaDocRetriever?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS/MacOS: Apple Beta Doc Retriever</a> by <a href="https://x.com/itsuki68391179">Itsuki</a></p><p>&#19968;&#27454; iOS/macOS &#24320;&#28304;&#24212;&#29992;&#65292;&#21487;&#24110;&#21161;&#24320;&#21457;&#32773;&#26597;&#30475;&#24102;&#26377; Beta &#26631;&#27880;&#30340;&#25991;&#26723;&#21644; API&#65292;&#24555;&#36895;&#20102;&#35299;&#26032;&#26087;&#31995;&#32479;&#29256;&#26412;&#38388;&#30340;&#24046;&#24322;&#12290;</p></li><li><p><a href="https://wwdc-quick-look.swiftgg.team/articles/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC Quick Look</a> by <a href="https://swift.swiftgg.team/">SwiftGG</a></p><p>&#27719;&#24635;&#20102;&#33258; WWDC 2020 &#33267;&#20170;&#30340;&#25152;&#26377; Session &#20869;&#23481;&#65292;&#21253;&#21547;&#20851;&#32852; Session&#12289;&#35270;&#39057;&#36339;&#36716;&#21644;&#20851;&#38190;&#20195;&#30721;&#29255;&#27573;&#65292;&#20063;&#25552;&#20379;&#20102; <a href="https://github.com/SwiftGGTeam/wwdc-quick-look">Skill</a>&#8288; &#26041;&#20415; AI &#24037;&#20855;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://askwwdc.com/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Ask WWDC</a> by <a href="https://x.com/matthew_spear">Matt Spear</a></p><p>&#19968;&#20010;&#38754;&#21521; WWDC &#20869;&#23481;&#30340;&#38382;&#31572;&#25628;&#32034;&#24037;&#20855;&#65292;&#21487;&#20197;&#26681;&#25454;&#33258;&#28982;&#35821;&#35328;&#38382;&#39064;&#24555;&#36895;&#23450;&#20301;&#30456;&#20851; Session&#65292;&#24182;&#25972;&#29702;&#20986;&#31616;&#30701;&#31572;&#26696;&#21644;&#37325;&#28857;&#20869;&#23481;&#12290;</p></li></ul><h3><strong>&#26032;&#21151;&#33021;</strong></h3><ul><li><p><a href="https://livsycode.com/swiftui/swiftuis-state-is-now-a-macro/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s @State is now a macro</a> by <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a></p><p><code>@State</code> &#22312; SwiftUI &#26089;&#26399;&#20027;&#35201;&#38754;&#21521;&#20540;&#31867;&#22411;&#65292;&#20294;&#38543;&#30528; Observation &#26694;&#26550;&#22312; iOS 17 &#24341;&#20837;&#65292;<code>@State</code> &#19981;&#20855;&#22791;&#31867;&#20284; <code>@StateObject</code> &#30340;&#23454;&#20363;&#25042;&#21152;&#36733;&#33021;&#21147;&#36825;&#19968;&#38382;&#39064;&#36880;&#28176;&#26174;&#29616;&#12290;WWDC26 &#32456;&#20110;&#34917;&#19978;&#20102;&#36825;&#22359;&#30701;&#26495;&#12290;&#23588;&#20854;&#20540;&#24471;&#20851;&#27880;&#30340;&#26159;&#65292;Apple &#24182;&#27809;&#26377;&#30452;&#25509;&#35843;&#25972;&#23646;&#24615;&#21253;&#35013;&#22120;&#30340;&#23454;&#29616;&#65292;&#32780;&#26159;&#36890;&#36807;&#21516;&#21517;&#23439;&#26469;&#23436;&#25104;&#25913;&#36896;&#65292;&#36825;&#25110;&#35768;&#20063;&#25552;&#20379;&#20102;&#19968;&#31181;&#26410;&#26469;&#22788;&#29702;&#20860;&#23481;&#24615;&#38382;&#39064;&#30340;&#26032;&#24605;&#36335;&#12290;</p></li><li><p><a href="https://swiftuisnippets.wordpress.com/2026/06/10/wwdc26-the-evolution-of-presentation-transitions-in-swiftui/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC26: The Evolution of Presentation Transitions in SwiftUI</a> by <a href="https://x.com/Codelaby">codelaby</a></p><p>WWDC26 &#20013;&#65292;SwiftUI &#20026; <code>sheet</code> / <code>fullScreenCover</code> &#26032;&#22686;&#20102; <code>crossFade</code> &#36716;&#22330;&#25928;&#26524;&#12290;&#36951;&#25022;&#30340;&#26159;&#65292;&#30446;&#21069;&#20173;&#26410;&#25552;&#20379;&#33258;&#23450;&#20041;&#36716;&#22330;&#33021;&#21147;&#12290;</p></li><li><p><a href="https://nilcoalescing.com/blog/CustomScrollLayoutsWithSwipeActionsInSwiftUIOnIOS27/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Custom scroll layouts with swipe actions in SwiftUI on iOS 27</a> by <a href="https://x.com/natpanferova">Natalia Panferova</a></p><p>&#20174; iOS 27 &#24320;&#22987;&#65292;<code>swipeActions</code> &#19981;&#20877;&#26159; <code>List</code> &#30340;&#19987;&#23646;&#33021;&#21147;&#12290;&#26032;&#22686;&#30340; <code>swipeActionsContainer()</code> &#21487;&#20197;&#35753; <code>ScrollView</code> &#20013;&#30340; <code>LazyVStack</code>&#12289;<code>LazyVGrid</code> &#25110;&#33258;&#23450;&#20041; <code>Layout</code> &#25903;&#25345;&#28369;&#21160;&#25805;&#20316;&#65307;&#26032;&#30340; <code>onPresentationChanged</code> &#22238;&#35843;&#20063;&#21487;&#20197;&#22312;&#26576;&#19968;&#34892;&#30340;&#28369;&#21160;&#25805;&#20316;&#23637;&#24320;&#25110;&#25910;&#36215;&#26102;&#35302;&#21457;&#65292;&#20415;&#20110;&#35760;&#24405;&#24403;&#21069;&#27963;&#36291;&#39033;&#12289;&#32852;&#21160;&#29366;&#24577;&#25110;&#25191;&#34892;&#39069;&#22806;&#36923;&#36753;&#12290;</p></li><li><p><a href="https://artemnovichkov.com/blog/using-claude-with-apple-foundation-models?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Claude with Apple Foundation Models</a> by <a href="https://x.com/iosartem">Artem Novichkov</a></p><p>Foundation Models framework &#22312; WWDC26 &#19978;&#33719;&#24471;&#20102;&#19968;&#20010;&#37325;&#35201;&#25193;&#23637;&#65306;&#38500;&#20102; Apple &#30340;&#31471;&#20391;&#27169;&#22411;&#65292;<code>LanguageModelSession</code> &#29616;&#22312;&#20063;&#21487;&#20197;&#25509;&#20837;&#31526;&#21512; <code>LanguageModel</code> &#21327;&#35758;&#30340;&#26381;&#21153;&#31471;&#22823;&#27169;&#22411;&#12290;&#25991;&#31456;&#23637;&#31034;&#20102;&#22914;&#20309;&#20351;&#29992; Anthropic &#30340; <code>ClaudeForFoundationModels</code> &#23558; Claude &#25509;&#20837; Apple Foundation Models&#12290;</p></li><li><p><a href="https://www.sagarunagar.com/blog/swiftui-prominent-tab-is-not-a-floating-action-button/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s New .prominent Tab in iOS 27 Is Not a Floating Action Button</a> by <a href="https://x.com/sagarunagar_">Sagar Unagar</a></p><p>iOS 27 &#20013;&#65292;SwiftUI &#26032;&#22686;&#30340; <code>Tab(role: .prominent)</code> &#21487;&#20197;&#35753;&#26576;&#20010; tab &#22312;&#31995;&#32479; tab bar &#20013;&#33719;&#24471;&#26356;&#24378;&#30340;&#35270;&#35273;&#24378;&#35843;&#12290;Sagar &#25552;&#37266;&#65292;&#36825;&#39033;&#33021;&#21147;&#24212;&#35813;&#29992;&#20110;&#31361;&#20986;&#24212;&#29992;&#20013;&#26368;&#37325;&#35201;&#30340;&#23548;&#33322;&#30446;&#30340;&#22320;&#65292;&#32780;&#19981;&#26159;&#26367;&#20195; Floating Action Button&#12289;&#23548;&#33322;&#26639; &#8220;+&#8221; &#25353;&#38062;&#25110;&#24377;&#20986; sheet &#30340;&#25805;&#20316;&#20837;&#21475;&#12290;</p></li></ul><h3><strong>&#38382;&#39064;&#19982;&#35299;&#20915;</strong></h3><ul><li><p><a href="https://www.donnywals.com/installing-simulator-runtimes-from-the-command-line/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Installing simulator runtimes from the command line</a> by <a href="https://x.com/donnywals">Donny Wals</a></p><p>&#22914;&#26524;&#24320;&#21457;&#32773;&#22312;&#23433;&#35013; Xcode 27 &#21518;&#36935;&#21040; iOS Simulator Runtime &#26080;&#27861;&#36890;&#36807; Xcode UI &#27491;&#24120;&#19979;&#36733;&#30340;&#38382;&#39064;&#65292;&#21487;&#20197;&#25913;&#29992; <code>xcodebuild</code> &#20174;&#21629;&#20196;&#34892;&#23433;&#35013;&#36816;&#34892;&#26102;&#12290;</p></li><li><p><a href="https://www.avanderlee.com/ai-development/using-xcode-27s-agent-skills-in-claude-codex-and-cursor/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Xcode 27&#8217;s Agent Skills in Claude, Codex, and Cursor</a> by <a href="https://x.com/twannl">Antoine v.d. SwiftLee</a></p><p>Xcode 27 &#20869;&#32622;&#20102;&#19968;&#32452; Apple &#23448;&#26041;&#25552;&#20379;&#30340; Agent Skills&#65292;&#28085;&#30422; SwiftUI&#12289;UIKit&#12289;&#27979;&#35797;&#31561;&#22330;&#26223;&#65292;&#24182;&#25552;&#20379;&#20102;&#23548;&#20986;&#33021;&#21147;&#65292;&#26041;&#20415;&#22312; Claude&#12289;Codex&#12289;Cursor &#31561;&#24037;&#20855;&#20013;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://github.com/SkyBlue997/enableMacosAI?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">EnableMacosAI</a> by <a href="https://github.com/SkyBlue997">&#28023;&#31354;&#33980;</a></p><p>&#19968;&#20010;&#29992;&#20110;&#22312;&#20013;&#22269;&#38144;&#21806;&#30340; macOS &#35774;&#22791;&#19978;&#21551;&#29992;&#23436;&#25972; Apple Intelligence &#30340;&#24037;&#20855;&#12290;</p></li></ul><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><ul><li><p><a href="https://www.swift.org/blog/migrating-truetype-hinting-to-swift/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift at Apple: Migrating the TrueType Hinting Interpreter</a> by <a href="https://mastodon.social/@numist@xoxo.zone">Scott Perry</a></p><p>Apple &#23433;&#20840;&#22242;&#38431;&#20998;&#20139;&#20102;&#23558; TrueType hinting interpreter &#20174; C &#36801;&#31227;&#21040; Swift &#30340;&#32463;&#39564;&#65306;&#22312;&#20445;&#25345;&#20687;&#32032;&#32423;&#19968;&#33268;&#30340;&#21069;&#25552;&#19979;&#65292;&#26032;&#30340;&#20869;&#23384;&#23433;&#20840; Swift &#23454;&#29616;&#24179;&#22343;&#27604;&#21407; C &#23454;&#29616;&#24555; 13%&#65292;&#25991;&#31456;&#20063;&#28145;&#20837;&#20171;&#32461;&#20102;&#38750;&#21487;&#22797;&#21046;&#31867;&#22411;&#12289;Span&#12289;projection type &#31561;&#22312;&#31995;&#32479;&#32423;&#24615;&#33021;&#20248;&#21270;&#20013;&#30340;&#23454;&#36341;&#12290;</p></li></ul><blockquote><p>TrueType hinting interpreter &#26159; TrueType &#23383;&#20307;&#28210;&#26579;&#31995;&#32479;&#20013;&#30340;&#25552;&#31034;&#25351;&#20196;&#35299;&#37322;&#22120;&#65292;&#23427;&#20250;&#35835;&#21462;&#23383;&#20307;&#20013;&#30340; hinting &#23383;&#33410;&#30721;&#65292;&#24182;&#26681;&#25454;&#36825;&#20123;&#25351;&#20196;&#35843;&#25972;&#23383;&#24418;&#25511;&#21046;&#28857;&#65292;&#35753;&#25991;&#23383;&#22312;&#29305;&#23450;&#23383;&#21495;&#21644;&#23631;&#24149;&#20687;&#32032;&#32593;&#26684;&#19978;&#26174;&#31034;&#24471;&#26356;&#28165;&#26224;&#12290;</p></blockquote><ul><li><p><a href="https://deliveryhero.jobs/blog/scaling-ios-application-development-with-tuist/?utm_medium=LinkedIn&amp;utm_source=Employee_Advocacy_Program?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Scaling iOS application development with Tuist</a> by <a href="https://www.linkedin.com/in/mikeamike/">Michael Gerasymenko</a> and <a href="https://www.linkedin.com/in/dubeyashu/">Ashutosh Dubey</a></p><p>Delivery Hero Logistics &#22242;&#38431;&#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Tuist &#25193;&#23637;&#22823;&#22411; iOS &#24037;&#31243;&#65306;&#22312;&#20445;&#30041; Xcode &#21644; Swift Package Manager &#24037;&#20316;&#27969;&#30340;&#21516;&#26102;&#65292;&#36890;&#36807; Swift &#20195;&#30721;&#23450;&#20041;&#39033;&#30446;&#32467;&#26500;&#12289;&#26174;&#24335;&#20381;&#36182;&#22270;&#12289;&#20108;&#36827;&#21046;&#32531;&#23384;&#21644;&#36873;&#25321;&#24615;&#27979;&#35797;&#65292;&#23558;&#26412;&#22320; clean build &#20174; 2.5 &#20998;&#38047;&#38477;&#21040; 0.5 &#20998;&#38047;&#65292;&#24182;&#35753; CI &#26500;&#24314;&#21644;&#21333;&#27979;&#32791;&#26102;&#32553;&#30701; 2.5 &#20493;&#12290;</p></li></ul><blockquote><p>&#25991;&#31456;&#30340;&#37325;&#28857;&#19981;&#21482;&#26159;&#8220;Tuist &#21487;&#20197;&#21152;&#24555;&#26500;&#24314;&#8221;&#65292;&#32780;&#26159;&#23637;&#31034;&#20102;&#23427;&#22914;&#20309;&#24110;&#21161;&#22242;&#38431;&#25226;&#22823;&#22411; iOS &#24037;&#31243;&#21464;&#24471;&#26356;&#21487;&#32500;&#25252;&#12290;</p></blockquote><ul><li><p><a href="https://alejandromp.com/development/blog/keeping-up-with-swift-forums-using-codex?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Keeping Up With Swift Forums Using Codex</a> by <a href="https://x.com/alexito4">Alejandro Martinez</a></p><p>Alejandro &#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Codex Automations &#21644; Swift CLI &#26500;&#24314;&#19968;&#20010;&#27599;&#22825;&#33258;&#21160;&#36319;&#36827; Swift Forums &#30340;&#20010;&#20154;&#24037;&#20316;&#27969;&#65306;&#30001; CLI &#22788;&#29702;&#35770;&#22363;&#25968;&#25454;&#21644;&#29366;&#24577;&#21516;&#27493;&#65292;Codex &#36127;&#36131;&#29702;&#35299;&#19978;&#19979;&#25991;&#12289;&#29983;&#25104;&#25688;&#35201;&#21644;&#25512;&#36827;&#21518;&#32493;&#25506;&#32034;&#65292;&#23637;&#31034;&#20102;&#19968;&#31181;&#8220;AI &#39537;&#21160;&#12289;&#31243;&#24207;&#20316;&#20026;&#24037;&#20855;&#8221;&#30340;&#23454;&#29992;&#33258;&#21160;&#21270;&#35774;&#35745;&#12290;</p></li><li><p><a href="https://github.com/apple/container?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Container 1.0</a></p><p>Apple &#20960;&#22825;&#21069;&#27491;&#24335;&#21457;&#24067;&#20102; Container 1.0&#12290;&#20316;&#20026;&#38754;&#21521; Apple silicon &#30340; OCI &#23481;&#22120;&#26041;&#26696;&#65292;&#23427;&#30456;&#27604; Docker &#22312;&#38548;&#31163;&#12289;&#21551;&#21160;&#36895;&#24230;&#21644; macOS &#21407;&#29983;&#20307;&#39564;&#19978;&#26356;&#26377;&#20248;&#21183;&#12290;&#24403;&#28982;&#65292;&#30001;&#20110;&#29983;&#24577;&#20173;&#26032;&#65292;&#30456;&#20851;&#21151;&#33021;&#21644;&#24037;&#20855;&#38142;&#36824;&#22312;&#25345;&#32493;&#23436;&#21892;&#20013;&#12290;</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #139]]></title><description><![CDATA[First Impressions of WWDC 2026: In Line with Expectations, but More Pragmatic]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Tue, 09 Jun 2026 12:03:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!chp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!chp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!chp5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 424w, https://substackcdn.com/image/fetch/$s_!chp5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 848w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77180,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/201238663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!chp5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 424w, https://substackcdn.com/image/fetch/$s_!chp5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 848w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>First Impressions of WWDC 2026: In Line with Expectations, but More Pragmatic</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-139/">Read on web &#8594;</a></p><p>Like many developers, I cared more this year about improvements in stability and efficiency, and I also deliberately lowered my expectations for &#8220;surprising new features.&#8221; With that mindset, after quickly going through several topics from the first day of WWDC 2026 that I personally care about, my initial impression of this year&#8217;s event is: it was in line with expectations, and quite pragmatic.</p><p><strong>AI</strong></p><p>Although Foundation Models was introduced last year, the capabilities it offered at the time were still not compelling enough for many developers. This year&#8217;s changes are clearly more practical: the APIs have been further integrated; image input is now supported; developers can choose between on-device models, Private Cloud Compute, or third-party server models depending on the task; and eligible developers can use Apple Foundation Models running on Private Cloud Compute for free. At the same time, the system is also gaining stronger view awareness, better understanding of app context, and the ability to bring users back into apps through App Intents.</p><p>These improvements significantly increase the practicality and appeal of Foundation Models. It is no longer merely a framework that is &#8220;worth trying&#8221;; it is beginning to have the foundation needed to enter real product workflows. Unsurprisingly, more developers will likely be willing to experiment with this system this year and gradually incorporate it as one of the core capabilities of their apps.</p><p><strong>SwiftUI</strong></p><p>For me, the biggest change in SwiftUI comes from its comprehensive support for document-based apps. It not only adds a large number of new APIs, but also shifts the mental model toward &#8220;observable document objects + asynchronous snapshots + dedicated readers / writers.&#8221; This is clearly better suited to complex document apps, and it also aligns more closely with the overall evolution of modern Swift around Observation and Concurrency.</p><p>The sessions also mentioned that SwiftUI continues to optimize layout- and container-related implementations, bringing noticeable performance improvements in some scenarios. This is an improvement developers have urgently needed. However, SwiftUI still does not provide the ability to create custom Lazy containers, which remains a clear disappointment. <code>reorderable</code> and <code>swipeActions</code> are no longer limited to specific containers. This is not merely an expansion of their applicable scope; it also reflects further integration of the underlying interaction logic. Perhaps the benefits of this integration will become more apparent in next year&#8217;s APIs.</p><p><code>@State</code> now supports lazy initialization, text selection on iOS has been enhanced, and <code>alert</code> / <code>confirmationDialog</code> now provide <code>Binding&lt;T?&gt;</code> support. These are all welcome improvements, though they do feel like they arrived a little late. <code>AnyNavigationTransition</code> appears in the interface, but there is still no public support for custom transitions. For now, developers can only choose between the system-provided zoom and crossFade transitions.</p><p>The new DataDetection framework gives <code>Text</code> better content recognition capabilities; toolbars also gain more control. These changes also show Apple&#8217;s continued emphasis on using SwiftUI to build macOS apps. Overall, SwiftUI this year does not rely on a single standout API to create surprise. Instead, through a set of additions and integrations, it moves closer to the everyday needs of complex apps.</p><p><strong>SwiftData</strong></p><p>Compared with <code>@Query</code> gaining support for section fetches, and <code>ResultsObserver</code> enabling observation of query result changes outside views, I am more interested in <code>@Attribute(.codable)</code>. It provides a clearer storage intent and gives developers a way to avoid falling into the black box of composition.</p><p>Of course, <code>@Attribute(.codable)</code> is not a silver bullet. It is more like a clearly defined escape hatch SwiftData provides for opaque Codable types: suitable for storing external types that you cannot model yourself, but still genuinely need to persist. The cost is that this content cannot participate in SwiftData&#8217;s predicate, sort, or migration awareness. Precisely for this reason, its value lies not in being &#8220;more powerful,&#8221; but in being &#8220;more explicit.&#8221;</p><p>However, SwiftData still does not provide cloud syncing for public / shared data, nor have I seen a clearer signal of performance improvements. These issues will continue to limit its adoption. For many developers, SwiftData this year feels more like it is filling key gaps rather than making a leap significant enough to fundamentally change confidence in it.</p><p><strong>Xcode</strong></p><p>Over the past six months, my development workflow has basically been Codex App / Claude App + Xcode, with Xcode appearing significantly less often than the former two. After briefly trying Xcode 27, I expect Xcode&#8217;s presence in my workflow to increase noticeably. I am especially looking forward to the changes Xcode&#8217;s built-in AI workflows may bring in areas such as fine-tuning UI, improving performance, and validating previews.</p><p>Device Hub is undoubtedly a major surprise. It integrates simulators, physical device management, system state testing, and dynamic size adjustment into a new workflow. Its impact on day-to-day development experience may be more direct than that of many individual APIs. That said, iPhone apps now also support dynamic size adjustment, which will bring new challenges for developers, especially in terms of data and state organization. Adapting to different sizes is not something that can be solved merely by relying on dynamic layout containers. In many scenarios, large and small sizes correspond to very different navigation logic.</p><div><hr></div><p>This year, I probably won&#8217;t rush to write articles about the new SwiftUI and SwiftData APIs. Instead of introducing new interfaces one by one, I would rather spend some time systematically digesting these changes and sorting out the implicit logic behind them: how Apple is reorganizing the relationship between SwiftUI, SwiftData, Foundation Models, and Xcode&#8217;s AI workflow &#8212; and how these changes will ultimately affect the way we build apps.</p><p><a href="https://fatbobman.com/en/weekly/issue-138/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/core-data-observation-freer-mental-model/?utm_source=fatbobman%20weekly%20issue%20139&amp;utm_medium=web">Core Data + Observation: From Property-Level Reactivity to a Freer Mental Model</a></strong></h3><p>The introduction of the Observation framework refined SwiftUI&#8217;s state-driven updates from object-level observation to property-level observation, significantly reducing many unnecessary refreshes caused by coarse-grained observation. More importantly, it makes the declarative logic of state management feel natural again: a view only needs to read the properties it truly depends on, and the framework can establish the corresponding reactive relationships from there. To bring the conveniences of modern Swift features to Core Data, a long-standing persistence framework, I recently explored and implemented Observation support in <a href="https://fatbobman.com/zh/posts/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/">Core Data Evolution</a> (CDE), giving <code>NSManagedObject</code> precise property-level observation capabilities. This article discusses the motivation behind this feature, how to use it, the implementation approach, engineering challenges, and some of the trade-offs made during development.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-01">Bringing Goodnotes to the Web with Swift and WebAssembly</a></strong></h3><p>As a well-known note-taking app in the Apple ecosystem, Goodnotes did not choose to completely rewrite its product when moving to the Web. Instead, it brought years of accumulated Swift code into the browser environment through WebAssembly. In this article, <a href="https://x.com/kateinoigakukun">Yuta Saito</a> explains how Goodnotes maintains the same ink rendering, document synchronization, CRDT-based conflict resolution, search indexing, and interaction experience on the Web as in the native app. The Swift codebase for Goodnotes Web is about 2.2 million lines of code, of which 1.47 million lines are shared code; the final generated WebAssembly binary is about 50 MB, compressed to around 12 MB with Brotli. The significance of this article is not merely that it shows Swift can run on the Web, but that it presents how a real, large-scale Swift application can use WebAssembly to extend core capabilities originally deeply rooted in Apple platforms to more platforms.</p><blockquote><p>Yuta&#8217;s iOS Conf 2026 talk, <a href="https://www.youtube.com/watch?v=ysD4_qqd-po">Swift at Scale: Where Performance Really Comes From</a>, is also worth watching. Compared with the official article&#8217;s overview of the overall Goodnotes Web architecture, this talk focuses more on a real Swift performance case: the Goodnotes team found that an <code>Update</code> value type used to aggregate partial UI updates had grown to about 6 KB as features accumulated, and it contained many non-trivial members. Even though most updates only used one or two fields, the hot path still paid the cost of copying and reference counting. The team eventually refactored the data structure through a hot-cold split, keeping frequently accessed fields in the main struct while moving infrequent updates into separate storage. This reduced the type size from about 6 KB to around 300 bytes and brought about a 42% improvement in CPU time.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-02">Announcing the Networking Workgroup</a></strong></h3><p>Swift&#8217;s networking APIs are not lacking in choices; rather, there are too many choices with overlapping responsibilities. From <code>URLSession</code> and <code>Network.framework</code> on Apple platforms, to SwiftNIO and AsyncHTTPClient in the server-side ecosystem, and further down to lower-level HTTP representation types, developers often have to deal with inconsistent models and migration costs across different platforms and abstraction layers. More importantly, many of these APIs appeared before modern Swift capabilities such as async/await, structured concurrency, actors, and <code>Sendable</code> had matured, making it difficult for them to naturally reflect Swift&#8217;s current strengths in concurrency, safety, and cross-platform development. These issues are discussed more systematically in <a href="https://github.com/swiftlang/swift-evolution/blob/main/visions/networking.md">A Vision for Networking in Swift</a>, while the <a href="https://github.com/apple/swift-http-api-proposal">Swift HTTP API Proposal</a> can be seen as an early exploration in this direction.</p><p>The official establishment of the Networking Workgroup sends an important signal: the Swift ecosystem is beginning to treat networking as cross-platform infrastructure that requires long-term governance, rather than simply allowing individual frameworks and packages to evolve independently within their own domains. The goal of the workgroup is not to simply replace existing solutions, but to promote clearer layering, more consistent types, better interoperability, and stronger observability, so that Swift can have a more unified, modern, and sustainable networking foundation across Apple platforms, server-side development, CLI tools, WebAssembly, Android, Windows, and even Embedded Swift.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-03">WWDC 2026 Wish Lists</a></strong></h3><p><a href="https://x.com/mjtsai">Michael Tsai</a> collected wish lists from several Apple developers ahead of WWDC 2026. Similar to the expectations I shared in <a href="https://fatbobman.com/zh/weekly/issue-138/">the previous issue of the weekly newsletter</a>, most developers are calling for a Snow Leopard-style quality-focused release: rethinking the usability of Liquid Glass on the Mac, reducing instability at the system and framework levels, and fixing long-standing issues that affect daily development, such as iCloud sync, Spotlight, System Settings, error messages, SwiftUI, Xcode, Simulator, indexing, and previews. Many developers also hope that this year will not introduce another wave of &#8220;busywork&#8221; caused by adapting to new designs, new frameworks, or new review requirements, but instead give the existing platforms more time for refinement.</p><p>Another clear theme is how Apple&#8217;s developer tools should evolve in the age of AI agents. Several authors mention that they hope Apple will provide more official Agent Skills, MCP support, CLI tools, and automation interfaces, allowing AI to more reliably read documentation, operate Xcode, manage App Store Connect, modify project settings, run builds, control Simulator, and even understand UI hierarchies in a more structured way, rather than relying on screenshots or fragile Accessibility information.</p><blockquote><p>Adapting to the AI era and improving system stability are indeed becoming shared expectations among more Apple developers. By the time you read this issue, WWDC 2026 has already begun. After reading these wish lists and then watching this year&#8217;s announcements, I wonder whether everyone has found the answers they were hoping for.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-04">Apple-like</a></strong></h3><p>Around WWDC 2026, discussions about Apple&#8217;s future direction have become noticeably more frequent. Many people expect Apple to &#8220;return to its roots&#8221; or rediscover its former state, but in this article, <a href="https://mastodon.social/@_Davidsmith">David Smith</a> chooses a more constructive question: what does it mean to be Apple-like? As a long-time Apple platform developer, he summarizes this quality into several directions: The Best, and then Better; Excellence for Everyone; and Beneficial and Brilliant. In other words, continuously pursuing high quality, and not spending down user expectations even after getting ahead; making excellent experiences available to as many people as possible through pricing, accessibility, and design; and avoiding manipulative ways of chasing short-term metrics, instead solving users&#8217; problems in ways that are genuinely beneficial and delightful.</p><blockquote><p>When we expect Apple to improve system stability, developer tools, and platform experience, this article also reminds us that independent developers and app teams can examine their own products through similar standards.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-05">MarkdownPDF: A Markdown-to-PDF Engine Written Entirely in Swift</a></strong></h3><p>MarkdownPDF is an open-source Markdown-to-PDF engine written entirely in Swift by <a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263;</a>. It does not depend on platform or system capabilities such as PDFKit, CoreGraphics, WebKit, Chromium, LaTeX, or C-based PDF/Markdown libraries. Markdown parsing, layout, and PDF serialization are all implemented in Swift. Precisely because its core is pure and its dependencies are restrained, the project has strong cross-platform potential. It can target WebAssembly/WASI and generate PDFs from Markdown locally in the browser. The <a href="https://pdf.aleahim.com/">Playground</a> provided by the author demonstrates this capability.</p><blockquote><p>Goodnotes shows the engineering practice of migrating a large Swift application to the Web, while MarkdownPDF offers another perspective: when the core logic is pure enough and the dependencies are restrained enough, Swift tools themselves can also adapt naturally to the WebAssembly runtime environment. Swift&#8217;s move toward the Web is evolving from a proof of concept into an increasingly concrete engineering choice.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-06">AdaEngine: A Swift-first Open Source Game Engine</a></strong></h3><p>AdaEngine is an open-source Swift-first game engine and application framework created by <a href="https://x.com/SpectralDragon_">Vladislav Prusakov</a>, which recently released its first public milestone, 0.1.0. The project is designed for cross-platform development. Apple platforms are currently the most mature, while support for Windows, Linux, Android, and WebAssembly/WebGPU is also being developed.</p><p>With a data-driven ECS at its core, AdaEngine combines Swift macros, a plugin-based architecture, SwiftUI-like AdaUI, asset hot reloading, a scene system, 2D physics, audio, input, and Metal / WebGPU rendering backends. It aims to let Swift serve not only Apple platform app development, but also games, interactive tools, and creative software.</p><blockquote><p>Vladislav gives a more complete introduction to the project in <a href="https://adaengine.org/articles/introducing-adaengine-0-1-0">Introducing AdaEngine 0.1.0</a>.</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>WWDC 2026 &#21021;&#21360;&#35937;&#65306;&#31526;&#21512;&#39044;&#26399;&#65292;&#20294;&#26356;&#21153;&#23454;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-139/">&#32593;&#39029;&#29256;</a></strong></p><p>&#21644;&#24456;&#22810;&#24320;&#21457;&#32773;&#19968;&#26679;&#65292;&#25105;&#20170;&#24180;&#26356;&#30475;&#37325;&#31283;&#23450;&#24615;&#19982;&#25928;&#29575;&#26041;&#38754;&#30340;&#25913;&#21892;&#65292;&#20063;&#20027;&#21160;&#38477;&#20302;&#20102;&#23545;&#8220;&#24778;&#21916;&#22411;&#26032;&#21151;&#33021;&#8221;&#30340;&#26399;&#24453;&#12290;&#24102;&#30528;&#36825;&#26679;&#30340;&#39044;&#26399;&#65292;&#24555;&#36895;&#27983;&#35272;&#20102; WWDC 2026 &#31532;&#19968;&#22825;&#20013;&#20960;&#20010;&#25105;&#27604;&#36739;&#20851;&#24515;&#30340;&#20027;&#39064;&#21518;&#65292;&#26412;&#23626;&#27963;&#21160;&#32473;&#25105;&#30340;&#21021;&#27493;&#21360;&#35937;&#26159;&#65306;&#31526;&#21512;&#39044;&#26399;&#65292;&#32780;&#19988;&#30456;&#24403;&#21153;&#23454;&#12290;</p><p><strong>AI</strong></p><p>&#23613;&#31649; Foundation Models &#22312;&#21435;&#24180;&#24050;&#32463;&#25512;&#20986;&#65292;&#20294;&#24403;&#26102;&#25552;&#20379;&#30340;&#33021;&#21147;&#65292;&#23545;&#24456;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#20173;&#19981;&#36275;&#20197;&#26500;&#25104;&#36275;&#22815;&#24378;&#30340;&#21560;&#24341;&#21147;&#12290;&#20170;&#24180;&#30340;&#21464;&#21270;&#21017;&#26126;&#26174;&#26356;&#21153;&#23454;&#65306;API &#36827;&#19968;&#27493;&#25972;&#21512;&#65292;&#25903;&#25345;&#22270;&#20687;&#36755;&#20837;&#65292;&#21487;&#20197;&#26681;&#25454;&#20219;&#21153;&#36873;&#25321;&#35774;&#22791;&#31471;&#27169;&#22411;&#12289;&#31169;&#26377;&#20113;&#35745;&#31639;&#25110;&#31532;&#19977;&#26041;&#26381;&#21153;&#22120;&#27169;&#22411;&#65307;&#28385;&#36275;&#26465;&#20214;&#30340;&#24320;&#21457;&#32773;&#36824;&#21487;&#20197;&#20813;&#36153;&#20351;&#29992;&#36816;&#34892;&#22312;&#31169;&#26377;&#20113;&#35745;&#31639;&#19978;&#30340; Apple &#22522;&#30784;&#27169;&#22411;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#31995;&#32479;&#20063;&#24320;&#22987;&#20855;&#22791;&#26356;&#24378;&#30340;&#35270;&#22270;&#24863;&#30693;&#12289;App &#19978;&#19979;&#25991;&#29702;&#35299;&#65292;&#20197;&#21450;&#36890;&#36807; App Intents &#23558;&#29992;&#25143;&#37325;&#26032;&#24102;&#22238;&#24212;&#29992;&#30340;&#33021;&#21147;&#12290;</p><p>&#36825;&#20123;&#25913;&#36827;&#22823;&#24133;&#25552;&#21319;&#20102; Foundation Models &#30340;&#23454;&#29992;&#24615;&#21644;&#21560;&#24341;&#21147;&#12290;&#23427;&#19981;&#20877;&#21482;&#26159;&#19968;&#20010;&#8220;&#21487;&#20197;&#35797;&#35797;&#8221;&#30340;&#26694;&#26550;&#65292;&#32780;&#26159;&#24320;&#22987;&#20855;&#22791;&#36827;&#20837;&#30495;&#23454;&#20135;&#21697;&#27969;&#31243;&#30340;&#22522;&#30784;&#12290;&#19981;&#20986;&#24847;&#22806;&#65292;&#20170;&#24180;&#20250;&#26377;&#26356;&#22810;&#24320;&#21457;&#32773;&#24895;&#24847;&#23581;&#35797;&#36825;&#22871;&#31995;&#32479;&#65292;&#24182;&#36880;&#27493;&#23558;&#20854;&#32435;&#20837;&#24212;&#29992;&#30340;&#26680;&#24515;&#33021;&#21147;&#20043;&#19968;&#12290;</p><p><strong>SwiftUI</strong></p><p>&#23545;&#25105;&#26469;&#35828;&#65292;SwiftUI &#26368;&#22823;&#30340;&#21464;&#21270;&#26469;&#33258;&#23545;&#25991;&#26723;&#31867;&#24212;&#29992;&#30340;&#20840;&#38754;&#25903;&#25345;&#12290;&#23427;&#19981;&#20165;&#22686;&#21152;&#20102;&#22823;&#37327;&#26032; API&#65292;&#20063;&#23558;&#24515;&#26234;&#27169;&#22411;&#35843;&#25972;&#20026;&#8220;&#21487;&#35266;&#23519;&#25991;&#26723;&#23545;&#35937; + &#24322;&#27493;&#24555;&#29031; + &#19987;&#29992; reader / writer&#8221;&#12290;&#36825;&#26174;&#28982;&#26356;&#36866;&#21512;&#22797;&#26434;&#25991;&#26723; App&#65292;&#20063;&#26356;&#31526;&#21512;&#29616;&#20195; Swift &#22312; Observation &#21644; Concurrency &#26041;&#21521;&#19978;&#30340;&#25972;&#20307;&#28436;&#36827;&#12290;</p><p>Session &#20013;&#20063;&#25552;&#21040;&#65292;SwiftUI &#22312;&#24067;&#23616;&#19982;&#23481;&#22120;&#30456;&#20851;&#23454;&#29616;&#19978;&#32487;&#32493;&#20248;&#21270;&#65292;&#37096;&#20998;&#22330;&#26223;&#19979;&#30340;&#24615;&#33021;&#20250;&#26377;&#26126;&#26174;&#25552;&#21319;&#12290;&#36825;&#26159;&#24320;&#21457;&#32773;&#36843;&#20999;&#38656;&#35201;&#30340;&#25913;&#36827;&#12290;&#19981;&#36807;&#65292;SwiftUI &#20173;&#26410;&#25552;&#20379;&#33258;&#23450;&#20041; Lazy &#23481;&#22120;&#30340;&#33021;&#21147;&#65292;&#36825;&#26080;&#30097;&#26159;&#19968;&#20010;&#36951;&#25022;&#12290;<code>reorderable</code> &#21644; <code>swipeActions</code> &#19981;&#20877;&#23616;&#38480;&#20110;&#29305;&#23450;&#23481;&#22120;&#65292;&#36825;&#19981;&#21482;&#26159;&#36866;&#29992;&#33539;&#22260;&#30340;&#25193;&#22823;&#65292;&#20063;&#20307;&#29616;&#20102;&#24213;&#23618;&#20132;&#20114;&#36923;&#36753;&#30340;&#36827;&#19968;&#27493;&#25972;&#21512;&#12290;&#25110;&#35768;&#36825;&#20123;&#25972;&#21512;&#24102;&#26469;&#30340;&#25910;&#30410;&#65292;&#20250;&#22312;&#26126;&#24180;&#30340; API &#20013;&#21576;&#29616;&#24471;&#26356;&#21152;&#26126;&#26174;&#12290;</p><p><code>@State</code> &#25903;&#25345;&#24816;&#24615;&#21021;&#22987;&#21270;&#65292;iOS &#19978;&#30340; text selection &#24471;&#21040;&#22686;&#24378;&#65292;<code>alert</code> / <code>confirmationDialog</code> &#25552;&#20379;&#20102; <code>Binding&lt;T?&gt;</code> &#25903;&#25345;&#65292;&#36825;&#20123;&#37117;&#24456;&#22909;&#65292;&#21482;&#26159;&#24863;&#35273;&#26469;&#24471;&#31245;&#26202;&#20102;&#19968;&#20123;&#12290;interface &#20013;&#20986;&#29616;&#20102; <code>AnyNavigationTransition</code>&#65292;&#20294;&#30446;&#21069;&#20173;&#27809;&#26377;&#24320;&#25918;&#33258;&#23450;&#20041; transition &#30340;&#33021;&#21147;&#65292;&#21482;&#33021;&#22312;&#31995;&#32479;&#39044;&#35774;&#30340; zoom &#21644; crossFade &#20013;&#20999;&#25442;&#12290;</p><p>&#26032;&#30340; DataDetection &#26694;&#26550;&#20026; <code>Text</code> &#25552;&#20379;&#20102;&#26356;&#22909;&#30340;&#20869;&#23481;&#35782;&#21035;&#33021;&#21147;&#65307;toolbar &#33719;&#24471;&#20102;&#26356;&#22810;&#25511;&#21046;&#21147;&#65292;&#20063;&#33021;&#30475;&#20986; Apple &#23545;&#20351;&#29992; SwiftUI &#24320;&#21457; macOS &#24212;&#29992;&#30340;&#37325;&#35270;&#12290;&#25972;&#20307;&#26469;&#30475;&#65292;&#20170;&#24180;&#30340; SwiftUI &#24182;&#19981;&#26159;&#38752;&#26576;&#20010;&#21333;&#28857; API &#24102;&#26469;&#24778;&#21916;&#65292;&#32780;&#26159;&#36890;&#36807;&#19968;&#32452;&#34917;&#40784;&#21644;&#25972;&#21512;&#65292;&#35753;&#23427;&#26356;&#25509;&#36817;&#22797;&#26434; App &#30340;&#26085;&#24120;&#38656;&#27714;&#12290;</p><p><strong>SwiftData</strong></p><p>&#30456;&#36739;&#20110; <code>@Query</code> &#25903;&#25345; section fetch&#65292;&#20197;&#21450; <code>ResultsObserver</code> &#25552;&#20379;&#35270;&#22270;&#22806;&#35266;&#23519;&#26597;&#35810;&#32467;&#26524;&#21464;&#21270;&#30340;&#33021;&#21147;&#65292;&#25105;&#26356;&#30475;&#37325; <code>@Attribute(.codable)</code>&#12290;&#23427;&#25552;&#20379;&#20102;&#26356;&#26126;&#30830;&#30340;&#23384;&#20648;&#24847;&#22270;&#65292;&#20063;&#32473;&#20102;&#24320;&#21457;&#32773;&#19968;&#20010;&#36991;&#20813;&#38519;&#20837; composition &#40657;&#30418;&#30340;&#28192;&#36947;&#12290;</p><p>&#24403;&#28982;&#65292;<code>@Attribute(.codable)</code> &#24182;&#19981;&#26159;&#38134;&#24377;&#12290;&#23427;&#26356;&#20687;&#26159; SwiftData &#20026;&#19981;&#36879;&#26126; Codable &#31867;&#22411;&#25552;&#20379;&#30340;&#26126;&#30830;&#20986;&#21475;&#65306;&#36866;&#21512;&#23384;&#20648;&#20320;&#26080;&#27861;&#24314;&#27169;&#12289;&#20294;&#21448;&#30830;&#23454;&#38656;&#35201;&#25345;&#20037;&#21270;&#30340;&#22806;&#37096;&#31867;&#22411;&#65307;&#20195;&#20215;&#21017;&#26159;&#36825;&#37096;&#20998;&#20869;&#23481;&#26080;&#27861;&#21442;&#19982; SwiftData &#30340; predicate&#12289;sort &#21644; migration &#24863;&#30693;&#12290;&#27491;&#22240;&#22914;&#27492;&#65292;&#23427;&#30340;&#20215;&#20540;&#19981;&#22312;&#20110;&#8220;&#26356;&#24378;&#8221;&#65292;&#32780;&#22312;&#20110;&#8220;&#26356;&#26126;&#30830;&#8221;&#12290;</p><p>&#19981;&#36807;&#65292;SwiftData &#20173;&#27809;&#26377;&#25552;&#20379; public / shared &#25968;&#25454;&#30340;&#20113;&#31471;&#21516;&#27493;&#33021;&#21147;&#65292;&#20063;&#27809;&#26377;&#30475;&#21040;&#26356;&#26126;&#30830;&#30340;&#24615;&#33021;&#25913;&#21892;&#20449;&#21495;&#12290;&#36825;&#20123;&#38382;&#39064;&#20173;&#20250;&#38480;&#21046;&#23427;&#30340;&#37319;&#32435;&#29575;&#12290;&#23545;&#35768;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;SwiftData &#20170;&#24180;&#26356;&#20687;&#26159;&#22312;&#34917;&#40784;&#20851;&#38190;&#32570;&#21475;&#65292;&#32780;&#19981;&#26159;&#23436;&#25104;&#19968;&#27425;&#36275;&#20197;&#25913;&#21464;&#20449;&#24515;&#30340;&#36291;&#36801;&#12290;</p><p><strong>Xcode</strong></p><p>&#36807;&#21435;&#21322;&#24180;&#20013;&#65292;&#25105;&#30340;&#24320;&#21457;&#27169;&#24335;&#22522;&#26412;&#26159; Codex App / Claude App + Xcode&#65292;&#20854;&#20013; Xcode &#30340;&#20986;&#22330;&#26102;&#38388;&#26126;&#26174;&#23569;&#20110;&#21069;&#20004;&#32773;&#12290;&#22312;&#31616;&#21333;&#20351;&#29992; Xcode 27 &#21518;&#65292;&#25105;&#39044;&#35745;&#25509;&#19979;&#26469;&#23427;&#30340;&#20986;&#22330;&#26102;&#38388;&#20250;&#26126;&#26174;&#22686;&#21152;&#12290;&#25105;&#23588;&#20854;&#26399;&#24453;&#22312; UI &#31934;&#32454;&#35843;&#25972;&#12289;&#24615;&#33021;&#25913;&#21892;&#12289;&#39044;&#35272;&#39564;&#35777;&#31561;&#26041;&#38754;&#65292;Xcode &#20869;&#32622; AI &#27969;&#31243;&#33021;&#24102;&#26469;&#30340;&#21464;&#21270;&#12290;</p><p>Device Hub &#26080;&#30097;&#26159;&#19968;&#20010;&#24040;&#22823;&#24778;&#21916;&#12290;&#23427;&#23558;&#27169;&#25311;&#22120;&#12289;&#23454;&#20307;&#35774;&#22791;&#31649;&#29702;&#12289;&#31995;&#32479;&#29366;&#24577;&#27979;&#35797;&#21644;&#21160;&#24577;&#23610;&#23544;&#35843;&#25972;&#25972;&#21512;&#21040;&#19968;&#20010;&#26032;&#30340;&#24037;&#20316;&#27969;&#20013;&#65292;&#36825;&#23545;&#26085;&#24120;&#24320;&#21457;&#20307;&#39564;&#30340;&#24433;&#21709;&#21487;&#33021;&#27604;&#24456;&#22810;&#21333;&#20010; API &#26356;&#30452;&#25509;&#12290;&#19981;&#36807;&#65292;iPhone &#24212;&#29992;&#20063;&#24320;&#22987;&#25903;&#25345;&#21160;&#24577;&#23610;&#23544;&#35843;&#25972;&#65292;&#36825;&#20250;&#32473;&#24320;&#21457;&#32773;&#24102;&#26469;&#26032;&#30340;&#25361;&#25112;&#65292;&#23588;&#20854;&#26159;&#22312;&#25968;&#25454;&#21644;&#29366;&#24577;&#32452;&#32455;&#23618;&#38754;&#12290;&#38024;&#23545;&#19981;&#21516;&#23610;&#23544;&#30340;&#36866;&#37197;&#65292;&#24182;&#19981;&#26159;&#21482;&#38752;&#21160;&#24577;&#24067;&#23616;&#23481;&#22120;&#23601;&#33021;&#35299;&#20915;&#30340;&#12290;&#24456;&#22810;&#22330;&#26223;&#19979;&#65292;&#22823;&#23610;&#23544;&#21644;&#23567;&#23610;&#23544;&#23545;&#24212;&#30340;&#23548;&#33322;&#36923;&#36753;&#20250;&#26377;&#24456;&#22823;&#24046;&#24322;&#12290;</p><div><hr></div><p>&#20170;&#24180;&#25105;&#24212;&#35813;&#19981;&#20250;&#31532;&#19968;&#26102;&#38388;&#22260;&#32469; SwiftUI&#12289;SwiftData &#30340;&#26032; API &#20889;&#25991;&#31456;&#12290;&#30456;&#27604;&#36880;&#26465;&#20171;&#32461;&#26032;&#22686;&#25509;&#21475;&#65292;&#25105;&#26356;&#24819;&#33457;&#19968;&#20123;&#26102;&#38388;&#31995;&#32479;&#28040;&#21270;&#36825;&#20123;&#21464;&#21270;&#65292;&#26803;&#29702;&#23427;&#20204;&#32972;&#21518;&#30340;&#38544;&#21547;&#36923;&#36753;&#65306;Apple &#27491;&#22312;&#24590;&#26679;&#37325;&#26032;&#32452;&#32455; SwiftUI&#12289;SwiftData&#12289;Foundation Models &#19982; Xcode AI &#24037;&#20316;&#27969;&#20043;&#38388;&#30340;&#20851;&#31995;&#65292;&#20197;&#21450;&#36825;&#20123;&#21464;&#21270;&#26368;&#32456;&#20250;&#22914;&#20309;&#24433;&#21709;&#25105;&#20204;&#26500;&#24314; App &#30340;&#26041;&#24335;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-138/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/core-data-observation-freer-mental-model/?utm_source=fatbobman%20weekly%20issue%20139&amp;utm_medium=web">Core Data + Observation&#65306;&#20174;&#23646;&#24615;&#32423;&#21709;&#24212;&#21040;&#24515;&#26234;&#35299;&#25918;</a></strong></h3><p>Observation &#26694;&#26550;&#30340;&#25512;&#20986;&#65292;&#35753; SwiftUI &#30340;&#29366;&#24577;&#21709;&#24212;&#20174;&#23545;&#35937;&#32423;&#36827;&#19968;&#27493;&#32454;&#21270;&#21040;&#23646;&#24615;&#32423;&#65292;&#26174;&#33879;&#32531;&#35299;&#20102;&#35768;&#22810;&#30001;&#31895;&#31890;&#24230;&#35266;&#23519;&#24102;&#26469;&#30340;&#26080;&#25928;&#21047;&#26032;&#38382;&#39064;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#23427;&#35753;&#29366;&#24577;&#31649;&#29702;&#30340;&#22768;&#26126;&#24335;&#36923;&#36753;&#37325;&#26032;&#21464;&#24471;&#33258;&#28982;&#65306;&#35270;&#22270;&#21482;&#38656;&#35201;&#35835;&#21462;&#33258;&#24049;&#30495;&#27491;&#20381;&#36182;&#30340;&#23646;&#24615;&#65292;&#26694;&#26550;&#20415;&#33021;&#25454;&#27492;&#24314;&#31435;&#21709;&#24212;&#20851;&#31995;&#12290;&#20026;&#20102;&#35753; Core Data &#36825;&#20010;&#32769;&#29260;&#25345;&#20037;&#21270;&#26694;&#26550;&#20063;&#33021;&#20139;&#21463;&#21040;&#29616;&#20195; Swift &#29305;&#24615;&#30340;&#20415;&#21033;&#65292;&#25105;&#36817;&#26399;&#22312; <a href="https://fatbobman.com/zh/posts/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/">Core Data Evolution</a>&#65288;CDE&#65289;&#20013;&#25506;&#32034;&#24182;&#23454;&#29616;&#20102;&#23545; Observation &#30340;&#25903;&#25345;&#65292;&#36171;&#20104; <code>NSManagedObject</code> &#23646;&#24615;&#32423;&#30340;&#31934;&#30830;&#35266;&#23519;&#33021;&#21147;&#12290;&#26412;&#25991;&#23558;&#22260;&#32469;&#36825;&#19968;&#33021;&#21147;&#30340;&#21160;&#22240;&#12289;&#20351;&#29992;&#26041;&#24335;&#12289;&#23454;&#29616;&#24605;&#36335;&#12289;&#24037;&#31243;&#25361;&#25112;&#20197;&#21450;&#24320;&#21457;&#36807;&#31243;&#20013;&#30340;&#19968;&#20123;&#21462;&#33293;&#23637;&#24320;&#35752;&#35770;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-01">&#29992; Swift &#21644; WebAssembly &#25226; Goodnotes &#24102;&#21040; Web (Bringing Goodnotes to the web with Swift and WebAssembly)</a></strong></h3><p>&#20316;&#20026;&#33529;&#26524;&#29983;&#24577;&#20013;&#33879;&#21517;&#30340;&#31508;&#35760;&#24212;&#29992;&#65292;Goodnotes &#22312;&#36208;&#21521; Web &#24179;&#21488;&#26102;&#65292;&#24182;&#27809;&#26377;&#36873;&#25321;&#23436;&#20840;&#37325;&#20889;&#65292;&#32780;&#26159;&#25226;&#22810;&#24180;&#31215;&#32047;&#30340; Swift &#20195;&#30721;&#36890;&#36807; WebAssembly &#24102;&#21040;&#27983;&#35272;&#22120;&#29615;&#22659;&#37324;&#12290;<a href="https://x.com/kateinoigakukun">Yuta Saito</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#20102; Goodnotes &#22914;&#20309;&#22312; Web &#31471;&#20445;&#25345;&#19982;&#21407;&#29983; App &#19968;&#33268;&#30340;&#22696;&#36857;&#28210;&#26579;&#12289;&#25991;&#26723;&#21516;&#27493;&#12289;CRDT &#20914;&#31361;&#22788;&#29702;&#12289;&#25628;&#32034;&#32034;&#24341;&#19982;&#20132;&#20114;&#20307;&#39564;&#12290;Goodnotes Web &#30340; Swift &#20195;&#30721;&#35268;&#27169;&#32422; 220 &#19975;&#34892;&#65292;&#20854;&#20013; 147 &#19975;&#34892;&#26159;&#20849;&#20139;&#20195;&#30721;&#65307;&#26368;&#32456;&#29983;&#25104;&#30340; WebAssembly &#20108;&#36827;&#21046;&#32422; 50 MB&#65292;&#32463; Brotli &#21387;&#32553;&#21518;&#32422; 12 MB&#12290;&#36825;&#31687;&#25991;&#31456;&#30340;&#24847;&#20041;&#19981;&#21482;&#26159;&#23637;&#31034; Swift &#21487;&#20197;&#36816;&#34892;&#22312; Web &#19978;&#65292;&#32780;&#26159;&#21576;&#29616;&#20102;&#19968;&#20010;&#30495;&#23454;&#30340;&#22823;&#22411; Swift &#24212;&#29992;&#22914;&#20309;&#20511;&#21161; WebAssembly&#65292;&#25226;&#21407;&#26412;&#28145;&#26893;&#20110;&#33529;&#26524;&#24179;&#21488;&#30340;&#26680;&#24515;&#33021;&#21147;&#24310;&#23637;&#21040;&#26356;&#22810;&#24179;&#21488;&#12290;</p><blockquote><p>Yuta &#22312; iOS Conf 2026 &#30340;&#28436;&#35762; <a href="https://www.youtube.com/watch?v=ysD4_qqd-po">Swift at Scale: Where Performance Really Comes From</a> &#20063;&#24456;&#20540;&#24471;&#35266;&#30475;&#12290;&#30456;&#27604;&#23448;&#26041;&#25991;&#31456;&#23545; Goodnotes Web &#25972;&#20307;&#26550;&#26500;&#30340;&#20171;&#32461;&#65292;&#36825;&#22330;&#28436;&#35762;&#26356;&#32858;&#28966;&#19968;&#20010;&#30495;&#23454;&#30340; Swift &#24615;&#33021;&#26696;&#20363;&#65306;Goodnotes &#22242;&#38431;&#21457;&#29616;&#65292;&#19968;&#20010;&#29992;&#20110;&#32858;&#21512; UI &#23616;&#37096;&#26356;&#26032;&#30340; Update &#20540;&#31867;&#22411;&#38543;&#30528;&#21151;&#33021;&#22686;&#38271;&#33192;&#32960;&#21040;&#32422; 6 KB&#65292;&#24182;&#21253;&#21547;&#22823;&#37327; non-trivial &#25104;&#21592;&#12290;&#21363;&#20351;&#22823;&#22810;&#25968;&#26356;&#26032;&#21482;&#20351;&#29992;&#19968;&#20004;&#20010;&#23383;&#27573;&#65292;&#28909;&#36335;&#24452;&#20013;&#20173;&#35201;&#20026;&#22797;&#21046;&#21644;&#24341;&#29992;&#35745;&#25968;&#25104;&#26412;&#20184;&#36153;&#12290;&#22242;&#38431;&#26368;&#32456;&#36890;&#36807; hot-cold split &#37325;&#26500;&#25968;&#25454;&#32467;&#26500;&#65292;&#23558;&#39640;&#39057;&#23383;&#27573;&#20445;&#30041;&#22312;&#20027;&#32467;&#26500;&#20307;&#20013;&#65292;&#25226;&#20302;&#39057;&#26356;&#26032;&#31227;&#20837;&#21333;&#29420;&#23384;&#20648;&#65292;&#20351;&#31867;&#22411;&#22823;&#23567;&#20174;&#32422; 6 KB &#38477;&#21040;&#32422; 300 bytes&#65292;&#24182;&#24102;&#26469;&#32422; 42% &#30340; CPU &#26102;&#38388;&#25913;&#21892;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-02">Swift &#23448;&#26041;&#25104;&#31435;&#32593;&#32476;&#24037;&#20316;&#32452; (Announcing the Networking Workgroup)</a></strong></h3><p>Swift &#29616;&#22312;&#30340;&#32593;&#32476; API &#24182;&#19981;&#26159;&#32570;&#23569;&#36873;&#25321;&#65292;&#32780;&#26159;&#36873;&#25321;&#36807;&#22810;&#19988;&#23384;&#22312;&#37325;&#21472;&#65306;&#20174; Apple &#24179;&#21488;&#19978;&#30340; URLSession&#12289;Network.framework&#65292;&#21040;&#26381;&#21153;&#31471;&#29983;&#24577;&#20013;&#30340; SwiftNIO&#12289;AsyncHTTPClient&#65292;&#20877;&#21040;&#26356;&#24213;&#23618;&#30340; HTTP &#34920;&#31034;&#31867;&#22411;&#65292;&#24320;&#21457;&#32773;&#22312;&#19981;&#21516;&#24179;&#21488;&#12289;&#19981;&#21516;&#25277;&#35937;&#23618;&#20043;&#38388;&#24448;&#24448;&#38656;&#35201;&#38754;&#23545;&#19981;&#19968;&#33268;&#30340;&#27169;&#22411;&#21644;&#36801;&#31227;&#25104;&#26412;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#24456;&#22810; API &#20986;&#29616;&#20110; async/await&#12289;structured concurrency&#12289;actors&#12289;Sendable &#31561;&#29616;&#20195; Swift &#33021;&#21147;&#25104;&#29087;&#20043;&#21069;&#65292;&#22240;&#27492;&#24456;&#38590;&#33258;&#28982;&#22320;&#20307;&#29616;&#20170;&#22825; Swift &#22312;&#24182;&#21457;&#12289;&#23433;&#20840;&#24615;&#21644;&#36328;&#24179;&#21488;&#26041;&#38754;&#30340;&#35821;&#35328;&#20248;&#21183;&#12290;&#36825;&#20123;&#38382;&#39064;&#22312; <a href="https://github.com/swiftlang/swift-evolution/blob/main/visions/networking.md">A Vision for Networking in Swift</a> &#20013;&#26377;&#26356;&#31995;&#32479;&#30340;&#38416;&#36848;&#65292;&#32780; <a href="https://github.com/apple/swift-http-api-proposal">Swift HTTP API Proposal</a> &#21017;&#21487;&#20197;&#30475;&#20316;&#26159;&#23545;&#36825;&#19968;&#26041;&#21521;&#30340;&#26089;&#26399;&#25506;&#32034;&#12290;</p><p>&#26412;&#27425; Swift &#23448;&#26041;&#25104;&#31435; Networking Workgroup&#65292;&#37322;&#25918;&#20102;&#19968;&#20010;&#24456;&#37325;&#35201;&#30340;&#20449;&#21495;&#65306;Swift &#29983;&#24577;&#24320;&#22987;&#25226;&#32593;&#32476;&#33021;&#21147;&#20316;&#20026;&#19968;&#39033;&#38656;&#35201;&#38271;&#26399;&#27835;&#29702;&#30340;&#36328;&#24179;&#21488;&#22522;&#30784;&#35774;&#26045;&#26469;&#25512;&#36827;&#65292;&#32780;&#19981;&#21482;&#26159;&#35753;&#21508;&#20010;&#26694;&#26550;&#21644;&#21253;&#22312;&#21508;&#33258;&#22330;&#26223;&#20013;&#29420;&#31435;&#28436;&#36827;&#12290;&#24037;&#20316;&#32452;&#30340;&#30446;&#26631;&#19981;&#26159;&#31616;&#21333;&#26367;&#20195;&#29616;&#26377;&#26041;&#26696;&#65292;&#32780;&#26159;&#25512;&#21160;&#26356;&#28165;&#26224;&#30340;&#20998;&#23618;&#12289;&#26356;&#19968;&#33268;&#30340;&#31867;&#22411;&#12289;&#26356;&#22909;&#30340;&#20114;&#25805;&#20316;&#24615;&#21644;&#21487;&#35266;&#27979;&#24615;&#65292;&#35753; Swift &#22312; Apple &#24179;&#21488;&#12289;&#26381;&#21153;&#31471;&#12289;CLI&#12289;WebAssembly&#12289;Android&#12289;Windows &#20035;&#33267; Embedded Swift &#31561;&#22330;&#26223;&#20013;&#65292;&#37117;&#33021;&#25317;&#26377;&#26356;&#32479;&#19968;&#12289;&#29616;&#20195;&#19988;&#21487;&#25345;&#32493;&#30340;&#32593;&#32476;&#22522;&#30784;&#35774;&#26045;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-03">WWDC 26 &#24895;&#26395;&#21333;&#27719;&#24635; (WWDC 2026 Wish Lists)</a></strong></h3><p><a href="https://x.com/mjtsai">Michael Tsai</a> &#27719;&#24635;&#20102;&#22810;&#20301; Apple &#24320;&#21457;&#32773;&#22312; WWDC 2026 &#21069;&#30340;&#24895;&#26395;&#28165;&#21333;&#12290;&#21644;&#25105;&#22312; <a href="https://fatbobman.com/zh/weekly/issue-138/">&#19978;&#19968;&#26399;&#21608;&#25253;</a> &#20013;&#30340;&#26399;&#35768;&#31867;&#20284;&#65292;&#22823;&#22810;&#24320;&#21457;&#32773;&#22312;&#21628;&#21505;&#19968;&#27425;&#20559;&#21521; Snow Leopard &#24335;&#30340;&#36136;&#37327;&#20462;&#22797;&#65306;&#37325;&#26032;&#23457;&#35270; Liquid Glass &#22312; Mac &#19978;&#30340;&#21487;&#29992;&#24615;&#65292;&#20943;&#23569;&#31995;&#32479;&#21644;&#26694;&#26550;&#23618;&#38754;&#30340;&#19981;&#31283;&#23450;&#65292;&#20462;&#22797; iCloud &#21516;&#27493;&#12289;Spotlight&#12289;&#31995;&#32479;&#35774;&#32622;&#12289;&#38169;&#35823;&#25552;&#31034;&#12289;SwiftUI&#12289;Xcode&#12289;Simulator&#12289;&#32034;&#24341;&#21644;&#39044;&#35272;&#31561;&#38271;&#26399;&#24433;&#21709;&#26085;&#24120;&#24320;&#21457;&#20307;&#39564;&#30340;&#38382;&#39064;&#12290;&#20063;&#26377;&#19981;&#23569;&#24320;&#21457;&#32773;&#24076;&#26395;&#20170;&#24180;&#19981;&#35201;&#20877;&#24341;&#20837;&#22823;&#37327;&#20026;&#20102;&#36866;&#37197;&#26032;&#35774;&#35745;&#12289;&#26032;&#26694;&#26550;&#25110;&#26032;&#23457;&#26680;&#35201;&#27714;&#32780;&#20135;&#29983;&#30340;&#8220;&#24537;&#30860;&#24037;&#20316;&#8221;&#65292;&#32780;&#26159;&#32473;&#29616;&#26377;&#24179;&#21488;&#26356;&#22810;&#25171;&#30952;&#26102;&#38388;&#12290;</p><p>&#21478;&#19968;&#20010;&#26126;&#26174;&#20027;&#39064;&#26159; AI Agent &#26102;&#20195;&#19979;&#30340; Apple &#24320;&#21457;&#24037;&#20855;&#24212;&#35813;&#22914;&#20309;&#28436;&#36827;&#12290;&#22810;&#20301;&#20316;&#32773;&#37117;&#25552;&#21040;&#65292;&#24076;&#26395; Apple &#25552;&#20379;&#26356;&#23448;&#26041;&#30340; Agent Skills&#12289;MCP&#12289;CLI &#21644;&#21487;&#33258;&#21160;&#21270;&#25509;&#21475;&#65292;&#35753; AI &#33021;&#26356;&#21487;&#38752;&#22320;&#35835;&#21462;&#25991;&#26723;&#12289;&#25805;&#20316; Xcode&#12289;&#31649;&#29702; App Store Connect&#12289;&#20462;&#25913;&#39033;&#30446;&#37197;&#32622;&#12289;&#36816;&#34892;&#26500;&#24314;&#12289;&#25511;&#21046; Simulator&#65292;&#29978;&#33267;&#20197;&#26356;&#32467;&#26500;&#21270;&#30340;&#26041;&#24335;&#29702;&#35299; UI &#23618;&#32423;&#65292;&#32780;&#19981;&#26159;&#20381;&#36182;&#25130;&#22270;&#25110;&#33030;&#24369;&#30340; Accessibility &#20449;&#24687;&#12290;</p><blockquote><p>&#19982; AI &#26102;&#20195;&#30340;&#36866;&#37197;&#21644;&#31995;&#32479;&#31283;&#23450;&#24615;&#65292;&#30830;&#23454;&#27491;&#22312;&#25104;&#20026;&#26356;&#22810; Apple &#24320;&#21457;&#32773;&#30340;&#20849;&#21516;&#26399;&#24453;&#12290;&#30475;&#21040;&#26412;&#26399;&#21608;&#25253;&#26102;&#65292;WWDC 2026 &#24050;&#32463;&#24320;&#24149;&#65292;&#19981;&#30693;&#36947;&#35835;&#23436;&#36825;&#20123;&#24895;&#26395;&#20877;&#30475;&#20170;&#24180;&#30340;&#21457;&#24067;&#20250;&#65292;&#22823;&#23478;&#26159;&#21542;&#25214;&#21040;&#20102;&#24515;&#20013;&#26399;&#24453;&#30340;&#31572;&#26696;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-04">Apple-like</a></strong></h3><p>&#22312; WWDC 2026 &#21069;&#21518;&#65292;&#22260;&#32469; Apple &#26410;&#26469;&#26041;&#21521;&#30340;&#35752;&#35770;&#26126;&#26174;&#22686;&#22810;&#12290;&#24456;&#22810;&#20154;&#26399;&#24453; Apple &#8220;&#22238;&#21040;&#26681;&#26412;&#8221;&#25110;&#37325;&#26032;&#25214;&#22238;&#36807;&#21435;&#30340;&#29366;&#24577;&#65292;&#20294; <a href="https://mastodon.social/@_Davidsmith">David Smith</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#36873;&#25321;&#20102;&#19968;&#20010;&#26356;&#26377;&#24314;&#35774;&#24615;&#30340;&#38382;&#39064;&#65306;&#20160;&#20040;&#25165;&#26159; Apple-like&#65311;&#20316;&#20026;&#19968;&#21517;&#38271;&#26399;&#30340; Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#65292;&#20182;&#23558;&#36825;&#31181;&#27668;&#36136;&#24635;&#32467;&#20026;&#20960;&#20010;&#26041;&#21521;&#65306;The Best, and then Better&#65292;Excellence for Everyone&#65292;&#20197;&#21450; Beneficial and Brilliant&#12290;&#20063;&#23601;&#26159;&#25345;&#32493;&#36861;&#27714;&#39640;&#36136;&#37327;&#65292;&#21363;&#20351;&#24050;&#32463;&#39046;&#20808;&#20063;&#19981;&#33021;&#28040;&#32791;&#29992;&#25143;&#26399;&#24453;&#65307;&#22312;&#20215;&#26684;&#12289;&#21487;&#35775;&#38382;&#24615;&#21644;&#35774;&#35745;&#19978;&#35753;&#20248;&#31168;&#20307;&#39564;&#23613;&#21487;&#33021;&#26381;&#21153;&#26356;&#22810;&#20154;&#65307;&#24182;&#19988;&#36991;&#20813;&#29992;&#25805;&#32437;&#24615;&#30340;&#26041;&#24335;&#36861;&#36880;&#30701;&#26399;&#25351;&#26631;&#65292;&#32780;&#26159;&#29992;&#30495;&#27491;&#26377;&#30410;&#12289;&#20196;&#20154;&#24778;&#21916;&#30340;&#26041;&#24335;&#35299;&#20915;&#29992;&#25143;&#30340;&#38382;&#39064;&#12290;</p><blockquote><p>&#24403;&#25105;&#20204;&#26399;&#24453; Apple &#25913;&#21892;&#31995;&#32479;&#31283;&#23450;&#24615;&#12289;&#24320;&#21457;&#24037;&#20855;&#21644;&#24179;&#21488;&#20307;&#39564;&#26102;&#65292;&#36825;&#31687;&#25991;&#31456;&#20063;&#25552;&#37266;&#25105;&#20204;&#65292;&#29420;&#31435;&#24320;&#21457;&#32773;&#21644;&#24212;&#29992;&#22242;&#38431;&#21516;&#26679;&#21487;&#20197;&#29992;&#31867;&#20284;&#30340;&#26631;&#20934;&#23457;&#35270;&#33258;&#24049;&#30340;&#20135;&#21697;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-05">MarkdownPDF&#65306;&#32431; Swift &#32534;&#20889;&#30340; Markdown &#36716; PDF &#24341;&#25806;</a></strong></h3><p>MarkdownPDF &#26159; <a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263;</a> &#24320;&#28304;&#30340;&#32431; Swift Markdown &#36716; PDF &#24341;&#25806;&#12290;&#23427;&#19981;&#20381;&#36182; PDFKit&#12289;CoreGraphics&#12289;WebKit&#12289;Chromium&#12289;LaTeX&#12289;C PDF/Markdown &#24211;&#31561;&#24179;&#21488;&#25110;&#31995;&#32479;&#33021;&#21147;&#65292;Markdown &#35299;&#26512;&#12289;&#25490;&#29256;&#19982; PDF &#24207;&#21015;&#21270;&#37117;&#22312; Swift &#20869;&#23436;&#25104;&#12290;&#27491;&#22240;&#20026;&#26680;&#24515;&#36275;&#22815;&#32431;&#20928;&#12289;&#20381;&#36182;&#36275;&#22815;&#20811;&#21046;&#65292;&#39033;&#30446;&#20855;&#22791;&#33391;&#22909;&#30340;&#36328;&#24179;&#21488;&#28508;&#21147;&#65292;&#21487;&#20197;&#36866;&#37197;&#21040; WebAssembly/WASI &#36816;&#34892;&#30446;&#26631;&#65292;&#24182;&#22312;&#27983;&#35272;&#22120;&#26412;&#22320;&#23436;&#25104; Markdown &#21040; PDF &#30340;&#29983;&#25104;&#12290;&#20316;&#32773;&#25552;&#20379;&#30340; <a href="https://pdf.aleahim.com/">Playground</a> &#27491;&#26159;&#36825;&#19968;&#33021;&#21147;&#30340;&#28436;&#31034;&#12290;</p><blockquote><p>Goodnotes &#23637;&#31034;&#30340;&#26159;&#22823;&#22411; Swift &#24212;&#29992;&#36801;&#31227;&#21040; Web &#30340;&#24037;&#31243;&#23454;&#36341;&#65292;MarkdownPDF &#21017;&#25552;&#20379;&#20102;&#21478;&#19968;&#20010;&#35282;&#24230;&#65306;&#24403;&#26680;&#24515;&#36923;&#36753;&#36275;&#22815;&#32431;&#20928;&#12289;&#20381;&#36182;&#36275;&#22815;&#20811;&#21046;&#26102;&#65292;Swift &#24037;&#20855;&#26412;&#36523;&#20063;&#21487;&#20197;&#33258;&#28982;&#36866;&#37197;&#21040; WebAssembly &#36816;&#34892;&#29615;&#22659;&#12290;Swift &#36208;&#21521; Web&#65292;&#27491;&#22312;&#20174;&#27010;&#24565;&#39564;&#35777;&#21464;&#25104;&#36234;&#26469;&#36234;&#20855;&#20307;&#30340;&#24037;&#31243;&#36873;&#25321;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-06">AdaEngine&#65306;Swift-first &#24320;&#28304;&#28216;&#25103;&#24341;&#25806;</a></strong></h3><p>AdaEngine &#26159; <a href="https://x.com/SpectralDragon_">Vladislav Prusakov</a> &#25512;&#20986;&#30340;&#24320;&#28304; Swift-first &#28216;&#25103;&#24341;&#25806;&#19982;&#24212;&#29992;&#26694;&#26550;&#65292;&#36817;&#26399;&#21457;&#24067;&#20102;&#31532;&#19968;&#20010;&#20844;&#24320;&#37324;&#31243;&#30865; 0.1.0&#12290;&#39033;&#30446;&#38754;&#21521;&#36328;&#24179;&#21488;&#32780;&#35774;&#35745;&#65292;&#30446;&#21069; Apple &#24179;&#21488;&#26368;&#25104;&#29087;&#65292;&#24182;&#27491;&#22312;&#25512;&#36827; Windows&#12289;Linux&#12289;Android &#19982; WebAssembly/WebGPU &#31561;&#24179;&#21488;&#25903;&#25345;&#12290;</p><p>&#23427;&#20197; data-driven ECS &#20026;&#26680;&#24515;&#65292;&#32467;&#21512; Swift &#23439;&#12289;&#25554;&#20214;&#21270;&#26550;&#26500;&#12289;&#31867; SwiftUI &#30340; AdaUI&#12289;&#36164;&#20135;&#28909;&#37325;&#36733;&#12289;&#22330;&#26223;&#31995;&#32479;&#12289;2D &#29289;&#29702;&#12289;&#38899;&#39057;&#12289;&#36755;&#20837;&#65292;&#20197;&#21450; Metal / WebGPU &#28210;&#26579;&#21518;&#31471;&#31561;&#33021;&#21147;&#65292;&#35797;&#22270;&#35753; Swift &#19981;&#21482;&#26381;&#21153;&#20110; Apple &#24179;&#21488;&#24212;&#29992;&#65292;&#20063;&#33021;&#36827;&#20837;&#28216;&#25103;&#12289;&#20114;&#21160;&#24037;&#20855;&#19982;&#21019;&#24847;&#36719;&#20214;&#24320;&#21457;&#22330;&#26223;&#12290;</p><blockquote><p>Vladislav &#22312; <a href="https://adaengine.org/articles/introducing-adaengine-0-1-0">Introducing AdaEngine 0.1.0</a> &#19968;&#25991;&#20013;&#23545;&#39033;&#30446;&#20570;&#20102;&#26356;&#23436;&#25972;&#30340;&#20171;&#32461;&#12290;</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #138]]></title><description><![CDATA[Stability > New Features]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 01 Jun 2026 12:04:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!eZJ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eZJ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 424w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 848w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1272w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" width="1456" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112960,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/200084313?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 424w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 848w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1272w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@scottkelley?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Scott Kelley</a> on <a href="https://unsplash.com/photos/silhouette-of-stones-on-beach-during-sunset-ie0Hk-btBvw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Stability &gt; New Features</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-138/">Read on web &#8594;</a></p><p>Whether it is SwiftUI or SwiftData, these foundational frameworks, into which Apple poured so much hope, promised a bright future when they were first introduced. However, their actual trajectory seems to have diverged from the original blueprint. The deeper I dive into these frameworks, the more I marvel at their elegant architectural design&#8212;yet I also find myself speechless at their underwhelming implementation. Watching the halo around these designs gradually fade, I cannot help but feel a sense of wistfulness.</p><p>Rumor has it that in the upcoming operating systems to be released this year (including iOS 27 and macOS 27), Apple will adopt a refinement strategy similar to the Mac OS X Snow Leopard era. This means prioritizing system stability, performance optimization, clearing legacy code, and squashing bugs over introducing disruptive visual redesigns or a flurry of new low-level features. If this indeed turns out to be the case, it would be deeply reassuring. Looking back at <a href="https://fatbobman.com/en/weekly/issue-006/">Issue #006</a> of the weekly newsletter published more than two years ago, rumors also circulated back then that Apple would focus on fixing existing defects and improving performance. Yet, judging by the actual user experience over the past two years, that goal seems to have fallen short.</p><p>With WWDC 26 less than ten days away, rather than more flashy new features, what I look forward to most this year is Apple delivering a grounded, more stable experience for both developers and consumers.</p><p><a href="https://fatbobman.com/en/weekly/issue-137/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/taming-row-height-and-spacing-jumps/?utm_source=fatbobman%20weekly%20issue%20138&amp;utm_medium=web">Taming Row Height and Spacing Jumps in SwiftUI List with a Custom Layout</a></strong></h3><p>In SwiftUI, adding animation to view state changes often takes very little code, but <code>List</code> does not always produce the kind of smooth transition we expect. This is especially noticeable when the height of content inside a row changes dynamically&#8212;for example, when a subtitle goes from empty to non-empty, or when updated text changes its line count. In these cases, the system&#8217;s default layout process can easily cause the row height to jump abruptly, leading to visible flickering, clipping, or sudden spacing changes. Starting from this common issue, this article gradually breaks down why dynamic row-height animations fail in <code>List</code>, and builds a solution entirely based on native SwiftUI capabilities through custom <code>Layout</code>, <code>Animatable</code>, <code>LayoutValueKey</code>, and state decoupling.</p><p>This is not an article primarily aimed at providing a ready-to-use component. Rather than focusing only on the final code, I hope to use this problem to outline a way of investigating SwiftUI layout issues: first understand why the framework &#8220;does not behave as expected,&#8221; then reorganize state, measurement, and layout along the grain of its mechanisms, so that the animation happens at the correct level.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-01">Stateless Actors</a></strong></h3><p>Actors are usually understood as tools for protecting mutable state, so an actor with no stored properties&#8212;a seemingly stateless actor&#8212;naturally raises the question: does it have any reason to exist? This article explores that question through examples such as <code>NetworkClient</code>, custom global actors, custom executors, and file-system access. It shows that stateless actors are not necessarily unreasonable, but they may introduce extra costs such as serialization, protocol-adaptation difficulties, and type-system propagation. The key question is what problem they are actually solving.</p><p>The most important point in the article is the &#8220;first rule of actors&#8221; proposed by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a>: just like with any synchronization primitive, before using an actor, you should be able to clearly explain why it is necessary. A stateless actor is not necessarily wrong, but it may indicate that we are using an actor to solve a problem that does not actually require one. Only when it clearly takes on responsibilities such as isolation, serialization, executor adaptation, or protection of external state does it become a reasonable design.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-02">Building a Custom Data Store in SwiftData</a></strong></h3><p>Many developers tend to think of SwiftData as Apple&#8217;s high-level wrapper around SQLite, but that underestimates its potential as a framework for object-graph management and persistence coordination. Whether we are talking about SwiftData or Core Data, their more important capability is not merely reading and writing a database for us, but keeping model objects, queries, context management, and the underlying storage clearly separated. As long as the underlying storage can exchange data in the way the framework expects, the data source does not have to be SQLite.</p><p><a href="https://x.com/azamsharp">Mohammad Azam</a> demonstrates this by implementing a JSON-file-based custom data store. The article shows that what SwiftData exchanges with the underlying store is not the live object marked with <code>@Model</code>, but a converted snapshot. Once you understand this, the responsibility boundaries of <code>DataStoreConfiguration</code>, <code>DataStore</code>, <code>DefaultSnapshot</code>, <code>PersistentIdentifier</code>, and <code>fetch</code> / <code>save</code> become much clearer: SwiftData is responsible for model objects, observation, change tracking, and SwiftUI integration, while the custom store is only responsible for reading and writing snapshots.</p><blockquote><p>In <a href="https://fatbobman.com/en/weekly/issue-127/#datastorekit">Weekly Issue #127</a>, I recommended <a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a>, a more engineering-oriented custom DataStore project. It does not simply replace SwiftData&#8217;s backend with JSON or file storage; instead, it attempts to reimplement a SwiftData-aware SQLite storage layer based on custom DataStore, with extensive work around predicate translation, inheritance, caching, persistent history, and background prefetching. Developers who want to explore this direction further can use it as an advanced reference.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-03">Task Names in Swift Concurrency</a></strong></h3><p>GCD has queue labels, but tasks in Swift Concurrency long lacked a similar diagnostic identifier. With SE-0469 implemented in Swift 6.2, APIs such as <code>Task</code>, <code>Task.detached</code>, and task group <code>addTask</code> now support a <code>name</code> parameter. Developers can assign short, readable names to concurrent tasks, making it easier to locate specific execution units in LLDB, Instruments, and logs.</p><p><a href="https://x.com/iosartem">Artem Novichkov</a> walks through the usage and limitations of task names, and reminds developers that a task name should be treated as diagnostic information, not as part of program logic. It is useful for debugging, performance analysis, and log investigation, but it should not carry business state.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-04">UniqueBox, Ref, and MutableRef in Swift 6.4</a></strong></h3><p>Swift 6.4 continues the language&#8217;s evolution around ownership, borrow, noncopyable types, lifetime dependency, <code>Span</code>, and <code>MutableSpan</code>. Through the three types <code>UniqueBox</code>, <code>Ref</code>, and <code>MutableRef</code>, <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> introduces Swift&#8217;s new expressive capabilities around storage location, ownership, and access lifetime. Their significance is not that ordinary business code should immediately start using these low-level building blocks, but that Swift is gradually elevating relationships that previously depended on class boxes, <code>UnsafePointer</code>, or compiler-internal reasoning into language models that can be written into API shapes and checked by the type system.</p><p>Specifically, <code>UniqueBox</code> expresses that &#8220;a value lives on the heap and is owned by a single owner,&#8221; while <code>Ref</code> and <code>MutableRef</code> correspond to shared reading and exclusive mutation within a given lifetime. In other words, these types do not merely add a convenient API for a specific business scenario; they provide a more precise low-level vocabulary for describing &#8220;where a value lives, who owns it, and who can access it.&#8221;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-05">Clarification on Current CloudKit CKAsset File Size Limits</a></strong></h3><p>There has long been a confusing claim in the community around the file-size limit of <code>CKAsset</code>: some documentation has mentioned a 50 MB limit, but that mostly applies to CloudKit Web Services rather than <code>CKAsset</code> uploads through the native CloudKit framework on Apple platforms. This time, an Apple Frameworks Engineer gave a very clear answer on the developer forums: a single <code>CKAsset</code> supports up to 50 GB, assuming the user has enough remaining iCloud storage. Apps therefore need to correctly handle <code>CKError.quotaExceeded</code>.</p><blockquote><p>I am introducing this Q&amp;A in the weekly not just because it clarifies a number, but because it draws an important boundary: the fact that <code>CKAsset</code> supports large files does not mean large-file syncing is a simple or automatically reliable engineering problem. The follow-up discussion also mentions that large file transfers often need to consider background execution when an app is suspended or terminated, and can use long-lived CloudKit operations or schedule uploads through <code>BGProcessingTask</code> in <code>BackgroundTasks</code>. In other words, 50 GB answers the question &#8220;does CloudKit allow it?&#8221;; background transfer, failure recovery, quota handling, and user experience still need to be designed carefully by the app.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-06">Providing Useful Debugging Information for Agents</a></strong></h3><p>As AI agents become increasingly involved in compiling, testing, and diagnosing Swift projects, a very practical problem has become more prominent: the output of <code>xcodebuild</code> is simply too long. If the complete log is handed directly to an agent, it not only consumes a large number of tokens, but also risks burying the useful information in noise. The <a href="https://github.com/ldomaradzki/xcsift">Xcsift</a> tool introduced by <a href="https://www.linkedin.com/in/gamehelper/">Lee young-jun</a> in this article is designed precisely for this scenario. Unlike <code>xcpretty</code>, which is mainly aimed at human readability, Xcsift organizes <code>xcodebuild</code> / SwiftPM output into structured results that are more suitable for LLM consumption, including compile errors, warnings, test failures, coverage, and build timing.</p><blockquote><p>One easily overlooked detail in AI-assisted development workflows is that we should not let agents &#8220;read everything and decide what matters by themselves.&#8221; Instead, we should try to perform filtering and structuring at the tool layer first. Xcsift is a practical solution built on top of existing <code>xcodebuild</code> output, while the Tuist team previously discussed structured build data beyond build logs in <a href="https://l.fatbobman.com/w0113-09">Teaching AI to Read Xcode Builds</a>. Viewed together, they show two levels of build diagnosis in agentic coding: first reduce noise, then improve semantics.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-07">The MiniSwift Story</a></strong></h3><p>I previously recommended <a href="https://miniswift.run/">MiniSwift</a> in the weekly. At that time, the most fascinating part was that <a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> had implemented a Swift compiler frontend and WASM backend from scratch in C, without relying on LLVM, Clang, or Apple&#8217;s official toolchain. In this article, the author fills in the story behind the project: it did not begin as a &#8220;show-off compiler project,&#8221; but from a very specific question&#8212;could one get a more stable SwiftUI preview on canvas, free from the instability of WebView or Xcode Preview?</p><p>The reason MiniSwift is worth recommending again is that it has clearly taken a big step from an early compiler prototype toward its original goal. It no longer merely compiles Swift code to WASM; through a custom UIIR, canvas renderer, and diff engine, it can now <strong>render SwiftUI code directly into an interactive preview in the browser</strong>. Judging from the official demo, <code>@State</code>, basic layout, buttons, text, and some modifiers can already provide immediate feedback in the browser similar to SwiftUI Preview. In other words, the previously mentioned idea of a &#8220;SwiftUI browser preview that does not crash&#8221; is turning from a concept into a tool that can be experienced directly.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-08">MistKit: Letting Server-Side Swift Access CloudKit</a></strong></h3><p>Developed by <a href="https://x.com/leogdion">Leo G Dion</a>, MistKit has a clear goal: to wrap Apple&#8217;s CloudKit Web Services REST API in a modern Swift interface, allowing server-side Swift, command-line tools, and environments such as Linux and Windows&#8212;where the native CloudKit framework is unavailable&#8212;to access the same CloudKit containers. It is not meant to replace the CloudKit framework on Apple platforms, but to fill the gap in scenarios where the native framework cannot be used directly.</p><p>The project builds its lower-level client on top of swift-openapi-generator, while providing higher-level capabilities such as async/await, type-safe CloudKit operations, structured errors, record querying and CRUD, record / zone changes, asset upload, and user-identity-related functionality. For authentication, it supports API Token, Web Auth Token, and Server-to-Server. Server-to-Server is mainly for the public database, while operations involving user context in private or shared databases require Web Auth Token. This makes it suitable for background tasks, CLIs, content catalogs, public database management, and data bridging between the web and Apple devices.</p><blockquote><p>CloudKit is often seen as a &#8220;client-side service,&#8221; but MistKit makes it more natural for servers to participate in the CloudKit ecosystem. For example, a scheduled job could maintain a software version catalog, RSS aggregation content, or app asset packages in the public database; or, after user authorization, a backend could process data in a user&#8217;s private database. For apps already relying on CloudKit, it provides a path for extending data-processing capabilities beyond Apple platforms.</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#31283;&#23450; &gt; &#26032;&#21151;&#33021;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-138/">&#32593;&#39029;&#29256;</a></strong></p><p>&#26080;&#35770;&#26159; SwiftUI &#36824;&#26159; SwiftData&#65292;&#36825;&#20123;&#33529;&#26524;&#23492;&#20104;&#21402;&#26395;&#30340;&#22522;&#30784;&#26694;&#26550;&#65292;&#22312;&#25512;&#20986;&#26102;&#37117;&#25551;&#32472;&#20102;&#20805;&#28385;&#20809;&#26126;&#30340;&#26410;&#26469;&#65292;&#20294;&#23454;&#38469;&#36208;&#21183;&#20284;&#20046;&#37117;&#21644;&#26368;&#21021;&#30340;&#35774;&#23450;&#19981;&#22826;&#19968;&#26679;&#12290;&#24403;&#25105;&#36234;&#28145;&#20837;&#20102;&#35299;&#36825;&#20123;&#26694;&#26550;&#65292;&#23601;&#36234;&#23545;&#23427;&#20204;&#31934;&#22937;&#30340;&#26550;&#26500;&#35774;&#35745;&#25152;&#25240;&#26381;&#65292;&#21516;&#26102;&#20063;&#23545;&#37027;&#20123;&#19981;&#23613;&#22914;&#20154;&#24847;&#30340;&#23454;&#29616;&#24863;&#21040;&#26080;&#35821;&#12290;&#30524;&#30475;&#30528;&#36825;&#20123;&#35774;&#35745;&#30340;&#20809;&#29615;&#36880;&#28176;&#35114;&#21435;&#65292;&#24515;&#20013;&#19981;&#20813;&#21775;&#22040;&#12290;</p><p>&#20256;&#38395;&#33529;&#26524;&#22312;&#20170;&#24180;&#21363;&#23558;&#21457;&#24067;&#30340;&#20840;&#26032;&#25805;&#20316;&#31995;&#32479;&#65288;&#21253;&#25324; iOS 27 &#21644; macOS 27&#65289;&#20013;&#65292;&#23558;&#37319;&#21462;&#31867;&#20284;&#20110;&#24403;&#24180; Mac OS X Snow Leopard &#26102;&#20195;&#30340;&#35843;&#25972;&#31574;&#30053;&#8212;&#8212;&#23558;&#37325;&#24515;&#25918;&#22312;&#31995;&#32479;&#31283;&#23450;&#24615;&#12289;&#24615;&#33021;&#20248;&#21270;&#12289;&#28165;&#29702;&#32769;&#26087;&#20195;&#30721;&#21644;&#20462;&#22797; Bug &#19978;&#65292;&#32780;&#19981;&#26159;&#24341;&#20837;&#39072;&#35206;&#24615;&#30340;&#35270;&#35273;&#35774;&#35745;&#25110;&#32321;&#22810;&#30340;&#24213;&#23618;&#26032;&#21151;&#33021;&#12290;&#22914;&#26524;&#30495;&#33021;&#22914;&#27492;&#65292;&#37027;&#23454;&#22312;&#26159;&#20196;&#20154;&#27427;&#24944;&#12290;&#22238;&#30475;&#20004;&#24180;&#22810;&#21069;&#30340; <a href="https://fatbobman.com/zh/weekly/issue-006/">&#31532;&#20845;&#26399;&#21608;&#25253;</a>&#65292;&#24403;&#26102;&#20063;&#20256;&#20986;&#36807;&#33529;&#26524;&#35201;&#38598;&#20013;&#20462;&#22797;&#24444;&#26102;&#23384;&#22312;&#30340;&#32570;&#38519;&#24182;&#25552;&#39640;&#36719;&#20214;&#24615;&#33021;&#65292;&#20294;&#33267;&#23569;&#20174;&#36807;&#21435;&#20004;&#24180;&#30340;&#23454;&#38469;&#20351;&#29992;&#20307;&#39564;&#26469;&#30475;&#65292;&#36825;&#20010;&#30446;&#26631;&#20284;&#20046;&#26410;&#33021;&#36798;&#25104;&#12290;</p><p>&#36317;&#31163; WWDC 26 &#24050;&#32463;&#19981;&#36275;&#21313;&#22825;&#20102;&#12290;&#30456;&#36739;&#20110;&#26356;&#22810;&#12289;&#26356;&#28843;&#30340;&#26032;&#21151;&#33021;&#65292;&#25105;&#20170;&#24180;&#26356;&#26399;&#24453;&#33529;&#26524;&#33021;&#32473;&#24320;&#21457;&#32773;&#21644;&#28040;&#36153;&#32773;&#24102;&#26469;&#19968;&#27425;&#33050;&#36367;&#23454;&#22320;&#12289;&#26356;&#21152;&#31283;&#23450;&#30340;&#20307;&#39564;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-137/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/taming-row-height-and-spacing-jumps/?utm_source=fatbobman%20weekly%20issue%20138&amp;utm_medium=web">&#29992;&#33258;&#23450;&#20041; Layout &#21270;&#35299; SwiftUI List &#30340;&#34892;&#39640;&#19982;&#38388;&#36317;&#36339;&#21464;</a></strong></h3><p>&#22312; SwiftUI &#20013;&#65292;&#20026;&#35270;&#22270;&#29366;&#24577;&#21464;&#21270;&#28155;&#21152;&#21160;&#30011;&#24448;&#24448;&#21482;&#38656;&#35201;&#24456;&#23569;&#30340;&#20195;&#30721;&#65292;&#20294; <code>List</code> &#24182;&#19981;&#24635;&#33021;&#32473;&#20986;&#31526;&#21512;&#39044;&#26399;&#30340;&#36807;&#28193;&#25928;&#26524;&#12290;&#23588;&#20854;&#24403; row &#20869;&#37096;&#30340;&#20869;&#23481;&#39640;&#24230;&#21457;&#29983;&#21464;&#21270;&#26102;&#65292;&#20363;&#22914;&#21103;&#26631;&#39064;&#20174;&#26080;&#21040;&#26377;&#12289;&#25991;&#26412;&#34892;&#25968;&#22240;&#25968;&#25454;&#26356;&#26032;&#32780;&#25913;&#21464;&#65292;&#31995;&#32479;&#40664;&#35748;&#30340;&#24067;&#23616;&#36807;&#31243;&#24456;&#23481;&#26131;&#35753;&#34892;&#39640;&#30452;&#25509;&#30828;&#20999;&#65292;&#36827;&#32780;&#24102;&#26469;&#38378;&#28865;&#12289;&#35009;&#21098;&#25110; spacing &#31361;&#21464;&#12290;&#26412;&#25991;&#20174;&#36825;&#19968;&#24120;&#35265;&#38382;&#39064;&#20986;&#21457;&#65292;&#36880;&#27493;&#25286;&#35299; <code>List</code> &#21160;&#24577;&#34892;&#39640;&#21160;&#30011;&#22833;&#25928;&#30340;&#21407;&#22240;&#65292;&#24182;&#36890;&#36807;&#33258;&#23450;&#20041; <code>Layout</code>&#12289;<code>Animatable</code>&#12289;<code>LayoutValueKey</code> &#19982;&#29366;&#24577;&#35299;&#32806;&#65292;&#26500;&#24314;&#20986;&#19968;&#22871;&#23436;&#20840;&#22522;&#20110; SwiftUI &#21407;&#29983;&#33021;&#21147;&#30340;&#35299;&#20915;&#26041;&#26696;&#12290;</p><p>&#36825;&#24182;&#19981;&#26159;&#19968;&#31687;&#20197;&#25552;&#20379;&#24320;&#31665;&#21363;&#29992;&#32452;&#20214;&#20026;&#20027;&#35201;&#30446;&#26631;&#30340;&#25991;&#31456;&#12290;&#30456;&#27604;&#26368;&#32456;&#20195;&#30721;&#65292;&#25105;&#26356;&#24076;&#26395;&#20511;&#36825;&#20010;&#38382;&#39064;&#26803;&#29702;&#19968;&#26465; SwiftUI &#24067;&#23616;&#38382;&#39064;&#30340;&#25506;&#26597;&#36335;&#24452;&#65306;&#20808;&#29702;&#35299;&#26694;&#26550;&#20026;&#20160;&#20040;&#8220;&#19981;&#25353;&#39044;&#26399;&#24037;&#20316;&#8221;&#65292;&#20877;&#39034;&#30528;&#23427;&#30340;&#26426;&#21046;&#37325;&#26032;&#32452;&#32455;&#29366;&#24577;&#12289;&#27979;&#37327;&#19982;&#24067;&#23616;&#65292;&#35753;&#21160;&#30011;&#30495;&#27491;&#21457;&#29983;&#22312;&#27491;&#30830;&#30340;&#23618;&#32423;&#19978;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-01">&#26080;&#29366;&#24577; actor (Stateless Actors)</a></strong></h3><p>Actor &#36890;&#24120;&#34987;&#29702;&#35299;&#20026;&#8220;&#29992;&#26469;&#20445;&#25252;&#21487;&#21464;&#29366;&#24577;&#8221;&#30340;&#24037;&#20855;&#65292;&#22240;&#27492;&#19968;&#20010;&#27809;&#26377;&#23384;&#20648;&#23646;&#24615;&#12289;&#30475;&#20284;&#26080;&#29366;&#24577;&#30340; actor &#24456;&#23481;&#26131;&#35753;&#20154;&#30097;&#24785;&#65306;&#23427;&#21040;&#24213;&#26377;&#27809;&#26377;&#23384;&#22312;&#30340;&#24517;&#35201;&#65311;&#25991;&#31456;&#20197; <code>NetworkClient</code>&#12289;&#33258;&#23450;&#20041; global actor&#12289;custom executor &#19982;&#25991;&#20214;&#31995;&#32479;&#35775;&#38382;&#31561;&#22330;&#26223;&#20026;&#20363;&#65292;&#35828;&#26126;&#26080;&#29366;&#24577; actor &#24182;&#38750;&#19968;&#23450;&#19981;&#21512;&#29702;&#65292;&#20294;&#20063;&#21487;&#33021;&#24102;&#26469;&#20018;&#34892;&#21270;&#12289;&#21327;&#35758;&#36866;&#37197;&#21644;&#31867;&#22411;&#31995;&#32479;&#20256;&#25773;&#31561;&#39069;&#22806;&#25104;&#26412;&#65307;&#20851;&#38190;&#22312;&#20110;&#23427;&#31350;&#31455;&#26159;&#22312;&#35299;&#20915;&#20160;&#20040;&#38382;&#39064;&#12290;</p><p>&#36825;&#31687;&#25991;&#31456;&#26368;&#20540;&#24471;&#20851;&#27880;&#30340;&#28857;&#65292;&#26159; <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#25552;&#20986;&#30340;&#8220;actor &#31532;&#19968;&#21407;&#21017;&#8221;&#65306;&#20687;&#20351;&#29992;&#20219;&#20309;&#21516;&#27493;&#21407;&#35821;&#19968;&#26679;&#65292;&#22312;&#20351;&#29992; actor &#20043;&#21069;&#65292;&#24212;&#35813;&#33021;&#28165;&#26970;&#35828;&#26126;&#23427;&#20026;&#20160;&#20040;&#24517;&#35201;&#12290;&#26080;&#29366;&#24577; actor &#24182;&#19981;&#19968;&#23450;&#26159;&#38169;&#35823;&#65292;&#20294;&#23427;&#24456;&#21487;&#33021;&#24847;&#21619;&#30528;&#25105;&#20204;&#27491;&#22312;&#29992; actor &#35299;&#20915;&#19968;&#20010;&#24182;&#19981;&#38656;&#35201; actor &#30340;&#38382;&#39064;&#65307;&#21482;&#26377;&#24403;&#23427;&#30830;&#23454;&#25215;&#25285;&#20102;&#38548;&#31163;&#12289;&#20018;&#34892;&#21270;&#12289;executor &#36866;&#37197;&#25110;&#22806;&#37096;&#29366;&#24577;&#20445;&#25252;&#31561;&#26126;&#30830;&#32844;&#36131;&#26102;&#65292;&#25165;&#26159;&#21512;&#29702;&#30340;&#35774;&#35745;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-02">&#20026; SwiftData &#26500;&#24314;&#33258;&#23450;&#20041;&#23384;&#20648;&#26684;&#24335; (Building a Custom Data Store in SwiftData)</a></strong></h3><p>&#24456;&#22810;&#24320;&#21457;&#32773;&#23481;&#26131;&#23558; SwiftData &#29702;&#35299;&#20026;&#33529;&#26524;&#23448;&#26041;&#23545; SQLite &#30340;&#39640;&#23618;&#23553;&#35013;&#65292;&#20294;&#36825;&#20854;&#23454;&#20302;&#20272;&#20102;&#23427;&#20316;&#20026;&#23545;&#35937;&#22270;&#31649;&#29702;&#19982;&#25345;&#20037;&#21270;&#21327;&#35843;&#26694;&#26550;&#30340;&#28508;&#21147;&#12290;&#26080;&#35770;&#26159; SwiftData &#36824;&#26159; Core Data&#65292;&#26356;&#37325;&#35201;&#30340;&#33021;&#21147;&#37117;&#19981;&#21482;&#26159;&#26367;&#25105;&#20204;&#35835;&#20889;&#25968;&#25454;&#24211;&#65292;&#32780;&#26159;&#35753;&#27169;&#22411;&#23545;&#35937;&#12289;&#26597;&#35810;&#12289;&#19978;&#19979;&#25991;&#31649;&#29702;&#19982;&#24213;&#23618;&#23384;&#20648;&#20043;&#38388;&#20445;&#25345;&#28165;&#26224;&#20998;&#24037;&#12290;&#21482;&#35201;&#24213;&#23618;&#23384;&#20648;&#33021;&#22815;&#25353;&#29031;&#26694;&#26550;&#35201;&#27714;&#23436;&#25104;&#25968;&#25454;&#20132;&#25442;&#65292;&#25968;&#25454;&#26469;&#28304;&#23601;&#19981;&#19968;&#23450;&#38750;&#24471;&#26159; SQLite&#12290;</p><p><a href="https://x.com/azamsharp">Mohammad Azam</a> &#36890;&#36807;&#23454;&#29616;&#19968;&#20010;&#22522;&#20110; JSON &#25991;&#20214;&#30340; custom data store&#65292;&#23637;&#31034;&#20102; SwiftData &#19982;&#24213;&#23618;&#23384;&#20648;&#20043;&#38388;&#30495;&#27491;&#20132;&#25442;&#30340;&#24182;&#19981;&#26159; <code>@Model</code> &#26631;&#35760;&#30340;&#23454;&#26102;&#23545;&#35937;&#65292;&#32780;&#26159;&#32463;&#36807;&#36716;&#25442;&#21518;&#30340; snapshot&#12290;&#29702;&#35299;&#36825;&#19968;&#28857;&#20043;&#21518;&#65292;<code>DataStoreConfiguration</code>&#12289;<code>DataStore</code>&#12289;<code>DefaultSnapshot</code>&#12289;<code>PersistentIdentifier</code> &#20197;&#21450; <code>fetch</code> / <code>save</code> &#30340;&#32844;&#36131;&#36793;&#30028;&#37117;&#20250;&#21464;&#24471;&#28165;&#26224;&#36215;&#26469;&#65306;SwiftData &#36127;&#36131;&#27169;&#22411;&#23545;&#35937;&#12289;&#35266;&#23519;&#12289;&#21464;&#26356;&#36861;&#36394;&#21644; SwiftUI &#38598;&#25104;&#65292;&#32780;&#33258;&#23450;&#20041; store &#21482;&#36127;&#36131;&#35835;&#21462;&#21644;&#20889;&#20837;&#24555;&#29031;&#12290;</p><blockquote><p>&#22312; <a href="https://fatbobman.com/zh/weekly/issue-127/#datastorekit">#127 &#26399;&#21608;&#25253;&#20013;</a>&#65292;&#25105;&#26366;&#25512;&#33616;&#36807;&#19968;&#20010;&#26356;&#24037;&#31243;&#21270;&#30340;&#33258;&#23450;&#20041; DataStore &#39033;&#30446; <a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a>&#12290;&#23427;&#24182;&#19981;&#26159;&#31616;&#21333;&#22320;&#25226; SwiftData &#21518;&#31471;&#25442;&#25104; JSON &#25110;&#25991;&#20214;&#23384;&#20648;&#65292;&#32780;&#26159;&#23581;&#35797;&#22522;&#20110; custom DataStore &#37325;&#26032;&#23454;&#29616;&#19968;&#22871; SwiftData-aware &#30340; SQLite &#23384;&#20648;&#23618;&#65292;&#24182;&#22312; predicate &#32763;&#35793;&#12289;&#32487;&#25215;&#12289;&#32531;&#23384;&#12289;&#21382;&#21490;&#36861;&#36394;&#20197;&#21450;&#21518;&#21488;&#39044;&#21462;&#31561;&#26041;&#38754;&#20570;&#20102;&#22823;&#37327;&#25193;&#23637;&#12290;&#24819;&#22312;&#27492;&#26041;&#21521;&#36827;&#19968;&#27493;&#30740;&#31350;&#30340;&#24320;&#21457;&#32773;&#65292;&#21487;&#20197;&#23558;&#23427;&#20316;&#20026;&#36827;&#38454;&#21442;&#32771;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-03">&#32473; Swift &#24182;&#21457;&#20219;&#21153;&#21629;&#21517; (Task Names in Swift Concurrency)</a></strong></h3><p>GCD &#26377; queue label&#65292;Swift Concurrency &#30340; task &#21364;&#38271;&#26399;&#32570;&#23569;&#31867;&#20284;&#30340;&#35786;&#26029;&#26631;&#35782;&#12290;&#38543;&#30528; SE-0469 &#22312; Swift 6.2 &#20013;&#23454;&#29616;&#65292;Task&#12289;Task.detached&#12289;task group &#30340; addTask &#31561; API &#24320;&#22987;&#25903;&#25345; name &#21442;&#25968;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#20026;&#24182;&#21457;&#20219;&#21153;&#28155;&#21152;&#31616;&#30701;&#12289;&#21487;&#35835;&#30340;&#21517;&#31216;&#65292;&#20174;&#32780;&#22312; LLDB&#12289;Instruments &#21644;&#26085;&#24535;&#20013;&#26356;&#23481;&#26131;&#23450;&#20301;&#20855;&#20307;&#25191;&#34892;&#21333;&#20803;&#12290;</p><p><a href="https://x.com/iosartem">Artem Novichkov</a> &#26803;&#29702;&#20102; task name &#30340;&#29992;&#27861;&#19982;&#38480;&#21046;&#65292;&#24182;&#25552;&#37266;&#24320;&#21457;&#32773;&#65306;task name &#24212;&#21482;&#20316;&#20026;&#35786;&#26029;&#20449;&#24687;&#65292;&#32780;&#19981;&#26159;&#31243;&#24207;&#36923;&#36753;&#30340;&#19968;&#37096;&#20998;&#12290;&#23427;&#36866;&#21512;&#36741;&#21161;&#35843;&#35797;&#12289;&#24615;&#33021;&#20998;&#26512;&#21644;&#26085;&#24535;&#25490;&#26597;&#65292;&#20294;&#19981;&#24212;&#25215;&#36733;&#19994;&#21153;&#29366;&#24577;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-04">UniqueBox, Ref, and MutableRef in Swift 6.4</a>&#65532;</strong></h3><p>Swift 6.4 &#24310;&#32493;&#20102;&#36817;&#20960;&#24180;&#22260;&#32469; ownership&#12289;borrow&#12289;noncopyable type&#12289;lifetime dependency&#12289;<code>Span</code> &#19982; <code>MutableSpan</code> &#31561;&#26041;&#21521;&#30340;&#28436;&#36827;&#12290;<a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> &#36890;&#36807; <code>UniqueBox</code>&#12289;<code>Ref</code> &#21644; <code>MutableRef</code> &#36825;&#19977;&#20010;&#31867;&#22411;&#65292;&#20171;&#32461;&#20102; Swift &#22312;&#23384;&#20648;&#20301;&#32622;&#12289;&#25152;&#26377;&#26435;&#19982;&#35775;&#38382;&#29983;&#21629;&#21608;&#26399;&#19978;&#30340;&#26032;&#34920;&#36798;&#33021;&#21147;&#12290;&#23427;&#20204;&#30340;&#24847;&#20041;&#24182;&#19981;&#26159;&#40723;&#21169;&#26222;&#36890;&#19994;&#21153;&#20195;&#30721;&#31435;&#21051;&#25913;&#29992;&#36825;&#20123;&#24213;&#23618;&#26500;&#20214;&#65292;&#32780;&#26159;&#23637;&#31034; Swift &#27491;&#22312;&#25226;&#36807;&#21435;&#20381;&#36182; class box&#12289;UnsafePointer &#25110;&#32534;&#35793;&#22120;&#20869;&#37096;&#25512;&#29702;&#30340;&#20851;&#31995;&#65292;&#36880;&#27493;&#25552;&#21319;&#20026;&#21487;&#20197;&#20889;&#36827; API &#24418;&#29366;&#12289;&#24182;&#30001;&#31867;&#22411;&#31995;&#32479;&#26816;&#26597;&#30340;&#35821;&#35328;&#27169;&#22411;&#12290;</p><p>&#20854;&#20013;&#65292;<code>UniqueBox</code> &#29992;&#26469;&#34920;&#36798;&#8220;&#19968;&#20010;&#20540;&#20301;&#20110;&#22534;&#19978;&#65292;&#24182;&#30001;&#21333;&#19968;&#25152;&#26377;&#32773;&#25345;&#26377;&#8221;&#65307;<code>Ref</code> &#21644; <code>MutableRef</code> &#21017;&#20998;&#21035;&#23545;&#24212;&#26576;&#27573;&#29983;&#21629;&#21608;&#26399;&#20869;&#30340;&#20849;&#20139;&#35835;&#21462;&#19982;&#29420;&#21344;&#20462;&#25913;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#36825;&#20123;&#31867;&#22411;&#34917;&#19978;&#30340;&#19981;&#26159;&#26576;&#20010;&#20855;&#20307;&#19994;&#21153;&#22330;&#26223;&#30340;&#20415;&#21033; API&#65292;&#32780;&#26159;&#19968;&#22871;&#26356;&#31934;&#30830;&#25551;&#36848;&#8220;&#20540;&#22312;&#21738;&#37324;&#12289;&#24402;&#35841;&#25152;&#26377;&#12289;&#35841;&#33021;&#35775;&#38382;&#8221;&#30340;&#24213;&#23618;&#35789;&#27719;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-05">&#20851;&#20110; CloudKit CKAsset &#24403;&#21069;&#25991;&#20214;&#22823;&#23567;&#38480;&#21046;&#30340;&#28548;&#28165; (Clarification on Current CloudKit CKAsset File Size Limits)</a>&#65532;</strong></h3><p>&#20851;&#20110; <code>CKAsset</code> &#30340;&#25991;&#20214;&#22823;&#23567;&#19978;&#38480;&#65292;&#31038;&#21306;&#37324;&#38271;&#26399;&#23384;&#22312;&#19968;&#20010;&#23481;&#26131;&#28151;&#28102;&#30340;&#35828;&#27861;&#65306;&#26377;&#20123;&#25991;&#26723;&#20013;&#25552;&#21040;&#36807; 50 MB &#38480;&#21046;&#65292;&#20294;&#37027;&#26356;&#22810;&#23545;&#24212; CloudKit Web Services&#65292;&#32780;&#19981;&#26159; Apple &#24179;&#21488;&#19978;&#36890;&#36807;&#21407;&#29983; CloudKit framework &#19978;&#20256;&#30340; <code>CKAsset</code>&#12290;&#36825;&#27425; Apple Frameworks Engineer &#22312;&#24320;&#21457;&#32773;&#35770;&#22363;&#20013;&#32473;&#20986;&#20102;&#19968;&#20010;&#38750;&#24120;&#26126;&#30830;&#30340;&#22238;&#31572;&#65306;&#21333;&#20010; <code>CKAsset</code> &#26368;&#39640;&#25903;&#25345; 50 GB&#65292;&#21069;&#25552;&#26159;&#29992;&#25143;&#20173;&#26377;&#36275;&#22815;&#30340; iCloud &#23384;&#20648;&#31354;&#38388;&#65292;&#22240;&#27492;&#24212;&#29992;&#38656;&#35201;&#27491;&#30830;&#22788;&#29702; <code>CKError.quotaExceeded</code>&#12290;</p><blockquote><p>&#20043;&#25152;&#20197;&#22312;&#21608;&#25253;&#20013;&#20171;&#32461;&#36825;&#20010;&#38382;&#31572;&#65292;&#24182;&#19981;&#21482;&#26159;&#22240;&#20026;&#23427;&#28548;&#28165;&#20102;&#19968;&#20010;&#25968;&#23383;&#65292;&#32780;&#26159;&#22240;&#20026;&#23427;&#21010;&#28165;&#20102;&#19968;&#20010;&#37325;&#35201;&#36793;&#30028;&#65306;<code>CKAsset</code> &#25903;&#25345;&#22823;&#25991;&#20214;&#65292;&#24182;&#19981;&#31561;&#20110;&#22823;&#25991;&#20214;&#21516;&#27493;&#23601;&#26159;&#31616;&#21333;&#21487;&#38752;&#30340;&#24037;&#31243;&#38382;&#39064;&#12290;&#21518;&#32493;&#35752;&#35770;&#20063;&#25552;&#21040;&#65292;&#22823;&#25991;&#20214;&#20256;&#36755;&#24448;&#24448;&#38656;&#35201;&#32771;&#34385;&#24212;&#29992;&#25346;&#36215;&#12289;&#32456;&#27490;&#21518;&#30340;&#21518;&#21488;&#25191;&#34892;&#33021;&#21147;&#65292;&#21487;&#20197;&#32467;&#21512; long-lived CloudKit operations&#65292;&#25110;&#36890;&#36807; <code>BackgroundTasks</code> &#20013;&#30340; <code>BGProcessingTask</code> &#26469;&#23433;&#25490;&#19978;&#20256;&#20219;&#21153;&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;50 GB &#22238;&#31572;&#30340;&#26159;&#8220;CloudKit &#26159;&#21542;&#20801;&#35768;&#8221;&#65292;&#32780;&#21518;&#21488;&#20256;&#36755;&#12289;&#22833;&#36133;&#24674;&#22797;&#12289;&#37197;&#39069;&#22788;&#29702;&#21644;&#29992;&#25143;&#20307;&#39564;&#65292;&#20173;&#28982;&#38656;&#35201;&#24212;&#29992;&#33258;&#24049;&#35748;&#30495;&#35774;&#35745;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-06">&#20026; Agent &#25552;&#20379;&#26377;&#25928;&#30340;&#35843;&#35797;&#20449;&#24687; (Don&#8217;t allow the agent reading whole output of Xcodebuild)</a></strong></h3><p>&#38543;&#30528; AI agent &#36234;&#26469;&#36234;&#22810;&#22320;&#21442;&#19982; Swift &#39033;&#30446;&#30340;&#32534;&#35793;&#12289;&#27979;&#35797;&#21644;&#38382;&#39064;&#23450;&#20301;&#65292;&#19968;&#20010;&#24456;&#29616;&#23454;&#30340;&#38382;&#39064;&#24320;&#22987;&#21464;&#24471;&#31361;&#20986;&#65306;<code>xcodebuild</code> &#30340;&#36755;&#20986;&#23454;&#22312;&#22826;&#38271;&#20102;&#12290;&#22914;&#26524;&#30452;&#25509;&#25226;&#23436;&#25972;&#26085;&#24535;&#20132;&#32473; agent&#65292;&#19981;&#20165;&#20250;&#28040;&#32791;&#22823;&#37327; token&#65292;&#20063;&#23481;&#26131;&#35753;&#30495;&#27491;&#26377;&#29992;&#30340;&#20449;&#24687;&#34987;&#28153;&#27809;&#22312;&#22122;&#22768;&#20013;&#12290;<a href="https://www.linkedin.com/in/gamehelper/">Lee young-jun</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#30340; <a href="https://github.com/ldomaradzki/xcsift">Xcsift</a> &#27491;&#26159;&#20026;&#36825;&#20010;&#22330;&#26223;&#35774;&#35745;&#30340;&#24037;&#20855;&#65306;&#23427;&#19981;&#20687; <code>xcpretty</code> &#37027;&#26679;&#20027;&#35201;&#38754;&#21521;&#20154;&#31867;&#38405;&#35835;&#65292;&#32780;&#26159;&#25226; <code>xcodebuild</code> / SwiftPM &#30340;&#36755;&#20986;&#25972;&#29702;&#25104;&#26356;&#36866;&#21512; LLM &#28040;&#36153;&#30340;&#32467;&#26500;&#21270;&#32467;&#26524;&#65292;&#20363;&#22914;&#32534;&#35793;&#38169;&#35823;&#12289;&#35686;&#21578;&#12289;&#27979;&#35797;&#22833;&#36133;&#12289;&#35206;&#30422;&#29575;&#21644;&#26500;&#24314;&#32791;&#26102;&#31561;&#12290;</p><blockquote><p>AI &#36741;&#21161;&#24320;&#21457;&#24037;&#20316;&#27969;&#20013;&#19968;&#20010;&#23481;&#26131;&#34987;&#24573;&#30053;&#30340;&#32454;&#33410;&#26159;&#65306;&#25105;&#20204;&#19981;&#24212;&#35813;&#35753; agent &#8220;&#35835;&#23436;&#25152;&#26377;&#20869;&#23481;&#20877;&#33258;&#24049;&#21028;&#26029;&#37325;&#28857;&#8221;&#65292;&#32780;&#24212;&#35813;&#23613;&#37327;&#22312;&#24037;&#20855;&#23618;&#20808;&#23436;&#25104;&#20449;&#24687;&#31579;&#36873;&#19982;&#32467;&#26500;&#21270;&#12290;Xcsift &#26159;&#19968;&#20010;&#22522;&#20110;&#29616;&#26377; <code>xcodebuild</code> &#36755;&#20986;&#30340;&#23454;&#29992;&#26041;&#26696;&#65292;&#32780; Tuist &#22242;&#38431;&#27492;&#21069;&#22312; <a href="https://l.fatbobman.com/w0113-09">Teaching AI to Read Xcode Builds</a> &#20013;&#21017;&#36827;&#19968;&#27493;&#35752;&#35770;&#20102;&#26500;&#24314;&#26085;&#24535;&#20043;&#22806;&#30340;&#32467;&#26500;&#21270; build data&#12290;&#20004;&#32773;&#25918;&#22312;&#19968;&#36215;&#30475;&#65292;&#27491;&#22909;&#20307;&#29616;&#20102; agentic coding &#22312;&#26500;&#24314;&#35786;&#26029;&#19978;&#30340;&#20004;&#20010;&#23618;&#27425;&#65306;&#20808;&#20943;&#23569;&#22122;&#22768;&#65292;&#20877;&#25552;&#21319;&#35821;&#20041;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-07">The MiniSwift Story</a>&#65532;</strong></h3><p>&#25105;&#22312;&#20043;&#21069;&#30340;&#21608;&#25253;&#20013;&#26366;&#25512;&#33616;&#36807; <a href="https://miniswift.run/">MiniSwift</a>&#65292;&#24403;&#26102;&#26368;&#21560;&#24341;&#20154;&#30340;&#37096;&#20998;&#65292;&#26159; <a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> &#22312;&#19981;&#20381;&#36182; LLVM&#12289;Clang &#25110; Apple &#23448;&#26041;&#24037;&#20855;&#38142;&#30340;&#24773;&#20917;&#19979;&#65292;&#29992; C &#20174;&#38646;&#23454;&#29616;&#20102; Swift &#32534;&#35793;&#22120;&#21069;&#31471;&#19982; WASM &#21518;&#31471;&#12290;&#32780;&#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;&#20316;&#32773;&#34917;&#20840;&#20102;&#39033;&#30446;&#32972;&#21518;&#30340;&#26469;&#40857;&#21435;&#33033;&#65306;&#23427;&#26368;&#21021;&#24182;&#19981;&#26159;&#20026;&#20102;&#8220;&#28843;&#25216;&#24335;&#22320;&#20889;&#19968;&#20010;&#32534;&#35793;&#22120;&#8221;&#65292;&#32780;&#26159;&#28304;&#20110;&#19968;&#20010;&#24456;&#20855;&#20307;&#30340;&#38382;&#39064;&#8212;&#8212;&#33021;&#19981;&#33021;&#25670;&#33073; WebView &#25110; Xcode Preview &#30340;&#19981;&#31283;&#23450;&#65292;&#29992; canvas &#24471;&#21040;&#26356;&#31283;&#23450;&#30340; SwiftUI &#39044;&#35272;&#12290;</p><p>&#36825;&#27425;&#20540;&#24471;&#20877;&#27425;&#25512;&#33616;&#65292;&#26159;&#22240;&#20026; MiniSwift &#24050;&#32463;&#26126;&#26174;&#20174;&#26089;&#26399; compiler prototype &#21521;&#23427;&#26368;&#21021;&#30340;&#30446;&#26631;&#36808;&#36827;&#20102;&#19968;&#22823;&#27493;&#12290;&#29616;&#22312;&#23427;&#19981;&#21482;&#26159;&#25226; Swift &#20195;&#30721;&#32534;&#35793;&#21040; WASM&#65292;&#32780;&#26159;&#36827;&#19968;&#27493;&#36890;&#36807;&#33258;&#23450;&#20041; UIIR&#12289;canvas renderer &#21644; diff engine&#65292;<strong>&#25226; SwiftUI &#20195;&#30721;&#30452;&#25509;&#28210;&#26579;&#25104;&#27983;&#35272;&#22120;&#20013;&#30340;&#21487;&#20132;&#20114;&#39044;&#35272;</strong>&#65307;&#20174;&#23448;&#32593;&#23637;&#31034;&#26469;&#30475;&#65292;<code>@State</code>&#12289;&#22522;&#30784;&#24067;&#23616;&#12289;&#25353;&#38062;&#12289;&#25991;&#26412;&#21644;&#37096;&#20998;&#20462;&#39280;&#22120;&#24050;&#32463;&#21487;&#20197;&#22312;&#32593;&#39029;&#20013;&#24418;&#25104;&#31867;&#20284; SwiftUI Preview &#30340;&#21363;&#26102;&#21453;&#39304;&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;&#20043;&#21069;&#25552;&#21040;&#30340;&#8220;&#19981;&#20250;&#23849;&#28291;&#30340; SwiftUI &#27983;&#35272;&#22120;&#39044;&#35272;&#8221;&#65292;&#27491;&#22312;&#20174;&#35774;&#24819;&#21464;&#25104;&#19968;&#20010;&#21487;&#20197;&#30452;&#25509;&#20307;&#39564;&#30340;&#24037;&#20855;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-08">MistKit&#65306;&#35753;&#26381;&#21153;&#31471; Swift &#35775;&#38382; CloudKit</a></strong></h3><p>&#30001; <a href="https://x.com/leogdion">Leo G Dion</a> &#24320;&#21457;&#30340; MistKit &#30446;&#26631;&#24456;&#26126;&#30830;&#65306;&#25226; Apple &#30340; CloudKit Web Services REST API &#23553;&#35013;&#25104;&#29616;&#20195; Swift &#25509;&#21475;&#65292;&#35753;&#26381;&#21153;&#31471; Swift&#12289;&#21629;&#20196;&#34892;&#24037;&#20855;&#65292;&#20197;&#21450; Linux&#12289;Windows &#31561;&#27809;&#26377;&#21407;&#29983; CloudKit framework &#30340;&#29615;&#22659;&#65292;&#20063;&#33021;&#35775;&#38382;&#21516;&#19968;&#22871; CloudKit &#23481;&#22120;&#12290;&#23427;&#24182;&#19981;&#26159;&#35201;&#26367;&#20195; Apple &#24179;&#21488;&#19978;&#30340; CloudKit framework&#65292;&#32780;&#26159;&#34917;&#36275;&#37027;&#20123;&#26080;&#27861;&#30452;&#25509;&#20351;&#29992;&#21407;&#29983;&#26694;&#26550;&#30340;&#22330;&#26223;&#12290;</p><p>&#39033;&#30446;&#22522;&#20110; swift-openapi-generator &#26500;&#24314;&#24213;&#23618;&#23458;&#25143;&#31471;&#65292;&#19978;&#23618;&#25552;&#20379; async/await&#12289;&#31867;&#22411;&#23433;&#20840;&#30340; CloudKit &#25805;&#20316;&#12289;&#32467;&#26500;&#21270;&#38169;&#35823;&#12289;record &#26597;&#35810;&#19982;&#22686;&#21024;&#25913;&#12289;record / zone changes&#12289;asset upload &#21644;&#29992;&#25143;&#36523;&#20221;&#30456;&#20851;&#33021;&#21147;&#12290;&#35748;&#35777;&#26041;&#38754;&#35206;&#30422; API Token&#12289;Web Auth Token &#19982; Server-to-Server&#65307;&#20854;&#20013; Server-to-Server &#20027;&#35201;&#29992;&#20110; public database&#65292;&#28041;&#21450; private &#25110; shared database &#30340;&#29992;&#25143;&#19978;&#19979;&#25991;&#25805;&#20316;&#21017;&#38656;&#35201; Web Auth Token&#12290;&#36825;&#20351;&#23427;&#36866;&#21512;&#21518;&#21488;&#20219;&#21153;&#12289;CLI&#12289;&#20869;&#23481;&#30446;&#24405;&#12289;&#20844;&#20849;&#25968;&#25454;&#24211;&#31649;&#29702;&#65292;&#20197;&#21450; Web &#19982; Apple &#35774;&#22791;&#20043;&#38388;&#30340;&#25968;&#25454;&#26725;&#25509;&#12290;</p><blockquote><p>CloudKit &#24120;&#34987;&#35270;&#20026;&#8220;&#23458;&#25143;&#31471;&#26381;&#21153;&#8221;&#65292;&#20294; MistKit &#35753;&#26381;&#21153;&#31471;&#21442;&#19982; CloudKit &#29983;&#24577;&#21464;&#24471;&#26356;&#33258;&#28982;&#12290;&#20363;&#22914;&#65292;&#29992;&#23450;&#26102;&#20219;&#21153;&#32500;&#25252; public database &#20013;&#30340;&#36719;&#20214;&#29256;&#26412;&#30446;&#24405;&#12289;RSS &#32858;&#21512;&#20869;&#23481;&#12289;&#24212;&#29992;&#32032;&#26448;&#21253;&#65307;&#25110;&#22312;&#29992;&#25143;&#25480;&#26435;&#21518;&#65292;&#35753;&#21518;&#31471;&#22788;&#29702; private database &#20013;&#30340;&#25968;&#25454;&#12290;&#23545;&#24050;&#32463;&#20381;&#36182; CloudKit &#30340;&#24212;&#29992;&#26469;&#35828;&#65292;&#23427;&#25552;&#20379;&#20102;&#19968;&#26465;&#22312; Apple &#24179;&#21488;&#20043;&#22806;&#25193;&#23637;&#25968;&#25454;&#22788;&#29702;&#33021;&#21147;&#30340;&#36335;&#24452;&#12290;</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #137]]></title><description><![CDATA[From Community Guidepost to Ecosystem Cornerstone: Dave Verwer&#8217;s New Chapter]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-137</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-137</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 25 May 2026 12:03:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PERA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PERA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PERA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 424w, https://substackcdn.com/image/fetch/$s_!PERA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 848w, https://substackcdn.com/image/fetch/$s_!PERA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 1272w, https://substackcdn.com/image/fetch/$s_!PERA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PERA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:268194,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/199127465?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PERA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 424w, https://substackcdn.com/image/fetch/$s_!PERA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 848w, https://substackcdn.com/image/fetch/$s_!PERA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 1272w, https://substackcdn.com/image/fetch/$s_!PERA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F036bb0d3-c6c9-4bcc-8449-98884bbc2b17_1500x1000.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@jannerboy62?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nick Fewings</a> on <a href="https://unsplash.com/photos/white-arrow-painted-on-brick-wall-zF_pTLx_Dkg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>From Community Guidepost to Ecosystem Cornerstone: Dave Verwer&#8217;s New Chapter</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-137/">Read on web &#8594;</a></p><p>In issue 751 of iOS Dev Weekly, Dave Verwer announced that the newsletter, which has been running for nearly 15 years, will be handed over to a new team, while he will dedicate himself full-time to Swift Package Index. My own blog gained early attention thanks in part to recommendations from iOS Dev Weekly, and my commitment to writing a commentary for each issue of my newsletter was also greatly inspired by Dave Verwer. For many Apple platform developers, iOS Dev Weekly has long been more than a collection of links. It has been both a guidepost for the community and a long-term companion.</p><p>Rather than viewing this as &#8220;Dave leaving iOS Dev Weekly&#8221;, a phrase that inevitably carries a sense of farewell, I prefer to see it as a shift in focus: from curating the information flow of the Swift community to building infrastructure for the Swift ecosystem.</p><p>Swift Package Index was originally created by Dave Verwer and Sven A. Schmidt as the successor to, and a rewrite of, SwiftPM Library. When it first appeared, it was easy to understand it simply as a &#8220;website for finding Swift packages.&#8221; But after several years of development, SPI has clearly grown far beyond the scope of an ordinary index site. It not only records basic package information, but also uses real builds to verify compatibility across Swift versions and platforms, hosts DocC documentation, displays maintenance status, dependency relationships, licenses, tests, and package scores, and, through projects such as Ready for Swift 6, observes how the broader package ecosystem migrates toward new language features.</p><p>These capabilities may seem scattered, but in essence they all point to the same goal: making the Swift package ecosystem easier to evaluate, compare, and trust. For individual developers, choosing a dependency becomes a little less like opening a &#8220;blind box&#8221;. For teams, it becomes easier to assess risks before introducing third-party libraries. For package authors, SPI provides a public window for showcasing project health and documentation quality. A mature package ecosystem cannot exist on <code>Package.swift</code> alone. It also needs visible compatibility, continuous documentation, stable build verification, and a trust mechanism gradually built around all this information.</p><p>In <a href="https://fatbobman.com/en/weekly/issue-135/">Issue 135</a>, I wrote that CocoaPods is on its way out, while SwiftPM has only just turned to its second chapter. With CocoaPods Trunk counting down toward becoming read-only, and ecosystems such as Flutter also moving toward SPM, the &#8220;unification&#8221; of dependency management on Apple platforms now seems increasingly close. But that does not mean SwiftPM has truly broken beyond its existing boundaries. It will certainly become the default answer on Apple platforms, but if Swift is to keep expanding into Linux, Android, Wasm, embedded systems, and other scenarios, SwiftPM will need to address more than just &#8220;whether dependencies can be installed.&#8221; The real question is whether the entire ecosystem is transparent, reliable, and sustainable enough.</p><p>In this regard, the value of SPI may be far greater than its name suggests. It can be an index, but also an ecosystem dashboard; it can be a documentation hosting platform, but also a compatibility lab. In the future, it may even take on a larger role in areas such as package collections, supply chain security, version immutability, and public registries. Dave has previously mentioned that SwiftPM registries could bring safer and faster distribution to Swift dependency management, while a public registry for open-source packages remains an important missing piece worth looking forward to.</p><p>iOS Dev Weekly records the weekly ripples of the Swift community, while Swift Package Index touches the waterline beneath those ripples. Dave&#8217;s shift may also suggest that the Swift ecosystem has entered a new stage: we still need excellent content curators, but we need even more infrastructure builders who can help the ecosystem continue running for the long term.</p><p><a href="https://fatbobman.com/en/weekly/issue-136/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-01">Monads are Easy</a></strong></h3><p>Monad is probably one of the most infamous &#8212; and most intimidatingly explained &#8212; concepts in functional programming. But at its core, it really just solves one problem: how to safely and continuously compose computations around values that carry &#8220;context.&#8221; <a href="https://www.linkedin.com/in/krishna-kotecha/">Krishna Kotecha</a> explains Monad in a way that feels very approachable to Swift developers, using a warehouse book-scanning analogy: values are books, containers are boxes, <code>map</code> scans books one by one, while <code>flatMap</code> opens nested boxes and flattens everything back into a single box. Whether it&#8217;s <code>Optional</code>, <code>Result</code>, or Optional chaining, they all exhibit strong Monad-like behavior. In Swift, every <code>?.</code> you write is essentially a <code>flatMap</code> disguised as syntax sugar.</p><blockquote><p>Krishna Kotecha not only explains Monads in an intuitive way, but also includes excellent diagrams throughout the article. The &#8220;unboxing and repacking&#8221; visuals make the core idea behind <code>flatMap</code> remarkably easy to grasp.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-02">Type-Driven Design in Swift: Better Money Formatting</a></strong></h3><p>For many Swift developers, Type-Driven Design often stops at &#8220;preventing invalid parameters from being passed around.&#8221; But in more complex domains &#8212; such as finance, state machines, permissions, or orders &#8212; types themselves can become part of the business rules and domain constraints. In this article, <a href="https://www.linkedin.com/in/uwaisalqadri/">Uwais Alqadri</a> uses the separation of &#8220;raw money value&#8221; and &#8220;display value&#8221; as a starting point to explain why fintech applications should never perform calculations directly on <code>Double</code> values or formatted display strings. Through a series of practical examples, the article demonstrates how locale differences, currency precision, and rounding rules can introduce subtle but serious bugs, while also highlighting the value of Type-Driven Design in domain modeling.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-03">Is AndroidX ViewModel the best choice for KMP projects?</a></strong></h3><p>For Swift developers, a ViewModel is usually just an object that holds view state and interaction logic. In SwiftUI, it can be an <code>@Observable</code> type or simply a reference type organized around view state; task lifecycles are typically managed by <code>.task</code>, the view hierarchy, or other SwiftUI-native mechanisms. But when Swift developers enter the Kotlin Multiplatform or Android ecosystem, it&#8217;s easy to underestimate what AndroidX ViewModel is actually responsible for: it&#8217;s not only the &#8220;ViewModel&#8221; in MVVM, but also part of Android&#8217;s lifecycle management, ViewModelStore, and coroutine scope system.</p><p><a href="https://www.linkedin.com/in/faogustavo/">Gustavo F&#227;o Valvassori</a> walks through the historical background of Android ViewModel, explaining why it became tightly coupled to Activity / Fragment recreation, configuration changes, and <code>viewModelScope</code>, and further explores the friction this model can introduce when brought into KMP projects targeting native iOS UI. For Swift developers, the most valuable aspect of the article is not whether AndroidX ViewModel should be adopted directly, but rather understanding that the term &#8220;ViewModel&#8221; can carry very different architectural responsibilities across platforms.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-04">Deprecating your own convenience API</a></strong></h3><p>To support different OS versions &#8212; or provide a consistent experience across old and new systems &#8212; developers often create wrappers, compatibility layers, or custom modifiers to smooth over platform differences. But as deployment targets rise over time, much of that code quietly turns into &#8220;dead code&#8221; nobody dares to remove. <a href="https://x.com/mecid">Majid Jabrayilov</a> demonstrates a very practical SwiftUI technique using <code>@available(..., deprecated:, obsoleted:)</code> to explicitly define the lifecycle of these transitional APIs. Once the minimum deployment target increases, the compiler can automatically surface warnings or even errors, reminding developers to finally remove obsolete compatibility layers.</p><blockquote><p>In a sense, <code>@available</code> is not only about API availability &#8212; it&#8217;s also a way to manage the expiration date of technical debt.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-11">Hiding SwiftUI Views from Screen Capture</a></strong></h3><p>SwiftUI has long lacked a capability that sounds deceptively simple, yet is actually quite low-level and highly practical: allowing a View to remain visible on screen while being excluded from screenshots, screen recordings, AirPlay, or other system capture pipelines. Public APIs mainly provide &#8220;capture state detection,&#8221; rather than true per-view capture privacy protection. <a href="https://x.com/KyleSwifter">Kyle Ye</a>, the developer behind OpenSwiftUI, walks through the entire stack &#8212; from public APIs, secure <code>UITextField</code> tricks, and the private <code>CALayer.disableUpdateMask</code> behavior, all the way down to SwiftUI&#8217;s internal DisplayList and RendererEffect mechanisms &#8212; eventually implementing a genuinely SwiftUI-style view extension. Instead of moving SwiftUI content into a secure text field subtree, the approach directly leverages SwiftUI&#8217;s existing <code>screencaptureProhibited</code> rendering property to exclude the corresponding layer from capture output.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-05">A Public Symbol Server for Swift on Windows</a></strong></h3><p><a href="https://x.com/browsercompany">The Browser Company</a> recently made its Swift on Windows Symbol Server publicly available. Through this service, developers can directly fetch PDB symbol files for the Swift runtime and standard library inside native Windows debugging tools such as WinDBG, Visual Studio, and Windows Performance Analyzer, enabling fully symbolicated stack traces and much clearer crash analysis.</p><p>What makes the article particularly interesting, however, is not just how to configure a Symbol Server, but the broader explanation of Swift&#8217;s debugging infrastructure across platforms: from object file formats like Mach-O, ELF, and PE/COFF, to DWARF versus PDB/CodeView debug information systems, and the very different ways Darwin, Linux, and Windows manage symbols. For developers who have only worked on Apple platforms, this article offers a surprisingly clear reminder that making Swift truly cross-platform involves far more than simply &#8220;being able to compile and run.&#8221;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-06">Replacing Bash with Swift in an AI Harness</a></strong></h3><p>As AI Agent tooling evolves, &#8220;letting models execute code&#8221; is gradually becoming less of a terminal wrapper problem and more of a runtime design problem. This article documents a fascinating experiment: <a href="https://x.com/alexito4">Alejandro Martinez</a> replaces Bash inside an AI Harness with an embeddable Swift interpreter, allowing the model to generate and execute Swift directly instead of shell scripts. Combined with SwiftScript and ShellKit, the project demonstrates how embedded interpreters, controlled working directories, and sandboxing can provide a much more constrained and controllable Swift Runtime for LLMs.</p><blockquote><p><a href="https://github.com/Cocoanetics/SwiftScript">SwiftScript</a> is a particularly interesting experimental project created by <a href="https://x.com/cocoanetics">Oliver Drobnik</a>: a fully Swift-written, embeddable Swift interpreter. It parses and executes Swift ASTs directly using <code>swift-syntax</code>, rather than compiling binaries through <code>swiftc</code>, making it feel much closer to JavaScriptCore or a Python-style embedded scripting runtime.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-07">Hanging on the Promise of SwiftUI</a></strong></h3><p>Seven years after SwiftUI&#8217;s introduction, we still seem to be in a strange in-between state: it has become too important for Apple platform developers to ignore, yet it still feels incomplete enough that many real-world applications eventually fall back to AppKit or UIKit. In this article, <a href="https://mastodon.social/@patrickmcconnell/">Patrick McConnell</a> expresses his complicated relationship with SwiftUI: it is good enough to make developers want to invest deeply in it, but that also makes its recurring &#8220;almost, but not quite there&#8221; limitations in extensibility, completeness, and lower-level capabilities especially frustrating.</p><blockquote><p>I&#8217;ve always felt that SwiftUI will only truly mature once Apple itself fully commits to using it at scale across first-party applications. Third-party developers should not be treated as framework beta testers &#8212; they should be the first to benefit from the convenience and stability the framework promises.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-08">App Store &amp; Google Play Screenshots Generator</a></strong></h3><p>App Store &amp; Google Play Screenshots Generator is an AI coding agent&#8211;oriented screenshot generation skill created by <a href="https://www.linkedin.com/in/parthjadhav04/">Parth Jadhav</a>. Rather than simply offering templates, it turns the entire screenshot workflow &#8212; collecting product information, organizing marketing copy, choosing visual styles, local editing, and exporting multiple sizes &#8212; into an executable process.</p><p>The project generates a local Next.js + ShadCN editor for the current directory, supporting drag-and-drop ordering, inline title editing, real screenshot uploads, iOS / Android device switching, and persistent project state stored in a versionable <code>app-store-screenshots.json</code> file. Its most valuable idea is treating store screenshots explicitly as advertising assets: each screenshot should communicate a single selling point, prioritizing user benefit, emotion, and pain points over mechanically showcasing UI.</p><blockquote><p>For indie developers, tools like this are genuinely useful. They won&#8217;t replace final visual judgment or platform guideline reviews, but they can consolidate a large amount of repetitive and error-prone screenshot work into a much more agent-friendly local workflow.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-10">Editorio: A Native macOS Markdown &amp; Code Editor</a></strong></h3><p>Tired of bloated Electron editors and the ever-growing subscription culture around note-taking apps, <a href="https://www.linkedin.com/in/lcrncevic/">Lovre Crncevic</a> decided to build a lightweight, fully native Markdown and code editor for himself.</p><p><strong>Editorio</strong> uses Swift + AppKit for its native interface and a Rust-powered text engine for performance optimization. It supports live Markdown preview, project sidebars, minimaps, themes, and syntax highlighting for many programming languages. According to the author, Editorio typically uses around 40MB of memory while maintaining near-instant startup and file loading times. In some ways, it feels like a return to the classic era of &#8220;small and fast&#8221; Mac applications.</p><blockquote><p>Lovre has promised that the app will remain <strong>free forever</strong>, and mentioned in a <a href="https://www.reddit.com/r/macapps/comments/1tgpbb7/mac_editorio_native_macos_markdown_code_editor/">Reddit discussion</a> that once the codebase is cleaned up further, he plans to open source Editorio on GitHub.</p></blockquote><h2><strong>Event</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-09">Swift Mentorship Program 2026</a></strong></h3><p>The Swift Mentorship Program is an official community initiative that has become a recurring part of the Swift ecosystem in recent years. Its goal is to help more developers meaningfully participate in Swift open source development through direct mentorship from experienced contributors. Over a 10-week period, mentees work alongside mentors to complete real open-source contributions &#8212; whether to the Swift compiler itself or any Swift-based open-source project. Compared to simply reading tutorials or browsing issue trackers, this &#8220;guided first contribution&#8221; model provides a much more authentic open-source collaboration experience.</p><p>The program was originally driven by the Swift Contributor Experience Workgroup and has gradually evolved into a stable community activity. Beyond technical learning, it also helps lower barriers to entry, cultivate new contributors, and strengthen community connections. The Swift team explicitly encourages participation from groups such as Women in Swift, Black in Swift, and Pride in Swift.</p><p>The 2026 program has already opened, with mentor and mentee sign-ups beginning in May and June respectively, followed by the official 10-week mentorship cycle starting in July.</p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-137?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-137?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#20174;&#31038;&#21306;&#36335;&#26631;&#21040;&#29983;&#24577;&#22522;&#30707;&#65306;Dave Verwer &#30340;&#26032;&#31687;&#31456;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-137/">&#32593;&#39029;&#29256;</a></strong></p><p>Dave Verwer &#22312; iOS Dev Weekly &#31532; 751 &#26399;&#23459;&#24067;&#65292;&#36825;&#20221;&#24050;&#32463;&#25345;&#32493;&#36817; 15 &#24180;&#30340;&#21608;&#25253;&#23558;&#20132;&#30001;&#26032;&#30340;&#22242;&#38431;&#32487;&#32493;&#36816;&#33829;&#65292;&#32780;&#20182;&#33258;&#24049;&#25509;&#19979;&#26469;&#20250;&#20840;&#32844;&#25237;&#20837; Swift Package Index&#12290;&#25105;&#30340;&#21338;&#23458;&#22312;&#26089;&#26399;&#33719;&#24471;&#20851;&#27880;&#65292;&#20063;&#26366;&#24471;&#30410;&#20110; iOS Dev Weekly &#30340;&#25512;&#33616;&#65307;&#32780;&#25105;&#22312;&#21608;&#25253;&#20013;&#22362;&#25345;&#25776;&#20889;&#27599;&#26399;&#21608;&#35780;&#65292;&#21516;&#26679;&#22312;&#24456;&#22823;&#31243;&#24230;&#19978;&#21463;&#21040; Dave Verwer &#30340;&#21551;&#21457;&#12290;&#23545;&#20110;&#24456;&#22810; Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;iOS Dev Weekly &#26089;&#24050;&#19981;&#21482;&#26159;&#19968;&#20221;&#38142;&#25509;&#21512;&#38598;&#12290;&#23427;&#26082;&#26159;&#31038;&#21306;&#36335;&#26631;&#65292;&#20063;&#26159;&#38271;&#26399;&#38506;&#20276;&#12290;</p><p>&#19981;&#36807;&#65292;&#30456;&#36739;&#20110;&#8220;Dave &#31163;&#24320; iOS Dev Weekly&#8221;&#36825;&#20010;&#30053;&#24102;&#21578;&#21035;&#24863;&#30340;&#34920;&#36848;&#65292;&#25105;&#26356;&#24895;&#24847;&#25226;&#36825;&#20214;&#20107;&#30475;&#20316;&#19968;&#27425;&#37325;&#24515;&#36716;&#31227;&#65306;&#20174;&#25972;&#29702; Swift &#31038;&#21306;&#30340;&#20449;&#24687;&#27969;&#65292;&#36716;&#21521;&#24314;&#35774; Swift &#29983;&#24577;&#30340;&#22522;&#30784;&#35774;&#26045;&#12290;</p><p>Swift Package Index &#26368;&#21021;&#30001; Dave Verwer &#21644; Sven A. Schmidt &#20849;&#21516;&#21019;&#24314;&#65292;&#26159; SwiftPM Library &#30340;&#32487;&#25215;&#32773;&#19982;&#37325;&#26500;&#29256;&#12290;&#21018;&#20986;&#29616;&#26102;&#65292;&#23427;&#24456;&#23481;&#26131;&#34987;&#29702;&#35299;&#20026;&#19968;&#20010;&#8220;&#25214; Swift &#21253;&#30340;&#32593;&#31449;&#8221;&#12290;&#20294;&#20960;&#24180;&#36807;&#21435;&#21518;&#65292;SPI &#24050;&#32463;&#26126;&#26174;&#36229;&#20986;&#20102;&#26222;&#36890;&#32034;&#24341;&#31449;&#28857;&#30340;&#33539;&#30068;&#12290;&#23427;&#19981;&#20165;&#35760;&#24405;&#21253;&#30340;&#22522;&#26412;&#20449;&#24687;&#65292;&#20063;&#36890;&#36807;&#30495;&#23454;&#26500;&#24314;&#26469;&#39564;&#35777;&#19981;&#21516; Swift &#29256;&#26412;&#21644;&#24179;&#21488;&#30340;&#20860;&#23481;&#24615;&#65292;&#25176;&#31649; DocC &#25991;&#26723;&#65292;&#23637;&#31034;&#32500;&#25252;&#29366;&#24577;&#12289;&#20381;&#36182;&#20851;&#31995;&#12289;&#35768;&#21487;&#35777;&#12289;&#27979;&#35797;&#19982;&#36136;&#37327;&#35780;&#20998;&#65292;&#36824;&#36890;&#36807; Ready for Swift 6 &#36825;&#26679;&#30340;&#39033;&#30446;&#65292;&#35266;&#23519;&#25972;&#20010;&#21253;&#29983;&#24577;&#21521;&#26032;&#35821;&#35328;&#29305;&#24615;&#36801;&#31227;&#30340;&#36827;&#24230;&#12290;</p><p>&#36825;&#20123;&#33021;&#21147;&#30475;&#20284;&#20998;&#25955;&#65292;&#23454;&#38469;&#19978;&#25351;&#21521;&#30340;&#26159;&#21516;&#19968;&#20214;&#20107;&#65306;&#35753; Swift &#21253;&#29983;&#24577;&#21464;&#24471;&#26356;&#21487;&#21028;&#26029;&#12289;&#26356;&#21487;&#27604;&#36739;&#65292;&#20063;&#26356;&#21487;&#20449;&#12290;&#23545;&#20110;&#20010;&#20154;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36873;&#25321;&#20381;&#36182;&#26102;&#21487;&#20197;&#23569;&#19968;&#28857;&#8220;&#24320;&#30450;&#30418;&#8221;&#65307;&#23545;&#20110;&#22242;&#38431;&#26469;&#35828;&#65292;&#22312;&#24341;&#20837;&#31532;&#19977;&#26041;&#24211;&#21069;&#33021;&#26356;&#28165;&#26970;&#22320;&#35780;&#20272;&#39118;&#38505;&#65307;&#23545;&#20110;&#21253;&#20316;&#32773;&#26469;&#35828;&#65292;&#20063;&#22810;&#20102;&#19968;&#20010;&#23637;&#31034;&#39033;&#30446;&#20581;&#24247;&#24230;&#21644;&#25991;&#26723;&#36136;&#37327;&#30340;&#20844;&#20849;&#31383;&#21475;&#12290;&#19968;&#20010;&#25104;&#29087;&#30340;&#21253;&#29983;&#24577;&#65292;&#19981;&#33021;&#21482;&#38752; <code>Package.swift</code> &#23384;&#22312;&#12290;&#23427;&#36824;&#38656;&#35201;&#21487;&#35265;&#30340;&#20860;&#23481;&#24615;&#12289;&#25345;&#32493;&#30340;&#25991;&#26723;&#12289;&#31283;&#23450;&#30340;&#26500;&#24314;&#39564;&#35777;&#65292;&#20197;&#21450;&#22260;&#32469;&#36825;&#20123;&#20449;&#24687;&#36880;&#28176;&#24418;&#25104;&#30340;&#20449;&#20219;&#26426;&#21046;&#12290;</p><p>&#25105;&#22312; <a href="https://fatbobman.com/zh/weekly/issue-135/">&#31532; 135 &#26399;</a> &#20013;&#25552;&#21040;&#65306;CocoaPods &#27491;&#22312;&#36864;&#22330;&#65292;SwiftPM &#25165;&#21018;&#32763;&#21040;&#31532;&#20108;&#31456;&#12290;&#38543;&#30528; CocoaPods Trunk &#36827;&#20837;&#21482;&#35835;&#20498;&#35745;&#26102;&#65292;Flutter &#31561;&#36328;&#24179;&#21488;&#29983;&#24577;&#20063;&#24320;&#22987;&#36716;&#21521; SPM&#65292;Apple &#24179;&#21488;&#20381;&#36182;&#31649;&#29702;&#30340;&#8220;&#22823;&#19968;&#32479;&#8221;&#30475;&#36215;&#26469;&#24050;&#32463;&#36234;&#26469;&#36234;&#25509;&#36817;&#12290;&#20294;&#36825;&#24182;&#19981;&#24847;&#21619;&#30528; SwiftPM &#24050;&#32463;&#23436;&#25104;&#20102;&#30495;&#27491;&#24847;&#20041;&#19978;&#30340;&#30772;&#22280;&#12290;&#23427;&#24403;&#28982;&#20250;&#25104;&#20026; Apple &#24179;&#21488;&#30340;&#40664;&#35748;&#31572;&#26696;&#65292;&#21487;&#22914;&#26524; Swift &#24819;&#22312; Linux&#12289;Android&#12289;Wasm&#12289;&#23884;&#20837;&#24335;&#31561;&#26356;&#22810;&#22330;&#26223;&#20013;&#32487;&#32493;&#25193;&#23637;&#65292;SwiftPM &#38656;&#35201;&#38754;&#23545;&#30340;&#23601;&#19981;&#21482;&#26159;&#8220;&#33021;&#19981;&#33021;&#23433;&#35013;&#20381;&#36182;&#8221;&#65292;&#32780;&#26159;&#25972;&#20010;&#29983;&#24577;&#26159;&#21542;&#36275;&#22815;&#36879;&#26126;&#12289;&#21487;&#38752;&#12289;&#21487;&#25345;&#32493;&#12290;</p><p>&#22312;&#36825;&#19968;&#28857;&#19978;&#65292;SPI &#30340;&#20215;&#20540;&#21487;&#33021;&#27604;&#23427;&#30340;&#21517;&#23383;&#26263;&#31034;&#30340;&#35201;&#22823;&#24471;&#22810;&#12290;&#23427;&#21487;&#20197;&#26159;&#32034;&#24341;&#65292;&#20063;&#21487;&#20197;&#26159;&#29983;&#24577;&#20202;&#34920;&#30424;&#65307;&#21487;&#20197;&#26159;&#25991;&#26723;&#25176;&#31649;&#24179;&#21488;&#65292;&#20063;&#21487;&#20197;&#26159;&#20860;&#23481;&#24615;&#23454;&#39564;&#23460;&#65307;&#26410;&#26469;&#29978;&#33267;&#26377;&#26426;&#20250;&#22312;&#21253;&#38598;&#21512;&#12289;&#20379;&#24212;&#38142;&#23433;&#20840;&#12289;&#29256;&#26412;&#19981;&#21487;&#21464;&#24615;&#12289;&#20844;&#20849; registry &#31561;&#26041;&#21521;&#19978;&#25215;&#25285;&#26356;&#22810;&#35282;&#33394;&#12290;Dave &#27492;&#21069;&#20063;&#26366;&#25552;&#21040;&#65292;SwiftPM registry &#33021;&#20026; Swift &#20381;&#36182;&#31649;&#29702;&#24102;&#26469;&#26356;&#23433;&#20840;&#12289;&#26356;&#24555;&#30340;&#20998;&#21457;&#26041;&#24335;&#65292;&#32780;&#20844;&#20849;&#24320;&#28304; registry &#20173;&#26159;&#19968;&#20010;&#20540;&#24471;&#26399;&#24453;&#30340;&#31354;&#30333;&#12290;</p><p>iOS Dev Weekly &#35760;&#24405;&#30340;&#26159; Swift &#31038;&#21306;&#27599;&#21608;&#30340;&#28063;&#28458;&#65292;&#32780; Swift Package Index &#35302;&#21450;&#30340;&#21017;&#26159;&#36825;&#20123;&#28063;&#28458;&#20043;&#19979;&#30340;&#27700;&#20301;&#12290;Dave &#30340;&#36716;&#36523;&#65292;&#25110;&#35768;&#20063;&#35828;&#26126; Swift &#29983;&#24577;&#24050;&#32463;&#36208;&#21040;&#19968;&#20010;&#26032;&#38454;&#27573;&#65306;&#25105;&#20204;&#20173;&#28982;&#38656;&#35201;&#22909;&#30340;&#20869;&#23481;&#31574;&#23637;&#32773;&#65292;&#20294;&#26356;&#38656;&#35201;&#33021;&#35753;&#25972;&#20010;&#29983;&#24577;&#38271;&#26399;&#36816;&#36716;&#19979;&#21435;&#30340;&#22522;&#30784;&#35774;&#26045;&#24314;&#35774;&#32773;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-136/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-01">&#36731;&#26494;&#29702;&#35299; Monad (Monads are Easy)</a>&#65532;</strong></h3><p>Monad &#21487;&#33021;&#26159;&#20989;&#25968;&#24335;&#32534;&#31243;&#20013;&#8220;&#21517;&#27668;&#26368;&#22823;&#12289;&#35299;&#37322;&#26368;&#21523;&#20154;&#8221;&#30340;&#27010;&#24565;&#20043;&#19968;&#65292;&#20294;&#23427;&#30495;&#27491;&#35299;&#20915;&#30340;&#38382;&#39064;&#65292;&#20854;&#23454;&#21482;&#26159;&#22914;&#20309;&#22312;&#8220;&#24102;&#19978;&#19979;&#25991;&#8221;&#30340;&#20540;&#20043;&#38388;&#65292;&#23433;&#20840;&#12289;&#36830;&#32493;&#22320;&#32452;&#21512;&#35745;&#31639;&#12290;<a href="https://www.linkedin.com/in/krishna-kotecha/">Krishna Kotecha</a> &#29992; Swift &#24320;&#21457;&#32773;&#23481;&#26131;&#29702;&#35299;&#30340;&#26041;&#24335;&#65292;&#36890;&#36807;&#8220;&#20179;&#24211;&#25195;&#25551;&#20070;&#31821;&#8221;&#30340;&#31867;&#27604;&#65292;&#25226; Monad &#25286;&#35299;&#25104;&#20102;&#19968;&#20010;&#26497;&#20854;&#20855;&#20307;&#30340;&#27969;&#31243; &#8212;&#8212; &#20540;&#26159;&#20070;&#12289;&#23481;&#22120;&#26159;&#31665;&#23376;&#12289;<code>map</code> &#26159;&#36880;&#20010;&#25195;&#25551;&#65292;&#32780; <code>flatMap</code> &#21017;&#36127;&#36131;&#25286;&#24320;&#23884;&#22871;&#31665;&#23376;&#24182;&#37325;&#26032;&#21387;&#24179;&#25104;&#19968;&#20010;&#32479;&#19968;&#30340;&#31665;&#23376;&#12290;&#26080;&#35770;&#26159; <code>Optional</code>&#12289;<code>Result</code>&#65292;&#36824;&#26159;&#38142;&#24335; Optional chaining&#65292;&#26412;&#36136;&#19978;&#37117;&#24102;&#26377;&#26126;&#26174;&#30340; Monad &#39118;&#26684;&#12290;&#22312; Swift &#20013;&#65292;&#20320;&#20889;&#19979;&#30340;&#27599;&#19968;&#20010; <code>?.</code>&#65292;&#26412;&#36136;&#19978;&#37117;&#26159;&#19968;&#20010;&#20266;&#35013;&#25104;&#35821;&#27861;&#31958;&#30340; <code>flatMap</code>&#12290;</p><blockquote><p>Krishna Kotecha &#19981;&#20165;&#25226; Monads &#35762;&#24471;&#21313;&#20998;&#30452;&#35266;&#65292;&#25991;&#31456;&#20013;&#30340;&#37197;&#22270;&#20063;&#30456;&#24403;&#20986;&#33394;&#12290;&#36825;&#20123;&#8220;&#25286;&#31665;&#20877;&#35013;&#31665;&#8221;&#30340;&#27969;&#31243;&#22270;&#65292;&#25226; <code>flatMap</code> &#30340;&#26680;&#24515;&#24605;&#24819;&#23637;&#29616;&#24471;&#38750;&#24120;&#24418;&#35937;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-02">Swift &#31867;&#22411;&#39537;&#21160;&#35774;&#35745;&#65306;&#26356;&#22909;&#30340;&#37329;&#39069;&#26684;&#24335;&#21270; (Type-Driven Design in Swift: Better Money Formatting)</a>&#65532;</strong></h3><p>&#23545;&#24456;&#22810; Swift &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;Type-Driven Design &#24448;&#24448;&#20572;&#30041;&#22312;&#8220;&#36991;&#20813;&#20256;&#38169;&#21442;&#25968;&#8221;&#30340;&#23618;&#38754;&#12290;&#20294;&#22312;&#28041;&#21450;&#37329;&#39069;&#12289;&#29366;&#24577;&#26426;&#12289;&#26435;&#38480;&#12289;&#35746;&#21333;&#31561;&#22797;&#26434;&#19994;&#21153;&#26102;&#65292;&#31867;&#22411;&#26412;&#36523;&#20854;&#23454;&#20063;&#21487;&#20197;&#25104;&#20026;&#19994;&#21153;&#35268;&#21017;&#19982;&#39046;&#22495;&#32422;&#26463;&#30340;&#19968;&#37096;&#20998;&#12290;<a href="https://www.linkedin.com/in/uwaisalqadri/">Uwais Alqadri</a> &#22312;&#26412;&#25991;&#20013;&#65292;&#20197;&#8220;&#37329;&#39069;&#30340;&#21407;&#22987;&#20540;&#19982;&#23637;&#31034;&#20540;&#24517;&#39035;&#20998;&#31163;&#8221;&#20026;&#20999;&#20837;&#28857;&#65292;&#35752;&#35770;&#20102;&#20026;&#20160;&#20040;&#37329;&#34701;&#31867;&#24212;&#29992;&#19981;&#24212;&#30452;&#25509;&#20351;&#29992; <code>Double</code> &#25110;&#26684;&#24335;&#21270;&#21518;&#30340;&#23637;&#31034;&#25991;&#26412;&#21442;&#19982;&#37329;&#39069;&#35745;&#31639;&#12290;&#25991;&#31456;&#19981;&#20165;&#36890;&#36807;&#22810;&#20010;&#23454;&#38469;&#26696;&#20363;&#35828;&#26126;&#20102;&#19981;&#21516; locale&#12289;&#36135;&#24065;&#31934;&#24230;&#19982; rounding rule &#24102;&#26469;&#30340;&#28508;&#22312;&#38382;&#39064;&#65292;&#20063;&#36827;&#19968;&#27493;&#24341;&#20986;&#20102; Type-Driven Design &#22312;&#19994;&#21153;&#24314;&#27169;&#20013;&#30340;&#20215;&#20540;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-03">AndroidX ViewModel &#26159; KMP &#39033;&#30446;&#30340;&#26368;&#20339;&#36873;&#25321;&#21527;&#65311;(Is AndroidX ViewModel the best choice for KMP projects?)</a></strong></h3><p>&#23545;&#20110; Swift &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;ViewModel &#36890;&#24120;&#21482;&#26159;&#19968;&#20010;&#25215;&#36733;&#35270;&#22270;&#29366;&#24577;&#19982;&#20132;&#20114;&#36923;&#36753;&#30340;&#23545;&#35937;&#12290;&#22312; SwiftUI &#20013;&#65292;&#23427;&#21487;&#20197;&#26159;&#19968;&#20010; <code>@Observable</code> &#31867;&#22411;&#65292;&#20063;&#21487;&#20197;&#21482;&#26159;&#19968;&#20010;&#22260;&#32469; View &#29366;&#24577;&#32452;&#32455;&#36215;&#26469;&#30340;&#26222;&#36890;&#24341;&#29992;&#31867;&#22411;&#65307;&#20219;&#21153;&#29983;&#21629;&#21608;&#26399;&#24448;&#24448;&#20132;&#32473; <code>.task</code>&#12289;&#35270;&#22270;&#23618;&#32423;&#25110;&#20854;&#20182;&#26356;&#36148;&#36817; SwiftUI &#30340;&#26426;&#21046;&#22788;&#29702;&#12290;&#20294;&#24403; Swift &#24320;&#21457;&#32773;&#36827;&#20837; Kotlin Multiplatform &#25110; Android &#29983;&#24577;&#26102;&#65292;&#24456;&#23481;&#26131;&#20302;&#20272; AndroidX ViewModel &#25152;&#25215;&#25285;&#30340;&#32844;&#36131;&#65306;&#23427;&#19981;&#20165;&#26159; MVVM &#20013;&#30340;&#8220;ViewModel&#8221;&#65292;&#21516;&#26102;&#20063;&#26159; Android &#29983;&#21629;&#21608;&#26399;&#12289;ViewModelStore &#19982; coroutine scope &#30340;&#19968;&#37096;&#20998;&#12290;</p><p><a href="https://www.linkedin.com/in/faogustavo/">Gustavo F&#227;o Valvassori</a> &#20174; Android ViewModel &#30340;&#21382;&#21490;&#32972;&#26223;&#35762;&#36215;&#65292;&#35299;&#37322;&#23427;&#20026;&#20309;&#20250;&#19982; Activity / Fragment &#30340;&#37325;&#24314;&#12289;&#37197;&#32622;&#21464;&#21270;&#21644; <code>viewModelScope</code> &#28145;&#24230;&#32465;&#23450;&#65292;&#24182;&#36827;&#19968;&#27493;&#35752;&#35770;&#24403;&#36825;&#19968;&#22871;&#26426;&#21046;&#34987;&#24102;&#20837; KMP &#39033;&#30446;&#21518;&#65292;&#22312; iOS &#21407;&#29983; UI &#20013;&#21487;&#33021;&#20135;&#29983;&#30340;&#25705;&#25830;&#12290;&#23545;&#20110; Swift &#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#25991;&#31456;&#26368;&#26377;&#20215;&#20540;&#30340;&#22320;&#26041;&#24182;&#19981;&#22312;&#20110;&#26159;&#21542;&#24212;&#35813;&#30452;&#25509;&#37319;&#29992; AndroidX ViewModel&#65292;&#32780;&#26159;&#24110;&#21161;&#25105;&#20204;&#29702;&#35299;&#65306;&#21516;&#26679;&#21483;&#20316; ViewModel&#65292;&#22312;&#19981;&#21516;&#24179;&#21488;&#19978;&#21487;&#33021;&#25215;&#36733;&#30528;&#23436;&#20840;&#19981;&#21516;&#30340;&#26550;&#26500;&#36131;&#20219;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-04">&#22914;&#20309;&#20248;&#38597;&#22320;&#24223;&#24323;&#33258;&#23450;&#20041;&#20860;&#23481; API (Deprecating your own convenience API)</a>&#65532;</strong></h3><p>&#20026;&#20102;&#20860;&#23481;&#19981;&#21516;&#30340;&#31995;&#32479;&#29256;&#26412;&#65292;&#25110;&#20026;&#26032;&#26087;&#31995;&#32479;&#25552;&#20379;&#19968;&#33268;&#30340;&#34892;&#20026;&#19982;&#20307;&#39564;&#65292;&#24320;&#21457;&#32773;&#36890;&#24120;&#20250;&#36890;&#36807;&#32479;&#19968;&#23553;&#35013;&#12289;&#20026;&#26087;&#31995;&#32479;&#34917;&#40784;&#20860;&#23481;&#23454;&#29616;&#65292;&#25110;&#32773;&#29992;&#33258;&#23450;&#20041; modifier &#25273;&#24179;&#19981;&#21516;&#31995;&#32479;&#20043;&#38388;&#30340;&#34892;&#20026;&#24046;&#24322;&#12290;&#20294;&#38543;&#30528;&#24212;&#29992;&#26368;&#20302;&#25903;&#25345;&#29256;&#26412;&#19981;&#26029;&#25552;&#39640;&#65292;&#20854;&#20013;&#24456;&#22810;&#20195;&#30721;&#26368;&#32456;&#37117;&#20250;&#24708;&#24708;&#21464;&#25104;&#27809;&#20154;&#25954;&#21024;&#30340;&#8220;&#27515;&#20195;&#30721;&#8221;&#12290;<a href="https://x.com/mecid">Majid Jabrayilov</a> &#20197;&#19968;&#20010;&#38750;&#24120;&#20856;&#22411;&#30340; SwiftUI &#22330;&#26223;&#20026;&#20363;&#65292;&#21033;&#29992; <code>@available(..., deprecated:, obsoleted:)</code> &#26631;&#35760;&#36825;&#20123;&#8220;&#36807;&#28193; API&#8221;&#30340;&#29983;&#21629;&#21608;&#26399;&#12290;&#24403;&#26368;&#20302;&#37096;&#32626;&#29256;&#26412;&#25552;&#21319;&#21518;&#65292;&#32534;&#35793;&#22120;&#20250;&#33258;&#21160;&#23558;&#36825;&#20123;&#20860;&#23481;&#23618;&#26631;&#35760;&#20026; warning &#29978;&#33267; error&#65292;&#20174;&#32780;&#25552;&#37266;&#24320;&#21457;&#32773;&#21450;&#26102;&#31227;&#38500;&#12290;</p><blockquote><p>&#26576;&#31181;&#24847;&#20041;&#19978;&#65292;<code>@available</code> &#19981;&#20165;&#26159;&#22312;&#31649;&#29702; API &#30340;&#21487;&#29992;&#24615;&#65292;&#20063;&#26159;&#22312;&#31649;&#29702;&#8220;&#25216;&#26415;&#20538;&#30340;&#20445;&#36136;&#26399;&#8221;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-11">&#35753; SwiftUI View &#22312;&#25130;&#22270;&#20013;&#38544;&#34255;</a></strong></h3><p>SwiftUI &#19968;&#30452;&#32570;&#23569;&#19968;&#20010;&#30475;&#20284;&#31616;&#21333;&#12289;&#20294;&#20854;&#23454;&#30456;&#24403;&#23454;&#29992;&#19988;&#24213;&#23618;&#30340;&#33021;&#21147;&#65306;&#35753;&#26576;&#20010; View &#22312;&#23631;&#24149;&#19978;&#27491;&#24120;&#26174;&#31034;&#65292;&#20294;&#22312;&#25130;&#22270;&#12289;&#24405;&#23631;&#12289;&#25237;&#23631;&#25110;&#20854;&#20182;&#31995;&#32479;&#25429;&#33719;&#36335;&#24452;&#20013;&#34987;&#38544;&#34255;&#12290;&#20844;&#24320; API &#25552;&#20379;&#30340;&#26356;&#22810;&#26159;&#8220;&#25429;&#33719;&#29366;&#24577;&#26816;&#27979;&#8221;&#65292;&#32780;&#19981;&#26159;&#30495;&#27491;&#24847;&#20041;&#19978;&#30340;&#25429;&#33719;&#38544;&#31169;&#20445;&#25252;&#12290;OpenSwiftUI &#30340;&#24320;&#21457;&#32773; <a href="https://x.com/KyleSwifter">Kyle Ye</a> &#20174;&#20844;&#24320; API&#12289;secure <code>UITextField</code> &#25216;&#24039;&#12289;<code>CALayer.disableUpdateMask</code> &#31169;&#26377;&#34892;&#20026;&#65292;&#19968;&#36335;&#20998;&#26512;&#21040; SwiftUI &#20869;&#37096; DisplayList &#19982; RendererEffect &#30340;&#24037;&#20316;&#26426;&#21046;&#65292;&#26368;&#32456;&#23454;&#29616;&#20102;&#19968;&#20010;&#30495;&#27491; SwiftUI &#39118;&#26684;&#30340;&#35270;&#22270;&#25193;&#23637;&#12290;&#23427;&#19981;&#38656;&#35201;&#25226; SwiftUI &#20869;&#23481;&#22622;&#36827; secure text field subtree&#65292;&#32780;&#26159;&#30452;&#25509;&#21033;&#29992; SwiftUI &#20869;&#37096;&#24050;&#32463;&#23384;&#22312;&#30340; <code>screencaptureProhibited</code> rendering property&#65292;&#23558;&#23545;&#24212; layer &#20174; capture output &#20013;&#31227;&#38500;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-05">Windows &#24179;&#21488; Swift &#20844;&#20849;&#31526;&#21495;&#26381;&#21153;&#22120;&#19978;&#32447; (A Public Symbol Server for Swift on Windows)</a>&#65532;</strong></h3><p><a href="https://x.com/browsercompany">The Browser Company</a> &#36817;&#26085;&#20844;&#24320;&#20102; Swift on Windows &#30340; Symbol Server&#12290;&#36890;&#36807;&#35813;&#26381;&#21153;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#22312; WinDBG&#12289;Visual Studio&#12289;Windows Performance Analyzer &#31561; Windows &#21407;&#29983;&#35843;&#35797;&#24037;&#20855;&#20013;&#65292;&#30452;&#25509;&#33719;&#21462; Swift Runtime &#19982;&#26631;&#20934;&#24211;&#30340; PDB &#31526;&#21495;&#25991;&#20214;&#65292;&#20174;&#32780;&#33719;&#24471;&#23436;&#25972;&#30340;&#31526;&#21495;&#21270;&#35843;&#29992;&#26632;&#19982;&#26356;&#28165;&#26224;&#30340;&#23849;&#28291;&#20998;&#26512;&#33021;&#21147;&#12290;</p><p>&#36825;&#31687;&#25991;&#31456;&#30495;&#27491;&#26377;&#36259;&#30340;&#22320;&#26041;&#65292;&#24182;&#19981;&#20165;&#20165;&#26159;&#22914;&#20309;&#37197;&#32622; Symbol Server&#65292;&#32780;&#26159;&#23427;&#31995;&#32479;&#26803;&#29702;&#20102; Swift &#22312;&#19981;&#21516;&#24179;&#21488;&#19978;&#30340;&#35843;&#35797;&#22522;&#30784;&#35774;&#26045;&#65306;&#20174; Mach-O&#12289;ELF&#12289;PE/COFF &#31561;&#23545;&#35937;&#25991;&#20214;&#26684;&#24335;&#65292;&#21040; DWARF &#19982; PDB/CodeView &#20004;&#22871;&#35843;&#35797;&#20449;&#24687;&#20307;&#31995;&#65292;&#20877;&#21040; Darwin&#12289;Linux &#19982; Windows &#22312; symbol &#31649;&#29702;&#19978;&#30340;&#19981;&#21516;&#35774;&#35745;&#12290;&#23545;&#20110;&#38271;&#26399;&#21482;&#22312; Apple &#24179;&#21488;&#24320;&#21457;&#30340; Swift &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#31687;&#25991;&#31456;&#20250;&#35753;&#20320;&#31532;&#19968;&#27425;&#27604;&#36739;&#30452;&#35266;&#22320;&#24847;&#35782;&#21040;&#65306;Swift &#24819;&#30495;&#27491;&#25104;&#20026;&#36328;&#24179;&#21488;&#35821;&#35328;&#65292;&#20165;&#20165;&#8220;&#33021;&#22815;&#32534;&#35793;&#36816;&#34892;&#8221;&#36828;&#36828;&#19981;&#22815;&#65292;&#23427;&#36824;&#38656;&#35201;&#28145;&#20837;&#34701;&#20837;&#30446;&#26631;&#24179;&#21488;&#21407;&#29983;&#30340;&#35843;&#35797;&#20307;&#31995;&#19982;&#24037;&#20855;&#38142;&#29983;&#24577;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-06">&#22312; AI &#23481;&#22120;&#20013;&#29992; Swift &#26367;&#20195; Bash (Replacing Bash with Swift in an AI Harness)</a></strong></h3><p>&#38543;&#30528; AI Agent &#24037;&#20855;&#30340;&#21457;&#23637;&#65292;&#8220;&#35753;&#27169;&#22411;&#25191;&#34892;&#20195;&#30721;&#8221;&#27491;&#22312;&#36880;&#28176;&#20174;&#31616;&#21333;&#30340; terminal &#35843;&#29992;&#28436;&#21464;&#25104;&#26032;&#30340;&#36816;&#34892;&#26102;&#35774;&#35745;&#38382;&#39064;&#12290;&#36825;&#31687;&#25991;&#31456;&#35760;&#24405;&#20102;&#19968;&#20010;&#30456;&#24403;&#26377;&#36259;&#30340;&#23454;&#39564;&#65306;<a href="https://x.com/alexito4">Alejandro Martinez</a> &#23581;&#35797;&#22312; AI Harness &#20013;&#65292;&#29992;&#21487;&#23884;&#20837;&#30340; Swift &#35299;&#37322;&#22120;&#26367;&#25442; Bash&#65292;&#35753;&#27169;&#22411;&#19981;&#20877;&#29983;&#25104; shell script&#65292;&#32780;&#26159;&#30452;&#25509;&#29983;&#25104;&#24182;&#25191;&#34892; Swift &#20195;&#30721;&#12290;&#32467;&#21512; SwiftScript &#19982; ShellKit&#65292;&#23637;&#31034;&#20102;&#22914;&#20309;&#36890;&#36807;&#23884;&#20837;&#24335;&#35299;&#37322;&#22120;&#12289;&#21463;&#25511;&#24037;&#20316;&#30446;&#24405;&#19982; sandbox&#65292;&#20026; LLM &#25552;&#20379;&#19968;&#20010;&#26356;&#21487;&#25511;&#30340; Swift Runtime&#12290;</p><blockquote><p><a href="https://github.com/Cocoanetics/SwiftScript">SwiftScript</a> &#26159;&#19968;&#20010;&#30456;&#24403;&#26377;&#24847;&#24605;&#30340;&#23454;&#39564;&#24615;&#39033;&#30446;&#65292;&#30001; <a href="https://x.com/cocoanetics">Oliver Drobnik</a> &#21019;&#24314;&#65306;&#19968;&#20010;&#23436;&#20840;&#30001; Swift &#32534;&#20889;&#12289;&#21487;&#23884;&#20837;&#24212;&#29992;&#30340; Swift &#35299;&#37322;&#22120;&#12290;&#23427;&#22522;&#20110; <code>swift-syntax</code> &#35299;&#26512;&#24182;&#30452;&#25509;&#25191;&#34892; Swift AST&#65292;&#32780;&#19981;&#26159;&#36890;&#36807; <code>swiftc</code> &#32534;&#35793;&#29983;&#25104;&#20108;&#36827;&#21046;&#65292;&#22240;&#27492;&#26356;&#25509;&#36817; JavaScriptCore &#25110; Python Runtime &#36825;&#31867;&#8220;&#23884;&#20837;&#24335;&#33050;&#26412;&#36816;&#34892;&#26102;&#8221;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-07">&#23545; SwiftUI &#30340;&#32416;&#32467;&#19982;&#26399;&#35768; (Hanging on the Promise of SwiftUI)</a></strong></h3><p>SwiftUI &#21457;&#24067;&#19971;&#24180;&#21518;&#65292;&#25105;&#20204;&#20284;&#20046;&#20173;&#22788;&#20110;&#19968;&#31181;&#24494;&#22937;&#30340;&#29366;&#24577;&#65306;&#23427;&#24050;&#32463;&#36275;&#22815;&#37325;&#35201;&#65292;&#37325;&#35201;&#21040;&#20960;&#20046;&#25152;&#26377; Apple &#24179;&#21488;&#24320;&#21457;&#37117;&#26080;&#27861;&#32469;&#24320;&#23427;&#65307;&#20294;&#23427;&#21448;&#20381;&#28982;&#19981;&#22815;&#23436;&#25972;&#65292;&#24456;&#22810;&#31245;&#24494;&#22797;&#26434;&#19968;&#28857;&#30340;&#30495;&#23454;&#24212;&#29992;&#65292;&#26368;&#32456;&#20173;&#19981;&#24471;&#19981;&#37325;&#26032;&#22238;&#21040; AppKit / UIKit&#12290;<a href="https://mastodon.social/@patrickmcconnell/">Patrick McConnell</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;&#38598;&#20013;&#34920;&#36798;&#20102;&#20182;&#23545; SwiftUI &#30340;&#22797;&#26434;&#24773;&#32490;&#65306;&#23427;&#24456;&#22909;&#65292;&#22909;&#21040;&#35753;&#20154;&#24895;&#24847;&#25345;&#32493;&#25237;&#20837;&#65307;&#20294;&#20063;&#27491;&#22240;&#20026;&#22914;&#27492;&#65292;&#24403;&#23427;&#22312;&#25193;&#23637;&#24615;&#12289;&#23436;&#25972;&#24615;&#19982;&#24213;&#23618;&#33021;&#21147;&#19978;&#22987;&#32456;&#8220;&#24046;&#19968;&#28857;&#8221;&#26102;&#65292;&#25165;&#20250;&#26174;&#24471;&#26684;&#22806;&#20196;&#20154;&#27822;&#20007;&#12290;</p><blockquote><p>&#25105;&#19968;&#30452;&#35273;&#24471;&#65292;&#21482;&#26377;&#33529;&#26524;&#22312;&#31532;&#19968;&#26041;&#24212;&#29992;&#19978;&#30495;&#27491;&#20840;&#21147;&#12289;&#22823;&#35268;&#27169;&#22320;&#20351;&#29992; SwiftUI&#65292;SwiftUI &#25165;&#21487;&#33021;&#36827;&#20837;&#26356;&#24555;&#30340;&#25104;&#29087;&#26399;&#12290;&#31532;&#19977;&#26041;&#24320;&#21457;&#32773;&#19981;&#24212;&#25104;&#20026;&#26694;&#26550;&#30340;&#23567;&#30333;&#40736;&#65292;&#32780;&#24212;&#35813;&#20248;&#20808;&#20139;&#21463;&#21040;&#26694;&#26550;&#24102;&#26469;&#30340;&#20415;&#21033;&#19982;&#31283;&#23450;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-08">App Store &amp; Google Play Screenshots Generator</a></strong></h3><p>App Store &amp; Google Play Screenshots Generator &#26159;&#19968;&#20010;&#38754;&#21521; AI coding agent &#30340;&#21830;&#24215;&#25130;&#22270;&#29983;&#25104; skill&#65292;&#30001; <a href="https://www.linkedin.com/in/parthjadhav04/">Parth Jadhav</a> &#24320;&#21457;&#12290;&#23427;&#19981;&#26159;&#31616;&#21333;&#32473;&#20320;&#19968;&#22871;&#25130;&#22270;&#27169;&#26495;&#65292;&#32780;&#26159;&#25226;&#8220;&#25910;&#38598;&#20135;&#21697;&#20449;&#24687; &#8594; &#32452;&#32455;&#21334;&#28857;&#25991;&#26696; &#8594; &#36873;&#25321;&#35270;&#35273;&#39118;&#26684; &#8594; &#26412;&#22320;&#32534;&#36753; &#8594; &#25209;&#37327;&#23548;&#20986;&#23610;&#23544;&#8221;&#30340;&#27969;&#31243;&#20570;&#25104;&#20102;&#19968;&#20010;&#21487;&#25191;&#34892;&#24037;&#20316;&#27969;&#12290;</p><p>&#39033;&#30446;&#20250;&#20026;&#24403;&#21069;&#30446;&#24405;&#29983;&#25104;&#19968;&#20010; Next.js + ShadCN &#30340;&#26412;&#22320;&#32534;&#36753;&#22120;&#65292;&#25903;&#25345;&#25302;&#25341;&#25490;&#24207;&#12289;&#22312;&#32447;&#20462;&#25913;&#26631;&#39064;&#12289;&#19978;&#20256;&#30495;&#23454;&#25130;&#22270;&#12289;&#20999;&#25442; iOS / Android &#35774;&#22791;&#65292;&#24182;&#23558;&#39033;&#30446;&#29366;&#24577;&#20445;&#23384;&#20026;&#21487;&#29256;&#26412;&#21270;&#30340; app-store-screenshots.json&#12290;&#23427;&#26368;&#20540;&#24471;&#20511;&#37492;&#30340;&#22320;&#26041;&#65292;&#26159;&#25226;&#21830;&#24215;&#25130;&#22270;&#26126;&#30830;&#35270;&#20026;&#24191;&#21578;&#32032;&#26448;&#65306;&#27599;&#24352;&#22270;&#21482;&#34920;&#36798;&#19968;&#20010;&#21334;&#28857;&#65292;&#20248;&#20808;&#21576;&#29616;&#29992;&#25143;&#25910;&#30410;&#12289;&#24773;&#32490;&#21644;&#30171;&#28857;&#65292;&#32780;&#19981;&#26159;&#26426;&#26800;&#23637;&#31034; UI&#12290;</p><blockquote><p>&#23545;&#29420;&#31435;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#31867;&#24037;&#20855;&#24456;&#23454;&#29992;&#12290;&#23427;&#19981;&#33021;&#26367;&#20195;&#26368;&#32456;&#30340;&#23457;&#32654;&#21028;&#26029;&#21644;&#24179;&#21488;&#35268;&#21017;&#26680;&#23545;&#65292;&#20294;&#33021;&#25226;&#19978;&#26550;&#25130;&#22270;&#21046;&#20316;&#20013;&#22823;&#37327;&#37325;&#22797;&#12289;&#29712;&#30862;&#12289;&#23481;&#26131;&#20986;&#38169;&#30340;&#37096;&#20998;&#25910;&#25314;&#21040;&#19968;&#20010; agent &#21451;&#22909;&#30340;&#26412;&#22320;&#27969;&#31243;&#37324;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0137-10">Editorio: macOS &#21407;&#29983; Markdown &#19982;&#20195;&#30721;&#32534;&#36753;&#22120;</a></strong></h3><p><a href="https://www.linkedin.com/in/lcrncevic/">Lovre Crncevic</a> &#22240;&#20026;&#19981;&#29976;&#24525;&#21463; Electron &#32534;&#36753;&#22120;&#30340;&#33219;&#32959;&#65292;&#20197;&#21450;&#21508;&#31867;&#31508;&#35760;&#36719;&#20214;&#27867;&#28389;&#30340;&#35746;&#38405;&#21046;&#65292;&#20915;&#23450;&#20026;&#33258;&#24049;&#25171;&#36896;&#19968;&#27454;&#32431;&#21407;&#29983;&#30340;&#36731;&#37327;&#32423; Markdown &#19982;&#20195;&#30721;&#32534;&#36753;&#22120;&#12290;</p><p><strong>Editorio</strong> &#20351;&#29992; Swift + AppKit &#26500;&#24314;&#21407;&#29983;&#30028;&#38754;&#65292;&#24182;&#20351;&#29992; Rust &#26500;&#24314;&#24213;&#23618;&#25991;&#26412;&#24341;&#25806;&#20197;&#25552;&#21319;&#24615;&#33021;&#65292;&#25903;&#25345; Markdown &#23454;&#26102;&#39044;&#35272;&#12289;&#39033;&#30446;&#20391;&#36793;&#26639;&#12289;minimap&#12289;&#20027;&#39064;&#20999;&#25442;&#65292;&#20197;&#21450;&#22810;&#31181;&#32534;&#31243;&#35821;&#35328;&#30340;&#35821;&#27861;&#39640;&#20142;&#12290;&#20316;&#32773;&#34920;&#31034;&#65292;Editorio &#20856;&#22411;&#20869;&#23384;&#21344;&#29992;&#32422; 40MB&#65292;&#32780;&#20919;&#21551;&#21160;&#19982;&#25991;&#20214;&#35835;&#21462;&#21017;&#20445;&#25345;&#22312;&#27627;&#31186;&#32423;&#21709;&#24212;&#12290;&#26576;&#31181;&#31243;&#24230;&#19978;&#65292;&#23427;&#35753;&#20154;&#37325;&#26032;&#24819;&#36215;&#20102;&#36807;&#21435;&#37027;&#20123;&#8220;&#23567;&#32780;&#24555;&#8221;&#30340;&#32463;&#20856; Mac &#24212;&#29992;&#12290;</p><blockquote><p>Lovre &#25215;&#35834;&#65292;&#35813;&#24212;&#29992;<strong>&#27704;&#20037;&#20813;&#36153;</strong>&#65292;&#24182;&#22312; Reddit &#19978;&#30340;<a href="https://www.reddit.com/r/macapps/comments/1tgpbb7/mac_editorio_native_macos_markdown_code_editor/">&#35752;&#35770;</a>&#20013;&#34920;&#31034;&#65306;&#31561;&#39033;&#30446;&#20195;&#30721;&#36827;&#19968;&#27493;&#25972;&#29702;&#21518;&#65292;&#20182;&#35745;&#21010;&#23558; Editorio &#22312; GitHub &#19978;&#24320;&#28304;&#12290;</p><p>5.1 &#29256;&#26412;&#23545;&#38750;&#33521;&#25991;&#30340;&#36755;&#20837;&#25903;&#25345;&#26377;&#38382;&#39064;&#65292;&#25105;&#24050;&#21453;&#39304;&#20316;&#32773;&#12290;5.2 &#29256;&#26412;&#65288;&#23457;&#26597;&#20013;&#65289;&#20013;&#24050;&#35299;&#20915;&#12290;</p></blockquote><h2><strong>&#27963;&#21160;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0137-09">2026 &#24180;&#24230; Swift &#23448;&#26041;&#23548;&#24072;&#35745;&#21010; (Swift Mentorship Program 2026)</a>&#65532;</strong></h3><p>Swift Mentorship Program &#26159; Swift &#31038;&#21306;&#36817;&#24180;&#26469;&#25345;&#32493;&#20030;&#21150;&#30340;&#19968;&#39033;&#23448;&#26041; Mentorship &#27963;&#21160;&#65292;&#26088;&#22312;&#24110;&#21161;&#26356;&#22810;&#24320;&#21457;&#32773;&#30495;&#27491;&#21442;&#19982; Swift &#24320;&#28304;&#29983;&#24577;&#12290;&#39033;&#30446;&#36890;&#36807;&#23548;&#24072;&#37197;&#23545;&#30340;&#26041;&#24335;&#65292;&#35753;&#21442;&#19982;&#32773;&#22312; 10 &#21608;&#26102;&#38388;&#20869;&#65292;&#19982;&#32463;&#39564;&#20016;&#23500;&#30340; Swift &#24320;&#21457;&#32773;&#20849;&#21516;&#23436;&#25104;&#19968;&#27425;&#30495;&#23454;&#30340;&#24320;&#28304;&#36129;&#29486;&#65306;&#26082;&#21487;&#20197;&#26159; Swift &#32534;&#35793;&#22120;&#26412;&#36523;&#65292;&#20063;&#21487;&#20197;&#26159;&#20219;&#24847;&#20351;&#29992; Swift &#32534;&#20889;&#30340;&#24320;&#28304;&#39033;&#30446;&#12290;&#30456;&#27604;&#21333;&#32431;&#30340;&#32447;&#19978;&#25945;&#31243;&#25110; issue &#21015;&#34920;&#65292;&#36825;&#31181;&#8220;&#24102;&#30528;&#26032;&#20154;&#30495;&#27491;&#23436;&#25104;&#19968;&#27425;&#36129;&#29486;&#8221;&#30340;&#26041;&#24335;&#65292;&#26174;&#28982;&#26356;&#25509;&#36817;&#30495;&#23454;&#30340;&#24320;&#28304;&#21327;&#20316;&#20307;&#39564;&#12290;</p><p>&#35813;&#39033;&#30446;&#26368;&#26089;&#30001; Swift Contributor Experience Workgroup &#25512;&#21160;&#65292;&#36817;&#20960;&#24180;&#24050;&#32463;&#36880;&#28176;&#25104;&#20026; Swift &#31038;&#21306;&#22266;&#23450;&#27963;&#21160;&#20043;&#19968;&#12290;&#38500;&#20102;&#25216;&#26415;&#23398;&#20064;&#22806;&#65292;&#23427;&#20063;&#25215;&#25285;&#30528;&#38477;&#20302;&#31038;&#21306;&#21442;&#19982;&#38376;&#27099;&#12289;&#22521;&#20859;&#26032;&#36129;&#29486;&#32773;&#20197;&#21450;&#21152;&#24378;&#31038;&#21306;&#32676;&#20307;&#36830;&#25509;&#30340;&#20316;&#29992;&#12290;&#23448;&#26041;&#36824;&#29305;&#21035;&#40723;&#21169; Women in Swift&#12289;Black in Swift &#19982; Pride in Swift &#31561;&#31038;&#21306;&#25104;&#21592;&#21442;&#19982;&#20854;&#20013;&#12290;</p><p>2026 &#24180;&#24230;&#27963;&#21160;&#24050;&#32463;&#24320;&#21551;&#65292;Mentor &#19982; Mentee &#30340;&#25253;&#21517;&#26102;&#38388;&#20998;&#21035;&#20174; 5 &#26376;&#19982; 6 &#26376;&#24320;&#22987;&#65292;7 &#26376;&#27491;&#24335;&#36827;&#20837;&#20026;&#26399; 10 &#21608;&#30340; Mentorship &#21608;&#26399;&#12290;</p><div><hr></div><h3><strong><a href="https://mp.weixin.qq.com/s/fR4BzUgKSqJgWDZ341SeIg?from=groupmessage&amp;isappinstalled=0&amp;scene=1&amp;clicktime=1779630042&amp;enterid=1779630042">WWDC26 &#27966;&#23545;&#20043;&#22812;&#65306;&#22478;&#24066;&#12289;&#22330;&#27425;&#21644;&#25253;&#21517;&#20449;&#24687;</a></strong></h3><p>WWDC26 &#20027;&#39064;&#28436;&#35762;&#23558;&#20110;&#24403;&#22320;&#26102;&#38388; 06 &#26376; 08 &#26085; 10:00 &#22312;&#24211;&#27604;&#33922;&#35834;&#20030;&#34892;&#12290;</p><p>&#20316;&#20026;&#36830;&#32493;&#22810;&#24180;&#20837;&#36873; Apple &#24320;&#21457;&#32773;&#32593;&#31449; WWDC &#31038;&#21306;&#27963;&#21160;&#30340; WWDC.playground&#65292;&#30001; SwiftGG &#21457;&#36215;&#30340; WWDC26.playground &#32447;&#19979;&#35266;&#24433;&#27966;&#23545;&#23558;&#20110;&#21271;&#20140;&#26102;&#38388; 06 &#26376; 08 &#26085;&#26202;&#38388;&#33267; 06 &#26376; 09 &#26085;&#20940;&#26216;&#65292;&#22312;&#21271;&#20140;&#12289;&#19978;&#28023;&#12289;&#24191;&#24030;&#12289;&#28145;&#22323;&#12289;&#26477;&#24030;&#21644;&#38738;&#23707;&#31561;&#22810;&#24231;&#22478;&#24066;&#20030;&#21150;&#12290;</p><p>&#20837;&#22330;&#26102;&#38388;&#21644;&#25253;&#21517;&#36153;&#29992;&#31561;&#24418;&#24335;&#65292;&#22312;&#19981;&#21516;&#22478;&#24066;/&#22330;&#27425;&#38388;&#21487;&#33021;&#26377;&#25152;&#19981;&#21516;&#65292;&#35831;&#20197;&#23454;&#22320;&#24773;&#20917;&#20026;&#20934;&#12290;&#128073; <a href="https://mp.weixin.qq.com/s/fR4BzUgKSqJgWDZ341SeIg?from=groupmessage&amp;isappinstalled=0&amp;scene=1&amp;clicktime=1779630042&amp;enterid=1779630042">&#21508;&#22320;&#25253;&#21517;&#26041;&#24335;</a></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #136]]></title><description><![CDATA[The Vanishing WWDC Wishlists]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-136</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-136</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 18 May 2026 12:01:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1yap!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1yap!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1yap!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!1yap!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!1yap!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!1yap!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1yap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:505980,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/198199684?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1yap!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!1yap!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!1yap!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!1yap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6214fdcc-b3a9-4bf6-995e-4e71296388c7_1536x1024.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@emmanuelphaeton?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Emmanuel Phaeton</a> on <a href="https://unsplash.com/photos/a-note-sitting-on-top-of-a-chair-next-to-a-pen-xQ9DWqXnWIU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>The Vanishing WWDC Wishlists</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-136/">Read on web &#8594;</a></p><p>WWDC 2026 is just 20 days away. Every year around this time, I usually see many developers sharing their WWDC wishlists, jotting down their predictions and expectations. But this year, at least by the time I was putting together this issue, there seemed to be noticeably fewer such posts than around the same time last year. Has developers' anticipation for WWDC waned, or are more of us simply adopting the mindset of "keeping expectations low to be pleasantly surprised"?</p><p>Perhaps the issue isn&#8217;t a lack of anticipation, but rather that the traditional format of a wishlist is no longer quite sufficient. In the past, we looked forward to a specific API, framework, or feature. Now, however, as software development rapidly pivots toward the AI Agent era, our expectations themselves have become much harder to clearly articulate.</p><p>A year ago, few developers could have predicted that software development would enter the AI Agent era so swiftly. Even if we hoped for better AI support in Xcode, prior to the release of Xcode 26.3, we probably wouldn&#8217;t have imagined that Apple would provide such seamless Agent integration right within the IDE. Applications and APIs are no longer just interfaces for consumers or developers; they can now become objects for AI Agents to understand, invoke, and orchestrate. AI is no longer merely a development tool; it acts as a new participant, deeply involved in the very construction and utilization of software services.</p><p>I believe this perfectly captures why many developers feel a mix of anticipation and uncertainty heading into WWDC 2026. We hope to see updated features, more stable frameworks, and a clearer platform direction. Yet, at the same time, we are pondering how to maintain our uniqueness and indispensability as developers in this new paradigm, and how to build better services alongside AI.</p><p>Let&#8217;s wait and see just how many changes WWDC 2026 will bring.</p><div><hr></div><p><strong>BTW:</strong> Last week, I had the incredible honor of being featured in the recently announced <strong><a href="https://developer.apple.com/community/recognition/">Apple Developer Community Spotlight</a></strong>. As a content creator, receiving this recognition is both an encouragement and a driving force for me: a reminder to keep writing earnestly and continue delivering valuable content to all of you. A heartfelt thank you to everyone who has read, shared feedback, and supported me along the way.</p><p><a href="https://fatbobman.com/en/weekly/issue-135/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0136-01">URLSession to Electrons: How Networking works on iOS</a></strong></h3><p>Most iOS developers know that a <code>URLSessionDataTask</code> does not actually begin until you call <code>resume()</code>. But what really happens after that? In this long-form article, <a href="https://x.com/jacobtechtavern">Jacob Bartlett</a> follows an ordinary network request all the way down the stack &#8212; from <code>URLSession</code>, CFNetwork, TCP/IP, and Wi-Fi to radio signals, antennas, and electromagnetic waves. Along the way, he connects concepts developers often use but rarely fully understand, including HTTP, DNS, TCP, QUIC, and IPv6, while also exploring <code>Network.framework</code>, the XNU TCP stack, Wi-Fi frame structures, and cellular scheduling mechanisms inside iOS.</p><blockquote><p>A simple <code>resume()</code> call may sit atop decades of protocol and infrastructure evolution. Modern software exists on layers upon layers of abstraction, and most of the time, we are simply fortunate enough to live in an era where those abstractions remain stable.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-02b">When AI and Xcode Fight: I Built a Tool to Keep the Peace</a></strong></h3><p>Xcode&#8217;s build system was never truly designed for parallel development. When multiple tasks build simultaneously, DerivedData, ModuleCache, SwiftPM caches, and even Simulators can collide with one another &#8212; and this problem becomes dramatically worse in multi-agent AI workflows. In this article, <a href="https://x.com/Maples67">Maples7</a> introduces his solution: <a href="https://github.com/Maples7/VibeChard">VibeChard</a>. Built on Git Worktree, it creates isolated build sandboxes for each AI agent while separating DerivedData, ModuleCache, SwiftPM caches, and Simulator environments. Most interestingly, it does not require developers to modify build commands directly. Instead, it transparently intercepts <code>xcodebuild</code> via a PATH shim, allowing the entire toolchain &#8212; including Tuist and Fastlane &#8212; to operate inside isolated environments automatically.</p><p>More than just a utility, this project highlights a deeper issue emerging in the age of AI coding: as code generation speeds accelerate dramatically, traditional development toolchains must also evolve their isolation and infrastructure capabilities.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-03">Has Swift Really Become a Mess? Some Honest Thoughts After Years of Using It</a></strong></h3><p>Swift becoming increasingly complex is an undeniable reality. But does that mean Swift has become a bad language? In this article, <a href="https://juejin.cn/user/4089838986071175/posts">&#36855;&#36884;&#37233;</a> revisits Swift&#8217;s &#8220;expansion&#8221; through the lens of real-world language evolution constraints. The author argues that much of the complexity people complain about comes from Swift simultaneously serving multiple roles: an application language, a systems language, a DSL host, and even a server-side language. Concurrency safety and ownership models themselves also belong to the category of &#8220;hard complexity&#8221; inherent to computer science.</p><p>The article discusses rapidly growing concepts such as <code>Sendable</code>, <code>actor isolation</code>, <code>borrowing</code>, and <code>~Copyable</code>, while also candidly criticizing Swift&#8217;s concurrency keywords, increasingly dense generics syntax, and the &#8220;magic&#8221; behind SwiftUI. One particularly thought-provoking point is the idea that Swift is effectively &#8220;multiple layers of a language.&#8221; Most developers building everyday apps do not actually need to carry the full weight of the language&#8217;s complexity, yet WWDC sessions and official documentation often present all of these features side by side.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-04">Writing shell scripts for Xcode Cloud</a></strong></h3><p>Xcode Cloud is easy to get started with, but in real-world projects many automation workflows still rely on shell scripts. Using &#8220;automatically creating a GitHub Release after archiving&#8221; as an example, <a href="https://www.linkedin.com/in/amy-delves-41968418b/">Amy Delves</a> demonstrates how to leverage Xcode Cloud environment variables to determine whether a build originated from the <code>main</code> branch, extract version and build numbers from an archive, and create releases via the GitHub API.</p><p>The example itself is fairly straightforward, but it nicely illustrates that Xcode Cloud is more than just a &#8220;click a few buttons to run tests&#8221; service. With environment variables, script hooks, and external APIs, it can support much richer release automation workflows.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-05">Why CloudKit is amazing and why we&#8217;re leaving it</a></strong></h3><p>This is a surprisingly candid and nuanced retrospective on migrating away from CloudKit. Rather than criticizing it outright, <a href="https://x.com/JagCesar">C&#233;sar Pinto Castillo</a> first acknowledges that for small teams, CloudKit offers an almost unbelievable combination of features: free sync, automatic authentication, end-to-end encryption, serverless infrastructure, and built-in sharing across Apple platforms.</p><p>But as their product evolved, CloudKit&#8217;s limitations became increasingly apparent: limited server-side observability, manual schema deployment steps, long-standing synchronization edge cases across Apple platforms, heavy reliance on iCloud accounts, and most importantly, the inability to truly expand toward the Web and cross-platform ecosystems. Eventually, C&#233;sar&#8217;s team migrated to a Supabase/Postgres-based synchronization architecture.</p><blockquote><p>CloudKit remains one of the strongest moats in Apple&#8217;s ecosystem. But as apps grow more complex, datasets larger, and user expectations around synchronization latency higher, its boundaries are becoming increasingly visible. In pursuing &#8220;invisible sync,&#8221; Apple may also need to seriously rethink this infrastructure layer that has seen relatively little evolution over the years.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-06">Training an LLM in Swift, Part 1: Taking matrix multiplication from Gflop/s to Tflop/s</a></strong></h3><p>Training an LLM in Swift sounds somewhat absurd at first glance, but <a href="https://mastodon.social/@cocoawithlove">Matt Gallagher</a> delivers an impressively deep performance exploration. Starting from handwritten matrix multiplication &#8212; without relying on existing ML frameworks &#8212; he gradually optimizes a basic Swift implementation from 2.8 Gflop/s to 1.1 Tflop/s. Through a complete optimization journey, the article reveals what high-performance Swift actually looks like in practice: Swift can absolutely be fast, but as you approach hardware limits, you inevitably enter a world of <code>UnsafeBufferPointer</code>, SIMD, concurrent slicing, memory layout tuning, and GPU tile optimization.</p><p>The article is not advocating for handwritten ML kernels in production. On the contrary, Matt repeatedly emphasizes that developers should prefer mature frameworks such as Accelerate, BNNS, Core ML, and MPSGraph whenever possible.</p><blockquote><p>Once Swift is pushed close to C-level performance, can it still preserve the readability and elegance that originally made Swift appealing? This article offers a remarkably concrete &#8212; and honest &#8212; answer.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-07">Swift Is Great for Apps, Not for Training ML Models</a></strong></h3><p>While the previous article demonstrated how handwritten Swift matrix multiplication could be optimized all the way to Tflop/s territory, this article pours some cold water on the idea from a different angle. <a href="https://x.com/azamsharp">Mohammad Azam</a> argues that Swift and Core ML are excellent for deploying machine learning models, but poorly suited for modern machine learning training workflows. He points out that the majority of effort in ML development is rarely spent on training itself, but rather on data cleaning, feature engineering, normalization, pipeline composition, and iterative experimentation &#8212; areas where the Python ecosystem remains vastly more mature and ergonomic.</p><blockquote><p>Swift is not incapable of reaching into the lower layers of machine learning. But once the problem shifts from &#8220;performance&#8221; to &#8220;data science workflows,&#8221; the differences in language priorities and ecosystem maturity quickly become obvious. It also highlights one of Swift&#8217;s current dilemmas: while the language itself is capable of expanding into many domains, its surrounding ecosystem still struggles to provide equally smooth experiences outside of application development.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0136-08">Swift MarkdownEngine</a></strong></h3><p>MarkdownEngine is a native editor engine extracted and open-sourced by the team behind <a href="https://nodes-web.com/">Nodes</a>, their macOS Markdown application. It is neither an HTML renderer nor a WebView wrapper. Instead, it is a source-style Markdown editor built on TextKit 2 and AppKit, then bridged into SwiftUI. The editor preserves plain Markdown text while providing live styling similar to Obsidian Live Preview or iA Writer. Features include wiki links, image embedding, syntax highlighting, LaTeX, task lists, Writing Tools support, and suppression of spell-checking for code, formulas, and links.</p><blockquote><p>TextKit 2 documentation remains sparse and full of behavioral quirks. By open-sourcing an editor stack already used in <a href="https://apps.apple.com/us/app/nodes-by-the-werk/id6745401961">Nodes.app</a>, this project offers valuable reference material for developers building writing, note-taking, or knowledge-management apps on macOS.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-09">Harness: Let AI Test Your App Like a Real User</a></strong></h3><p>Harness is a native macOS developer tool created by <a href="https://www.linkedin.com/in/alanwizemann/">Alan Wizemann</a> that can drive iOS Simulators, macOS apps, and Web apps. You describe a goal in natural language, choose a persona, and Harness allows an LLM agent to observe the UI through screenshots, perform clicks and text input, then generate replayable execution paths, success or failure reports, and categorized UX friction logs. Rather than simply letting AI &#8220;operate an app,&#8221; it feels more like a developer-focused user testing workstation that combines AI agents, screenshots, event logs, credential redaction, replay systems, and friction analysis.</p><p>The project is still in alpha. Web support currently depends on WebKit, and Set-of-Mark targeting for iOS/macOS is still planned for the future. As a result, it is better suited for exploring ambiguous UX issues and hidden usability dead-ends than replacing deterministic regression testing. Still, from its use of Swift 6, SwiftUI, SwiftData, actor-based execution flows, JSONL run logs, and cross-provider abstractions for Anthropic/OpenAI/Gemini models, it is already far beyond a simple demo &#8212; and a fascinating example of an AI-native developer tool.</p><blockquote><p>Traditional UI testing excels at validating predefined flows created by developers. Harness is attempting to answer a different question: can a real user, with a specific goal and persona, actually complete a task successfully inside your interface?</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-136?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-136?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#28040;&#22833;&#30340; WWDC &#24895;&#26395;&#21333;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-136/">&#32593;&#39029;&#29256;</a></strong></p><p>&#36317;&#31163; WWDC 2026 &#21482;&#21097;&#19979; 20 &#22825;&#20102;&#12290;&#27599;&#24180;&#21040;&#36825;&#20010;&#26102;&#20505;&#65292;&#25105;&#37117;&#20250;&#30475;&#21040;&#19981;&#23569;&#24320;&#21457;&#32773;&#20998;&#20139;&#33258;&#24049;&#30340; WWDC &#24895;&#26395;&#21333;&#65292;&#20889;&#19979;&#39044;&#27979;&#19982;&#26399;&#35768;&#12290;&#20294;&#20170;&#24180;&#65292;&#33267;&#23569;&#21040;&#25105;&#27719;&#24635;&#26412;&#26399;&#21608;&#25253;&#26102;&#65292;&#36825;&#31867;&#20869;&#23481;&#30456;&#36739;&#21435;&#24180;&#21516;&#26399;&#26126;&#26174;&#23569;&#20102;&#35768;&#22810;&#12290;&#31350;&#31455;&#26159;&#24320;&#21457;&#32773;&#23545; WWDC &#30340;&#26399;&#24453;&#21464;&#28129;&#20102;&#65292;&#36824;&#26159;&#26356;&#22810;&#20154;&#24320;&#22987;&#31177;&#25345;&#8220;&#38477;&#20302;&#39044;&#26399;&#25165;&#33021;&#33719;&#24471;&#26356;&#22810;&#24778;&#21916;&#8221;&#30340;&#24515;&#29702;&#65311;</p><p>&#20063;&#35768;&#38382;&#39064;&#24182;&#19981;&#26159;&#24320;&#21457;&#32773;&#27809;&#26377;&#26399;&#24453;&#65292;&#32780;&#26159;&#26087;&#26377;&#30340;&#24895;&#26395;&#21333;&#24418;&#24335;&#24050;&#32463;&#19981;&#22826;&#22815;&#29992;&#20102;&#12290;&#36807;&#21435;&#65292;&#25105;&#20204;&#26399;&#24453;&#30340;&#26159;&#26576;&#20010; API&#12289;&#26576;&#20010;&#26694;&#26550;&#12289;&#26576;&#39033;&#21151;&#33021;&#65307;&#32780;&#29616;&#22312;&#65292;&#24403;&#36719;&#20214;&#24320;&#21457;&#36805;&#36895;&#21521; AI Agent &#26102;&#20195;&#38752;&#25314;&#26102;&#65292;&#24456;&#22810;&#26399;&#24453;&#26412;&#36523;&#20063;&#21464;&#24471;&#26356;&#38590;&#34987;&#28165;&#26224;&#25551;&#36848;&#12290;</p><p>&#19968;&#24180;&#21069;&#65292;&#24656;&#24597;&#24456;&#23569;&#26377;&#24320;&#21457;&#32773;&#20250;&#39044;&#26009;&#21040;&#36719;&#20214;&#24320;&#21457;&#20250;&#22914;&#27492;&#36805;&#36895;&#22320;&#36827;&#20837; AI Agent &#26102;&#20195;&#12290;&#21363;&#20415;&#25105;&#20204;&#26399;&#24453; Xcode &#25552;&#20379;&#26356;&#22909;&#30340; AI &#25903;&#25345;&#65292;&#22312; Xcode 26.3 &#25512;&#20986;&#21069;&#65292;&#20063;&#26410;&#24517;&#20250;&#24819;&#21040;&#33529;&#26524;&#20250;&#22312; IDE &#20013;&#25552;&#20379;&#19982; Agent &#22914;&#27492;&#32039;&#23494;&#30340;&#38598;&#25104;&#12290;&#24212;&#29992;&#25110; API &#24050;&#19981;&#20877;&#21482;&#26159;&#38754;&#21521;&#28040;&#36153;&#32773;&#25110;&#24320;&#21457;&#32773;&#30340;&#25509;&#21475;&#65292;&#23427;&#20204;&#20063;&#21487;&#33021;&#25104;&#20026; AI Agent &#29702;&#35299;&#12289;&#35843;&#29992;&#21644;&#32534;&#25490;&#30340;&#23545;&#35937;&#12290;AI &#19981;&#21482;&#26159;&#24320;&#21457;&#24037;&#20855;&#65292;&#20063;&#20250;&#20316;&#20026;&#26032;&#30340;&#21442;&#19982;&#32773;&#65292;&#28145;&#24230;&#36827;&#20837;&#36719;&#20214;&#26381;&#21153;&#30340;&#26500;&#24314;&#21644;&#20351;&#29992;&#36807;&#31243;&#12290;</p><p>&#25105;&#24819;&#65292;&#36825;&#20063;&#26159;&#19981;&#23569;&#24320;&#21457;&#32773;&#38754;&#23545; WWDC 2026 &#26102;&#26082;&#26399;&#24453;&#21448;&#33579;&#28982;&#30340;&#22320;&#26041;&#12290;&#25105;&#20204;&#24076;&#26395;&#30475;&#21040;&#26356;&#26032;&#30340;&#21151;&#33021;&#12289;&#26356;&#31283;&#23450;&#30340;&#26694;&#26550;&#12289;&#26356;&#28165;&#26224;&#30340;&#24179;&#21488;&#26041;&#21521;&#65307;&#21516;&#26102;&#20063;&#22312;&#24605;&#32771;&#65292;&#22312;&#36825;&#26679;&#30340;&#24320;&#21457;&#20307;&#31995;&#20013;&#65292;&#22914;&#20309;&#32487;&#32493;&#20445;&#25345;&#33258;&#24049;&#20316;&#20026;&#24320;&#21457;&#32773;&#30340;&#29420;&#29305;&#24615;&#19982;&#24517;&#35201;&#24615;&#65292;&#24182;&#19982; AI &#19968;&#36215;&#26500;&#24314;&#26356;&#22909;&#30340;&#26381;&#21153;&#12290;</p><p>WWDC 2026 &#31350;&#31455;&#20250;&#24102;&#26469;&#22810;&#23569;&#21464;&#21270;&#65292;&#35753;&#25105;&#20204;&#25325;&#30446;&#20197;&#24453;&#12290;</p><div><hr></div><p><strong>BTW</strong>&#65306;&#19978;&#21608;&#25105;&#38750;&#24120;&#26377;&#24184;&#20837;&#36873;&#20102;&#33529;&#26524;&#23448;&#26041;&#26368;&#26032;&#20844;&#24067;&#30340; <strong><a href="https://developer.apple.com/community/recognition/">Apple Developer Community Spotlight</a></strong>&#12290;&#20316;&#20026;&#19968;&#21517;&#20869;&#23481;&#21019;&#20316;&#32773;&#65292;&#33021;&#22815;&#24471;&#21040;&#36825;&#26679;&#30340;&#35748;&#21487;&#65292;&#23545;&#25105;&#26469;&#35828;&#26082;&#26159;&#40723;&#21169;&#65292;&#20063;&#26159;&#38829;&#31574;&#65306;&#32487;&#32493;&#35748;&#30495;&#20889;&#19979;&#21435;&#65292;&#32487;&#32493;&#25226;&#26377;&#20215;&#20540;&#30340;&#20869;&#23481;&#24102;&#32473;&#22823;&#23478;&#12290;&#24863;&#35874;&#27599;&#19968;&#20301;&#38271;&#26399;&#38405;&#35835;&#12289;&#21453;&#39304;&#21644;&#25903;&#25345;&#25105;&#30340;&#26379;&#21451;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-135/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0136-01">&#20174; URLSession &#21040;&#30005;&#30913;&#27874;&#65306;iOS &#32593;&#32476;&#35831;&#27714;&#30340;&#24213;&#23618;&#21407;&#29702; (URLSession to Electrons: How Networking works on iOS)</a></strong></h3><p>&#24456;&#22810; iOS &#24320;&#21457;&#32773;&#37117;&#30693;&#36947;&#65306;<code>URLSessionDataTask</code> &#38656;&#35201;&#35843;&#29992; <code>resume()</code> &#25165;&#20250;&#30495;&#27491;&#24320;&#22987;&#35831;&#27714;&#12290;&#20294;&#22312;&#36825;&#20043;&#21518;&#31350;&#31455;&#21457;&#29983;&#20102;&#20160;&#20040;&#65311;<a href="https://x.com/jacobtechtavern">Jacob Bartlett</a> &#29992;&#19968;&#31687;&#38271;&#25991;&#65292;&#24102;&#35835;&#32773;&#19968;&#36335;&#36319;&#38543;&#19968;&#20010;&#26222;&#36890;&#30340;&#32593;&#32476;&#35831;&#27714;&#65292;&#20174; <code>URLSession</code>&#12289;CFNetwork&#12289;TCP/IP&#12289;Wi-Fi&#65292;&#19968;&#30452;&#28145;&#20837;&#21040;&#26080;&#32447;&#30005;&#12289;&#22825;&#32447;&#19982;&#30005;&#30913;&#27874;&#12290;Jacob &#19981;&#20165;&#20018;&#32852;&#36215; HTTP&#12289;DNS&#12289;TCP&#12289;QUIC&#12289;IPv6 &#31561;&#24320;&#21457;&#32773;&#29087;&#24713;&#21364;&#26410;&#24517;&#30495;&#27491;&#29702;&#35299;&#30340;&#27010;&#24565;&#65292;&#20063;&#32467;&#21512; iOS &#20869;&#37096;&#23454;&#29616;&#20171;&#32461;&#20102; <code>Network.framework</code>&#12289;XNU &#20869;&#26680; TCP &#26632;&#12289;Wi-Fi &#24103;&#32467;&#26500;&#20197;&#21450;&#34562;&#31389;&#32593;&#32476;&#30340;&#35843;&#24230;&#26426;&#21046;&#12290;</p><blockquote><p>&#19968;&#20010;&#31616;&#21333;&#30340; <code>resume()</code>&#65292;&#32972;&#21518;&#28041;&#21450;&#30340;&#20195;&#30721;&#19982;&#21327;&#35758;&#28436;&#36827;&#36328;&#24230;&#65292;&#21487;&#33021;&#36229;&#36807;&#21313;&#20960;&#29978;&#33267;&#20960;&#21313;&#24180;&#12290;&#19981;&#24471;&#19981;&#24863;&#24936;&#65292;&#29616;&#20195;&#36719;&#20214;&#19990;&#30028;&#24314;&#31435;&#22312;&#23618;&#23618;&#25277;&#35937;&#20043;&#19978;&#65292;&#32780;&#32477;&#22823;&#22810;&#25968;&#26102;&#20505;&#65292;&#25105;&#20204;&#20854;&#23454;&#21482;&#26159;&#24184;&#36816;&#22320;&#29983;&#27963;&#22312;&#36825;&#20123;&#25277;&#35937;&#36275;&#22815;&#31283;&#23450;&#30340;&#24180;&#20195;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-02a">&#24403; AI &#21644; Xcode &#25171;&#26550;&#26102;&#65306;&#25105;&#20889;&#20102;&#20010;&#24037;&#20855;&#26469;&#25289;&#26550;</a></strong></h3><p>Xcode &#30340;&#26500;&#24314;&#31995;&#32479;&#20174;&#26410;&#30495;&#27491;&#20026;&#8220;&#24182;&#34892;&#24320;&#21457;&#8221;&#35774;&#35745;&#36807;&#12290;&#22810;&#20010;&#20219;&#21153;&#21516;&#26102;&#26500;&#24314;&#26102;&#65292;DerivedData&#12289;ModuleCache&#12289;SwiftPM &#32531;&#23384;&#20035;&#33267; Simulator &#37117;&#21487;&#33021;&#20114;&#30456;&#36393;&#36367;&#65292;&#32780;&#36825;&#19968;&#38382;&#39064;&#22312; AI Agent &#24182;&#34892;&#24320;&#21457;&#22330;&#26223;&#19979;&#34987;&#36827;&#19968;&#27493;&#25918;&#22823;&#12290;<a href="https://x.com/Maples67">Maples7</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#20102;&#20182;&#30340;&#35299;&#20915;&#26041;&#26696;&#65306;<a href="https://github.com/Maples7/VibeChard">VibeChard</a>&#12290;&#23427;&#22522;&#20110; Git Worktree&#65292;&#20026;&#27599;&#20010; AI Agent &#21019;&#24314;&#29420;&#31435;&#30340;&#26500;&#24314;&#27801;&#31665;&#65292;&#24182;&#36827;&#19968;&#27493;&#38548;&#31163; DerivedData&#12289;ModuleCache&#12289;SwiftPM &#32531;&#23384;&#20197;&#21450;&#27169;&#25311;&#22120;&#29615;&#22659;&#12290;&#26368;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#23427;&#24182;&#19981;&#35201;&#27714;&#24320;&#21457;&#32773;&#20462;&#25913;&#26500;&#24314;&#21629;&#20196;&#65292;&#32780;&#26159;&#36890;&#36807; PATH shim &#36879;&#26126;&#25509;&#31649; <code>xcodebuild</code>&#65292;&#35753;&#21253;&#25324; Tuist&#12289;Fastlane &#22312;&#20869;&#30340;&#25972;&#26465;&#24037;&#20855;&#38142;&#37117;&#33258;&#21160;&#36816;&#34892;&#22312;&#38548;&#31163;&#29615;&#22659;&#20013;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#20010;&#21333;&#32431;&#30340;&#36741;&#21161;&#24037;&#20855;&#65292;&#19981;&#22914;&#35828;&#23427;&#25581;&#31034;&#20102; AI &#32534;&#31243;&#26102;&#20195;&#19968;&#20010;&#26356;&#24213;&#23618;&#30340;&#38382;&#39064;&#65306;&#24403;&#20195;&#30721;&#29983;&#25104;&#36895;&#24230;&#22823;&#24133;&#25552;&#21319;&#21518;&#65292;&#20256;&#32479;&#24320;&#21457;&#24037;&#20855;&#38142;&#30340;&#29615;&#22659;&#38548;&#31163;&#33021;&#21147;&#20063;&#24517;&#39035;&#38543;&#20043;&#21319;&#32423;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-03">Swift &#30495;&#30340;&#34987;&#25630;&#24471;&#20081;&#19971;&#20843;&#31967;&#20102;&#21527;&#65311;&#20889;&#20102;&#20960;&#24180;&#20043;&#21518;&#35828;&#28857;&#23454;&#35805;</a></strong></h3><p>Swift &#21464;&#24471;&#36234;&#26469;&#36234;&#22797;&#26434;&#65292;&#36825;&#26159;&#19968;&#20010;&#19981;&#20105;&#30340;&#20107;&#23454;&#12290;&#20294;&#36825;&#26159;&#21542;&#24847;&#21619;&#30528; Swift &#24050;&#32463;&#21464;&#25104;&#20102;&#19968;&#38376;&#31967;&#31957;&#30340;&#35821;&#35328;&#65311;<a href="https://juejin.cn/user/4089838986071175/posts">&#36855;&#36884;&#37233;</a> &#20174;&#35821;&#35328;&#28436;&#36827;&#30340;&#29616;&#23454;&#32422;&#26463;&#20986;&#21457;&#65292;&#37325;&#26032;&#23457;&#35270; Swift &#36825;&#20123;&#24180;&#30340;&#8220;&#33192;&#32960;&#8221;&#12290;&#20316;&#32773;&#35748;&#20026;&#65292;&#35768;&#22810;&#34987;&#21520;&#27133;&#30340;&#22797;&#26434;&#24230;&#65292;&#20854;&#23454;&#26469;&#33258; Swift &#21516;&#26102;&#25215;&#25285;&#24212;&#29992;&#23618;&#12289;&#31995;&#32479;&#32423;&#12289;DSL &#23487;&#20027;&#19982;&#26381;&#21153;&#31471;&#35821;&#35328;&#31561;&#22810;&#37325;&#30446;&#26631;&#65292;&#32780;&#24182;&#21457;&#23433;&#20840;&#19982;&#25152;&#26377;&#26435;&#27169;&#22411;&#26412;&#36523;&#65292;&#20063;&#23646;&#20110;&#35745;&#31639;&#26426;&#31185;&#23398;&#23618;&#38754;&#30340;&#8220;&#30828;&#22797;&#26434;&#24230;&#8221;&#12290;</p><p>&#25991;&#31456;&#26082;&#35752;&#35770;&#20102; <code>Sendable</code>&#12289;<code>actor isolation</code>&#12289;<code>borrowing</code>&#12289;<code>~Copyable</code> &#31561;&#36817;&#24180;&#26469;&#24555;&#36895;&#22686;&#38271;&#30340;&#26032;&#27010;&#24565;&#65292;&#20063;&#22374;&#29575;&#25351;&#20986; Swift &#22312;&#24182;&#21457;&#20851;&#38190;&#23383;&#12289;&#27867;&#22411;&#35821;&#27861;&#20197;&#21450; SwiftUI &#8220;&#39764;&#27861;&#24863;&#8221;&#19978;&#30340;&#35774;&#35745;&#38382;&#39064;&#12290;&#23588;&#20854;&#26159;&#8220;Swift &#20854;&#23454;&#26159;&#19968;&#20010;&#35821;&#35328;&#30340;&#22810;&#20010;&#23618;&#32423;&#8221;&#36825;&#19968;&#35266;&#28857;&#65292;&#30456;&#24403;&#20540;&#24471;&#24605;&#32771;&#65306;&#32477;&#22823;&#22810;&#25968;&#24320;&#21457;&#32773;&#26085;&#24120;&#20889; App &#26102;&#65292;&#20854;&#23454;&#24182;&#19981;&#38656;&#35201;&#25215;&#25285;&#20840;&#37096;&#22797;&#26434;&#24230;&#65292;&#20294; WWDC &#19982;&#23448;&#26041;&#25991;&#26723;&#21364;&#32463;&#24120;&#25226;&#36825;&#20123;&#20869;&#23481;&#21516;&#26102;&#21576;&#29616;&#22312;&#25152;&#26377;&#20154;&#38754;&#21069;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-04">Xcode Cloud &#36827;&#38454;&#65306;Shell &#33050;&#26412;&#33258;&#21160;&#21270;&#23454;&#25112; (Writing shell scripts for Xcode Cloud)</a></strong></h3><p>Xcode Cloud &#30340;&#19978;&#25163;&#20307;&#39564;&#24050;&#32463;&#36275;&#22815;&#31616;&#21333;&#65292;&#20294;&#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#65292;&#35768;&#22810;&#33258;&#21160;&#21270;&#38656;&#27714;&#20173;&#28982;&#38656;&#35201;&#20511;&#21161; shell scripts &#23436;&#25104;&#12290;<a href="https://www.linkedin.com/in/amy-delves-41968418b/">Amy Delves</a> &#20197;&#8220;&#22312;&#24402;&#26723;&#23436;&#25104;&#21518;&#33258;&#21160;&#21019;&#24314; GitHub Release&#8221;&#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#22914;&#20309;&#32467;&#21512; Xcode Cloud &#25552;&#20379;&#30340;&#29615;&#22659;&#21464;&#37327;&#21028;&#26029;&#24403;&#21069;&#26500;&#24314;&#26159;&#21542;&#26469;&#33258; <code>main</code> &#20998;&#25903;&#30340;&#24402;&#26723;&#27969;&#31243;&#65292;&#22914;&#20309;&#35835;&#21462; archive &#20013;&#30340;&#29256;&#26412;&#21495;&#19982;&#26500;&#24314;&#21495;&#29983;&#25104; tag&#65292;&#24182;&#36890;&#36807; GitHub API &#21019;&#24314; release&#12290;&#34429;&#28982;&#31034;&#20363;&#26412;&#36523;&#24182;&#19981;&#22797;&#26434;&#65292;&#20294;&#23427;&#24456;&#22909;&#22320;&#35828;&#26126;&#20102; Xcode Cloud &#24182;&#19981;&#21482;&#26159;&#19968;&#20010;&#8220;&#28857;&#20960;&#19979;&#23601;&#33021;&#36305;&#27979;&#35797;&#8221;&#30340;&#26381;&#21153;&#65306;&#20511;&#21161;&#29615;&#22659;&#21464;&#37327;&#12289;&#33050;&#26412;&#38057;&#23376;&#19982;&#22806;&#37096; API&#65292;&#23427;&#21516;&#26679;&#21487;&#20197;&#25215;&#25285;&#26356;&#23436;&#25972;&#30340;&#21457;&#24067;&#33258;&#21160;&#21270;&#24037;&#20316;&#27969;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-05">&#25105;&#20204;&#20026;&#20160;&#20040;&#31163;&#24320;&#20102;&#24456;&#26834;&#30340; CloudKit (Why CloudKit is amazing and why we&#8217;re leaving it)</a></strong></h3><p>&#36825;&#26159;&#19968;&#31687;&#30456;&#24403;&#23569;&#35265;&#12289;&#22374;&#35802;&#30340; CloudKit &#36801;&#31227;&#22797;&#30424;&#12290;<a href="https://x.com/JagCesar">C&#233;sar Pinto Castillo</a> &#24182;&#27809;&#26377;&#31616;&#21333;&#25209;&#35780; CloudKit&#65292;&#24688;&#24688;&#30456;&#21453;&#65292;&#20182;&#39318;&#20808;&#25215;&#35748;&#65306;&#23545;&#20110;&#23567;&#22242;&#38431;&#26469;&#35828;&#65292;CloudKit &#20960;&#20046;&#25552;&#20379;&#20102;&#19968;&#22871;&#8220;&#19981;&#21487;&#24605;&#35758;&#8221;&#30340;&#33021;&#21147;&#32452;&#21512;&#8212;&#8212;&#20813;&#36153;&#21516;&#27493;&#12289;&#33258;&#21160;&#36523;&#20221;&#35748;&#35777;&#12289;&#31471;&#21040;&#31471;&#21152;&#23494;&#12289;&#26080;&#26381;&#21153;&#22120;&#36816;&#32500;&#65292;&#20197;&#21450;&#36328; Apple &#24179;&#21488;&#30340;&#20849;&#20139;&#33021;&#21147;&#12290;</p><p>&#20294;&#38543;&#30528;&#20135;&#21697;&#36880;&#28176;&#21457;&#23637;&#65292;CloudKit &#30340;&#21478;&#19968;&#38754;&#20063;&#24320;&#22987;&#26174;&#29616;&#65306;&#32570;&#20047;&#26381;&#21153;&#31471;&#21487;&#35266;&#27979;&#24615;&#12289;Schema &#21457;&#24067;&#20381;&#36182;&#25163;&#21160;&#25805;&#20316;&#12289;&#19981;&#21516; Apple &#24179;&#21488;&#38388;&#38271;&#26399;&#23384;&#22312;&#30340;&#21516;&#27493;&#36793;&#32536;&#38382;&#39064;&#12289;&#23545; iCloud &#36134;&#25143;&#30340;&#24378;&#20381;&#36182;&#65292;&#20197;&#21450;&#26368;&#20851;&#38190;&#30340;&#8212;&#8212;&#26080;&#27861;&#30495;&#27491;&#36208;&#21521; Web &#19982;&#36328;&#24179;&#21488;&#29983;&#24577;&#12290;&#26368;&#32456;&#65292;C&#233;sar &#25152;&#22312;&#30340;&#22242;&#38431;&#23558;&#25968;&#25454;&#36801;&#31227;&#21040;&#20102;&#22522;&#20110; Supabase/Postgres &#30340;&#21516;&#27493;&#26550;&#26500;&#12290;</p><blockquote><p>CloudKit &#26159;&#33529;&#26524;&#29983;&#24577;&#26368;&#37325;&#35201;&#30340;&#25252;&#22478;&#27827;&#20043;&#19968;&#12290;&#20294;&#22312;&#24212;&#29992;&#36234;&#26469;&#36234;&#22797;&#26434;&#12289;&#25968;&#25454;&#35268;&#27169;&#36234;&#26469;&#36234;&#22823;&#12289;&#29992;&#25143;&#23545;&#21516;&#27493;&#23454;&#26102;&#24615;&#30340;&#35201;&#27714;&#36234;&#26469;&#36234;&#39640;&#30340;&#20170;&#22825;&#65292;&#23427;&#30340;&#33021;&#21147;&#36793;&#30028;&#20063;&#24320;&#22987;&#26174;&#29616;&#12290;&#22312;&#36861;&#27714;&#8220;&#26080;&#24863;&#21516;&#27493;&#8221;&#30340;&#21516;&#26102;&#65292;&#25105;&#24819;&#33529;&#26524;&#20063;&#30830;&#23454;&#38656;&#35201;&#37325;&#26032;&#35748;&#30495;&#23457;&#35270;&#36825;&#20010;&#22810;&#24180;&#26410;&#21457;&#29983;&#26126;&#26174;&#28436;&#36827;&#30340;&#22522;&#30784;&#35774;&#26045;&#20102;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-06">&#29992; Swift &#25163;&#20889; LLM &#35757;&#32451;&#20869;&#26680; (Training an LLM in Swift, Part 1: Taking matrix multiplication from Gflop/s to Tflop/s)</a></strong></h3><p>&#22312; Swift &#20013;&#35757;&#32451; LLM &#21548;&#36215;&#26469;&#22810;&#23569;&#26377;&#20123;&#8220;&#21290;&#22839;&#25152;&#24605;&#8221;&#65292;&#20294; <a href="https://mastodon.social/@cocoawithlove">Matt Gallagher</a> &#20570;&#20102;&#19968;&#27425;&#38750;&#24120;&#30828;&#26680;&#30340;&#24615;&#33021;&#25506;&#32034;&#65306;&#19981;&#20381;&#36182;&#29616;&#25104;&#26426;&#22120;&#23398;&#20064;&#26694;&#26550;&#65292;&#32780;&#26159;&#20174;&#25163;&#20889;&#30697;&#38453;&#20056;&#27861;&#24320;&#22987;&#65292;&#19968;&#27493;&#27493;&#23558;&#22522;&#30784; Swift &#23454;&#29616;&#20174; 2.8 Gflop/s &#20248;&#21270;&#21040; 1.1 Tflop/s&#12290;&#25991;&#31456;&#36890;&#36807;&#19968;&#20010;&#23436;&#25972;&#30340;&#20248;&#21270;&#36807;&#31243;&#65292;&#23637;&#31034;&#20102;&#39640;&#24615;&#33021; Swift &#30340;&#29616;&#23454;&#38754;&#35980;&#65306;Swift &#24182;&#19981;&#26159;&#19981;&#33021;&#24555;&#65292;&#20294;&#24403;&#20320;&#36880;&#28176;&#36924;&#36817;&#30828;&#20214;&#33021;&#21147;&#26102;&#65292;&#20063;&#23558;&#19981;&#21487;&#36991;&#20813;&#22320;&#36827;&#20837; <code>UnsafeBufferPointer</code>&#12289;SIMD&#12289;&#24182;&#21457;&#20999;&#29255;&#12289;&#20869;&#23384;&#24067;&#23616;&#19982; GPU tile &#20248;&#21270;&#30340;&#19990;&#30028;&#12290;</p><p>&#36825;&#31687;&#25991;&#31456;&#30340;&#20215;&#20540;&#24182;&#19981;&#22312;&#20110;&#40723;&#21169;&#24320;&#21457;&#32773;&#25163;&#20889;&#26426;&#22120;&#23398;&#20064;&#20869;&#26680;&#12290;&#24688;&#24688;&#30456;&#21453;&#65292;&#20316;&#32773;&#21453;&#22797;&#24378;&#35843;&#65292;&#29983;&#20135;&#29615;&#22659;&#24212;&#35813;&#20248;&#20808;&#20351;&#29992; Accelerate&#12289;BNNS&#12289;Core ML&#12289;MPSGraph &#31561;&#25104;&#29087;&#26694;&#26550;&#12290;</p><blockquote><p>&#24403; Swift &#34987;&#20248;&#21270;&#21040;&#25509;&#36817; C &#30340;&#31243;&#24230;&#26102;&#65292;&#23427;&#36824;&#33021;&#21542;&#20445;&#25345;&#21407;&#26412;&#30340;&#21487;&#35835;&#24615;&#19982;&#20248;&#38597;&#65311;&#36825;&#31687;&#25991;&#31456;&#32473;&#20986;&#20102;&#19968;&#20010;&#38750;&#24120;&#20855;&#20307;&#65292;&#20063;&#24456;&#35802;&#23454;&#30340;&#31572;&#26696;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-07">Swift &#36866;&#21512;&#20889; App&#65292;&#20294;&#19981;&#36866;&#21512;&#35757;&#32451; ML &#27169;&#22411; (Swift Is Great for Apps, Not for Training ML Models)</a></strong></h3><p>&#19978;&#19968;&#31687;&#25991;&#31456;&#36824;&#22312;&#23637;&#31034;&#22914;&#20309;&#23558; Swift &#25163;&#20889;&#30697;&#38453;&#20056;&#27861;&#19968;&#36335;&#20248;&#21270;&#21040; Tflop/s&#65292;&#36825;&#31687;&#25991;&#31456;&#21017;&#20174;&#21478;&#19968;&#20010;&#35282;&#24230;&#27900;&#20102;&#30406;&#20919;&#27700;&#65306;<a href="https://x.com/azamsharp">Mohammad Azam</a> &#35748;&#20026;&#65292;Swift &#19982; Core ML &#38750;&#24120;&#36866;&#21512;&#8220;&#37096;&#32626;&#8221;&#26426;&#22120;&#23398;&#20064;&#27169;&#22411;&#65292;&#20294;&#24182;&#19981;&#36866;&#21512;&#25215;&#25285;&#29616;&#20195;&#26426;&#22120;&#23398;&#20064;&#35757;&#32451;&#27969;&#31243;&#26412;&#36523;&#12290;Mohammad &#25351;&#20986;&#65292;&#30495;&#27491;&#32791;&#36153;&#26102;&#38388;&#30340;&#24448;&#24448;&#19981;&#26159;&#27169;&#22411;&#35757;&#32451;&#65292;&#32780;&#26159;&#25968;&#25454;&#28165;&#27927;&#12289;&#29305;&#24449;&#24037;&#31243;&#12289;&#24402;&#19968;&#21270;&#12289;Pipeline &#32452;&#21512;&#19982;&#23454;&#39564;&#36845;&#20195;&#65292;&#32780;&#36825;&#20123;&#24688;&#24688;&#26159; Python &#29983;&#24577;&#26368;&#25104;&#29087;&#12289;&#26368;&#39034;&#25163;&#30340;&#39046;&#22495;&#12290;</p><blockquote><p>Swift &#24182;&#38750;&#19981;&#33021;&#35302;&#30896;&#26426;&#22120;&#23398;&#20064;&#24213;&#23618;&#65292;&#20294;&#24403;&#38382;&#39064;&#20174;&#8220;&#24615;&#33021;&#8221;&#36716;&#21521;&#8220;&#25968;&#25454;&#31185;&#23398;&#24037;&#20316;&#27969;&#8221;&#21518;&#65292;&#35821;&#35328;&#19982;&#29983;&#24577;&#30340;&#37325;&#24515;&#24046;&#24322;&#20415;&#20250;&#36805;&#36895;&#26174;&#29616;&#12290;&#36825;&#20063;&#20984;&#26174;&#20102; Swift &#24403;&#21069;&#30340;&#19968;&#20010;&#22256;&#22659;&#65306;&#23427;&#20855;&#22791;&#36827;&#20837;&#22810;&#20010;&#39046;&#22495;&#30340;&#35821;&#35328;&#33021;&#21147;&#65292;&#20294;&#22312;&#24212;&#29992;&#24320;&#21457;&#20043;&#22806;&#65292;&#37197;&#22871;&#29983;&#24577;&#20173;&#19981;&#36275;&#20197;&#25903;&#25745;&#21516;&#31561;&#39034;&#30021;&#30340;&#24320;&#21457;&#20307;&#39564;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0136-08">Swift MarkdownEngine</a></strong></h3><p>MarkdownEngine &#26159; <a href="https://nodes-web.com/">Nodes</a> &#22242;&#38431;&#20174;&#33258;&#23478; macOS Markdown &#24212;&#29992;&#20013;&#25277;&#31163;&#24182;&#24320;&#28304;&#30340;&#21407;&#29983;&#32534;&#36753;&#22120;&#24341;&#25806;&#12290;&#23427;&#19981;&#26159; HTML &#28210;&#26579;&#22120;&#65292;&#20063;&#19981;&#26159; WebView &#21253;&#35013;&#65292;&#32780;&#26159;&#22522;&#20110; TextKit 2 &#19982; AppKit &#26500;&#24314;&#65292;&#24182;&#26725;&#25509;&#21040; SwiftUI &#30340; source-style Markdown &#32534;&#36753;&#22120;&#65306;&#25991;&#26412;&#20173;&#20445;&#25345;&#32431; Markdown&#65292;&#20294;&#22312;&#32534;&#36753;&#26102;&#25552;&#20379;&#31867;&#20284; Obsidian Live Preview / iA Writer &#30340;&#23454;&#26102;&#26679;&#24335;&#12290;&#39033;&#30446;&#25903;&#25345; wiki link&#12289;&#22270;&#29255;&#23884;&#20837;&#12289;&#20195;&#30721;&#22359;&#39640;&#20142;&#12289;LaTeX&#12289;&#20219;&#21153;&#21015;&#34920;&#12289;Writing Tools&#65292;&#20197;&#21450;&#38024;&#23545;&#20195;&#30721;&#12289;&#20844;&#24335;&#21644;&#38142;&#25509;&#30340;&#25340;&#20889;&#26816;&#26597;&#25233;&#21046;&#12290;</p><blockquote><p>TextKit 2 &#25991;&#26723;&#31232;&#34180;&#12289;&#34892;&#20026;&#32454;&#33410;&#22810;&#65292;&#32780;&#36825;&#20010;&#39033;&#30446;&#25226;&#19968;&#22871;&#24050;&#22312; <a href="https://apps.apple.com/us/app/nodes-by-the-werk/id6745401961">Nodes.app</a> &#20013;&#20351;&#29992;&#30340;&#32534;&#36753;&#22120;&#33021;&#21147;&#24320;&#28304;&#20986;&#26469;&#65292;&#23545;&#27491;&#22312;&#24320;&#21457;&#20889;&#20316;&#12289;&#31508;&#35760;&#25110;&#30693;&#35782;&#31649;&#29702;&#31867; macOS &#24212;&#29992;&#30340;&#24320;&#21457;&#32773;&#24456;&#26377;&#21442;&#32771;&#20215;&#20540;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0136-09">Harness&#65306;&#35753; AI &#20687;&#30495;&#23454;&#29992;&#25143;&#19968;&#26679;&#27979;&#35797;&#20320;&#30340; App</a></strong></h3><p>Harness &#26159;&#30001; <a href="https://www.linkedin.com/in/alanwizemann/">Alan Wizemann</a> &#24320;&#21457;&#30340;&#19968;&#27454;&#21407;&#29983; macOS &#24320;&#21457;&#32773;&#24037;&#20855;&#65292;&#21487;&#20197;&#39537;&#21160; iOS Simulator&#12289;macOS App &#21644; Web App&#12290;&#20320;&#29992;&#33258;&#28982;&#35821;&#35328;&#20889;&#19979;&#30446;&#26631;&#65292;&#36873;&#25321;&#19968;&#20010; persona&#65292;Harness &#20250;&#35753; LLM agent &#22522;&#20110;&#25130;&#22270;&#35266;&#23519;&#30028;&#38754;&#12289;&#25191;&#34892;&#28857;&#20987;&#21644;&#36755;&#20837;&#65292;&#24182;&#29983;&#25104;&#21487;&#22238;&#25918;&#30340;&#36816;&#34892;&#36335;&#24452;&#12289;&#25104;&#21151;&#25110;&#22833;&#36133;&#32467;&#35770;&#65292;&#20197;&#21450;&#25353;&#31867;&#22411;&#35760;&#24405;&#30340; UX friction&#12290;&#30456;&#27604;&#21333;&#32431;&#35753; AI &#8220;&#25805;&#20316;&#24212;&#29992;&#8221;&#65292;&#23427;&#26356;&#20687;&#26159;&#25226; AI agent&#12289;&#25130;&#22270;&#12289;&#20107;&#20214;&#26085;&#24535;&#12289;&#20973;&#35777;&#33073;&#25935;&#12289;&#36816;&#34892;&#22238;&#25918;&#21644;&#25705;&#25830;&#20998;&#31867;&#25972;&#21512;&#25104;&#20102;&#19968;&#22871;&#38754;&#21521;&#24320;&#21457;&#38454;&#27573;&#30340;&#29992;&#25143;&#27979;&#35797;&#24037;&#20316;&#21488;&#12290;</p><p>&#30446;&#21069;&#39033;&#30446;&#20173;&#22788;&#20110; alpha &#38454;&#27573;&#65292;Web &#31471;&#20381;&#36182; WebKit&#65292;iOS/macOS &#30340; Set-of-Mark &#23450;&#20301;&#33021;&#21147;&#36824;&#22312;&#35268;&#21010;&#20013;&#65292;&#22240;&#27492;&#26356;&#36866;&#21512;&#29992;&#20110;&#25506;&#32034;&#20135;&#21697;&#20307;&#39564;&#20013;&#30340;&#27169;&#31946;&#28857;&#21644;&#27515;&#35282;&#65292;&#32780;&#19981;&#26159;&#26367;&#20195;&#30830;&#23450;&#24615;&#30340;&#22238;&#24402;&#27979;&#35797;&#12290;&#19981;&#36807;&#20174; Swift 6&#12289;SwiftUI&#12289;SwiftData&#12289;actor &#21270;&#30340;&#25191;&#34892;&#27969;&#31243;&#12289;JSONL run log&#65292;&#20197;&#21450;&#36328; Anthropic/OpenAI/Gemini &#30340;&#27169;&#22411;&#25277;&#35937;&#26469;&#30475;&#65292;&#23427;&#24050;&#32463;&#19981;&#26159;&#19968;&#20010;&#31616;&#21333; demo&#65292;&#32780;&#26159;&#19968;&#20010;&#24456;&#20540;&#24471;&#35266;&#23519;&#30340; AI-native developer tool &#26679;&#26412;&#12290;</p><blockquote><p>&#20256;&#32479; UI &#27979;&#35797;&#26356;&#25797;&#38271;&#39564;&#35777;&#24320;&#21457;&#32773;&#39044;&#35774;&#22909;&#30340;&#36335;&#24452;&#65292;&#32780; Harness &#35797;&#22270;&#22238;&#31572;&#21478;&#19968;&#20010;&#38382;&#39064;&#65306;&#19968;&#20010;&#24102;&#30528;&#20855;&#20307;&#30446;&#26631;&#21644;&#36523;&#20221;&#35774;&#23450;&#30340;&#30495;&#23454;&#29992;&#25143;&#65292;&#20250;&#19981;&#20250;&#22312;&#20320;&#30340;&#30028;&#38754;&#20013;&#39034;&#21033;&#23436;&#25104;&#20219;&#21153;&#12290;</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #135]]></title><description><![CDATA[CocoaPods Is on Its Way Out, but SwiftPM&#8217;s Story Is Just Entering Chapter Two]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-135</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-135</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 11 May 2026 12:02:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Cr68!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Cr68!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cr68!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 424w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 848w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 1272w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cr68!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp" width="1456" height="698" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:698,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22826,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/197094930?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Cr68!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 424w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 848w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 1272w, https://substackcdn.com/image/fetch/$s_!Cr68!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ea72ffd-e91e-4664-9b18-588fc34b0c09_1531x734.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>CocoaPods Is on Its Way Out, but SwiftPM&#8217;s Story Is Just Entering Chapter Two</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-135/">Read on web &#8594;</a></p><p>Google recently announced that, starting with the next Flutter stable release, version 3.44, Swift Package Manager will replace CocoaPods in the default workflow and become the default dependency manager for iOS and macOS apps. CocoaPods&#8217; Trunk repository will officially become read-only on December 2, 2026 &#8212; a date we already discussed in the 2024 issues of the newsletter. Still, when Flutter truly began replacing CocoaPods with SPM in its default path, it sparked widespread discussion across the community.</p><p>Many developers who have long been constrained by CocoaPods, especially those with a front-end background, greeted the news with great enthusiasm. After all, they can finally spend less time wrestling with <code>gem install</code> on M-series Macs, and they no longer have to face those mysterious Pods errors that always seem to appear from nowhere yet somehow manage to block the build process with surgical precision. The update even briefly turned into something of a &#8220;celebration of breaking free from Ruby.&#8221; However, because Flutter&#8217;s official switch came somewhat abruptly, many third-party plugin authors also felt anxious, as issues requesting <code>Package.swift</code> support quickly began pouring into numerous open-source projects.</p><p>Compared with the short-term adaptation pressure on plugin authors, the more lasting test brought by this transition lies in the reconstruction of CI/CD workflows for enterprise projects. For teams whose foundations still contain a large number of historical CocoaPods dependencies, switching to SPM smoothly and with as little pain as possible will become a major infrastructure-level challenge. Migration is not simply a matter of adding a <code>Package.swift</code> file locally. It means that build caches, private dependencies, binary frameworks, Xcode project generation, static and dynamic linking strategies, and multi-platform build scripts all need to be recalibrated.</p><p>This is not limited to Flutter. Given that CocoaPods has long acted as the &#8220;universal glue&#8221; between cross-platform frameworks and the native iOS ecosystem, communities such as React Native and KMP have also begun laying the groundwork for migration to SPM, while Unity-related iOS dependency resolution workflows have also started supporting SPM. Over the next period, cross-platform communities built around Apple platform build pipelines will very likely go through a painful &#8220;great migration.&#8221; It is fair to say that by 2027, SPM &#8212; a tool that has already been around for a decade &#8212; will most likely complete its &#8220;great unification&#8221; of the mainstream dependency management path across Apple platforms.</p><p>For SPM, this is undoubtedly a major victory. But we should also be clear-eyed about what this victory means. It does not mean that SPM has achieved a true breakthrough beyond its original circle. Rather, it looks more like an inward-facing victory within Apple&#8217;s native ecosystem: replacing an older solution from the Objective-C era with a modern toolchain that offers better Swift support and tighter integration with Xcode. As long as cross-platform frameworks want to deliver reliably on Apple platforms, they will ultimately find it difficult to bypass Apple&#8217;s native rules.</p><p>So where will SPM go in its next decade? Will it continue to serve as the &#8220;internal optimal solution&#8221; for Apple&#8217;s ecosystem, or will it truly step beyond the walls and compete on the same stage as tools like Cargo and npm? The answer probably does not lie in SPM itself, but in whether the Swift language can produce truly killer use cases in areas such as Linux, Android, and embedded systems.</p><p>Until that day arrives, there is one thing we can be certain of: CocoaPods&#8217; exit is already irreversible, but SwiftPM&#8217;s story has only just turned to its second chapter.</p><p><a href="https://fatbobman.com/en/weekly/issue-134/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0135-01">Deep Understanding while using LLMs</a></strong></h3><p>At the beginning of his SwiftUI workshops, <a href="https://m.objc.io/@chris">Chris Eidhof</a> tells attendees to put LLMs aside during the exercises. The reason is not that he is against AI, but that getting an answer quickly with an LLM is not the same as truly understanding the problem. The core of this article is an increasingly visible phenomenon in the age of AI-assisted programming: more and more developers are falling into &#8220;shallow thinking.&#8221; They keep prompting, patching, and pushing features forward, while gradually losing a real understanding of the system itself. Once project complexity increases, things start to spiral out of control.</p><p>The article&#8217;s subtitle, &#8220;Solve It in 20 Minutes &#8212; Or Actually Understand It,&#8221; is not only a description of the workshop setting, but also a choice that the AI programming era places in front of developers. LLMs do not replace engineering ability; they amplify the understanding and judgment that developers already have.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-02">Installing Swift scripts as global commands with npm</a></strong></h3><p>More Swift developers are starting to use Swift to write CLI tools. But during development, having to recompile after every change, manually move the binary, or maintain shell aliases can easily interrupt the iteration flow. <a href="https://www.linkedin.com/in/crisfeim/">Cristian Felipe Pati&#241;o Rojas</a> offers a creative solution: use npm&#8217;s <code>bin</code> mechanism to register a Swift script with a shebang as a global command. This allows the Swift script to be invoked just like a regular CLI tool, while npm only creates a global symlink and does not participate in building the Swift code.</p><blockquote><p>Considering that launching a script through <code>swift</code> has a nontrivial cold-start cost, often taking several seconds, this approach is better suited to the development stage of Swift CLI tools. For small utilities like these, developers do not necessarily need to turn them into full Swift Packages from the very beginning. Starting with the lightest possible approach, then compiling and distributing the tool once it stabilizes, is often a better fit for real-world workflows.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-03">WatchConnectivity was failing 40% of the time. So I stopped using it.</a></strong></h3><p>While building real-time communication for an Apple Watch app, <a href="https://www.linkedin.com/in/tarek-sabry-846514147/">Tarek Sabry</a> ran into a very frustrating problem: Apple&#8217;s official WatchConnectivity framework was unstable, with a connection success rate of only around 60%. Eventually, Tarek stopped treating WatchConnectivity as the only reliable channel and introduced a parallel network transport path instead: BLE for service discovery, HTTP for data transfer, SSE for the push channel, plus frame IDs, ack confirmation, deduplication, and retransmission. This successfully raised the connection success rate from 60% to 99%, with an almost immediate effect.</p><p>The more interesting by-product of this approach is that, because it is entirely based on standard network protocols, the Watch does not know whether the other end is an iPhone, an Android phone, or any device with an IP address. According to the author, as of April 2026, this is the only publicly available Android &#8596; Apple Watch communication solution. The solution has been open-sourced under the name <a href="https://github.com/tareksabry1337/WatchLink">WatchLink</a>, supports Swift 6, and has no third-party dependencies.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-04">Using SwiftUI to Build a Mac-assed App in 2026</a></strong></h3><p>The term &#8220;Mac-assed app&#8221; describes software that truly belongs on the Mac: it uses native system controls, deeply integrates with system features, and gets every interaction detail aligned with platform conventions. While building a macOS app entirely in SwiftUI, <a href="https://x.com/pfandrade_">Paulo Andrade</a> found that although SwiftUI provides enough APIs to cover simple scenarios, the framework itself often becomes an obstacle when developers try to reproduce the interaction conventions that Mac apps have accumulated over decades.</p><p>The article breaks down several clear shortcomings of SwiftUI on macOS today: custom lists struggle to fully reproduce the subtle differences between selection, loss of focus, and right-click context targets; there is no way to detect when a context menu is open, making it difficult to correctly highlight the object the menu applies to; visibility into drag state is almost nonexistent; keyboard navigation is easily &#8220;swallowed&#8221; once a <code>TextField</code> has focus; and toolbar layout control is far less precise than in AppKit. Paulo argues that SwiftUI still has not completed the handoff from AppKit.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-05">Scheduling and handling background app refresh in SwiftUI</a></strong></h3><p>Background refresh in iOS may look simple at the API level, but it is easy to run into pitfalls in practice. In this article, <a href="https://x.com/natpanferova">Natalia Panferova</a> demonstrates how to configure <code>BGAppRefreshTaskRequest</code> with the Background Tasks framework under the SwiftUI App lifecycle, and how to register the handling logic through the <code>backgroundTask(_:action:)</code> scene modifier. The article walks through the full basic flow of adding background refresh to a SwiftUI app, from enabling Background Modes and registering the task identifier in Info.plist, to submitting the background refresh request and handling the app when the system wakes it. The author also explains how to simulate a background task trigger on a physical device using an Xcode debugger command, making it easier to verify the logic during development.</p><blockquote><p>It is worth noting that background refresh is not a precise scheduler. Even if <code>earliestBeginDate</code> is set, the system decides whether and when to wake the app based on factors such as battery level and user behavior. Therefore, critical logic should not depend on it running on time.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-06">How to avoid Swift 6 concurrency crashes</a></strong></h3><p>Even with zero compile-time warnings under Swift 6 strict concurrency mode, runtime safety is not guaranteed. The compiler injects dynamic isolation assertions at actor and GCD boundaries, and if the execution path does not match the compiler&#8217;s assumptions, the app can still crash in production with <code>_dispatch_assert_queue_fail</code> or <code>_swift_task_checkIsolatedSwift</code>.</p><p><a href="https://x.com/onmyway133">Khoa</a> lists several common triggering scenarios: closures defined inside an <code>@MainActor</code> context inherit main actor isolation, and if they are later called on a background thread by old-style callback or queue-based APIs, a crash may occur; in Combine pipelines, the position of <code>receive(on:)</code> affects closure isolation inheritance; and if a delegate method inherits main actor isolation because the entire class is marked <code>@MainActor</code>, but the SDK actually calls it from an internal queue, it can also trigger a runtime assertion.</p><blockquote><p>The approaches Khoa introduces in this article can help developers quickly locate and fix common runtime crash points when migrating old projects to Swift 6. However, if time and energy allow, the more ideal direction is still to reorganize feature code according to Swift 6&#8217;s modern concurrency model, make isolation boundaries explicit, and reduce reliance on local annotations and patch-style fixes.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0135-07">SwiftMetalNumerics: A Swift-native GPU numerical computing library for Apple Silicon</a></strong></h3><p>When building real-time audio analysis or on-device signal modeling on Apple platforms, developers often get stuck in an awkward middle ground. High-level APIs such as SoundAnalysis and AVAudioEngine are convenient, but they often behave like black boxes that only provide processed results. Once you need to control STFT, frequency binning, matrix operations, or feed extracted features into custom neural network layers, you often have to bridge back and forth between Accelerate/vDSP and low-level Metal. CPU-side computation can be fast, but once the downstream computation enters the GPU pipeline, data movement and synchronization may become the bottleneck for real-time processing.</p><p><a href="https://www.linkedin.com/in/acemoglu/">Bugra Acemoglu</a>&#8217;s SwiftMetalNumerics is a new project aimed precisely at this middle ground. It tries to wrap Metal / MPS / MPSGraph and Accelerate / LAPACK on Apple Silicon behind Swift APIs, bringing matrix computation, FFT/STFT, convolution, and basic neural network layers into a unified numerical computing interface. What makes it interesting is not merely &#8220;GPU acceleration,&#8221; but its attempt to take advantage of the unified memory architecture to minimize back-and-forth copying between DSP, matrix computation, and lightweight ML pipelines.</p><blockquote><p>SwiftMetalNumerics is not a full replacement for Accelerate. For small-scale, one-off computations, the CPU path is often still faster. But if your task is a longer real-time signal processing or on-device inference pipeline, SwiftMetalNumerics presents a direction worth watching: connecting low-level mathematical control with GPU computing power in a more Swift-native and Apple Silicon-native way.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-08">SwiftUI Preview Runner: A SwiftUI preview engine for custom tools and AI workflows</a></strong></h3><p>SwiftUI Preview Runner is an inspiring experimental project developed by <a href="https://www.linkedin.com/in/aryan-rogye-1b6a47156/">Aryan Rogye</a>. It does not launch a simulator, nor does it replicate Xcode Preview&#8217;s XPC-based preview mechanism. Instead, it writes a piece of SwiftUI code into a temporary Swift Package, compiles it into a dynamic library, dynamically loads it with dlopen, and renders it inside a host macOS app using NSHostingView.</p><p>As a result, it feels more like a &#8220;SwiftUI Playground&#8221; that can be embedded into custom toolchains: you can connect an editor, AI generation, an MCP validator, or other automation workflows in front of it, allowing generated SwiftUI code to immediately enter a feedback loop of &#8220;can it compile, and can it render?&#8221;</p><blockquote><p>Note that the project targets macOS SwiftUI rendering, not the iOS simulator; compilation introduces latency; and dynamically loading code also means the security boundary must be handled with great care. Even so, as an exploration of how AI-generated SwiftUI can receive real runtime feedback, it is worth paying attention to.</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-135?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-135?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>CocoaPods &#27491;&#22312;&#36864;&#22330;&#65292;SwiftPM &#25165;&#21018;&#21040;&#31532;&#20108;&#31456;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-135/">&#32593;&#39029;&#29256;</a></strong></p><p>&#35895;&#27468;&#36817;&#26399;&#23459;&#24067;&#65292;&#20174;&#19979;&#19968;&#20010; Flutter &#31283;&#23450;&#29256; 3.44 &#24320;&#22987;&#65292;Swift Package Manager &#23558;&#22312;&#40664;&#35748;&#36335;&#24452;&#19978;&#21462;&#20195; CocoaPods&#65292;&#25104;&#20026; iOS &#21644; macOS &#24212;&#29992;&#30340;&#40664;&#35748;&#20381;&#36182;&#31649;&#29702;&#22120;&#12290;CocoaPods &#30340; Trunk &#20179;&#24211;&#35745;&#21010;&#20110; 2026 &#24180; 12 &#26376; 2 &#26085;&#27491;&#24335;&#36827;&#20837;&#21482;&#35835;&#29366;&#24577;&#8212;&#8212;&#36825;&#20010;&#26102;&#38388;&#28857;&#25105;&#20204;&#22312; 2024 &#24180;&#30340;&#21608;&#25253;&#20013;&#23601;&#35752;&#35770;&#36807;&#20102;&#65292;&#20294;&#24403; Flutter &#30495;&#27491;&#24320;&#22987;&#22312;&#40664;&#35748;&#36335;&#24452;&#19978;&#29992; SPM &#26367;&#25442; CocoaPods &#26102;&#65292;&#36824;&#26159;&#24341;&#21457;&#20102;&#31038;&#21306;&#30340;&#24191;&#27867;&#28909;&#35758;&#12290;</p><p>&#19981;&#23569;&#38271;&#26399;&#21463;&#21046;&#20110; CocoaPods &#30340;&#24320;&#21457;&#32773;&#65292;&#23588;&#20854;&#26159;&#21069;&#31471;&#32972;&#26223;&#30340;&#24320;&#21457;&#32773;&#65292;&#23545;&#27492;&#34920;&#36798;&#20102;&#26497;&#22823;&#30340;&#21916;&#24742;&#12290;&#27605;&#31455;&#65292;&#20182;&#20204;&#32456;&#20110;&#21487;&#20197;&#23569;&#22312; M &#31995;&#21015; Mac &#19978;&#25240;&#33150; <code>gem install</code>&#65292;&#20063;&#19981;&#29992;&#20877;&#38754;&#23545;&#37027;&#20123;&#26469;&#36335;&#19981;&#26126;&#12289;&#21364;&#21448;&#24635;&#33021;&#31934;&#20934;&#21345;&#20303;&#26500;&#24314;&#27969;&#31243;&#30340; Pods &#25253;&#38169;&#20102;&#12290;&#36825;&#22330;&#26356;&#26032;&#29978;&#33267;&#19968;&#24230;&#28436;&#21464;&#25104;&#20102;&#19968;&#22330;&#8220;&#25670;&#33073; Ruby &#30340;&#29378;&#27426;&#8221;&#12290;&#19981;&#36807;&#65292;&#30001;&#20110; Flutter &#36825;&#27425;&#23448;&#26041;&#20999;&#25442;&#30053;&#26174;&#31361;&#28982;&#65292;&#19981;&#23569;&#31532;&#19977;&#26041;&#25554;&#20214;&#20316;&#32773;&#20063;&#24863;&#21040;&#20102;&#28966;&#34385;&#65292;&#35201;&#27714;&#36866;&#37197; <code>Package.swift</code> &#30340; Issue &#36805;&#36895;&#28044;&#20837;&#20102;&#19981;&#23569;&#24320;&#28304;&#24211;&#12290;</p><p>&#30456;&#36739;&#20110;&#25554;&#20214;&#20316;&#32773;&#30340;&#30701;&#26399;&#36866;&#37197;&#21387;&#21147;&#65292;&#26412;&#27425;&#20999;&#25442;&#26356;&#38271;&#26399;&#30340;&#32771;&#39564;&#20854;&#23454;&#22312;&#20225;&#19994;&#32423;&#39033;&#30446;&#30340; CI/CD &#37325;&#26500;&#19978;&#12290;&#23545;&#20110;&#37027;&#20123;&#24213;&#23618;&#20173;&#24102;&#26377;&#22823;&#37327; CocoaPods &#21382;&#21490;&#20381;&#36182;&#30340;&#22242;&#38431;&#26469;&#35828;&#65292;&#22914;&#20309;&#24179;&#28369;&#12289;&#23613;&#21487;&#33021;&#20302;&#30171;&#22320;&#20999;&#25442;&#21040; SPM&#65292;&#23558;&#25104;&#20026;&#22522;&#24314;&#23618;&#38754;&#30340;&#19968;&#39033;&#37325;&#22823;&#25361;&#25112;&#12290;&#36801;&#31227;&#24182;&#19981;&#26159;&#21482;&#22312;&#26412;&#22320;&#22810;&#20889;&#19968;&#20010; <code>Package.swift</code>&#65292;&#32780;&#26159;&#24847;&#21619;&#30528;&#26500;&#24314;&#32531;&#23384;&#12289;&#31169;&#26377;&#20381;&#36182;&#12289;&#20108;&#36827;&#21046;&#26694;&#26550;&#12289;Xcode &#24037;&#31243;&#29983;&#25104;&#12289;&#38745;&#24577;/&#21160;&#24577;&#38142;&#25509;&#31574;&#30053;&#20197;&#21450;&#22810;&#24179;&#21488;&#26500;&#24314;&#33050;&#26412;&#37117;&#35201;&#36319;&#30528;&#37325;&#26032;&#26657;&#20934;&#12290;</p><p>&#19981;&#20165;&#26159; Flutter&#65292;&#32771;&#34385;&#21040; CocoaPods &#26366;&#38271;&#26399;&#20805;&#24403;&#36328;&#31471;&#26694;&#26550;&#19982; iOS &#21407;&#29983;&#29983;&#24577;&#20043;&#38388;&#30340;&#8220;&#19975;&#33021;&#33014;&#27700;&#8221;&#65292;React Native&#12289;KMP &#31561;&#31038;&#21306;&#20063;&#24050;&#32463;&#24320;&#22987;&#38138;&#35774;&#21521; SPM &#36801;&#31227;&#30340;&#36335;&#24452;&#65292;Unity &#30456;&#20851;&#30340; iOS &#20381;&#36182;&#35299;&#26512;&#38142;&#36335;&#20063;&#24320;&#22987;&#25903;&#25345; SPM&#12290;&#25509;&#19979;&#26469;&#19968;&#27573;&#26102;&#38388;&#65292;&#22260;&#32469; Apple &#24179;&#21488;&#26500;&#24314;&#38142;&#36335;&#30340;&#36328;&#31471;&#31038;&#21306;&#65292;&#22823;&#27010;&#29575;&#20250;&#32463;&#21382;&#19968;&#22330;&#38453;&#30171;&#24335;&#30340;&#8220;&#22823;&#36801;&#24473;&#8221;&#12290;&#21487;&#20197;&#35828;&#65292;&#21040; 2027 &#24180;&#65292;SPM &#36825;&#20010;&#24050;&#32463;&#38754;&#19990;&#21313;&#24180;&#30340;&#24037;&#20855;&#65292;&#23558;&#22823;&#27010;&#29575;&#23436;&#25104;&#23545; Apple &#24179;&#21488;&#20027;&#27969;&#20381;&#36182;&#31649;&#29702;&#36335;&#24452;&#30340;&#8220;&#22823;&#19968;&#32479;&#8221;&#12290;</p><p>&#23545;&#20110; SPM &#32780;&#35328;&#65292;&#36825;&#26080;&#30097;&#26159;&#19968;&#20010;&#24040;&#22823;&#30340;&#32988;&#21033;&#12290;&#20294;&#25105;&#20204;&#20063;&#24517;&#39035;&#30475;&#28165;&#65292;&#36825;&#24182;&#19981;&#20195;&#34920; SPM &#24050;&#32463;&#23454;&#29616;&#20102;&#30495;&#27491;&#24847;&#20041;&#19978;&#30340;&#8220;&#30772;&#22280;&#8221;&#12290;&#23427;&#26356;&#20687;&#26159;&#33529;&#26524;&#21407;&#29983;&#29983;&#24577;&#30340;&#19968;&#22330;&#8220;&#20869;&#21367;&#24335;&#32988;&#21033;&#8221;&#65306;&#29992;&#19968;&#22871;&#23545; Swift &#25903;&#25345;&#26356;&#23436;&#25972;&#12289;&#19982; Xcode &#38598;&#25104;&#26356;&#32039;&#23494;&#30340;&#29616;&#20195;&#24037;&#20855;&#65292;&#26367;&#25442;&#25481;&#20102;&#23646;&#20110; Objective-C &#26102;&#20195;&#30340;&#26087;&#26377;&#26041;&#26696;&#12290;&#21482;&#35201;&#36824;&#24819;&#22312; Apple &#24179;&#21488;&#19978;&#31283;&#23450;&#20132;&#20184;&#65292;&#36328;&#24179;&#21488;&#26694;&#26550;&#26368;&#32456;&#37117;&#24456;&#38590;&#32469;&#24320;&#33529;&#26524;&#30340;&#21407;&#29983;&#35268;&#21017;&#12290;</p><p>&#37027;&#20040;&#65292;SPM &#30340;&#19979;&#19968;&#20010;&#21313;&#24180;&#20250;&#36208;&#21521;&#21738;&#37324;&#65311;&#26159;&#32487;&#32493;&#20570;&#33529;&#26524;&#29983;&#24577;&#30340;&#8220;&#20869;&#37096;&#26368;&#20248;&#35299;&#8221;&#65292;&#36824;&#26159;&#30495;&#27491;&#36208;&#20986;&#22260;&#22681;&#65292;&#21644; Cargo&#12289;npm &#36825;&#26679;&#30340;&#24037;&#20855;&#31449;&#21040;&#21516;&#19968;&#20010;&#31454;&#20105;&#33310;&#21488;&#19978;&#65311;&#31572;&#26696;&#24656;&#24597;&#24182;&#19981;&#22312; SPM &#33258;&#36523;&#65292;&#32780;&#22312; Swift &#35821;&#35328;&#33021;&#19981;&#33021;&#22312; Linux&#12289;Android&#12289;&#23884;&#20837;&#24335;&#31561;&#22330;&#26223;&#37324;&#36305;&#20986;&#30495;&#27491;&#30340;&#26432;&#25163;&#32423;&#29992;&#20363;&#12290;</p><p>&#22312;&#37027;&#19968;&#22825;&#21040;&#26469;&#20043;&#21069;&#65292;&#25105;&#20204;&#33021;&#30830;&#23450;&#30340;&#21482;&#26377;&#19968;&#20214;&#20107;&#65306;CocoaPods &#30340;&#36864;&#22330;&#24050;&#32463;&#19981;&#21487;&#36870;&#65292;&#20294; SwiftPM &#30340;&#25925;&#20107;&#65292;&#25165;&#21018;&#21018;&#32763;&#21040;&#31532;&#20108;&#31456;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-134/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0135-01">&#35686;&#24789; AI &#32534;&#31243;&#26102;&#20195;&#30340;&#8220;&#27973;&#23618;&#24605;&#32771;&#8221; (Deep Understanding while using LLMs)</a></strong></h3><p><a href="https://m.objc.io/@chris">Chris Eidhof</a> &#20250;&#22312;&#20854; SwiftUI workshop &#24320;&#22987;&#26102;&#21578;&#30693;&#23398;&#21592;&#65292;&#32451;&#20064;&#26399;&#38388;&#35831;&#26242;&#26102;&#25918;&#19979; LLM&#12290;&#21407;&#22240;&#24182;&#19981;&#26159;&#20182;&#21453;&#23545; AI&#65292;&#32780;&#26159;&#36890;&#36807; LLM &#24555;&#36895;&#24471;&#21040;&#31572;&#26696;&#65292;&#24182;&#19981;&#31561;&#20110;&#30495;&#27491;&#29702;&#35299;&#38382;&#39064;&#12290;&#36825;&#31687;&#25991;&#31456;&#35752;&#35770;&#30340;&#26680;&#24515;&#65292;&#26159;&#24403;&#21069; AI &#32534;&#31243;&#26102;&#20195;&#19968;&#20010;&#36234;&#26469;&#36234;&#26126;&#26174;&#30340;&#29616;&#35937;&#65306;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#24320;&#22987;&#38519;&#20837;&#8220;&#27973;&#23618;&#24605;&#32771;&#8221;&#12290;&#19981;&#26029; prompt&#12289;&#19981;&#26029;&#20462;&#34917;&#12289;&#19981;&#26029;&#25512;&#36827;&#21151;&#33021;&#65292;&#21364;&#22312;&#19981;&#30693;&#19981;&#35273;&#20013;&#22833;&#21435;&#23545;&#31995;&#32479;&#26412;&#36523;&#30340;&#30495;&#23454;&#29702;&#35299;&#12290;&#19968;&#26086;&#39033;&#30446;&#22797;&#26434;&#24230;&#19978;&#21319;&#65292;&#38382;&#39064;&#20415;&#24320;&#22987;&#22833;&#25511;&#12290;</p><p>&#26412;&#25991;&#30340;&#21103;&#26631;&#39064; &#8220;Solve It in 20 Minutes &#8212; Or Actually Understand It&#8221;&#65292;&#19981;&#21482;&#26159;&#23545; workshop &#22330;&#26223;&#30340;&#25551;&#36848;&#65292;&#20063;&#20687;&#26159; AI &#32534;&#31243;&#26102;&#20195;&#25670;&#22312;&#24320;&#21457;&#32773;&#38754;&#21069;&#30340;&#19968;&#36947;&#36873;&#25321;&#39064;&#12290;LLM &#24182;&#19981;&#20250;&#26367;&#20195;&#24037;&#31243;&#33021;&#21147;&#65292;&#23427;&#21482;&#20250;&#25918;&#22823;&#24320;&#21457;&#32773;&#24050;&#26377;&#30340;&#29702;&#35299;&#19982;&#21028;&#26029;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-02">&#24039;&#29992; npm &#20840;&#23616;&#23433;&#35013; Swift &#33050;&#26412; (Installing Swift scripts as global commands with npm)</a></strong></h3><p>&#36234;&#26469;&#36234;&#22810; Swift &#24320;&#21457;&#32773;&#24320;&#22987;&#29992; Swift &#32534;&#20889; CLI &#24037;&#20855;&#12290;&#20294;&#22312;&#24320;&#21457;&#36807;&#31243;&#20013;&#65292;&#27599;&#27425;&#20462;&#25913;&#21518;&#37117;&#38656;&#35201;&#37325;&#26032;&#32534;&#35793;&#12289;&#25163;&#21160;&#31227;&#21160; binary&#65292;&#25110;&#32500;&#25252; shell alias&#65292;&#24456;&#23481;&#26131;&#25171;&#26029;&#36845;&#20195;&#33410;&#22863;&#12290;<a href="https://www.linkedin.com/in/crisfeim/">Cristian Felipe Pati&#241;o Rojas</a> &#32473;&#20986;&#20102;&#19968;&#20010;&#24456;&#26377;&#21019;&#24847;&#30340;&#35299;&#20915;&#26041;&#26696;&#65306;&#20511;&#21161; npm &#30340; <code>bin</code> &#26426;&#21046;&#65292;&#23558;&#24102;&#26377; shebang &#30340; Swift &#33050;&#26412;&#27880;&#20876;&#20026;&#20840;&#23616;&#21629;&#20196;&#12290;&#36825;&#26679;&#19968;&#26469;&#65292;Swift &#33050;&#26412;&#21487;&#20197;&#20687;&#26222;&#36890; CLI &#24037;&#20855;&#19968;&#26679;&#30452;&#25509;&#35843;&#29992;&#65292;&#32780; npm &#21482;&#36127;&#36131;&#21019;&#24314;&#20840;&#23616;&#36719;&#38142;&#25509;&#65292;&#24182;&#19981;&#21442;&#19982; Swift &#20195;&#30721;&#30340;&#26500;&#24314;&#36807;&#31243;&#12290;</p><blockquote><p>&#32771;&#34385;&#21040;&#36890;&#36807; <code>swift</code> &#21551;&#21160;&#33050;&#26412;&#30340;&#20919;&#21551;&#21160;&#24320;&#38144;&#24182;&#19981;&#23567;&#65292;&#36890;&#24120;&#21487;&#33021;&#38656;&#35201;&#25968;&#31186;&#65292;&#35813;&#26041;&#26696;&#26356;&#36866;&#21512;&#29992;&#20110; Swift CLI &#30340;&#24320;&#21457;&#38454;&#27573;&#12290;&#23545;&#20110;&#36825;&#31867;&#23567;&#24037;&#20855;&#65292;&#24320;&#21457;&#32773;&#24182;&#19981;&#19968;&#23450;&#35201;&#19968;&#24320;&#22987;&#23601;&#20570;&#25104;&#23436;&#25972; Swift Package&#12290;&#20808;&#29992;&#26368;&#36731;&#30340;&#26041;&#24335;&#36305;&#36215;&#26469;&#65292;&#31561;&#24037;&#20855;&#31283;&#23450;&#21518;&#20877;&#32534;&#35793;&#21644;&#20998;&#21457;&#65292;&#24448;&#24448;&#26356;&#21152;&#31526;&#21512;&#23454;&#38469;&#24037;&#20316;&#27969;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-03">&#24323;&#29992; WatchConnectivity&#65306;&#25171;&#36896;&#39640;&#21487;&#38752;&#30340; Watch &#36890;&#20449;&#26041;&#26696; (WatchConnectivity was failing 40% of the time. So I stopped using it.)</a></strong></h3><p>&#22312;&#20026; Apple Watch app &#26500;&#24314;&#23454;&#26102;&#36890;&#20449;&#33021;&#21147;&#26102;&#65292;<a href="https://www.linkedin.com/in/tarek-sabry-846514147/">Tarek Sabry</a> &#36935;&#21040;&#20102;&#19968;&#20010;&#24456;&#20196;&#20154;&#22836;&#30140;&#30340;&#38382;&#39064;&#65306;&#23448;&#26041;&#30340; WatchConnectivity &#24182;&#19981;&#31283;&#23450;&#65292;&#36830;&#25509;&#25104;&#21151;&#29575;&#21482;&#26377;&#32422; 60%&#12290;&#26368;&#32456;&#65292;Tarek &#36873;&#25321;&#19981;&#20877;&#25226; WatchConnectivity &#20316;&#20026;&#21807;&#19968;&#21487;&#38752;&#36890;&#36947;&#65292;&#32780;&#26159;&#24341;&#20837;&#19968;&#22871;&#24182;&#34892;&#30340;&#32593;&#32476;&#20256;&#36755;&#36335;&#24452;&#65306;&#29992; BLE &#20570;&#26381;&#21153;&#21457;&#29616;&#12289;HTTP &#20570;&#25968;&#25454;&#20256;&#36755;&#12289;SSE &#24314;&#31435;&#25512;&#36865;&#36890;&#36947;&#65292;&#20877;&#37197;&#21512; frame ID&#12289;ack &#30830;&#35748;&#12289;&#21435;&#37325;&#21644;&#37325;&#20256;&#26426;&#21046;&#12290;&#25104;&#21151;&#22320;&#23558;&#36830;&#25509;&#25104;&#21151;&#29575;&#20174; 60% &#25552;&#21319;&#21040; 99%&#65292;&#25928;&#26524;&#20960;&#20046;&#26159;&#31435;&#31487;&#35265;&#24433;&#12290;</p><p>&#26356;&#26377;&#24847;&#24605;&#30340;&#26159;&#36825;&#20010;&#26041;&#26696;&#30340;&#21103;&#20135;&#21697;&#65306;&#30001;&#20110;&#23436;&#20840;&#22522;&#20110;&#26631;&#20934;&#32593;&#32476;&#21327;&#35758;&#65292;Watch &#24182;&#19981;&#30693;&#36947;&#21478;&#19968;&#31471;&#26159; iPhone&#12289;Android &#25163;&#26426;&#65292;&#36824;&#26159;&#20219;&#24847;&#24102; IP &#22320;&#22336;&#30340;&#35774;&#22791;&#12290;&#25454;&#20316;&#32773;&#31216;&#65292;&#25130;&#33267; 2026 &#24180; 4 &#26376;&#65292;&#36825;&#26159;&#20844;&#24320;&#21487;&#29992;&#30340;&#21807;&#19968;&#19968;&#20010; Android &#8596; Apple Watch &#36890;&#20449;&#35299;&#20915;&#26041;&#26696;&#12290;&#35813;&#26041;&#26696;&#24050;&#24320;&#28304;&#65292;&#21629;&#21517;&#20026; <a href="https://github.com/tareksabry1337/WatchLink">WatchLink</a>&#65292;&#25903;&#25345; Swift 6&#65292;&#26080;&#31532;&#19977;&#26041;&#20381;&#36182;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-04">SwiftUI &#31163;&#26497;&#33268;&#21407;&#29983;&#30340; Mac &#24212;&#29992;&#36824;&#26377;&#22810;&#36828;&#65311; (Using SwiftUI to Build a Mac-assed App in 2026)</a></strong></h3><p>&#8220;Mac-assed app&#8221; &#19968;&#35789;&#25551;&#36848;&#30340;&#26159;&#37027;&#31181;&#30495;&#27491;&#23646;&#20110; Mac &#30340;&#36719;&#20214;&#65306;&#20351;&#29992;&#31995;&#32479;&#21407;&#29983;&#25511;&#20214;&#12289;&#28145;&#24230;&#38598;&#25104;&#31995;&#32479;&#21151;&#33021;&#65292;&#27599;&#19968;&#20010;&#20132;&#20114;&#32454;&#33410;&#37117;&#31526;&#21512;&#24179;&#21488;&#24815;&#20363;&#12290;<a href="https://x.com/pfandrade_">Paulo Andrade</a> &#22312;&#20351;&#29992;&#32431; SwiftUI &#24320;&#21457; macOS &#24212;&#29992;&#26102;&#21457;&#29616;&#65292;&#23613;&#31649; SwiftUI &#25552;&#20379;&#20102;&#36275;&#20197;&#35206;&#30422;&#31616;&#21333;&#22330;&#26223;&#30340; API&#65292;&#20294;&#24403;&#24320;&#21457;&#32773;&#35797;&#22270;&#36824;&#21407; Mac &#24212;&#29992;&#20960;&#21313;&#24180;&#31215;&#32047;&#19979;&#26469;&#30340;&#20132;&#20114;&#24815;&#20363;&#26102;&#65292;&#26694;&#26550;&#26412;&#36523;&#21453;&#32780;&#24120;&#24120;&#25104;&#20102;&#38459;&#30861;&#12290;</p><p>&#25991;&#31456;&#25286;&#35299;&#20102;&#24403;&#21069; SwiftUI &#22312; macOS &#19978;&#30340;&#20960;&#20010;&#26126;&#26174;&#30701;&#26495;&#65306;&#33258;&#23450;&#20041;&#21015;&#34920;&#38590;&#20197;&#23436;&#25972;&#36824;&#21407;&#36873;&#20013;&#12289;&#22833;&#28966;&#19982;&#21491;&#38190;&#19978;&#19979;&#25991;&#30446;&#26631;&#20043;&#38388;&#30340;&#32454;&#24494;&#29366;&#24577;&#24046;&#24322;&#65307;&#21491;&#38190;&#33756;&#21333;&#25171;&#24320;&#26102;&#26080;&#27861;&#24863;&#30693;&#65292;&#23548;&#33268;&#24320;&#21457;&#32773;&#38590;&#20197;&#27491;&#30830;&#39640;&#20142;&#33756;&#21333;&#20316;&#29992;&#23545;&#35937;&#65307;&#25302;&#25341;&#36807;&#31243;&#20013;&#30340;&#29366;&#24577;&#21487;&#35265;&#24615;&#20960;&#20046;&#20026;&#38646;&#65307;&#38190;&#30424;&#23548;&#33322;&#22312; <code>TextField</code> &#33719;&#28966;&#21518;&#24456;&#23481;&#26131;&#34987;&#8220;&#21534;&#25481;&#8221;&#65307;&#24037;&#20855;&#26639;&#30340;&#24067;&#23616;&#25511;&#21046;&#33021;&#21147;&#20063;&#36828;&#19981;&#21450; AppKit &#31934;&#32454;&#12290;Paulo &#35748;&#20026;&#65292;SwiftUI &#20173;&#26410;&#23436;&#25104;&#23545; AppKit &#30340;&#20132;&#25509;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-05">SwiftUI &#21518;&#21488;&#24212;&#29992;&#21047;&#26032;&#30340;&#35843;&#24230;&#19982;&#22788;&#29702;&#25351;&#21335; (Scheduling and handling background app refresh in SwiftUI)</a></strong></h3><p>iOS &#20013;&#30340;&#21518;&#21488;&#21047;&#26032;&#21151;&#33021;&#30475;&#20284; API &#31616;&#21333;&#65292;&#20294;&#23454;&#38469;&#24456;&#23481;&#26131;&#36393;&#22353;&#12290;<a href="https://x.com/natpanferova">Natalia Panferova</a> &#22312;&#26412;&#25991;&#20013;&#28436;&#31034;&#20102;&#22914;&#20309;&#22312; SwiftUI App &#29983;&#21629;&#21608;&#26399;&#19979;&#20351;&#29992; Background Tasks framework &#37197;&#32622; <code>BGAppRefreshTaskRequest</code>&#65292;&#24182;&#36890;&#36807; <code>backgroundTask(_:action:)</code> scene modifier &#27880;&#20876;&#22788;&#29702;&#36923;&#36753;&#12290;&#25991;&#31456;&#20174;&#21551;&#29992; Background Modes&#12289;&#22312; Info.plist &#20013;&#30331;&#35760; task identifier&#65292;&#21040;&#25552;&#20132;&#21518;&#21488;&#21047;&#26032;&#35831;&#27714;&#21644;&#22788;&#29702;&#31995;&#32479;&#21796;&#37266;&#65292;&#23436;&#25972;&#20018;&#36215;&#20102; SwiftUI &#24212;&#29992;&#25509;&#20837;&#21518;&#21488;&#21047;&#26032;&#30340;&#22522;&#26412;&#27969;&#31243;&#12290;&#20316;&#32773;&#36824;&#20171;&#32461;&#20102;&#22914;&#20309;&#36890;&#36807; Xcode &#35843;&#35797;&#22120;&#21629;&#20196;&#22312;&#30495;&#26426;&#19978;&#27169;&#25311;&#21518;&#21488;&#20219;&#21153;&#35302;&#21457;&#65292;&#20415;&#20110;&#24320;&#21457;&#38454;&#27573;&#39564;&#35777;&#36923;&#36753;&#12290;</p><blockquote><p>&#20540;&#24471;&#27880;&#24847;&#30340;&#26159;&#65292;&#21518;&#21488;&#21047;&#26032;&#24182;&#19981;&#26159;&#19968;&#20010;&#21487;&#31934;&#30830;&#35843;&#24230;&#30340;&#23450;&#26102;&#22120;&#12290;&#21363;&#20351;&#35774;&#32622;&#20102; <code>earliestBeginDate</code>&#65292;&#31995;&#32479;&#20063;&#20250;&#26681;&#25454;&#30005;&#37327;&#12289;&#29992;&#25143;&#20351;&#29992;&#20064;&#24815;&#31561;&#22240;&#32032;&#33258;&#34892;&#20915;&#23450;&#26159;&#21542;&#20197;&#21450;&#20309;&#26102;&#21796;&#37266;&#24212;&#29992;&#65292;&#22240;&#27492;&#20851;&#38190;&#36923;&#36753;&#19981;&#24212;&#20381;&#36182;&#23427;&#20934;&#26102;&#25191;&#34892;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-06">Swift 6 &#24182;&#21457;&#36816;&#34892;&#26102;&#23849;&#28291;&#36991;&#22353;&#25351;&#21335; (How to avoid Swift 6 concurrency crashes)</a></strong></h3><p>Swift 6 &#20005;&#26684;&#24182;&#21457;&#27169;&#24335;&#19979;&#21363;&#20415;&#32534;&#35793;&#26399;&#38646;&#35686;&#21578;&#65292;&#20063;&#24182;&#19981;&#31561;&#20110;&#36816;&#34892;&#26399;&#23433;&#20840;&#12290;&#32534;&#35793;&#22120;&#20250;&#22312; actor &#36793;&#30028;&#21644; GCD &#36793;&#30028;&#27880;&#20837;&#21160;&#24577;&#38548;&#31163;&#26029;&#35328;&#65292;&#19968;&#26086;&#25191;&#34892;&#36335;&#24452;&#19982;&#32534;&#35793;&#22120;&#30340;&#20551;&#35774;&#19981;&#31526;&#65292;&#20173;&#21487;&#33021;&#22312;&#29983;&#20135;&#29615;&#22659;&#20013;&#35302;&#21457; <code>_dispatch_assert_queue_fail</code> &#25110; <code>_swift_task_checkIsolatedSwift</code> &#23849;&#28291;&#12290;</p><p><a href="https://x.com/onmyway133">Khoa</a> &#21015;&#20030;&#20102;&#20960;&#31867;&#24120;&#35265;&#35302;&#21457;&#22330;&#26223;&#65306;<code>@MainActor</code> &#19978;&#19979;&#25991;&#20013;&#23450;&#20041;&#30340;&#38381;&#21253;&#20250;&#32487;&#25215;&#20027; actor &#38548;&#31163;&#65292;&#33509;&#38543;&#21518;&#34987;&#26087;&#24335; callback &#25110; queue API &#22312;&#21518;&#21488;&#32447;&#31243;&#35843;&#29992;&#65292;&#20415;&#21487;&#33021;&#35302;&#21457;&#23849;&#28291;&#65307;Combine pipeline &#20013; <code>receive(on:)</code> &#30340;&#20301;&#32622;&#39034;&#24207;&#20250;&#24433;&#21709;&#38381;&#21253;&#30340;&#38548;&#31163;&#32487;&#25215;&#65307;delegate &#26041;&#27861;&#33509;&#22240;&#25972;&#20010;&#31867;&#26631;&#27880;&#20102; <code>@MainActor</code> &#32780;&#32487;&#25215;&#20027; actor &#38548;&#31163;&#65292;&#20294; SDK &#23454;&#38469;&#20174;&#20869;&#37096;&#38431;&#21015;&#22238;&#35843;&#65292;&#21516;&#26679;&#20250;&#35302;&#21457;&#36816;&#34892;&#26102;&#26029;&#35328;&#12290;</p><blockquote><p>Khoa &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#30340;&#26041;&#27861;&#65292;&#33021;&#24110;&#21161;&#24320;&#21457;&#32773;&#24555;&#36895;&#23450;&#20301;&#24182;&#20462;&#22797;&#26087;&#39033;&#30446;&#36801;&#31227; Swift 6 &#26102;&#24120;&#35265;&#30340;&#36816;&#34892;&#26102;&#23849;&#28291;&#28857;&#12290;&#19981;&#36807;&#65292;&#22914;&#26524;&#31934;&#21147;&#35768;&#21487;&#65292;&#26356;&#29702;&#24819;&#30340;&#26041;&#21521;&#20173;&#28982;&#26159;&#25353;&#29031; Swift 6 &#29616;&#20195;&#24182;&#21457;&#30340;&#26500;&#22411;&#37325;&#26032;&#32452;&#32455;&#21151;&#33021;&#20195;&#30721;&#65292;&#26126;&#30830;&#38548;&#31163;&#36793;&#30028;&#65292;&#20943;&#23569;&#23545;&#23616;&#37096;&#26631;&#27880;&#21644;&#34917;&#19969;&#24335;&#20462;&#22797;&#30340;&#20381;&#36182;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0135-07">SwiftMetalNumerics&#65306;&#38754;&#21521; Apple Silicon &#30340; Swift &#21407;&#29983; GPU &#25968;&#20540;&#35745;&#31639;&#24211;</a></strong></h3><p>&#22312; Apple &#24179;&#21488;&#19978;&#20570;&#23454;&#26102;&#38899;&#39057;&#20998;&#26512;&#25110;&#31471;&#20391;&#20449;&#21495;&#24314;&#27169;&#26102;&#65292;&#24320;&#21457;&#32773;&#24120;&#20250;&#21345;&#22312;&#19968;&#20010;&#23604;&#23596;&#20301;&#32622;&#65306;SoundAnalysis&#12289;AVAudioEngine &#36825;&#31867;&#39640;&#23618; API &#36275;&#22815;&#26041;&#20415;&#65292;&#20294;&#24456;&#22810;&#26102;&#20505;&#20687;&#40657;&#31665;&#65292;&#21482;&#32473;&#25972;&#29702;&#22909;&#30340;&#32467;&#26524;&#65307;&#32780;&#24403;&#20320;&#38656;&#35201;&#33258;&#24049;&#25511;&#21046; STFT&#12289;&#39057;&#29575;&#20998;&#26742;&#12289;&#30697;&#38453;&#36816;&#31639;&#65292;&#29978;&#33267;&#25226;&#29305;&#24449;&#32487;&#32493;&#36865;&#20837;&#33258;&#23450;&#20041;&#31070;&#32463;&#32593;&#32476;&#23618;&#26102;&#65292;&#21448;&#24448;&#24448;&#35201;&#22238;&#21040; Accelerate/vDSP &#21644;&#24213;&#23618; Metal &#20043;&#38388;&#26469;&#22238;&#34900;&#25509;&#12290;CPU &#20391;&#35745;&#31639;&#24456;&#24555;&#65292;&#20294;&#19968;&#26086;&#21518;&#32493;&#35745;&#31639;&#36827;&#20837; GPU &#31649;&#32447;&#65292;&#25968;&#25454;&#25644;&#36816;&#21644;&#21516;&#27493;&#23601;&#21487;&#33021;&#25104;&#20026;&#23454;&#26102;&#22788;&#29702;&#30340;&#29942;&#39048;&#12290;</p><p><a href="https://www.linkedin.com/in/acemoglu/">Bugra Acemoglu</a> &#24320;&#21457;&#30340; SwiftMetalNumerics &#27491;&#26159;&#30596;&#20934;&#36825;&#20010;&#20013;&#38388;&#22320;&#24102;&#30340;&#19968;&#20010;&#26032;&#39033;&#30446;&#12290;&#23427;&#23581;&#35797;&#29992; Swift API &#23553;&#35013; Apple Silicon &#19978;&#30340; Metal / MPS / MPSGraph &#19982; Accelerate / LAPACK&#65292;&#25226;&#30697;&#38453;&#35745;&#31639;&#12289;FFT/STFT&#12289;&#21367;&#31215;&#21644;&#22522;&#30784;&#31070;&#32463;&#32593;&#32476;&#23618;&#25918;&#36827;&#21516;&#19968;&#22871;&#25968;&#20540;&#35745;&#31639;&#25509;&#21475;&#20013;&#12290;&#23427;&#30495;&#27491;&#26377;&#24847;&#24605;&#30340;&#22320;&#26041;&#19981;&#21482;&#26159;&#8220;GPU &#21152;&#36895;&#8221;&#65292;&#32780;&#26159;&#21033;&#29992;&#32479;&#19968;&#20869;&#23384;&#26550;&#26500;&#65292;&#23613;&#37327;&#20943;&#23569; DSP&#12289;&#30697;&#38453;&#35745;&#31639;&#21644;&#36731;&#37327; ML pipeline &#20043;&#38388;&#30340;&#26469;&#22238;&#25335;&#36125;&#12290;</p><blockquote><p>SwiftMetalNumerics &#24182;&#19981;&#26159; Accelerate &#30340;&#20840;&#38754;&#26367;&#20195;&#21697;&#12290;&#23567;&#35268;&#27169;&#12289;&#21333;&#27425;&#35745;&#31639;&#65292;CPU &#36335;&#24452;&#24448;&#24448;&#20173;&#28982;&#26356;&#24555;&#65307;&#20294;&#22914;&#26524;&#20320;&#30340;&#20219;&#21153;&#26159;&#19968;&#26465;&#36739;&#38271;&#30340;&#23454;&#26102;&#20449;&#21495;&#22788;&#29702;&#25110;&#31471;&#20391;&#25512;&#29702;&#31649;&#32447;&#65292;SwiftMetalNumerics &#23637;&#31034;&#20102;&#19968;&#20010;&#20540;&#24471;&#20851;&#27880;&#30340;&#26041;&#21521;&#65306;&#29992;&#26356; Swift&#12289;&#26356; Apple Silicon-native &#30340;&#26041;&#24335;&#65292;&#25226;&#21407;&#22987;&#25968;&#23398;&#25511;&#21046;&#26435;&#21644; GPU &#35745;&#31639;&#33021;&#21147;&#36830;&#25509;&#36215;&#26469;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0135-08">SwiftUI Preview Runner&#65306;&#38754;&#21521;&#33258;&#23450;&#20041;&#24037;&#20855;&#19982; AI &#24037;&#20316;&#27969;&#30340; SwiftUI &#39044;&#35272;&#24341;&#25806;</a></strong></h3><p>SwiftUI Preview Runner &#26159;&#19968;&#20010;&#24456;&#26377;&#21551;&#21457;&#24615;&#30340;&#23454;&#39564;&#39033;&#30446;&#65292;&#30001; <a href="https://www.linkedin.com/in/aryan-rogye-1b6a47156/">Aryan Rogye</a> &#24320;&#21457;&#12290;&#23427;&#24182;&#19981;&#26159;&#35843;&#29992;&#27169;&#25311;&#22120;&#65292;&#20063;&#19981;&#26159;&#22797;&#21051; Xcode Preview &#30340; XPC &#39044;&#35272;&#26426;&#21046;&#65292;&#32780;&#26159;&#25226;&#19968;&#27573; SwiftUI &#20195;&#30721;&#20889;&#20837;&#20020;&#26102; Swift Package&#65292;&#32534;&#35793;&#25104;&#21160;&#24577;&#24211;&#65292;&#20877;&#36890;&#36807; dlopen &#21160;&#24577;&#21152;&#36733;&#65292;&#24182;&#22312;&#23487;&#20027; macOS App &#20013;&#29992; NSHostingView &#28210;&#26579;&#20986;&#26469;&#12290;</p><p>&#22240;&#27492;&#65292;&#23427;&#26356;&#20687;&#26159;&#19968;&#20010;&#21487;&#23884;&#20837;&#33258;&#26377;&#24037;&#20855;&#38142;&#30340;&#8220;SwiftUI Playground&#8221;&#65306;&#20320;&#21487;&#20197;&#25226;&#32534;&#36753;&#22120;&#12289;AI &#29983;&#25104;&#12289;MCP validator &#25110;&#20854;&#20182;&#33258;&#21160;&#21270;&#27969;&#31243;&#25509;&#21040;&#23427;&#21069;&#38754;&#65292;&#35753;&#29983;&#25104;&#20986;&#26469;&#30340; SwiftUI &#20195;&#30721;&#31435;&#21363;&#36827;&#20837;&#8220;&#33021;&#21542;&#32534;&#35793;&#12289;&#33021;&#21542;&#28210;&#26579;&#8221;&#30340;&#21453;&#39304;&#29615;&#12290;</p><blockquote><p>&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65306;&#35813;&#39033;&#30446;&#30340;&#28210;&#26579;&#30446;&#26631;&#26159; macOS SwiftUI&#65292;&#19981;&#26159; iOS &#27169;&#25311;&#22120;&#65307;&#32534;&#35793;&#20250;&#24102;&#26469;&#24310;&#36831;&#65307;&#21160;&#24577;&#21152;&#36733;&#20195;&#30721;&#20063;&#24847;&#21619;&#30528;&#23433;&#20840;&#36793;&#30028;&#24517;&#39035;&#38750;&#24120;&#35880;&#24910;&#12290;&#23613;&#31649;&#22914;&#27492;&#65292;&#20316;&#20026;&#8220;&#22914;&#20309;&#35753; AI &#29983;&#25104;&#30340; SwiftUI &#33719;&#24471;&#30495;&#23454;&#36816;&#34892;&#21453;&#39304;&#8221;&#30340;&#25506;&#32034;&#26679;&#26412;&#65292;&#23427;&#20540;&#24471;&#20851;&#27880;&#12290;</p></blockquote>]]></content:encoded></item></channel></rss>