<?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>Sun, 14 Jun 2026 02:09:20 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 #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"><svg role="img" 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"><g><title></title><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"><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"><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"><svg role="img" 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"><g><title></title><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"><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"><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"><svg role="img" 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"><g><title></title><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"><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"><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"><svg role="img" 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"><g><title></title><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"><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"><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"><svg role="img" 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"><g><title></title><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"><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"><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><item><title><![CDATA[Fatbobman's Swift Weekly #134]]></title><description><![CDATA[Getting AI from Handy to Heartfelt]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-134</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-134</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 04 May 2026 12:03:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yyGg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.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_!yyGg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yyGg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 424w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 848w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 1272w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yyGg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp" width="1400" height="747" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:747,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:96714,&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/196298775?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.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_!yyGg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 424w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 848w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.webp 1272w, https://substackcdn.com/image/fetch/$s_!yyGg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b015777-fd68-4cbd-be19-94adaf0d1be8_1400x747.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"><svg role="img" 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"><g><title></title><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"><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"><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/@countchris?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Count Chris</a> on <a href="https://unsplash.com/photos/red-and-yellow-smiley-balloon-hQNFPZK8F80?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Getting AI from Handy to Heartfelt</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-134/">Read on web &#8594;</a></p><p>It&#8217;s been three years since I started using AI tools in earnest. Over these three years, I&#8217;ve witnessed AI&#8217;s remarkable leaps in capability &#8212; and grown increasingly aware of its limits. By now, AI has firmly established itself as an excellent productivity tool. Yet getting it to produce code that truly feels &#8220;heartfelt&#8221; &#8212; code that aligns with my personal style, ideas, and design philosophy &#8212; remains a considerable challenge.</p><p>Even though mainstream models now routinely offer 1M-token context windows, the information they can carry still falls far short of a human developer&#8217;s holistic grasp of a project as it grows. Compounded by attention decay, the truly usable context is actually quite limited. This is why, over the past stretch of time, I&#8217;ve published fewer technical articles written for human readers &#8212; and produced quite a lot of documentation written for AI instead. Readers often write to ask why my blog has slowed down; this is the reason.</p><p>The point of writing all this dedicated documentation isn&#8217;t merely to give AI enough context to work with. More importantly, I&#8217;m exploring a SwiftUI state pattern of my own design &#8212; one that diverges significantly from the prevailing paradigm. This means AI&#8217;s vast trove of pretraining data often becomes noise, even active resistance: it keeps unconsciously pulling you back toward the most common conventions. The whole process therefore takes on a kind of tug-of-war rhythm. I use AI to validate ideas rapidly, turning vague intuitions into precise contracts and interfaces; in parallel, I keep refining the documentation, which in turn constrains the AI and steers it toward code that matches my intent.</p><p>There&#8217;s still some distance to the finish line, but as the code, structure, and documentation iterate together &#8212; and especially as my half-formed ideas gradually crystallize and land &#8212; I can feel a clear shift: the AI is becoming noticeably more fluent within this project, and its output is converging on what I have in mind.</p><p>There are countless ways to arrive at the same UI outcome. What I want is to use various constraints to make AI choose the specific path I&#8217;ve laid out. I&#8217;m not claiming my own code is flawless &#8212; only that I want AI&#8217;s output to feel familiar and within my grasp, so I can step in and maintain it without friction.</p><p>With clear goals and thorough guidance, AI now implements things tens or even hundreds of times faster than I can. When &#8220;efficiency&#8221; is no longer the bottleneck, the real question for the next stage is how to make this lightning-fast assistant more <em>heartfelt</em> &#8212; more in tune with us.</p><p><a href="https://fatbobman.com/en/weekly/issue-133/">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/w0134-01">Q&amp;A: Swift Concurrency - Formatted</a></strong></h3><p>This is a transcript of a <a href="https://www.youtube.com/live/E95agtPgaa0">Swift Concurrency Q&amp;A</a> with Apple engineers, compiled by <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a>. In the session, the engineers addressed many of the most commonly misunderstood aspects of Swift&#8217;s current concurrency model: from the behavior change behind <code>nonisolated(nonsending)</code>, to the boundaries of <code>@concurrent</code>, to Task lifetime and cancellation. Rather than merely adding more knowledge, this feels more like a &#8220;semantic recalibration.&#8221;</p><blockquote><p>One noteworthy signal is that Swift is moving from &#8220;async implies concurrency by default&#8221; toward a more conservative default, where concurrency is introduced explicitly only when needed.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-02">Immediate tasks in Swift Concurrency explained</a></strong></h3><p>Swift 6.2 introduced a subtle but useful new feature: <code>Task.immediate</code>. Unlike a regular <code>Task</code>, an immediate task starts synchronously in the current execution context and continues running until the first actual suspension point. <a href="https://x.com/twannl">Antoine van der Lee</a> offers a clear explanation of its behavior in this article.</p><p>This capability mainly fills a long-standing gap: calling async logic from a synchronous context while still preserving execution order, such as immediately updating state when the actor isolation is already correct. In these scenarios, <code>Task.immediate</code> can avoid the timing mismatch caused by scheduling delay.</p><blockquote><p>Its risk is just as direct: if heavy synchronous work runs before the first suspension point, especially on the MainActor, it can block the current executor and cause visible UI hitches. <code>Task.immediate</code> only changes when a task starts executing, not the task&#8217;s overall lifecycle. In most cases, the regular Task scheduling behavior remains the safer choice.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-03">Concurrency Step-by-Step: Designing Protocols</a></strong></h3><p>In this article, <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> shares a more practically executable approach to protocol design in the context of Swift 6 strict concurrency.</p><p>In Swift 6, protocol design has become more difficult than ever. You are no longer just defining methods; you are also defining isolation boundaries. Should the protocol be marked <code>@MainActor</code>? Should it inherit from <code>Sendable</code>? Should its methods be <code>async</code>? Matt points out that many of the &#8220;waterfalls of concurrency errors&#8221; developers encounter when adopting Swift 6 may look like isolation-domain conflicts on the surface, but are often architectural problems caused by premature abstraction. If you try to design the perfect protocol before the requirements are clear, it is very easy to get &#8220;locked in&#8221; by concurrency rules.</p><p>Matt&#8217;s advice is to avoid starting with a protocol. Start with concrete types instead. Let the interface boundaries gradually emerge from real usage, and postpone abstractions that involve isolation domains or context-dependent capabilities. This approach helps avoid falling into the trap of fat protocols and excessive constraints in the concurrency era. Rather than a protocol design guide, it is more like a pragmatic &#8220;delay decisions&#8221; strategy for Swift 6.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-04">Automating your Xcode Project</a></strong></h3><p>Xcode project files have long been a source of trouble in version control. Starting from this pain point, <a href="https://x.com/leogdion">Leo G Dion</a> introduces practical ways to generate Xcode projects using XcodeGen and Tuist, along with a fairly complete Tuist workflow. The article also walks through the key configuration required for a minimally shippable project: deployment target, App Icon, Privacy Manifest, signing information, and version management, forming a useful automation-oriented &#8220;project checklist.&#8221;</p><blockquote><p>Although I am currently the only developer on my projects, I have also switched to generating Xcode projects with Tuist. On one hand, these tools provide a higher degree of engineering determinism. On the other hand, their value is further amplified in AI-assisted development: most agents support them well, and when files in the workspace are modified, they can automatically trigger <code>generate</code> when compilation requires it. Tools like Tuist and XcodeGen are gradually becoming more AI-friendly engineering infrastructure.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-05">Appearance Mode Changer</a></strong></h3><p>Two days ago, <a href="https://x.com/StewartLynch">Stewart Lynch</a> celebrated his 75th birthday. In a <a href="https://x.com/StewartLynch/status/2050470594408481019">post</a>, he wrote: &#8220;75 years of patches, upgrades, bug fixes, deprecated habits, and surprisingly few fatal errors. Still compiling. Still shipping. Still learning.&#8221;</p><p>As a well-known video tutorial creator, Stewart has also recently restarted his blog, publishing short tips in written form. This article covers an implementation of appearance mode switching in SwiftUI.</p><p>For those of us working in a fast-moving industry that can easily trigger age anxiety, this may be one of the most enviable states a developer can reach. Happy birthday to Stewart, and I hope this &#8220;Still&#8221; spirit reaches everyone as well.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-06">Six Years Perfecting Maps on watchOS</a></strong></h3><p>In this design diary, <a href="https://mastodon.social/@_Davidsmith">David Smith</a> looks back on the six-year journey of building the Apple Watch mapping experience for Pedometer++.</p><p>The most valuable part of the article is not the implementation itself, but the series of trade-offs behind it: interactions on watchOS must be direct enough, complex configuration is almost unacceptable, and the relationship between map and data requires constant balancing between readability and information density. Even the base map is no longer an off-the-shelf dependency, but something specifically customized for Liquid Glass. His technical choice is also representative: even though MapKit has arrived on watchOS, he still chose a fully custom solution because its configurability and expressiveness remain limited. Behind this decision is not only technical capability, but also a clear sense of product-experience priorities.</p><p>This is a classic example of long-term product refinement.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0134-07">Kadr: Describing Video Composition with a Swift DSL</a></strong></h3><p>Developed by <a href="https://www.linkedin.com/in/steliyan-hadzhidenev-7a0471101/">Steliyan Hadzhidenev</a>, Kadr is a Swift-native video composition library that uses a Result Builder DSL to organize AVFoundation&#8217;s otherwise scattered concepts &#8212; clips, transitions, multiple tracks, filters, overlays, audio, and export workflows &#8212; into a declarative API. What makes it worth following is not merely the cleaner syntax, but how it demonstrates the coordination of Swift 6 strict concurrency, <code>Sendable</code>, async/await, and time models such as <code>CMTime</code> in a real media-processing context.</p><p>Its companion project, <a href="https://github.com/SteliyanH/kadr-ui">KadrUI</a>, provides a set of SwiftUI-side editing components, including VideoPreview, OverlayHost, multi-track TimelineView, InspectorPanel, and KeyframeEditor. This means the DSL is not limited to export workflows, but can also support core video-editor interactions such as previewing, dragging, trimming, keyframes, and overlay editing.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-08">SwiftVLC: A Modern libVLC Wrapper for SwiftUI</a></strong></h3><p>Developed by <a href="https://www.linkedin.com/in/omaralbeik/">Omar Albeik</a>, SwiftVLC is a SwiftUI-oriented Swift wrapper around libVLC 4.0. Compared with the traditional VLCKit, it removes the Objective-C middle layer and directly provides an <code>@Observable</code> Player, <code>AsyncStream</code> event streams, typed throws, and a <code>VideoView(player)</code> that can be integrated in a single line. Its value is not just that it is &#8220;more Swift,&#8221; but that it offers a way to connect low-level multimedia capabilities with the modern Swift concurrency model. If your app needs to handle formats, subtitles, or complex network protocols that AVFoundation does not cover well, libVLC-based solutions remain hard to replace.</p><p>Of course, the limitations are equally clear: it requires relatively new system versions, and the underlying libVLC still requires attention to LGPL compliance.</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-134?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-134?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#35753; AI &#20174;&#31216;&#25163;&#21040;&#31216;&#24515;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-134/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20174;&#24320;&#22987;&#28145;&#24230;&#20351;&#29992; AI &#24037;&#20855;&#33267;&#20170;&#24050;&#26377;&#19977;&#24180;&#12290;&#19977;&#24180;&#38388;&#65292;&#25105;&#20146;&#21382;&#20102; AI &#33021;&#21147;&#30340;&#39134;&#36291;&#65292;&#20063;&#36234;&#26469;&#36234;&#28165;&#26224;&#22320;&#35302;&#25720;&#21040;&#23427;&#30340;&#36793;&#30028;&#12290;&#25130;&#33267;&#30446;&#21069;&#65292;AI &#26089;&#24050;&#26159;&#38750;&#24120;&#20986;&#33394;&#30340;&#25928;&#29575;&#24037;&#20855;&#65292;&#20294;&#22914;&#20309;&#35753;&#23427;&#20889;&#20986;&#30495;&#27491;&#8220;&#31216;&#24515;&#8221;&#8212;&#8212;&#31526;&#21512;&#25105;&#20010;&#20154;&#39118;&#26684;&#12289;&#24819;&#27861;&#19982;&#35774;&#35745;&#21746;&#23398;&#8212;&#8212;&#30340;&#20195;&#30721;&#65292;&#20173;&#26159;&#19968;&#20010;&#19981;&#23567;&#30340;&#25361;&#25112;&#12290;</p><p>&#21363;&#20415;&#20027;&#27969;&#27169;&#22411;&#24050;&#26222;&#36941;&#25552;&#20379; 1M token &#30340;&#19978;&#19979;&#25991;&#31383;&#21475;&#65292;&#20294;&#38543;&#30528;&#39033;&#30446;&#35268;&#27169;&#25193;&#22823;&#65292;&#23427;&#25152;&#33021;&#25215;&#36733;&#30340;&#20449;&#24687;&#20381;&#28982;&#36828;&#36828;&#33853;&#21518;&#20110;&#20154;&#31867;&#24320;&#21457;&#32773;&#30340;&#8220;&#20840;&#23616;&#35266;&#8221;&#65307;&#21472;&#21152;&#27880;&#24847;&#21147;&#34928;&#20943;&#38382;&#39064;&#65292;&#30495;&#27491;&#21487;&#29992;&#30340;&#19978;&#19979;&#25991;&#20854;&#23454;&#30456;&#24403;&#26377;&#38480;&#12290;&#36825;&#20063;&#26159;&#20026;&#20160;&#20040;&#26368;&#36817;&#19968;&#27573;&#26102;&#38388;&#65292;&#25105;&#20943;&#23569;&#20102;&#20889;&#32473;&#20154;&#31867;&#38405;&#35835;&#30340;&#25216;&#26415;&#25991;&#31456;&#65292;&#21364;&#20135;&#20986;&#20102;&#19981;&#23569;&#20889;&#32473; AI &#30475;&#30340;&#25991;&#26723;&#8212;&#8212;&#24120;&#26377;&#35835;&#32773;&#26469;&#20449;&#38382;&#25105;&#21338;&#23458;&#20026;&#20309;&#26356;&#26032;&#25918;&#32531;&#65292;&#21407;&#22240;&#27491;&#22312;&#20110;&#27492;&#12290;</p><p>&#20043;&#25152;&#20197;&#35201;&#32534;&#20889;&#22823;&#37327;&#30340;&#19987;&#23646;&#25991;&#26723;&#65292;&#19981;&#20165;&#20165;&#26159;&#20026;&#20102;&#32473; AI &#25552;&#20379;&#36275;&#22815;&#30340;&#19978;&#19979;&#25991;&#25351;&#23548;&#65292;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#25105;&#27491;&#22312;&#25506;&#32034;&#19968;&#22871;&#33258;&#30740;&#30340; SwiftUI &#29366;&#24577;&#27169;&#24335;&#12290;&#23427;&#19982;&#24403;&#21069;&#20027;&#27969;&#30340;&#24320;&#21457;&#33539;&#24335;&#26377;&#24456;&#22823;&#21306;&#21035;&#8212;&#8212;&#36825;&#24847;&#21619;&#30528;&#65292;AI &#24222;&#22823;&#30340;&#39044;&#35757;&#32451;&#25968;&#25454;&#22312;&#27492;&#26102;&#32463;&#24120;&#21464;&#25104;&#8220;&#22122;&#38899;&#8221;&#29978;&#33267;&#38459;&#21147;&#65292;&#23427;&#24635;&#26159;&#19981;&#33258;&#35273;&#22320;&#25226;&#20320;&#25289;&#22238;&#26368;&#24120;&#35265;&#30340;&#20889;&#27861;&#12290;&#25972;&#20010;&#24320;&#21457;&#36807;&#31243;&#22240;&#27492;&#21576;&#29616;&#20986;&#19968;&#31181;&#8220;&#25289;&#38191;&#8221;&#30340;&#33410;&#22863;&#65306;&#25105;&#29992; AI &#24555;&#36895;&#39564;&#35777;&#65292;&#25226;&#27169;&#31946;&#30340;&#24819;&#27861;&#33853;&#23454;&#20026;&#31934;&#20934;&#30340;&#21512;&#32422;&#19982;&#25509;&#21475;&#65307;&#21516;&#26102;&#19981;&#26029;&#23436;&#21892;&#25991;&#26723;&#65292;&#21453;&#36807;&#26469;&#32422;&#26463; AI&#65292;&#35753;&#23427;&#20889;&#20986;&#26356;&#36148;&#36817;&#25105;&#24515;&#24847;&#30340;&#20195;&#30721;&#12290;</p><p>&#23613;&#31649;&#36317;&#31163;&#26368;&#32456;&#23436;&#25104;&#36824;&#26377;&#19968;&#27573;&#26102;&#38388;&#65292;&#20294;&#38543;&#30528;&#20195;&#30721;&#12289;&#32467;&#26500;&#12289;&#25991;&#26723;&#30340;&#25345;&#32493;&#36845;&#20195;&#65292;&#23588;&#20854;&#26159;&#37027;&#20123;&#23578;&#26410;&#23436;&#20840;&#25104;&#22411;&#30340;&#24819;&#27861;&#36880;&#28176;&#28165;&#26224;&#24182;&#33853;&#22320;&#20043;&#21518;&#65292;&#25105;&#33021;&#26126;&#26174;&#24863;&#35273;&#21040;&#65306;&#24403;&#21069;&#30340; AI &#22312;&#36825;&#20010;&#39033;&#30446;&#20013;&#36234;&#26469;&#36234;&#39034;&#25163;&#65292;&#23427;&#20889;&#20986;&#30340;&#20195;&#30721;&#27491;&#22312;&#36880;&#28176;&#21521;&#25105;&#30340;&#39044;&#26399;&#38752;&#25314;&#12290;</p><p>&#23454;&#29616;&#30456;&#21516;&#30340;&#30028;&#38754;&#32467;&#26524;&#21487;&#20197;&#26377;&#26080;&#25968;&#31181;&#26041;&#24335;&#65292;&#20294;&#25105;&#24076;&#26395;&#36890;&#36807;&#31181;&#31181;&#32422;&#26463;&#65292;&#35753; AI &#21482;&#36873;&#25321;&#25105;&#35268;&#21010;&#30340;&#37027;&#26465;&#36335;&#24452;&#12290;&#25105;&#24182;&#19981;&#26159;&#35828;&#33258;&#24049;&#20889;&#30340;&#20195;&#30721;&#26377;&#22810;&#23436;&#32654;&#65292;&#32780;&#26159;&#24076;&#26395; AI &#20135;&#20986;&#30340;&#19996;&#35199;&#33021;&#35753;&#25105;&#26377;&#29087;&#24713;&#24863;&#21644;&#25484;&#25511;&#24863;&#65292;&#35753;&#25105;&#33021;&#27627;&#26080;&#38556;&#30861;&#22320;&#20171;&#20837;&#19982;&#32500;&#25252;&#12290;</p><p>&#22312;&#26126;&#30830;&#30340;&#30446;&#26631;&#19982;&#23436;&#21892;&#30340;&#25351;&#23548;&#19979;&#65292;AI &#30340;&#23454;&#29616;&#36895;&#24230;&#24050;&#26159;&#25105;&#30340;&#20960;&#21313;&#19978;&#30334;&#20493;&#12290;&#24403;&#8221;&#25928;&#29575;&#8221;&#19981;&#20877;&#26159;&#29942;&#39048;&#65292;&#22914;&#20309;&#35753;&#36825;&#20301;&#26497;&#36895;&#30340;&#21161;&#25163;&#21464;&#24471;&#26356;&#8220;&#31216;&#24515;&#8221;&#12289;&#26356;&#40664;&#22865;&#65292;&#25165;&#26159;&#19979;&#19968;&#38454;&#27573;&#30495;&#27491;&#20540;&#24471;&#25237;&#20837;&#30340;&#26041;&#21521;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-133/">&#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/w0134-01">Swift &#24182;&#21457;&#26680;&#24515;&#37322;&#30097; (Q&amp;A: Swift Concurrency - Formatted)</a></strong></h3><p>&#36825;&#26159;&#19968;&#20221;&#26469;&#33258; Apple &#24037;&#31243;&#24072;&#30340; <a href="https://www.youtube.com/live/E95agtPgaa0">Swift Concurrency Q&amp;A</a> &#23454;&#24405;&#65292;&#30001; <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a> &#25972;&#29702;&#12290;&#22312;&#27963;&#21160;&#20013;&#65292;&#24037;&#31243;&#24072;&#20204;&#38024;&#23545;&#24403;&#21069;&#24182;&#21457;&#27169;&#22411;&#20013;&#26368;&#23481;&#26131;&#20135;&#29983;&#35823;&#35299;&#30340;&#38382;&#39064;&#36827;&#34892;&#20102;&#38598;&#20013;&#35299;&#31572;&#12290;&#20174; <code>nonisolated(nonsending)</code> &#30340;&#34892;&#20026;&#21464;&#21270;&#65292;&#21040; <code>@concurrent</code> &#30340;&#20351;&#29992;&#36793;&#30028;&#65292;&#20877;&#21040; Task &#29983;&#21629;&#21608;&#26399;&#19982;&#21462;&#28040;&#26426;&#21046;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#27425;&#30693;&#35782;&#34917;&#20805;&#65292;&#19981;&#22914;&#35828;&#26159;&#19968;&#27425;&#8220;&#35821;&#20041;&#26657;&#20934;&#8221;&#12290;</p><blockquote><p>&#19968;&#20010;&#20540;&#24471;&#27880;&#24847;&#30340;&#20449;&#21495;&#26159;&#65306;Swift &#27491;&#22312;&#20174;&#8220;async &#40664;&#35748;&#24182;&#21457;&#8221;&#36716;&#21521;&#8220;&#40664;&#35748;&#20445;&#23432;&#65292;&#20165;&#22312;&#38656;&#35201;&#26102;&#26174;&#24335;&#24341;&#20837;&#24182;&#21457;&#8221;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-02">&#35299;&#26512; Task.immediate &#30340;&#35843;&#24230;&#34892;&#20026; (Immediate tasks in Swift Concurrency explained)</a></strong></h3><p>Swift 6.2 &#24341;&#20837;&#20102;&#19968;&#20010;&#30456;&#24403;&#8220;&#24494;&#22937;&#20294;&#26377;&#29992;&#8221;&#30340;&#26032;&#29305;&#24615;&#65306;<code>Task.immediate</code>&#12290;&#19982;&#24120;&#35268; <code>Task</code> &#19981;&#21516;&#65292;immediate task &#20250;&#22312;&#24403;&#21069;&#25191;&#34892;&#19978;&#19979;&#25991;&#20013;&#21516;&#27493;&#21551;&#21160;&#65292;&#24182;&#25345;&#32493;&#25191;&#34892;&#30452;&#21040;&#31532;&#19968;&#20010;&#30495;&#27491;&#30340; suspension point&#12290;<a href="https://x.com/twannl">Antoine van der Lee</a> &#22312;&#26412;&#25991;&#20013;&#23545;&#20854;&#34892;&#20026;&#36827;&#34892;&#20102;&#28165;&#26224;&#25286;&#35299;&#12290;</p><p>&#36825;&#31181;&#33021;&#21147;&#20027;&#35201;&#29992;&#20110;&#24357;&#21512;&#19968;&#20010;&#38271;&#26399;&#23384;&#22312;&#30340;&#31354;&#38553;&#65306;&#22312;&#21516;&#27493;&#19978;&#19979;&#25991;&#20013;&#35843;&#29992; async &#36923;&#36753;&#65292;&#21516;&#26102;&#21448;&#24076;&#26395;&#20445;&#25345;&#25191;&#34892;&#39034;&#24207;&#65288;&#20363;&#22914;&#22312; actor &#24050;&#27491;&#30830;&#38548;&#31163;&#30340;&#21069;&#25552;&#19979;&#31435;&#21363;&#26356;&#26032;&#29366;&#24577;&#65289;&#12290;&#22312;&#36825;&#20123;&#22330;&#26223;&#20013;&#65292;<code>Task.immediate</code> &#21487;&#20197;&#36991;&#20813;&#35843;&#24230;&#24310;&#36831;&#24102;&#26469;&#30340;&#8220;&#26102;&#24207;&#38169;&#20301;&#8221;&#12290;</p><blockquote><p>&#19981;&#36807;&#65292;&#23427;&#30340;&#39118;&#38505;&#21516;&#26679;&#30452;&#25509;&#8212;&#8212;&#22914;&#26524;&#22312;&#31532;&#19968;&#20010; suspension &#20043;&#21069;&#25191;&#34892;&#20102;&#36739;&#37325;&#30340;&#21516;&#27493;&#24037;&#20316;&#65288;&#23588;&#20854;&#26159;&#22312; MainActor &#19978;&#65289;&#65292;&#23601;&#20250;&#38459;&#22622;&#24403;&#21069;&#25191;&#34892;&#22120;&#65292;&#24102;&#26469;&#26126;&#26174;&#30340; UI &#21345;&#39039;&#12290;<code>Task.immediate</code> &#25913;&#21464;&#30340;&#21482;&#26159;&#8220;&#20219;&#21153;&#20309;&#26102;&#24320;&#22987;&#25191;&#34892;&#8221;&#65292;&#32780;&#19981;&#26159;&#20219;&#21153;&#30340;&#25972;&#20307;&#29983;&#21629;&#21608;&#26399;&#12290;&#22312;&#22823;&#22810;&#25968;&#24773;&#20917;&#19979;&#65292;&#24120;&#35268; Task &#30340;&#35843;&#24230;&#34892;&#20026;&#20173;&#28982;&#26159;&#26356;&#23433;&#20840;&#30340;&#36873;&#25321;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-03">Swift 6 &#24182;&#21457;&#35821;&#22659;&#19979;&#30340;&#21327;&#35758;&#35774;&#35745; (Concurrency Step-by-Step: Designing Protocols)</a></strong></h3><p><a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#20998;&#20139;&#20102;&#19968;&#31181;&#22312; Swift 6 &#20005;&#26684;&#24182;&#21457;&#35821;&#22659;&#19979;&#65292;&#26356;&#20855;&#8220;&#24037;&#31243;&#21487;&#25191;&#34892;&#24615;&#8221;&#30340;&#21327;&#35758;&#35774;&#35745;&#26041;&#27861;&#12290;</p><p>&#22312; Swift 6 &#20013;&#65292;&#21327;&#35758;&#35774;&#35745;&#21464;&#24471;&#21069;&#25152;&#26410;&#26377;&#22320;&#22256;&#38590;&#8212;&#8212;&#20320;&#19981;&#20165;&#35201;&#23450;&#20041;&#26041;&#27861;&#65292;&#36824;&#35201;&#23450;&#20041;&#38548;&#31163;&#36793;&#30028;&#65288;Isolation&#65289;&#12290;&#35201;&#19981;&#35201;&#21152; <code>@MainActor</code>&#65311;&#35201;&#19981;&#35201;&#32487;&#25215; <code>Sendable</code>&#65311;&#26041;&#27861;&#38656;&#19981;&#38656;&#35201; <code>async</code>&#65311;Matt &#24378;&#35843;&#65292;&#35768;&#22810;&#24320;&#21457;&#32773;&#22312;&#36866;&#37197; Swift 6 &#26102;&#36935;&#21040;&#30340;&#8220;&#24182;&#21457;&#25253;&#38169;&#28689;&#24067;&#8221;&#65292;&#34920;&#38754;&#19978;&#26159;&#38548;&#31163;&#22495;&#20914;&#31361;&#65292;&#26412;&#36136;&#19978;&#20854;&#23454;&#26159;&#36807;&#26089;&#25277;&#35937;&#24102;&#26469;&#30340;&#26550;&#26500;&#38382;&#39064;&#12290;&#22914;&#26524;&#22312;&#38656;&#27714;&#19981;&#26126;&#26102;&#23601;&#35797;&#22270;&#35774;&#35745;&#20986;&#23436;&#32654;&#21327;&#35758;&#65292;&#26497;&#26131;&#34987;&#24182;&#21457;&#35268;&#21017;&#8220;&#38145;&#27515;&#8221;&#12290;</p><p>Matt &#24314;&#35758;&#65306;&#19981;&#35201;&#19968;&#24320;&#22987;&#23601;&#20889; Protocol&#65292;&#32780;&#26159;&#20174;&#20855;&#20307;&#30340;&#23454;&#29616;&#65288;Concrete Types&#65289;&#20986;&#21457;&#12290;&#22312;&#30495;&#23454;&#20351;&#29992;&#22330;&#26223;&#20013;&#19981;&#26029;&#25910;&#25947;&#25509;&#21475;&#36793;&#30028;&#65292;&#24182;&#23558;&#28041;&#21450;&#38548;&#31163;&#22495;&#21644;&#19978;&#19979;&#25991;&#30456;&#20851;&#30340;&#33021;&#21147;&#24310;&#21518;&#25277;&#35937;&#12290;&#36825;&#31181;&#26041;&#24335;&#21487;&#20197;&#26377;&#25928;&#36991;&#20813;&#22312;&#24182;&#21457;&#26102;&#20195;&#38519;&#20837;&#8220;&#32982;&#21327;&#35758;&#8221;&#19982;&#36807;&#24230;&#32422;&#26463;&#30340;&#27877;&#28525;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#31181;&#21327;&#35758;&#35774;&#35745;&#25351;&#21335;&#65292;&#19981;&#22914;&#35828;&#26159; Swift 6 &#26102;&#20195;&#19968;&#31181;&#26356;&#21153;&#23454;&#30340;&#8220;&#24310;&#36831;&#20915;&#31574;&#8221;&#31574;&#30053;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-04">Xcode &#24037;&#31243;&#33258;&#21160;&#21270;&#26500;&#24314;&#23454;&#36341; (Automating your Xcode Project)</a></strong></h3><p>Xcode &#24037;&#31243;&#25991;&#20214;&#38271;&#26399;&#20197;&#26469;&#37117;&#26159;&#29256;&#26412;&#25511;&#21046;&#20013;&#30340;&#8220;&#38382;&#39064;&#28304;&#22836;&#8221;&#12290;<a href="https://x.com/leogdion">Leo G Dion</a> &#20174;&#36825;&#19968;&#30171;&#28857;&#20986;&#21457;&#65292;&#20171;&#32461;&#20102;&#20351;&#29992; XcodeGen &#19982; Tuist &#33258;&#21160;&#29983;&#25104;&#24037;&#31243;&#30340;&#23454;&#36341;&#26041;&#24335;&#65292;&#24182;&#32473;&#20986;&#20102;&#36739;&#20026;&#23436;&#25972;&#30340; Tuist &#20351;&#29992;&#27969;&#31243;&#12290;&#25991;&#31456;&#36824;&#31995;&#32479;&#26803;&#29702;&#20102;&#19968;&#20010;&#26368;&#23567;&#21487;&#21457;&#24067;&#24037;&#31243;&#25152;&#38656;&#30340;&#20851;&#38190;&#37197;&#32622;&#65306;deployment target&#12289;App Icon&#12289;Privacy Manifest&#12289;&#31614;&#21517;&#20449;&#24687;&#20197;&#21450;&#29256;&#26412;&#31649;&#29702;&#31574;&#30053;&#31561;&#65292;&#25552;&#20379;&#20102;&#19968;&#20221;&#36866;&#21512;&#33258;&#21160;&#21270;&#30340;&#8220;&#24037;&#31243;&#28165;&#21333;&#8221;&#12290;</p><blockquote><p>&#23613;&#31649;&#25105;&#30340;&#39033;&#30446;&#30446;&#21069;&#21482;&#26377;&#25105;&#19968;&#20010;&#24320;&#21457;&#32773;&#65292;&#25105;&#20063;&#24050;&#32463;&#20999;&#25442;&#21040;&#20351;&#29992; Tuist &#26469;&#29983;&#25104; Xcode &#24037;&#31243;&#12290;&#19968;&#26041;&#38754;&#65292;&#36825;&#31867;&#24037;&#20855;&#26412;&#36523;&#20855;&#22791;&#36739;&#39640;&#30340;&#24037;&#31243;&#30830;&#23450;&#24615;&#65307;&#21478;&#19968;&#26041;&#38754;&#65292;&#22312; AI &#36741;&#21161;&#32534;&#31243;&#30340;&#22330;&#26223;&#19979;&#65292;&#23427;&#20204;&#30340;&#20215;&#20540;&#34987;&#36827;&#19968;&#27493;&#25918;&#22823;&#8212;&#8212;&#21508;&#31867; Agent &#23545;&#20854;&#25903;&#25345;&#26222;&#36941;&#36739;&#22909;&#65292;&#22312;&#20462;&#25913;&#24037;&#20316;&#21306;&#25991;&#20214;&#21518;&#22914;&#38656;&#32534;&#35793;&#20250;&#33258;&#21160;&#35302;&#21457; generate&#12290;Tuist &#21644; XcodeGen &#36825;&#31867;&#24037;&#20855;&#65292;&#27491;&#22312;&#36880;&#28176;&#25104;&#20026; AI &#26102;&#20195;&#26356;&#8220;&#21451;&#22909;&#8221;&#30340;&#24037;&#31243;&#22522;&#30784;&#35774;&#26045;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-05">SwiftUI &#22806;&#35266;&#20027;&#39064;&#20999;&#25442;&#26041;&#26696; (Appearance Mode Changer)</a></strong></h3><p>&#20004;&#22825;&#21069;&#65292;<a href="https://x.com/StewartLynch">Stewart Lynch</a> &#36814;&#26469;&#20102;&#20182;&#30340; 75 &#23681;&#29983;&#26085;&#12290;&#20182;&#22312;<a href="https://x.com/StewartLynch/status/2050470594408481019">&#25512;&#25991;</a>&#19978;&#20889;&#36947;&#65306;&#8220;75 years of patches, upgrades, bug fixes, deprecated habits, and surprisingly few fatal errors. Still compiling. Still shipping. Still learning.&#8221;</p><p>&#20316;&#20026;&#30693;&#21517;&#30340;&#35270;&#39057;&#25945;&#31243;&#20316;&#32773;&#65292;Stewart &#36817;&#26399;&#20063;&#37325;&#21551;&#20102;&#21338;&#23458;&#65292;&#23558;&#19968;&#20123;&#31616;&#30701;&#30340;&#25216;&#24039;&#20197;&#25991;&#23383;&#24418;&#24335;&#25972;&#29702;&#21457;&#24067;&#65292;&#26412;&#25991;&#26159;&#20851;&#20110; SwiftUI &#22806;&#35266;&#27169;&#24335;&#20999;&#25442;&#30340;&#23454;&#29616;&#26041;&#26696;&#12290;</p><p>&#23545;&#20110;&#36523;&#22788;&#36825;&#20010;&#24555;&#36895;&#36845;&#20195;&#12289;&#23481;&#26131;&#35753;&#20154;&#20135;&#29983;&#24180;&#40836;&#28966;&#34385;&#30340;&#34892;&#19994;&#20013;&#30340;&#25105;&#20204;&#26469;&#35828;&#65292;&#36825;&#22823;&#27010;&#23601;&#26159;&#19968;&#20301;&#24320;&#21457;&#32773;&#26368;&#20196;&#20154;&#32673;&#24917;&#30340;&#29702;&#24819;&#29366;&#24577;&#12290;&#31069; Stewart &#29983;&#26085;&#24555;&#20048;&#65292;&#20063;&#25226;&#36825;&#20221;&#8221;Still&#8221;&#30340;&#31934;&#31070;&#20998;&#20139;&#32473;&#22823;&#23478;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-06">&#25171;&#30952; watchOS &#22320;&#22270;&#20307;&#39564;&#30340;&#20845;&#24180;&#21382;&#31243; (Six Years Perfecting Maps on watchOS)</a></strong></h3><p><a href="https://mastodon.social/@_Davidsmith">David Smith</a> &#22312;&#36825;&#31687;&#35774;&#35745;&#26085;&#24535;&#20013;&#22238;&#39038;&#20102;&#20182;&#20026; Pedometer++ &#25171;&#36896; Apple Watch &#22320;&#22270;&#20307;&#39564;&#30340;&#20845;&#24180;&#21382;&#31243;&#12290;</p><p>&#25991;&#31456;&#26368;&#26377;&#20215;&#20540;&#30340;&#37096;&#20998;&#24182;&#19981;&#22312;&#20855;&#20307;&#23454;&#29616;&#65292;&#32780;&#22312;&#20110;&#19968;&#31995;&#21015;&#21462;&#33293;&#65306;watchOS &#19978;&#30340;&#20132;&#20114;&#24517;&#39035;&#36275;&#22815;&#30452;&#25509;&#65292;&#22797;&#26434;&#37197;&#32622;&#20960;&#20046;&#19981;&#21487;&#25509;&#21463;&#65307;&#22320;&#22270;&#19982;&#25968;&#25454;&#20043;&#38388;&#65292;&#38656;&#35201;&#22312;&#8220;&#21487;&#35835;&#24615;&#8221;&#19982;&#8220;&#20449;&#24687;&#23494;&#24230;&#8221;&#20043;&#38388;&#19981;&#26029;&#26435;&#34913;&#65307;&#29978;&#33267;&#36830;&#24213;&#22270;&#20063;&#19981;&#20877;&#20381;&#36182;&#29616;&#25104;&#26041;&#26696;&#65292;&#32780;&#26159;&#19987;&#38376;&#20026; Liquid Glass &#23450;&#21046;&#12290;&#22312;&#25216;&#26415;&#36873;&#25321;&#19978;&#65292;&#20182;&#20063;&#32473;&#20986;&#20102;&#19968;&#20010;&#39047;&#20855;&#20195;&#34920;&#24615;&#30340;&#21028;&#26029;&#65306;&#21363;&#20415; MapKit &#24050;&#32463;&#30331;&#38470; watchOS&#65292;&#22312;&#21487;&#23450;&#21046;&#24615;&#19982;&#34920;&#29616;&#21147;&#20173;&#26377;&#38480;&#30340;&#24773;&#20917;&#19979;&#65292;&#20381;&#28982;&#36873;&#25321;&#23436;&#20840;&#33258;&#24314;&#26041;&#26696;&#12290;&#36825;&#32972;&#21518;&#20307;&#29616;&#30340;&#65292;&#19981;&#21482;&#26159;&#25216;&#26415;&#33021;&#21147;&#65292;&#26356;&#26159;&#23545;&#20135;&#21697;&#20307;&#39564;&#20248;&#20808;&#32423;&#30340;&#28165;&#26224;&#21028;&#26029;&#12290;</p><p>&#36825;&#26159;&#19968;&#27573;&#20856;&#22411;&#30340;&#8220;&#38271;&#26399;&#25171;&#30952;&#22411;&#8221;&#20135;&#21697;&#28436;&#36827;&#36807;&#31243;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0134-07">Kadr&#65306;&#29992; Swift DSL &#25551;&#36848;&#35270;&#39057;&#21512;&#25104;</a></strong></h3><p>&#30001; <a href="https://www.linkedin.com/in/steliyan-hadzhidenev-7a0471101/">Steliyan Hadzhidenev</a> &#24320;&#21457;&#30340; Kadr &#26159;&#19968;&#20010; Swift &#21407;&#29983;&#30340;&#35270;&#39057;&#21512;&#25104;&#24211;&#65292;&#20351;&#29992; Result Builder DSL &#23558; AVFoundation &#20013;&#21407;&#26412;&#20998;&#25955;&#30340;&#21098;&#36753;&#12289;&#36716;&#22330;&#12289;&#22810;&#36712;&#12289;&#28388;&#38236;&#12289;overlay&#12289;&#38899;&#39057;&#19982;&#23548;&#20986;&#27969;&#31243;&#32452;&#32455;&#20026;&#22768;&#26126;&#24335; API&#12290;&#23427;&#20540;&#24471;&#20851;&#27880;&#30340;&#22320;&#26041;&#19981;&#21482;&#26159;&#35821;&#27861;&#23618;&#38754;&#30340;&#31616;&#21270;&#65292;&#32780;&#22312;&#20110;&#23427;&#23637;&#31034;&#20102;&#22312;&#30495;&#23454;&#23186;&#20307;&#22788;&#29702;&#22330;&#26223;&#20013;&#65292;&#22914;&#20309;&#23558; Swift 6 &#30340; strict concurrency&#12289;Sendable&#12289;async/await &#19982; CMTime &#36825;&#31867;&#26102;&#38388;&#27169;&#22411;&#21327;&#21516;&#36215;&#26469;&#12290;</p><p>&#20854;&#37197;&#22871;&#30340; <a href="https://github.com/SteliyanH/kadr-ui">KadrUI</a> &#21017;&#25552;&#20379;&#20102; SwiftUI &#20391;&#30340;&#19968;&#25972;&#22871;&#32534;&#36753;&#30028;&#38754;&#32452;&#20214;&#65292;&#21253;&#25324; VideoPreview&#12289;OverlayHost&#12289;&#22810;&#36712; TimelineView&#12289;InspectorPanel &#19982; KeyframeEditor&#65292;&#20351;&#36825;&#22871; DSL &#19981;&#20165;&#21487;&#20197;&#29992;&#20110;&#23548;&#20986;&#27969;&#31243;&#65292;&#20063;&#20855;&#22791;&#25903;&#25745;&#35270;&#39057;&#32534;&#36753;&#22120;&#39044;&#35272;&#12289;&#25302;&#25341;&#12289;&#35009;&#21098;&#12289;&#20851;&#38190;&#24103;&#21644;&#21472;&#21152;&#23618;&#32534;&#36753;&#31561;&#26680;&#24515;&#20132;&#20114;&#30340;&#33021;&#21147;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0134-08">SwiftVLC&#65306;&#38754;&#21521; SwiftUI &#30340;&#29616;&#20195; libVLC &#23553;&#35013;</a></strong></h3><p>&#30001; <a href="https://www.linkedin.com/in/omaralbeik/">Omar Albeik</a> &#24320;&#21457;&#30340; SwiftVLC &#26159;&#19968;&#20010;&#38754;&#21521; SwiftUI &#30340; libVLC 4.0 Swift &#23553;&#35013;&#12290;&#30456;&#27604;&#20256;&#32479;&#30340; VLCKit&#65292;&#23427;&#21435;&#38500;&#20102; Objective-C &#20013;&#38388;&#23618;&#65292;&#30452;&#25509;&#25552;&#20379;&#22522;&#20110; <code>@Observable</code> &#30340; Player&#12289;<code>AsyncStream</code> &#20107;&#20214;&#27969;&#12289;typed throws&#65292;&#20197;&#21450;&#19968;&#34892;&#21363;&#21487;&#38598;&#25104;&#30340; <code>VideoView(player)</code>&#12290;&#23427;&#30340;&#20215;&#20540;&#19981;&#20165;&#22312;&#20110;&#8220;&#26356; Swift&#8221;&#65292;&#36824;&#22312;&#20110;&#25552;&#20379;&#20102;&#19968;&#31181;&#23558;&#24213;&#23618;&#22810;&#23186;&#20307;&#33021;&#21147;&#19982;&#29616;&#20195; Swift &#24182;&#21457;&#27169;&#22411;&#32467;&#21512;&#30340;&#23454;&#29616;&#26041;&#24335;&#12290;&#22914;&#26524;&#20320;&#30340;&#24212;&#29992;&#38656;&#35201;&#22788;&#29702; AVFoundation &#38590;&#20197;&#35206;&#30422;&#30340;&#26684;&#24335;&#12289;&#23383;&#24149;&#25110;&#22797;&#26434;&#32593;&#32476;&#21327;&#35758;&#65292;&#36825;&#31867;&#22522;&#20110; libVLC &#30340;&#26041;&#26696;&#20381;&#28982;&#20855;&#26377;&#19981;&#21487;&#26367;&#20195;&#24615;&#12290;</p><p>&#24403;&#28982;&#65292;&#38480;&#21046;&#20063;&#21516;&#26679;&#26126;&#30830;&#65306;&#23545;&#31995;&#32479;&#29256;&#26412;&#35201;&#27714;&#36739;&#39640;&#65292;&#21516;&#26102;&#24213;&#23618; libVLC &#20173;&#38656;&#20851;&#27880; LGPL &#21512;&#35268;&#38382;&#39064;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #133]]></title><description><![CDATA[Swift Concurrency is Gaining Broader Adoption]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-133</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-133</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 27 Apr 2026 12:03:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!dbsm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.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_!dbsm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dbsm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 424w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 848w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 1272w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dbsm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp" width="1400" height="927" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/73788071-281d-40bf-b94a-190a503f4053_1400x927.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:927,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:379300,&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/195580115?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.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_!dbsm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 424w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 848w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.webp 1272w, https://substackcdn.com/image/fetch/$s_!dbsm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73788071-281d-40bf-b94a-190a503f4053_1400x927.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"><svg role="img" 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"><g><title></title><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"><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"><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/@tomas_nz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Tomas Sobek</a> on <a href="https://unsplash.com/photos/two-red-and-blue-zippers-plwud_FPvwU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Swift Concurrency is Gaining Broader Adoption</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-133/">Read on web &#8594;</a></p><p>It has been almost 5 years since Swift 5.5 introduced a new concurrency model aligned with modern programming paradigms. From 5.5 to the current 6.3, the Swift community has been actively advancing the evolution of concurrency APIs through small, iterative steps. However, this process hasn&#8217;t exactly been smooth sailing for developers, who had to grapple with a plethora of new keywords, complex isolation concepts, and some confusing &#8220;anti-patterns.&#8221;</p><p>As a newsletter editor, I&#8217;ve seen a massive amount of complaints and pleas for help over the past few years, but this sense of anxiety seems to have noticeably faded since the beginning of this year. In recent months, there have been more and more success stories shared within the community about migrating legacy projects to the new concurrency model. Although there are still a few scattered complaints, the prevailing attitude has shifted toward active embrace. Looking at the practical results, the new code&#8212;born from the growing pains of refactoring&#8212;has significantly reduced the cognitive load on developers when maintaining concurrency states.</p><p>Of course, behind this phenomenon, aside from developers becoming increasingly proficient with the new system, the maturity of the ecosystem also deserves a lot of credit. Over the past few years, both first-party and third-party frameworks and components have gradually completed their transition to the new concurrency implementations. This has greatly lowered the barrier to entry, allowing an increasing number of developers to immediately enjoy the convenience and data safety it brings.</p><p>There is also an interesting factor at play: thanks to the selfless sharing of many excellent content creators and open-source authors in the community, AI has accumulated a much richer corpus of Swift concurrency data over the past year or two. The new generation of large language models released in recent months clearly possesses a more accurate understanding of Swift&#8217;s concurrency rules, which has greatly accelerated developers&#8217; mastery and application of the new concurrency.</p><p>Imperceptibly, the development of Swift&#8217;s new concurrency has entered a virtuous cycle. As can be seen from the new features in Swift 6.3, following the release of version 6.2, the evolution of Swift concurrency has largely entered a stable phase. Consequently, the community&#8217;s focus has shifted toward broader areas such as cross-platform and embedded development.</p><p>Perhaps the term &#8220;new concurrency model&#8221; in Swift can soon drop the &#8220;new&#8221; label and officially become part of the lifeblood of our daily development. Of course, it&#8217;s not entirely impossible that in another five to ten years, yet another &#8220;brand-new&#8221; concurrency model will arrive to amaze (or torture) us once again.</p><p><a href="https://fatbobman.com/en/weekly/issue-132/">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/w0133-01">The Flaky Test That Taught Me How Swift Concurrency Actually Works</a></strong></h3><p>Writing a test <code>MockClock</code> to support debounce behavior may not seem difficult for many Swift developers. But if you overlook differences in execution context &#8212; the executor &#8212; the result may be less deterministic than expected. Through the debugging process of a real-world case, <a href="https://x.com/budo_coder">Xiangyu</a> reveals many details of modern Swift concurrency: <code>nonisolated async</code> functions hop away from the caller&#8217;s actor; <code>Task.yield()</code> only yields the current executor; and <code>isolated</code> parameters plus <code>#isolation</code> can let utility functions &#8220;run with the caller.&#8221; The value of this article is not in how to implement a test Clock, but in how clearly it shows the real relationship between tasks, actors, executors, and isolation in Swift Concurrency.</p><blockquote><p>As Swift evolves, the behavior of <code>nonisolated</code> is no longer always equivalent to &#8220;necessarily hopping away from the current caller.&#8221; It can also be affected by the language mode and settings such as <code>NonisolatedNonsendingByDefault</code>. I ran into a <a href="https://fatbobman.com/en/posts/letting-swift-closures-automatically-inherit-isolation/">similar issue</a>, and solved it in the same way: with <code>isolated</code> + <code>#isolation</code>.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-02">What&#8217;s that &#8220;structured&#8221; in Structured Concurrency?</a></strong></h3><p>Although <code>Task</code> has a handle and can be cancelled, making it look &#8220;more structured&#8221; than <code>dispatch_async</code>, its definition in Swift&#8217;s modern concurrency system is actually quite clear: <code>Task</code> is an <em>unstructured top-level task</em>. In this article, <a href="https://objc.social/@macguru17">Max Seelemann</a> explains what &#8220;structured&#8221; really means: the truly structured concurrency constructs are essentially <code>async let</code> and <code>TaskGroup</code>. What they share is an inescapable dependency relationship: the caller must wait for the subtasks to complete, and cancellation automatically propagates downward. <code>Task</code>, by contrast, is the opposite &#8212; it can be freely created and forgotten, with a lifecycle detached from the caller.</p><p>The article ends with a practical suggestion: use closures instead of <code>Task</code> whenever possible. Expressing a unit of work as <code>() async -&gt; Void</code> is simpler, easier to test, and naturally inherits cancellation behavior from the calling context compared with passing around a <code>Task</code> object.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-03">SwiftUI: Refreshable Task Cancellation</a></strong></h3><p><code>.refreshable</code> accepts an async closure in which developers can fetch new data and update view state. But it has an easy-to-miss pitfall: if you modify the <code>@State</code> that drives the current view while the closure is running, the resulting redraw may cancel the refreshable task before it completes. In this article, <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a> clearly explains this behavior: the lifecycle of <code>.refreshable</code> is tied to the view, and if a redraw is triggered during the refresh process, SwiftUI may terminate the task early &#8212; in other words, the task is cancelled by the very update it caused.</p><p>The author gives two possible fixes: either collect intermediate results in a local variable and update state once at the end, avoiding repeated redraws; or wrap the actual work in <code>Task { }.value</code>, allowing it to &#8220;detach&#8221; from the current refresh task and avoid being interrupted by the view lifecycle.</p><blockquote><p>The issue faced by <code>.refreshable</code> also exists with <code>.task</code>. This is not a bug, but a concrete expression of SwiftUI&#8217;s structured concurrency model: async tasks are attached to the view lifecycle and are cancelled when that lifecycle ends. Without realizing this, it is easy to create a &#8220;self-cancellation&#8221; scenario between state updates and task execution.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-04">Swift 6.3 experimentalCGen guide: SwiftPM natively supports C code generation</a></strong></h3><p>The <code>experimentalCGen</code> feature introduced in Swift 6.3 fills a long-standing gap in SwiftPM: C-family artifacts generated by Build Tool Plugins can finally participate directly in the compilation of C module targets, without relying on external scripts or precommitted generated files. This means the complete build graph can be closed within SwiftPM &#8212; local builds, CI, and Xcode can all use the same rules instead of each maintaining part of the build knowledge. In this article, <a href="https://x.com/RbBtSn0w">Snow</a> gives a detailed overview of the background, usage, and migration path for this feature.</p><blockquote><p><code>experimentalCGen</code> still has clear limitations. For example, each target can only have one generated module map, and headers referenced by that module map must be located in the same directory. As a result, it is better suited to code generation workflows with clear boundaries and stable outputs, rather than serving as a replacement for a full native build system.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-05">How I migrated 300 screens to SwiftUI and what I learned</a></strong></h3><p>Migrating 300 screens to SwiftUI sounds like a complete transformation, but the strategy adopted by <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> and his team was quite restrained: SwiftUI was responsible only for UI construction, while navigation remained in UIKit. This separation was not a compromise, but a deliberate choice &#8212; allowing the team to benefit from SwiftUI&#8217;s strengths in layout and component reuse while avoiding unnecessary risks around navigation, deep linking, and complex flows. The article records recurring issues during the migration: the team was used to imperative thinking and often wrote SwiftUI as &#8220;UIKit with different syntax&#8221;; side effects were placed inside <code>body</code>; <code>onAppear</code> was treated as <code>viewDidLoad</code>; nested <code>ObservableObject</code> structures led to unexpected state propagation problems. After continuous review and internal workshops, the team eventually settled on a clear architectural direction: MVVM + enum-driven state and interaction modeling + Use Cases for separating business logic.</p><blockquote><p>Even outside migration projects, combining SwiftUI and UIKit is a realistic and effective choice. The two frameworks are not opposed to each other. Mixing them is not the hard part; the real challenge is writing code that fits each framework&#8217;s intended mental model.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0133-06">Mini Swift: A Swift Compiler Written in Pure C</a></strong></h3><p>A fascinating project with a strong hacker spirit. Without using LLVM, Clang, or any official Apple toolchain, <a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> single-handedly wrote a lightweight Swift compiler in more than 70,000 lines of C. Starting from lexical analysis and the AST, he built the pipeline all the way to a backend that directly outputs WASM, bringing an astonishing sub-0.1 ms &#8220;instant compilation&#8221; experience to the web. In an era where pulling in hundreds of megabytes of dependencies is common, this zero-dependency act of &#8220;building the wheel by hand&#8221; feels almost romantically retro.</p><p>The project began with a simple goal: to build a SwiftUI browser preview that would not crash. The author also revealed that he is currently developing a layer called UIIR &#8212; a UI intermediate representation &#8212; with the eventual goal of mapping SwiftUI code into a platform-independent set of instructions that can render native-like results directly on the Web or even Android, fulfilling his original vision.</p><blockquote><p>The compiler frontend&#8217;s core code &#8212; lexer, parser, and semantic analysis &#8212; is currently <a href="https://github.com/toprakdeviren/msf">open source</a>.</p><p>If combined with a terminal-based WASM runtime (such as Wasmtime), Mini Swift could significantly alleviate the current pain point of slow cold starts when writing terminal scripts in Swift, truly enhancing the Swift scripting experience. I am very much looking forward to seeing community explorations in this direction.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-07">Yotei: A SwiftUI Calendar Component Library</a></strong></h3><p>Yotei is an iOS calendar component library by <a href="https://www.linkedin.com/in/mikalai-zmachynski-36006010/">Mikalai Zmachynski</a>. The project provides SwiftUI APIs while relying on UIKit to maintain scrolling performance in high-load scenarios such as schedule lists, pagination, and timelines. It includes components such as a date picker, day timeline, month grid, and schedule list, along with fairly detailed customization entry points.</p><p>Yotei demonstrates an increasingly common trade-off in complex SwiftUI components: SwiftUI handles composition, state binding, and extension points, while UIKit provides more mature and stable list and paging behavior.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-08">Runtime Viewer</a></strong></h3><p>If you still remember RuntimeBrowser, then Runtime Viewer, developed by <a href="https://x.com/JH_Pointer">Mx-Iris</a>, can be seen as a modern rewrite of that idea for today&#8217;s Apple platform context. It can browse not only Objective-C runtime information, but also Swift types, enum layouts, VTable offsets, and more, while offering a code-reading experience close to Xcode.</p><p>It is not merely a tool that &#8220;shows more interfaces.&#8221; Instead, it brings runtime inspection, cross-process communication, code injection, Bonjour device discovery, and even MCP integration into a single tool. For developers interested in reverse engineering, security research, learning system frameworks, or simply understanding the internal structure of a binary, it feels more like a runtime inspection workbench for modern Apple platforms.</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-133?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-133?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Swift &#24182;&#21457;&#27491;&#34987;&#26356;&#24191;&#27867;&#22320;&#25509;&#32435;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-133/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20174; Swift 5.5 &#24341;&#20837;&#31526;&#21512;&#29616;&#20195;&#32534;&#31243;&#24605;&#24819;&#30340;&#26032;&#24182;&#21457;&#27169;&#22411;&#31639;&#36215;&#65292;&#19968;&#36716;&#30524;&#24555; 5 &#24180;&#20102;&#12290;&#20174; 5.5 &#21040;&#30446;&#21069;&#30340; 6.3&#65292;Swift &#31038;&#21306;&#19968;&#30452;&#22312;&#37319;&#29992;&#23567;&#27493;&#36845;&#20195;&#30340;&#26041;&#24335;&#65292;&#31215;&#26497;&#25512;&#36827;&#24182;&#21457; API &#30340;&#28436;&#36827;&#12290;&#20294;&#22312;&#24212;&#23545;&#36807;&#22810;&#30340;&#26032;&#20851;&#38190;&#23383;&#12289;&#22797;&#26434;&#30340;&#38548;&#31163;&#27010;&#24565;&#20197;&#21450;&#19968;&#20123;&#23481;&#26131;&#24341;&#21457;&#22256;&#25200;&#30340;&#8220;&#21453;&#27169;&#24335;&#8221;&#26102;&#65292;&#36825;&#20010;&#36807;&#31243;&#23545;&#24320;&#21457;&#32773;&#26469;&#35828;&#24182;&#19981;&#31639;&#39034;&#21033;&#12290;</p><p>&#20316;&#20026;&#19968;&#20010;&#21608;&#25253;&#32534;&#36753;&#65292;&#25105;&#22312;&#36807;&#21435;&#20960;&#24180;&#38388;&#30475;&#21040;&#36807;&#22823;&#37327;&#30340;&#21520;&#27133;&#19982;&#27714;&#21161;&#65292;&#20294;&#36825;&#31181;&#28966;&#34385;&#24863;&#20284;&#20046;&#20174;&#20170;&#24180;&#21021;&#24320;&#22987;&#26126;&#26174;&#36716;&#24369;&#20102;&#12290;&#26368;&#36817;&#20960;&#20010;&#26376;&#65292;&#31038;&#21306;&#20013;&#20986;&#29616;&#20102;&#36234;&#26469;&#36234;&#22810;&#23558;&#26087;&#39033;&#30446;&#36801;&#31227;&#21040;&#26032;&#24182;&#21457;&#27169;&#22411;&#30340;&#25104;&#21151;&#20998;&#20139;&#12290;&#23613;&#31649;&#20854;&#20013;&#20173;&#22841;&#26434;&#30528;&#23569;&#37327;&#30340;&#25265;&#24616;&#65292;&#20294;&#20027;&#27969;&#24577;&#24230;&#24050;&#32463;&#23637;&#29616;&#20986;&#31215;&#26497;&#25317;&#25265;&#30340;&#24577;&#21183;&#12290;&#20174;&#23454;&#38469;&#30340;&#24212;&#29992;&#25928;&#26524;&#26469;&#30475;&#65292;&#32463;&#21382;&#36807;&#38453;&#30171;&#37325;&#26500;&#21518;&#30340;&#26032;&#20195;&#30721;&#65292;&#26497;&#22823;&#22320;&#38477;&#20302;&#20102;&#24320;&#21457;&#32773;&#22312;&#32500;&#25252;&#24182;&#21457;&#29366;&#24577;&#26102;&#30340;&#24515;&#26234;&#36127;&#25285;&#12290;</p><p>&#24403;&#28982;&#65292;&#36825;&#19968;&#29616;&#35937;&#30340;&#32972;&#21518;&#65292;&#38500;&#20102;&#24320;&#21457;&#32773;&#33258;&#36523;&#23545;&#26032;&#20307;&#31995;&#30340;&#25484;&#25569;&#36234;&#26469;&#36234;&#29087;&#32451;&#22806;&#65292;&#29983;&#24577;&#30340;&#25104;&#29087;&#20063;&#21151;&#19981;&#21487;&#27809;&#12290;&#22312;&#36807;&#21435;&#30340;&#20960;&#24180;&#37324;&#65292;&#26080;&#35770;&#26159;&#31532;&#19968;&#26041;&#36824;&#26159;&#31532;&#19977;&#26041;&#26694;&#26550;&#19982;&#32452;&#20214;&#65292;&#37117;&#36880;&#28176;&#23436;&#25104;&#20102;&#21521;&#26032;&#24182;&#21457;&#23454;&#29616;&#30340;&#36807;&#28193;&#12290;&#36825;&#22823;&#22823;&#38477;&#20302;&#20102;&#29992;&#25143;&#30340;&#20351;&#29992;&#38376;&#27099;&#65292;&#35753;&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#33021;&#22312;&#31532;&#19968;&#26102;&#38388;&#20139;&#21463;&#21040;&#26032;&#24182;&#21457;&#24102;&#26469;&#30340;&#20415;&#25463;&#19982;&#25968;&#25454;&#23433;&#20840;&#12290;</p><p>&#27492;&#22806;&#36824;&#26377;&#19968;&#20010;&#26377;&#36259;&#30340;&#22240;&#32032;&#65306;&#24471;&#30410;&#20110;&#31038;&#21306;&#20247;&#22810;&#20248;&#31168;&#20869;&#23481;&#21019;&#20316;&#32773;&#12289;&#24320;&#28304;&#20316;&#32773;&#30340;&#26080;&#31169;&#20998;&#20139;&#65292;AI &#22312;&#36807;&#21435;&#19968;&#20004;&#24180;&#20013;&#31215;&#32047;&#20102;&#26356;&#20016;&#23500;&#30340; Swift &#24182;&#21457;&#35821;&#26009;&#12290;&#36807;&#21435;&#20960;&#20010;&#26376;&#38388;&#25512;&#20986;&#30340;&#26032;&#19968;&#20195;&#22823;&#35821;&#35328;&#27169;&#22411;&#65292;&#26126;&#26174;&#23545; Swift &#30340;&#24182;&#21457;&#35268;&#21017;&#26377;&#20102;&#26356;&#20934;&#30830;&#30340;&#29702;&#35299;&#65292;&#36825;&#20063;&#22823;&#22823;&#21152;&#24555;&#20102;&#24320;&#21457;&#32773;&#23545;&#26032;&#24182;&#21457;&#30340;&#25484;&#25569;&#21644;&#24212;&#29992;&#12290;</p><p>&#22312;&#19981;&#30693;&#19981;&#35273;&#20013;&#65292;Swift &#26032;&#24182;&#21457;&#30340;&#21457;&#23637;&#24050;&#32463;&#36827;&#20837;&#20102;&#19968;&#20010;&#33391;&#24615;&#24490;&#29615;&#12290;&#20174; Swift 6.3 &#30340;&#26032;&#21151;&#33021;&#23601;&#33021;&#30475;&#20986;&#65292;&#22312;&#32463;&#21382;&#20102; 6.2 &#29256;&#26412;&#20043;&#21518;&#65292;Swift &#30340;&#24182;&#21457;&#28436;&#36827;&#24050;&#22522;&#26412;&#36827;&#20837;&#31283;&#23450;&#26399;&#65292;&#31038;&#21306;&#30340;&#20851;&#27880;&#28966;&#28857;&#20063;&#38543;&#20043;&#36716;&#31227;&#21040;&#20102;&#36328;&#24179;&#21488;&#12289;&#23884;&#20837;&#24335;&#31561;&#26356;&#24191;&#38420;&#30340;&#39046;&#22495;&#12290;</p><p>&#25110;&#35768;&#65292;Swift &#30340;&#8220;&#26032;&#24182;&#21457;&#27169;&#22411;&#8221;&#36825;&#20010;&#31216;&#21628;&#65292;&#24456;&#24555;&#23601;&#21487;&#20197;&#25688;&#25481;&#8220;&#26032;&#8221;&#30340;&#24125;&#23376;&#65292;&#27491;&#24335;&#34701;&#20837;&#26085;&#24120;&#24320;&#21457;&#30340;&#34880;&#28082;&#20013;&#20102;&#12290;&#24403;&#28982;&#65292;&#20063;&#19981;&#25490;&#38500;&#20877;&#36807;&#20010;&#20116;&#21040;&#21313;&#24180;&#65292;&#21448;&#20250;&#26377;&#19968;&#20010;&#8220;&#20840;&#26032;&#8221;&#30340;&#24182;&#21457;&#27169;&#22411;&#20877;&#27425;&#24778;&#33395;&#65288;&#25110;&#25240;&#30952;&#65289;&#25105;&#20204;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-132/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0133-01">&#19968;&#20010;&#20598;&#21457;&#24615;&#27979;&#35797;&#22833;&#36133;&#65292;&#25581;&#24320;&#20102; Swift &#24182;&#21457;&#35843;&#24230;&#30340;&#30495;&#30456; (The Flaky Test That Taught Me How Swift Concurrency Actually Works)</a></strong></h3><p>&#20026;&#25903;&#25345; debounce &#34892;&#20026;&#32534;&#20889;&#19968;&#20010;&#27979;&#35797;&#29992;&#30340; <code>MockClock</code>&#65292;&#23545;&#24456;&#22810; Swift &#24320;&#21457;&#32773;&#26469;&#35828;&#20284;&#20046;&#24182;&#19981;&#22797;&#26434;&#12290;&#20294;&#22914;&#26524;&#24573;&#30053;&#20102;&#25191;&#34892;&#19978;&#19979;&#25991;&#65288;executor&#65289;&#30340;&#24046;&#24322;&#65292;&#32467;&#26524;&#21487;&#33021;&#23601;&#27809;&#26377;&#24819;&#35937;&#20013;&#37027;&#20040;&#30830;&#23450;&#12290;<a href="https://x.com/budo_coder">Xiangyu</a> &#36890;&#36807;&#19968;&#20010;&#23454;&#38469;&#26696;&#20363;&#30340;&#35843;&#35797;&#36807;&#31243;&#65292;&#25581;&#31034;&#20102; Swift &#29616;&#20195;&#24182;&#21457;&#20013;&#30340;&#35832;&#22810;&#32454;&#33410;&#65306;<code>nonisolated async</code> &#20989;&#25968;&#20250;&#36339;&#31163;&#35843;&#29992;&#32773; actor&#65307;<code>Task.yield()</code> &#21482;&#35753;&#20986;&#24403;&#21069;&#25191;&#34892;&#22120;&#65307;<code>isolated</code> &#21442;&#25968; + <code>#isolation</code> &#21487;&#20197;&#35753;&#24037;&#20855;&#20989;&#25968;&#8220;&#38543;&#35843;&#29992;&#32773;&#36816;&#34892;&#8221;&#12290;&#26412;&#25991;&#30340;&#20215;&#20540;&#19981;&#22312;&#20110;&#22914;&#20309;&#23454;&#29616;&#19968;&#20010;&#27979;&#35797;&#29992;&#30340; Clock&#65292;&#32780;&#22312;&#20110;&#23427;&#28165;&#26224;&#22320;&#23637;&#31034;&#20102; Swift Concurrency &#20013;&#12300;&#20219;&#21153;&#12289;actor&#12289;executor&#12289;&#38548;&#31163;&#12301;&#20043;&#38388;&#30340;&#30495;&#23454;&#20851;&#31995;&#12290;</p><blockquote><p>&#38543;&#30528; Swift &#29256;&#26412;&#30340;&#21457;&#23637;&#65292;<code>nonisolated</code> &#30340;&#34892;&#20026;&#20063;&#19981;&#20877;&#24635;&#26159;&#31561;&#21516;&#20110;&#8220;&#24517;&#28982;&#36339;&#31163;&#24403;&#21069;&#35843;&#29992;&#32773;&#8221;&#65292;&#32780;&#20250;&#21463;&#21040;&#35821;&#35328;&#27169;&#24335;&#20197;&#21450; <code>NonisolatedNonsendingByDefault</code> &#31561;&#35774;&#32622;&#30340;&#24433;&#21709;&#12290;&#25105;&#20063;&#30896;&#21040;&#36807;&#21644;&#26412;&#25991;&#31867;&#20284;&#30340;<a href="https://fatbobman.com/zh/posts/letting-swift-closures-automatically-inherit-isolation/">&#38382;&#39064;</a>&#65292;&#21516;&#26679;&#20063;&#26159;&#36890;&#36807; <code>isolated</code> + <code>#isolation</code> &#26469;&#35299;&#20915;&#30340;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-02">&#12300;&#32467;&#26500;&#21270;&#24182;&#21457;&#12301;&#37324;&#30340;&#12300;&#32467;&#26500;&#21270;&#12301;&#31350;&#31455;&#26159;&#20160;&#20040;&#24847;&#24605;&#65311; (What&#8217;s that &#8220;structured&#8221; in Structured Concurrency?)</a></strong></h3><p>&#23613;&#31649; <code>Task</code> &#26377;&#21477;&#26564;&#12289;&#21487;&#21462;&#28040;&#65292;&#27604; <code>dispatch_async</code> &#30475;&#36215;&#26469;&#8220;&#26356;&#26377;&#32467;&#26500;&#8221;&#65292;&#20294;&#22312; Swift &#30340;&#29616;&#20195;&#24182;&#21457;&#31995;&#32479;&#20013;&#65292;&#23427;&#30340;&#23450;&#20041;&#20854;&#23454;&#24456;&#26126;&#30830;&#65306;<code>Task</code> &#26159; <em>unstructured top-level task</em>&#12290;<a href="https://objc.social/@macguru17">Max Seelemann</a> &#22312;&#26412;&#25991;&#20013;&#35299;&#37322;&#20102;&#8220;&#32467;&#26500;&#21270;&#8221;&#30340;&#30495;&#27491;&#21547;&#20041;&#65306;&#30495;&#27491;&#23646;&#20110;&#32467;&#26500;&#21270;&#24182;&#21457;&#30340;&#65292;&#20854;&#23454;&#21482;&#26377;&#20004;&#31181;&#8212;&#8212;<code>async let</code> &#21644; <code>TaskGroup</code>&#12290;&#23427;&#20204;&#30340;&#20849;&#21516;&#28857;&#22312;&#20110;&#19968;&#31181;&#19981;&#21487;&#36867;&#36991;&#30340;&#20381;&#36182;&#20851;&#31995;&#65306;&#35843;&#29992;&#32773;&#24517;&#39035;&#31561;&#24453;&#23376;&#20219;&#21153;&#23436;&#25104;&#65292;&#19988;&#21462;&#28040;&#20250;&#33258;&#21160;&#21521;&#19979;&#20256;&#25773;&#12290;&#32780; <code>Task</code> &#21017;&#23436;&#20840;&#30456;&#21453;&#8212;&#8212;&#21487;&#20197;&#34987;&#38543;&#24847;&#21019;&#24314;&#21644;&#36951;&#24536;&#65292;&#20854;&#29983;&#21629;&#21608;&#26399;&#19982;&#35843;&#29992;&#32773;&#33073;&#38057;&#12290;</p><p>&#25991;&#31456;&#26368;&#21518;&#32473;&#20986;&#20102;&#19968;&#26465;&#39047;&#20855;&#23454;&#36341;&#24847;&#20041;&#30340;&#24314;&#35758;&#65306;&#33021;&#29992;&#38381;&#21253;&#23601;&#23613;&#37327;&#19981;&#29992; <code>Task</code>&#12290;&#23558;&#24037;&#20316;&#21333;&#20803;&#34920;&#36798;&#20026; <code>() async -&gt; Void</code>&#65292;&#30456;&#27604;&#20256;&#36882;&#19968;&#20010; <code>Task</code> &#23545;&#35937;&#65292;&#26356;&#31616;&#21333;&#12289;&#26356;&#26131;&#27979;&#35797;&#65292;&#21516;&#26102;&#21462;&#28040;&#34892;&#20026;&#20063;&#20250;&#33258;&#28982;&#32487;&#25215;&#33258;&#35843;&#29992;&#19978;&#19979;&#25991;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-03">.refreshable &#33258;&#24049;&#32456;&#32467;&#33258;&#24049;&#30340;&#38519;&#38449; (SwiftUI: Refreshable Task Cancellation)</a></strong></h3><p><code>.refreshable</code> &#25509;&#21463;&#19968;&#20010;&#24322;&#27493;&#38381;&#21253;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#22312;&#20854;&#20013;&#33719;&#21462;&#26032;&#25968;&#25454;&#24182;&#26356;&#26032;&#35270;&#22270;&#29366;&#24577;&#12290;&#20294;&#23427;&#26377;&#19968;&#20010;&#23481;&#26131;&#36393;&#21040;&#30340;&#38519;&#38449;&#65306;&#22914;&#26524;&#22312;&#38381;&#21253;&#25191;&#34892;&#36807;&#31243;&#20013;&#20462;&#25913;&#20102;&#39537;&#21160;&#24403;&#21069;&#35270;&#22270;&#30340; <code>@State</code>&#65292;&#30001;&#27492;&#35302;&#21457;&#30340;&#35270;&#22270;&#37325;&#32472;&#65292;&#21487;&#33021;&#20250;&#35753; refreshable &#30340;&#20219;&#21153;&#22312;&#23436;&#25104;&#21069;&#34987;&#21462;&#28040;&#12290;<a href="https://x.com/AntonGubarenko">Anton Gubarenko</a> &#22312;&#26412;&#25991;&#20013;&#23545;&#36825;&#19968;&#34892;&#20026;&#20570;&#20102;&#28165;&#26224;&#35299;&#37322;&#65306;<code>.refreshable</code> &#30340;&#20219;&#21153;&#29983;&#21629;&#21608;&#26399;&#19982;&#35270;&#22270;&#32465;&#23450;&#65292;&#24403;&#21047;&#26032;&#36807;&#31243;&#20013;&#35302;&#21457;&#37325;&#32472;&#26102;&#65292;SwiftUI &#21487;&#33021;&#25552;&#21069;&#32456;&#27490;&#35813;&#20219;&#21153;&#65292;&#20063;&#23601;&#26159;&#8220;&#20219;&#21153;&#34987;&#33258;&#24049;&#35302;&#21457;&#30340;&#26356;&#26032;&#25152;&#21462;&#28040;&#8221;&#12290;</p><p>&#20316;&#32773;&#32473;&#20986;&#20102;&#20004;&#31181;&#20462;&#22797;&#24605;&#36335;&#65306;&#35201;&#20040;&#23558;&#20013;&#38388;&#32467;&#26524;&#25910;&#38598;&#21040;&#26412;&#22320;&#21464;&#37327;&#65292;&#26368;&#21518;&#19968;&#27425;&#24615;&#26356;&#26032;&#29366;&#24577;&#65292;&#36991;&#20813;&#22810;&#27425;&#35302;&#21457;&#37325;&#32472;&#65307;&#35201;&#20040;&#23558;&#23454;&#38469;&#24037;&#20316;&#21253;&#35065;&#22312; <code>Task { }.value</code> &#20013;&#65292;&#20351;&#20854;&#20174;&#24403;&#21069;&#21047;&#26032;&#20219;&#21153;&#20013;&#8220;&#33073;&#31163;&#8221;&#65292;&#20174;&#32780;&#36991;&#20813;&#34987;&#35270;&#22270;&#29983;&#21629;&#21608;&#26399;&#25171;&#26029;&#12290;</p><blockquote><p><code>.refreshable</code> &#38754;&#20020;&#30340;&#38382;&#39064;&#65292;&#22312; <code>.task</code> &#20013;&#21516;&#26679;&#23384;&#22312;&#12290;&#36825;&#24182;&#19981;&#26159; Bug&#65292;&#32780;&#26159; SwiftUI &#23545;&#32467;&#26500;&#21270;&#24182;&#21457;&#30340;&#19968;&#31181;&#20855;&#20307;&#20307;&#29616;&#65306;&#24322;&#27493;&#20219;&#21153;&#20381;&#38468;&#20110;&#35270;&#22270;&#29983;&#21629;&#21608;&#26399;&#65292;&#24182;&#38543;&#20854;&#32467;&#26463;&#32780;&#34987;&#21462;&#28040;&#12290;&#22914;&#26524;&#27809;&#26377;&#24847;&#35782;&#21040;&#36825;&#19968;&#28857;&#65292;&#23601;&#24456;&#23481;&#26131;&#22312;&#29366;&#24577;&#26356;&#26032;&#19982;&#20219;&#21153;&#25191;&#34892;&#20043;&#38388;&#21046;&#36896;&#20986;&#8220;&#33258;&#25105;&#21462;&#28040;&#8221;&#30340;&#22330;&#26223;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-04">Swift 6.3 experimentalCGen &#25351;&#21335;&#65306;SwiftPM &#21407;&#29983;&#25903;&#25345; C &#20195;&#30721;&#29983;&#25104;</a></strong></h3><p>Swift 6.3 &#24341;&#20837;&#30340; <code>experimentalCGen</code> &#22635;&#34917;&#20102; SwiftPM &#38271;&#26399;&#20197;&#26469;&#30340;&#19968;&#20010;&#20851;&#38190;&#32570;&#21475;&#65306;Build Tool Plugin &#29983;&#25104;&#30340; C-family &#20135;&#29289;&#65292;&#32456;&#20110;&#21487;&#20197;&#30452;&#25509;&#21442;&#19982; C module target &#30340;&#32534;&#35793;&#65292;&#32780;&#19981;&#20877;&#20381;&#36182;&#22806;&#37096;&#33050;&#26412;&#25110;&#39044;&#25552;&#20132;&#30340;&#29983;&#25104;&#25991;&#20214;&#12290;&#36825;&#24847;&#21619;&#30528;&#23436;&#25972;&#30340;&#26500;&#24314;&#22270;&#21487;&#20197;&#22312; SwiftPM &#20869;&#38381;&#29615;&#8212;&#8212;&#26412;&#22320;&#12289;CI&#12289;Xcode &#20351;&#29992;&#21516;&#19968;&#22871;&#35268;&#21017;&#65292;&#19981;&#20877;&#21508;&#33258;&#32500;&#25252;&#19968;&#37096;&#20998;&#26500;&#24314;&#30693;&#35782;&#12290;<a href="https://x.com/RbBtSn0w">Snow</a> &#22312;&#26412;&#25991;&#20013;&#35814;&#32454;&#26803;&#29702;&#20102;&#20854;&#32972;&#26223;&#12289;&#29992;&#27861;&#19982;&#36801;&#31227;&#24605;&#36335;&#12290;</p><blockquote><p><code>experimentalCGen</code> &#30446;&#21069;&#20173;&#26377;&#26126;&#30830;&#38480;&#21046;&#65292;&#20363;&#22914;&#21516;&#19968; target &#21482;&#33021;&#26377;&#19968;&#20010;&#29983;&#25104;&#30340; module map&#65292;&#19988; module map &#24341;&#29992;&#30340; header &#38656;&#35201;&#20301;&#20110;&#21516;&#19968;&#30446;&#24405;&#12290;&#22240;&#27492;&#23427;&#26356;&#36866;&#21512;&#36793;&#30028;&#28165;&#26224;&#12289;&#36755;&#20986;&#31283;&#23450;&#30340;&#20195;&#30721;&#29983;&#25104;&#22330;&#26223;&#65292;&#32780;&#19981;&#26159;&#29992;&#26469;&#26367;&#20195;&#23436;&#25972;&#30340;&#21407;&#29983;&#26500;&#24314;&#31995;&#32479;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-05">&#23558; 300 &#20010;&#35270;&#22270;&#36801;&#31227;&#21040; SwiftUI &#21518;&#25152;&#23398;&#21040;&#30340; (How I migrated 300 screens to SwiftUI and what I learned)</a></strong></h3><p>&#23558; 300 &#20010;&#30028;&#38754;&#36801;&#31227;&#21040; SwiftUI&#65292;&#21548;&#36215;&#26469;&#20687;&#19968;&#27425;&#24443;&#24213;&#30340;&#36716;&#22411;&#65292;&#20294; <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> &#21450;&#20854;&#22242;&#38431;&#30340;&#31574;&#30053;&#21364;&#30456;&#24403;&#20811;&#21046;&#65306;SwiftUI &#21482;&#36127;&#36131; UI &#26500;&#24314;&#65292;&#23548;&#33322;&#20381;&#28982;&#30041;&#22312; UIKit&#12290;&#36825;&#31181;&#20998;&#23618;&#24182;&#38750;&#22949;&#21327;&#65292;&#32780;&#26159;&#26377;&#24847;&#20026;&#20043;&#8212;&#8212;&#35753;&#22242;&#38431;&#22312;&#20139;&#21463; SwiftUI &#24067;&#23616;&#19982;&#32452;&#20214;&#22797;&#29992;&#20248;&#21183;&#30340;&#21516;&#26102;&#65292;&#36991;&#20813;&#22312;&#23548;&#33322;&#12289;&#28145;&#38142;&#36335;&#21644;&#22797;&#26434;&#27969;&#31243;&#19978;&#24341;&#20837;&#19981;&#24517;&#35201;&#30340;&#39118;&#38505;&#12290;&#25991;&#31456;&#35760;&#24405;&#20102;&#36801;&#31227;&#20013;&#21453;&#22797;&#20986;&#29616;&#30340;&#38382;&#39064;&#65306;&#22242;&#38431;&#20064;&#24815;&#20102;&#21629;&#20196;&#24335;&#24605;&#32500;&#65292;&#24120;&#25226; SwiftUI &#24403;&#20316;&#8220;&#35821;&#27861;&#19981;&#21516;&#30340; UIKit&#8221;&#26469;&#20889;&#65307;<code>body</code> &#20013;&#22841;&#24102;&#21103;&#20316;&#29992;&#12289;&#23558; <code>onAppear</code> &#24403;&#20316; <code>viewDidLoad</code> &#20351;&#29992;&#12289;&#23884;&#22871; <code>ObservableObject</code> &#23548;&#33268;&#29366;&#24577;&#20256;&#25773;&#19981;&#22914;&#39044;&#26399;&#8230;&#8230;&#36825;&#20123;&#38382;&#39064;&#22312;&#36801;&#31227;&#36807;&#31243;&#20013;&#19968;&#20877;&#20986;&#29616;&#12290;&#32463;&#36807;&#25345;&#32493;&#30340;&#23457;&#26597;&#19982;&#20869;&#37096;&#24037;&#20316;&#22346;&#65292;&#22242;&#38431;&#26368;&#32456;&#27785;&#28096;&#20986;&#19968;&#22871;&#28165;&#26224;&#30340;&#26550;&#26500;&#26041;&#21521;&#65306;MVVM + &#26522;&#20030;&#39537;&#21160;&#30340;&#29366;&#24577;&#19982;&#20132;&#20114;&#24314;&#27169; + Use Case &#20998;&#31163;&#19994;&#21153;&#36923;&#36753;&#12290;</p><blockquote><p>&#21363;&#20415;&#19981;&#26159;&#36801;&#31227;&#39033;&#30446;&#65292;SwiftUI &#19982; UIKit &#28151;&#29992;&#20063;&#26159;&#19968;&#31181;&#29616;&#23454;&#19988;&#26377;&#25928;&#30340;&#36873;&#25321;&#12290;&#20004;&#20010;&#26694;&#26550;&#24182;&#38750;&#23545;&#31435;&#65292;&#28151;&#29992;&#26412;&#36523;&#19981;&#38590;&#65292;&#38590;&#30340;&#26159;&#22312;&#21508;&#33258;&#30340;&#24605;&#32500;&#27169;&#22411;&#19979;&#20889;&#20986;&#31526;&#21512;&#20854;&#35774;&#35745;&#24847;&#22270;&#30340;&#20195;&#30721;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0133-06">Mini Swift: &#32431; C &#20889;&#30340; Swift &#32534;&#35793;&#22120;</a></strong></h3><p>&#19968;&#20010;&#24456;&#26377;&#36259;&#19988;&#26497;&#20855;&#26497;&#23458;&#31934;&#31070;&#30340;&#39033;&#30446;&#12290;<a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> &#22312;&#19981;&#20351;&#29992; LLVM&#12289;Clang &#25110;&#33529;&#26524;&#20219;&#20309;&#23448;&#26041;&#24037;&#20855;&#38142;&#30340;&#24773;&#20917;&#19979;&#65292;&#21333;&#26538;&#21305;&#39532;&#29992; 7 &#19975;&#22810;&#34892; C &#35821;&#35328;&#8220;&#25163;&#25619;&#8221;&#20102;&#19968;&#20010;&#36731;&#37327;&#32423;&#30340; Swift &#32534;&#35793;&#22120;&#12290;&#20182;&#20174;&#35789;&#27861;&#20998;&#26512;&#12289;&#25277;&#35937;&#35821;&#27861;&#26641;&#19968;&#36335;&#20889;&#21040;&#20102;&#30452;&#25509;&#36755;&#20986; WASM &#30340;&#21518;&#31471;&#65292;&#20026;&#32593;&#39029;&#31471;&#24102;&#26469;&#20102; 0.1 &#27627;&#31186;&#32423;&#8220;&#31186;&#32534;&#35793;&#8221;&#30340;&#24778;&#20154;&#20307;&#39564;&#12290;&#22312;&#36825;&#20010;&#21160;&#36740;&#25289;&#20837;&#20960;&#30334;&#20806;&#20381;&#36182;&#21253;&#30340;&#26102;&#20195;&#65292;&#36825;&#31181;&#38646;&#20381;&#36182;&#30340;&#8220;&#24466;&#25163;&#36896;&#36718;&#23376;&#8221;&#34892;&#20026;&#26080;&#30097;&#26159;&#19968;&#31181;&#22797;&#21476;&#30340;&#28010;&#28459;&#12290;</p><p>&#36825;&#20010;&#39033;&#30446;&#28304;&#20110;&#20316;&#32773;&#19968;&#20010;&#31616;&#21333;&#21021;&#34935;&#65306;&#20570;&#19968;&#20010;&#19981;&#20250;&#23849;&#28291;&#30340; SwiftUI &#27983;&#35272;&#22120;&#39044;&#35272;&#12290;&#20316;&#32773;&#36879;&#38706;&#65292;&#20182;&#30446;&#21069;&#27491;&#22312;&#24320;&#21457;&#19968;&#20010;&#21517;&#20026; UIIR&#65288;UI &#20013;&#38388;&#34920;&#31034;&#65289;&#30340;&#23618;&#65292;&#26368;&#32456;&#30446;&#30340;&#26159;&#24819;&#25226; SwiftUI &#20195;&#30721;&#26144;&#23556;&#25104;&#19968;&#22871;&#24179;&#21488;&#26080;&#20851;&#30340;&#25351;&#20196;&#65292;&#30452;&#25509;&#22312; Web &#29978;&#33267; Android &#19978;&#28210;&#26579;&#20986;&#21407;&#29983;&#25928;&#26524;&#65292;&#20197;&#27492;&#26469;&#23436;&#25104;&#20182;&#26368;&#21021;&#30340;&#35774;&#24819;&#12290;</p><blockquote><p>&#35813;&#32534;&#35793;&#22120;&#21069;&#31471;&#30340;&#26680;&#24515;&#20195;&#30721;&#65288;&#35789;&#27861;&#12289;&#35821;&#27861;&#12289;&#35821;&#20041;&#20998;&#26512;&#65289;&#30446;&#21069;&#24050; <a href="https://github.com/toprakdeviren/msf">&#24320;&#28304;</a>&#12290;</p><p>&#22914;&#26524;&#32467;&#21512;&#32456;&#31471;&#29256;&#26412;&#30340; WASM &#36816;&#34892;&#26102;&#65288;&#22914; Wasmtime &#31561;&#65289;&#65292;&#25110;&#35768; Mini Swift &#21487;&#20197;&#22823;&#24133;&#25913;&#21892;&#30446;&#21069; Swift &#32534;&#20889;&#32456;&#31471;&#33050;&#26412;&#26102;&#20919;&#21551;&#21160;&#36807;&#24930;&#30340;&#30171;&#28857;&#65292;&#30495;&#27491;&#25552;&#21319; Swift &#30340;&#33050;&#26412;&#21270;&#20307;&#39564;&#12290;&#25105;&#24456;&#26399;&#24453;&#31038;&#21306;&#22312;&#36825;&#20010;&#26041;&#21521;&#19978;&#30340;&#23581;&#35797;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-07">Yotei: SwiftUI &#26085;&#21382;&#32452;&#20214;&#24211;</a></strong></h3><p>Yotei &#26159;&#19968;&#20010; iOS &#26085;&#21382;&#32452;&#20214;&#24211;&#65292;&#20316;&#32773;&#26159; <a href="https://www.linkedin.com/in/mikalai-zmachynski-36006010/">Mikalai Zmachynski</a>&#12290;&#39033;&#30446;&#25552;&#20379;&#20102; SwiftUI API&#65292;&#21516;&#26102;&#22312;&#26085;&#31243;&#21015;&#34920;&#12289;&#20998;&#39029;&#21644;&#26102;&#38388;&#36724;&#31561;&#39640;&#36127;&#36733;&#22330;&#26223;&#20013;&#20511;&#21161; UIKit &#20445;&#25345;&#28378;&#21160;&#24615;&#33021;&#12290;&#23427;&#26377; date picker&#12289;day timeline&#12289;month grid&#12289;schedule list &#31561;&#32452;&#20214;&#65292;&#20063;&#32473;&#20102;&#36739;&#32454;&#30340;&#23450;&#21046;&#20837;&#21475;&#12290;</p><p>Yotei &#23637;&#31034;&#20102;&#19968;&#31181;&#22312;&#22797;&#26434; SwiftUI &#32452;&#20214;&#20013;&#36234;&#26469;&#36234;&#24120;&#35265;&#30340;&#21462;&#33293;&#65306;SwiftUI &#36127;&#36131;&#32452;&#21512;&#12289;&#29366;&#24577;&#32465;&#23450;&#19982;&#25193;&#23637;&#28857;&#65292;UIKit &#36127;&#36131;&#26356;&#25104;&#29087;&#12289;&#31283;&#23450;&#30340;&#21015;&#34920;&#21644;&#20998;&#39029;&#20307;&#39564;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0133-08">Runtime Viewer</a></strong></h3><p>&#22914;&#26524;&#20320;&#36824;&#35760;&#24471; RuntimeBrowser&#65292;&#37027;&#20040; <a href="https://x.com/JH_Pointer">Mx-Iris</a> &#24320;&#21457;&#30340; Runtime Viewer &#21487;&#20197;&#30475;&#20316;&#23427;&#22312;&#20170;&#22825;&#33529;&#26524;&#24179;&#21488;&#35821;&#22659;&#19979;&#30340;&#19968;&#27425;&#29616;&#20195;&#21270;&#37325;&#20889;&#12290;&#23427;&#19981;&#20165;&#33021;&#27983;&#35272; Objective-C runtime &#20449;&#24687;&#65292;&#20063;&#25226; Swift &#31867;&#22411;&#12289;&#26522;&#20030;&#24067;&#23616;&#12289;VTable &#20559;&#31227;&#31561;&#20869;&#23481;&#32435;&#20837;&#20102;&#20998;&#26512;&#33539;&#22260;&#65292;&#24182;&#25552;&#20379;&#25509;&#36817; Xcode &#30340;&#20195;&#30721;&#38405;&#35835;&#20307;&#39564;&#12290;</p><p>&#23427;&#19981;&#21482;&#26159;&#8220;&#33021;&#30475;&#26356;&#22810;&#25509;&#21475;&#8221;&#65292;&#32780;&#26159;&#25226;&#36816;&#34892;&#26102;&#26816;&#26597;&#12289;&#36328;&#36827;&#31243;&#36890;&#20449;&#12289;&#20195;&#30721;&#27880;&#20837;&#12289;Bonjour &#35774;&#22791;&#21457;&#29616;&#65292;&#29978;&#33267; MCP &#25509;&#20837;&#25918;&#36827;&#20102;&#21516;&#19968;&#20010;&#24037;&#20855;&#37324;&#12290;&#23545;&#36870;&#21521;&#12289;&#23433;&#20840;&#30740;&#31350;&#12289;&#31995;&#32479; Framework &#23398;&#20064;&#65292;&#25110;&#32773;&#21482;&#26159;&#24819;&#29702;&#35299;&#26576;&#20010;&#20108;&#36827;&#21046;&#20869;&#37096;&#32467;&#26500;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#23427;&#37117;&#26356;&#20687;&#19968;&#20010;&#38754;&#21521;&#29616;&#20195; Apple &#24179;&#21488;&#30340; runtime inspection &#24037;&#20316;&#21488;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #132]]></title><description><![CDATA[From OpenSwiftUI to DanceUI: Another Way to Dive into SwiftUI]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-132</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-132</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 20 Apr 2026 12:03:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!m4Ir!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.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_!m4Ir!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m4Ir!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 424w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 848w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 1272w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m4Ir!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp" width="1456" height="965" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:965,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:136672,&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/194743370?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.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_!m4Ir!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 424w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 848w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.webp 1272w, https://substackcdn.com/image/fetch/$s_!m4Ir!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d0b96b9-42c5-4b88-9c89-1ff6ecd3bc55_1920x1273.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"><svg role="img" 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"><g><title></title><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"><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"><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/@carrier_lost?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ian Taylor</a> on <a href="https://unsplash.com/photos/a-one-way-sign-on-a-pole-on-a-city-street-h7b1SUEMPIs?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>From OpenSwiftUI to DanceUI: Another Way to Dive into SwiftUI</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-132/">Read on web &#8594;</a></p><p>Counting from its debut in 2019, SwiftUI is approaching its seventh year. It has long shed its initial growing pains and gradually become one of the foundational skills for developers in the Apple ecosystem. However, SwiftUI&#8217;s closed-source nature also means that many of its underlying mechanisms remain opaque. While developers can certainly feel its expressive advantages when using it, it&#8217;s often difficult to trace the root cause once a problem occurs. This characteristic also puts SwiftUI at a bit of a disadvantage in the era of AI-assisted programming&#8212;compared to technologies that have long been exposed in community discussions, source codes, and documentation, the high-quality materials available for large models to reference are ultimately limited.</p><p>Because of this, the community has always hoped to replicate SwiftUI through open-source projects: on the one hand, to give this excellent design a chance to run on more platforms; on the other hand, to gain a better understanding of SwiftUI&#8217;s internal mechanisms through the replication process. In recent years, the most highly-watched project in this regard is undoubtedly <a href="https://github.com/OpenSwiftUIProject/OpenSwiftUI">OpenSwiftUI</a>. Driven continuously by the community, it has already filled in some of the core implementations of SwiftUI and made experimental explorations on platforms outside the Apple ecosystem. Although it obviously still has a long way to go to reach its goal, it remains one of the most important gateways for developers today to understand SwiftUI&#8217;s internal mechanisms.</p><p>Actually, besides the community, some companies&#8212;even very large ones&#8212;have also conducted in-depth research and replication of SwiftUI over the past few years. Last week, ByteDance open-sourced their SwiftUI replication project, <a href="https://github.com/bytedance/DanceUI">DanceUI</a>.</p><p>I first heard about this project in 2022. What surprised me the most at the time wasn&#8217;t &#8220;someone is replicating SwiftUI,&#8221; but rather, &#8220;why is ByteDance doing this?&#8221; Later, after communicating with the developers involved in this project, I roughly understood their motives: on one hand, they wanted to gain stronger control when introducing declarative development into their massive product ecosystem; on the other hand, they hoped to grasp key capabilities like runtime, dependency graphs, and host integration in their own hands by studying excellent frameworks like SwiftUI. Compared to OpenSwiftUI, DanceUI looks less like a community-driven replica and more like a sample of reverse-engineering SwiftUI driven by practical engineering needs.</p><p>More importantly, over the past few years, DanceUI has already entered production environments in some product modules within ByteDance. This means it is clearly not just an experimental toy, but a set of development tools that have withstood a certain level of testing in terms of performance and stability. For SwiftUI developers, it therefore provides another gateway to understanding SwiftUI.</p><p>Of course, such projects shouldn&#8217;t be over-glorified. They are not SwiftUI itself, nor do they represent Apple&#8217;s official implementation. Projects like OpenSwiftUI, which are strongly research- and compatibility-oriented, naturally have clear boundaries; while projects like DanceUI carry an obvious background of large-tech internal engineering and practical application. Neither should be treated as the sole source of &#8220;SwiftUI truth.&#8221;</p><p>However, this does not prevent them from being excellent learning materials. None of them are SwiftUI, yet they can all help us get closer to it. Diving into SwiftUI by following open-source projects is essentially not about finding an &#8220;open-source alternative,&#8221; but rather using these projects to train our own way of understanding SwiftUI.</p><p><a href="https://fatbobman.com/en/weekly/issue-131/">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/w0132-01">Interface Segregation Principle In IOS: How To Prevent A Protocol From Becoming A Prison</a></strong></h3><p>Many developers have likely experienced a similar trajectory: a carefully designed small protocol in the early stages of a project gradually evolves into an unwieldy &#8220;monster&#8221; as team collaboration and business requirements grow. <a href="https://twitter.com/PawelKozielecki">Pawel Kozielecki</a> illustrates this through a progressively bloated <code>UserService</code>, showing how fat protocols introduce testing overhead, hidden coupling, and significant refactoring costs. Beyond proposing a practical approach based on smaller protocols and incremental migration, the article highlights a deeper issue: the real danger often lies not in a single flawed design decision, but in a series of seemingly reasonable &#8220;let&#8217;s just add this here for now&#8221; choices.</p><blockquote><p>In the era of AI-assisted programming, this problem can be further amplified. Large models tend to infer semantics from file and protocol names, and vague or overly broad naming naturally attracts more loosely related responsibilities. Clear, precise, and restrained naming is no longer just a matter of style&#8212;it increasingly defines system boundaries.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-02">Animating Strikethroughs in SwiftUI</a></strong></h3><p>How would you animate a strikethrough or underline in SwiftUI <code>Text</code>? A common first instinct is to use an overlay with Shape. However, this approach struggles with Dynamic Type and multi-line text. <a href="https://www.linkedin.com/in/ashlirankin/">Ashli Rankin</a> presents a more systematic solution: leveraging the <code>TextRenderer</code> API introduced in iOS 17 to access <code>Text.Layout</code> internals (lines, glyphs, etc.), and using a <code>progress</code> value accumulated across lines to draw a continuous, animatable strikethrough. By conforming to <code>Animatable</code>, SwiftUI can smoothly interpolate state changes.</p><p>An interesting detail: <code>TextField</code> does not use the same rendering pipeline as <code>Text</code>, so <code>TextRenderer</code> cannot be applied directly. The workaround involves overlaying a transparent <code>Text</code> (for rendering the animation) on top of a real <code>TextField</code>, combined with a custom <code>Layout</code> to enforce consistent wrapping width, ultimately resolving multi-line alignment issues.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-03">Checking accessibility with SwiftUI Previews</a></strong></h3><p>SwiftUI Previews are typically used to verify UI layout, but they can also help validate certain aspects of accessibility during development. <a href="https://www.linkedin.com/in/rob-whitaker/">Rob Whitaker</a> outlines several practical approaches: using Xcode Canvas to quickly toggle light/dark mode, orientation, and Dynamic Type, or defining specific environments via Preview Traits.</p><p>The article also highlights some <strong>private environment properties available only in Previews</strong> (such as increased contrast, reduced motion, or inverted colors), which can be enabled via underscored key paths. These must be restricted to <code>#if DEBUG</code> to avoid leaking private APIs into production builds.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-04">A UIKit Project&#8217;s SwiftUI Migration: A Practical Retrospective</a></strong></h3><p><a href="https://x.com/tobi462">Yusuke Hosonuma</a> reflects on his experience working on a UIKit + RxSwift + Coordinator project and gradually migrating most of its UI to SwiftUI over the course of a year. Rather than focusing on implementation details, the article centers on real-world engineering trade-offs: how a small team, with minimal communication and almost no documentation, can maintain long-term evolvability through continuous delivery, incremental replacement, and intentionally simple design.</p><p>The author also offers grounded reflections on common practices, such as being cautious with protocol abstraction, EnvironmentObject, premature generalization, and the urge to &#8220;clean up everything&#8221; during migration. This is less a technical guide and more a realistic retrospective on team practices and engineering judgment.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-05">Cancelling SwiftUI Animations: What Actually Works (And Why)</a></strong></h3><p>Stopping an in-flight <code>repeatForever</code> animation in SwiftUI is not as straightforward as it seems. Using <code>.none</code> or disabling animations via <code>Transaction</code> only affects new animations, not those already running in the rendering system. <a href="https://x.com/Codelaby">Codelaby</a> provides a working solution: defining a custom <code>CustomAnimation</code> that returns <code>nil</code> from <code>animate</code> (signaling immediate completion), and using <code>shouldMerge</code> to take over the current animation, effectively cancelling it.</p><blockquote><p>SwiftUI performs interpolation based on state changes and animation functions. &#8220;Stopping&#8221; an animation is essentially replacing it with a new state transition that takes control, rather than interrupting the existing animation.</p></blockquote><div><hr></div><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0132-06">Swift Institute: Rebuilding the Swift Ecosystem as a Solo Effort</a></strong></h3><p>An astonishing project discovered by chance. Over the past nine months, <a href="https://x.com/coenttb">Coen ten Thije Boonkkamp</a> has made nearly 9,800 commits, single-handedly building a Swift ecosystem of almost 300 packages across three layers: primitives, standards, and foundations. The goal is to realize his proposed <a href="https://coenttb.com/en/blog/4-1-the-swift-package">Modern Swift Library Architecture</a>: dependencies flow downward, integration happens outside core types, and &#8220;test what you own, trust what you import.&#8221;</p><p>One person, one idea, explored and validated with AI. Whether it ultimately succeeds or not, this is exactly the kind of exploration that demonstrates the real value of AI.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-07">swift-ast-lint: Writing Swift Lint Rules in Swift</a></strong></h3><p>Developed by <a href="https://x.com/ryu_hu03">Ryu</a>, <code>swift-ast-lint</code> is not another SwiftLint, but a custom linting infrastructure built on SwiftSyntax. It is designed for teams that need AST-level rules, filling the gap where regex-based approaches fall short.</p><p>The project supports scaffolding, parameterized rules, path filtering, and <code>--fix</code> auto-correction. It is well-suited for enforcing architectural constraints, code organization, and module boundaries&#8212;areas where regex is unreliable. While not ideal for out-of-the-box use, it is a strong option for teams with established conventions who want to formalize them as tooling.</p><blockquote><p>As AI-assisted development becomes more common, the real value may lie not only in generation, but in how we encode and enforce team constraints.</p></blockquote><div><hr></div><h2><strong>Event</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0132-08">Swift Craft 2026</a></strong></h3><p>Swift Craft is a community-driven iOS / Apple platform developer conference taking place May 18&#8211;20 in Folkestone, UK. The schedule is already available, covering topics across Swift, SwiftUI, and application architecture.</p><p>Compared to larger conferences, Swift Craft focuses more on small-scale, in-depth discussions and emphasizes a strong community atmosphere. One notable detail is the venue: <a href="https://maps.app.goo.gl/uvDHqTgGTbSQuWt67">Leas Cliff Hall</a>, perched on a seaside cliff with floor-to-ceiling windows overlooking the English Channel&#8212;an environment that naturally enhances the overall experience.</p><p>The organizers are offering a discount code <strong>FBM26 (&#163;50 off Indie tickets)</strong> for readers of this newsletter. If you&#8217;re considering attending a developer event in Europe, you can check the details via the <a href="https://l.fatbobman.com/w0132-08-t">Swift Craft tickets page</a>.</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-132?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-132?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#20174; OpenSwiftUI &#21040; DanceUI&#65306;&#25442;&#20010;&#26041;&#24335; Dive SwiftUI</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-132/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20174; 2019 &#24180;&#38382;&#19990;&#31639;&#36215;&#65292;SwiftUI &#24050;&#32463;&#24555;&#19971;&#24180;&#20102;&#12290;&#23427;&#26089;&#24050;&#33073;&#21435;&#20102;&#26368;&#21021;&#20960;&#24180;&#30340;&#31258;&#27668;&#65292;&#36880;&#28176;&#25104;&#20026;&#33529;&#26524;&#29983;&#24577;&#24320;&#21457;&#32773;&#30340;&#22522;&#30784;&#33021;&#21147;&#20043;&#19968;&#12290;&#19981;&#36807;&#65292;SwiftUI &#30340;&#38381;&#28304;&#23646;&#24615;&#20063;&#24847;&#21619;&#30528;&#65292;&#23427;&#30340;&#24456;&#22810;&#36816;&#34892;&#26426;&#21046;&#22987;&#32456;&#19981;&#36879;&#26126;&#12290;&#24320;&#21457;&#32773;&#22312;&#20351;&#29992;&#26102;&#22266;&#28982;&#33021;&#24863;&#21463;&#21040;&#23427;&#30340;&#34920;&#36798;&#20248;&#21183;&#65292;&#20294;&#19968;&#26086;&#36935;&#21040;&#38382;&#39064;&#65292;&#24448;&#24448;&#24456;&#38590;&#36827;&#19968;&#27493;&#36861;&#36394;&#21407;&#22240;&#12290;&#36825;&#31181;&#29305;&#24615;&#20063;&#35753; SwiftUI &#22312; AI &#36741;&#21161;&#32534;&#31243;&#26102;&#20195;&#26174;&#24471;&#26377;&#20123;&#8220;&#21507;&#20111;&#8221;&#8212;&#8212;&#30456;&#27604;&#37027;&#20123;&#38271;&#26399;&#26292;&#38706;&#22312;&#31038;&#21306;&#35752;&#35770;&#12289;&#28304;&#30721;&#21644;&#25991;&#26723;&#20013;&#30340;&#25216;&#26415;&#65292;&#22823;&#27169;&#22411;&#33021;&#21442;&#32771;&#30340;&#39640;&#36136;&#37327;&#26448;&#26009;&#32456;&#31350;&#26377;&#38480;&#12290;</p><p>&#20063;&#27491;&#22240;&#27492;&#65292;&#31038;&#21306;&#19968;&#30452;&#24076;&#26395;&#36890;&#36807;&#24320;&#28304;&#39033;&#30446;&#21435;&#22797;&#21051; SwiftUI&#65306;&#19968;&#26041;&#38754;&#65292;&#26159;&#24076;&#26395;&#35753; SwiftUI &#36825;&#22871;&#20248;&#31168;&#30340;&#35774;&#35745;&#26377;&#26426;&#20250;&#36816;&#34892;&#22312;&#26356;&#22810;&#24179;&#21488;&#19978;&#65307;&#21478;&#19968;&#26041;&#38754;&#65292;&#20063;&#26159;&#24076;&#26395;&#20511;&#21161;&#22797;&#21051;&#36807;&#31243;&#65292;&#23545; SwiftUI &#30340;&#20869;&#37096;&#26426;&#21046;&#33719;&#24471;&#26356;&#22810;&#29702;&#35299;&#12290;&#26368;&#36817;&#20960;&#24180;&#65292;&#36825;&#26041;&#38754;&#26368;&#21463;&#20851;&#27880;&#30340;&#39033;&#30446;&#26080;&#30097;&#26159; <a href="https://github.com/OpenSwiftUIProject/OpenSwiftUI">OpenSwiftUI</a>&#12290;&#22312;&#31038;&#21306;&#25345;&#32493;&#25512;&#36827;&#19979;&#65292;&#23427;&#24050;&#32463;&#34917;&#40784;&#20102; SwiftUI &#30340;&#19968;&#37096;&#20998;&#26680;&#24515;&#23454;&#29616;&#65292;&#24182;&#22312;&#33529;&#26524;&#29983;&#24577;&#20043;&#22806;&#30340;&#24179;&#21488;&#19978;&#20570;&#20986;&#20102;&#19968;&#20123;&#23454;&#39564;&#24615;&#25506;&#32034;&#12290;&#34429;&#28982;&#36317;&#31163;&#23427;&#30340;&#30446;&#26631;&#26174;&#28982;&#36824;&#26377;&#19981;&#30701;&#30340;&#36335;&#35201;&#36208;&#65292;&#20294;&#23427;&#20381;&#28982;&#26159;&#24403;&#19979;&#24320;&#21457;&#32773;&#29702;&#35299; SwiftUI &#20869;&#37096;&#26426;&#21046;&#30340;&#37325;&#35201;&#20837;&#21475;&#20043;&#19968;&#12290;</p><p>&#20854;&#23454;&#65292;&#38500;&#20102;&#31038;&#21306;&#20043;&#22806;&#65292;&#19968;&#20123;&#20844;&#21496;&#65292;&#29978;&#33267;&#35268;&#27169;&#24456;&#22823;&#30340;&#20844;&#21496;&#65292;&#20063;&#22312;&#36807;&#21435;&#20960;&#24180;&#37324;&#20570;&#36807;&#23545; SwiftUI &#30340;&#28145;&#20837;&#30740;&#31350;&#21644;&#22797;&#21051;&#12290;&#19978;&#21608;&#65292;&#23383;&#33410;&#36339;&#21160;&#24320;&#28304;&#20102;&#20182;&#20204;&#30340; SwiftUI &#22797;&#21051;&#39033;&#30446; <a href="https://github.com/bytedance/DanceUI">DanceUI</a>&#12290;</p><p>&#25105;&#31532;&#19968;&#27425;&#21548;&#35828;&#36825;&#20010;&#39033;&#30446;&#26159;&#22312; 2022 &#24180;&#12290;&#24403;&#26102;&#26368;&#35753;&#25105;&#24863;&#21040;&#24847;&#22806;&#30340;&#65292;&#19981;&#26159;&#8220;&#26377;&#20154;&#22312;&#22797;&#21051; SwiftUI&#8221;&#65292;&#32780;&#26159;&#8220;&#20026;&#20160;&#20040;&#26159;&#23383;&#33410;&#36339;&#21160;&#22312;&#20570;&#36825;&#20214;&#20107;&#8221;&#12290;&#21518;&#26469;&#38470;&#32493;&#21644;&#21442;&#19982;&#36825;&#20010;&#39033;&#30446;&#30340;&#24320;&#21457;&#32773;&#20132;&#27969;&#21518;&#65292;&#25105;&#22823;&#33268;&#29702;&#35299;&#20102;&#20182;&#20204;&#30340;&#21160;&#26426;&#65306;&#19968;&#26041;&#38754;&#65292;&#20182;&#20204;&#24076;&#26395;&#22312;&#23558;&#22768;&#26126;&#24335;&#24320;&#21457;&#24341;&#20837;&#24222;&#22823;&#20135;&#21697;&#20307;&#31995;&#26102;&#33719;&#24471;&#26356;&#24378;&#30340;&#25511;&#21046;&#21147;&#65307;&#21478;&#19968;&#26041;&#38754;&#65292;&#20063;&#24076;&#26395;&#20511;&#30001;&#23545; SwiftUI &#36825;&#31867;&#20248;&#31168;&#26694;&#26550;&#30340;&#30740;&#31350;&#65292;&#25226;&#36816;&#34892;&#26102;&#12289;&#20381;&#36182;&#22270;&#21644;&#23487;&#20027;&#25972;&#21512;&#31561;&#20851;&#38190;&#33021;&#21147;&#25569;&#22312;&#33258;&#24049;&#25163;&#37324;&#12290;&#21644; OpenSwiftUI &#30456;&#27604;&#65292;DanceUI &#26356;&#19981;&#20687;&#19968;&#20010;&#31038;&#21306;&#24335;&#22797;&#21051;&#39033;&#30446;&#65292;&#32780;&#26356;&#20687;&#19968;&#22871;&#20174;&#24037;&#31243;&#33853;&#22320;&#20986;&#21457;&#12289;&#21453;&#21521;&#25286;&#35299; SwiftUI &#30340;&#26679;&#26412;&#12290;</p><p>&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#36807;&#21435;&#20960;&#24180;&#20013;&#65292;DanceUI &#24050;&#32463;&#22312;&#23383;&#33410;&#20869;&#37096;&#30340;&#19968;&#20123;&#20135;&#21697;&#27169;&#22359;&#20013;&#36827;&#20837;&#20102;&#29983;&#20135;&#29615;&#22659;&#12290;&#36825;&#24847;&#21619;&#30528;&#23427;&#26174;&#28982;&#19981;&#21482;&#26159;&#19968;&#20010;&#23454;&#39564;&#24615;&#30340;&#29609;&#20855;&#65292;&#32780;&#26159;&#19968;&#22871;&#22312;&#24615;&#33021;&#21644;&#31283;&#23450;&#24615;&#19978;&#37117;&#32463;&#21463;&#36807;&#19968;&#23450;&#26816;&#39564;&#30340;&#24320;&#21457;&#24037;&#20855;&#12290;&#23545;&#20110; SwiftUI &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#23427;&#20063;&#22240;&#27492;&#25552;&#20379;&#20102;&#21478;&#19968;&#20010;&#29702;&#35299; SwiftUI &#30340;&#20837;&#21475;&#12290;</p><p>&#24403;&#28982;&#65292;&#36825;&#31867;&#39033;&#30446;&#24182;&#19981;&#36866;&#21512;&#34987;&#31616;&#21333;&#31070;&#21270;&#12290;&#23427;&#20204;&#19981;&#26159; SwiftUI &#26412;&#36523;&#65292;&#20063;&#19981;&#20195;&#34920;&#33529;&#26524;&#23448;&#26041;&#23454;&#29616;&#12290;&#23588;&#20854;&#20687; OpenSwiftUI &#36825;&#26679;&#24102;&#26377;&#24378;&#28872;&#30740;&#31350;&#21644;&#20860;&#23481;&#24615;&#23548;&#21521;&#30340;&#39033;&#30446;&#65292;&#26412;&#36523;&#23601;&#26377;&#26126;&#30830;&#36793;&#30028;&#65307;&#32780;&#20687; DanceUI &#36825;&#26679;&#30340;&#39033;&#30446;&#65292;&#21017;&#24102;&#30528;&#26126;&#26174;&#30340;&#22823;&#21378;&#20869;&#37096;&#24037;&#31243;&#32972;&#26223;&#21644;&#33853;&#22320;&#21462;&#21521;&#12290;&#23427;&#20204;&#37117;&#19981;&#24212;&#35813;&#34987;&#24403;&#25104;&#8220;SwiftUI &#30495;&#30456;&#8221;&#30340;&#21807;&#19968;&#26469;&#28304;&#12290;</p><p>&#20294;&#36825;&#24182;&#19981;&#22952;&#30861;&#23427;&#20204;&#25104;&#20026;&#24456;&#22909;&#30340;&#23398;&#20064;&#26448;&#26009;&#12290;&#23427;&#20204;&#37117;&#19981;&#26159; SwiftUI&#65292;&#21364;&#37117;&#33021;&#24110;&#21161;&#25105;&#20204;&#26356;&#25509;&#36817; SwiftUI&#12290;&#36319;&#30528;&#24320;&#28304;&#39033;&#30446;&#21435; dive SwiftUI&#65292;&#26412;&#36136;&#19978;&#19981;&#26159;&#22312;&#25214;&#19968;&#20010;&#8220;&#24320;&#28304;&#26367;&#20195;&#21697;&#8221;&#65292;&#32780;&#26159;&#22312;&#20511;&#36825;&#20123;&#39033;&#30446;&#35757;&#32451;&#33258;&#24049;&#29702;&#35299; SwiftUI &#30340;&#26041;&#24335;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-131/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0132-01">&#21035;&#35753;&#21327;&#35758;&#21464;&#25104;&#8220;&#24618;&#29289;&#8221;&#65306;iOS &#20013;&#30340;&#25509;&#21475;&#38548;&#31163;&#23454;&#36341; (Interface Segregation Principle In IOS: How To Prevent A Protocol From Becoming A Prison)</a></strong></h3><p>&#24456;&#22810;&#24320;&#21457;&#32773;&#21487;&#33021;&#37117;&#32463;&#21382;&#36807;&#31867;&#20284;&#30340;&#36807;&#31243;&#65306;&#39033;&#30446;&#26089;&#26399;&#19968;&#20010;&#31934;&#24515;&#35774;&#35745;&#30340;&#23567;&#21327;&#35758;&#65292;&#38543;&#30528;&#22242;&#38431;&#21327;&#20316;&#19982;&#19994;&#21153;&#28436;&#36827;&#65292;&#36880;&#28176;&#33192;&#32960;&#20026;&#38590;&#20197;&#32500;&#25252;&#30340;&#8220;&#24618;&#29289;&#8221;&#12290;<a href="https://twitter.com/PawelKozielecki">Pawel Kozielecki</a> &#36890;&#36807;&#19968;&#20010;&#36880;&#27493;&#22833;&#25511;&#30340; <code>UserService</code> &#26696;&#20363;&#65292;&#20855;&#20307;&#23637;&#31034;&#20102;&#32982;&#21327;&#35758;&#22914;&#20309;&#22312;&#22242;&#38431;&#21327;&#20316;&#20013;&#24341;&#20837;&#27979;&#35797;&#36127;&#25285;&#12289;&#38544;&#24615;&#32806;&#21512;&#65292;&#20197;&#21450;&#38590;&#20197;&#25512;&#36827;&#30340;&#37325;&#26500;&#25104;&#26412;&#12290;&#20316;&#32773;&#19981;&#20165;&#32473;&#20986;&#20102;&#22522;&#20110;&#23567;&#21327;&#35758;&#32452;&#21512;&#19982;&#28176;&#36827;&#36801;&#31227;&#30340;&#29616;&#23454;&#26041;&#26696;&#65292;&#20063;&#28857;&#20986;&#20102;&#38382;&#39064;&#30340;&#26681;&#28304;&#65306;&#30495;&#27491;&#21361;&#38505;&#30340;&#65292;&#24448;&#24448;&#19981;&#26159;&#19968;&#27425;&#26126;&#26174;&#30340;&#35774;&#35745;&#22833;&#35823;&#65292;&#32780;&#26159;&#19968;&#36830;&#20018;&#8220;&#36825;&#27425;&#20808;&#21152;&#36827;&#21435;&#20063;&#27809;&#20851;&#31995;&#8221;&#30340;&#21512;&#29702;&#20915;&#23450;&#12290;</p><blockquote><p>&#22312; AI &#36741;&#21161;&#32534;&#31243;&#26085;&#30410;&#26222;&#21450;&#30340;&#32972;&#26223;&#19979;&#65292;&#36825;&#19968;&#38382;&#39064;&#21453;&#32780;&#26356;&#23481;&#26131;&#34987;&#25918;&#22823;&#12290;&#22823;&#27169;&#22411;&#20542;&#21521;&#20110;&#20381;&#25454;&#25991;&#20214;&#21517;&#12289;&#21327;&#35758;&#21517;&#36827;&#34892;&#35821;&#20041;&#25512;&#26029;&#65292;&#19968;&#20010;&#27169;&#31946;&#25110;&#36807;&#20110;&#23485;&#27867;&#30340;&#21629;&#21517;&#65292;&#24448;&#24448;&#20250;&#33258;&#28982;&#22320;&#21560;&#24341;&#26356;&#22810;&#8220;&#19981;&#37027;&#20040;&#30456;&#20851;&#8221;&#30340;&#32844;&#36131;&#34987;&#19981;&#26029;&#21472;&#21152;&#36827;&#21435;&#12290;&#28165;&#26224;&#12289;&#20934;&#30830;&#19988;&#20811;&#21046;&#30340;&#21629;&#21517;&#65292;&#27491;&#22312;&#20174;&#20195;&#30721;&#39118;&#26684;&#38382;&#39064;&#65292;&#36880;&#28176;&#28436;&#21464;&#20026;&#24433;&#21709;&#31995;&#32479;&#36793;&#30028;&#30340;&#37325;&#35201;&#22240;&#32032;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-02">&#20026; Text &#23454;&#29616;&#21024;&#38500;&#32447;&#21160;&#30011; (Animating Strikethroughs in SwiftUI)</a></strong></h3><p>&#20026; SwiftUI <code>Text</code> &#30340;&#21024;&#38500;&#32447;&#25110;&#19979;&#21010;&#32447;&#23454;&#29616;&#21160;&#30011;&#25928;&#26524;&#65311;&#19981;&#23569;&#20154;&#31532;&#19968;&#21453;&#24212;&#21487;&#33021;&#26159;&#22522;&#20110; overlay + Shape &#30340;&#26041;&#26696;&#12290;&#19981;&#36807;&#65292;&#36825;&#31181;&#26041;&#24335;&#24456;&#38590;&#27491;&#30830;&#36866;&#37197; Dynamic Type &#20197;&#21450;&#22810;&#34892;&#25991;&#26412;&#22330;&#26223;&#12290;<a href="https://www.linkedin.com/in/ashlirankin/">Ashli Rankin</a> &#23637;&#31034;&#20102;&#19968;&#26465;&#26356;&#8220;&#31995;&#32479;&#21270;&#8221;&#30340;&#36335;&#24452;&#65306;&#22522;&#20110; iOS 17 &#24341;&#20837;&#30340; <code>TextRenderer</code>&#65292;&#30452;&#25509;&#35775;&#38382; <code>Text.Layout</code> &#30340;&#20869;&#37096;&#32467;&#26500;&#65288;&#34892;&#12289;glyph &#31561;&#65289;&#65292;&#24182;&#36890;&#36807;&#19968;&#20010; <code>progress</code> &#20540;&#22312;&#25152;&#26377;&#34892;&#20043;&#38388;&#32047;&#35745;&#32472;&#21046;&#65292;&#20174;&#32780;&#23454;&#29616;&#36830;&#32493;&#12289;&#21487;&#21160;&#30011;&#30340;&#21024;&#38500;&#32447;&#25928;&#26524;&#12290;&#21516;&#26102;&#36890;&#36807;&#23454;&#29616; <code>Animatable</code>&#65292;&#35753; SwiftUI &#22312;&#29366;&#24577;&#21464;&#21270;&#26102;&#33258;&#21160;&#23436;&#25104;&#25554;&#20540;&#36807;&#28193;&#12290;</p><p>&#19968;&#20010;&#26356;&#26377;&#24847;&#24605;&#30340;&#32454;&#33410;&#22312;&#20110;&#65306;<code>TextField</code> &#24182;&#19981;&#20250;&#36208; <code>Text</code> &#30340;&#28210;&#26579;&#27969;&#31243;&#65292;&#22240;&#27492; <code>TextRenderer</code> &#26080;&#27861;&#30452;&#25509;&#24212;&#29992;&#12290;&#20316;&#32773;&#36890;&#36807;&#21472;&#21152;&#19968;&#20010;&#36879;&#26126;&#30340; <code>Text</code>&#65288;&#36127;&#36131;&#32472;&#21046;&#21160;&#30011;&#65289;&#19982;&#30495;&#23454;&#30340; <code>TextField</code>&#65292;&#24182;&#32467;&#21512;&#33258;&#23450;&#20041; <code>Layout</code> &#24378;&#21046;&#20004;&#32773;&#20351;&#29992;&#19968;&#33268;&#30340;&#25442;&#34892;&#23485;&#24230;&#65292;&#26368;&#32456;&#35299;&#20915;&#20102;&#22810;&#34892;&#38169;&#20301;&#38382;&#39064;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-03">&#22312; SwiftUI &#39044;&#35272;&#20013;&#39564;&#35777;&#21487;&#35775;&#38382;&#24615; (Checking accessibility with SwiftUI Previews)</a></strong></h3><p>SwiftUI Previews &#36890;&#24120;&#29992;&#20110;&#26816;&#26597;&#30028;&#38754;&#24067;&#23616;&#65292;&#20294;&#21516;&#26679;&#21487;&#20197;&#22312;&#24320;&#21457;&#38454;&#27573;&#24555;&#36895;&#39564;&#35777;&#37096;&#20998;&#21487;&#35775;&#38382;&#24615;&#65288;Accessibility&#65289;&#34920;&#29616;&#12290;<a href="https://www.linkedin.com/in/rob-whitaker/">Rob Whitake</a> &#26803;&#29702;&#20102;&#20960;&#31181;&#24120;&#29992;&#36884;&#24452;&#65306;&#20363;&#22914;&#36890;&#36807; Xcode Canvas &#30452;&#25509;&#20999;&#25442;&#28145;&#27973;&#33394;&#12289;&#26041;&#21521;&#12289;Dynamic Type &#31561;&#36827;&#34892;&#24555;&#36895;&#26816;&#26597;&#65292;&#25110;&#20511;&#21161; Preview Traits &#23450;&#20041;&#29305;&#23450;&#30340;&#39044;&#35272;&#29615;&#22659;&#12290;&#25991;&#31456;&#36824;&#25552;&#21040;&#20102;&#19968;&#20123;<strong>&#20165;&#29992;&#20110; Preview &#30340;&#31169;&#26377;&#29615;&#22659;&#21464;&#37327;</strong>&#65288;&#22914;&#22686;&#24378;&#23545;&#27604;&#24230;&#12289;&#20943;&#23569;&#21160;&#30011;&#12289;&#39068;&#33394;&#21453;&#36716;&#31561;&#65289;&#65292;&#36890;&#36807;&#24102;&#19979;&#21010;&#32447;&#30340; keyPath &#21487;&#20197;&#24378;&#21046;&#24320;&#21551;&#36825;&#20123;&#29366;&#24577;&#12290;&#19981;&#36807;&#38656;&#35201;&#27880;&#24847;&#65292;&#36825;&#31867; API &#24517;&#39035;&#38480;&#21046;&#22312; <code>#if DEBUG</code> &#20013;&#20351;&#29992;&#65292;&#20197;&#36991;&#20813;&#31169;&#26377;&#31526;&#21495;&#36827;&#20837;&#26368;&#32456;&#26500;&#24314;&#65292;&#24102;&#26469;&#23457;&#26680;&#39118;&#38505;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-04">&#19968;&#20010; UIKit &#39033;&#30446;&#30340; SwiftUI &#36801;&#31227;&#23454;&#24405;</a></strong></h3><p><a href="https://x.com/tobi462">Yusuke Hosonuma</a> &#22238;&#39038;&#20102;&#33258;&#24049;&#21442;&#19982;&#19968;&#20010; UIKit + RxSwift + Coordinator &#39033;&#30446;&#65292;&#24182;&#22312;&#19968;&#24180;&#22810;&#26102;&#38388;&#37324;&#36880;&#27493;&#23436;&#25104;&#22823;&#37096;&#20998;&#30028;&#38754; SwiftUI &#21270;&#30340;&#32463;&#21382;&#12290;&#25991;&#31456;&#32858;&#28966;&#20110;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#24037;&#31243;&#21462;&#33293;&#65306;&#22312;&#23567;&#22242;&#38431;&#12289;&#20302;&#27807;&#36890;&#12289;&#20960;&#20046;&#26080;&#25991;&#26723;&#30340;&#26465;&#20214;&#19979;&#65292;&#22914;&#20309;&#36890;&#36807;&#25345;&#32493;&#20132;&#20184;&#12289;&#28176;&#36827;&#26367;&#25442;&#19982;&#23613;&#37327;&#31616;&#21333;&#30340;&#35774;&#35745;&#65292;&#35753;&#39033;&#30446;&#20445;&#25345;&#21487;&#28436;&#36827;&#24615;&#12290;&#20316;&#32773;&#23545;&#19981;&#23569;&#24120;&#35265;&#20570;&#27861;&#37117;&#32473;&#20986;&#20102;&#24456;&#26377;&#29616;&#23454;&#24863;&#30340;&#21453;&#24605;&#65292;&#20363;&#22914;&#35880;&#24910;&#23545;&#24453; protocol &#25277;&#35937;&#12289;EnvironmentObject&#12289;&#36807;&#26089;&#20849;&#36890;&#21270;&#65292;&#20197;&#21450;&#8220;&#39034;&#25163;&#28165;&#29702;&#19968;&#20999;&#26087;&#26550;&#26500;&#8221;&#30340;&#20914;&#21160;&#12290;&#36825;&#24182;&#38750;&#21333;&#32431;&#30340;&#25216;&#26415;&#23454;&#29616;&#24635;&#32467;&#65292;&#32780;&#26159;&#19968;&#31687;&#20805;&#28385;&#30495;&#23454;&#24863;&#30340;&#22242;&#38431;&#23454;&#36341;&#22797;&#30424;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-05">&#22914;&#20309;&#20572;&#27490;&#19968;&#20010;&#36816;&#34892;&#20013;&#30340; SwiftUI &#21160;&#30011; Cancelling SwiftUI Animations: What Actually Works (And Why)</a></strong></h3><p>&#22312; SwiftUI &#20013;&#65292;&#20572;&#27490;&#19968;&#20010;&#24050;&#32463;&#36816;&#34892;&#30340; <code>repeatForever</code> &#21160;&#30011;&#24182;&#19981;&#20687;&#24819;&#35937;&#20013;&#37027;&#20040;&#31616;&#21333;&#12290;&#26080;&#35770;&#26159;&#20351;&#29992; <code>.none</code>&#65292;&#36824;&#26159;&#36890;&#36807; <code>Transaction</code> &#31105;&#29992;&#21160;&#30011;&#65292;&#37117;&#21482;&#33021;&#24433;&#21709;&#26032;&#30340;&#21160;&#30011;&#65292;&#32780;&#26080;&#27861;&#20013;&#26029;&#24050;&#32463;&#23384;&#22312;&#20110;&#28210;&#26579;&#31995;&#32479;&#20013;&#30340;&#21160;&#30011;&#12290;<a href="https://x.com/Codelaby">Codelaby</a> &#32473;&#20986;&#20102;&#19968;&#20010;&#21487;&#34892;&#26041;&#26696;&#65306;&#36890;&#36807;&#33258;&#23450;&#20041; <code>CustomAnimation</code>&#65292;&#35753; <code>animate</code> &#36820;&#22238; <code>nil</code>&#65288;&#34920;&#31034;&#31435;&#21363;&#23436;&#25104;&#65289;&#65292;&#24182;&#36890;&#36807; <code>shouldMerge</code> &#25509;&#31649;&#24403;&#21069;&#21160;&#30011;&#65292;&#20174;&#32780;&#23454;&#29616;&#32456;&#27490;&#21160;&#30011;&#30340;&#25928;&#26524;&#12290;</p><blockquote><p>SwiftUI &#20250;&#22522;&#20110;&#29366;&#24577;&#21464;&#21270;&#19982;&#21160;&#30011;&#20989;&#25968;&#33258;&#21160;&#36827;&#34892;&#25554;&#20540;&#35745;&#31639;&#12290;&#25152;&#35859;&#8220;&#20572;&#27490;&#8221;&#65292;&#26412;&#36136;&#19978;&#26159;&#29992;&#19968;&#20010;&#26032;&#30340;&#29366;&#24577;&#21464;&#21270;&#21435;&#25509;&#31649;&#24403;&#21069;&#21160;&#30011;&#65292;&#32780;&#19981;&#26159;&#20013;&#26029;&#20043;&#21069;&#30340;&#21160;&#30011;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0132-06">Swift Institute: &#19968;&#20010;&#20154;&#30340; Swift &#22522;&#30784;&#35774;&#26045;&#37325;&#20889;</a></strong></h3><p>&#20598;&#28982;&#30475;&#21040;&#30340;&#19968;&#20010;&#35753;&#25105;&#38663;&#24778;&#30340;&#39033;&#30446;&#12290;<a href="https://x.com/coenttb">Coen ten Thije Boonkkamp</a> &#22312;&#36807;&#21435; 9 &#20010;&#26376;&#37324;&#25552;&#20132;&#20102;&#32422; 9800 &#27425; git commit&#65292;&#29420;&#33258;&#26500;&#24314;&#20102;&#19968;&#20010;&#20998;&#20026; primitives&#12289;standards&#12289;foundations &#19977;&#23618;&#12289;&#32047;&#35745;&#36817; 300 &#20010;&#21253;&#30340; Swift &#29983;&#24577;&#12290;&#30446;&#26631;&#21482;&#26377;&#19968;&#20010;&#8212;&#8212;&#33853;&#22320;&#20182;&#21435;&#24180;&#25552;&#20986;&#30340; <a href="https://coenttb.com/en/blog/4-1-the-swift-package">Modern Swift Library Architecture</a> &#24605;&#24819;&#65306;&#20381;&#36182;&#21482;&#33021;&#21521;&#19979;&#12289;&#38598;&#25104;&#21457;&#29983;&#22312;&#26680;&#24515;&#31867;&#22411;&#20043;&#22806;&#12289;&#8221;test what you own, trust what you import&#8221;&#12290;</p><p>&#19968;&#20010;&#20154;&#12289;&#19968;&#20010;&#26500;&#24819;&#65292;&#36890;&#36807; AI &#26469;&#36827;&#34892;&#23581;&#35797;&#12289;&#39564;&#35777;&#12290;&#26080;&#35770;&#26368;&#21518;&#26159;&#21542;&#25104;&#21151;&#65292;&#20294;&#36825;&#26159;&#25105;&#24819;&#30475;&#21040;&#30340; AI &#24847;&#20041;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0132-07">swift-ast-lint&#65306;&#29992; Swift &#20889; Swift &#20195;&#30721;&#26816;&#26597;&#35268;&#21017;</a></strong></h3><p>&#30001; <a href="https://x.com/ryu_hu03">Ryu</a> &#24320;&#21457;&#30340; <code>swift-ast-lint</code> &#19981;&#26159;&#21478;&#19968;&#20010; SwiftLint&#65292;&#32780;&#26159;&#19968;&#22871;&#22522;&#20110; SwiftSyntax &#30340;&#33258;&#23450;&#20041; lint &#22522;&#30784;&#35774;&#26045;&#12290;&#23427;&#26356;&#36866;&#21512;&#38656;&#35201;&#32534;&#20889; AST &#32423;&#35268;&#21017;&#30340;&#22242;&#38431;&#65292;&#29992;&#26469;&#34917;&#36275;&#27491;&#21017;&#21305;&#37197;&#22312;&#32467;&#26500;&#21270;&#26816;&#26597;&#19978;&#30340;&#23616;&#38480;&#12290;</p><p>&#39033;&#30446;&#25903;&#25345;&#33050;&#25163;&#26550;&#29983;&#25104;&#12289;&#21442;&#25968;&#21270;&#35268;&#21017;&#12289;&#36335;&#24452;&#36807;&#28388;&#20197;&#21450; <code>--fix</code> &#33258;&#21160;&#20462;&#22797;&#65292;&#27604;&#36739;&#36866;&#21512;&#22788;&#29702;&#26550;&#26500;&#32422;&#26463;&#12289;&#20195;&#30721;&#32452;&#32455;&#12289;&#27169;&#22359;&#36793;&#30028;&#31561; <code>regex</code> &#24456;&#38590;&#21487;&#38752;&#35206;&#30422;&#30340;&#38382;&#39064;&#12290;&#23427;&#19981;&#22826;&#36866;&#21512;&#21482;&#24819;&#24320;&#31665;&#21363;&#29992;&#30340;&#29992;&#25143;&#65292;&#20294;&#23545;&#20110;&#24050;&#32463;&#26377;&#26126;&#30830;&#24037;&#31243;&#35268;&#33539;&#12289;&#21448;&#24076;&#26395;&#25226;&#36825;&#20123;&#35268;&#33539;&#24037;&#20855;&#21270;&#30340; Swift &#22242;&#38431;&#26469;&#35828;&#65292;&#26159;&#19968;&#20010;&#20540;&#24471;&#20851;&#27880;&#30340;&#39033;&#30446;&#12290;</p><blockquote><p>&#22312; AI &#36741;&#21161;&#24320;&#21457;&#36234;&#26469;&#36234;&#26222;&#36941;&#20043;&#21518;&#65292;&#30495;&#27491;&#26377;&#20215;&#20540;&#30340;&#21487;&#33021;&#19981;&#21482;&#26159;&#29983;&#25104;&#33021;&#21147;&#26412;&#36523;&#65292;&#36824;&#21253;&#25324;&#22914;&#20309;&#25226;&#22242;&#38431;&#35268;&#33539;&#21644;&#32467;&#26500;&#32422;&#26463;&#24037;&#20855;&#21270;&#12290;</p></blockquote><h2><strong>&#27963;&#21160;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0132-08">Swift Craft 2026</a></strong></h3><p>Swift Craft &#26159;&#19968;&#20010;&#30001;&#31038;&#21306;&#39537;&#21160;&#30340; iOS / Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#22823;&#20250;&#65292;&#23558;&#20110; 5 &#26376; 18&#8211;20 &#26085;&#22312;&#33521;&#22269; Folkestone &#20030;&#34892;&#12290;&#30446;&#21069;&#35758;&#31243;&#24050;&#32463;&#20844;&#24067;&#65292;&#28085;&#30422; Swift&#12289;SwiftUI &#20197;&#21450;&#24212;&#29992;&#26550;&#26500;&#31561;&#22810;&#20010;&#26041;&#21521;&#12290;</p><p>&#30456;&#27604;&#22823;&#22411;&#20250;&#35758;&#65292;Swift Craft &#26356;&#20559;&#21521;&#23567;&#35268;&#27169;&#19982;&#28145;&#24230;&#20132;&#27969;&#65292;&#20063;&#26356;&#24378;&#35843;&#24320;&#21457;&#32773;&#20043;&#38388;&#30340;&#31038;&#21306;&#27675;&#22260;&#12290;&#19968;&#20010;&#26377;&#36259;&#30340;&#32454;&#33410;&#26159;&#26412;&#27425;&#20250;&#35758;&#30340;&#22330;&#22320;&#65306;&#20301;&#20110;&#28023;&#36793;&#24748;&#23830;&#19978;&#30340; <a href="https://maps.app.goo.gl/uvDHqTgGTbSQuWt67">Leas Cliff Hall</a>&#65292;&#20250;&#22330;&#19977;&#38754;&#33853;&#22320;&#31383;&#30452;&#38754;&#33521;&#21513;&#21033;&#28023;&#23777;&#65292;&#36825;&#31181;&#29615;&#22659;&#26412;&#36523;&#23601;&#36275;&#20197;&#35753;&#20250;&#35758;&#20307;&#39564;&#21464;&#24471;&#19982;&#20247;&#19981;&#21516;&#12290;</p><p>&#20027;&#21150;&#26041;&#20026;&#26412;&#21608;&#25253;&#35835;&#32773;&#25552;&#20379;&#20102;&#25240;&#25187;&#30721; <strong>FBM26&#65288;&#163;50 off Indie &#31080;&#65289;</strong>&#12290;&#22914;&#26524;&#20320;&#26377;&#21442;&#19982;&#32447;&#19979;&#24320;&#21457;&#32773;&#27963;&#21160;&#30340;&#35745;&#21010;&#65292;&#21487;&#20197;&#36890;&#36807; <a href="https://l.fatbobman.com/w0132-08-t">Swift Craft tickets page</a> &#20102;&#35299;&#35814;&#24773;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #131]]></title><description><![CDATA[Copyright Walls Demolished by Vibe Coding, and the Developer's New Moat]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-131</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-131</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 13 Apr 2026 12:03:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XVoV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.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_!XVoV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XVoV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 424w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 848w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 1272w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XVoV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp" width="1456" height="896" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:896,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14340,&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/194017694?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.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_!XVoV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 424w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 848w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.webp 1272w, https://substackcdn.com/image/fetch/$s_!XVoV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91e7d9ff-13f0-4ffc-9150-e0ece655730b_1920x1182.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"><svg role="img" 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"><g><title></title><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"><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"><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/@helloimnik?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nik</a> on <a href="https://unsplash.com/photos/yellow-and-white-round-plastic-toy-zYdYz7JlevE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Copyright Walls Demolished by Vibe Coding, and the Developer&#8217;s New Moat</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-131/">Read on web &#8594;</a></p><p>Anthropic recently announced that because its latest model, Mythos, has become &#8220;too powerful&#8221; at cybersecurity work and software vulnerability discovery&#8212;reaching a level the company finds unsettling&#8212;it has taken the unusually restrained step of not releasing the model publicly. Access is limited to a handful of critical infrastructure companies within Project Glasswing, and ordinary developers cannot reach it through the API either. (Some analysts have pointed out, of course, that this arrangement also conveniently helps prevent model distillation and locks in enterprise-tier customers.) But even with this &#8220;beast&#8221; kept on a leash for the moment, the coding capabilities of today&#8217;s mainstream AI models are already more than enough to make cloning a product trivially easy.</p><p>Last week, a developer on Reddit claimed that he had spent a year &#8220;reverse-engineering the SwiftUI API&#8221; to build an entirely new Swift web framework. The post was fluent and precise in its terminology, and it drew considerable attention. Paul Hudson soon appeared in the comments and called it out: the so-called &#8220;independent research&#8221; was in fact little more than a string replacement performed on his MIT-licensed open-source project <a href="https://github.com/twostraws/Ignite">Ignite</a>&#8212;down to the point that the original author&#8217;s personal, stylistically distinctive code comments had been preserved verbatim. The entire repository was then squashed into a single commit to erase its history, and the license was illicitly changed to the copyleft GPL. A number of developers in the community suspect that the &#8220;reverse-engineering SwiftUI&#8221; narrative itself was AI-generated as well. More intriguingly, the author in question was actually a major contributor to Ignite himself&#8212;when Vibe Coding has driven the cost of &#8220;repackaging a project&#8221; close to zero, &#8220;I was involved in this&#8221; can itself become a rhetorical device for blurring the lines of responsibility.</p><p>Around the same time, Vibe Island&#8212;a polished macOS menu-bar app for monitoring AI coding agents&#8212;was pixel-for-pixel cloned shortly after its release. Although the copycat published its code under the banner of an &#8220;open-source alternative,&#8221; the impact on the original author&#8217;s sales and creative motivation was real and significant. Yet even if the author wished to pursue legal action, he would run into a new problem of the times: in both establishing ownership and enforcing his rights, he might need to prove that his work possesses sufficient human originality and account for the extent of AI-generated content involved&#8212;otherwise, he would face considerably greater legal uncertainty.</p><p>Indeed, the legal walls protecting code are beginning to crumble on the &#8220;ownership side&#8221; first. Last month, China&#8217;s Copyright Protection Centre officially rolled out a new version of its software copyright registration application and accompanying review rules, which explicitly require the filer to make a notarized personal commitment that &#8220;no AI has been used to develop the code, author the documentation, or generate the registration materials,&#8221; and the review process now focuses on whether the human intellectual contribution clears the originality threshold required by copyright law. Content without substantive human involvement will struggle to obtain registration. Violators may also be placed on a registry of dishonest filers, with consequences tied to their personal credit records.</p><p>This trend is converging with the recent direction of case law in Europe and the United States: if a piece of code is primarily &#8220;rewritten or recombined&#8221; at high speed by an AI responding to prompts, its chances of obtaining copyright protection drop considerably.</p><p>We have to face a harsh truth: &#8220;I had a brilliant idea and vibe-coded it into existence&#8221; is no longer enough to constitute a business moat. The new paradigm we call Vibe Coding has not only reshaped development workflows and dramatically improved efficiency&#8212;it has simultaneously shaken the foundational logic of the software copyright system from three directions at once: the bar for ownership has risen, the burden of proof for infringement has grown heavier, and functional cloning has been quietly normalized.</p><p>What makes it all the more disheartening is that, controversial as these clone projects may be, they still rack up no small number of stars on GitHub. That suggests that when the cost of getting something is vanishingly low, moral appeals alone can no longer hold back the rush toward &#8220;free equivalents.&#8221;</p><p>Perhaps, as we noted in <a href="https://fatbobman.com/en/weekly/issue-120/">Issue 120&#8217;s discussion of Skip&#8217;s move to go open source</a>&#8212;in an era where the cost of implementing code is approaching zero and any app can be cloned at any moment by an AI, building behind closed doors and &#8220;selling the tool&#8221; will only get harder. Forging real connections with users, and turning &#8220;the credibility of the maker and the trust of the community&#8221; into brand equity that cannot be copied&#8212;this, perhaps, is the true core competency and moat for developers in the years ahead.</p><p><a href="https://fatbobman.com/en/weekly/issue-130/">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/w0131-01">Swift Blog Carnival: Tiny Languages</a></strong></h3><p>The Swift community has launched its first <a href="https://swiftcarnival.github.io/">Blog Carnival</a>, with April&#8217;s theme being <strong>Tiny Languages</strong>. <a href="https://mastodon.social/@ctietze">Christian Tietze</a> invites developers to write about this topic&#8212;custom DSLs, result builders, scripting languages, routing rules&#8230; any perspective related to &#8220;tiny languages&#8221; is welcome. The submission deadline is May 1.</p><p>So far, three entries have been published:</p><ul><li><p><a href="https://mastodon.social/@mattiem">Matt Massicotte</a> reflects on his journey <a href="https://l.fatbobman.com/w0131-01a">from Rake to Make</a>, and then to various Swift-based task runners, noting that he still hasn&#8217;t found an ideal replacement</p></li><li><p><a href="https://x.com/liscio">Chris Liscio</a> shares the design of <a href="https://l.fatbobman.com/w0131-01b">Capo&#8217;s embedded DSL</a>, used to describe keyboard and MIDI bindings, built on Point-Free&#8217;s <code>swift-parsing</code> library</p></li><li><p><a href="https://x.com/krugazor">Nicolas Zinovieff</a> presents an experimental <a href="https://l.fatbobman.com/w0131-01c">symbolic math DSL</a>, leveraging protocols and operator overloading to make expressions like <code>(1 + 2 * "X") * (3 - "Y")</code> valid Swift code, with lazy evaluation when concrete values are provided&#8212;implemented in under 300 lines</p></li></ul><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-02">Indicating Selection in macOS Menus Using SwiftUI</a></strong></h3><p>SwiftUI provides several components for representing selection, such as <code>Picker</code>, <code>Toggle</code>, and <code>Menu</code>. However, clearly guiding users through choices and accurately reflecting the current selection is not as straightforward as it may seem. <a href="https://x.com/gabtheodor">Gabriel Theodoropoulos</a> starts from basic <code>Button</code> implementations and gradually evolves toward <code>Picker</code> and <code>Toggle</code>, systematically outlining common approaches and their limitations.</p><p>The value of this article lies not in presenting a &#8220;single correct solution,&#8221; but in reminding developers that SwiftUI&#8217;s standard components do not automatically guarantee the best user experience. In practice, you still need to balance <strong>system consistency</strong> and <strong>implementation flexibility</strong>.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-03">Building List Replacement in SwiftUI</a></strong></h3><p>Choosing between <code>List</code> and <code>ScrollView + LazyStack</code> remains a common challenge for SwiftUI developers. In this article, <a href="https://x.com/mecid">Majid Jabrayilov</a> rebuilds parts of his CardioBot app using the SwiftUI Container View API (iOS 18+), creating three reusable components&#8212;ScrollingSurface, DividedCard, and SectionedSurface&#8212;as a replacement for <code>List</code>.</p><p>These components closely mirror the usage of <code>List</code> + <code>Section</code>, while eliminating constraints tied to <code>List</code>, such as <code>listRowBackground</code> and <code>listItemTint</code>.</p><blockquote><p><code>List</code> is not just a &#8220;styled LazyVStack&#8221;&#8212;the two differ fundamentally in architecture, scrolling behavior, integration with navigation containers, and performance on large datasets. For a deeper comparison, see this <a href="https://fatbobman.com/en/posts/list-or-lazyvstack/">previous article</a>.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-04">AppIntents meet MCP</a></strong></h3><p>While many still see AppIntents as a companion to Siri and Shortcuts, <a href="https://x.com/FloWritesCode">Florian Schweizer</a> explores a more forward-looking direction: exposing AppIntents as MCP (Model Context Protocol) tools, enabling LLMs to directly interact with your app&#8217;s capabilities.</p><p>Based on <a href="https://github.com/Cocoanetics/SwiftMCP.git">SwiftMCP</a>, Florian uses macros to build an MCP server and seamlessly maps AppIntents into MCP tools. This allows AI agents to invoke app functionality directly, enabling cross-app automation.</p><blockquote><p>Rumors have suggested since last year that Apple is bringing MCP support into its ecosystem. Perhaps we&#8217;ll get answers at WWDC 26 in a couple of months.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-05">Ride the Lightning Air: Building Interactive WidgetKit Widgets</a></strong></h3><p>Many developers are misled by WidgetKit documentation, mistakenly treating <code>AppIntentTimelineProvider</code> as the key to interactive widgets. In reality, it is designed for <strong>user-configurable widgets</strong> (e.g., editing options via long-press), not for interactivity.</p><p>The actual foundation for interactive widgets remains <code>TimelineProvider</code>. <a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> demonstrates the correct approach through a fictional airline widget: Using <code>TimelineProvider</code> + <code>Button(intent:)</code> + App Group shared storage to build interactive widgets.</p><p>The data flow forms a clean loop:  User action &#8594; Intent execution &#8594; State update &#8594; Widget reload &#8594; UI refresh</p><div><hr></div><h3><strong>File Storage and iCloud: A Complete View from Local to Cloud</strong></h3><p>In iOS and macOS development (and usage), file storage is often treated as a basic capability&#8212;but it actually defines the lifecycle and behavior of your data.</p><p>In <a href="https://l.fatbobman.com/w0131-06a">Working with files and directories in iOS</a>, <a href="https://x.com/tanaschita">Natascha Fadeeva</a> systematically explains the App Sandbox structure and the roles of <code>Documents</code>, <code>Library</code>, and <code>Caches</code>, helping developers understand where different types of data should reside&#8212;and how to avoid unnecessary iCloud backups.</p><p>Meanwhile, <a href="https://x.com/howardnoakley">Howard Oakley</a> in <a href="https://l.fatbobman.com/w0131-06b">Understanding and Testing iCloud</a> explores what happens next: iCloud is not a single service, but a collection of subsystems such as CloudKit, iCloud Drive, and system update services. Different types of data follow different synchronization and backup paths.</p><blockquote><p>File placement is not just an organizational concern&#8212;it defines whether data is backed up, synchronized, and how it flows across devices.</p></blockquote><p>As a result, iCloud issues are rarely just about &#8220;whether sync is enabled.&#8221; They often involve multiple layers, including client state, network conditions, caching behavior, and server-side throttling.</p><div><hr></div><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0131-07">Bad Dock: Animate Your Dock Icon</a></strong></h3><p>This is a &#8220;ridiculous yet serious&#8221; macOS experiment. <a href="https://ericmartz.com/">Eric Martz</a> uses the public <code>NSDockTile</code> / <code>NSDockTilePlugin</code> APIs to bypass the squircle constraints introduced in Big Sur and render a video stream directly inside a Dock icon.</p><p>The implementation is straightforward but well-structured: decoding video with <code>AVAssetReader</code>, reducing frame rate to ~12fps, and managing memory with a ring buffer. The result is a polished technical proof-of-concept built from what initially seems like a playful idea.</p><blockquote><p>The real value of projects like this lies not in their functionality, but in revealing that system API boundaries often extend far beyond what the documentation suggests.</p></blockquote><p>Note: This project implements <strong>runtime dynamic Dock icons</strong> (continuously rendered while the app is running). After the app exits, only a static custom icon can be preserved via <code>NSDockTilePlugin</code>.</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-131?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-131?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#34987; Vibe &#25703;&#27585;&#30340;&#29256;&#26435;&#22721;&#22418;&#65292;&#19982;&#24320;&#21457;&#32773;&#30340;&#26032;&#25252;&#22478;&#27827;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-131/">&#32593;&#39029;&#29256;</a></strong></p><p>Anthropic &#19981;&#20037;&#21069;&#23459;&#24067;&#65292;&#30001;&#20110;&#20854;&#26368;&#26032;&#27169;&#22411; Mythos &#22312;&#32593;&#32476;&#23433;&#20840;&#19982;&#20195;&#30721;&#28431;&#27934;&#25366;&#25496;&#26041;&#38754;&#30340;&#33021;&#21147;&#8220;&#36807;&#20110;&#24378;&#22823;&#8221;&#65292;&#24050;&#36798;&#21040;&#20196;&#20154;&#19981;&#23433;&#30340;&#31243;&#24230;&#65292;&#22240;&#27492;&#37319;&#21462;&#20102;&#26497;&#20026;&#32597;&#35265;&#30340;&#20811;&#21046;&#25514;&#26045;&#65306;&#20165;&#21521; Project Glasswing &#20869;&#30340;&#23569;&#25968;&#20851;&#38190;&#22522;&#30784;&#35774;&#26045;&#20225;&#19994;&#24320;&#25918;&#65292;&#19981;&#38754;&#21521;&#20844;&#20247;&#21457;&#24067;&#65292;&#26222;&#36890;&#24320;&#21457;&#32773;&#20063;&#26080;&#27861;&#36890;&#36807; API &#35843;&#29992;&#65288;&#24403;&#28982;&#65292;&#20063;&#26377;&#20998;&#26512;&#32773;&#25351;&#20986;&#65292;&#36825;&#19968;&#23433;&#25490;&#21516;&#26679;&#26377;&#21161;&#20110;&#38450;&#27490;&#27169;&#22411;&#33976;&#39311;&#65292;&#24182;&#38145;&#23450;&#20225;&#19994;&#32423;&#23458;&#25143;&#65289;&#12290;&#20294;&#21363;&#20415;&#36825;&#22836;&#8220;&#29467;&#20861;&#8221;&#34987;&#26242;&#26102;&#25353;&#20303;&#65292;&#24403;&#21069;&#20027;&#27969; AI &#27169;&#22411;&#30340;&#20195;&#30721;&#33021;&#21147;&#65292;&#24050;&#32463;&#36275;&#20197;&#35753;&#22797;&#21046;&#19968;&#27454;&#20135;&#21697;&#21464;&#24471;&#36731;&#32780;&#26131;&#20030;&#12290;</p><p>&#19978;&#21608;&#65292;Reddit &#19978;&#19968;&#20301;&#24320;&#21457;&#32773;&#23459;&#31216;&#65292;&#33258;&#24049;&#33457;&#20102;&#19968;&#24180;&#26102;&#38388;&#8220;&#36870;&#21521; SwiftUI API&#8221;&#65292;&#25171;&#36896;&#20102;&#19968;&#20010;&#20840;&#26032;&#30340; Swift Web &#26694;&#26550;&#12290;&#24086;&#23376;&#34892;&#25991;&#27969;&#30021;&#12289;&#26415;&#35821;&#32771;&#31350;&#65292;&#19968;&#24230;&#21560;&#24341;&#20102;&#19981;&#23569;&#20851;&#27880;&#12290;&#20294; Paul Hudson &#24456;&#24555;&#29616;&#36523;&#35780;&#35770;&#21306;&#25171;&#20551;&#65306;&#25152;&#35859;&#8220;&#29420;&#31435;&#30740;&#21457;&#8221;&#65292;&#23454;&#38469;&#19978;&#21482;&#26159;&#23558;&#20182;&#30340; MIT &#24320;&#28304;&#39033;&#30446; <a href="https://github.com/twostraws/Ignite">Ignite</a> &#20570;&#20102;&#31616;&#21333;&#30340;&#23383;&#31526;&#20018;&#26367;&#25442;&#65292;&#29978;&#33267;&#36830;&#21407;&#20316;&#32773;&#24102;&#26377;&#20010;&#20154;&#39118;&#26684;&#30340;&#20195;&#30721;&#27880;&#37322;&#37117;&#21407;&#23553;&#19981;&#21160;&#20445;&#30041;&#65292;&#38543;&#21518;&#23558;&#25972;&#20010;&#20179;&#24211;&#21387;&#32553;&#20026;&#19968;&#27425;&#25552;&#20132;&#20197;&#25273;&#38500;&#21382;&#21490;&#65292;&#24182;&#36829;&#35268;&#25913;&#20026;&#20855;&#26377;&#20256;&#26579;&#24615;&#30340; GPL &#21327;&#35758;&#12290;&#31038;&#21306;&#20013;&#19981;&#23569;&#24320;&#21457;&#32773;&#37117;&#24576;&#30097;&#65292;&#36825;&#22871;&#8220;&#36870;&#21521; SwiftUI&#8221;&#30340;&#21465;&#20107;&#26412;&#36523;&#20063;&#26159;&#30001; AI &#29983;&#25104;&#12290;&#26356;&#32784;&#20154;&#23547;&#21619;&#30340;&#26159;&#65292;&#35813;&#20316;&#32773;&#26412;&#23601;&#26159; Ignite &#30340;&#20027;&#35201;&#36129;&#29486;&#32773;&#20043;&#19968;&#8212;&#8212;&#24403; Vibe Coding &#23558;&#8220;&#37325;&#26032;&#25171;&#21253;&#19968;&#20010;&#39033;&#30446;&#8221;&#30340;&#25104;&#26412;&#38477;&#33267;&#26497;&#20302;&#26102;&#65292;&#8220;&#25105;&#21442;&#19982;&#36807;&#8221;&#26412;&#36523;&#20063;&#21487;&#33021;&#25104;&#20026;&#19968;&#31181;&#27169;&#31946;&#36131;&#20219;&#36793;&#30028;&#30340;&#35805;&#26415;&#12290;</p><p>&#20960;&#20046;&#22312;&#21516;&#19968;&#26102;&#38388;&#65292;macOS &#19978;&#31934;&#33268;&#30340; AI &#24037;&#20316;&#29366;&#24577;&#30417;&#25511;&#24212;&#29992; Vibe Island &#22312;&#21457;&#24067;&#21518;&#19981;&#20037;&#20415;&#36973;&#36935;&#20102;&#20687;&#32032;&#32423;&#20223;&#21046;&#12290;&#23613;&#31649;&#20223;&#21046;&#32773;&#25171;&#30528;&#8220;&#24320;&#28304;&#26367;&#20195;&#21697;&#8221;&#30340;&#26071;&#21495;&#20844;&#24320;&#20102;&#20195;&#30721;&#65292;&#36825;&#20381;&#28982;&#23545;&#21407;&#20316;&#32773;&#30340;&#21830;&#19994;&#38144;&#21806;&#19982;&#21019;&#20316;&#28909;&#24773;&#36896;&#25104;&#20102;&#26126;&#26174;&#20914;&#20987;&#12290;&#28982;&#32780;&#65292;&#21363;&#20415;&#20316;&#32773;&#24076;&#26395;&#37319;&#21462;&#27861;&#24459;&#25163;&#27573;&#65292;&#20063;&#23558;&#38754;&#20020;&#19968;&#20010;&#26032;&#30340;&#26102;&#20195;&#38590;&#39064;&#65306;&#22312;&#30830;&#26435;&#19982;&#32500;&#26435;&#36807;&#31243;&#20013;&#65292;&#20182;&#21487;&#33021;&#38656;&#35201;&#35777;&#26126;&#20854;&#20316;&#21697;&#20855;&#22791;&#36275;&#22815;&#30340;&#20154;&#31867;&#29420;&#21019;&#24615;&#65292;&#24182;&#35828;&#26126; AI &#29983;&#25104;&#20869;&#23481;&#30340;&#21442;&#19982;&#31243;&#24230;&#65292;&#21542;&#21017;&#23558;&#38754;&#20020;&#26356;&#39640;&#30340;&#19981;&#30830;&#23450;&#24615;&#12290;</p><p>&#20107;&#23454;&#19978;&#65292;&#20195;&#30721;&#30340;&#27861;&#24459;&#22721;&#22418;&#27491;&#20174;&#8220;&#30830;&#26435;&#31471;&#8221;&#24320;&#22987;&#26494;&#21160;&#12290;&#19978;&#20010;&#26376;&#65292;&#20013;&#22269;&#29256;&#26435;&#20445;&#25252;&#20013;&#24515;&#27491;&#24335;&#21551;&#29992;&#26032;&#29256;&#12298;&#35745;&#31639;&#26426;&#36719;&#20214;&#33879;&#20316;&#26435;&#30331;&#35760;&#30003;&#35831;&#34920;&#12299;&#21450;&#30456;&#20851;&#23457;&#26597;&#26032;&#35268;&#65292;&#26126;&#30830;&#35201;&#27714;&#32463;&#21150;&#20154;&#23454;&#21517;&#25215;&#35834;&#8220;&#26410;&#20351;&#29992; AI &#24320;&#21457;&#32534;&#20889;&#20195;&#30721;&#12289;&#25776;&#20889;&#25991;&#26723;&#25110;&#29983;&#25104;&#30331;&#35760;&#26448;&#26009;&#8221;&#65292;&#24182;&#22312;&#23457;&#26597;&#20013;&#37325;&#28857;&#35780;&#20272;&#20154;&#31867;&#26234;&#21147;&#25237;&#20837;&#26159;&#21542;&#36798;&#21040;&#33879;&#20316;&#26435;&#27861;&#25152;&#35201;&#27714;&#30340;&#8220;&#29420;&#21019;&#24615;&#8221;&#38376;&#27099;&#65307;&#32570;&#20047;&#23454;&#36136;&#20154;&#31867;&#21442;&#19982;&#30340;&#20869;&#23481;&#65292;&#23558;&#38590;&#20197;&#33719;&#24471;&#30830;&#26435;&#12290;&#36829;&#35268;&#32773;&#36824;&#21487;&#33021;&#34987;&#32435;&#20837;&#22833;&#20449;&#21517;&#21333;&#65292;&#24182;&#19982;&#20010;&#20154;&#24449;&#20449;&#25346;&#38057;&#12290;</p><p>&#36825;&#19968;&#36235;&#21183;&#20063;&#19982;&#27431;&#32654;&#36817;&#26399;&#30340;&#21028;&#20363;&#26041;&#21521;&#36235;&#20110;&#19968;&#33268;&#65306;&#22914;&#26524;&#19968;&#27573;&#20195;&#30721;&#20027;&#35201;&#30001; AI &#26681;&#25454;&#25552;&#31034;&#35789;&#24555;&#36895;&#8220;&#25913;&#20889;&#25110;&#37325;&#32452;&#8221;&#29983;&#25104;&#65292;&#20854;&#33719;&#24471;&#33879;&#20316;&#26435;&#20445;&#25252;&#30340;&#21487;&#33021;&#24615;&#23558;&#26174;&#33879;&#38477;&#20302;&#12290;</p><p>&#25105;&#20204;&#24517;&#39035;&#25215;&#35748;&#19968;&#20010;&#27531;&#37239;&#30340;&#20107;&#23454;&#65306;&#8220;&#25105;&#26377;&#19968;&#20010;&#32477;&#22937;&#30340; Idea&#65292;&#24182;&#25226;&#23427; Vibe &#25104;&#20195;&#30721;&#8221;&#65292;&#24050;&#32463;&#19981;&#36275;&#20197;&#26500;&#25104;&#21830;&#19994;&#22721;&#22418;&#12290;&#36825;&#31181;&#21517;&#20026; Vibe Coding &#30340;&#26032;&#33539;&#24335;&#65292;&#19981;&#20165;&#25913;&#21464;&#20102;&#24320;&#21457;&#27969;&#31243;&#12289;&#26174;&#33879;&#25552;&#21319;&#20102;&#25928;&#29575;&#65292;&#20063;&#20174;&#19977;&#20010;&#26041;&#21521;&#21516;&#26102;&#21160;&#25671;&#20102;&#36719;&#20214;&#29256;&#26435;&#20307;&#31995;&#30340;&#22522;&#30784;&#36923;&#36753;&#65306;&#30830;&#26435;&#38376;&#27099;&#25552;&#39640;&#12289;&#20405;&#26435;&#20030;&#35777;&#21464;&#38590;&#12289;&#21151;&#33021;&#22797;&#21051;&#34987;&#40664;&#35768;&#12290;</p><p>&#20196;&#20154;&#36951;&#25022;&#30340;&#26159;&#65292;&#21363;&#20415;&#36825;&#20123;&#20811;&#38534;&#39033;&#30446;&#39281;&#21463;&#20105;&#35758;&#65292;&#23427;&#20204;&#20381;&#28982;&#22312; GitHub &#19978;&#25910;&#33719;&#20102;&#19981;&#33778;&#30340; Star&#12290;&#36825;&#35828;&#26126;&#65292;&#22312;&#33719;&#21462;&#25104;&#26412;&#26497;&#20302;&#30340;&#21069;&#25552;&#19979;&#65292;&#20165;&#38752;&#36947;&#24503;&#21628;&#21505;&#65292;&#24050;&#32463;&#24456;&#38590;&#38459;&#27490;&#20154;&#20204;&#23545;&#8220;&#20813;&#36153;&#24179;&#26367;&#8221;&#30340;&#36861;&#36880;&#12290;</p><p>&#25110;&#35768;&#65292;&#27491;&#22914;&#25105;&#20204;&#22312; <a href="https://fatbobman.com/zh/weekly/issue-120/">&#31532; 120 &#26399;&#21608;&#25253;&#20013;&#35752;&#35770; Skip &#30340;&#24320;&#28304;&#20030;&#25514;</a> &#26102;&#25152;&#25552;&#21040;&#30340;&#37027;&#26679;&#8212;&#8212;&#22312;&#20195;&#30721;&#23454;&#29616;&#25104;&#26412;&#36235;&#36817;&#20110;&#38646;&#12289;&#24212;&#29992;&#38543;&#26102;&#21487;&#33021;&#34987; AI &#19968;&#38190;&#20811;&#38534;&#30340;&#24403;&#19979;&#65292;&#38381;&#38376;&#36896;&#36710;&#8220;&#21334;&#24037;&#20855;&#8221;&#23558;&#21464;&#24471;&#24840;&#21457;&#22256;&#38590;&#12290;&#19982;&#29992;&#25143;&#24314;&#31435;&#30495;&#23454;&#36830;&#25509;&#65292;&#23558;&#8220;&#20986;&#21697;&#26041;&#30340;&#20449;&#35465;&#19982;&#31038;&#21306;&#30340;&#20449;&#20219;&#8221;&#36716;&#21270;&#20026;&#19981;&#21487;&#22797;&#21046;&#30340;&#21697;&#29260;&#36164;&#20135;&#65292;&#25110;&#35768;&#25165;&#26159;&#26410;&#26469;&#24320;&#21457;&#32773;&#30495;&#27491;&#30340;&#26680;&#24515;&#31454;&#20105;&#21147;&#19982;&#25252;&#22478;&#27827;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-130/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0131-01">Swift Blog Carnival: Tiny Languages</a></strong></h3><p>Swift &#31038;&#21306;&#27491;&#22312;&#21457;&#36215;&#31532;&#19968;&#23626; <a href="https://swiftcarnival.github.io/">Blog Carnival</a>&#65292;&#22235;&#26376;&#30340;&#20027;&#39064;&#26159; <strong>Tiny Languages</strong>&#12290;<a href="https://mastodon.social/@ctietze">Christian Tietze</a> &#36992;&#35831;&#24320;&#21457;&#32773;&#22260;&#32469;&#36825;&#19968;&#20027;&#39064;&#25776;&#20889;&#21338;&#23458;&#65306;&#33258;&#23450;&#20041; DSL&#12289;Result Builder&#12289;&#33050;&#26412;&#35299;&#26512;&#22120;&#12289;&#36335;&#30001;&#35268;&#21017;&#8230;&#8230;&#20219;&#20309;&#19982;&#8220;&#24494;&#22411;&#35821;&#35328;&#8221;&#30456;&#20851;&#30340;&#24605;&#32771;&#37117;&#21487;&#20197;&#20316;&#20026;&#20999;&#20837;&#28857;&#65292;&#25130;&#27490;&#26085;&#26399;&#20026; 5 &#26376; 1 &#26085;&#12290;</p><p>&#30446;&#21069;&#24050;&#26377;&#19977;&#31687;&#25237;&#31295;&#65306;</p><ul><li><p><a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#22238;&#39038;&#20102;&#20182; <a href="https://l.fatbobman.com/w0131-01a">&#20174; Rake &#21040; Make</a>&#65292;&#20877;&#21040;&#21508;&#31867; Swift &#20219;&#21153;&#36816;&#34892;&#22120;&#30340;&#25506;&#32034;&#21382;&#31243;&#65292;&#22374;&#35328;&#33267;&#20170;&#20173;&#26410;&#25214;&#21040;&#29702;&#24819;&#26367;&#20195;&#21697;</p></li><li><p><a href="https://x.com/liscio">Chris Liscio</a> &#20998;&#20139;&#20102; <a href="https://l.fatbobman.com/w0131-01b">Capo &#24212;&#29992;&#20869;&#32622; DSL</a> &#30340;&#35774;&#35745;&#65306;&#29992;&#20110;&#25551;&#36848;&#38190;&#30424;&#19982; MIDI &#32465;&#23450;&#65292;&#22522;&#20110; Point-Free &#30340; <code>swift-parsing</code> &#24211;&#26500;&#24314;</p></li><li><p><a href="https://x.com/krugazor">Nicolas Zinovieff</a> &#21017;&#23637;&#31034;&#20102;&#19968;&#20010; <a href="https://l.fatbobman.com/w0131-01c">&#31526;&#21495;&#25968;&#23398; DSL</a> &#30340;&#23454;&#39564;&#65306;&#36890;&#36807;&#21327;&#35758;&#19982;&#36816;&#31639;&#31526;&#37325;&#36733;&#65292;&#35753; <code>(1 + 2 * "X") * (3 - "Y")</code>&#25104;&#20026;&#21512;&#27861;&#30340; Swift &#34920;&#36798;&#24335;&#65292;&#24182;&#22312;&#25552;&#20379;&#20855;&#20307;&#20540;&#26102;&#24816;&#24615;&#27714;&#20540;&#65292;&#26680;&#24515;&#23454;&#29616;&#19981;&#36229;&#36807; 300 &#34892;</p></li></ul><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-02">&#22312; macOS &#33756;&#21333;&#20013;&#28165;&#26224;&#26174;&#31034;&#24403;&#21069;&#36873;&#20013;&#29366;&#24577; (Indicating Selection in macOS Menus Using SwiftUI)</a></strong></h3><p>SwiftUI &#25552;&#20379;&#20102;&#19981;&#23569;&#29992;&#20110;&#34920;&#36798;&#36873;&#25321;&#30340;&#32452;&#20214;&#65292;&#20363;&#22914; <code>Picker</code>&#12289;<code>Toggle</code>&#12289;<code>Menu</code>&#65292;&#20294;&#22914;&#20309;&#28165;&#26224;&#22320;&#24341;&#23548;&#29992;&#25143;&#36827;&#34892;&#36873;&#25321;&#65292;&#24182;&#20934;&#30830;&#26631;&#35782;&#24403;&#21069;&#36873;&#20013;&#39033;&#65292;&#24182;&#27809;&#26377;&#24819;&#35937;&#20013;&#37027;&#26679;&#29702;&#25152;&#24403;&#28982;&#12290;<a href="https://x.com/gabtheodor">Gabriel Theodoropoulos</a> &#20174;&#26368;&#22522;&#30784;&#30340; <code>Button</code> &#20986;&#21457;&#65292;&#19968;&#27493;&#27493;&#28436;&#36827;&#21040; <code>Picker</code> &#19982; <code>Toggle</code>&#65292;&#31995;&#32479;&#26803;&#29702;&#20102;&#20960;&#31181;&#24120;&#35265;&#26041;&#26696;&#21450;&#20854;&#21508;&#33258;&#30340;&#23616;&#38480;&#12290;&#25991;&#31456;&#30340;&#20215;&#20540;&#19981;&#22312;&#20110;&#32473;&#20986;&#8220;&#21807;&#19968;&#27491;&#30830;&#35299;&#8221;&#65292;&#32780;&#22312;&#20110;&#25552;&#37266;&#24320;&#21457;&#32773;&#65306;SwiftUI &#25552;&#20379;&#30340;&#26631;&#20934;&#32452;&#20214;&#65292;&#24182;&#19981;&#20250;&#33258;&#21160;&#24102;&#26469;&#26368;&#20339;&#30340;&#29992;&#25143;&#21576;&#29616;&#25928;&#26524;&#12290;&#24456;&#22810;&#26102;&#20505;&#65292;&#20320;&#20173;&#38656;&#22312;&#8220;&#31995;&#32479;&#19968;&#33268;&#24615;&#8221;&#19982;&#8220;&#23454;&#29616;&#33258;&#30001;&#24230;&#8221;&#20043;&#38388;&#20570;&#20986;&#26435;&#34913;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-03">&#26500;&#24314; List &#30340;&#26367;&#20195;&#32452;&#20214; (Building List replacement in SwiftUI)</a></strong></h3><p>&#22914;&#20309;&#22312; <code>List</code> &#19982; <code>ScrollView + LazyStack</code> &#20043;&#38388;&#20570;&#20986;&#36873;&#25321;&#65292;&#19968;&#30452;&#26159;&#22256;&#25200;&#19981;&#23569; SwiftUI &#24320;&#21457;&#32773;&#30340;&#38382;&#39064;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://x.com/mecid">Majid Jabrayilov</a> &#22312;&#37325;&#26500;&#20854; CardioBot &#24212;&#29992;&#26102;&#65292;&#36873;&#25321;&#22522;&#20110; SwiftUI &#30340; Container View API&#65288;iOS 18+&#65289;&#26500;&#24314;&#20102;&#19977;&#20010;&#21487;&#22797;&#29992;&#30340; UI &#32452;&#20214;&#65306;ScrollingSurface&#12289;DividedCard&#12289;SectionedSurface&#65292;&#20197;&#26367;&#20195; <code>List</code>&#12290;&#36825;&#20123;&#32452;&#20214;&#22312;&#20351;&#29992;&#26041;&#24335;&#19978;&#19982; <code>List</code> + <code>Section</code> &#39640;&#24230;&#30456;&#20284;&#65292;&#20294;&#24443;&#24213;&#25670;&#33073;&#20102; <code>listRowBackground</code>&#12289;<code>listItemTint</code> &#31561;&#20165;&#22312; <code>List</code> &#20013;&#29983;&#25928;&#30340;&#38480;&#21046;&#12290;</p><blockquote><p><code>List</code> &#24182;&#38750;&#21482;&#26159;&#8220;&#26377;&#40664;&#35748;&#26679;&#24335;&#30340; <code>LazyVStack</code>&#8221;&#8212;&#8212;&#20004;&#32773;&#22312;&#24213;&#23618;&#26550;&#26500;&#12289;&#28378;&#21160;&#25511;&#21046;&#12289;&#19982;&#23548;&#33322;&#23481;&#22120;&#30340;&#21327;&#21516;&#12289;&#20197;&#21450;&#22823;&#25968;&#25454;&#38598;&#19979;&#30340;&#24615;&#33021;&#34920;&#29616;&#19978;&#22343;&#26377;&#26412;&#36136;&#24046;&#24322;&#12290;&#22914;&#20309;&#22312;&#20004;&#32773;&#20043;&#38388;&#20570;&#20986;<a href="https://fatbobman.com/zh/posts/list-or-lazyvstack/">&#32508;&#21512;&#21028;&#26029;</a>&#65292;&#21487;&#20197;&#21442;&#32771;&#36825;&#31687;&#26087;&#25991;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-04">AppIntents meet MCP</a></strong></h3><p>&#24403;&#22823;&#23478;&#36824;&#22312;&#23558; AppIntents &#35270;&#20026; Siri &#19982;&#24555;&#25463;&#25351;&#20196;&#30340;&#8220;&#37197;&#22871;&#24037;&#20855;&#8221;&#26102;&#65292;<a href="https://x.com/FloWritesCode">Florian Schweizer</a> &#32473;&#20986;&#20102;&#19968;&#20010;&#26356;&#20540;&#24471;&#20851;&#27880;&#30340;&#26041;&#21521;&#65306;&#23558; AppIntents &#30452;&#25509;&#26292;&#38706;&#20026; MCP&#65288;Model Context Protocol&#65289;&#24037;&#20855;&#65292;&#20174;&#32780;&#35753; LLM &#33021;&#22815;&#35843;&#29992;&#20320;&#30340;&#24212;&#29992;&#33021;&#21147;&#12290;Florian &#22522;&#20110; <a href="https://github.com/Cocoanetics/SwiftMCP.git">SwiftMCP</a>&#65292;&#36890;&#36807;&#23439;&#26500;&#24314; MCP Server&#65292;&#24182;&#23558; AppIntents &#26080;&#32541;&#26144;&#23556;&#20026; MCP Tools&#65292;&#20351; AI Agent &#33021;&#22815;&#30452;&#25509;&#35843;&#29992;&#24212;&#29992;&#20013;&#30340; Intent&#65292;&#23454;&#29616;&#36328;&#24212;&#29992;&#33258;&#21160;&#21270;&#12290;</p><blockquote><p>&#21435;&#24180;&#20415;&#26377;<a href="https://fatbobman.com/zh/weekly/issue-104/">&#20256;&#38395;</a>&#65292;&#33529;&#26524;&#27491;&#22312;&#20026;&#20854;&#29983;&#24577;&#31995;&#32479;&#24341;&#20837; MCP &#25903;&#25345;&#12290;&#25110;&#35768;&#20877;&#36807;&#20004;&#20010;&#26376;&#65292;&#22312; WWDC 26 &#19978;&#31572;&#26696;&#20415;&#20250;&#25581;&#26195;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0131-05">&#21019;&#24314;&#20132;&#20114;&#24335;&#23567;&#32452;&#20214; (Ride the Lightning Air: Building Interactive WidgetKit Widgets)</a></strong></h3><p>&#24456;&#22810;&#24320;&#21457;&#32773;&#37117;&#20250;&#34987; WidgetKit &#30340;&#25991;&#26723;&#35823;&#23548;&#65292;&#38169;&#23558; <code>AppIntentTimelineProvider</code> &#35270;&#20026;&#23454;&#29616;&#20132;&#20114;&#25353;&#38062;&#30340;&#20851;&#38190;&#8212;&#8212;&#23454;&#21017;&#19981;&#28982;&#12290;&#23427;&#26159;&#20026;&#8220;&#29992;&#25143;&#21487;&#37197;&#32622; Widget&#8221;&#65288;&#22914;&#38271;&#25353;&#21518;&#32534;&#36753;&#35774;&#32622;&#39033;&#65289;&#20934;&#22791;&#30340;&#65292;&#19982;&#20132;&#20114;&#34892;&#20026;&#24182;&#26080;&#30452;&#25509;&#20851;&#31995;&#12290;&#32780;&#30495;&#27491;&#29992;&#20110;&#23454;&#29616;&#20132;&#20114;&#65288;&#25353;&#38062;&#28857;&#20987;&#35302;&#21457;&#34892;&#20026;&#65289;&#30340;&#65292;&#20381;&#28982;&#26159;&#26368;&#22522;&#30784;&#30340; <code>TimelineProvider</code>&#12290;<a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> &#36890;&#36807;&#19968;&#20010;&#34394;&#26500;&#33322;&#31354;&#20844;&#21496;&#30340;&#30331;&#26426;&#29366;&#24577; Widget&#65292;&#23436;&#25972;&#28436;&#31034;&#20102;&#27491;&#30830;&#36335;&#24452;&#65306;&#20351;&#29992; <code>TimelineProvider</code></p><ul><li><p><code>Button(intent:)</code> + AppGroup &#20849;&#20139;&#23384;&#20648;&#26469;&#26500;&#24314;&#20132;&#20114;&#24335; Widget&#12290;</p><p>&#25972;&#20010;&#25968;&#25454;&#27969;&#24418;&#25104;&#19968;&#20010;&#28165;&#26224;&#30340;&#38381;&#29615;&#65306;&#29992;&#25143;&#25805;&#20316; &#8594; Intent &#25191;&#34892; &#8594; &#29366;&#24577;&#20889;&#20837; &#8594; Widget &#21047;&#26032; &#8594; UI &#26356;&#26032;&#12290;</p></li></ul><div><hr></div><h3><strong>&#25991;&#20214;&#23384;&#20648;&#19982; iCloud&#65306;&#20174;&#26412;&#22320;&#21040;&#20113;&#31471;&#30340;&#23436;&#25972;&#35748;&#30693;</strong></h3><p>&#22312; iOS / macOS &#24320;&#21457;&#21644;&#20351;&#29992;&#20013;&#65292;&#25991;&#20214;&#23384;&#20648;&#24448;&#24448;&#34987;&#24403;&#20316;&#8220;&#22522;&#30784;&#33021;&#21147;&#8221;&#65292;&#20294;&#23427;&#23454;&#38469;&#19978;&#30452;&#25509;&#20915;&#23450;&#20102;&#25968;&#25454;&#30340;&#29983;&#21629;&#21608;&#26399;&#19982;&#31995;&#32479;&#34892;&#20026;&#12290;</p><p>&#22312; <a href="https://l.fatbobman.com/w0131-06a">Working with files and directories in iOS</a> &#19968;&#25991;&#20013;&#65292;<a href="https://x.com/tanaschita">Natascha Fadeeva</a> &#31995;&#32479;&#26803;&#29702;&#20102; App Sandbox &#30340;&#32467;&#26500;&#65292;&#20197;&#21450; <code>Documents</code>&#12289;<code>Library</code>&#12289;<code>Caches</code> &#31561;&#30446;&#24405;&#30340;&#32844;&#36131;&#21010;&#20998;&#65292;&#24110;&#21161;&#24320;&#21457;&#32773;&#24314;&#31435;&#8220;&#20160;&#20040;&#25968;&#25454;&#35813;&#25918;&#22312;&#21738;&#37324;&#8221;&#30340;&#22522;&#26412;&#35748;&#30693;&#65292;&#24182;&#35828;&#26126;&#22914;&#20309;&#36991;&#20813;&#26080;&#20851;&#25991;&#20214;&#34987; iCloud &#22791;&#20221;&#12290;</p><p>&#32780; <a href="https://x.com/howardnoakley">Howard Oakley</a> &#25776;&#20889;&#30340; <a href="https://l.fatbobman.com/w0131-06b">Understanding and Testing iCloud</a> &#21017;&#20174;&#31995;&#32479;&#23618;&#38754;&#25581;&#31034;&#20102;&#36825;&#20123;&#25968;&#25454;&#30340;&#8220;&#21518;&#32493;&#21629;&#36816;&#8221;&#12290;iCloud &#24182;&#38750;&#21333;&#19968;&#26381;&#21153;&#65292;&#32780;&#26159;&#30001; CloudKit&#12289;iCloud Drive&#12289;&#31995;&#32479;&#26356;&#26032;&#31561;&#22810;&#20010;&#23376;&#31995;&#32479;&#32452;&#25104;&#65292;&#19981;&#21516;&#25968;&#25454;&#31867;&#22411;&#23545;&#24212;&#19981;&#21516;&#30340;&#21516;&#27493;&#19982;&#22791;&#20221;&#36335;&#24452;&#12290;</p><blockquote><p>&#25991;&#20214;&#30340;&#23384;&#20648;&#20301;&#32622;&#65292;&#24182;&#19981;&#20165;&#20165;&#26159;&#32452;&#32455;&#38382;&#39064;&#65292;&#26356;&#26159;&#22312;&#23450;&#20041;&#23427;&#26159;&#21542;&#20250;&#34987;&#22791;&#20221;&#12289;&#21516;&#27493;&#65292;&#20197;&#21450;&#22312;&#35774;&#22791;&#20043;&#38388;&#22914;&#20309;&#27969;&#36716;&#12290;</p></blockquote><p>&#22240;&#27492;&#65292;iCloud &#38382;&#39064;&#24448;&#24448;&#19981;&#26159;&#8220;&#26159;&#21542;&#24320;&#21551;&#21516;&#27493;&#8221;&#36825;&#20040;&#31616;&#21333;&#65292;&#32780;&#26159;&#28041;&#21450;&#23458;&#25143;&#31471;&#12289;&#32593;&#32476;&#12289;&#32531;&#23384;&#20197;&#21450;&#26381;&#21153;&#31471;&#38480;&#27969;&#31561;&#22810;&#20010;&#29615;&#33410;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0131-07">Bad Dock: &#35753;&#20320;&#30340; Dock &#22270;&#26631;&#21160;&#36215;&#26469;</a></strong></h3><p>&#36825;&#26159;&#19968;&#20010;&#8220;&#31163;&#35889;&#20294;&#20005;&#32899;&#8221;&#30340; macOS &#23454;&#39564;&#39033;&#30446;&#12290;<a href="https://ericmartz.com/">Eric Martz</a> &#21033;&#29992;&#20844;&#24320;&#30340; <code>NSDockTile</code> / <code>NSDockTilePlugin</code> API&#65292;&#32469;&#36807; Big Sur &#20043;&#21518; Dock &#22270;&#26631;&#30340; squircle &#38480;&#21046;&#65292;&#23558;&#35270;&#39057;&#27969;&#30452;&#25509;&#28210;&#26579;&#36827; Dock &#22270;&#26631;&#12290;&#23454;&#29616;&#24605;&#36335;&#24182;&#19981;&#22797;&#26434;&#65292;&#20294;&#38750;&#24120;&#23436;&#25972;&#65306;&#20351;&#29992; <code>AVAssetReader</code> &#35299;&#30721;&#35270;&#39057;&#12289;&#20027;&#21160;&#38477;&#24103;&#33267;&#32422; 12fps&#12289;&#36890;&#36807; ring buffer &#25511;&#21046;&#20869;&#23384;&#21344;&#29992;&#65292;&#26368;&#32456;&#23558;&#19968;&#20010;&#8220;&#25972;&#27963;&#24819;&#27861;&#8221;&#25171;&#30952;&#25104;&#20102;&#32467;&#26500;&#28165;&#26224;&#30340;&#25216;&#26415;&#39564;&#35777;&#12290;</p><blockquote><p>&#36825;&#31867;&#39033;&#30446;&#30340;&#20215;&#20540;&#19981;&#22312;&#21151;&#33021;&#26412;&#36523;&#65292;&#32780;&#22312;&#20110;&#23637;&#31034;&#65306;&#31995;&#32479; API &#30340;&#36793;&#30028;&#65292;&#24448;&#24448;&#27604;&#25991;&#26723;&#20889;&#24471;&#26356;&#36828;&#12290;</p></blockquote><p>&#34917;&#20805;&#35828;&#26126;&#65306;&#35813;&#39033;&#30446;&#23454;&#29616;&#30340;&#26159;<strong>&#36816;&#34892;&#26102;&#21160;&#24577; Dock &#22270;&#26631;</strong>&#65288;&#24212;&#29992;&#36816;&#34892;&#26102;&#25345;&#32493;&#32472;&#21046;&#65289;&#65307;&#24212;&#29992;&#36864;&#20986;&#21518;&#65292;&#20165;&#33021;&#36890;&#36807; <code>NSDockTilePlugin</code> &#20445;&#30041;&#38745;&#24577;&#33258;&#23450;&#20041;&#22270;&#26631;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #130]]></title><description><![CDATA[Apple's Rare Concession: When Critical Vulnerabilities Meet the "Update Refusal" Wave]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-130</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-130</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 06 Apr 2026 12:03:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!zIqb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_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_!zIqb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zIqb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zIqb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d416ea2f-3a44-48a6-b259-6fec7a0a2484_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;:35916,&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/193306465?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_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_!zIqb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!zIqb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd416ea2f-3a44-48a6-b259-6fec7a0a2484_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"><svg role="img" 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"><g><title></title><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"><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"><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/@rmrdnl?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Daniel Romero</a> on <a href="https://unsplash.com/photos/a-person-is-holding-an-iphone-showcasing-apps--piUPY2-44A?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Apple&#8217;s Rare Concession: When Critical Vulnerabilities Meet the &#8220;Update Refusal&#8221; Wave</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-130/">Read on web &#8594;</a></p><p>Most iOS users have recently encountered news about two serious security threats: Coruna and DarkSword. Both exploit chains rely on watering hole attacks &#8212; no user interaction required. Simply visiting a legitimate website embedded with a malicious iframe, or loading a compromised advertisement in Safari, is enough to trigger the full attack chain. Once data is exfiltrated, the malware cleans up its own traces automatically. Because the vulnerabilities exploited span the vast majority of iOS versions from iOS 13 through iOS 18.7, hundreds of millions of devices have been affected to date.</p><p>Coruna primarily targets devices running iOS 13 through iOS 17. Apple has pushed multiple security updates to these systems over the past several months. DarkSword, meanwhile, targets iOS 18.4 through 18.7 &#8212; devices that are all perfectly capable of running iOS 26, yet for various reasons, a significant number of iOS 18 users have chosen to stay put.</p><p>For a long time, iOS users were notably eager to update &#8212; one of the defining characteristics of the Apple ecosystem. That changed last year. The sweeping visual overhaul introduced by Liquid Glass prompted an unprecedented wave of deliberate refusals to upgrade to iOS 26, something Apple had never seen at this scale before. Compounding the problem, Apple introduced a mandatory age verification system in iOS 26.4 for UK users, in compliance with the Online Safety Act. The verification requirements proved strict enough that many adults found themselves forcibly locked into a &#8220;child mode,&#8221; fueling a separate wave of UK users choosing to remain on iOS 18 or iOS 26.3. In both cases, the decision to avoid updating meant forgoing all subsequent security patches &#8212; leaving devices increasingly exposed.</p><p>Faced with this situation, Apple came under significant public pressure and reputational risk. The turning point came in late March, when DarkSword&#8217;s complete exploit code was leaked to GitHub, effectively democratizing what had been a nation-state-level hacking tool and forcing Apple&#8217;s hand. Apple ultimately took the rare step of releasing a dedicated security patch for iOS 18 &#8212; iOS 18.7.7 &#8212; backporting the same protections already present in iOS 26 to the older system. With that, Apple completed its official security response to this wave of critical vulnerabilities.</p><p>Both Apple and developers across the ecosystem generally want users to stay current with system updates &#8212; it reduces the burden of maintaining compatibility across multiple versions and lets users benefit from new APIs sooner. The reality, though, is that a portion of users will always choose to lock their devices to a particular version, whether for performance, battery life, habit, or privacy reasons.</p><p>This episode may leave two lasting marks. On one side, Apple &#8212; under pressure &#8212; broke from a long-held update policy and made a concession to users who had deliberately chosen to stay on older software. On the other, the widespread attention the attacks received may nudge more users to reconsider the &#8220;update only when necessary&#8221; mindset and return to a more proactive stance toward system updates. That shift in both directions might just be the unexpected upside of an otherwise alarming security event.</p><p><a href="https://fatbobman.com/en/weekly/issue-129/">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/w0130-01">Animatable in SwiftUI Explained - Complete Guide with Examples &amp; Deep Dive</a></strong></h3><p>There is no shortage of articles exploring SwiftUI&#8217;s animation system, yet this piece by <a href="https://x.com/sagarunagar_">Sagar Unagar</a> offers a particularly insightful perspective. Rather than starting from implicit or explicit animations, it builds a systematic understanding around the <code>Animatable</code> protocol: from the role of <code>animatableData</code>, to how <code>AnimatablePair</code> carries multiple interpolated values, and finally to enabling more complex data structures to participate in animations via custom <code>VectorArithmetic</code>.</p><p>The most valuable takeaway is its core viewpoint: SwiftUI is not animating views directly&#8212;it is animating data.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-02">Localization in Swift Packages</a></strong></h3><p>Xcode can automatically generate type-safe Swift symbols for <code>.xcstrings</code> files, but these symbols are only visible within the module that owns the resources. Once localization is extracted into a standalone <code>Localization</code> package, other feature modules lose the benefit of compile-time checks.</p><p><a href="https://bsky.app/profile/khanwinter.com">Khan Winter</a> proposes a straightforward solution: use a bash script to parse the JSON structure of <code>.xcstrings</code> and generate a <code>public extension LocalizedStringResource</code>, allowing all modules to access keys via <code>.l10n.helloWorld</code>.</p><p>One particularly noteworthy detail is the use of <code>@dynamicMemberLookup</code> in Debug builds&#8212;missing keys log warnings instead of crashing, while Release builds retain full compile-time validation. Compared to approaches based on Swift executables, this solution is lightweight and easy to adopt&#8212;just copy the script.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-03">SwiftUI Coordinator Pattern: Navigation Without NavigationLink</a></strong></h3><p>Although SwiftUI continues to evolve its state-driven navigation APIs, managing global navigation remains a persistent challenge. <a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> demonstrates a Coordinator-based approach using a five-tab music collection app as an example.</p><p>The idea is to extract navigation decisions from views: define all destinations in a <code>Route</code> enum, let a single Coordinator own navigation state and perform transitions, and have views simply declare &#8220;where to go&#8221; without caring about &#8220;how to get there.&#8221;</p><p>The article does not shy away from real-world tradeoffs, such as the opacity of <code>NavigationPath</code> and the complications of making route-carrying model objects conform to <code>Hashable</code>. For most mid-sized SwiftUI applications, this is a pragmatic and implementable approach to regaining control over navigation.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-04">Teach your AI to write Swift the Hacking with Swift way</a></strong></h3><p><a href="https://x.com/twostraws">Paul Hudson</a> and his Hacking with Swift have helped many developers get started with Swift and SwiftUI. In the age of AI, Paul is not only releasing specialized skills for Apple platform development, but also experimenting with injecting his personal coding style into AI collaboration.</p><p>In this article, he shares a highly distinctive (and characteristically humorous) <code>AGENTS.md</code> configuration. These rules go beyond technical choices&#8212;they embed Paul&#8217;s personality into the AI: prioritize showing results before explanations, favor clarity over cleverness, and even encourage a well-timed &#8220;Boom!&#8221; when code turns out particularly satisfying.</p><p>Rather than a simple system prompt, this feels more like defining a coding philosophy for AI. In a sense, it pushes code generation beyond mechanical output toward something closer to style transfer.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-05">The Principles and Practices of AI Agents</a></strong></h3><p>At the recent <a href="https://letsvision.swiftgg.team/">Let&#8217;s Vision 2026</a>, <a href="https://x.com/onevcat">Wang Wei (Onevcat)</a> delivered a talk on applying AI agents within large development teams. The focus was not on specific tools, but on how development workflows should evolve when the cost of code generation drops dramatically&#8212;and how the role of engineers should be redefined.</p><p>As a member of the LINE development team, Onevcat&#8217;s own work has already shifted in recent months. In his words, he is transitioning from a traditional iOS engineer to someone exploring how AI can support large-scale product development. This perspective gives the talk a depth that goes beyond typical tool introductions.</p><p>The talk revolves around three key questions: how to control context pollution, how to turn individual experience into reusable team-level memory and skills, and how to evolve collaboration from &#8220;humans directing multiple agents&#8221; toward more automated workflows. It includes many practical suggestions, such as keeping AGENTS.md concise, providing architectural lookup scripts, encouraging multiple harnesses (Claude Code, Codex, OpenCode) to coexist, and integrating agents into workflows via webhooks, cron jobs, pipelines, and automated validation.</p><blockquote><p>The <a href="https://github.com/onevcat/2026-let-s-vision">presentation repository</a> includes not only the Slidev source but also supporting materials such as raw research and full AI collaboration traces&#8212;well worth exploring.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-06">From Zero: The Complete Guide to Building a Native iOS App with AI</a></strong></h3><p>I often see &#8220;non-developers&#8221; on social media building products entirely with AI. Even after using AI tools for quite some time, I still find myself wondering: is this path really as effective as it seems?</p><p><a href="https://www.linkedin.com/in/zacharyzhangee/">Zachary Zhang</a> shares a full end-to-end journey of building and shipping a native iOS app (SwiftUI + Cloudflare backend) entirely with AI. What stands out most is his disciplined engineering pipeline: before generating any code, he first produces a structured PRD and HTML-based visual references. For tooling, he strongly recommends terminal-based tools like Claude Code during the &#8220;0 to 1&#8221; phase, as they provide better visibility and control when constructing a multi-file project architecture.</p><blockquote><p>You might share the same skepticism about fully AI-driven development. But as code generation becomes increasingly cheap, the true leverage of developers is shifting toward precise requirement decomposition, architectural control, and the ability to orchestrate systems in response to errors.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0130-07">Slots: A Macro for Improving Custom SwiftUI Component Design</a></strong></h3><p>Composing multiple views into reusable components is a common need in SwiftUI&#8212;especially for teams and library authors. However, once a component introduces multiple generic slots (title, icon, image, action, etc.), initializer combinations can quickly explode.</p><p>The Slots macro by <a href="https://mastodon.social/@kylebshr">Kyle Bashour</a> addresses this problem by generating initializer combinations automatically based on declared slot properties, eliminating the need to manually write numerous <code>init</code> overloads. For text-friendly slots, <code>@Slot(.text)</code> can also generate <code>LocalizedStringKey</code> and <code>String</code> variants automatically.</p><p>Slots is particularly well-suited for building design system components such as Card, Row, Banner, and Toolbar&#8212;where both ease of use and flexibility are required.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-08">Explore SwiftUI: A Visual Reference for Native Components and Modifiers</a></strong></h3><p>Although Apple&#8217;s documentation has improved over the years, SwiftUI&#8212;being declarative and visually driven&#8212;still lacks intuitive side-by-side mappings between code and UI results, especially across platforms like iOS, macOS, and visionOS.</p><p>As a result, developers often resort to complex third-party libraries or verbose custom views for UI details that SwiftUI might already support natively.</p><p><a href="https://x.com/Typ0genius">Florian</a> created Explore SwiftUI as a &#8220;visual dictionary&#8221; to address this gap. It focuses entirely on native components, with no third-party abstractions. Code examples are stripped of unrelated logic and paired with high-quality previews&#8212;allowing developers to simply copy, paste, and run.</p><h2><strong>Book</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0130-09">SwiftUI Architecture: Patterns and Practices for Building Scalable Applications</a></strong></h3><p>This is a recently published book by <a href="https://x.com/azamsharp">Mohammad Azam</a>. It is not an introductory guide to <code>VStack</code> or animations, but a deep dive into SwiftUI architecture, data flow, and modern engineering practices.</p><p>The book addresses real production challenges, such as building global Sheets and Toasts, designing decoupled multi-tab routing with <code>NavigationPath</code>, and implementing elegant form validation using property wrappers. Importantly, it does not enforce a rigid architectural pattern, but instead helps you develop a true declarative mindset.</p><p>Some might wonder whether architecture-focused books still matter in the age of AI-assisted coding. As Azam puts it: AI makes code generation cheap&#8212;but precisely because of that, system design (clear boundaries and ownership of state) becomes more important than ever.</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-130?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-130?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#33529;&#26524;&#30340;&#32597;&#35265;&#22949;&#21327;&#65306;&#24403;&#39640;&#21361;&#28431;&#27934;&#36935;&#19978;&#8220;&#25298;&#21319;&#8221;&#28526;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-130/">&#32593;&#39029;&#29256;</a></strong></p><p>&#23545;&#20110; iOS &#29992;&#25143;&#26469;&#35828;&#65292;&#26368;&#36817;&#25110;&#22810;&#25110;&#23569;&#37117;&#20250;&#30475;&#21040;&#19982; Coruna&#12289;DarkSword &#26377;&#20851;&#30340;&#39640;&#21361;&#28431;&#27934;&#28040;&#24687;&#12290;&#20004;&#20010;&#25915;&#20987;&#38142;&#22343;&#37319;&#29992;&#27700;&#22353;&#25915;&#20987;&#30340;&#26041;&#24335;&#65292;&#25915;&#20987;&#32773;&#26080;&#38656;&#21463;&#23475;&#32773;&#36827;&#34892;&#20219;&#20309;&#20132;&#20114;&#65292;&#20165;&#38656;&#35775;&#38382;&#19968;&#20010;&#34987;&#26893;&#20837;&#24694;&#24847; iframe &#30340;&#21512;&#27861;&#32593;&#31449;&#25110;&#21152;&#36733;&#24694;&#24847;&#24191;&#21578;&#65292;&#21363;&#21487;&#35302;&#21457;&#23436;&#25972;&#30340;&#25915;&#20987;&#38142;&#65292;&#22312;&#31363;&#21462;&#36164;&#26009;&#21518;&#33258;&#21160;&#28165;&#29702;&#25915;&#20987;&#30165;&#36857;&#12290;&#30001;&#20110;&#24037;&#20855;&#38142;&#21033;&#29992;&#30340;&#28431;&#27934;&#23384;&#22312;&#20110; iOS 13 &#33267; 18.7 &#30340;&#32477;&#22823;&#22810;&#25968;&#29256;&#26412;&#20013;&#65292;&#25130;&#27490;&#30446;&#21069;&#65292;&#24050;&#26377;&#19978;&#20159;&#29992;&#25143;&#21463;&#21040;&#24433;&#21709;&#12290;</p><p>Coruna &#20027;&#35201;&#38024;&#23545; iOS 13 &#33267; iOS 17 &#30340;&#35774;&#22791;&#65292;&#22312;&#36807;&#21435;&#20960;&#20010;&#26376;&#38388;&#65292;&#33529;&#26524;&#24050;&#20026;&#36825;&#20123;&#31995;&#32479;&#25512;&#36865;&#20102;&#22810;&#27425;&#23433;&#20840;&#26356;&#26032;&#12290;DarkSword &#21017;&#20027;&#35201;&#38024;&#23545; iOS 18.4 &#33267; 18.7 &#30340;&#35774;&#22791;&#12290;&#23613;&#31649;&#36825;&#37096;&#20998;&#35774;&#22791;&#22343;&#20855;&#22791;&#21319;&#32423;&#33267; iOS 26 &#30340;&#30828;&#20214;&#26465;&#20214;&#65292;&#20294;&#30001;&#20110;&#31181;&#31181;&#21407;&#22240;&#65292;&#20173;&#26377;&#19981;&#23569; iOS 18 &#29992;&#25143;&#36873;&#25321;&#25353;&#20853;&#19981;&#21160;&#12290;</p><p>&#22312;&#24456;&#38271;&#19968;&#27573;&#26102;&#38388;&#37324;&#65292;&#33529;&#26524;&#29992;&#25143;&#23545;&#20110;&#31995;&#32479;&#26356;&#26032;&#30340;&#24577;&#24230;&#37117;&#30456;&#24403;&#31215;&#26497;&#65292;&#36825;&#20063;&#26159;&#33529;&#26524;&#29983;&#24577;&#30340;&#19968;&#22823;&#29305;&#33394;&#12290;&#20294;&#36825;&#19968;&#36235;&#21183;&#22312;&#21435;&#24180;&#20986;&#29616;&#20102;&#21464;&#21270;&#8212;&#8212;Liquid Glass &#24102;&#26469;&#30340;&#24040;&#22823;&#35270;&#35273;&#20914;&#20987;&#65292;&#35753;&#33529;&#26524;&#29992;&#25143;&#20013;&#31532;&#19968;&#27425;&#20986;&#29616;&#20102;&#30456;&#24403;&#27604;&#20363;&#20027;&#21160;&#25298;&#32477;&#21319;&#32423;&#21040; iOS 26 &#30340;&#29616;&#35937;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#20026;&#36981;&#23432;&#33521;&#22269;&#12298;&#32593;&#32476;&#23433;&#20840;&#27861;&#12299;&#65288;Online Safety Act&#65289;&#30340;&#35201;&#27714;&#65292;&#33529;&#26524;&#22312; iOS 26.4 &#20013;&#20026;&#33521;&#22269;&#29992;&#25143;&#24341;&#20837;&#20102;&#24378;&#21046;&#24180;&#40836;&#39564;&#35777;&#26426;&#21046;&#65292;&#30001;&#20110;&#39564;&#35777;&#26465;&#20214;&#20005;&#33499;&#65292;&#19981;&#23569;&#25104;&#24180;&#29992;&#25143;&#29978;&#33267;&#34987;&#31995;&#32479;&#24378;&#34892;&#38145;&#20837;&#8216;&#20799;&#31461;&#27169;&#24335;&#8217;&#65292;&#36827;&#19968;&#27493;&#25512;&#21160;&#20102;&#33521;&#22269;&#29992;&#25143;&#20572;&#30041;&#22312; iOS 18 &#25110; iOS 26.3 &#30340;&#39118;&#28526;&#12290;&#32780;&#25298;&#32477;&#23433;&#35013;&#26032;&#29256;&#26412;&#65292;&#24847;&#21619;&#30528;&#36825;&#37096;&#20998;&#29992;&#25143;&#21516;&#26102;&#25918;&#24323;&#20102;&#21518;&#32493;&#25152;&#26377;&#23433;&#20840;&#34917;&#19969;&#65292;&#35753;&#35774;&#22791;&#36827;&#19968;&#27493;&#26292;&#38706;&#22312;&#28508;&#22312;&#39118;&#38505;&#20043;&#19979;&#12290;</p><p>&#38754;&#23545;&#36825;&#19968;&#23616;&#38754;&#65292;&#33529;&#26524;&#25215;&#21463;&#20102;&#26126;&#26174;&#30340;&#33286;&#35770;&#21387;&#21147;&#19982;&#21697;&#29260;&#39118;&#38505;&#12290;&#29305;&#21035;&#26159;&#22312; 3 &#26376;&#19979;&#26092;&#65292;DarkSword &#30340;&#23436;&#25972;&#25915;&#20987;&#20195;&#30721;&#34987;&#27844;&#38706;&#21040;&#20102; GitHub &#19978;&#65292;&#35753;&#36825;&#19968;&#22269;&#23478;&#32423;&#40657;&#23458;&#24037;&#20855;&#30636;&#38388;&#24179;&#27665;&#21270;&#65292;&#30452;&#25509;&#36843;&#20351;&#33529;&#26524;&#24517;&#39035;&#37319;&#21462;&#32039;&#24613;&#34892;&#21160;&#12290;&#26368;&#32456;&#65292;&#33529;&#26524;&#32597;&#35265;&#22320;&#20026; iOS 18 &#21333;&#29420;&#25512;&#20986;&#20102;&#23433;&#20840;&#34917;&#19969; iOS 18.7.7&#65292;&#23558;&#21407;&#26412;&#20165;&#29992;&#20110; iOS 26 &#30340;&#38450;&#25252;&#26426;&#21046;&#22238;&#31227;&#26893;&#21040;&#26087;&#31995;&#32479;&#12290;&#33267;&#27492;&#65292;&#33529;&#26524;&#23436;&#25104;&#20102;&#38024;&#23545;&#26412;&#27425;&#39640;&#21361;&#28431;&#27934;&#30340;&#20840;&#37096;&#23448;&#26041;&#23433;&#20840;&#21709;&#24212;&#12290;</p><p>&#26080;&#35770;&#26159;&#33529;&#26524;&#36824;&#26159;&#29983;&#24577;&#20013;&#30340;&#24320;&#21457;&#32773;&#65292;&#22823;&#22810;&#24076;&#26395;&#29992;&#25143;&#33021;&#31215;&#26497;&#36319;&#36827;&#31995;&#32479;&#26356;&#26032;&#8212;&#8212;&#26082;&#33021;&#20943;&#23569;&#22810;&#29256;&#26412;&#36866;&#37197;&#30340;&#32500;&#25252;&#36127;&#25285;&#65292;&#20063;&#33021;&#35753;&#29992;&#25143;&#23613;&#24555;&#20139;&#21463;&#21040;&#26032; API &#24102;&#26469;&#30340;&#20415;&#21033;&#12290;&#20294;&#29616;&#23454;&#26159;&#65292;&#22987;&#32456;&#26377;&#19968;&#37096;&#20998;&#29992;&#25143;&#20986;&#20110;&#24615;&#33021;&#12289;&#32493;&#33322;&#12289;&#20351;&#29992;&#20064;&#24815;&#20035;&#33267;&#38544;&#31169;&#31561;&#26041;&#38754;&#30340;&#32771;&#37327;&#65292;&#26377;&#24847;&#23558;&#35774;&#22791;&#38145;&#23450;&#22312;&#26576;&#20010;&#29256;&#26412;&#12290;</p><p>&#26412;&#27425;&#20107;&#20214;&#25110;&#35768;&#20250;&#24102;&#26469;&#20004;&#20010;&#26041;&#21521;&#19978;&#30340;&#21464;&#21270;&#65306;&#33529;&#26524;&#22312;&#21387;&#21147;&#19979;&#35843;&#25972;&#20102;&#38271;&#26399;&#22362;&#23432;&#30340;&#26356;&#26032;&#31574;&#30053;&#65292;&#20026;&#21051;&#24847;&#30041;&#23432;&#26087;&#31995;&#32479;&#30340;&#29992;&#25143;&#20570;&#20986;&#20102;&#22949;&#21327;&#65307;&#32780;&#20107;&#20214;&#26412;&#36523;&#30340;&#24191;&#27867;&#20256;&#25773;&#65292;&#20063;&#21487;&#33021;&#20419;&#20351;&#26356;&#22810;&#29992;&#25143;&#20174;&#23433;&#20840;&#35282;&#24230;&#37325;&#26032;&#23457;&#35270;&#8220;&#33021;&#19981;&#26356;&#26032;&#23601;&#19981;&#26356;&#26032;&#8221;&#30340;&#24815;&#24615;&#65292;&#22238;&#21040;&#31215;&#26497;&#26356;&#26032;&#30340;&#36712;&#36947;&#12290;&#36825;&#31181;&#21452;&#21521;&#30340;&#25913;&#21464;&#65292;&#25110;&#35768;&#27491;&#26159;&#36825;&#22330;&#39118;&#27874;&#24847;&#26009;&#20043;&#22806;&#30340;&#25910;&#33719;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-129/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0130-01">&#36890;&#36807; Animatable &#28145;&#20837; SwiftUI &#21160;&#30011; (Animatable in SwiftUI Explained - Complete Guide with Examples &amp; Deep Dive)</a></strong></h3><p>&#32593;&#32476;&#19978;&#24182;&#19981;&#32570;&#23569;&#25506;&#35752; SwiftUI &#21160;&#30011;&#26426;&#21046;&#30340;&#25991;&#31456;&#65292;&#20294; <a href="https://x.com/sagarunagar_">Sagar Unagar</a>&#65532;&#30340;&#36825;&#31687;&#20173;&#28982;&#25552;&#20379;&#20102;&#19968;&#20010;&#39047;&#20855;&#21551;&#21457;&#24615;&#30340;&#20999;&#20837;&#28857;&#12290;&#20182;&#27809;&#26377;&#20174;&#38544;&#24335;&#25110;&#26174;&#24335;&#21160;&#30011;&#20837;&#25163;&#65292;&#32780;&#26159;&#22260;&#32469; Animatable &#21327;&#35758;&#20570;&#20102;&#19968;&#27425;&#31995;&#32479;&#26803;&#29702;&#65306;&#20174; animatableData &#30340;&#20316;&#29992;&#65292;&#21040; AnimatablePair &#22914;&#20309;&#25215;&#36733;&#22810;&#20010;&#25554;&#20540;&#21442;&#25968;&#65292;&#20877;&#21040;&#36890;&#36807;&#33258;&#23450;&#20041; VectorArithmetic &#35753;&#26356;&#22797;&#26434;&#30340;&#25968;&#25454;&#32467;&#26500;&#21442;&#19982;&#21160;&#30011;&#12290;&#25991;&#31456;&#26368;&#20540;&#24471;&#27880;&#24847;&#30340;&#19968;&#28857;&#22312;&#20110;&#20854;&#26680;&#24515;&#35270;&#35282;&#65306;SwiftUI &#23454;&#38469;&#19978;&#26159;&#22312;&#8220;&#21160;&#30011;&#25968;&#25454;&#8221;&#65292;&#32780;&#38750;&#30452;&#25509;&#23545;&#35270;&#22270;&#36827;&#34892;&#21160;&#30011;&#22788;&#29702;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-02">&#22312; Swift Package &#20013;&#20849;&#20139;&#26412;&#22320;&#21270;&#36164;&#28304; (Localization in Swift Packages)</a></strong></h3><p>Xcode &#33021;&#20026; <code>.xcstrings</code> &#25991;&#20214;&#33258;&#21160;&#29983;&#25104;&#31867;&#22411;&#23433;&#20840;&#30340; Swift &#31526;&#21495;&#65292;&#20294;&#36825;&#20123;&#31526;&#21495;&#20165;&#22312;&#36164;&#28304;&#25152;&#22312;&#30340; module &#20869;&#21487;&#35265;&#8212;&#8212;&#19968;&#26086;&#23558;&#26412;&#22320;&#21270;&#36164;&#28304;&#25277;&#31163;&#20026;&#29420;&#31435;&#30340; <code>Localization</code> &#21253;&#65292;&#20854;&#20182; feature &#21253;&#20415;&#26080;&#27861;&#20139;&#21463;&#32534;&#35793;&#26399;&#26816;&#26597;&#30340;&#20248;&#21183;&#12290;<a href="https://bsky.app/profile/khanwinter.com">Khan Winter</a> &#30340;&#35299;&#20915;&#26041;&#26696;&#30456;&#24403;&#30452;&#25509;&#65306;&#36890;&#36807;&#19968;&#20010; bash &#33050;&#26412;&#35299;&#26512; <code>.xcstrings</code> &#30340; JSON &#32467;&#26500;&#65292;&#29983;&#25104; <code>public extension LocalizedStringResource</code> &#25193;&#23637;&#65292;&#20351;&#25152;&#26377;&#27169;&#22359;&#37117;&#33021;&#20197; <code>.l10n.helloWorld</code> &#30340;&#24418;&#24335;&#35775;&#38382;&#32763;&#35793;&#38190;&#12290;</p><p>&#20854;&#20013;&#19968;&#20010;&#39047;&#20855;&#21442;&#32771;&#20215;&#20540;&#30340;&#32454;&#33410;&#26159; Debug &#27169;&#24335;&#19979;&#30340; <code>@dynamicMemberLookup</code> &#35774;&#35745;&#8212;&#8212;&#35775;&#38382;&#19981;&#23384;&#22312;&#30340;&#38190;&#26102;&#20165;&#35760;&#24405;&#26085;&#24535;&#32780;&#19981;&#23849;&#28291;&#65292;&#32780;&#22312; Release &#26500;&#24314;&#20013;&#20173;&#20445;&#30041;&#23436;&#25972;&#30340;&#32534;&#35793;&#26399;&#26657;&#39564;&#12290;&#30456;&#27604;&#22522;&#20110; Swift &#21487;&#25191;&#34892;&#25991;&#20214;&#30340;&#26041;&#26696;&#65292;&#36825;&#31181;&#23454;&#29616;&#26356;&#21152;&#36731;&#37327;&#65292;&#22797;&#21046;&#33050;&#26412;&#21363;&#21487;&#20351;&#29992;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-03">Coordinator &#20840;&#23616;&#23548;&#33322;&#27169;&#24335; (SwiftUI Coordinator Pattern: Navigation Without NavigationLink)</a></strong></h3><p>&#23613;&#31649; SwiftUI &#19968;&#30452;&#22312;&#20016;&#23500;&#22522;&#20110;&#29366;&#24577;&#39537;&#21160;&#30340;&#23548;&#33322; API&#65292;&#20294;&#31649;&#29702;&#20840;&#23616;&#23548;&#33322;&#19968;&#30452;&#26159; SwiftUI &#20013;&#30340;&#19968;&#20010;&#8220;&#30171;&#28857;&#8221;&#12290;<a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> &#20197;&#19968;&#20010;&#20116; Tab &#30340;&#38899;&#20048;&#25910;&#34255;&#24212;&#29992;&#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#22914;&#20309;&#36890;&#36807; Coordinator &#27169;&#24335;&#23558;&#23548;&#33322;&#20915;&#31574;&#20174; View &#20013;&#25277;&#31163;&#65306;&#29992;&#19968;&#20010; Route &#26522;&#20030;&#32479;&#19968;&#25551;&#36848;&#25152;&#26377;&#30446;&#30340;&#22320;&#65292;&#30001;&#21333;&#19968;&#30340; Coordinator &#23545;&#35937;&#25345;&#26377;&#23548;&#33322;&#29366;&#24577;&#24182;&#25191;&#34892;&#36339;&#36716;&#65292;View &#21482;&#38656;&#22768;&#26126;&#8220;&#21435;&#21738;&#8221;&#32780;&#26080;&#38656;&#20851;&#24515;&#8220;&#24590;&#20040;&#21435;&#8221;&#12290;&#25991;&#31456;&#27809;&#26377;&#22238;&#36991; NavigationPath &#19981;&#36879;&#26126;&#12289;&#36335;&#30001;&#25658;&#24102;&#27169;&#22411;&#23545;&#35937;&#23548;&#33268;&#30340; Hashable &#22256;&#22659;&#31561;&#23454;&#38469;&#38382;&#39064;&#12290;&#23545;&#20110;&#22823;&#22810;&#25968;&#20013;&#31561;&#35268;&#27169;&#30340; SwiftUI &#24212;&#29992;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20010;&#21153;&#23454;&#19988;&#26131;&#20110;&#33853;&#22320;&#30340;&#23548;&#33322;&#27835;&#29702;&#26041;&#26696;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-04">&#25226; Hacking with Swift &#30340;&#32534;&#31243;&#39118;&#26684;&#20889;&#36827; AI (Teach your AI to write Swift the Hacking with Swift way)</a></strong></h3><p><a href="https://x.com/twostraws">Paul Hudson</a> &#21644;&#20182;&#30340; Hacking with Swift &#35753;&#24456;&#22810;&#24320;&#21457;&#32773;&#36208;&#19978;&#20102; Swift &#19982; SwiftUI &#30340;&#23398;&#20064;&#20043;&#36335;&#12290;&#22312; AI &#26102;&#20195;&#65292;Paul &#19981;&#20165;&#25512;&#20986;&#20102;&#38754;&#21521;&#33529;&#26524;&#24320;&#21457;&#29983;&#24577;&#30340;&#21508;&#31867;&#19987;&#19994; Skill&#65292;&#20063;&#24320;&#22987;&#23581;&#35797;&#22312;&#19982; AI &#30340;&#21327;&#20316;&#20013;&#27880;&#20837;&#26356;&#20855;&#20010;&#20154;&#29305;&#36136;&#30340;&#32534;&#31243;&#39118;&#26684;&#12290;</p><p>&#22312;&#26412;&#25991;&#20013;&#65292;&#20182;&#20998;&#20139;&#20102;&#19968;&#20221;&#26497;&#20855;&#36776;&#35782;&#24230;&#65288;&#19988;&#20805;&#28385;&#20182;&#26631;&#24535;&#24615;&#24189;&#40664;&#65289;&#30340; <code>AGENTS.md</code> &#37197;&#32622;&#12290;&#36825;&#22871;&#35268;&#21017;&#19981;&#20165;&#32422;&#26463;&#20102; AI &#30340;&#25216;&#26415;&#36873;&#22411;&#65292;&#36824;&#20026; AI &#27880;&#20837;&#20102; Paul &#30340;&#28789;&#39746;&#65306;&#24378;&#35843;&#20808;&#23637;&#31034;&#32467;&#26524;&#20877;&#35299;&#37322;&#21407;&#29702;&#12289;&#20559;&#22909;&#28165;&#26224;&#32780;&#38750;&#28843;&#25216;&#12289;&#29978;&#33267;&#21253;&#25324;&#22312;&#20195;&#30721;&#20889;&#24471;&#28418;&#20142;&#26102;&#36866;&#26102;&#22320;&#21898;&#20986;&#19968;&#21477; &#8220;Boom!&#8221;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#20221;&#29992;&#20110; AI &#30340;&#8220;&#31995;&#32479;&#25552;&#31034;&#35789;&#8221;&#65292;&#19981;&#22914;&#35828;&#26159;&#22312;&#20026; AI &#23450;&#20041;&#19968;&#31181;&#32534;&#30721;&#21746;&#23398;&#8212;&#8212;&#26576;&#31181;&#31243;&#24230;&#19978;&#65292;&#36825;&#31181;&#26041;&#24335;&#27491;&#22312;&#23558;&#20919;&#20912;&#20912;&#30340;&#8220;&#20195;&#30721;&#29983;&#25104;&#8221;&#25512;&#21521;&#24102;&#26377;&#20154;&#24773;&#21619;&#30340;&#8220;&#39118;&#26684;&#36801;&#31227;&#8221;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-05">AI Agent &#30340;&#36947;&#19982;&#26415;</a></strong></h3><p>&#22312;&#21018;&#36807;&#21435;&#30340; <a href="https://letsvision.swiftgg.team/">Let&#8217;s Vision 2026</a> &#20013;&#65292;<a href="https://x.com/onevcat">&#29579;&#24013;&#65288;Onevcat&#65289;</a> &#21457;&#34920;&#20102;&#20851;&#20110;&#22312;&#22823;&#22411;&#24320;&#21457;&#22242;&#38431;&#20013;&#24212;&#29992; AI Agent &#30340;&#28436;&#35762;&#12290;&#25972;&#22330;&#20998;&#20139;&#35752;&#35770;&#30340;&#37325;&#28857;&#65292;&#24182;&#19981;&#26159;&#26576;&#20010;&#20855;&#20307;&#24037;&#20855;&#26377;&#22810;&#24378;&#65292;&#32780;&#26159;&#24403;&#20195;&#30721;&#23454;&#29616;&#25104;&#26412;&#34987;&#36805;&#36895;&#21387;&#20302;&#21518;&#65292;&#22242;&#38431;&#35813;&#22914;&#20309;&#37325;&#26032;&#32452;&#32455;&#24320;&#21457;&#27969;&#31243;&#65292;&#20197;&#21450;&#24037;&#31243;&#24072;&#30340;&#20215;&#20540;&#35813;&#22914;&#20309;&#37325;&#26032;&#23450;&#20301;&#12290;</p><p>&#20316;&#20026; LINE &#24212;&#29992;&#24320;&#21457;&#22242;&#38431;&#30340;&#19968;&#21592;&#65292;Onevcat &#22312;&#36807;&#21435;&#20960;&#20010;&#26376;&#20013;&#30340;&#24037;&#20316;&#37325;&#24515;&#20063;&#24050;&#26126;&#26174;&#21457;&#29983;&#21464;&#21270;&#12290;&#29992;&#20182;&#33258;&#24049;&#30340;&#35805;&#35828;&#65292;&#20182;&#27491;&#22312;&#36880;&#27493;&#20174;&#20256;&#32479;&#24847;&#20041;&#19978;&#30340; iOS &#24037;&#31243;&#24072;&#65292;&#36716;&#21521;&#25506;&#32034;&#22914;&#20309;&#23558; AI &#24212;&#29992;&#20110;&#26381;&#21153;&#22823;&#22411;&#20135;&#21697;&#30740;&#21457;&#22242;&#38431;&#30340;&#23454;&#36341;&#32773;&#12290;&#36825;&#31181;&#35282;&#33394;&#19978;&#30340;&#21464;&#21270;&#65292;&#20063;&#35753;&#36825;&#22330;&#20998;&#20139;&#27604;&#19968;&#33324;&#30340;&#24037;&#20855;&#20171;&#32461;&#26356;&#26377;&#35828;&#26381;&#21147;&#12290;</p><p>&#28436;&#35762;&#22260;&#32469;&#19977;&#20010;&#20851;&#38190;&#38382;&#39064;&#23637;&#24320;&#65306;&#22914;&#20309;&#25511;&#21046;&#19978;&#19979;&#25991;&#27745;&#26579;&#65292;&#22914;&#20309;&#25226;&#20010;&#20154;&#32463;&#39564;&#27785;&#28096;&#20026;&#22242;&#38431;&#21487;&#22797;&#29992;&#30340; memory &#19982; skill&#65292;&#20197;&#21450;&#22914;&#20309;&#35753;&#21327;&#20316;&#27169;&#24335;&#20174;&#8220;&#20154;&#25351;&#25381;&#22810;&#20010; Agent&#8221;&#36880;&#27493;&#36208;&#21521;&#26356;&#33258;&#21160;&#21270;&#30340;&#38381;&#29615;&#12290;&#37324;&#38754;&#26377;&#19981;&#23569;&#30456;&#24403;&#25509;&#22320;&#27668;&#30340;&#23454;&#36341;&#24314;&#35758;&#65292;&#20363;&#22914;&#23558; AGENTS.md &#25511;&#21046;&#22312;&#31934;&#31616;&#33539;&#22260;&#20869;&#12289;&#20026; Agent &#25552;&#20379;&#27169;&#22359;&#23450;&#20301;&#19982;&#26550;&#26500;&#36895;&#26597;&#33050;&#26412;&#12289;&#40723;&#21169; Claude Code&#12289;Codex&#12289;OpenCode &#31561;&#22810;&#31181; harness &#24182;&#23384;&#65292;&#20197;&#21450;&#36890;&#36807; webhook&#12289;cron&#12289;pipeline &#21644;&#33258;&#21160;&#39564;&#25910;&#26426;&#21046;&#35753; Agent &#30495;&#27491;&#36827;&#20837;&#22242;&#38431;&#27969;&#31243;&#12290;</p><blockquote><p><a href="https://github.com/onevcat/2026-let-s-vision">&#28436;&#35762;&#31295;&#20179;&#24211;</a> &#20013;&#19981;&#20165;&#21253;&#21547;&#23436;&#25972;&#30340; Slidev &#28304;&#30721;&#65292;&#20063;&#20445;&#30041;&#20102;&#19981;&#23569;&#28436;&#35762;&#37197;&#22871;&#26448;&#26009;&#65292;&#21253;&#25324;&#21407;&#22987;&#36164;&#26009;&#25910;&#38598;&#21644;&#19982; AI &#21327;&#20316;&#30340;&#23436;&#25972; trace&#65292;&#20540;&#24471;&#19968;&#24182;&#38405;&#35835;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-06">&#20174;&#38646;&#24320;&#22987;&#65306;&#29992; AI &#24320;&#21457;&#19968;&#20010; iOS &#21407;&#29983; APP &#23436;&#25972;&#25351;&#21335;</a></strong></h3><p>&#25105;&#32463;&#24120;&#20250;&#22312;&#31038;&#20132;&#23186;&#20307;&#19978;&#30475;&#21040;&#19968;&#20123;&#38646;&#22522;&#30784;&#30340;&#8220;&#24320;&#21457;&#32773;&#8221;&#36890;&#36807; AI &#26500;&#24314;&#20102;&#33258;&#24049;&#30340;&#20135;&#21697;&#25110;&#26381;&#21153;&#12290;&#23613;&#31649;&#25105;&#20351;&#29992; AI &#30340;&#26102;&#38388;&#20063;&#19981;&#30701;&#65292;&#20294;&#25105;&#20173;&#28982;&#27604;&#36739;&#22256;&#24785;&#65306;&#36825;&#26465;&#36335;&#24452;&#30495;&#30340;&#20687;&#22823;&#23478;&#25551;&#36848;&#30340;&#37027;&#26679;&#26377;&#25928;&#21527;&#65311;<a href="https://www.linkedin.com/in/zacharyzhangee/">Zachary Zhang</a> &#20998;&#20139;&#20102;&#20182;&#23436;&#20840;&#20511;&#21161; AI &#24037;&#20855;&#65292;&#20174;&#38646;&#26500;&#24314;&#24182;&#19978;&#26550;&#19968;&#27454;&#32431;&#21407;&#29983; iOS &#24212;&#29992;&#65288;SwiftUI + Cloudflare &#21518;&#31471;&#65289;&#30340;&#23454;&#25112;&#20840;&#36807;&#31243;&#12290;&#36825;&#31687;&#25991;&#31456;&#26368;&#35753;&#25105;&#21360;&#35937;&#28145;&#21051;&#30340;&#65292;&#26159;&#20182;&#20005;&#35880;&#30340;&#8220;&#24037;&#31243;&#21270;&#31649;&#32447;&#8221;&#65306;&#22312;&#35753; AI &#20889;&#20195;&#30721;&#21069;&#65292;&#24517;&#39035;&#20808;&#29983;&#25104;&#32467;&#26500;&#21270;&#30340; PRD &#21644; HTML &#26684;&#24335;&#30340;&#35270;&#35273;&#21442;&#32771;&#65307;&#32780;&#22312;&#24037;&#20855;&#36873;&#25321;&#19978;&#65292;&#20182;&#22312;&#39033;&#30446;&#8220;&#20174; 0 &#21040; 1&#8221;&#30340;&#20919;&#21551;&#21160;&#38454;&#27573;&#65292;&#26497;&#21147;&#25512;&#33616; Claude Code &#31561;&#32456;&#31471;&#24037;&#20855;&#65292;&#20197;&#20415;&#26356;&#22909;&#22320;&#32479;&#35272;&#20840;&#23616;&#65292;&#19968;&#27425;&#24615;&#26500;&#24314;&#20986;&#21512;&#29702;&#30340;&#22810;&#25991;&#20214;&#39033;&#30446;&#26550;&#26500;&#12290;</p><blockquote><p>&#25110;&#35768;&#20320;&#21644;&#25105;&#19968;&#26679;&#65292;&#23545;&#20110; 100% &#22522;&#20110; AI &#30340;&#24320;&#21457;&#26041;&#24335;&#20173;&#23384;&#30097;&#24785;&#12290;&#20294;&#22312;&#20195;&#30721;&#29983;&#25104;&#36234;&#26469;&#36234;&#24265;&#20215;&#30340;&#20170;&#22825;&#65292;&#24320;&#21457;&#32773;&#30340;&#26680;&#24515;&#22721;&#22418;&#65292;&#27491;&#22312;&#21152;&#36895;&#21521;&#8220;&#38656;&#27714;&#31934;&#20934;&#25286;&#35299;&#8221;&#12289;&#8220;&#31995;&#32479;&#26550;&#26500;&#25226;&#25511;&#8221;&#20197;&#21450;&#8220;&#38754;&#21521;&#25253;&#38169;&#30340;&#20840;&#23616;&#35843;&#24230;&#33021;&#21147;&#8221;&#36716;&#31227;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0130-07">Slots&#65306;&#25552;&#39640;&#33258;&#23450;&#20041; SwiftUI &#32452;&#20214;&#35774;&#35745;&#25928;&#29575;&#30340;&#23439;</a></strong></h3><p>&#23558;&#22810;&#20010;&#35270;&#22270;&#32452;&#21512;&#23553;&#35013;&#25104;&#21487;&#22797;&#29992;&#32452;&#20214;&#65292;&#26159; SwiftUI &#24320;&#21457;&#20013;&#30340;&#24120;&#35265;&#38656;&#27714;&#65292;&#23545;&#22242;&#38431;&#20869;&#37096;&#24320;&#21457;&#32773;&#25110;&#31532;&#19977;&#26041;&#24211;&#20316;&#32773;&#26469;&#35828;&#26356;&#26159;&#22914;&#27492;&#12290;&#20294;&#24403;&#32452;&#20214;&#21253; title&#12289;icon&#12289;image&#12289;action &#31561;&#22810;&#20010;&#27867;&#22411; View &#25554;&#27133;&#21518;&#65292;&#21021;&#22987;&#21270;&#22120;&#30340;&#32452;&#21512;&#25968;&#37327;&#24448;&#24448;&#20250;&#36805;&#36895;&#33192;&#32960;&#12290;<a href="https://mastodon.social/@kylebshr">Kyle Bashour</a> &#21019;&#24314;&#30340; Slots &#23439;&#65292;&#27491;&#26159;&#20026;&#20102;&#35299;&#20915;&#36825;&#31867;&#22810; slot &#32452;&#20214;&#30340;&#26679;&#26495;&#20195;&#30721;&#38382;&#39064;&#12290;</p><p>&#24320;&#21457;&#32773;&#21482;&#38656;&#22768;&#26126;&#32452;&#20214;&#30340; slot &#23646;&#24615;&#65292;&#23439;&#20415;&#20250;&#25353;&#32452;&#21512;&#33258;&#21160;&#29983;&#25104;&#25152;&#38656;&#30340;&#21021;&#22987;&#21270;&#22120;&#65292;&#26080;&#38656;&#25163;&#20889;&#22823;&#37327; init &#37325;&#36733;&#12290;&#23545;&#20110;&#38656;&#35201;&#25903;&#25345;&#25991;&#26412;&#20415;&#25463;&#20889;&#27861;&#30340; slot&#65292;&#36824;&#21487;&#20197;&#36890;&#36807; <code>@Slot(.text)</code> &#33258;&#21160;&#33719;&#24471; <code>LocalizedStringKey</code> &#21644; <code>String</code> &#29256;&#26412;&#30340;&#21021;&#22987;&#21270;&#26041;&#24335;&#12290; Slots &#24456;&#36866;&#21512;&#29992;&#20110;&#26500;&#24314;&#35774;&#35745;&#31995;&#32479;&#20013;&#30340; Card&#12289;Row&#12289;Banner&#12289;Toolbar &#36825;&#31867;&#26082;&#35201;&#25903;&#25345;&#31616;&#21333;&#35843;&#29992;&#12289;&#21448;&#35201;&#20445;&#30041;&#39640;&#24230;&#23450;&#21046;&#33021;&#21147;&#30340;&#32452;&#20214;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0130-08">Explore SwiftUI&#65306;&#32431;&#21407;&#29983;&#32452;&#20214;&#19982;&#20462;&#39280;&#31526;&#30340;&#35270;&#35273;&#36895;&#26597;&#22270;&#24211;</a></strong></h3><p>&#23613;&#31649; Apple &#23448;&#26041;&#25991;&#26723;&#30340;&#36136;&#37327;&#22312;&#36880;&#24180;&#25913;&#21892;&#65292;&#20294;&#23545;&#20110;&#20197;&#22768;&#26126;&#24335;&#21644;&#35270;&#35273;&#39537;&#21160;&#20026;&#20027;&#30340; SwiftUI &#26469;&#35828;&#65292;&#23448;&#26041;&#25991;&#26723;&#20013;&#20381;&#28982;&#32570;&#20047;&#36275;&#22815;&#30452;&#35266;&#30340;&#20195;&#30721;&#19982; UI &#25928;&#26524;&#23545;&#29031;&#65292;&#23588;&#20854;&#26159;&#21516;&#19968;&#32452;&#20214;&#22312; iOS&#12289;macOS &#21644; visionOS &#31561;&#22810;&#24179;&#21488;&#19978;&#30340;&#34920;&#29616;&#24046;&#24322;&#12290;&#24456;&#22810;&#26102;&#20505;&#65292;&#24320;&#21457;&#32773;&#20026;&#20102;&#23454;&#29616;&#26576;&#20010;&#29305;&#23450;&#30340; UI &#32454;&#33410;&#65292;&#24448;&#24448;&#20250;&#21435;&#27714;&#21161;&#20110;&#22797;&#26434;&#30340;&#31532;&#19977;&#26041;&#24211;&#25110;&#25163;&#20889;&#20887;&#38271;&#30340;&#33258;&#23450;&#20041;&#35270;&#22270;&#65292;&#21364;&#24573;&#30053;&#20102; SwiftUI &#26412;&#36523;&#21487;&#33021;&#24050;&#32463;&#25552;&#20379;&#20102;&#32477;&#20339;&#30340;&#21407;&#29983;&#35299;&#20915;&#26041;&#26696;&#12290;<a href="https://x.com/Typ0genius">Florian</a> &#24314;&#31435;&#30340; Explore SwiftUI &#31449;&#28857;&#65292;&#27491;&#26159;&#19968;&#20010;&#20026;&#20102;&#35299;&#20915;&#36825;&#19968;&#30171;&#28857;&#32780;&#29983;&#30340;&#8220;&#35270;&#35273;&#36895;&#26597;&#23383;&#20856;&#8221;&#12290;&#23427;&#25682;&#24323;&#20102;&#20219;&#20309;&#31532;&#19977;&#26041;&#23553;&#35013;&#65292;&#32431;&#31929;&#20197;&#23637;&#31034; Apple &#23448;&#26041;&#20869;&#32622;&#32452;&#20214;&#30340;&#21407;&#29983;&#33021;&#21147;&#20026;&#26680;&#24515;&#12290;&#25152;&#26377;&#30340;&#20195;&#30721;&#31034;&#20363;&#37117;&#34987;&#21093;&#31163;&#20102;&#26080;&#20851;&#30340;&#19994;&#21153;&#36923;&#36753;&#65292;&#20445;&#25345;&#26497;&#31616;&#65292;&#37197;&#20197;&#39640;&#36136;&#37327;&#30340;&#35270;&#35273;&#39044;&#35272;&#65292;&#24320;&#21457;&#32773;&#21482;&#38656;&#8220;&#22797;&#21046;&#12289;&#31896;&#36148;&#12289;&#36816;&#34892;&#8221;&#21363;&#21487;&#30452;&#25509;&#39564;&#35777;&#25928;&#26524;&#12290;</p><h2><strong>&#20070;&#31821;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0130-09">SwiftUI Architecture: Patterns and Practices for Building Scalable Applications</a></strong></h3><p>&#36825;&#26159;&#19968;&#26412; <a href="https://x.com/azamsharp">Mohammad Azam</a> &#22312;&#19981;&#20037;&#21069;&#20986;&#29256;&#30340;&#26032;&#20070;&#12290;&#23427;&#19981;&#26159;&#19968;&#26412;&#25945;&#20320;&#22914;&#20309;&#20351;&#29992; <code>VStack</code> &#25110;&#32534;&#20889;&#21160;&#30011;&#30340;&#20837;&#38376;&#20070;&#65292;&#32780;&#26159;&#19968;&#26412;&#32431;&#31929;&#25506;&#35752; SwiftUI &#24212;&#29992;&#26550;&#26500;&#12289;&#25968;&#25454;&#27969;&#21644;&#29616;&#20195;&#24037;&#31243;&#21270;&#23454;&#36341;&#30340;&#36827;&#38454;&#35835;&#29289;&#12290;</p><p>&#20070;&#20013;&#25552;&#20379;&#20102;&#22823;&#37327;&#30452;&#20987;&#29983;&#20135;&#29615;&#22659;&#30171;&#28857;&#30340;&#35299;&#20915;&#26041;&#26696;&#65292;&#20363;&#22914;&#65306;&#22914;&#20309;&#26500;&#24314;&#20840;&#23616;&#30340; Sheets &#21644; Toasts&#12289;&#22914;&#20309;&#21033;&#29992; <code>NavigationPath</code> &#35774;&#35745;&#35299;&#32806;&#30340;&#22810; Tab &#32534;&#31243;&#24335;&#36335;&#30001;&#12289;&#20197;&#21450;&#22914;&#20309;&#20351;&#29992; Property Wrapper &#32534;&#20889;&#20248;&#38597;&#30340;&#34920;&#21333;&#39564;&#35777;&#12290;&#23588;&#20026;&#37325;&#35201;&#30340;&#26159;&#65292;&#20316;&#32773;&#24182;&#19981;&#26159;&#35201;&#21521;&#20320;&#28748;&#36755;&#26576;&#31181;&#27515;&#26495;&#30340;&#26550;&#26500;&#27169;&#24335;&#65292;&#32780;&#26159;&#26088;&#22312;&#24110;&#21161;&#20320;&#24314;&#31435;&#30495;&#27491;&#30340;&#22768;&#26126;&#24335;&#24515;&#26234;&#27169;&#22411;&#12290;</p><p>&#25110;&#35768;&#26377;&#20154;&#35273;&#24471;&#65292;&#22312; AI &#36741;&#21161;&#32534;&#31243;&#30427;&#34892;&#30340;&#26102;&#20195;&#65292;&#36825;&#31867;&#25506;&#35752;&#26550;&#26500;&#30340;&#20070;&#31821;&#36824;&#37325;&#35201;&#21527;&#65311;&#20511;&#29992; Mohammad Azam &#22312;&#20070;&#20013;&#30340;&#35266;&#28857;&#65306;AI &#35753;&#20195;&#30721;&#29983;&#25104;&#21464;&#24471;&#24265;&#20215;&#65292;&#20294;&#20063;&#27491;&#22240;&#22914;&#27492;&#65292;&#31995;&#32479;&#26550;&#26500;&#30340;&#35774;&#35745;&#65288;&#36793;&#30028;&#30340;&#21010;&#20998;&#21644;&#29366;&#24577;&#25152;&#26377;&#26435;&#30340;&#26126;&#30830;&#65289;&#21464;&#24471;&#27604;&#20197;&#24448;&#20219;&#20309;&#26102;&#20505;&#37117;&#26356;&#21152;&#37325;&#35201;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #129]]></title><description><![CDATA[A Wall Away, Worlds Apart]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-129</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-129</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 30 Mar 2026 12:03:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3XHm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.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_!3XHm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3XHm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 424w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 848w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 1272w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3XHm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp" width="1200" height="628" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:628,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54286,&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/192584589?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.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_!3XHm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 424w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 848w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.webp 1272w, https://substackcdn.com/image/fetch/$s_!3XHm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F325d15bb-84b2-4e4c-85fd-5c7c87f6491b_1200x628.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"><svg role="img" 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"><g><title></title><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"><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"><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>A Wall Away, Worlds Apart</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-129/">Read on web &#8594;</a></p><p>The annual <a href="https://letsvision.swiftgg.team/">Let&#8217;s Vision</a> conference was held in Shanghai as scheduled, with this year&#8217;s theme being: &#8220;Born to Create, Powered by AI.&#8221; Therefore, alongside the regular sessions on Swift and spatial computing, the conference invited many developers to share their applications and insights regarding AI in their daily workflows. I benefited immensely from the speakers&#8217; introductions to their AI workflows. The AI-themed venue, originally designed to hold only 300 people, was packed inside and out with an enthusiastic crowd.</p><p>However, among the many excellent sessions, a talk prepared by <a href="https://www.linkedin.com/in/iamhands0me/">YuChe Cheng</a> titled &#8220;Let&#8217;s Create 1-liner Code in Swift&#8221; drew my attention to another room. What exactly was this topic about? Driven by curiosity, I walked in. As a developer with a LeetCode rating of 2200+, YuChe Cheng demonstrated how to use the extensive higher-order functions provided by <code>Foundation</code> and <code>Swift Algorithms</code> to transform plain, ordinary <code>for-loop</code> code into elegant, beautiful, and highly Swift-styled function chaining (1-liner code). In doing so, he achieved a brilliant balance between readability and performance.</p><p>Watching the function chaining on the slides being elegantly iterated over and over again, I felt a refreshing sense of clarity and enlightenment. For the entire 30-minute talk, I remained in a state of pure excitement&#8212;a feeling that typically only emerges after I&#8217;ve racked my brain to finally conquer a difficult problem, or when I&#8217;ve deeply grasped a new concept.</p><p>Even though it was only a wall away from the main venue, the overwhelming popularity of the AI topic meant the audience for this talk was noticeably sparse. Rather than feeling regret that so many missed out on a fantastic presentation, my real concern is this: <strong>As AI penetrates further into our industry, will that distinctive &#8220;character&#8221; developers once pursued and imbued into their code&#8212;beyond mere functionality&#8212;fade into oblivion?</strong></p><p>Developers shouldn&#8217;t only care about cold, compiled binaries. Code itself is a vessel for personal style. Just like writing an essay, beyond delivering logic and results, it carries aesthetic expression, reflecting the author&#8217;s personal taste and ingenuity.</p><p>At this year&#8217;s Let&#8217;s Vision, I felt as though we were standing at a crossroads: <strong>Should we relentlessly pursue the extreme efficiency brought by AI, or, while embracing change, can we ensure that the pride and craftsmanship belonging to developers are still preserved in the AI era?</strong></p><p><a href="https://fatbobman.com/en/weekly/issue-128/">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/w0129-01">Swift 6.3 Released</a></strong></h3><p>Since Swift 6, the language has settled into a steady cadence of one minor release every six months. Swift 6.3 was released as expected last week. Compared to previous releases, this version does not introduce any major headline features, but instead focuses on refining the existing system: improvements in concurrency diagnostics, the introduction of the <code>@c</code> attribute to further strengthen C/C++ interoperability, and more granular control over compiler optimizations.</p><p>That said, this release still sends a clear signal: Swift is evolving from a language centered around Apple platforms into a more general-purpose language with cross-platform and system-level capabilities. The continued progress of Embedded Swift, Android support, and the unification of the SwiftPM build system all point in this direction. For most iOS developers, the short-term impact may feel limited, but in the long run, this is a foundational update paving the way for what comes next.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-02">Designing a type-driven JSON in Swift</a></strong></h3><p>When API contracts are unstable and the understanding of fields between frontend and backend frequently drifts, Swift&#8217;s strong type system can actually amplify the friction at the JSON boundary. <a href="https://www.linkedin.com/in/inekipelov/">Roman Niekipielov</a> introduces a deliberately minimal <code>JSONValue</code> type to handle such transitional data.</p><p>Compared to <code>[String: Any]</code>, it preserves clearer type structure; compared to fully defined <code>Codable</code> models, it better accommodates frequently changing contracts. This approach does not aim to replace formal models, but rather to contain uncertainty at the boundary layer.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-03">Swift Native AI Agent Development Series</a></strong></h3><p>While many developers build AI agents using Python or TypeScript, <a href="https://x.com/chris_karani">Chris Karani</a> argues that Swift&#8217;s concurrency model is naturally well-suited for agent isolation and scheduling, with its strong type system and macro capabilities adding extra safety guarantees.</p><p>Across six articles, he explores this idea from multiple angles&#8212;from a unified multi-provider LLM SDK <a href="https://github.com/christopherkarani/Conduit">Conduit</a>, to an agent runtime built on Apple Foundation Models <a href="https://github.com/christopherkarani/Colony">Colony</a>, and even Metal-accelerated context memory management. If you are considering building AI features on Apple platforms, this is one of the few comprehensive native approaches available today.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-04">Talking Liquid Glass with Apple</a></strong></h3><p><a href="https://x.com/dbolella">Danny Bolella</a> attended Apple&#8217;s Liquid Glass design workshop in New York, spending three days in close collaboration with design teams and SwiftUI engineers. The message from the event was clear: Liquid Glass is not a transitional experiment, but a long-term design direction that will become the default across future toolchains.</p><p>Apple also repeatedly emphasized the importance of hierarchy&#8212;interfaces should be built around content, with controls serving as supporting elements positioned toward the edges. Beyond that, Danny also shares practical advice and implementation insights from Apple engineers. The article offers an early look into the direction and philosophy behind this design evolution.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-05">Apple Dropped 100+ New Metrics. Your Competitors Are Already Using Them</a></strong></h3><p>Apple has rolled out one of the most significant updates to App Store Connect in recent years, introducing 100+ first-party metrics, cohort analysis by source, peer benchmarks (conversion rate and revenue per download), and subscription data export via API. <a href="https://www.linkedin.com/in/jessica-chung-197215220/">Jessica Chung</a> provides a structured overview of these changes.</p><p>Since all data now comes directly from Apple, developers can move away from third-party estimates and make decisions based on real user behavior. More importantly, this update fills a long-standing gap: you can now track user quality across channels and keywords, build a full funnel from impression to subscription and retention, and benchmark your performance against peers.</p><blockquote><p>This update is clearly beneficial for developers, but it also raises the bar for third-party App Store analytics tools, pushing them to deliver higher-value capabilities to remain competitive.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-06">Package Traits in Xcode</a></strong></h3><p>When building an SPM package, some dependencies may only be used by specific APIs. However, once the package is added, those dependencies are included regardless of whether those APIs are used. Package Traits were introduced to address this issue by allowing developers to define optional features that consumers can enable as needed, avoiding unnecessary dependencies.</p><p>Unfortunately, after its introduction, this feature was only available in community Swift toolchains. With the release of Xcode 26.4, Package Traits finally gained official support from Apple, making broader adoption more likely. <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> introduces the feature and demonstrates its usage in this article.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-07">Why your SwiftUI app feels slow even though Instruments says it&#8217;s fine?</a></strong></h3><p>When users complain about slow responsiveness, is it always a performance issue? <a href="https://www.linkedin.com/in/rafal-dubiel/">Rafa&#322; Dubiel</a> shifts the focus from actual performance to perceived performance, exploring how UI feedback and interaction timing can make apps feel faster.</p><p>Techniques such as skeleton views, delayed loading, and thoughtful animations can effectively mask waiting time. The key insight is that user experience is often less about reducing milliseconds and more about providing timely feedback. Compared to raw performance optimization, this perspective has a more direct impact on how users perceive fluidity.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-08">Adjusting line height in SwiftUI on iOS 26</a></strong></h3><p>iOS 26 introduces a new <code>lineHeight(_:)</code> modifier in SwiftUI for controlling the baseline distance between lines of text. <a href="https://x.com/natpanferova">Natalia Panferova</a> provides a detailed comparison of its configurations, including presets (<code>.loose</code>, <code>.tight</code>), proportional scaling (<code>.multiple(factor:)</code>), incremental adjustments (<code>.leading(increase:)</code>), and absolute control (<code>.exact(points:)</code>).</p><p>Unlike <code>lineSpacing(_:)</code>, which adjusts spacing between lines, <code>lineHeight(_:)</code> directly defines baseline distance, offering more consistent control. This addition further improves SwiftUI&#8217;s typography capabilities.</p><blockquote><p>Natalia Panferova, a former member of Apple&#8217;s SwiftUI core team, has recently published a new book <a href="https://books.nilcoalescing.com/the-swiftui-way">The SwiftUI Way</a>, aimed at experienced SwiftUI developers. The book focuses on production patterns, common anti-patterns, and how to work with the framework rather than against it.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0129-09">Cove: A Swift 6 Native macOS Open Source Database Client</a></strong></h3><p>Cove, developed by <a href="https://www.linkedin.com/in/emanuelemicheletti/">Emanuele Micheletti</a>, is a native macOS database client built entirely with Swift 6. It currently supports a wide range of backends including PostgreSQL, MySQL, MariaDB, SQLite, MongoDB, Redis, ScyllaDB, Cassandra, and Elasticsearch. Built with SwiftUI and AppKit instead of Electron or web technologies, it delivers a lightweight experience aligned with macOS conventions.</p><p>What makes Cove particularly interesting is its architecture. All database capabilities are abstracted through a unified <code>DatabaseBackend</code> protocol, with no backend-specific logic in the UI layer. Whether dealing with SQL databases, key-value stores like Redis, or NoSQL systems like MongoDB and Elasticsearch, everything is normalized into a table model for rendering. Although still in an early v0.1.0 stage, it already supports querying, schema browsing, editing, SSH tunneling, and multi-tab workflows. Even if you don&#8217;t plan to use it as your daily database tool, it&#8217;s a valuable reference for Swift-based desktop app architecture.</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-129?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-129?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#19968;&#22681;&#20043;&#38548;&#65292;&#19981;&#21516;&#30340;&#26102;&#31354;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-129/">&#32593;&#39029;&#29256;</a></strong></p><p>&#19968;&#24180;&#19968;&#24230;&#30340; <a href="https://letsvision.swiftgg.team/">Let&#8217;s Vision</a> &#22823;&#20250;&#22312;&#19978;&#28023;&#22914;&#26399;&#20030;&#34892;&#65292;&#20170;&#24180;&#30340;&#20027;&#39064;&#26159;&#65306;&#8220;Born to Create, Powered by AI&#8221;&#12290;&#38500;&#20102;&#19982; Swift&#12289;&#31354;&#38388;&#35745;&#31639;&#30456;&#20851;&#30340;&#24120;&#35268; Session&#65292;&#22823;&#20250;&#36824;&#36992;&#35831;&#20102;&#35768;&#22810;&#24320;&#21457;&#32773;&#20998;&#20139;&#20182;&#20204;&#22312;&#24037;&#20316;&#20013;&#23545; AI &#30340;&#24212;&#29992;&#19982;&#29702;&#35299;&#12290;&#36890;&#36807;&#36825;&#20123;&#35762;&#24072;&#23545; AI &#24037;&#20316;&#27969;&#30340;&#20171;&#32461;&#65292;&#25105;&#20063;&#21463;&#30410;&#21290;&#27973;&#12290;&#21407;&#26412;&#21482;&#33021;&#23481;&#32435; 300 &#20154;&#30340; AI &#20027;&#39064;&#20250;&#22330;&#65292;&#37324;&#19977;&#23618;&#22806;&#19977;&#23618;&#31449;&#28385;&#20102;&#28909;&#24773;&#39640;&#28072;&#30340;&#35266;&#20247;&#12290;</p><p>&#28982;&#32780;&#65292;&#22312;&#20247;&#22810;&#20248;&#31168;&#30340; Session &#20013;&#65292;&#19968;&#22330;&#30001; <a href="https://www.linkedin.com/in/iamhands0me/">YuChe Cheng</a> &#20934;&#22791;&#30340;&#12289;&#21517;&#20026;&#12298;Let&#8217;s Create 1-liner Code in Swift&#12299;&#30340;&#28436;&#35762;&#21364;&#23558;&#25105;&#30340;&#27880;&#24847;&#21147;&#24341;&#21521;&#20102;&#21478;&#19968;&#20010;&#20250;&#22330;&#12290;&#36825;&#31350;&#31455;&#26159;&#19968;&#20010;&#24590;&#26679;&#30340;&#35805;&#39064;&#65311;&#24102;&#30528;&#30097;&#38382;&#25105;&#36208;&#20102;&#36827;&#21435;&#12290;&#20316;&#20026;&#19968;&#20010; LeetCode &#31215;&#20998; 2200+ &#30340;&#24320;&#21457;&#32773;&#65292;YuChe Cheng &#22312;&#28436;&#35762;&#20013;&#23637;&#31034;&#20102;&#22914;&#20309;&#36890;&#36807; Foundation &#20197;&#21450; Swift Algorithms &#25552;&#20379;&#30340;&#22823;&#37327;&#39640;&#38454;&#20989;&#25968;&#65292;&#23558;&#21407;&#26412;&#24179;&#28129;&#26080;&#22855;&#30340; For-loop &#20195;&#30721;&#65292;&#36716;&#25442;&#25104;&#26356;&#21152;&#20248;&#38597;&#12289;&#32654;&#35266;&#12289;&#26497;&#20855; Swift &#39118;&#26684;&#30340; Function Chaining&#65288;1-liner code&#65289;&#65292;&#24182;&#22312;&#26131;&#35835;&#24615;&#19982;&#24615;&#33021;&#20043;&#38388;&#21462;&#24471;&#20102;&#24456;&#22909;&#30340;&#24179;&#34913;&#12290;</p><p>&#30475;&#30528;&#24187;&#28783;&#29255;&#19978;&#30340; Function Chaining &#34987;&#19968;&#27425;&#21448;&#19968;&#27425;&#22320;&#20248;&#38597;&#36845;&#20195;&#65292;&#25105;&#26377;&#31181;&#33541;&#22622;&#39039;&#24320;&#30340;&#30021;&#24555;&#12290;&#25972;&#25972; 30 &#20998;&#38047;&#30340;&#28436;&#35762;&#65292;&#35753;&#25105;&#22987;&#32456;&#22788;&#20110;&#19968;&#31181;&#32431;&#31929;&#30340;&#20852;&#22859;&#20043;&#20013;&#8212;&#8212;&#36825;&#31181;&#24863;&#35273;&#65292;&#36890;&#24120;&#21482;&#22312;&#25105;&#32478;&#23613;&#33041;&#27713;&#26368;&#32456;&#25915;&#20811;&#20102;&#19968;&#20010;&#38590;&#39064;&#65292;&#25110;&#26159;&#28145;&#21051;&#29702;&#35299;&#20102;&#19968;&#20010;&#26032;&#27010;&#24565;&#21518;&#25165;&#20250;&#28044;&#29616;&#12290;</p><p>&#23613;&#31649;&#19982;&#20027;&#20250;&#22330;&#21482;&#26377;&#19968;&#22681;&#20043;&#38548;&#65292;&#20294;&#30001;&#20110; AI &#35805;&#39064;&#30340;&#32477;&#23545;&#28909;&#24230;&#65292;&#26412;&#22330;&#28436;&#35762;&#30340;&#21548;&#20247;&#26126;&#26174;&#20559;&#23569;&#12290;&#19982;&#20854;&#35828;&#25105;&#20026;&#35768;&#22810;&#20154;&#38169;&#22833;&#20102;&#19968;&#22330;&#31934;&#24425;&#28436;&#35762;&#32780;&#24863;&#21040;&#36951;&#25022;&#65292;&#25105;&#30495;&#27491;&#25285;&#24515;&#30340;&#20854;&#23454;&#26159;&#65306;<strong>&#38543;&#30528; AI &#30340;&#36827;&#19968;&#27493;&#28183;&#36879;&#65292;&#35768;&#22810;&#24320;&#21457;&#32773;&#21407;&#26412;&#22312;&#36861;&#27714;&#21151;&#33021;&#20043;&#22806;&#25152;&#36171;&#20104;&#20195;&#30721;&#30340;&#37027;&#20221;&#8220;&#27668;&#36136;&#8221;&#65292;&#20250;&#19981;&#20250;&#23601;&#27492;&#28040;&#20129;&#65311;</strong></p><p>&#24320;&#21457;&#32773;&#19981;&#24212;&#35813;&#21482;&#20851;&#24515;&#32534;&#35793;&#21518;&#20919;&#20912;&#20912;&#30340;&#20108;&#36827;&#21046;&#21151;&#33021;&#65292;&#20195;&#30721;&#26412;&#36523;&#20063;&#26159;&#20010;&#20154;&#39118;&#26684;&#30340;&#36733;&#20307;&#12290;&#23427;&#23601;&#20687;&#25991;&#31456;&#19968;&#26679;&#65292;&#22312;&#36755;&#20986;&#36923;&#36753;&#19982;&#32467;&#26524;&#20043;&#22806;&#65292;&#36824;&#25215;&#36733;&#30528;&#32654;&#23398;&#34920;&#36798;&#65292;&#20307;&#29616;&#30528;&#32534;&#20889;&#32773;&#30340;&#20010;&#20154;&#21697;&#21619;&#19982;&#24039;&#24605;&#12290;</p><p>&#22312;&#20170;&#24180;&#30340; Let&#8217;s Vision &#19978;&#65292;&#25105;&#24863;&#35273;&#25105;&#20204;&#27491;&#31449;&#22312;&#19968;&#20010;&#26102;&#38388;&#30340;&#21313;&#23383;&#36335;&#21475;&#65306;<strong>&#25105;&#20204;&#26159;&#35813;&#19968;&#21619;&#36861;&#27714; AI &#24102;&#26469;&#30340;&#26497;&#33268;&#39640;&#25928;&#65292;&#36824;&#26159;&#22312;&#25317;&#25265;&#21464;&#21270;&#30340;&#21516;&#26102;&#65292;&#20381;&#28982;&#35753;&#23646;&#20110;&#24320;&#21457;&#32773;&#30340;&#37027;&#20221;&#39556;&#20658;&#19982;&#25163;&#33402;&#65292;&#22312; AI &#26102;&#20195;&#24471;&#20197;&#20445;&#30041;&#65311;</strong></p><p><a href="https://fatbobman.com/zh/weekly/issue-128/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#26412;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0129-01">Swift 6.3 Released</a></strong></h3><p>&#20174; Swift 6 &#24320;&#22987;&#65292;&#35821;&#35328;&#28436;&#36827;&#24050;&#32463;&#31283;&#23450;&#22312;&#21322;&#24180;&#19968;&#20010; minor &#29256;&#26412;&#30340;&#33410;&#22863;&#65292;&#19978;&#21608; Swift 6.3 &#22914;&#26399;&#21457;&#24067;&#12290;&#19982;&#21069;&#20960;&#20010;&#29256;&#26412;&#30456;&#27604;&#65292;&#36825;&#19968;&#29256;&#26412;&#24182;&#26410;&#24341;&#20837;&#26126;&#26174;&#30340;&#37325;&#30917;&#29305;&#24615;&#65292;&#26356;&#22810;&#26159;&#23545;&#26082;&#26377;&#20307;&#31995;&#30340;&#25171;&#30952;&#65306;&#24182;&#21457;&#27169;&#22411;&#22312;&#35786;&#26029;&#20934;&#30830;&#24615;&#26041;&#38754;&#26377;&#25152;&#25913;&#36827;&#65292;&#26032;&#22686;&#30340; <code>@c</code> &#29305;&#24615;&#65288;attribute&#65289;&#36827;&#19968;&#27493;&#24378;&#21270;&#20102; C/C++ &#20114;&#25805;&#20316;&#33021;&#21147;&#65292;&#21516;&#26102;&#32534;&#35793;&#20248;&#21270;&#30340;&#25511;&#21046;&#31890;&#24230;&#20063;&#21464;&#24471;&#26356;&#21152;&#32454;&#33268;&#12290;</p><p>&#23613;&#31649;&#22914;&#27492;&#65292;&#36825;&#19968;&#29256;&#26412;&#20063;&#37322;&#25918;&#20986;&#19968;&#20010;&#28165;&#26224;&#30340;&#20449;&#21495;&#65306;Swift &#27491;&#22312;&#20174;&#8220;&#20197; Apple &#24179;&#21488;&#20026;&#20013;&#24515;&#30340;&#24212;&#29992;&#24320;&#21457;&#35821;&#35328;&#8221;&#65292;&#36880;&#27493;&#21521;&#8220;&#20855;&#22791;&#36328;&#24179;&#21488;&#19982;&#31995;&#32479;&#32423;&#33021;&#21147;&#30340;&#36890;&#29992;&#35821;&#35328;&#8221;&#28436;&#36827;&#12290;Embedded Swift&#12289;Android &#25903;&#25345;&#30340;&#25345;&#32493;&#25512;&#36827;&#65292;&#20197;&#21450; SwiftPM &#26500;&#24314;&#20307;&#31995;&#30340;&#32479;&#19968;&#65292;&#37117;&#22312;&#25351;&#21521;&#36825;&#19968;&#26041;&#21521;&#12290;&#23545;&#22810;&#25968; iOS &#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#30701;&#26399;&#20307;&#24863;&#25110;&#35768;&#26377;&#38480;&#65292;&#20294;&#20174;&#26356;&#38271;&#30340;&#26102;&#38388;&#32500;&#24230;&#26469;&#30475;&#65292;&#36825;&#26356;&#20687;&#26159;&#19968;&#27425;&#20026;&#26410;&#26469;&#38138;&#36335;&#30340;&#22522;&#30784;&#24615;&#26356;&#26032;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-02">&#22914;&#20309;&#22312; Swift &#20013;&#25215;&#25509;&#23578;&#26410;&#31283;&#23450;&#30340; JSON (Designing a type-driven JSON in Swift)</a></strong></h3><p>&#24403; API &#22865;&#32422;&#23578;&#26410;&#31283;&#23450;&#12289;&#21069;&#21518;&#31471;&#23545;&#23383;&#27573;&#30340;&#29702;&#35299;&#21448;&#32463;&#24120;&#28418;&#31227;&#26102;&#65292;Swift &#30340;&#24378;&#31867;&#22411;&#31995;&#32479;&#21453;&#32780;&#20250;&#25918;&#22823;&#25968;&#25454;&#19982; JSON &#20043;&#38388;&#36716;&#25442;&#26102;&#30340;&#36793;&#30028;&#38382;&#39064;&#12290;<a href="https://www.linkedin.com/in/inekipelov/">Roman Niekipielov</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#20102;&#19968;&#20010;&#21051;&#24847;&#20570;&#23567;&#30340; <code>JSONValue</code> &#31867;&#22411;&#65292;&#29992;&#26469;&#25215;&#25509;&#36825;&#31867;&#36807;&#28193;&#38454;&#27573;&#30340; JSON &#25968;&#25454;&#12290;&#30456;&#27604; <code>[String: Any]</code>&#65292;&#23427;&#20445;&#30041;&#20102;&#26356;&#26126;&#30830;&#30340;&#31867;&#22411;&#32467;&#26500;&#65307;&#30456;&#27604;&#30452;&#25509;&#32534;&#20889; <code>Codable</code> &#27169;&#22411;&#65292;&#21448;&#26356;&#36866;&#21512;&#24212;&#23545;&#39057;&#32321;&#21464;&#21270;&#30340;&#22865;&#32422;&#12290;&#36825;&#20010;&#23454;&#29616;&#24182;&#19981;&#35797;&#22270;&#26367;&#20195;&#27491;&#24335;&#27169;&#22411;&#65292;&#32780;&#26159;&#23558;&#19981;&#30830;&#23450;&#24615;&#26242;&#26102;&#38480;&#21046;&#22312;&#36793;&#30028;&#23618;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-03">Swift &#21407;&#29983; AI Agent &#24320;&#21457;&#23454;&#36341;&#31995;&#21015;</a></strong></h3><p>&#24066;&#38754;&#19978;&#26377;&#22823;&#37327;&#24320;&#21457;&#32773;&#20351;&#29992; Python&#12289;TypeScript &#24320;&#21457; AI Agent&#65292;&#20294; <a href="https://x.com/chris_karani">Chris Karani</a> &#35748;&#20026;&#65292;Swift &#30340;&#24182;&#21457;&#27169;&#22411;&#22825;&#28982;&#26356;&#36866;&#21512; Agent &#30340;&#38548;&#31163;&#19982;&#35843;&#24230;&#65292;&#24378;&#31867;&#22411;&#31995;&#32479;&#21644;&#23439;&#21151;&#33021;&#20063;&#24102;&#26469;&#20102;&#39069;&#22806;&#30340;&#23433;&#20840;&#20445;&#35777;&#12290;&#20182;&#29992; 6 &#31687;&#25991;&#31456;&#12289;&#20174;&#22810;&#20010;&#35282;&#24230;&#23454;&#36341;&#20102;&#36825;&#19968;&#35266;&#28857;&#8212;&#8212;&#20174;&#32479;&#19968;&#22810;&#20010; LLM Provider &#30340; SDK <a href="https://github.com/christopherkarani/Conduit">Conduit</a>&#65292;&#21040;&#22522;&#20110; Apple Foundation Models &#30340; Agent &#36816;&#34892;&#26102; <a href="https://github.com/christopherkarani/Colony">Colony</a>&#65292;&#20877;&#21040;&#29992; Metal &#21152;&#36895;&#30340;&#19978;&#19979;&#25991;&#35760;&#24518;&#31649;&#29702;&#12290;&#22914;&#26524;&#20320;&#27491;&#22312;&#32771;&#34385;&#22312; Apple &#24179;&#21488;&#19978;&#26500;&#24314; AI &#21151;&#33021;&#65292;&#36825;&#20010;&#31995;&#21015;&#26159;&#30446;&#21069;&#23569;&#35265;&#30340;&#23436;&#25972;&#21407;&#29983;&#26041;&#26696;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-04">Liquid Glass &#35774;&#35745;&#24037;&#20316;&#22346; (Talking Liquid Glass with Apple)</a></strong></h3><p><a href="https://x.com/dbolella">Danny Bolella</a> &#22312;&#32445;&#32422;&#21442;&#21152;&#20102;&#33529;&#26524;&#20030;&#21150;&#30340; Liquid Glass &#35774;&#35745;&#24037;&#20316;&#22346;&#65292;&#19982;&#35774;&#35745;&#22242;&#38431;&#21644; SwiftUI &#24037;&#31243;&#24072;&#36827;&#34892;&#20102;&#20026;&#26399;&#19977;&#22825;&#30340;&#28145;&#20837;&#20132;&#27969;&#12290;&#26412;&#27425;&#27963;&#21160;&#20256;&#36882;&#20986;&#38750;&#24120;&#26126;&#30830;&#30340;&#20449;&#21495;&#65306;Liquid Glass &#24182;&#38750;&#36807;&#28193;&#24615;&#23581;&#35797;&#65292;&#32780;&#26159;&#33529;&#26524;&#26410;&#26469;&#25968;&#24180;&#30340;&#35774;&#35745;&#26041;&#21521;&#65292;&#19988;&#23558;&#22312;&#21518;&#32493;&#24037;&#20855;&#38142;&#20013;&#25104;&#20026;&#40664;&#35748;&#21069;&#25552;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#33529;&#26524;&#21453;&#22797;&#24378;&#35843;&#8220;&#23618;&#32423;&#65288;Hierarchy&#65289;&#8221;&#30340;&#37325;&#35201;&#24615;&#8212;&#8212;&#30028;&#38754;&#24212;&#22260;&#32469;&#20869;&#23481;&#26500;&#24314;&#65292;&#25511;&#20214;&#21482;&#26159;&#26381;&#21153;&#20110;&#20869;&#23481;&#30340;&#36741;&#21161;&#20803;&#32032;&#65292;&#24212;&#23613;&#37327;&#36864;&#23621;&#36793;&#32536;&#65292;&#35753;&#20449;&#24687;&#26412;&#36523;&#25104;&#20026;&#35270;&#35273;&#19982;&#20132;&#20114;&#30340;&#20013;&#24515;&#12290;&#38500;&#27492;&#20043;&#22806;&#65292;Danny &#36824;&#22312;&#26412;&#25991;&#20013;&#35760;&#24405;&#20102;&#20854;&#20182;&#19968;&#20123; SwiftUI &#24037;&#31243;&#24072;&#32473;&#20986;&#30340;&#24314;&#35758;&#21644;&#25216;&#24039;&#12290;&#26412;&#25991;&#35760;&#24405;&#30340;&#20869;&#23481;&#21487;&#20197;&#24110;&#21161;&#20320;&#26356;&#26089;&#29702;&#35299;&#36825;&#22330;&#35774;&#35745;&#28436;&#36827;&#30340;&#33410;&#22863;&#19982;&#26041;&#21521;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-05">App Store Connect &#22823;&#26356;&#26032; (Apple Dropped 100+ New Metrics. Your Competitors Are Already Using Them)</a></strong></h3><p>&#33529;&#26524;&#23545; App Store Connect &#36827;&#34892;&#20102;&#36817;&#24180;&#26469;&#26368;&#22823;&#30340;&#19968;&#27425;&#26356;&#26032;&#65292;&#19968;&#21475;&#27668;&#24341;&#20837;&#20102; 100+ &#23448;&#26041;&#25351;&#26631;&#12289;&#25353;&#26469;&#28304;&#21010;&#20998;&#30340; cohort &#20998;&#26512;&#12289;&#21516;&#34892;&#22522;&#20934;&#23545;&#27604;&#65288;&#36716;&#21270;&#29575;&#19982;&#21333;&#19979;&#36733;&#25910;&#30410;&#65289;&#20197;&#21450;&#21487;&#36890;&#36807; API &#23548;&#20986;&#30340;&#35746;&#38405;&#25968;&#25454;&#12290;<a href="https://www.linkedin.com/in/jessica-chung-197215220/">Jessica Chung</a> &#22312;&#26412;&#25991;&#20013;&#23545;&#36825;&#20123;&#20851;&#38190;&#21464;&#21270;&#36827;&#34892;&#20102;&#31995;&#32479;&#26803;&#29702;&#12290;&#30001;&#20110;&#25152;&#26377;&#25968;&#25454;&#22343;&#26469;&#33258;&#33529;&#26524;&#19968;&#25163;&#32479;&#35745;&#65292;&#36825;&#24847;&#21619;&#30528;&#24320;&#21457;&#32773;&#22312; ASO &#21644;&#22686;&#38271;&#20915;&#31574;&#20013;&#65292;&#23558;&#19981;&#20877;&#20381;&#36182;&#31532;&#19977;&#26041;&#20272;&#31639;&#65292;&#32780;&#21487;&#20197;&#30452;&#25509;&#22522;&#20110;&#30495;&#23454;&#29992;&#25143;&#34892;&#20026;&#36827;&#34892;&#20998;&#26512;&#19982;&#20248;&#21270;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#36825;&#27425;&#26356;&#26032;&#34917;&#40784;&#20102;&#38271;&#26399;&#32570;&#22833;&#30340;&#20851;&#38190;&#33021;&#21147;&#65306;&#20320;&#21487;&#20197;&#36861;&#36394;&#19981;&#21516;&#20851;&#38190;&#35789;&#19982;&#28192;&#36947;&#24102;&#26469;&#30340;&#29992;&#25143;&#36136;&#37327;&#65292;&#24314;&#31435;&#20174;&#26333;&#20809;&#12289;&#19979;&#36733;&#21040;&#35746;&#38405;&#19982;&#32493;&#36153;&#30340;&#23436;&#25972;&#36716;&#21270;&#38142;&#36335;&#65292;&#24182;&#36890;&#36807;&#21516;&#34892;&#22522;&#20934;&#26126;&#30830;&#33258;&#36523;&#25152;&#22788;&#20301;&#32622;&#12290;</p><blockquote><p>&#26412;&#27425;&#26356;&#26032;&#23545;&#20110;&#24320;&#21457;&#32773;&#32780;&#35328;&#26080;&#30097;&#26159;&#21033;&#22909;&#65292;&#20294;&#23545;&#20110;&#37096;&#20998;&#31532;&#19977;&#26041; App Store &#20998;&#26512;&#26381;&#21153;&#26469;&#35828;&#65292;&#20063;&#22312;&#19968;&#23450;&#31243;&#24230;&#19978;&#25552;&#39640;&#20102;&#31454;&#20105;&#38376;&#27099;&#65292;&#20419;&#20351;&#20854;&#25552;&#20379;&#26356;&#20855;&#38468;&#21152;&#20540;&#30340;&#33021;&#21147;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-06">Package Traits in Xcode</a></strong></h3><p>&#22312;&#21019;&#24314; SPM &#26102;&#65292;&#26576;&#20123;&#20381;&#36182;&#21487;&#33021;&#21482;&#34987;&#29305;&#23450; API &#20351;&#29992;&#65292;&#20294;&#19968;&#26086;&#29992;&#25143;&#24341;&#20837;&#35813;&#21253;&#65292;&#21363;&#20415;&#19981;&#20351;&#29992;&#36825;&#20123; API&#65292;&#20063;&#38656;&#35201;&#19968;&#24182;&#24341;&#20837;&#30456;&#20851;&#20381;&#36182;&#12290;Package Traits &#27491;&#26159;&#20026;&#20102;&#35299;&#20915;&#36825;&#19968;&#38382;&#39064;&#32780;&#24341;&#20837;&#30340;&#65292;&#23427;&#20026; SPM &#25552;&#20379;&#20102;&#19968;&#31181;&#22768;&#26126;&#21487;&#36873;&#29305;&#24615;&#30340;&#26041;&#24335;&#65292;&#20351;&#20351;&#29992;&#32773;&#33021;&#22815;&#25353;&#38656;&#21551;&#29992;&#21151;&#33021;&#65292;&#20174;&#32780;&#36991;&#20813;&#24341;&#20837;&#19981;&#24517;&#35201;&#30340;&#20381;&#36182;&#12290;&#36951;&#25022;&#30340;&#26159;&#65292;&#22312;&#35813;&#21151;&#33021;&#25512;&#20986;&#21518;&#65292;&#19968;&#30452;&#21482;&#33021;&#22312;&#31038;&#21306;&#29256;&#26412;&#30340; Swift &#24037;&#20855;&#38142;&#20013;&#20351;&#29992;&#12290;&#38543;&#30528; Xcode 26.4 &#30340;&#21457;&#24067;&#65292;Package Traits &#32456;&#20110;&#33719;&#24471;&#20102;&#33529;&#26524;&#23448;&#26041;&#25903;&#25345;&#65292;&#26377;&#26395;&#36814;&#26469;&#26356;&#24191;&#27867;&#30340;&#24212;&#29992;&#12290;<a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#22312;&#26412;&#25991;&#20013;&#23545;&#35813;&#29305;&#24615;&#36827;&#34892;&#20102;&#20171;&#32461;&#65292;&#24182;&#23637;&#31034;&#20102;&#20854;&#22522;&#26412;&#29992;&#27861;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-07">&#20248;&#21270;&#24863;&#23448;&#24615;&#33021;&#65292;&#35753;&#29992;&#25143;&#24863;&#35273;&#26356;&#24555; (Why your SwiftUI app feels slow even though Instruments says it&#8217;s fine?)</a></strong></h3><p>&#29992;&#25143;&#25237;&#35785;&#21709;&#24212;&#24930;&#65292;&#19968;&#23450;&#26159;&#24212;&#29992;&#24615;&#33021;&#38382;&#39064;&#21527;&#65311;<a href="https://www.linkedin.com/in/rafal-dubiel/">Rafa&#322; Dubiel</a> &#23558;&#20851;&#27880;&#28857;&#20174;&#8220;&#23454;&#38469;&#24615;&#33021;&#8221;&#36716;&#21521;&#8220;&#24863;&#30693;&#24615;&#33021;&#65288;Perceived Performance)&#8221;&#65292;&#35752;&#35770;&#22914;&#20309;&#36890;&#36807;&#30028;&#38754;&#21453;&#39304;&#19982;&#20132;&#20114;&#33410;&#22863;&#65292;&#35753;&#29992;&#25143;&#24863;&#35273;&#24212;&#29992;&#8220;&#26356;&#24555;&#8221;&#12290;&#20363;&#22914;&#36890;&#36807; skeleton view&#12289;&#24310;&#36831;&#21152;&#36733;&#65292;&#20197;&#21450;&#21512;&#29702;&#30340;&#21160;&#30011;&#19982;&#29366;&#24577;&#36807;&#28193;&#26469;&#25513;&#30422;&#31561;&#24453;&#26102;&#38388;&#12290;&#20316;&#32773;&#25351;&#20986;&#65292;&#22312;&#35768;&#22810;&#22330;&#26223;&#19979;&#65292;&#29992;&#25143;&#20307;&#39564;&#30340;&#20851;&#38190;&#24182;&#19981;&#22312;&#20110;&#20943;&#23569;&#27627;&#31186;&#32423;&#30340;&#35745;&#31639;&#26102;&#38388;&#65292;&#32780;&#22312;&#20110;&#26159;&#21542;&#21450;&#26102;&#25552;&#20379;&#21453;&#39304;&#12290;&#30456;&#27604;&#21333;&#32431;&#20248;&#21270;&#24615;&#33021;&#25351;&#26631;&#65292;&#36825;&#31181;&#20174;&#29992;&#25143;&#24863;&#30693;&#20986;&#21457;&#30340;&#24605;&#36335;&#65292;&#24448;&#24448;&#26356;&#30452;&#25509;&#22320;&#24433;&#21709;&#29992;&#25143;&#23545;&#24212;&#29992;&#27969;&#30021;&#24230;&#30340;&#21028;&#26029;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0129-08">&#22312; SwiftUI &#20013;&#25511;&#21046;&#34892;&#39640; (Adjusting line height in SwiftUI on iOS 26)</a></strong></h3><p>iOS 26 &#20026; SwiftUI &#26032;&#22686;&#20102; <code>lineHeight(_:)</code> modifier&#65292;&#29992;&#20110;&#25511;&#21046;&#25991;&#26412;&#30456;&#37051;&#20004;&#34892;&#22522;&#32447;&#20043;&#38388;&#30340;&#36317;&#31163;&#12290;<a href="https://x.com/natpanferova">Natalia Panferova</a> &#22312;&#26412;&#25991;&#20013;&#23545;&#21508;&#31181;&#37197;&#32622;&#26041;&#24335;&#36827;&#34892;&#20102;&#35814;&#32454;&#23545;&#27604;&#65306;&#20869;&#32622;&#39044;&#35774;&#65288;<code>.loose</code>&#12289;<code>.tight</code>&#65289;&#12289;&#22522;&#20110;&#23383;&#21495;&#20493;&#25968;&#30340; <code>.multiple(factor:)</code>&#12289;&#22266;&#23450;&#22686;&#37327;&#30340; <code>.leading(increase:)</code>&#65292;&#20197;&#21450;&#32477;&#23545;&#20540;&#25511;&#21046;&#30340; <code>.exact(points:)</code>&#12290;&#27492;&#22806;&#65292;<code>lineHeight(_:)</code> &#19982;&#24050;&#26377;&#30340; <code>lineSpacing(_:)</code> &#24182;&#19981;&#30456;&#21516;&#65306;&#21069;&#32773;&#25511;&#21046;&#22522;&#32447;&#38388;&#36317;&#65292;&#21518;&#32773;&#25511;&#21046;&#34892;&#24213;&#21040;&#19979;&#19968;&#34892;&#34892;&#39030;&#30340;&#36317;&#31163;&#12290;</p><blockquote><p>Natalia Panferova &#26366;&#26159; Apple SwiftUI &#26680;&#24515;&#22242;&#38431;&#25104;&#21592;&#65292;&#21442;&#19982;&#36807;&#22810;&#20010;&#20851;&#38190; API &#30340;&#35774;&#35745;&#19982;&#24320;&#21457;&#12290;&#26412;&#26376;&#22905;&#21018;&#21018;&#20986;&#29256;&#20102;&#26032;&#20070; <a href="https://books.nilcoalescing.com/the-swiftui-way">The SwiftUI Way</a>&#65292;&#38754;&#21521;&#26377;&#19968;&#23450; SwiftUI &#32463;&#39564;&#30340;&#24320;&#21457;&#32773;&#65292;&#32858;&#28966;&#20110;&#29983;&#20135;&#29615;&#22659;&#20013;&#30340;&#27169;&#24335;&#36873;&#25321;&#12289;&#24120;&#35265;&#21453;&#27169;&#24335;&#35782;&#21035;&#65292;&#20197;&#21450;&#22914;&#20309;&#19982;&#26694;&#26550;&#8220;&#39034;&#21183;&#32780;&#20026;&#8221;&#32780;&#38750;&#23545;&#25239;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0129-09">Cove&#65306;Swift 6 &#32534;&#20889;&#30340; macOS &#24320;&#28304;&#25968;&#25454;&#24211;&#23458;&#25143;&#31471;</a></strong></h3><p>Cove &#26159;&#30001; <a href="https://www.linkedin.com/in/emanuelemicheletti/">Emanuele Micheletti</a> &#24320;&#21457;&#30340;&#19968;&#27454;&#21407;&#29983; macOS &#25968;&#25454;&#24211;&#23458;&#25143;&#31471;&#65292;&#25972;&#20010;&#39033;&#30446;&#23436;&#20840;&#20351;&#29992; Swift 6 &#26500;&#24314;&#65292;&#30446;&#21069;&#24050;&#32463;&#25903;&#25345; PostgreSQL&#12289;MySQL&#12289;MariaDB&#12289;SQLite&#12289;MongoDB&#12289;Redis&#12289;ScyllaDB&#12289;Cassandra &#21644; Elasticsearch &#31561;&#22810;&#31181;&#21518;&#31471;&#12290;&#23427;&#37319;&#29992; SwiftUI &#25645;&#37197; AppKit &#21407;&#29983;&#25511;&#20214;&#23454;&#29616;&#65292;&#27809;&#26377;&#36208; Electron &#25110; Web &#25216;&#26415;&#26632;&#65292;&#22240;&#27492;&#25972;&#20307;&#26356;&#36731;&#37327;&#65292;&#20063;&#26356;&#31526;&#21512; macOS &#29992;&#25143;&#29087;&#24713;&#30340;&#20132;&#20114;&#20307;&#39564;&#12290;</p><p>&#30456;&#27604;&#8220;&#21448;&#19968;&#20010;&#25968;&#25454;&#24211; GUI&#8221;&#65292;Cove &#26356;&#20540;&#24471;&#20851;&#27880;&#30340;&#26159;&#23427;&#30340;&#23454;&#29616;&#24605;&#36335;&#12290;&#20316;&#32773;&#23558;&#25152;&#26377;&#25968;&#25454;&#24211;&#33021;&#21147;&#32479;&#19968;&#25277;&#35937;&#20026; DatabaseBackend &#21327;&#35758;&#65292;UI &#23618;&#19981;&#21253;&#21547;&#20219;&#20309;&#38024;&#23545;&#29305;&#23450;&#21518;&#31471;&#30340;&#20998;&#25903;&#36923;&#36753;&#12290;&#26080;&#35770;&#26159; SQL &#25968;&#25454;&#24211;&#12289;Redis &#36825;&#31867;&#38190;&#20540;&#25968;&#25454;&#24211;&#65292;&#36824;&#26159; MongoDB&#12289;Elasticsearch &#36825;&#31867;&#38750;&#20851;&#31995;&#22411;&#21518;&#31471;&#65292;&#26368;&#32456;&#37117;&#20250;&#34987;&#25972;&#29702;&#20026;&#32479;&#19968;&#30340;&#34920;&#26684;&#27169;&#22411;&#20132;&#30001;&#30028;&#38754;&#28210;&#26579;&#12290;&#39033;&#30446;&#30446;&#21069;&#20173;&#22788;&#20110; v0.1.0 &#30340;&#26089;&#26399;&#38454;&#27573;&#65292;&#20294;&#24050;&#32463;&#20855;&#22791;&#26597;&#35810;&#12289;&#32467;&#26500;&#27983;&#35272;&#12289;&#32534;&#36753;&#12289;SSH &#38567;&#36947;&#21644;&#22810;&#26631;&#31614;&#31561;&#22522;&#30784;&#33021;&#21147;&#12290;&#21363;&#20415;&#20320;&#24182;&#19981;&#25171;&#31639;&#25226;&#23427;&#20316;&#20026;&#26085;&#24120;&#25968;&#25454;&#24211;&#24037;&#20855;&#65292;Cove &#20381;&#28982;&#26159;&#19968;&#20010;&#24456;&#20540;&#24471; Swift &#24320;&#21457;&#32773;&#30740;&#31350;&#30340;&#26700;&#38754;&#24212;&#29992;&#26550;&#26500;&#26679;&#26412;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #128]]></title><description><![CDATA[Is My App Stuck in Review?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-128</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-128</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 23 Mar 2026 12:02:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!TXb6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.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_!TXb6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TXb6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 424w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 848w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 1272w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TXb6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp" width="1261" height="688" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:688,&quot;width&quot;:1261,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6222,&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/191741223?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.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_!TXb6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 424w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 848w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.webp 1272w, https://substackcdn.com/image/fetch/$s_!TXb6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffba21959-24f6-45a2-b0eb-a05cabc62c97_1261x688.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"><svg role="img" 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"><g><title></title><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"><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"><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>Is My App Stuck in Review?</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-128/">Read on web &#8594;</a></p><p>Last Thursday, a user in my Discord community complained that their app had been submitted to App Store Connect for four or five days but still hadn&#8217;t entered the review process. While I was enthusiastically analyzing the possible reasons with everyone, my heart suddenly skipped a beat: it seemed that the app I submitted on Monday hadn&#8217;t received any review updates either.</p><p>Someone suggested I apply for an &#8220;Expedited Review&#8221;. However, when I clicked into the page, the system prompted that I had &#8220;no eligible apps&#8221;. Upon closer inspection, I realized I was just a bit rusty from not updating my apps for so long&#8212;although my app had completed all the prerequisite steps, I simply hadn&#8217;t clicked the &#8220;Submit for Review&#8221; button at all.</p><p>Just a few hours after I finally clicked the button, the app was successfully approved and published.</p><p>While my situation was a mere false alarm, discussions in the community about Apple&#8217;s app review process slowing down have indeed been increasing recently. Many speculate that this might be related to the recent rise of Vibe Coding. Although there is no official confirmation, Vibe Coding has undeniably lowered the barrier to entry for development. In doing so, it has simultaneously amplified the volume of app submissions and the frequency of iterations in a short period, thereby passing the pressure down to the review team.</p><p>In fact, Apple has recently been holding up the review process for apps like Replit, which allow everyday consumers to engage in Vibe Coding. Even when allowing them to remain on the store, Apple has demanded compromises on core features. In Michael Tsai&#8217;s <a href="https://mjtsai.com/blog/2026/03/20/updates-to-vibe-coding-apps-rejected-from-the-app-store/">blog post</a> covering this news, I came across a very sharp comment:</p><blockquote><p>I thought the implication was that the vibe coding apps were being used to make the vibecoded apps that get submitted.</p></blockquote><p>AI is not only reshaping the way we develop software but also posing new challenges to the app review and distribution systems. One might ask: if we fight magic with magic and let AI fully take over the review process, wouldn&#8217;t it be more efficient?</p><p>Apple&#8217;s review mechanism has never been entirely transparent. Sometimes, whether an app passes smoothly or not even depends on whether you &#8220;happen to&#8221; encounter a sympathetic reviewer. But looking at it from another angle, at least &#8220;humans&#8221; remain the most crucial part of this defense line. Human judgment can be flawed and biased, but it still retains a certain degree of flexibility when dealing with rigid rules.</p><p>I truly hope that the software ecosystem of the future does not devolve into a closed loop of &#8220;AI Development -&gt; AI Review&#8221;.</p><p><a href="https://fatbobman.com/en/weekly/issue-127/">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/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/?utm_source=fatbobman%20weekly%20issue%20128&amp;utm_medium=web">CDE: An Attempt to Make Core Data Feel More Like Modern Swift</a></strong></h3><p>In <a href="https://fatbobman.com/en/posts/why-i-am-still-thinking-about-core-data-in-2026/">last week&#8217;s article</a>, I discussed the current reality of Core Data in modern projects: it hasn&#8217;t disappeared and still holds unique value, but the sense of misalignment between it and modern Swift development is becoming increasingly apparent. In this article, I continue along that line of thought and introduce an experimental project of mine: <a href="https://github.com/fatbobman/CoreDataEvolution">Core Data Evolution</a> (CDE).</p><p>It is not a new framework intended to replace Core Data, nor is it an attempt to pull developers back to older technologies. More accurately, it is my own response to this misalignment: <strong>if I still recognize the value of Core Data&#8217;s object graph model, migration system, and mature runtime, can it continue to exist in modern Swift projects in a more natural way?</strong></p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0128-01">Expanding Animations in SwiftUI Lists</a></strong></h3><p>Developers often encounter a frustrating animation issue: when dynamically changing the height of a row inside a <code>List</code>, the content does not expand smoothly, but instead jumps abruptly. In this article, <a href="https://x.com/myridiphis">Pavel Zak</a> demonstrates through several experiments why common approaches such as conditional rendering with <code>if</code>, <code>withAnimation</code>, or even <code>.transition</code> fail to produce the desired effect inside <code>List</code>. While built-in solutions like <code>DisclosureGroup</code> can achieve smoother results, Pavel presents a more flexible approach: using <code>Animatable</code> combined with view size measurement to ensure that <code>List</code> receives continuously changing height values during the animation, resulting in a truly smooth expansion.</p><blockquote><p>A key characteristic of <code>List</code> (which is still backed by UIKit/AppKit) is that it requires a <em>definitive row height</em> during layout. Therefore, instead of letting <code>List</code> deal with structural changes, developers should, like <code>DisclosureGroup</code>, transform &#8220;discrete changes&#8221; into &#8220;continuous changes&#8221; by providing interpolatable height values. This is also why developers often resort to the <code>Animatable</code> protocol when dealing with animation anomalies. For a deeper understanding of this protocol and its use cases, you can refer to my previous <a href="https://fatbobman.com/en/posts/animatable-protocol-taming-unruly-swiftui-animation/">article</a>.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-02">SwiftUI iPad Adaptive Layout: Five Layers for Apps That Don&#8217;t Break in Split View</a></strong></h3><p>While Apple&#8217;s push toward multi-window capabilities in iPadOS is well-intentioned, it significantly increases the complexity of layout adaptation. Apps may appear in various forms, such as iPhone-like layouts, traditional full-screen iPad views, or Stage Manager windows. <a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> points out that relying solely on <code>horizontalSizeClass</code> is often insufficient in real-world scenarios. Developers need to combine container size with size classes to build a more fine-grained <code>LayoutEnvironment</code>, make layout branching decisions at the root view, and leverage mechanisms like <code>ViewThatFits</code> to let the system choose the most appropriate UI based on actual constraints, rather than assumptions about the device.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-03">Pitfalls and workarounds when dealing with RGB HDR Gain Map using ImageIO</a></strong></h3><p>The introduction of RGB HDR Gain Map based on the ISO 21496-1 standard in iOS 18 enables richer HDR image processing, but also introduces new pitfalls. Although the relevant APIs can return auxiliary data dictionaries, in the RGB Gain Map scenario the actual bitmap data (<code>kCGImageAuxiliaryDataInfoData</code>) is missing, preventing further processing. In other words, ImageIO is unable to fully read the content it generates in this case. <a href="https://x.com/JuniperPhoton">Weichao Deng</a> proposes a hybrid approach: use Core Image to read the Gain Map as a <code>CIImage</code>, manually render it into bitmap data, reconstruct the missing fields, and then write it back via ImageIO. For developers working on camera or image processing apps that involve HDR Gain Maps, this article can save a significant amount of debugging time.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-04">A Vision for Networking in Swift</a></strong></h3><p>The <a href="https://www.swift.org/ecosystem-steering-group/">Swift Ecosystem Steering Group</a> recently published a vision document on networking, discussing the current fragmentation in Swift&#8217;s networking ecosystem and its potential future direction.</p><p>The document highlights a clear divide: <code>URLSession</code>, SwiftNIO, and Network.framework coexist with overlapping functionality but incompatible abstractions. Developers often need to commit early to a specific stack, making later changes costly. Additionally, most existing networking APIs were designed before Swift Concurrency and rely on completion handlers, delegates, or reactive patterns, which feel increasingly out of place in modern Swift.</p><p>The proposed direction is a unified, layered networking architecture: shared I/O primitives and buffer types at the bottom, reusable protocol implementations (TLS, HTTP/1.1/2/3, QUIC, WebSocket) in the middle, and async/await-based client and server APIs at the top. The <code>swift-http-types</code> package (defining <code>HTTPRequest</code> / <code>HTTPResponse</code>) can be seen as an early step in this direction. The document also emphasizes that SwiftNIO and Network.framework will not be replaced, but will gradually converge toward shared underlying primitives.</p><blockquote><p>The vision is currently open for community feedback. You can <a href="https://forums.swift.org/t/prospective-vision-networking/">participate here</a>.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-05">Preparing Your iOS Codebase for AI Agents</a></strong></h3><p>As AI agents (such as Codex and Claude Code) become increasingly involved in real-world development workflows, the focus is shifting from &#8220;how to use AI to write code&#8221; to &#8220;how to make codebases suitable for AI collaboration&#8221;. <a href="https://hachyderm.io/@IronHam">Hesham Salman</a> explores this transition from an engineering perspective.</p><p>He argues that AI relies more on explicit contracts than on prompts. By structuring project conventions and behavioral rules through layered <code>AGENTS.md</code> documentation, using a Makefile to standardize build and test workflows, and encoding multi-step processes into reusable &#8220;skills,&#8221; implicit engineering knowledge can be transformed into structured, machine-readable systems.</p><blockquote><p>One particularly insightful detail: the author requires agents to update documentation whenever they encounter undocumented conventions, while enforcing a strict rule &#8212; <strong>every change must make the document shorter or more useful</strong>. This self-maintaining mechanism prevents both documentation decay and uncontrolled growth, striking a practical balance.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-06">iOS Conf SG 2026 Videos</a></strong></h3><p>iOS Conf SG 2026 was held from January 21 to 23 in Singapore, featuring dozens of developers and content creators from around the world sharing their insights and experiences in the Apple ecosystem. Last week, the full set of talks was released. I also had the opportunity to participate as a speaker, and you can explore the sessions as you&#8217;re interested.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0128-07">TaskGate: Managing Actor Reentrancy</a></strong></h3><p>While actors largely eliminate data races, their reentrant nature means that logic which appears sequential can lose its execution order after an <code>await</code>, leading to duplicate work or inconsistent state.</p><p>TaskGate, created by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a>, addresses this scenario by introducing <code>AsyncGate</code> and <code>AsyncRecursiveGate</code>, which define critical sections for asynchronous code within actors. These ensure that only one task can enter a given section at a time. Unlike traditional locks, TaskGate allows safe asynchronous operations while holding the gate.</p><blockquote><p>Matt explicitly notes that this is not a replacement for well-designed actor models, but rather a supplementary tool when other approaches are insufficient. The gates are intentionally non-Sendable to reduce misuse across actors. If you&#8217;re dealing with reentrancy-related state issues or want to better understand this subtle aspect of Swift concurrency, both the library and the related <a href="https://www.reddit.com/r/swift/comments/1rx9aii/taskgate_library_for_managing_actor_reentrancy/">Reddit discussion</a> are worth exploring.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-08">pico-bare-swift</a></strong></h3><p>When Apple created Swift, the goal was clearly broader than just app development&#8212;it was meant to evolve into a general-purpose language across domains and abstraction levels. However, for a long time, Swift has struggled to gain traction in areas traditionally dominated by C/C++ or Rust. Through this example project, <a href="https://hachyderm.io/@kishikawakatsumi">kishikawa katsumi</a> demonstrates another possibility: with Embedded Swift, the language is beginning to enter the domain of embedded systems.</p><blockquote><p>What makes this project particularly appealing is that it turns something traditionally associated with low-level, C-centric development into a structured learning path. It goes far beyond &#8220;blinking an LED with Swift,&#8221; covering startup code, vector tables, memory initialization, register access, as well as drivers for UART, PWM, I2C, and SSD1306 OLED displays. In a sense, <strong>the value of such projects lies not in their practicality, but in how they redefine the boundaries of what Swift can do</strong>.</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-128?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-128?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#25105;&#30340; App &#23457;&#26680;&#34987;&#21345;&#20102;&#65311;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-128/">&#32593;&#39029;&#29256;</a></strong></p><p>&#19978;&#21608;&#22235;&#65292;&#25105; Discord &#31038;&#21306;&#37324;&#30340;&#19968;&#20301;&#32593;&#21451;&#25265;&#24616;&#65292;&#35828;&#20182;&#30340;&#24212;&#29992;&#22312; App Store Connect &#19978;&#25552;&#20132;&#20102;&#22235;&#20116;&#22825;&#65292;&#21364;&#36831;&#36831;&#27809;&#26377;&#36827;&#20837;&#23457;&#26680;&#29366;&#24577;&#12290;&#23601;&#22312;&#25105;&#36824;&#27941;&#27941;&#26377;&#21619;&#22320;&#36319;&#22823;&#20249;&#20799;&#20998;&#26512;&#21407;&#22240;&#26102;&#65292;&#31361;&#28982;&#24515;&#37324;&#19968;&#32039;&#65306;&#25105;&#21608;&#19968;&#25552;&#20132;&#30340;&#24212;&#29992;&#65292;&#22909;&#20687;&#20063;&#19968;&#30452;&#27809;&#25910;&#21040;&#23457;&#26680;&#21160;&#24577;&#65311;</p><p>&#26377;&#32593;&#21451;&#24314;&#35758;&#25105;&#21435;&#30003;&#35831;&#19968;&#19979;&#8220;&#21152;&#24613;&#23457;&#26680;&#8221;&#12290;&#21487;&#24403;&#25105;&#28857;&#36827;&#39029;&#38754;&#26102;&#65292;&#31995;&#32479;&#21364;&#25552;&#31034;&#25105;&#8220;&#27809;&#26377;&#21487;&#21152;&#24613;&#30340;&#24212;&#29992;&#8221;&#12290;&#20180;&#32454;&#19968;&#26597;&#25165;&#21457;&#29616;&#65292;&#21407;&#26469;&#26159;&#22826;&#20037;&#27809;&#26356;&#26032; App&#65292;&#19994;&#21153;&#37117;&#29983;&#30095;&#20102;&#8212;&#8212;&#25105;&#30340;&#24212;&#29992;&#34429;&#28982;&#23436;&#25104;&#20102;&#25152;&#26377;&#21069;&#32622;&#27493;&#39588;&#65292;&#20294;&#25105;&#21387;&#26681;&#20799;&#23601;&#27809;&#28857;&#37027;&#20010;&#8220;&#25552;&#20132;&#20197;&#20379;&#23457;&#26680;&#8221;&#30340;&#25353;&#38062;&#12290;</p><p>&#34917;&#28857;&#25353;&#38062;&#27809;&#36807;&#20960;&#20010;&#23567;&#26102;&#65292;&#24212;&#29992;&#23601;&#39034;&#21033;&#19978;&#26550;&#20102;&#12290;</p><p>&#23613;&#31649;&#25105;&#36825;&#32431;&#23646;&#34394;&#24778;&#19968;&#22330;&#65292;&#20294;&#26368;&#36817;&#31038;&#21306;&#37324;&#20851;&#20110;&#8220;&#33529;&#26524;&#23457;&#26680;&#21464;&#24930;&#8221;&#30340;&#35752;&#35770;&#30830;&#23454;&#22810;&#20102;&#36215;&#26469;&#12290;&#24456;&#22810;&#20154;&#29468;&#27979;&#65292;&#36825;&#25110;&#35768;&#19982;&#36817;&#26399; Vibe Coding &#30340;&#30427;&#34892;&#26377;&#20851;&#12290;&#34429;&#28982;&#27809;&#26377;&#23448;&#26041;&#35777;&#23454;&#65292;&#20294; Vibe Coding &#30830;&#23454;&#22312;&#38477;&#20302;&#24320;&#21457;&#38376;&#27099;&#30340;&#21516;&#26102;&#65292;&#20063;&#22312;&#30701;&#26102;&#38388;&#20869;&#25918;&#22823;&#20102;&#24212;&#29992;&#25552;&#20132;&#30340;&#25968;&#37327;&#19982;&#36845;&#20195;&#39057;&#29575;&#65292;&#20174;&#32780;&#25226;&#21387;&#21147;&#20256;&#23548;&#21040;&#20102;&#23457;&#26680;&#29615;&#33410;&#12290;</p><p>&#20107;&#23454;&#19978;&#65292;&#33529;&#26524;&#26368;&#36817;&#20063;&#30830;&#23454;&#23545; Replit &#36825;&#31867;&#20801;&#35768;&#26222;&#36890;&#29992;&#25143;&#36827;&#34892; Vibe Coding &#30340;&#24212;&#29992;&#22312;&#23457;&#26680;&#19978;&#36827;&#34892;&#20102;&#21345;&#20851;&#12290;&#21363;&#20415;&#20801;&#35768;&#20854;&#19978;&#26550;&#65292;&#20063;&#35201;&#27714;&#22312;&#26680;&#24515;&#21151;&#33021;&#19978;&#20570;&#20986;&#22949;&#21327;&#12290;&#22312; Michael Tsai &#20851;&#20110;&#27492;&#20107;&#30340;<a href="https://mjtsai.com/blog/2026/03/20/updates-to-vibe-coding-apps-rejected-from-the-app-store/">&#21338;&#23458;&#20171;&#32461;</a>&#20013;&#65292;&#25105;&#30475;&#21040;&#20102;&#19968;&#26465;&#38750;&#24120;&#25935;&#38160;&#30340;&#30041;&#35328;&#65306;</p><blockquote><p>I thought the implication was that the vibe coding apps were being used to make the vibecoded apps that get submitted.</p><p>&#36825;&#20123; Vibe Coding &#24212;&#29992;&#27491;&#34987;&#29992;&#26469;&#25209;&#37327;&#21046;&#36896;&#37027;&#20123;&#25552;&#20132;&#19978;&#26550;&#30340;&#24212;&#29992;&#12290;</p></blockquote><p>AI &#19981;&#20165;&#22312;&#37325;&#22609;&#24320;&#21457;&#26041;&#24335;&#65292;&#20063;&#27491;&#22312;&#23545;&#24212;&#29992;&#23457;&#26680;&#19982;&#21457;&#34892;&#20307;&#31995;&#25552;&#20986;&#26032;&#30340;&#25361;&#25112;&#12290;&#26377;&#20154;&#25110;&#35768;&#20250;&#38382;&#65306;&#22914;&#26524;&#29992;&#39764;&#27861;&#25171;&#36133;&#39764;&#27861;&#65292;&#35753; AI &#20063;&#20840;&#38754;&#25509;&#31649;&#23457;&#26680;&#27969;&#31243;&#65292;&#20250;&#19981;&#20250;&#26356;&#39640;&#25928;&#65311;</p><p>&#33529;&#26524;&#30340;&#23457;&#26680;&#26426;&#21046;&#21521;&#26469;&#19981;&#22815;&#36879;&#26126;&#65292;&#26377;&#26102;&#20505;&#24212;&#29992;&#33021;&#21542;&#39034;&#21033;&#36807;&#23457;&#65292;&#29978;&#33267;&#21462;&#20915;&#20110;&#26159;&#21542;&#8220;&#30896;&#24039;&#8221;&#36935;&#21040;&#19968;&#20301;&#27668;&#21619;&#30456;&#25237;&#30340;&#23457;&#26680;&#21592;&#12290;&#20294;&#25442;&#20010;&#35282;&#24230;&#30475;&#65292;&#33267;&#23569;&#8220;&#20154;&#8221;&#20173;&#28982;&#26159;&#36825;&#36947;&#38450;&#32447;&#20013;&#26368;&#37325;&#35201;&#30340;&#19968;&#29615;&#12290;&#20154;&#30340;&#21028;&#26029;&#20250;&#20986;&#38169;&#65292;&#20063;&#20250;&#24102;&#26377;&#20559;&#24046;&#65292;&#20294;&#22312;&#38754;&#23545;&#35268;&#21017;&#26102;&#20173;&#20445;&#26377;&#19968;&#23450;&#30340;&#24377;&#24615;&#12290;</p><p>&#25105;&#19981;&#24076;&#26395;&#65292;&#26410;&#26469;&#30340;&#36719;&#20214;&#29983;&#24577;&#65292;&#36208;&#21521;&#8220;AI &#24320;&#21457; -&gt; AI &#23457;&#26680;&#8221;&#30340;&#38381;&#29615;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-127/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/?utm_source=fatbobman%20weekly%20issue%20128&amp;utm_medium=web">CDE&#65306;&#19968;&#27425;&#35753; Core Data &#26356;&#20687;&#29616;&#20195; Swift &#30340;&#23581;&#35797;</a></strong></h3><p>&#22312; <a href="https://fatbobman.com/zh/posts/why-i-am-still-thinking-about-core-data-in-2026/">&#19978;&#21608;&#30340;&#25991;&#31456;</a> &#20013;&#65292;&#25105;&#32842;&#20102;&#32842; Core Data &#22312;&#24403;&#19979;&#39033;&#30446;&#20013;&#30340;&#19968;&#20123;&#29616;&#23454;&#22788;&#22659;&#65306;&#23427;&#24182;&#27809;&#26377;&#28040;&#22833;&#65292;&#20063;&#20173;&#28982;&#26377;&#20854;&#29420;&#29305;&#20215;&#20540;&#65292;&#20294;&#23427;&#21644;&#29616;&#20195; Swift &#39033;&#30446;&#20043;&#38388;&#30340;&#38169;&#20301;&#24863;&#21364;&#36234;&#26469;&#36234;&#26126;&#26174;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;&#25105;&#24819;&#32487;&#32493;&#39034;&#30528;&#36825;&#20010;&#38382;&#39064;&#24448;&#19979;&#36208;&#65292;&#20171;&#32461;&#25105;&#30340;&#19968;&#20010;&#23454;&#39564;&#24615;&#39033;&#30446;&#65306;<a href="https://github.com/fatbobman/CoreDataEvolution">Core Data Evolution</a>&#65288;CDE&#65289;&#12290;</p><p>&#23427;&#19981;&#26159;&#19968;&#20010;&#21462;&#20195; Core Data &#30340;&#26032;&#26694;&#26550;&#65292;&#20063;&#19981;&#26159;&#35201;&#25226;&#24320;&#21457;&#32773;&#37325;&#26032;&#25289;&#22238;&#26087;&#25216;&#26415;&#12290;&#26356;&#20934;&#30830;&#22320;&#35828;&#65292;&#23427;&#26159;&#25105;&#38754;&#23545;&#36825;&#20123;&#38169;&#20301;&#26102;&#65292;&#32473;&#33258;&#24049;&#30340;&#19968;&#31181;&#22238;&#31572;&#65306;<strong>&#22914;&#26524;&#25105;&#20173;&#28982;&#35748;&#21487; Core Data &#30340;&#23545;&#35937;&#22270;&#27169;&#22411;&#12289;&#36801;&#31227;&#20307;&#31995;&#21644;&#25104;&#29087;&#36816;&#34892;&#26102;&#33021;&#21147;&#65292;&#37027;&#20040;&#33021;&#19981;&#33021;&#35753;&#23427;&#22312;&#29616;&#20195; Swift &#39033;&#30446;&#20013;&#20197;&#19968;&#31181;&#26356;&#33258;&#28982;&#30340;&#26041;&#24335;&#32487;&#32493;&#23384;&#22312;&#19979;&#21435;&#65311;</strong></p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0128-01">&#23454;&#29616;&#24179;&#28369;&#30340; SwiftUI List &#23637;&#24320;&#21160;&#30011; (Expanding Animations in SwiftUI Lists)</a></strong></h3><p>&#24320;&#21457;&#32773;&#32463;&#24120;&#20250;&#36935;&#21040;&#19968;&#20010;&#21160;&#30011;&#31384;&#22659;&#65306;&#22312;&#21160;&#24577;&#35843;&#25972; <code>List</code> &#20013;&#26576;&#19968;&#34892;&#39640;&#24230;&#26102;&#65292;&#20869;&#23481;&#24182;&#19981;&#26159;&#24179;&#28369;&#23637;&#24320;&#65292;&#32780;&#26159;&#20276;&#38543;&#30528;&#26126;&#26174;&#30340;&#39640;&#24230;&#36339;&#21464;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://x.com/myridiphis">Pavel Zak</a> &#36890;&#36807;&#20960;&#20010;&#23454;&#39564;&#65292;&#23637;&#31034;&#20102;&#20026;&#20160;&#20040;&#24120;&#35265;&#30340; <code>if</code> &#26465;&#20214;&#28210;&#26579;&#12289;<code>withAnimation</code> &#29978;&#33267; <code>.transition</code> &#22312; <code>List</code> &#20013;&#37117;&#38590;&#20197;&#36798;&#21040;&#29702;&#24819;&#25928;&#26524;&#12290;&#23613;&#31649; <code>DisclosureGroup</code> &#36825;&#31181;&#20869;&#24314;&#26041;&#26696;&#21487;&#20197;&#36798;&#21040;&#39044;&#26399;&#65292;&#20294; Pavel &#36824;&#26159;&#32473;&#20986;&#20102;&#19968;&#20010;&#26356;&#28789;&#27963;&#30340;&#26041;&#26696;&#65306;&#22522;&#20110; <code>Animatable</code> &#19982;&#35270;&#22270;&#23610;&#23544;&#27979;&#37327;&#30340;&#23454;&#29616;&#26041;&#24335;&#65292;&#35753; <code>List</code> &#22312;&#21160;&#30011;&#36807;&#31243;&#20013;&#22987;&#32456;&#33719;&#24471;&#36830;&#32493;&#21464;&#21270;&#30340;&#39640;&#24230;&#65292;&#20174;&#32780;&#23454;&#29616;&#24179;&#28369;&#30340;&#23637;&#24320;&#21160;&#30011;&#12290;</p><blockquote><p><code>List</code>&#65288;&#24213;&#23618;&#20173;&#28982;&#26159; UIKit/AppKit &#30340;&#21015;&#34920;&#23454;&#29616;&#65289;&#26377;&#19968;&#20010;&#26680;&#24515;&#29305;&#28857;&#65306;&#23427;&#38656;&#35201;&#22312;&#24067;&#23616;&#38454;&#27573;&#23601;&#25343;&#21040;&#27599;&#19968;&#34892;&#30340;&#8220;&#30830;&#23450;&#39640;&#24230;&#8221;&#12290;&#22240;&#27492;&#65292;&#23545;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#19981;&#35201;&#35753; <code>List</code> &#38754;&#23545;&#32467;&#26500;&#21464;&#21270;&#65292;&#32780;&#26159;&#20687; <code>DisclosureGroup</code> &#37027;&#26679;&#65292;&#23558;&#8220;&#31163;&#25955;&#21464;&#21270;&#8221;&#36716;&#21270;&#20026;&#8220;&#36830;&#32493;&#21464;&#21270;&#8221;&#65292;&#25345;&#32493;&#25552;&#20379;&#21487;&#25554;&#20540;&#30340;&#39640;&#24230;&#20540;&#12290;&#36825;&#20063;&#26159;&#22312;&#22788;&#29702;&#21160;&#30011;&#24322;&#24120;&#26102;&#65292;&#24320;&#21457;&#32773;&#24120;&#24120;&#20511;&#21161; <code>Animatable</code> &#21327;&#35758;&#30340;&#21407;&#22240;&#12290;&#24819;&#36827;&#19968;&#27493;&#20102;&#35299;&#35813;&#21327;&#35758;&#30340;&#21407;&#29702;&#19982;&#36866;&#29992;&#22330;&#26223;&#65292;&#21487;&#20197;&#38405;&#35835;&#25105;&#20043;&#21069;&#30340;&#19968;&#31687;<a href="https://fatbobman.com/zh/posts/animatable-protocol-taming-unruly-swiftui-animation/">&#25991;&#31456;</a>&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-02">&#22914;&#20309;&#26356;&#22909;&#30340;&#36866;&#37197; iPadOS &#30340;&#24067;&#23616; (SwiftUI iPad Adaptive Layout: Five Layers for Apps That Don&#8217;t Break in Split View)</a></strong></h3><p>&#23613;&#31649;&#33529;&#26524;&#24378;&#21270; iPadOS &#22810;&#31383;&#21475;&#33021;&#21147;&#30340;&#21021;&#34935;&#26159;&#22909;&#30340;&#65292;&#20294;&#36825;&#20063;&#26174;&#33879;&#25552;&#21319;&#20102;&#24320;&#21457;&#32773;&#22312;&#24067;&#23616;&#36866;&#37197;&#19978;&#30340;&#22797;&#26434;&#24230;&#12290;&#24212;&#29992;&#21487;&#33021;&#20197;&#31867; iPhone&#12289;&#20256;&#32479; iPad &#20840;&#23631;&#12289;Stage Manager &#31383;&#21475;&#31561;&#22810;&#31181;&#27169;&#24335;&#21576;&#29616;&#12290;<a href="https://www.linkedin.com/in/wesmatlock/">Wesley Matlock</a> &#25351;&#20986;&#65292;&#20165;&#20381;&#36182; <code>horizontalSizeClass</code> &#36827;&#34892;&#24067;&#23616;&#21028;&#26029;&#22312;&#23454;&#38469;&#29615;&#22659;&#20013;&#24448;&#24448;&#26159;&#19981;&#22815;&#30340;&#12290;&#24320;&#21457;&#32773;&#38656;&#35201;&#32467;&#21512;&#23481;&#22120;&#23610;&#23544;&#19982; size class &#26500;&#24314;&#26356;&#32454;&#31890;&#24230;&#30340; <code>LayoutEnvironment</code>&#65292;&#24182;&#22312;&#26681;&#35270;&#22270;&#20013;&#32479;&#19968;&#23436;&#25104;&#24067;&#23616;&#20998;&#25903;&#20915;&#31574;&#65307;&#21516;&#26102;&#20511;&#21161; <code>ViewThatFits</code> &#31561;&#26426;&#21046;&#65292;&#35753;&#31995;&#32479;&#22522;&#20110;&#30495;&#23454;&#32422;&#26463;&#36873;&#25321;&#26368;&#21512;&#36866;&#30340;&#30028;&#38754;&#24418;&#24335;&#65292;&#32780;&#19981;&#26159;&#30001;&#24320;&#21457;&#32773;&#39044;&#20808;&#20551;&#35774;&#35774;&#22791;&#31867;&#22411;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-03">RGB HDR Gain Map + ImageIO &#20013;&#30340;&#20351;&#29992;&#38519;&#38449; (Pitfalls and workarounds when dealing with RGB HDR Gain Map using ImageIO)</a></strong></h3><p>iOS 18 &#20013;&#24341;&#20837;&#30340;&#22522;&#20110; ISO 21496-1 &#26631;&#20934;&#30340; RGB HDR Gain Map&#65292;&#35753;&#24320;&#21457;&#32773;&#22312;&#22788;&#29702; HDR &#22270;&#20687;&#26102;&#33719;&#24471;&#20102;&#26356;&#39640;&#30340;&#34920;&#29616;&#21147;&#65292;&#20294;&#22312;&#23454;&#38469;&#24212;&#29992;&#20013;&#20063;&#26356;&#23481;&#26131;&#36393;&#22353;&#65306;&#23613;&#31649;&#30456;&#20851;&#25509;&#21475;&#33021;&#22815;&#36820;&#22238;&#36741;&#21161;&#25968;&#25454;&#23383;&#20856;&#65292;&#20294;&#22312; RGB Gain Map &#22330;&#26223;&#19979;&#21364;&#32570;&#22833;&#20102;&#23454;&#38469;&#30340;&#20301;&#22270;&#25968;&#25454;&#65288;<code>kCGImageAuxiliaryDataInfoData</code>&#65289;&#65292;&#23548;&#33268;&#21518;&#32493;&#22788;&#29702;&#26080;&#27861;&#32487;&#32493;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;ImageIO &#22312;&#36825;&#19968;&#22330;&#26223;&#19979;&#29978;&#33267;&#26080;&#27861;&#23436;&#25972;&#35835;&#21462;&#33258;&#36523;&#29983;&#25104;&#30340;&#20869;&#23481;&#12290;<a href="https://x.com/JuniperPhoton">Weichao Deng</a> &#25552;&#20986;&#20102;&#19968;&#31181;&#28151;&#21512;&#26041;&#26696;&#65306;&#20351;&#29992; Core Image &#35835;&#21462; Gain Map &#30340; <code>CIImage</code>&#65292;&#25163;&#21160;&#28210;&#26579;&#20026; Bitmap Data&#65292;&#34917;&#40784;&#32570;&#22833;&#23383;&#27573;&#21518;&#65292;&#20877;&#36890;&#36807; ImageIO &#20889;&#22238;&#25991;&#20214;&#12290;&#23545;&#20110;&#27491;&#22312;&#24320;&#21457;&#30456;&#26426;&#25110;&#22270;&#20687;&#22788;&#29702;&#31867;&#24212;&#29992;&#12289;&#38656;&#35201;&#22788;&#29702; HDR Gain Map &#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#31687;&#25991;&#31456;&#25110;&#35768;&#33021;&#24110;&#20320;&#30465;&#19979;&#19981;&#23569;&#35843;&#35797;&#26102;&#38388;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-04">Swift &#31038;&#21306;&#30340;&#32593;&#32476;&#24895;&#26223; (A Vision for Networking in Swift)</a></strong></h3><p><a href="https://www.swift.org/ecosystem-steering-group/">Swift Ecosystem Steering Group</a> &#19978;&#21608;&#21457;&#24067;&#20102;&#19968;&#20221;&#20851;&#20110;&#32593;&#32476;&#32534;&#31243;&#30340;&#24895;&#26223;&#25991;&#26723;&#65292;&#35752;&#35770;&#20102; Swift &#32593;&#32476;&#29983;&#24577;&#24403;&#21069;&#30340;&#22256;&#22659;&#20197;&#21450;&#26410;&#26469;&#21487;&#33021;&#30340;&#21457;&#23637;&#26041;&#21521;&#12290;</p><p>&#25991;&#26723;&#25351;&#20986;&#65292;Swift &#22312;&#32593;&#32476;&#39046;&#22495;&#23384;&#22312;&#26126;&#26174;&#30340;&#20998;&#35010;&#65306;<code>URLSession</code>&#12289;SwiftNIO &#19982; Network.framework &#24182;&#23384;&#65292;&#21151;&#33021;&#37325;&#21472;&#21364;&#20114;&#19981;&#20860;&#23481;&#65292;&#24320;&#21457;&#32773;&#24448;&#24448;&#38656;&#35201;&#22312;&#39033;&#30446;&#26089;&#26399;&#23601;&#25276;&#27880;&#26576;&#19968;&#22871;&#25216;&#26415;&#26632;&#65292;&#19988;&#20999;&#25442;&#25104;&#26412;&#26497;&#39640;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#29616;&#26377;&#30340;&#22823;&#22810;&#25968;&#32593;&#32476; API &#37117;&#35806;&#29983;&#20110; Swift Concurrency &#20043;&#21069;&#65292;&#20381;&#36182; completion handler&#12289;delegate &#25110;&#21709;&#24212;&#24335;&#27169;&#24335;&#65292;&#19982;&#29616;&#20195; Swift &#30340;&#35821;&#35328;&#29305;&#24615;&#23384;&#22312;&#26126;&#26174;&#33073;&#33410;&#12290;</p><p>&#25991;&#26723;&#25552;&#20986;&#30340;&#26041;&#21521;&#26159;&#26500;&#24314;&#19968;&#22871;&#20998;&#23618;&#32479;&#19968;&#30340;&#32593;&#32476;&#26550;&#26500;&#65306;&#24213;&#23618;&#20849;&#20139; I/O &#21407;&#35821;&#19982;&#32531;&#20914;&#31867;&#22411;&#65292;&#20013;&#38388;&#23618;&#22797;&#29992; TLS&#12289;HTTP/1.1/2/3&#12289;QUIC&#12289;WebSocket &#31561;&#21327;&#35758;&#23454;&#29616;&#65292;&#39030;&#23618;&#25552;&#20379;&#20197; async/await &#21644;&#32467;&#26500;&#21270;&#24182;&#21457;&#20026;&#22522;&#30784;&#30340;&#23458;&#25143;&#31471;&#19982;&#26381;&#21153;&#31471; API&#12290;&#24050;&#26377;&#30340; <code>swift-http-types</code>&#65288;&#23450;&#20041;&#20102; <code>HTTPRequest</code> / <code>HTTPResponse</code>&#65289;&#21487;&#20197;&#35270;&#20026;&#36825;&#19968;&#24605;&#36335;&#30340;&#26089;&#26399;&#23454;&#36341;&#12290;&#25991;&#26723;&#21516;&#26102;&#24378;&#35843;&#65292;SwiftNIO &#21644; Network.framework &#19981;&#20250;&#34987;&#24223;&#24323;&#65292;&#32780;&#26159;&#23558;&#36880;&#27493;&#21521;&#32479;&#19968;&#30340;&#24213;&#23618;&#21407;&#35821;&#25910;&#25947;&#12290;</p><blockquote><p>&#35813;&#24895;&#26223;&#30446;&#21069;&#27491;&#22312;&#24449;&#38598;&#31038;&#21306;&#21453;&#39304;&#65292;&#21487;&#20197;<a href="https://forums.swift.org/t/prospective-vision-networking/">&#22312;&#27492;&#21442;&#19982;</a>&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-05">&#35753;&#20320;&#30340; iOS &#39033;&#30446;&#26356;&#36866;&#21512; AI &#21327;&#20316; (Preparing Your iOS Codebase for AI Agents)</a></strong></h3><p>&#38543;&#30528; AI agent&#65288;&#22914; Codex&#12289;Claude Code &#31561;&#65289;&#36880;&#28176;&#21442;&#19982;&#21040;&#23454;&#38469;&#24320;&#21457;&#27969;&#31243;&#20013;&#65292;&#38382;&#39064;&#24320;&#22987;&#20174;&#8220;&#22914;&#20309;&#20351;&#29992; AI &#20889;&#20195;&#30721;&#8221;&#36716;&#21521;&#8220;&#22914;&#20309;&#35753;&#20195;&#30721;&#24211;&#26412;&#36523;&#36866;&#21512; AI &#21327;&#20316;&#8221;&#12290;<a href="https://hachyderm.io/@IronHam">Hesham Salman</a> &#20174;&#24037;&#31243;&#23454;&#36341;&#30340;&#35282;&#24230;&#65292;&#31995;&#32479;&#24615;&#22320;&#25506;&#35752;&#20102;&#36825;&#19968;&#36716;&#21464;&#12290;</p><p>Hesham &#25351;&#20986;&#65292;&#30456;&#36739;&#20110;&#25552;&#31034;&#35789;&#65292;AI &#26356;&#20381;&#36182;&#26174;&#24335;&#22865;&#32422;&#12290;&#36890;&#36807;&#20998;&#23618;&#30340; <code>AGENTS.md</code> &#25991;&#26723;&#26126;&#30830;&#39033;&#30446;&#32422;&#23450;&#19982;&#34892;&#20026;&#35268;&#21017;&#65292;&#20351;&#29992; Makefile &#23558;&#26500;&#24314;&#12289;&#27979;&#35797;&#31561;&#25805;&#20316;&#32479;&#19968;&#20026;&#21487;&#25191;&#34892;&#20837;&#21475;&#65292;&#24182;&#36890;&#36807;&#8220;skills&#8221;&#23558;&#22810;&#27493;&#39588;&#27969;&#31243;&#32534;&#30721;&#20026;&#21487;&#22797;&#29992;&#30340;&#25191;&#34892;&#26041;&#27861;&#65292;&#20174;&#32780;&#23558;&#21407;&#26412;&#38544;&#24615;&#30340;&#24037;&#31243;&#30693;&#35782;&#32467;&#26500;&#21270;&#22320;&#23884;&#20837;&#21040;&#20195;&#30721;&#24211;&#20013;&#12290;</p><blockquote><p>&#25991;&#31456;&#20013;&#26377;&#19968;&#20010;&#32454;&#33410;&#20196;&#20154;&#21360;&#35937;&#28145;&#21051;&#65306;&#20316;&#32773;&#35201;&#27714; agent &#22312;&#21457;&#29616;&#26410;&#35760;&#24405;&#30340;&#32422;&#23450;&#26102;&#20027;&#21160;&#26356;&#26032;&#25991;&#26723;&#65292;&#21516;&#26102;&#21152;&#20837;&#20102;&#19968;&#26465;&#24378;&#32422;&#26463;&#8212;&#8212;<strong>&#27599;&#27425;&#20462;&#25913;&#37117;&#24517;&#39035;&#35753;&#25991;&#26723;&#26356;&#30701;&#25110;&#26356;&#26377;&#29992;</strong>&#12290;&#36825;&#19968;&#33258;&#32500;&#25252;&#26426;&#21046;&#26082;&#38450;&#27490;&#25991;&#26723;&#33104;&#21270;&#65292;&#20063;&#36991;&#20813;&#25991;&#26723;&#33192;&#32960;&#65292;&#26159;&#19968;&#20010;&#20540;&#24471;&#20511;&#37492;&#30340;&#24179;&#34913;&#31574;&#30053;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-06">iOS Conf SG 2026 &#35270;&#39057;</a></strong></h3><p>2026 &#24180; iOS Conf SG &#20110; 1 &#26376; 21 &#26085;&#33267; 23 &#26085;&#22312;&#26032;&#21152;&#22369;&#20030;&#34892;&#65292;&#26469;&#33258;&#20840;&#29699;&#30340;&#25968;&#21313;&#20301;&#24320;&#21457;&#32773;&#19982;&#20869;&#23481;&#21019;&#20316;&#32773;&#20998;&#20139;&#20102;&#21508;&#33258;&#22312;&#33529;&#26524;&#29983;&#24577;&#24320;&#21457;&#20013;&#30340;&#32463;&#39564;&#19982;&#24605;&#32771;&#12290;&#19978;&#21608;&#65292;&#23448;&#26041;&#25918;&#20986;&#20102;&#26412;&#23626;&#30340;&#20840;&#37096;&#28436;&#35762;&#35270;&#39057;&#12290;&#25105;&#20063;&#26377;&#24184;&#21442;&#19982;&#20102;&#20854;&#20013;&#30340;&#19968;&#22330;&#20998;&#20139;&#65292;&#24863;&#20852;&#36259;&#30340;&#35835;&#32773;&#21487;&#20197;&#25353;&#38656;&#25361;&#36873;&#35266;&#30475;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0128-07">TaskGate&#65306;&#35299;&#20915; Actor &#37325;&#20837;&#30340;&#24037;&#20855;</a></strong></h3><p>&#23613;&#31649; actor &#22312;&#24456;&#22823;&#31243;&#24230;&#19978;&#36991;&#20813;&#20102;&#25968;&#25454;&#31454;&#20105;&#65292;&#20294;&#20854;&#21487;&#37325;&#20837;&#65288;reentrancy&#65289;&#29305;&#24615;&#20063;&#24847;&#21619;&#30528;&#65292;&#19968;&#20123;&#30475;&#20284;&#20018;&#34892;&#30340;&#36923;&#36753;&#22312; <code>await</code> &#20043;&#21518;&#21487;&#33021;&#22833;&#21435;&#21407;&#26377;&#30340;&#25191;&#34892;&#39034;&#24207;&#65292;&#36827;&#32780;&#36896;&#25104;&#37325;&#22797;&#25191;&#34892;&#25110;&#29366;&#24577;&#19981;&#19968;&#33268;&#12290;</p><p><a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#32534;&#20889;&#30340; TaskGate &#27491;&#26159;&#20026;&#36825;&#31867;&#22330;&#26223;&#20934;&#22791;&#30340;&#12290;&#23427;&#25552;&#20379;&#20102; <code>AsyncGate</code> &#21644; <code>AsyncRecursiveGate</code> &#20004;&#31181;&#26426;&#21046;&#65292;&#29992;&#26469;&#20026; actor &#20869;&#37096;&#30340;&#24322;&#27493;&#20195;&#30721;&#23450;&#20041;&#8220;&#20020;&#30028;&#21306;&#8221;&#65292;&#30830;&#20445;&#21516;&#19968;&#26102;&#38388;&#21482;&#26377;&#19968;&#20010;&#20219;&#21153;&#33021;&#22815;&#36827;&#20837;&#30456;&#20851;&#36923;&#36753;&#12290;&#19982;&#20256;&#32479;&#38145;&#19981;&#21516;&#30340;&#26159;&#65292;&#23427;&#20801;&#35768;&#22312;&#25345;&#26377; gate &#30340;&#21516;&#26102;&#23433;&#20840;&#22320;&#25191;&#34892;&#24322;&#27493;&#35843;&#29992;&#12290;</p><blockquote><p>Matt &#26126;&#30830;&#25351;&#20986;&#65306;&#35813;&#24211;&#24182;&#19981;&#26159;&#29992;&#26469;&#26367;&#20195;&#33391;&#22909;&#30340; actor &#35774;&#35745;&#65292;&#32780;&#26356;&#20687;&#26159;&#19968;&#31181;&#22312;&#20854;&#20182;&#25163;&#27573;&#19981;&#22815;&#21512;&#36866;&#26102;&#30340;&#34917;&#20805;&#24037;&#20855;&#12290;&#24211;&#20013;&#23558; gate &#21051;&#24847;&#35774;&#35745;&#20026; non-Sendable&#65292;&#20197;&#38477;&#20302;&#36328; actor &#35823;&#29992;&#30340;&#39118;&#38505;&#12290;&#22914;&#26524;&#20320;&#27491;&#22312;&#22788;&#29702; actor &#37325;&#20837;&#23548;&#33268;&#30340;&#29366;&#24577;&#19968;&#33268;&#24615;&#38382;&#39064;&#65292;&#25110;&#24076;&#26395;&#26356;&#28145;&#20837;&#29702;&#35299; Swift &#24182;&#21457;&#20013;&#30340;&#36825;&#19968;&#34180;&#24369;&#29615;&#33410;&#65292;&#36825;&#20010;&#24211;&#20197;&#21450; Matt &#22312; Reddit &#20013;&#30340; <a href="https://www.reddit.com/r/swift/comments/1rx9aii/taskgate_library_for_managing_actor_reentrancy/">&#35752;&#35770;</a> &#37117;&#20540;&#24471;&#19968;&#30475;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0128-08">pico-bare-swift</a></strong></h3><p>&#33529;&#26524;&#24403;&#24180;&#21019;&#24314; Swift &#26102;&#65292;&#23545;&#23427;&#30340;&#26399;&#24453;&#26174;&#28982;&#19981;&#21482;&#26159;&#29992;&#20110;&#24320;&#21457; App&#65292;&#32780;&#26159;&#24076;&#26395;&#23427;&#26368;&#32456;&#25104;&#38271;&#20026;&#19968;&#38376;&#36866;&#29992;&#20110;&#19981;&#21516;&#39046;&#22495;&#12289;&#19981;&#21516;&#23618;&#27425;&#30340;&#36890;&#29992;&#35821;&#35328;&#12290;&#19981;&#36807;&#65292;&#22312;&#30456;&#24403;&#38271;&#19968;&#27573;&#26102;&#38388;&#37324;&#65292;Swift &#22312;&#37027;&#20123;&#20256;&#32479;&#19978;&#30001; C/C++ &#25110; Rust &#20027;&#23548;&#30340;&#39046;&#22495;&#20013;&#65292;&#22987;&#32456;&#27809;&#26377;&#23637;&#29616;&#20986;&#36275;&#22815;&#30340;&#23384;&#22312;&#24863;&#12290;<a href="https://hachyderm.io/@kishikawakatsumi">kishikawa katsumi</a> &#36890;&#36807;&#36825;&#20010;&#31034;&#20363;&#39033;&#30446;&#23637;&#31034;&#20102;&#21478;&#19968;&#31181;&#21487;&#33021;&#65306;&#20511;&#21161; Embedded Swift&#65292;Swift &#24050;&#32463;&#24320;&#22987;&#20855;&#22791;&#36827;&#20837;&#23884;&#20837;&#24335;&#24320;&#21457;&#22330;&#26223;&#30340;&#33021;&#21147;&#12290;</p><blockquote><p>&#36825;&#20010;&#39033;&#30446;&#26368;&#21560;&#24341;&#25105;&#30340;&#22320;&#26041;&#65292;&#22312;&#20110;&#23427;&#23558;&#19968;&#20214;&#21407;&#26412;&#24102;&#26377;&#26126;&#26174;&#8220;&#24213;&#23618;/C &#35821;&#35328;&#19987;&#23646;&#8221;&#33394;&#24425;&#30340;&#20107;&#24773;&#65292;&#32452;&#32455;&#25104;&#20102;&#19968;&#26465;&#30456;&#24403;&#28165;&#26224;&#30340;&#23398;&#20064;&#36335;&#24452;&#12290;&#23427;&#19981;&#20165;&#26159;&#8220;&#29992; Swift &#28857;&#20142;&#19968;&#20010; LED&#8221;&#65292;&#32780;&#26159;&#23558;&#21551;&#21160;&#20195;&#30721;&#12289;&#21521;&#37327;&#34920;&#12289;&#20869;&#23384;&#21021;&#22987;&#21270;&#12289;&#23492;&#23384;&#22120;&#35775;&#38382;&#65292;&#20197;&#21450; UART&#12289;PWM&#12289;I2C&#12289;SSD1306 OLED &#31561;&#22806;&#35774;&#39537;&#21160;&#19968;&#24182;&#32435;&#20837; Swift &#30340;&#23454;&#29616;&#33539;&#22260;&#20043;&#20013;&#12290;&#26576;&#31181;&#31243;&#24230;&#19978;&#65292;<strong>&#36825;&#31867;&#39033;&#30446;&#30340;&#24847;&#20041;&#19981;&#22312;&#20110;&#8220;&#26159;&#21542;&#23454;&#29992;&#8221;&#65292;&#32780;&#22312;&#20110;&#23427;&#37325;&#26032;&#21010;&#23450;&#20102; Swift &#30340;&#33021;&#21147;&#36793;&#30028;</strong>&#12290;</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #127]]></title><description><![CDATA[Apple at 50 and Me at 51]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-127</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-127</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 16 Mar 2026 12:04:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6zhq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.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_!6zhq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6zhq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 424w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 848w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 1272w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6zhq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp" width="1182" height="607" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:607,&quot;width&quot;:1182,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14120,&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/191012253?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.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_!6zhq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 424w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 848w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.webp 1272w, https://substackcdn.com/image/fetch/$s_!6zhq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cdd317-b63f-4003-a4d7-c9d218007685_1182x607.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"><svg role="img" 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"><g><title></title><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"><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"><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>Apple at 50 and Me at 51</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-127/">Read on web &#8594;</a></p><p>In less than half a month, Apple will celebrate its 50th birthday. Tim Cook has also published <a href="https://www.apple.com/50-years-of-thinking-different/">a short piece</a> paying tribute to the journey of the past half-century. However, because of Apple&#8217;s image as a constant trendsetter, many people don&#8217;t realize that it is now a veritable elder statesman in the IT industry. Among the tech giants of its age, very few remain at the top-tier table today.</p><p>As a tech enthusiast who is only one year older than Apple, from the Apple II to today&#8217;s iPhone and MacBook, Apple&#8217;s products have accompanied me through most of my life. Strictly speaking, I wouldn&#8217;t call myself a hardcore Apple fan&#8212;I don&#8217;t feel regret if I don&#8217;t buy a new product on day one, I rarely stay up late to watch keynotes anymore, and I&#8217;m even less familiar with the exact specs of their newest devices. But looking back, at every major milestone in my life, I have naturally chosen Apple products, and in recent years, I have become a part of the Apple developer ecosystem.</p><p>To be honest, I haven&#8217;t entirely figured out where Apple&#8217;s enduring appeal to me comes from. Is it because I started using its products so early on? Is it its innovation, user experience, and overall vibe? Or is it Steve Jobs&#8217; charisma? Truth be told, my choice today is driven purely by habit and instinct, much like the unspoken understanding between old friends&#8212;it simply no longer requires any specific reason.</p><p>Of course, Apple&#8217;s path of growth hasn&#8217;t always been smooth sailing; there have been valleys along the way. But one thing must be acknowledged: its corporate positioning over the past 50 years has remained almost completely unchanged&#8212;to create powerful tools for individuals and society. Even in the latest wave of AI, where Apple seems to have lost the first-mover advantage, as the core player connecting people to the digital world in that &#8220;last centimeter,&#8221; it still holds the capital to remain at the center of the table in the AI era. After all, we live in a physical world, and we need tangible hardware and personalized services to truly enjoy the fruits of technological progress.</p><p>Apple at 50 might offer an inspiration to other companies: rather than imitating its &#8220;cool&#8221; and &#8220;innovative&#8221; exterior, it is better to learn from its focus and persistence. Becoming a long-term companion to its users is perhaps the true secret to its success.</p><p>In all likelihood, ten years from now, when Apple turns 60 and I turn 61, I will still be using a Mac.</p><p>Happy Birthday, Apple!</p><p><a href="https://fatbobman.com/en/weekly/issue-126/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2><strong>This Week&#8217;s Sponsor</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-boltai">Native AI chat app &#8212; ultra-fast, privacy-first, 100+ pro features</a></strong></h3><p>One native app, 100+ AI models on Mac, iOS, and Android. Fast, keyboard-driven, no Electron. 25% off for a limited time with code <code>FATBOBMAN25</code>.</p><p><strong><a href="https://l.fatbobman.com/sb-boltai">&#9889;&#65039; Get BoltAI &#8212; 25% off -&gt;</a></strong></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/why-i-am-still-thinking-about-core-data-in-2026/?utm_source=fatbobman%20weekly%20issue%20127&amp;utm_medium=web">Why I&#8217;m Still Thinking About Core Data in 2026</a></strong></h3><p>By 2026, Core Data has been around for 21 years. While many developers still use it, in modern Swift projects it increasingly feels like a relic of an earlier era. Concurrency still relies on layers of <code>perform</code> calls, model declarations are filled with boilerplate, and string-based predicates are always ready to trip you up. This article is not a defense of Core Data, nor an attempt to persuade new developers to adopt it. Instead, it&#8217;s more of a problem inventory: why do some developers still choose to stick with Core Data in 2026, and if we continue using it, what are the real issues we need to address today?</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0127-01">Fortify Your App: Essential Strategies to Strengthen Security Q&amp;A</a></strong></h3><p>During a security-focused event hosted by Apple&#8217;s Developer Center, several Apple engineers spent nearly six hours discussing application security and memory safety, covering topics such as modern security challenges and the defensive technologies available across Apple platforms. <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a> compiled and organized a large portion of the developer Q&amp;A from the session. The discussion touches on topics such as evaluating the security of third-party libraries, risks when storing data with UserDefaults or plist files, best practices for Keychain and file protection, the safe use of Swift <code>unsafe</code> APIs, and enabling Enhanced Security capabilities in Xcode. For developers interested in understanding Apple&#8217;s platform security model and practical recommendations, this is a dense and valuable collection of insights, many of them coming directly from Apple engineers.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-02">Faster iOS Subscriptions with ASC CLI and RevenueCat MCP</a></strong></h3><p>Adding subscription support to an app isn&#8217;t particularly difficult, but configuring everything across both App Store Connect and RevenueCat can be surprisingly tedious. <a href="https://x.com/rudrank">Rudrank Riyam</a> introduces a more efficient approach: using the <a href="https://github.com/rudrankriyam/App-Store-Connect-CLI">ASC CLI</a> to create App Store Connect subscription products directly from the terminal, and then letting an AI agent configure the corresponding entitlements, offerings, and paywalls through RevenueCat&#8217;s MCP Server. This workflow effectively moves the entire setup process from manual dashboard interactions into a CLI + AI agent automation pipeline.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-03">JetBrains Swift Developers Survey</a></strong></h3><p>JetBrains recently released a survey aimed at Swift developers, inviting them to share the tools they use, their development workflows, and the pain points they encounter in the Swift ecosystem. Although JetBrains has not explained the specific purpose of the survey, the community has already started to speculate that it may be related to a renewed evaluation of Swift development tooling support.</p><p>After JetBrains discontinued AppCode in 2022, most Swift developers returned to an Xcode-centric toolchain. This new survey has sparked some discussion: some developers hope JetBrains might revisit Swift tooling, while others suspect the effort could be more closely related to Kotlin Multiplatform or Swift build tooling. If you&#8217;re interested in the future direction of Swift development tools, you might want to take part in the survey.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-04">How Well Can You Detect a Swift Protocol Without the Compiler?</a></strong></h3><p>Protocols are everywhere in Swift projects, but how reliably can you determine whether a Swift file defines or references a protocol without compiling the project or resolving its dependencies? In this article, <a href="https://x.com/budo_coder">Xiangyu Sun</a> evaluates a variety of detection strategies, including SourceKit/LSP queries, SwiftSyntax AST parsing, simple keyword regex matching, and heuristic signals such as <code>extension Foo: Bar</code> or the <code>any</code>/<code>some</code> prefixes. Each method is analyzed in terms of accuracy and applicability.</p><p>One particularly interesting finding is that <strong>simple naming conventions can dramatically improve static analysis accuracy</strong>. If a team consistently uses a <code>*Protocol</code> suffix for protocol types (for example, <code>PaymentServiceProtocol</code>), many otherwise ambiguous heuristics become far more reliable. The author also explores how this convention can benefit AI-assisted development workflows: by pre-classifying protocol files before sending code to an LLM, it becomes possible to reduce token usage and improve analysis efficiency &#8212; an insightful perspective for teams experimenting with AI-driven tooling.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-05">What you should know before Migrating from GCD to Swift Concurrency</a></strong></h3><p>Migrating from GCD to Swift Concurrency is not merely a matter of replacing syntax. In this article, <a href="https://x.com/soumya_mahunt">Soumya Ranjan Mahunt</a> highlights several important differences between the two concurrency models. Swift Concurrency differs from GCD in task scheduling, execution ordering, and concurrency semantics &#8212; differences that can introduce subtle data races or difficult-to-reproduce runtime issues during migration if not properly considered.</p><p>For example, <code>Task</code> scheduling does not guarantee the same FIFO execution order as GCD, and <code>actor</code> should not be viewed as a direct replacement for <code>DispatchQueue</code>, since task priorities and scheduling strategies can influence execution behavior. The article also discusses practical migration pitfalls, such as the lack of a direct equivalent to <code>DispatchGroup</code> in Swift Concurrency, and compatibility issues that may arise when using <code>assumeIsolated</code> on older system versions.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-06">A 9-Step Framework for Choosing the Right Agent Skill</a></strong></h3><p>As AI agents become increasingly integrated into development workflows, designing the right &#8220;skills&#8221; (tools or capabilities) for those agents is emerging as a new engineering challenge. <a href="https://x.com/twannl">Antoine van der Lee</a> proposes a nine-step framework to help determine when it actually makes sense to implement a dedicated agent skill.</p><p>As Antoine points out, not every task should be delegated directly to an LLM, and not every capability needs to become an agent tool. The framework evaluates factors such as task determinism, execution cost, reusability, and security considerations, providing a structured way to reason about when and how to extend an AI agent&#8217;s capabilities.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a></strong></h3><p>This is a particularly interesting open-source project developed by <a href="https://www.asymbas.com/">Anferne Pineda</a>. It leverages SwiftData&#8217;s custom store capability to re-implement a SQLite-backed persistence engine while preserving SwiftData&#8217;s higher-level developer experience. The project maps SwiftData models, predicates, and queries to SQLite schemas, SQL execution, snapshots, and persistent history management.</p><p>DataStoreKit also introduces several noteworthy capabilities. For example, it supports predicate queries on collection types such as arrays and dictionaries by mapping them to JSON structures stored in SQLite. It also exposes a SQL passthrough layer, allowing developers to bypass <code>#Predicate</code> when necessary and directly execute SQLite queries or maintenance operations.</p><p>This is one of the few projects that explores SwiftData&#8217;s <code>DataStore</code> extensibility at significant depth, demonstrating how SwiftData can function as a data abstraction layer rather than a complete persistence engine. The project is still in an early stage and its APIs and capabilities may evolve, but it is already well worth watching.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-08">Playwright for Swift</a></strong></h3><p>Developed by <a href="https://x.com/m1guelpf">Miguel Piedrafita</a>, <code>swift-playwright</code> brings the mature browser automation capabilities of <a href="https://playwright.dev/">Playwright</a> into the Swift ecosystem. Developers can control Chromium, Firefox, and WebKit directly from Swift code to perform tasks such as page navigation, clicking, form input, screenshots, and JavaScript execution. The API design also closely mirrors the official Playwright interface.</p><p>Under the hood, the project does not re-implement a browser automation framework. Instead, it wraps the Playwright protocol on the Swift side while continuing to communicate with browsers through the Node.js Playwright driver. For developers interested in building testing tools, CLI utilities, or even AI agents using Swift, this project offers a compelling entry point.</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-127?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-127?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>50 &#23681;&#30340;&#33529;&#26524;&#21644; 51 &#23681;&#30340;&#25105;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-127/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20877;&#26377;&#19981;&#21040;&#21322;&#20010;&#26376;&#65292;Apple &#23558;&#36814;&#26469; 50 &#23681;&#29983;&#26085;&#12290;Tim Cook &#20063;&#21457;&#34920;&#20102;<a href="https://www.apple.com/50-years-of-thinking-different/">&#19968;&#31687;&#30701;&#25991;</a>&#65292;&#33268;&#25964;&#36807;&#21435;&#21322;&#20010;&#19990;&#32426;&#30340;&#21382;&#31243;&#12290;&#19981;&#36807;&#65292;&#30001;&#20110;&#33529;&#26524;&#19968;&#30452;&#20197;&#26469;&#22987;&#32456;&#24341;&#39046;&#28526;&#27969;&#30340;&#24418;&#35937;&#65292;&#24456;&#22810;&#20154;&#24182;&#27809;&#26377;&#24847;&#35782;&#21040;&#23427;&#24050;&#32463;&#26159; IT &#20135;&#19994;&#20013;&#21517;&#21103;&#20854;&#23454;&#30340;&#20803;&#32769;&#12290;&#19982;&#23427;&#24180;&#40836;&#30456;&#24403;&#30340; IT &#24040;&#22836;&#65292;&#22914;&#20170;&#20173;&#30041;&#22312;&#19968;&#32447;&#29260;&#26700;&#19978;&#30340;&#23525;&#23525;&#26080;&#20960;&#12290;</p><p>&#20316;&#20026;&#19968;&#20010;&#21482;&#27604;&#33529;&#26524;&#22823;&#19968;&#23681;&#30340;&#31185;&#25216;&#29233;&#22909;&#32773;&#65292;&#20174; Apple II &#21040;&#22914;&#20170;&#30340; iPhone&#12289;MacBook&#65292;&#33529;&#26524;&#30340;&#20135;&#21697;&#20960;&#20046;&#20276;&#38543;&#25105;&#36208;&#36807;&#20102;&#22823;&#21322;&#20154;&#29983;&#12290;&#20005;&#26684;&#26469;&#35828;&#65292;&#25105;&#24182;&#19981;&#31639;&#30495;&#27491;&#30340;&#26524;&#31881;&#8212;&#8212;&#19981;&#20250;&#22240;&#20026;&#27809;&#33021;&#31532;&#19968;&#26102;&#38388;&#20080;&#21040;&#26032;&#21697;&#32780;&#36951;&#25022;&#65292;&#20063;&#20960;&#20046;&#19981;&#20877;&#29100;&#22812;&#30475;&#21457;&#24067;&#20250;&#65292;&#26356;&#35828;&#19981;&#20986;&#26032;&#20135;&#21697;&#30340;&#20855;&#20307;&#21442;&#25968;&#12290;&#20294;&#22238;&#39038;&#36807;&#21435;&#65292;&#22312;&#27599;&#19968;&#20010;&#20154;&#29983;&#33410;&#28857;&#19978;&#65292;&#25105;&#37117;&#20250;&#24456;&#33258;&#28982;&#22320;&#36873;&#25321;&#33529;&#26524;&#30340;&#20135;&#21697;&#65292;&#24182;&#22312;&#36817;&#20960;&#24180;&#25104;&#20026;&#20102;&#33529;&#26524;&#24320;&#21457;&#29983;&#24577;&#20013;&#30340;&#19968;&#21592;&#12290;</p><p>&#20854;&#23454;&#25105;&#20063;&#27809;&#26377;&#23436;&#20840;&#24819;&#26126;&#30333;&#65292;&#33529;&#26524;&#23545;&#25105;&#25345;&#20037;&#30340;&#21560;&#24341;&#21147;&#31350;&#31455;&#26469;&#33258;&#21738;&#37324;&#12290;&#26159;&#22240;&#20026;&#24456;&#26089;&#23601;&#24320;&#22987;&#20351;&#29992;&#23427;&#30340;&#20135;&#21697;&#65311;&#26159;&#23427;&#30340;&#21019;&#26032;&#12289;&#20307;&#39564;&#21644;&#27668;&#36136;&#65311;&#36824;&#26159; Jobs &#30340;&#20154;&#26684;&#39749;&#21147;&#65311;&#35828;&#23454;&#35805;&#65292;&#22914;&#20170;&#30340;&#36873;&#25321;&#24050;&#32463;&#23436;&#20840;&#20986;&#20110;&#20064;&#24815;&#21644;&#26412;&#33021;&#65292;&#23601;&#20687;&#32769;&#21451;&#38388;&#30340;&#40664;&#22865;&#65292;&#26089;&#24050;&#19981;&#38656;&#35201;&#20160;&#20040;&#29305;&#21035;&#30340;&#29702;&#30001;&#12290;</p><p>&#24403;&#28982;&#65292;&#33529;&#26524;&#30340;&#25104;&#38271;&#20043;&#36335;&#24182;&#38750;&#19968;&#24070;&#39118;&#39034;&#65292;&#20854;&#38388;&#20063;&#26377;&#36807;&#20302;&#35895;&#12290;&#20294;&#26377;&#19968;&#28857;&#24517;&#39035;&#25215;&#35748;&#65306;&#23427;&#22312;&#36807;&#21435; 50 &#24180;&#38388;&#30340;&#20225;&#19994;&#23450;&#20301;&#20960;&#20046;&#27809;&#21464;&#8212;&#8212;&#20026;&#20010;&#20154;&#21644;&#31038;&#20250;&#21019;&#36896;&#24378;&#22823;&#30340;&#24037;&#20855;&#12290;&#21363;&#20415;&#22312;&#26368;&#26032;&#19968;&#36718; AI &#28010;&#28526;&#20013;&#65292;&#33529;&#26524;&#30475;&#20284;&#22833;&#21435;&#20102;&#20808;&#26426;&#65292;&#20294;&#20316;&#20026;&#36830;&#25509;&#20154;&#19982;&#25968;&#23383;&#19990;&#30028;&#30340;&#8220;&#26368;&#21518;&#19968;&#21400;&#31859;&#8221;&#30340;&#26680;&#24515;&#21442;&#19982;&#32773;&#65292;&#23427;&#20173;&#28982;&#20855;&#22791;&#22312; AI &#26102;&#20195;&#30041;&#22312;&#29260;&#26700;&#20013;&#22830;&#30340;&#36164;&#26412;&#12290;&#27605;&#31455;&#65292;&#25105;&#20204;&#29983;&#27963;&#22312;&#29289;&#36136;&#19990;&#30028;&#20013;&#65292;&#38656;&#35201;&#23454;&#25171;&#23454;&#30340;&#30828;&#20214;&#35774;&#22791;&#21644;&#20010;&#20154;&#21270;&#26381;&#21153;&#26469;&#20139;&#21463;&#25216;&#26415;&#36827;&#27493;&#30340;&#25104;&#26524;&#12290;</p><p>50 &#23681;&#30340;&#33529;&#26524;&#25110;&#35768;&#33021;&#32473;&#26356;&#22810;&#20225;&#19994;&#24102;&#26469;&#21551;&#31034;&#65306;&#19982;&#20854;&#27169;&#20223;&#23427;&#8220;&#28843;&#37239;&#8221;&#12289;&#8220;&#21019;&#26032;&#8221;&#30340;&#22806;&#34920;&#65292;&#19981;&#22914;&#23398;&#20064;&#23427;&#30340;&#19987;&#27880;&#19982;&#22362;&#25345;&#12290;&#25104;&#20026;&#19982;&#29992;&#25143;&#38271;&#20037;&#20114;&#30456;&#38506;&#20276;&#30340;&#20249;&#20276;&#65292;&#25110;&#35768;&#25165;&#26159;&#23427;&#25104;&#21151;&#30340;&#30495;&#27491;&#23494;&#30721;&#12290;</p><p>&#22823;&#27010;&#29575;&#20877;&#36807;&#21313;&#24180;&#65292;&#24403;&#33529;&#26524; 60 &#23681;&#12289;&#25105; 61 &#23681;&#30340;&#26102;&#20505;&#65292;&#25105;&#20173;&#28982;&#29992;&#30528;&#19968;&#21488;&#33529;&#26524;&#30005;&#33041;&#12290;</p><p>&#29983;&#26085;&#24555;&#20048;&#65292;&#33529;&#26524;&#65281;</p><p><a href="https://fatbobman.com/zh/weekly/issue-126/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div><hr></div><h2><strong>&#26412;&#26399;&#36190;&#21161;</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-boltai">&#21407;&#29983; AI &#32842;&#22825;&#24212;&#29992; &#8212; &#26497;&#36895;&#12289;&#38544;&#31169;&#20248;&#20808;&#12289;100+ &#19987;&#19994;&#21151;&#33021;</a></strong></h3><p>&#19968;&#20010;&#21407;&#29983;&#24212;&#29992;&#65292;100+ AI &#27169;&#22411;&#65292;&#25903;&#25345; Mac&#12289;iOS &#21644; Android&#12290;&#26497;&#36895;&#21709;&#24212;&#12289;&#38190;&#30424;&#39537;&#21160;&#12289;&#38750; Electron&#12290;&#38480;&#26102;&#20248;&#24800;&#65292;&#20351;&#29992;&#30721; <code>FATBOBMAN25</code> &#31435;&#20139; 75 &#25240;&#12290;</p><p><strong><a href="https://l.fatbobman.com/sb-boltai">&#9889;&#65039; &#33719;&#21462; BoltAI &#8212; 75 &#25240;&#20248;&#24800;  -&gt;</a></strong></p><div><hr></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/why-i-am-still-thinking-about-core-data-in-2026/?utm_source=fatbobman%20weekly%20issue%20127&amp;utm_medium=web">2026 &#24180;&#65292;&#20026;&#20160;&#20040;&#25105;&#20173;&#22312;&#24605;&#32771; Core Data</a></strong></h3><p>&#21040; 2026 &#24180;&#65292;Core Data &#24050;&#32463;&#38382;&#19990; 21 &#24180;&#65292;&#23613;&#31649;&#20173;&#26377;&#19981;&#23569;&#24320;&#21457;&#32773;&#22312;&#20351;&#29992;&#23427;&#65292;&#20294;&#22312;&#20170;&#22825;&#30340; Swift &#39033;&#30446;&#37324;&#65292;&#23427;&#36234;&#26469;&#36234;&#20687;&#20010;&#8220;&#26102;&#20195;&#36951;&#30041;&#8221;&#12290;&#24182;&#21457;&#24471;&#38752; <code>perform</code> &#19968;&#23618;&#23618;&#22871;&#65292;&#27169;&#22411;&#22768;&#26126;&#22534;&#28385;&#26679;&#26495;&#20195;&#30721;&#65292;&#23383;&#31526;&#20018;&#35859;&#35789;&#38543;&#26102;&#31561;&#20320;&#36393;&#22353;&#12290;&#36825;&#31687;&#25991;&#31456;&#19981;&#26159;&#35201;&#20026; Core Data &#36777;&#25252;&#65292;&#20063;&#19981;&#26159;&#35201;&#35828;&#26381;&#26032;&#30340;&#24320;&#21457;&#32773;&#22238;&#21040; Core Data&#12290;&#23427;&#26356;&#20687;&#26159;&#19968;&#31687;&#38382;&#39064;&#25972;&#29702;&#65306;&#22312; 2026 &#24180;&#65292;&#20026;&#20160;&#20040;&#20173;&#26377;&#20154;&#22362;&#25345;&#20351;&#29992; Core Data&#65307;&#32780;&#22914;&#26524;&#35201;&#32487;&#32493;&#20351;&#29992;&#23427;&#65292;&#25105;&#20204;&#20170;&#22825;&#30495;&#27491;&#38656;&#35201;&#35299;&#20915;&#30340;&#38382;&#39064;&#21448;&#26159;&#20160;&#20040;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0127-01">&#33529;&#26524;&#24037;&#31243;&#24072;&#35848;&#24212;&#29992;&#23433;&#20840;&#19982;&#20869;&#23384;&#20445;&#25252; (Fortify Your App: Essential Strategies to Strengthen Security Q&amp;A)</a></strong></h3><p>&#22312;&#33529;&#26524;&#24320;&#21457;&#32773;&#20013;&#24515;&#20030;&#21150;&#30340;&#19968;&#22330;&#23433;&#20840;&#19987;&#39064;&#27963;&#21160;&#20013;&#65292;&#22810;&#20301;&#33529;&#26524;&#24037;&#31243;&#24072;&#22260;&#32469;&#24212;&#29992;&#23433;&#20840;&#19982;&#20869;&#23384;&#23433;&#20840;&#36827;&#34892;&#20102;&#36817;&#20845;&#23567;&#26102;&#30340;&#20998;&#20139;&#19982;&#38382;&#31572;&#65292;&#20869;&#23481;&#28085;&#30422;&#29616;&#20195;&#24212;&#29992;&#38754;&#20020;&#30340;&#23433;&#20840;&#25361;&#25112;&#65292;&#20197;&#21450; Apple &#24179;&#21488;&#25552;&#20379;&#30340;&#19968;&#31995;&#21015;&#38450;&#25252;&#25216;&#26415;&#12290;<a href="https://x.com/AntonGubarenko">Anton Gubarenko</a> &#23558;&#36825;&#22330;&#27963;&#21160;&#20013;&#30340;&#22823;&#37327;&#24320;&#21457;&#32773;&#38382;&#31572;&#25972;&#29702;&#25104;&#25991;&#65292;&#35752;&#35770;&#20102;&#31532;&#19977;&#26041;&#24211;&#23433;&#20840;&#35780;&#20272;&#12289;UserDefaults &#19982; plist &#25968;&#25454;&#23384;&#20648;&#30340;&#39118;&#38505;&#12289;Keychain &#19982;&#25991;&#20214;&#20445;&#25252;&#31574;&#30053;&#12289;Swift <code>unsafe</code> API &#30340;&#20351;&#29992;&#36793;&#30028;&#65292;&#20197;&#21450;&#22914;&#20309;&#22312; Xcode &#20013;&#21551;&#29992; Enhanced Security &#31561;&#33021;&#21147;&#12290;&#23545;&#20110;&#24076;&#26395;&#20102;&#35299; Apple &#24179;&#21488;&#23433;&#20840;&#26426;&#21046;&#19982;&#23454;&#36341;&#24314;&#35758;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20221;&#20449;&#24687;&#23494;&#24230;&#24456;&#39640;&#30340;&#38382;&#31572;&#25972;&#29702;&#65292;&#20854;&#20013;&#21253;&#21547;&#19981;&#23569;&#26469;&#33258;&#33529;&#26524;&#24037;&#31243;&#24072;&#30340;&#19968;&#25163;&#20449;&#24687;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-02">&#29992; CLI &#19982; MCP &#33258;&#21160;&#21270;&#37197;&#32622; iOS &#35746;&#38405; (Faster iOS Subscriptions with ASC CLI and RevenueCat MCP)</a></strong></h3><p>&#20026;&#24212;&#29992;&#28155;&#21152;&#35746;&#38405;&#21151;&#33021;&#26412;&#36523;&#24182;&#19981;&#22797;&#26434;&#65292;&#20294;&#22312; App Store Connect &#19982; RevenueCat &#20004;&#20010;&#21518;&#21488;&#20043;&#38388;&#26469;&#22238;&#37197;&#32622;&#65292;&#36807;&#31243;&#24448;&#24448;&#30456;&#24403;&#32321;&#29712;&#12290;<a href="https://x.com/rudrank">Rudrank Riyam</a> &#20171;&#32461;&#20102;&#19968;&#31181;&#26356;&#39640;&#25928;&#30340;&#20570;&#27861;&#65306;&#20351;&#29992; <a href="https://github.com/rudrankriyam/App-Store-Connect-CLI">ASC CLI</a> &#22312;&#32456;&#31471;&#20013;&#19968;&#27425;&#24615;&#21019;&#24314;&#35746;&#38405;&#20135;&#21697;&#65292;&#20877;&#35753; AI &#20195;&#29702;&#36890;&#36807; RevenueCat &#30340; MCP Server &#33258;&#21160;&#23436;&#25104; entitlements&#12289;offerings &#19982; paywall &#30340;&#37197;&#32622;&#65292;&#20174;&#32780;&#23558;&#21407;&#26412;&#20381;&#36182;&#25511;&#21046;&#21488;&#28857;&#20987;&#30340;&#27969;&#31243;&#36801;&#31227;&#21040; CLI + AI Agent &#30340;&#33258;&#21160;&#21270;&#24037;&#20316;&#27969;&#20013;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-03">JetBrains &#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#35843;&#26597; (JetBrains Swift Developers Survey)</a></strong></h3><p>JetBrains &#26368;&#36817;&#21457;&#24067;&#20102;&#19968;&#20221;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#35843;&#30740;&#38382;&#21367;&#65292;&#36992;&#35831;&#24320;&#21457;&#32773;&#20998;&#20139;&#24403;&#21069;&#20351;&#29992;&#30340;&#24320;&#21457;&#24037;&#20855;&#12289;&#24037;&#20316;&#27969;&#31243;&#20197;&#21450;&#22312; Swift &#29983;&#24577;&#20013;&#30340;&#30171;&#28857;&#12290;&#23613;&#31649;&#23448;&#26041;&#24182;&#26410;&#35828;&#26126;&#35843;&#30740;&#30340;&#20855;&#20307;&#29992;&#36884;&#65292;&#20294;&#31038;&#21306;&#20013;&#24050;&#32463;&#20986;&#29616;&#19981;&#23569;<a href="https://www.reddit.com/r/Jetbrains/comments/1rr6wto/jetbrains_might_be_considering_bringing_back/">&#29468;&#27979;</a>&#65306;&#36825;&#39033;&#35843;&#26597;&#21487;&#33021;&#19982; JetBrains &#37325;&#26032;&#35780;&#20272; Swift &#24320;&#21457;&#24037;&#20855;&#25903;&#25345;&#26377;&#20851;&#12290;</p><p>&#22312; JetBrains &#20110; 2022 &#24180;&#23459;&#24067;&#20572;&#27490;&#32500;&#25252; AppCode &#20043;&#21518;&#65292;Swift &#24320;&#21457;&#32773;&#22522;&#26412;&#22238;&#21040;&#20102;&#20197; Xcode &#20026;&#26680;&#24515;&#30340;&#24037;&#20855;&#38142;&#12290;&#27492;&#27425;&#35843;&#30740;&#20063;&#24341;&#21457;&#20102;&#19968;&#20123;&#35752;&#35770;&#8212;&#8212;&#26377;&#20154;&#26399;&#24453; JetBrains &#37325;&#26032;&#25506;&#32034; Swift tooling &#30340;&#21487;&#33021;&#24615;&#65292;&#20063;&#26377;&#20154;&#35748;&#20026;&#36825;&#26356;&#21487;&#33021;&#19982; Kotlin Multiplatform &#25110; Swift &#26500;&#24314;&#24037;&#20855;&#38142;&#30456;&#20851;&#12290;&#22914;&#26524;&#20320;&#23545; Swift &#24320;&#21457;&#24037;&#20855;&#29983;&#24577;&#30340;&#26410;&#26469;&#26041;&#21521;&#24863;&#20852;&#36259;&#65292;&#19981;&#22952;&#21442;&#19982;&#36825;&#20221;&#35843;&#26597;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-04">&#19981;&#20381;&#36182;&#32534;&#35793;&#22120;&#35782;&#21035; Swift Protocol &#30340;&#26041;&#27861; (How Well Can You Detect a Swift Protocol Without the Compiler?)</a></strong></h3><p>&#22312; Swift &#39033;&#30446;&#20013;&#65292;Protocol &#20960;&#20046;&#26080;&#22788;&#19981;&#22312;&#65292;&#20294;&#22914;&#26524;&#19981;&#20381;&#36182;&#32534;&#35793;&#22120;&#25110;&#23436;&#25972;&#26500;&#24314;&#29615;&#22659;&#65292;&#20165;&#36890;&#36807;&#28304;&#30721;&#25991;&#26412;&#21028;&#26029;&#19968;&#20010;&#25991;&#20214;&#26159;&#21542;&#23450;&#20041;&#25110;&#20351;&#29992;&#20102;&#21327;&#35758;&#65292;&#32467;&#26524;&#20250;&#26377;&#22810;&#21487;&#38752;&#65311;<a href="https://x.com/budo_coder">Xiangyu Sun</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#31995;&#32479;&#35780;&#20272;&#20102;&#22810;&#31181;&#26816;&#27979;&#31574;&#30053;&#65292;&#20363;&#22914;&#20351;&#29992; SourceKit/LSP&#12289;SwiftSyntax AST&#12289;&#20851;&#38190;&#23383;&#27491;&#21017;&#21305;&#37197;&#65292;&#20197;&#21450;&#36890;&#36807; <code>extension Foo: Bar</code>&#12289;<code>any</code> / <code>some</code> &#31561;&#35821;&#27861;&#20449;&#21495;&#36827;&#34892;&#21551;&#21457;&#24335;&#21028;&#26029;&#65292;&#24182;&#23545;&#36825;&#20123;&#26041;&#27861;&#30340;&#20934;&#30830;&#29575;&#19982;&#36866;&#29992;&#22330;&#26223;&#36827;&#34892;&#20102;&#27604;&#36739;&#12290;</p><p>&#25991;&#31456;&#26368;&#26377;&#24847;&#24605;&#30340;&#37096;&#20998;&#22312;&#20110;&#20316;&#32773;&#21457;&#29616;&#65306;<strong>&#31616;&#21333;&#30340;&#21629;&#21517;&#32422;&#23450;&#21487;&#20197;&#26174;&#33879;&#25552;&#21319;&#38745;&#24577;&#20998;&#26512;&#25928;&#26524;</strong>&#12290;&#22914;&#26524;&#22242;&#38431;&#32479;&#19968;&#20351;&#29992; <code>*Protocol</code> &#21518;&#32512;&#21629;&#21517;&#21327;&#35758;&#31867;&#22411;&#65288;&#22914; <code>PaymentServiceProtocol</code>&#65289;&#65292;&#24456;&#22810;&#21407;&#26412;&#23384;&#22312;&#27495;&#20041;&#30340;&#26816;&#27979;&#26041;&#27861;&#37117;&#20250;&#21464;&#24471;&#26356;&#21152;&#21487;&#38752;&#12290;&#20316;&#32773;&#36824;&#36827;&#19968;&#27493;&#35752;&#35770;&#20102;&#36825;&#31181;&#32422;&#23450;&#22312; AI &#36741;&#21161;&#24320;&#21457;&#20013;&#30340;&#20215;&#20540;&#65306;&#36890;&#36807;&#22312;&#25991;&#20214;&#32423;&#21035;&#39044;&#20998;&#31867;&#21327;&#35758;&#25991;&#20214;&#65292;&#21487;&#20197;&#22312;&#21521; LLM &#25552;&#20379;&#19978;&#19979;&#25991;&#26102;&#26174;&#33879;&#20943;&#23569; token &#28040;&#32791;&#65292;&#24182;&#25552;&#39640;&#20998;&#26512;&#25928;&#29575;&#65292;&#36825;&#26159;&#19968;&#20010;&#39047;&#20855;&#21551;&#21457;&#24615;&#30340;&#35270;&#35282;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-05">&#36801;&#31227;&#21040; Swift Concurrency &#21069;&#38656;&#35201;&#27880;&#24847;&#30340;&#32454;&#33410; (What you should know before Migrating from GCD to Swift Concurrency)</a></strong></h3><p>&#20174; GCD &#36801;&#31227;&#21040; Swift Concurrency &#24182;&#38750;&#31616;&#21333;&#30340;&#35821;&#27861;&#26367;&#25442;&#12290;&#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;<a href="https://x.com/soumya_mahunt">Soumya Ranjan Mahunt</a> &#25351;&#20986;&#65306;Swift Concurrency &#22312;&#20219;&#21153;&#35843;&#24230;&#12289;&#25191;&#34892;&#39034;&#24207;&#20197;&#21450;&#24182;&#21457;&#35821;&#20041;&#19978;&#19982; GCD &#23384;&#22312;&#19968;&#20123;&#20851;&#38190;&#24046;&#24322;&#65292;&#20363;&#22914; <code>Task</code> &#30340;&#35843;&#24230;&#24182;&#19981;&#20445;&#35777;&#19982; GCD &#30456;&#21516;&#30340; FIFO &#25191;&#34892;&#39034;&#24207;&#65292;&#32780; <code>actor</code> &#20063;&#24182;&#19981;&#26159; <code>DispatchQueue</code> &#30340;&#30452;&#25509;&#26367;&#20195;&#65292;&#20854;&#25191;&#34892;&#34892;&#20026;&#21487;&#33021;&#21463;&#21040;&#20219;&#21153;&#20248;&#20808;&#32423;&#21644;&#35843;&#24230;&#31574;&#30053;&#30340;&#24433;&#21709;&#12290;&#27492;&#22806;&#65292;&#25991;&#20013;&#36824;&#35752;&#35770;&#20102;&#19968;&#20123;&#22312;&#23454;&#38469;&#36801;&#31227;&#36807;&#31243;&#20013;&#23481;&#26131;&#34987;&#24573;&#35270;&#30340;&#38382;&#39064;&#65292;&#20363;&#22914; <code>DispatchGroup</code> &#22312; Swift Concurrency &#20013;&#24182;&#27809;&#26377;&#23436;&#20840;&#31561;&#20215;&#30340; API&#65292;&#20197;&#21450;&#22312;&#26087;&#31995;&#32479;&#29256;&#26412;&#20013;&#20351;&#29992; <code>assumeIsolated</code> &#21487;&#33021;&#36935;&#21040;&#30340;&#20860;&#23481;&#24615;&#38382;&#39064;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-06">&#36873;&#25321; AI Agent Skill &#30340;&#20061;&#27493;&#26694;&#26550; (A 9-Step Framework for Choosing the Right Agent Skill)</a></strong></h3><p>&#38543;&#30528; AI Agent &#22312;&#24320;&#21457;&#24037;&#20316;&#27969;&#20013;&#30340;&#24212;&#29992;&#36234;&#26469;&#36234;&#24191;&#27867;&#65292;&#22914;&#20309;&#20026; Agent &#35774;&#35745;&#21512;&#36866;&#30340;&#8220;&#25216;&#33021;&#8221;&#65288;Skill / Tool&#65289;&#20063;&#36880;&#28176;&#25104;&#20026;&#19968;&#20010;&#26032;&#30340;&#24037;&#31243;&#38382;&#39064;&#12290;<a href="https://x.com/twannl">Antoine van der Lee</a> &#25552;&#20986;&#20102;&#19968;&#20010;&#29992;&#20110;&#21028;&#26029;&#20309;&#26102;&#24212;&#35813;&#20026; Agent &#21019;&#24314;&#25216;&#33021;&#30340;&#20061;&#27493;&#26694;&#26550;&#65292;&#24110;&#21161;&#24320;&#21457;&#32773;&#22312;&#33258;&#21160;&#21270;&#33021;&#21147;&#12289;&#21487;&#32500;&#25252;&#24615;&#20197;&#21450;&#31995;&#32479;&#22797;&#26434;&#24230;&#20043;&#38388;&#21462;&#24471;&#24179;&#34913;&#12290;Antoine &#25351;&#20986;&#65292;&#24182;&#38750;&#25152;&#26377;&#20219;&#21153;&#37117;&#36866;&#21512;&#30452;&#25509;&#20132;&#32473; LLM&#65292;&#20063;&#24182;&#38750;&#25152;&#26377;&#33021;&#21147;&#37117;&#38656;&#35201;&#23454;&#29616;&#20026; Agent &#24037;&#20855;&#12290;&#25991;&#31456;&#20174;&#20219;&#21153;&#30830;&#23450;&#24615;&#12289;&#25191;&#34892;&#25104;&#26412;&#12289;&#21487;&#22797;&#29992;&#24615;&#20197;&#21450;&#23433;&#20840;&#24615;&#31561;&#35282;&#24230;&#20986;&#21457;&#65292;&#25552;&#20379;&#20102;&#19968;&#22871;&#30456;&#23545;&#31995;&#32479;&#30340;&#35780;&#20272;&#24605;&#36335;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a></strong></h3><p>&#36825;&#26159;&#19968;&#20010;&#24456;&#26377;&#24847;&#24605;&#30340;&#24320;&#28304;&#39033;&#30446;&#65292;&#30001; <a href="https://www.asymbas.com/">Anferne Pineda</a> &#24320;&#21457;&#12290;&#23427;&#22522;&#20110; SwiftData &#30340;&#33258;&#23450;&#20041; store &#33021;&#21147;&#65292;&#22312;&#20445;&#30041; SwiftData &#19978;&#23618;&#24320;&#21457;&#20307;&#39564;&#30340;&#21516;&#26102;&#65292;&#37325;&#26032;&#23454;&#29616;&#20102;&#19968;&#22871;&#38754;&#21521; SQLite &#30340;&#24213;&#23618;&#23384;&#20648;&#21518;&#31471;&#65292;&#21253;&#25324;&#20174; SwiftData &#27169;&#22411;&#12289;&#35859;&#35789;&#21040; SQLite schema&#12289;SQL&#12289;&#24555;&#29031;&#19982;&#25345;&#20037;&#21270;&#21382;&#21490;&#30340;&#26144;&#23556;&#21644;&#25191;&#34892;&#12290;</p><p>DataStoreKit &#25552;&#20379;&#20102;&#19968;&#20123;&#20540;&#24471;&#20851;&#27880;&#30340;&#29305;&#24615;&#65292;&#20363;&#22914;&#25903;&#25345;&#23545;&#25968;&#32452;&#12289;&#23383;&#20856;&#31561;&#38598;&#21512;&#31867;&#22411;&#25968;&#25454;&#36827;&#34892;&#35859;&#35789;&#26597;&#35810;&#65292;&#24213;&#23618;&#20197; JSON &#24418;&#24335;&#26144;&#23556;&#21040; SQLite&#65307;&#21516;&#26102;&#20063;&#25552;&#20379;&#20102; SQL &#30452;&#36890;&#33021;&#21147;&#65292;&#35753;&#24320;&#21457;&#32773;&#22312; <code>#Predicate</code> &#20043;&#22806;&#65292;&#33021;&#22815;&#30452;&#25509;&#21033;&#29992; SQLite &#30340;&#33021;&#21147;&#23436;&#25104;&#26597;&#35810;&#25110;&#32500;&#25252;&#25805;&#20316;&#12290;</p><p>&#36825;&#26159;&#30446;&#21069;&#20026;&#25968;&#19981;&#22810;&#12289;&#19988;&#23454;&#29616;&#28145;&#24230;&#36739;&#39640;&#30340; SwiftData <code>DataStore</code> &#33258;&#23450;&#20041;&#23454;&#36341;&#65292;&#23637;&#31034;&#20102; SwiftData &#20316;&#20026;&#25968;&#25454;&#34920;&#29616;&#23618;&#32780;&#38750;&#23436;&#25972;&#25345;&#20037;&#21270;&#24341;&#25806;&#30340;&#21478;&#19968;&#31181;&#21487;&#33021;&#24615;&#12290;&#39033;&#30446;&#30446;&#21069;&#20173;&#22788;&#20110;&#36739;&#26089;&#26399;&#38454;&#27573;&#65292;API &#21644;&#33021;&#21147;&#36793;&#30028;&#21487;&#33021;&#36824;&#20250;&#32487;&#32493;&#35843;&#25972;&#65292;&#20294;&#24050;&#32463;&#38750;&#24120;&#20540;&#24471;&#25345;&#32493;&#20851;&#27880;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0127-08">Playwright for Swift</a></strong></h3><p><a href="https://x.com/m1guelpf">Miguel Piedrafita</a> &#24320;&#21457;&#30340; <code>swift-playwright</code>&#65292;&#23558; <a href="https://playwright.dev/">Playwright</a> &#36825;&#22871;&#25104;&#29087;&#30340;&#27983;&#35272;&#22120;&#33258;&#21160;&#21270;&#33021;&#21147;&#24102;&#20837;&#20102; Swift &#29983;&#24577;&#12290;&#24320;&#21457;&#32773;&#21487;&#20197;&#30452;&#25509;&#20351;&#29992; Swift &#20195;&#30721;&#39537;&#21160; Chromium&#12289;Firefox &#21644; WebKit&#65292;&#23436;&#25104;&#39029;&#38754;&#23548;&#33322;&#12289;&#28857;&#20987;&#12289;&#36755;&#20837;&#12289;&#25130;&#22270;&#12289;&#25191;&#34892; JavaScript &#31561;&#24120;&#35265;&#25805;&#20316;&#65292;&#25972;&#20307; API &#39118;&#26684;&#20063;&#23613;&#37327;&#36148;&#36817;&#23448;&#26041; Playwright&#12290;</p><p>&#20174;&#23454;&#29616;&#26041;&#24335;&#19978;&#30475;&#65292;&#23427;&#24182;&#19981;&#26159;&#37325;&#26032;&#23454;&#29616;&#19968;&#22871;&#27983;&#35272;&#22120;&#33258;&#21160;&#21270;&#26694;&#26550;&#65292;&#32780;&#26159;&#22312; Swift &#20391;&#23553;&#35013;&#20102; Playwright &#21327;&#35758;&#65292;&#24213;&#23618;&#20381;&#28982;&#36890;&#36807; Node.js &#30340; Playwright driver &#19982;&#27983;&#35272;&#22120;&#36890;&#20449;&#12290;&#23545;&#20110;&#24076;&#26395;&#20351;&#29992; Swift &#26500;&#24314;&#27979;&#35797;&#24037;&#20855;&#12289;CLI&#65292;&#29978;&#33267; AI Agent &#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#20010;&#39033;&#30446;&#25552;&#20379;&#20102;&#19968;&#20010;&#39047;&#20855;&#21560;&#24341;&#21147;&#30340;&#20999;&#20837;&#28857;&#12290;</p><h2><strong>&#27963;&#21160;</strong></h2><h3><strong><a href="https://letsvision.swiftgg.team/?utm_source=fatbobman%20weekly%20issue%20127&amp;utm_medium=web">LET&#8217;S VISION 2026 -- Born to Create &#183; Powered by AI</a></strong></h3><ul><li><p>&#128064; 70+ &#23637;&#21830;&#29616;&#22330;&#20307;&#39564;</p></li><li><p>&#129302; AI &#21019;&#26032;&#20135;&#21697; / AI Agent</p></li><li><p>&#129405; XR / &#31354;&#38388;&#35745;&#31639;&#27785;&#28024;&#20307;&#39564;</p></li><li><p>&#127908; &#21019;&#20316;&#32773;&#19982;&#24320;&#21457;&#32773;&#20998;&#20139;</p></li></ul><p>&#22914;&#26524;&#20320;&#26159;&#24320;&#21457;&#32773;&#12289;&#35774;&#35745;&#24072;&#12289;&#20135;&#21697;&#32463;&#29702;&#12289;&#21019;&#20316;&#32773;&#65292;&#36824;&#26159;&#23545; AI &#21644;&#26410;&#26469;&#31185;&#25216;&#24863;&#20852;&#36259;&#30340;&#25506;&#32034;&#32773;&#65292;&#37117;&#24456;&#20540;&#24471;&#26469;&#36891;&#36891;&#12290;</p><ul><li><p>&#128197; 2026.3.28 &#8211; 3.29</p></li><li><p>&#128205; &#19978;&#28023; &#183; &#28437;&#27827;&#27902;&#20250;&#35758;&#20013;&#24515;</p></li></ul><p><a href="https://l.fatbobman.com/w0127-09">&#20843;&#20116;&#25240;&#38376;&#31080;&#33719;&#21462;&#20837;&#21475; &#128071;</a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YCtR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YCtR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 424w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 848w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 1272w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YCtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png" width="450" height="450" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:450,&quot;width&quot;:450,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;qrcode_www.huodongxing.com&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="qrcode_www.huodongxing.com" title="qrcode_www.huodongxing.com" srcset="https://substackcdn.com/image/fetch/$s_!YCtR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 424w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 848w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 1272w, https://substackcdn.com/image/fetch/$s_!YCtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6633fc4-2fbf-4fb7-90c2-3b45b05022a9_450x450.png 1456w" sizes="100vw" loading="lazy"></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"><svg role="img" 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"><g><title></title><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"><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"><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>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #126]]></title><description><![CDATA[MacBook Neo: The Starting Point of Apple's Return to Campus]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-125-cbb</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-125-cbb</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 09 Mar 2026 12:02:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!wHjK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.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_!wHjK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wHjK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wHjK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg" width="1456" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:137839,&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/190343271?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.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_!wHjK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wHjK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70bbc569-fc5c-4f62-a3c2-3689a1c62e12_1600x764.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"><svg role="img" 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"><g><title></title><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"><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"><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>MacBook Neo: The Starting Point of Apple&#8217;s Return to Campus</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-126/">Read on web &#8594;</a></p><p>Last week, Apple launched several new hardware products. Unlike previous launch events, this release was unusually low-key. Initially, I was only interested in the newly announced monitor, but after seeing numerous tech media outlets criticizing the MacBook Neo&#8217;s specs, I couldn&#8217;t help but pay closer attention to it. Looking past the superficial &#8220;downgrades&#8221;, I saw Apple&#8217;s clear determination to return to the education market through its precise pricing strategy. </p><p>Over a decade ago, Apple was a dominant player in the education hardware market. A significant portion of students who grew up using Apple devices on campus naturally transitioned into long-term consumers of Apple&#8217;s hardware and software after entering the workforce. However, as Google continuously ramped up its investments in Chromebooks and Apple lacked a price-competitive alternative, this K-12-centric market was gradually taken over by competitors (Chromebooks once captured nearly 60% of the U.S. K-12 education market). This not only cost Apple a portion of its revenue but, more importantly, weakened the brand affinity it had established among teenagers surrounding desktop and laptop computing forms. Compared to tablets, laptops still hold distinct advantages in teaching experience, use cases, durability, and centralized IT management.</p><p>In today&#8217;s service-first era, hardware is deeply intertwined with ecosystems. Chromebooks have long cultivated a massive cohort of young users accustomed to using Google Docs. As these users grow older and accumulate data, even if they eventually have the purchasing power to buy Apple devices, it becomes incredibly difficult to deeply lock them into Apple&#8217;s service ecosystem, let alone cultivate true brand loyalty.</p><p>The precise pricing of the Neo changes this dynamic. A starting price of $599 and an education discount of $499 give more children the opportunity to start using Apple devices and owning an Apple ID in school, thereby following Apple&#8217;s &#8220;predetermined path&#8221; to gradually purchase more products and services. As for the widely criticized &#8220;downgraded specs&#8221;&#8212;the A18 Pro chip is more than sufficient for daily K-12 scenarios. It isn&#8217;t lacking in performance; this is exactly where it is meant to be positioned. Apple traded a mobile chip for aggressive pricing headroom&#8212;a very shrewd calculation.</p><p>The subscription-based Apple Creator Studio also demonstrates Apple&#8217;s ambition to build long-term relationships with a broader audience within its ecosystem. For schools, cheap hardware combined with a powerful creative software suite forms a perfect closed loop. The MacBook Neo&#8217;s hardware performance may not be top-tier, but it is enough to provide a stable, usable experience over a typical 4- to 5-year device lifecycle, allowing users to gradually assimilate into Apple&#8217;s service system. From this perspective, the MacBook Neo acts more like an &#8220;ecosystem anchor&#8221; tossed by Apple to Gen Z and Gen Alpha.</p><p>Too many consumers and tech reviewers focus entirely on whether Apple&#8217;s products are cool or innovative, forgetting Apple&#8217;s roots&#8212;the education hardware market is deeply embedded in its DNA. Its success today stems from decades of past accumulation, and now it needs to fill the void left over the past dozen years. For the readers of this newsletter, the Neo is highly unlikely to be your cup of tea. But that doesn&#8217;t prevent it from being a highly targeted and ambitious product&#8212;one that isn&#8217;t designed to make a quick buck, but rather serves as Apple&#8217;s long-term bet on its ecosystem landscape for the next two decades.</p><p><a href="https://fatbobman.com/en/weekly/issue-125/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2><strong>This Week&#8217;s Sponsor</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-notepad">Notepad.exe &#8212; Your First Stop for Swift Experiments</a></strong></h3><p>New Swift 6 syntax to try? Xcode is too heavy, Playground too slow. Notepad.exe gets you from idea to running code in 30 seconds &#8212; no project setup. Multi-toolchain support, simulator integration, just open and code.</p><p><a href="https://l.fatbobman.com/sb-notepad">&#128640; Download for macOS &#8594;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/sendable-nsmanagedobjectcontext/?utm_source=fatbobman%20weekly%20issue%20126&amp;utm_medium=web">Why Does Passing NSManagedObjectContext Across Isolation Domains No Longer Error in Swift 6.2? The Real Change Isn&#8217;t in the Compiler</a></strong></h3><p>When a piece of concurrency-related code fails to compile in older versions of Xcode but compiles successfully in the latest Xcode 26 (Swift 6.2), what would be your first guess? Many developers might initially assume that Swift&#8217;s concurrency analysis&#8212;such as Region-Based Isolation&#8212;has evolved again. But the reality is not that simple. In this article, I document a rather interesting debugging journey I recently encountered: starting from a failing test, constructing a minimal reproducible example, and tracing the issue all the way down to the Core Data SDK interface. Eventually, I discovered that the key change was not entirely in the Swift compiler itself, but in how the framework is imported. In the new SDK, <code>NSManagedObjectContext</code> is now annotated with macros like <code>NS_SWIFT_SENDABLE</code>, giving it <code>Sendable</code> semantics in Swift.</p><blockquote><p>Although SwiftData is the most important persistence framework for the future of the Apple ecosystem, Core Data&#8212;the foundation beneath it&#8212;has not been neglected by Apple. Over the past few years, Apple has been quietly improving its compatibility and concurrency behavior in Swift 6, which is a very encouraging sign.</p></blockquote><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0126-01">What&#8217;s new in Swift: February 2026 Edition</a></strong></h3><p><a href="https://bsky.app/profile/karenchu.online">Karen Chu</a> and <a href="https://bsky.app/profile/davelester.dev">Dave Lester</a> compiled the latest developments in the Swift ecosystem for February 2026 on the official blog. The post not only highlights Swift&#8217;s strong presence at <a href="https://swiftlang.github.io/event-fosdem/">FOSDEM</a>&#8212;the world&#8217;s largest open source conference&#8212;but also showcases several notable open-source updates and Swift Evolution proposals. Among them, <a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0506-advanced-observation-tracking.md">SE-0506</a> particularly caught my attention. The proposal introduces an Options parameter to <code>withObservationTracking</code>, allowing developers to precisely control whether they observe changes before mutation (<code>willSet</code>), after mutation (<code>didSet</code>), or even lifecycle events such as <code>deinit</code>. Additionally, <code>withContinuousObservationTracking</code> enables stable, automatic continuous observation without the need to manually re-register observers recursively.</p><blockquote><p>The acceptance of SE-0506 is significant. It not only completes the timing control and continuity capabilities of state observation, but also marks the maturity of Swift&#8217;s native Observation system. It is no longer merely a companion feature for SwiftUI, but has evolved into a robust foundation capable of supporting industrial-grade, high-performance state-flow scheduling across Swift applications.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-09">macOS Input Method Development Guidelines for 2026</a></strong></h3><p>Based on years of experience developing macOS input methods, <a href="https://x.com/shikisuen">ShikiSuen</a>, the author of the <a href="https://vchewing.github.io/README.html">vChewing Input Method</a>, provides a comprehensive overview of the historical baggage of InputMethodKit (IMK) and the various issues it exposes under Swift 6&#8217;s strict concurrency checks. The article explores challenges such as NSConnection naming conventions, sandbox requirements, MainActor isolation conflicts, ARC congestion caused by frequent language switching (CapsLock), and even NSWindow memory leaks under the macOS 26 Liquid Glass mechanism. Rather than simply criticizing these legacy frameworks, the author proposes a set of engineering practices that resemble a &#8220;risk-control model&#8221;: reducing controllers to simple forwarding layers, moving business logic into weak-referenced sessions, using self-checking memory guards, and avoiding IMKCandidates entirely.</p><blockquote><p>Notably, ShikiSuen implemented these ideas in an open-source library called <a href="https://github.com/vChewing/IMKSwift">IMKSwift</a>. It provides an <code>@MainActor</code>-isolated <code>IMKInputSessionController</code> base class designed for Swift 6+, covering many concurrency pitfalls in the original <code>IMKInputController</code>. If you are developing macOS desktop applications or input methods, this library allows you to write type-safe, modern Swift code without manual hacks or data-race warnings.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-03">SwiftUI, Swift Effects: A Beautiful Onion Architecture</a></strong></h3><p>Handling data loading states in SwiftUI is something almost every application has to deal with. The common states&#8212;<code>loading</code>, <code>loaded</code>, and <code>failed</code>&#8212;are often intertwined with side effects such as network requests, caching, and logging, which can quickly make view code messy. In this article, <a href="https://www.linkedin.com/in/salgara/">Salgara</a> proposes an approach inspired by Onion Architecture. By combining ViewState with Effect Handlers, side effects such as <code>Fetch</code>, caching, and logging are separated into composable layers. AsyncSequence and injectable Effect Handlers then drive state transitions, allowing the UI to render purely based on state. In this design, the view layer remains clean while data and side effects flow through a clearly structured &#8220;effect pipeline.&#8221; The architecture also provides strong testability&#8212;tests can intercept effects and simulate data sources to validate state transitions.</p><blockquote><p>Salgara openly acknowledges that this architecture is still experimental: prototype-first, and treating everything as a view (Everything as a View). As more developers explore architectures that better align with SwiftUI&#8217;s design philosophy, such experiments may not only benefit SwiftUI itself but also enrich the broader landscape of declarative programming rather than merely replicating patterns from other UI frameworks.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-04">Spec-Driven Development: After AI Starts Writing Code</a></strong></h3><p>With the growing adoption of AI coding agents such as Cursor and Claude Code, developers are facing a new challenge: when AI can generate thousands of lines of code across dozens of files in minutes, how can humans effectively review it? And how should we deal with issues like context decay and hallucinations as conversations grow longer? A new development paradigm is emerging in response: <strong>Spec-Driven Development (SDD)</strong>. In this model, developers no longer focus primarily on writing code directly. Instead, they define clear specifications (Specs), and AI generates implementations based on those specifications.</p><p><a href="https://x.com/rbbtsn0w">Snow</a> explores this idea through a four-part series. Starting with the limitations of &#8220;Vibe Coding,&#8221; the articles outline a specification-centered development workflow and examine the evolving role of specifications in future software engineering. In this vision, code may no longer be the center of a project&#8212;it may simply become a byproduct of well-defined specifications.</p><blockquote><p>As AI increasingly handles implementation details, the center of software engineering may shift from &#8220;writing code&#8221; to &#8220;expressing intent.&#8221; SDD attempts to establish a strong layer of constraints between human ambiguity and AI&#8217;s indiscriminate code generation.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-05">Building a Mini Linker for SwiftUI Previews</a></strong></h3><p>Among the many tools provided by mcpbridge in Xcode 26.3, <code>RenderPreview</code> can directly return screenshots of SwiftUI previews, making them easier for AI to analyze. For developers who cannot yet use Xcode 26.3 mcpbridge, the approach and accompanying tools introduced by <a href="https://hachyderm.io/@IronHam">Hesham Salman</a> offer a similar capability. The technical highlight lies in using SwiftSyntax to construct a declaration dependency graph, then applying BFS to determine the minimal set of source files required by a given preview. This avoids the need to compile the entire App target, significantly reducing build time.</p><blockquote><p>The real value of this article lies in its approach: using SwiftSyntax + BFS to quickly identify the code segments required by a preview. In the past, SwiftSyntax had a relatively high barrier to entry, but in the age of AI-assisted development it is increasingly becoming foundational infrastructure for understanding code structure. Even if you are not as experienced with SwiftSyntax as Hesham Salman, once you understand its basic capabilities you can leverage AI to implement similar ideas&#8212;tools that previously were often built only by developers deeply familiar with compiler tooling.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-06">Swift at scale: building the TelemetryDeck analytics service</a></strong></h3><p>When discussing Swift on Server, many people still focus on a simple question: can it be used in production? TelemetryDeck provides a more concrete answer&#8212;not only can it be used, it is already powering an analytics service that processes data from over 16 million users each month. In this article, <a href="https://social.telemetrydeck.com/@daniel">Daniel Jilg</a> explains why the team chose Swift + Vapor for their backend stack and shares valuable lessons from operating a production system. These include using <code>Codable</code> to simplify API encoding and validation, keeping DTOs close to controllers, and recognizing that seemingly mundane practices&#8212;like cache TTLs, API versioning, and monitoring&#8212;often become the true moat in large-scale production systems.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-07">Get Rid of Your SwiftGen Dependency</a></strong></h3><p>For many years, developers relied on tools like SwiftGen to solve a longstanding issue in Apple&#8217;s resource system: resource access was stringly typed. Whether it was localization keys, image names, or color assets, typos often went unnoticed until runtime. <a href="https://www.linkedin.com/in/asserusama/">Asser Osama</a> points out that with the introduction and maturation of <strong>String Catalogs (.xcstrings)</strong> and <strong>Asset Catalog Symbols</strong>, Xcode can now automatically generate resource symbols during compilation. For many modern projects, this built-in capability may already replace the need for SwiftGen.</p><blockquote><p>It is worth noting that removing the dependency assumes your project runs entirely within the standard Xcode ecosystem. Resource symbol generation is an internal feature of the Xcode build system rather than a capability of the Swift compiler or Swift Package Manager. For teams using non-standard build systems such as Bazel or Buck, SwiftGen may still remain the more portable and controllable option.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0126-08">SwiftUI Agent Skill</a></strong></h3><p>Written by <a href="https://x.com/twostraws">Paul Hudson</a>, this SwiftUI Agent Skill aims to help developers produce smarter, simpler, and more modern SwiftUI code. The project gained over 1k stars within just two days of release.</p><blockquote><p>Over the past few weeks, this newsletter has recommended several skills created by well-known developers. While these skills encapsulate the authors&#8217; experience, I still don&#8217;t recommend using them blindly. At the very least, read them thoroughly before adopting them. A skill is essentially a condensed form of insights accumulated across dozens or even hundreds of articles. Only by understanding the underlying design ideas&#8212;and adapting them to your own development habits and project needs&#8212;can you truly unlock their value.</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-125-cbb?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-125-cbb?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Macbook Neo&#65306;&#33529;&#26524;&#37325;&#22238;&#26657;&#22253;&#30340;&#36215;&#28857;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-126/">&#32593;&#39029;&#29256;</a></strong></p><p>&#19978;&#21608;&#65292;&#33529;&#26524;&#25512;&#20986;&#20102;&#33509;&#24178;&#26032;&#27454;&#30828;&#20214;&#20135;&#21697;&#12290;&#19982;&#20197;&#24448;&#30340;&#21457;&#24067;&#20250;&#19981;&#21516;&#65292;&#36825;&#27425;&#21457;&#24067;&#26174;&#24471;&#24322;&#24120;&#20302;&#35843;&#12290;&#36215;&#21021;&#25105;&#21482;&#23545;&#20854;&#20013;&#26032;&#21457;&#24067;&#30340;&#26174;&#31034;&#22120;&#24863;&#20852;&#36259;&#65292;&#20294;&#22312;&#30475;&#21040;&#19981;&#23569;&#25968;&#30721;&#23186;&#20307;&#23545; Macbook Neo &#37197;&#32622;&#30340;&#21520;&#27133;&#21518;&#65292;&#20063;&#19981;&#30001;&#24471;&#22810;&#30041;&#24847;&#20102;&#36825;&#27454;&#20135;&#21697;&#12290;&#30456;&#36739;&#20110;&#20854;&#8220;&#20943;&#37197;&#8221;&#30340;&#34920;&#35937;&#65292;&#25105;&#26356;&#20174;&#20854;&#31934;&#20934;&#30340;&#23450;&#20215;&#20013;&#30475;&#21040;&#20102;&#33529;&#26524;&#37325;&#36820;&#25945;&#32946;&#24066;&#22330;&#30340;&#20915;&#24515;&#12290;</p><p>&#21313;&#20960;&#24180;&#21069;&#65292;&#33529;&#26524;&#36824;&#26366;&#26159;&#25945;&#32946;&#30828;&#20214;&#24066;&#22330;&#30340;&#37325;&#35201;&#21442;&#19982;&#32773;&#12290;&#37027;&#20123;&#22312;&#26657;&#22253;&#20013;&#20351;&#29992;&#33529;&#26524;&#35774;&#22791;&#25104;&#38271;&#36215;&#26469;&#30340;&#23398;&#29983;&#65292;&#20063;&#26377;&#30456;&#24403;&#19968;&#37096;&#20998;&#22312;&#36827;&#20837;&#31038;&#20250;&#21518;&#39034;&#29702;&#25104;&#31456;&#22320;&#25104;&#20026;&#33529;&#26524;&#36719;&#30828;&#20214;&#30340;&#38271;&#26399;&#28040;&#36153;&#32773;&#12290;&#20294;&#38543;&#30528;&#35895;&#27468;&#25345;&#32493;&#21152;&#22823;&#22312; Chromebook &#19978;&#30340;&#25237;&#20837;&#65292;&#32780;&#33529;&#26524;&#21448;&#32570;&#20047;&#26356;&#20855;&#20215;&#26684;&#31454;&#20105;&#21147;&#30340;&#20135;&#21697;&#65292;&#36825;&#19968;&#20197; K12 &#20026;&#26680;&#24515;&#30340;&#24066;&#22330;&#36880;&#28176;&#34987;&#23545;&#25163;&#21344;&#25454;&#65288;Chromebook &#26366;&#19968;&#24230;&#25343;&#19979;&#32654;&#22269;&#22522;&#30784;&#25945;&#32946;&#24066;&#22330;&#36817; 60% &#30340;&#20221;&#39069;&#65289;&#12290;&#36825;&#19981;&#20165;&#35753;&#33529;&#26524;&#25439;&#22833;&#20102;&#19968;&#37096;&#20998;&#25910;&#20837;&#65292;&#26356;&#37325;&#35201;&#30340;&#26159;&#21066;&#24369;&#20102;&#20854;&#22312;&#38738;&#23569;&#24180;&#32676;&#20307;&#20013;&#12289;&#22260;&#32469;&#21488;&#24335;&#26426;&#19982;&#31508;&#35760;&#26412;&#36825;&#31181;&#35745;&#31639;&#24418;&#24577;&#25152;&#24314;&#31435;&#30340;&#21697;&#29260;&#20146;&#21644;&#21147;&#12290;&#30456;&#27604;&#24179;&#26495;&#35774;&#22791;&#65292;&#31508;&#35760;&#26412;&#22312;&#25945;&#23398;&#20307;&#39564;&#12289;&#36866;&#29992;&#22330;&#26223;&#12289;&#32784;&#29992;&#24615;&#20197;&#21450; IT &#38598;&#20013;&#31649;&#29702;&#31561;&#26041;&#38754;&#20381;&#28982;&#20855;&#26377;&#26126;&#26174;&#20248;&#21183;&#12290;</p><p>&#22312;&#26381;&#21153;&#20248;&#20808;&#30340;&#20170;&#22825;&#65292;&#30828;&#20214;&#24448;&#24448;&#19982;&#29983;&#24577;&#28145;&#24230;&#32465;&#23450;&#12290;Chromebook &#26089;&#26089;&#22521;&#20859;&#20986;&#19968;&#22823;&#25209;&#20064;&#24815;&#20351;&#29992; Google Docs &#30340;&#24180;&#36731;&#29992;&#25143;&#12290;&#38543;&#30528;&#24180;&#40836;&#22686;&#38271;&#19982;&#25968;&#25454;&#30340;&#31215;&#32047;&#65292;&#21363;&#20415;&#20182;&#20204;&#26085;&#21518;&#20855;&#22791;&#36141;&#20080;&#33529;&#26524;&#35774;&#22791;&#30340;&#33021;&#21147;&#65292;&#20063;&#24456;&#38590;&#20877;&#19982;&#33529;&#26524;&#30340;&#26381;&#21153;&#29983;&#24577;&#24418;&#25104;&#28145;&#24230;&#32465;&#23450;&#65292;&#26356;&#38590;&#24418;&#25104;&#30495;&#27491;&#30340;&#21697;&#29260;&#20449;&#20208;&#12290;</p><p>Neo &#31934;&#20934;&#30340;&#23450;&#20215;&#25913;&#21464;&#20102;&#36825;&#19968;&#23616;&#38754;&#12290;$599 &#30340;&#36215;&#21806;&#20215;&#12289;$499 &#30340;&#25945;&#32946;&#20248;&#24800;&#65292;&#35753;&#26356;&#22810;&#23401;&#23376;&#26377;&#26426;&#20250;&#22312;&#23398;&#26657;&#23601;&#24320;&#22987;&#20351;&#29992;&#33529;&#26524;&#35774;&#22791;&#12289;&#25317;&#26377; Apple ID&#65292;&#20174;&#32780;&#39034;&#30528;&#33529;&#26524;&#8220;&#39044;&#35774;&#8221;&#30340;&#36712;&#36857;&#65292;&#36880;&#27493;&#36141;&#20080;&#26356;&#22810;&#20135;&#21697;&#19982;&#26381;&#21153;&#12290;&#33267;&#20110;&#34987;&#24191;&#27867;&#25209;&#35780;&#30340;&#8221;&#20943;&#37197;&#8221;&#8212;&#8212;A18 Pro &#33455;&#29255;&#23545; K12 &#26085;&#24120;&#20351;&#29992;&#22330;&#26223;&#32780;&#35328;&#23436;&#20840;&#36275;&#22815;&#65292;&#23427;&#32570;&#30340;&#19981;&#26159;&#24615;&#33021;&#65292;&#32780;&#26159;&#23450;&#20301;&#26412;&#23601;&#22914;&#27492;&#12290;&#33529;&#26524;&#29992;&#31227;&#21160;&#31471;&#33455;&#29255;&#25442;&#26469;&#20102;&#28608;&#36827;&#30340;&#23450;&#20215;&#31354;&#38388;&#65292;&#36825;&#26159;&#19968;&#31508;&#31639;&#24471;&#24456;&#28165;&#26970;&#30340;&#36134;&#12290;</p><p>&#37319;&#29992;&#35746;&#38405;&#21046;&#30340; Apple Creator Studio&#65292;&#21516;&#26679;&#23637;&#29616;&#20102;&#33529;&#26524;&#24076;&#26395;&#35753;&#26356;&#22810;&#20154;&#19982;&#20854;&#29983;&#24577;&#24314;&#31435;&#38271;&#26399;&#32852;&#31995;&#30340;&#37326;&#24515;&#12290;&#23545;&#20110;&#23398;&#26657;&#32780;&#35328;&#65292;&#24265;&#20215;&#30828;&#20214;+&#24378;&#22823;&#30340;&#21019;&#20316;&#36719;&#20214;&#22871;&#20214;&#65292;&#26500;&#25104;&#20102;&#38381;&#29615;&#12290;Macbook Neo &#30340;&#30828;&#20214;&#24615;&#33021;&#25110;&#35768;&#19981;&#31639;&#24378;&#21170;&#65292;&#20294;&#36275;&#20197;&#22312;&#27599;&#21488;&#35774;&#22791;&#32422; 4&#8211;5 &#24180;&#30340;&#29983;&#21629;&#21608;&#26399;&#20013;&#25552;&#20379;&#31283;&#23450;&#12289;&#21487;&#29992;&#30340;&#20307;&#39564;&#65292;&#35753;&#20351;&#29992;&#32773;&#36880;&#27493;&#34701;&#20837;&#33529;&#26524;&#30340;&#26381;&#21153;&#20307;&#31995;&#12290;&#20174;&#36825;&#20010;&#35282;&#24230;&#26469;&#30475;&#65292;MacBook Neo &#26356;&#20687;&#26159;&#33529;&#26524;&#25243;&#21521; Z &#19990;&#20195;&#19982; Alpha &#19990;&#20195;&#30340;&#19968;&#26522;&#8220;&#29983;&#24577;&#38170;&#28857;&#8221;&#12290;</p><p>&#22826;&#22810;&#28040;&#36153;&#32773;&#21644;&#25968;&#30721;&#21338;&#20027;&#36807;&#20110;&#32858;&#28966;&#20110;&#33529;&#26524;&#20135;&#21697;&#26159;&#21542;&#28843;&#37239;&#12289;&#26159;&#21542;&#26377;&#21019;&#26032;&#65292;&#21364;&#24536;&#35760;&#20102;&#33529;&#26524;&#30340;&#26469;&#26102;&#36335;&#8212;&#8212;&#25945;&#32946;&#30828;&#20214;&#24066;&#22330;&#28145;&#26893;&#20110;&#23427;&#30340;&#22522;&#22240;&#20043;&#20013;&#65292;&#20170;&#22825;&#30340;&#25104;&#21151;&#28304;&#20110;&#25968;&#21313;&#24180;&#21069;&#30340;&#31215;&#32047;&#65292;&#32780;&#29616;&#22312;&#23427;&#38656;&#35201;&#34917;&#19978;&#26368;&#36817;&#21313;&#20960;&#24180;&#30340;&#31354;&#32570;&#12290;&#23545;&#20110;&#26412;&#21608;&#25253;&#30340;&#35835;&#32773;&#26469;&#35828;&#65292;Neo &#22823;&#27010;&#29575;&#19981;&#26159;&#20320;&#30340;&#33756;&#12290;&#20294;&#36825;&#24182;&#19981;&#22952;&#30861;&#23427;&#25104;&#20026;&#19968;&#27454;&#26497;&#20855;&#38024;&#23545;&#24615;&#12289;&#20063;&#39047;&#20855;&#37326;&#24515;&#30340;&#20135;&#21697;&#8212;&#8212;&#19981;&#26159;&#29992;&#26469;&#36186;&#24555;&#38065;&#30340;&#65292;&#32780;&#26159;&#33529;&#26524;&#20026;&#26410;&#26469;&#20108;&#21313;&#24180;&#30340;&#29983;&#24577;&#29256;&#22270;&#25152;&#20570;&#30340;&#19968;&#27425;&#38271;&#26399;&#25276;&#27880;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-125/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div><hr></div><h2><strong>&#26412;&#26399;&#36190;&#21161;</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-notepad">Notepad.exe &#8212; Swift &#26032;&#29305;&#24615;&#30340;&#31532;&#19968;&#20010;&#23454;&#39564;&#22330;</a></strong></h3><p>Swift 6 &#20986;&#20102;&#26032;&#35821;&#27861;&#65311;Xcode &#22826;&#37325;&#65292;Playground &#21448;&#22826;&#24930;&#12290;Notepad.exe &#35753;&#20320;&#22312; 30 &#31186;&#20869;&#20889;&#20195;&#30721;&#12289;&#36305;&#32467;&#26524;&#65292;&#19987;&#27880;&#39564;&#35777;&#24819;&#27861;&#26412;&#36523;&#12290;&#25903;&#25345;&#22810;&#29256;&#26412;&#24037;&#20855;&#38142;&#20999;&#25442;&#65292;&#38598;&#25104;&#27169;&#25311;&#22120;&#65292;&#38543;&#24320;&#38543;&#29992;&#12290;</p><p><a href="https://l.fatbobman.com/sb-notepad">&#128640; &#31435;&#21363;&#20351;&#29992; &#8594;</a></p><div><hr></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/sendable-nsmanagedobjectcontext/?utm_source=fatbobman%20weekly%20issue%20126&amp;utm_medium=web">&#36328;&#22495;&#20256;&#36882; NSManagedObjectContext &#20026;&#20160;&#20040;&#22312; Swift 6.2 &#20013;&#19981;&#20877;&#25253;&#38169;&#65311;&#30495;&#27491;&#30340;&#21464;&#21270;&#19981;&#22312;&#32534;&#35793;&#22120;</a></strong></h3><p>&#24403;&#21516;&#19968;&#27573;&#19982;&#24182;&#21457;&#26377;&#20851;&#30340;&#20195;&#30721;&#22312;&#26087;&#29256; Xcode &#20013;&#26080;&#27861;&#36890;&#36807;&#65292;&#21364;&#22312;&#26032;&#29256; Xcode 26&#65288;Swift 6.2&#65289;&#20013;&#39034;&#21033;&#32534;&#35793;&#26102;&#65292;&#20320;&#31532;&#19968;&#26102;&#38388;&#20250;&#24819;&#21040;&#20160;&#20040;&#65311;&#24456;&#22810;&#20154;&#26368;&#21021;&#30340;&#21028;&#26029;&#21487;&#33021;&#26159; Swift &#32534;&#35793;&#22120;&#30340;&#24182;&#21457;&#20998;&#26512;&#65288;&#22914; Region-Based Isolation&#65289;&#21448;&#36827;&#21270;&#20102;&#65292;&#20294;&#29616;&#23454;&#24182;&#27809;&#26377;&#36825;&#20040;&#31616;&#21333;&#12290;&#26412;&#25991;&#35760;&#24405;&#20102;&#25105;&#26368;&#36817;&#36935;&#21040;&#30340;&#19968;&#27425;&#38750;&#24120;&#26377;&#24847;&#24605;&#30340;&#25490;&#26597;&#36807;&#31243;&#65306;&#20174;&#27979;&#35797;&#22833;&#36133;&#20986;&#21457;&#65292;&#36890;&#36807;&#26500;&#24314;&#26368;&#23567;&#22797;&#29616;&#29992;&#20363;&#65292;&#19968;&#27493;&#27493;&#36861;&#28335;&#21040; Core Data &#30340; SDK interface&#65292;&#26368;&#32456;&#21457;&#29616;&#65292;&#38382;&#39064;&#30340;&#20851;&#38190;&#24182;&#19981;&#23436;&#20840;&#22312; Swift &#32534;&#35793;&#22120;&#26412;&#36523;&#65292;&#32780;&#26159;&#26694;&#26550;&#30340;&#23548;&#20837;&#35821;&#20041;&#21457;&#29983;&#20102;&#21464;&#21270;&#8212;&#8212;&#22312;&#26032;&#30340; SDK &#20013;&#65292;<code>NSManagedObjectContext</code> &#33719;&#24471;&#20102; <code>NS_SWIFT_SENDABLE</code> &#31561;&#23439;&#26631;&#27880;&#65292;&#20351;&#20854;&#22312; Swift &#20013;&#25317;&#26377;&#20102; <code>Sendable</code> &#35821;&#20041;&#12290;</p><blockquote><p>&#23613;&#31649; SwiftData &#26159;&#26410;&#26469;&#33529;&#26524;&#29983;&#24577;&#26368;&#37325;&#35201;&#30340;&#25345;&#20037;&#21270;&#26694;&#26550;&#65292;&#20294;&#20316;&#20026;&#20854;&#22522;&#30784;&#30340; Core Data &#24182;&#27809;&#26377;&#34987;&#33529;&#26524;&#20919;&#33853;&#12290;&#22312;&#36807;&#21435;&#20960;&#24180;&#20013;&#65292;&#33529;&#26524;&#19968;&#30452;&#22312;&#40664;&#40664;&#25913;&#21892;&#20854;&#22312; Swift 6 &#20013;&#30340;&#20860;&#23481;&#24615;&#21644;&#24182;&#21457;&#20307;&#39564;&#65292;&#36825;&#26159;&#19968;&#20010;&#24456;&#22909;&#30340;&#29616;&#35937;&#12290;</p></blockquote><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0126-01">Swift &#35821;&#35328; 2 &#26376;&#26032;&#21160;&#24577; (What&#8217;s new in Swift: February 2026 Edition)</a></strong></h3><p><a href="https://bsky.app/profile/karenchu.online">Karen Chu</a> &#21644; <a href="https://bsky.app/profile/davelester.dev">Dave Lester</a> &#22312;&#23448;&#26041;&#21338;&#23458;&#19978;&#25972;&#29702;&#20102; 2026 &#24180; 2 &#26376; Swift &#31038;&#21306;&#30340;&#29983;&#24577;&#21160;&#24577;&#12290;&#20869;&#23481;&#19981;&#20165;&#28085;&#30422;&#20102; Swift &#22312; <a href="https://swiftlang.github.io/event-fosdem/">FOSDEM</a>&#65288;&#20840;&#29699;&#26368;&#22823;&#24320;&#28304;&#20250;&#35758;&#65289;&#19978;&#30340;&#27963;&#36291;&#34920;&#29616;&#65292;&#36824;&#25512;&#20171;&#20102;&#22810;&#39033;&#37325;&#30917;&#30340;&#24320;&#28304;&#36827;&#23637;&#19982; Swift Evolution &#25552;&#26696;&#12290;&#20854;&#20013;&#30340; <a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0506-advanced-observation-tracking.md">SE-0506</a> &#23588;&#20026;&#35753;&#25105;&#24778;&#21916;&#12290;&#35813;&#25552;&#26696;&#20026; <code>withObservationTracking</code> &#22686;&#21152;&#20102; Options &#21442;&#25968;&#65292;&#24320;&#21457;&#32773;&#29616;&#22312;&#21487;&#20197;&#31934;&#30830;&#25511;&#21046;&#26159;&#35266;&#23519;&#21464;&#21270;&#21069;&#65288;willSet&#65289;&#12289;&#21464;&#21270;&#21518;&#65288;didSet&#65289;&#36824;&#26159;&#23545;&#35937;&#30340;&#29983;&#21629;&#21608;&#26399;&#65288;&#22914; deinit&#65289;&#12290;&#24182;&#19988;&#36890;&#36807; <code>withContinuousObservationTracking</code> &#26080;&#38656;&#20877;&#25163;&#21160;&#36882;&#24402;&#27880;&#20876;&#65292;&#21363;&#21487;&#23454;&#29616;&#31283;&#23450;&#12289;&#33258;&#21160;&#24490;&#29615;&#30340;&#36830;&#32493;&#20107;&#20214;&#36861;&#36394;&#12290;</p><blockquote><p>SE-0506 &#25552;&#26696;&#30340;&#36890;&#36807;&#24847;&#20041;&#37325;&#22823;&#12290;&#23427;&#19981;&#20165;&#23436;&#32654;&#34917;&#40784;&#20102;&#29366;&#24577;&#36861;&#36394;&#30340;&#26102;&#26426;&#25511;&#21046;&#21644;&#36830;&#32493;&#24615;&#33021;&#21147;&#65292;&#26356;&#26631;&#24535;&#30528; Swift &#21407;&#29983;&#30340; Observation &#24050;&#32463;&#24443;&#24213;&#25104;&#29087;&#8212;&#8212;&#23427;&#19981;&#20877;&#20165;&#20165;&#26159; SwiftUI &#30340;&#8220;&#19987;&#23646;&#38468;&#24248;&#8221;&#65292;&#32780;&#26159;&#30495;&#27491;&#34581;&#21464;&#20026;&#20102; Swift &#35821;&#35328;&#20013;&#36275;&#20197;&#24212;&#23545;&#21508;&#31181;&#24037;&#19994;&#32423;&#12289;&#39640;&#24615;&#33021;&#29366;&#24577;&#27969;&#35843;&#24230;&#30340;&#26680;&#24515;&#22522;&#30784;&#35774;&#26045;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-02">&#20889;&#22312; 2026 &#24180;&#30340; macOS &#36755;&#20837;&#27861;&#24320;&#21457;&#35268;&#33539;</a></strong></h3><p><a href="https://vchewing.github.io/README.html">vChewing &#32500;&#38899;&#36755;&#20837;&#27861;</a> &#30340;&#20316;&#32773; <a href="https://x.com/shikisuen">ShikiSuen</a> &#22522;&#20110;&#22810;&#24180;&#28145;&#32789; macOS &#36755;&#20837;&#27861;&#30340;&#24320;&#21457;&#32463;&#39564;&#65292;&#20840;&#38754;&#26803;&#29702;&#20102; InputMethodKit (IMK) &#30340;&#21382;&#21490;&#21253;&#34993;&#65292;&#20197;&#21450;&#23427;&#22312; Swift 6 &#20005;&#26684;&#24182;&#21457;&#26816;&#26597;&#19979;&#26292;&#38706;&#20986;&#30340;&#31181;&#31181;&#30171;&#28857;&#12290;&#25991;&#31456;&#28145;&#20837;&#25506;&#35752;&#20102; NSConnection &#30340;&#21629;&#21517;&#35268;&#33539;&#12289;&#21551;&#29992;&#27801;&#30418;&#30340;&#24517;&#35201;&#24615;&#12289;MainActor &#38548;&#31163;&#20914;&#31361;&#65292;&#20197;&#21450;&#39640;&#39057;&#20013;&#33521;&#20999;&#25442;&#65288;CapsLock&#65289;&#23548;&#33268;&#30340; ARC &#25317;&#22581;&#12289;macOS 26 Liquid Glass &#26426;&#21046;&#19979; NSWindow &#20869;&#23384;&#19981;&#37322;&#25918;&#31561;&#26840;&#25163;&#38382;&#39064;&#12290;&#38754;&#23545;&#33529;&#26524;&#8220;&#19978;&#21476;&#26694;&#26550;&#8221;&#19982;&#29616;&#20195; Swift &#24182;&#21457;&#27169;&#22411;&#30340;&#30896;&#25758;&#65292;&#20316;&#32773;&#27809;&#26377;&#20572;&#30041;&#22312;&#25265;&#24616;&#19978;&#65292;&#32780;&#26159;&#25552;&#20986;&#20102;&#19968;&#22871;&#20687;&#8220;&#39118;&#38505;&#25511;&#21046;&#27169;&#22411;&#8221;&#19968;&#26679;&#30340;&#24037;&#31243;&#35268;&#33539;&#8212;&#8212;&#23558;&#25511;&#21046;&#22120;&#36864;&#21270;&#20026;&#32431;&#36716;&#21457;&#23618;&#12289;&#25226;&#19994;&#21153;&#36923;&#36753;&#21093;&#31163;&#21040;&#24369;&#24341;&#29992; Session&#12289;&#20351;&#29992;&#20869;&#23384;&#33258;&#26597;&#33258;&#23613;&#12289;&#24443;&#24213;&#36991;&#24320; IMKCandidates &#31561;&#12290;</p><blockquote><p>&#21487;&#36149;&#30340;&#26159;&#65292;ShikiSuen &#22522;&#20110;&#19978;&#36848;&#24605;&#36335;&#24320;&#21457;&#24182;&#24320;&#28304;&#20102; <a href="https://github.com/vChewing/IMKSwift">IMKSwift</a> &#24211;&#12290;&#23427;&#20026; Swift 6+ &#25552;&#20379;&#20102; <code>@MainActor</code> &#23436;&#25972;&#38548;&#31163;&#30340; <code>IMKInputSessionController</code> &#22522;&#31867;&#65292;&#23436;&#32654;&#35206;&#30422;&#20102;&#21407;&#29983; <code>IMKInputController</code> &#30340;&#24182;&#21457;&#22320;&#38647;&#21306;&#12290;&#22914;&#26524;&#20320;&#38656;&#35201;&#24320;&#21457; macOS &#26700;&#38754;&#31471;&#24212;&#29992;&#25110;&#36755;&#20837;&#27861;&#65292;&#36825;&#20010;&#24211;&#33021;&#35753;&#20320;&#26080;&#38656;&#25163;&#21160; Hack&#65292;&#23601;&#33021;&#20889;&#20986;&#31867;&#22411;&#23433;&#20840;&#12289;&#26080; data-race &#35686;&#21578;&#30340;&#29616;&#20195;&#20195;&#30721;&#65292;&#38750;&#24120;&#20540;&#24471;&#23398;&#20064;&#19982;&#20351;&#29992;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-03">SwiftUI &#30340;&#27915;&#33905;&#24335;&#26550;&#26500;&#65306;Swift Effects &#23454;&#36341; (SwiftUI, Swift Effects: A Beautiful Onion Architecture)</a></strong></h3><p>&#22312; SwiftUI &#20013;&#22788;&#29702;&#25968;&#25454;&#21152;&#36733;&#29366;&#24577;&#20960;&#20046;&#26159;&#27599;&#20010;&#24212;&#29992;&#37117;&#20250;&#38754;&#23545;&#30340;&#38382;&#39064;&#65306;<code>loading</code>&#12289;<code>loaded</code>&#12289;<code>failed</code> &#19977;&#31181;&#29366;&#24577;&#24448;&#24448;&#20276;&#38543;&#30528;&#32593;&#32476;&#35831;&#27714;&#12289;&#32531;&#23384;&#12289;&#26085;&#24535;&#35760;&#24405;&#31561;&#21103;&#20316;&#29992;&#36923;&#36753;&#65292;&#24456;&#23481;&#26131;&#35753;&#35270;&#22270;&#20195;&#30721;&#36880;&#28176;&#21464;&#24471;&#33219;&#32959;&#12290;<a href="https://www.linkedin.com/in/salgara/">Salgara</a> &#22312;&#26412;&#25991;&#20013;&#25552;&#20986;&#20102;&#19968;&#31181;&#31867;&#20284; Onion Architecture &#30340;&#24605;&#36335;&#65306;&#36890;&#36807; ViewState + Effect Handlers &#23558; <code>Fetch</code>&#12289;&#32531;&#23384;&#12289;&#26085;&#24535;&#31561;&#21103;&#20316;&#29992;&#25286;&#20998;&#20026;&#22810;&#20010;&#21487;&#32452;&#21512;&#23618;&#32423;&#65292;&#24182;&#21033;&#29992; AsyncSequence &#19982;&#21487;&#27880;&#20837;&#30340; Effect Handler &#39537;&#21160;&#29366;&#24577;&#21464;&#21270;&#65292;&#20351; UI &#20165;&#26681;&#25454;&#29366;&#24577;&#36827;&#34892;&#28210;&#26579;&#12290;&#36825;&#26679;&#19968;&#26469;&#65292;&#35270;&#22270;&#20445;&#25345;&#32431;&#31929;&#65292;&#32780;&#25968;&#25454;&#33719;&#21462;&#19982;&#21103;&#20316;&#29992;&#21017;&#27839;&#30528;&#19968;&#26465;&#28165;&#26224;&#30340;&#8220;Effect &#31649;&#36947;&#8221;&#36880;&#23618;&#27969;&#21160;&#12290;&#21516;&#26102;&#65292;&#36825;&#31181;&#32467;&#26500;&#20063;&#22825;&#28982;&#20855;&#22791;&#33391;&#22909;&#30340;&#21487;&#27979;&#35797;&#24615;&#8212;&#8212;&#27979;&#35797;&#20195;&#30721;&#21487;&#20197;&#30452;&#25509;&#25318;&#25130;&#24182;&#27169;&#25311;&#25968;&#25454;&#28304;&#36820;&#22238;&#20540;&#65292;&#20174;&#32780;&#39564;&#35777;&#23436;&#25972;&#30340;&#29366;&#24577;&#36716;&#25442;&#27969;&#31243;&#12290;</p><blockquote><p>Salgara &#22374;&#35328;&#65292;&#36825;&#31181;&#26550;&#26500;&#30446;&#21069;&#20173;&#28982;&#26159;&#23454;&#39564;&#24615;&#30340;&#65306;&#21407;&#22411;&#20248;&#20808;&#65292;&#24182;&#23581;&#35797;&#23558;&#19968;&#20999;&#35270;&#20026;&#35270;&#22270;&#65288;Everything as a View&#65289;&#12290;&#38543;&#30528;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#20174;&#19981;&#21516;&#35282;&#24230;&#24605;&#32771;&#24182;&#23581;&#35797;&#26500;&#24314;&#26356;&#31526;&#21512; SwiftUI &#29305;&#24615;&#30340;&#26550;&#26500;&#65292;&#36825;&#31867;&#25506;&#32034;&#19981;&#20165;&#21487;&#33021;&#35753; SwiftUI &#26412;&#36523;&#21463;&#30410;&#65292;&#20063;&#26377;&#26426;&#20250;&#21453;&#36807;&#26469;&#20016;&#23500;&#25972;&#20010;&#22768;&#26126;&#24335;&#32534;&#31243;&#33539;&#24335;&#65292;&#32780;&#19981;&#20877;&#21482;&#26159;&#22797;&#21046;&#20854;&#20182; UI &#26694;&#26550;&#30340;&#26082;&#26377;&#23454;&#36341;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-04">Spec-Driven Development&#65306;&#24403; AI &#20889;&#20195;&#30721;&#20043;&#21518;</a></strong></h3><p>&#38543;&#30528; Cursor&#12289;Claude Code &#31561; AI &#32534;&#31243;&#26234;&#33021;&#20307;&#65288;Agent&#65289;&#30340;&#26222;&#21450;&#65292;&#24320;&#21457;&#32773;&#20204;&#27491;&#38754;&#20020;&#19968;&#20010;&#26032;&#30340;&#30171;&#28857;&#65306;&#24403; AI &#33021;&#22312;&#20960;&#20998;&#38047;&#20869;&#36328;&#36234;&#20960;&#21313;&#20010;&#25991;&#20214;&#29983;&#25104;&#19978;&#21315;&#34892;&#20195;&#30721;&#26102;&#65292;&#20154;&#31867;&#35813;&#22914;&#20309;&#26377;&#25928;&#23457;&#26597;&#65311;&#21448;&#35813;&#22914;&#20309;&#24212;&#23545; AI &#22312;&#38271;&#27969;&#31243;&#20013;&#36880;&#28176;&#20986;&#29616;&#30340;&#8220;&#19978;&#19979;&#25991;&#36951;&#24536;&#65288;Context Decay&#65289;&#8221;&#19982;&#24187;&#35273;&#38382;&#39064;&#65311;&#20026;&#27492;&#65292;&#19968;&#31181;&#26032;&#30340;&#24320;&#21457;&#33539;&#24335;&#27491;&#22312;&#36880;&#28176;&#25104;&#24418;&#65306;Spec-Driven Development&#65288;SDD&#65289;&#12290;&#22312;&#36825;&#19968;&#27169;&#24335;&#19979;&#65292;&#24320;&#21457;&#32773;&#30340;&#20027;&#35201;&#20219;&#21153;&#19981;&#20877;&#26159;&#30452;&#25509;&#32534;&#20889;&#20195;&#30721;&#65292;&#32780;&#26159;&#23450;&#20041;&#28165;&#26224;&#30340;&#35268;&#26684;&#65288;Spec&#65289;&#65292;&#20877;&#30001; AI &#26681;&#25454;&#36825;&#20123;&#35268;&#26684;&#29983;&#25104;&#23454;&#29616;&#12290;</p><p><a href="https://x.com/rbbtsn0w">Snow</a> &#36890;&#36807;&#22235;&#31687;&#25991;&#31456;&#31995;&#32479;&#26803;&#29702;&#20102;&#36825;&#19968;&#24605;&#36335;&#65306;&#20174; &#8220;Vibe Coding&#8221; &#30340;&#23616;&#38480;&#20986;&#21457;&#65292;&#20171;&#32461;&#20197;&#35268;&#26684;&#20026;&#26680;&#24515;&#30340;&#24320;&#21457;&#27969;&#31243;&#65292;&#24182;&#36827;&#19968;&#27493;&#25506;&#35752;&#35268;&#26684;&#22312;&#26410;&#26469;&#36719;&#20214;&#24037;&#31243;&#20013;&#30340;&#35282;&#33394;&#8212;&#8212;&#20195;&#30721;&#25110;&#35768;&#19981;&#20877;&#26159;&#39033;&#30446;&#30340;&#20013;&#24515;&#65292;&#32780;&#21482;&#26159;&#35268;&#26684;&#30340;&#34893;&#29983;&#29289;&#12290;</p><blockquote><p>&#22312; AI &#36880;&#28176;&#25215;&#25285;&#23454;&#29616;&#32454;&#33410;&#30340;&#26102;&#20195;&#65292;&#36719;&#20214;&#24037;&#31243;&#30340;&#37325;&#24515;&#25110;&#35768;&#27491;&#22312;&#20174;&#8220;&#20889;&#20195;&#30721;&#8221;&#36716;&#21521;&#8220;&#34920;&#36798;&#24847;&#22270;&#8221;&#12290;SDD &#23581;&#35797;&#22312;&#20154;&#31867;&#30340;&#27169;&#31946;&#24847;&#22270;&#19982; AI &#30340;&#26080;&#24046;&#21035;&#29983;&#25104;&#20043;&#38388;&#65292;&#24314;&#31435;&#19968;&#23618;&#24378;&#26377;&#21147;&#30340;&#32422;&#26463;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-05">&#20026; SwiftUI Preview &#26500;&#24314;&#19968;&#20010; Mini Linker (Building a Mini Linker for SwiftUI Previews)</a></strong></h3><p>&#22312; Xcode 26.3 &#30340; mcpbridge &#25552;&#20379;&#30340;&#20247;&#22810;&#24037;&#20855;&#20013;&#65292;<code>RenderPreview</code> &#21487;&#20197;&#30452;&#25509;&#36820;&#22238; SwiftUI Preview &#30340;&#25130;&#22270;&#65292;&#26041;&#20415; AI &#36827;&#34892;&#20998;&#26512;&#12290;&#23545;&#20110;&#26242;&#26102;&#26080;&#27861;&#20351;&#29992; Xcode 26.3 mcpbridge &#30340;&#24320;&#21457;&#32773;&#65292;<a href="https://hachyderm.io/@IronHam">Hesham Salman</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#30340;&#24605;&#36335;&#20197;&#21450;&#37197;&#22871;&#24037;&#20855;&#65292;&#21516;&#26679;&#21487;&#20197;&#23454;&#29616;&#31867;&#20284;&#30340;&#33021;&#21147;&#12290;&#20854;&#25216;&#26415;&#20142;&#28857;&#22312;&#20110;&#21033;&#29992; SwiftSyntax &#26500;&#24314;&#22768;&#26126;&#20381;&#36182;&#22270;&#65292;&#20877;&#36890;&#36807; BFS &#25214;&#20986;&#24403;&#21069; Preview &#30495;&#27491;&#38656;&#35201;&#30340;&#26368;&#23567;&#28304;&#25991;&#20214;&#38598;&#21512;&#65292;&#20174;&#32780;&#36991;&#20813;&#32534;&#35793;&#25972;&#20010; App Target &#24102;&#26469;&#30340;&#26500;&#24314;&#31561;&#24453;&#12290;</p><blockquote><p>&#26412;&#25991;&#30340;&#31934;&#21326;&#22312;&#20110;&#24605;&#36335;&#65306;&#21033;&#29992; SwiftSyntax + BFS &#24555;&#36895;&#23450;&#20301; Preview &#20381;&#36182;&#30340;&#20195;&#30721;&#29255;&#27573;&#12290;&#36807;&#21435; SwiftSyntax &#30340;&#20351;&#29992;&#38376;&#27099;&#36739;&#39640;&#65292;&#20294;&#22312; AI &#36741;&#21161;&#24320;&#21457;&#36880;&#28176;&#26222;&#21450;&#30340;&#20170;&#22825;&#65292;&#23427;&#27491;&#36880;&#28176;&#25104;&#20026;&#29702;&#35299;&#20195;&#30721;&#32467;&#26500;&#30340;&#37325;&#35201;&#22522;&#30784;&#35774;&#26045;&#12290;&#21363;&#20415;&#20320;&#19981;&#20687; Hesham Salman &#37027;&#26679;&#29087;&#32451;&#25484;&#25569;&#35813;&#24037;&#20855;&#65292;&#20102;&#35299;&#20854;&#22522;&#26412;&#33021;&#21147;&#21518;&#65292;&#20063;&#21487;&#20197;&#20511;&#21161; AI &#23558;&#31867;&#20284;&#24605;&#36335;&#33853;&#22320;&#8212;&#8212;&#32780;&#36825;&#31867;&#24037;&#20855;&#22312;&#36807;&#21435;&#24448;&#24448;&#21482;&#23646;&#20110;&#23569;&#25968;&#29087;&#24713;&#32534;&#35793;&#22120;&#24037;&#20855;&#38142;&#30340;&#24320;&#21457;&#32773;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-06">Swift &#30340;&#35268;&#27169;&#21270;&#23454;&#36341;&#65306;TelemetryDeck &#30340;&#20998;&#26512;&#26381;&#21153; (Swift at scale: building the TelemetryDeck analytics service)</a></strong></h3><p>&#24456;&#22810;&#20154;&#35752;&#35770; Swift on Server &#26102;&#65292;&#20851;&#27880;&#28857;&#24448;&#24448;&#20572;&#30041;&#22312;&#8220;&#33021;&#19981;&#33021;&#29992;&#8221;&#65292;&#32780; TelemetryDeck &#32473;&#20986;&#30340;&#21017;&#26159;&#19968;&#20010;&#26356;&#23454;&#38469;&#30340;&#31572;&#26696;&#65306;&#19981;&#20165;&#33021;&#29992;&#65292;&#32780;&#19988;&#24050;&#32463;&#25903;&#25745;&#36215;&#19968;&#39033;&#38754;&#21521;&#24320;&#21457;&#32773;&#12289;&#27599;&#26376;&#22788;&#29702;&#36229;&#36807; 1600 &#19975;&#29992;&#25143;&#25968;&#25454;&#30340; analytics &#26381;&#21153;&#12290;<a href="https://social.telemetrydeck.com/@daniel">Daniel Jilg</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#22238;&#39038;&#20102;&#22242;&#38431;&#20026;&#20309;&#36873;&#25321; Swift + Vapor &#26500;&#24314;&#21518;&#31471;&#65292;&#24182;&#20998;&#20139;&#20102;&#19981;&#23569;&#26469;&#33258;&#29983;&#20135;&#29615;&#22659;&#30340;&#32463;&#39564;&#65306;&#20363;&#22914;&#22914;&#20309;&#20511;&#21161; <code>Codable</code> &#31616;&#21270; API &#32534;&#35299;&#30721;&#19982;&#26657;&#39564;&#12289;&#20026;&#20160;&#20040;&#24212;&#35753; DTO &#26356;&#36148;&#36817; controller&#12289;&#20197;&#21450;&#20026;&#20309;&#32531;&#23384; TTL&#12289;API &#29256;&#26412;&#31649;&#29702;&#21644;&#38169;&#35823;&#30417;&#25511;&#36825;&#20123;&#8220;&#32769;&#29983;&#24120;&#35848;&#8221;&#65292;&#22312;&#35268;&#27169;&#21270;&#30340;&#29983;&#20135;&#29615;&#22659;&#20013;&#24448;&#24448;&#25165;&#26159;&#30495;&#27491;&#30340;&#25252;&#22478;&#27827;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0126-07">&#26159;&#26102;&#20505;&#21578;&#21035; SwiftGen &#20102;&#21527;&#65311; (Get Rid of Your SwiftGen Dependency)</a></strong></h3><p>&#24456;&#38271;&#19968;&#27573;&#26102;&#38388;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#20381;&#36182;&#31867;&#20284; SwiftGen &#36825;&#26679;&#30340;&#24037;&#20855;&#26469;&#35299;&#20915; Apple &#36164;&#28304;&#31995;&#32479;&#20013;&#30340;&#19968;&#20010;&#32769;&#38382;&#39064;&#65306;&#36164;&#28304;&#35775;&#38382;&#26159;&#23383;&#31526;&#20018;&#31867;&#22411;&#65288;stringly-typed&#65289;&#12290;&#26080;&#35770;&#26159; localization key&#12289;&#22270;&#29255;&#21517;&#31216;&#36824;&#26159;&#39068;&#33394;&#36164;&#20135;&#65292;&#19968;&#26086;&#25340;&#20889;&#38169;&#35823;&#65292;&#24448;&#24448;&#21482;&#33021;&#22312;&#36816;&#34892;&#26102;&#25165;&#20250;&#26292;&#38706;&#38382;&#39064;&#12290;<a href="https://www.linkedin.com/in/asserusama/">Asser Osama</a> &#25351;&#20986;&#65292;&#38543;&#30528; String Catalog&#65288;.xcstrings&#65289;&#19982; Asset Catalog Symbols &#30340;&#24341;&#20837;&#19982;&#36880;&#27493;&#23436;&#21892;&#65292;Xcode &#24050;&#32463;&#33021;&#22815;&#22312;&#32534;&#35793;&#38454;&#27573;&#33258;&#21160;&#29983;&#25104;&#36164;&#28304;&#31526;&#21495;&#65292;&#36825;&#31181;&#21407;&#29983;&#33021;&#21147;&#22312;&#19981;&#23569;&#29616;&#20195;&#39033;&#30446;&#20013;&#25110;&#35768;&#24050;&#32463;&#36275;&#20197;&#26367;&#20195; SwiftGen&#12290;</p><blockquote><p>&#38656;&#35201;&#35828;&#26126;&#30340;&#26159;&#65292;&#8220;&#31227;&#38500;&#20381;&#36182;&#8221;&#30340;&#21069;&#25552;&#26159;&#39033;&#30446;&#23436;&#20840;&#36816;&#34892;&#22312;&#26631;&#20934;&#30340; Xcode &#29983;&#24577;&#20013;&#12290;Xcode &#30340;&#31526;&#21495;&#29983;&#25104;&#23646;&#20110;&#26500;&#24314;&#31995;&#32479;&#20869;&#37096;&#26426;&#21046;&#65292;&#32780;&#19981;&#26159; Swift &#32534;&#35793;&#22120;&#25110; Swift Package Manager &#30340;&#33021;&#21147;&#8212;&#8212;&#36825;&#24847;&#21619;&#30528;&#23545;&#20110;&#20351;&#29992; Bazel&#12289;Buck &#31561;&#38750;&#26631;&#20934;&#26500;&#24314;&#31995;&#32479;&#30340;&#22242;&#38431;&#26469;&#35828;&#65292;SwiftGen &#20173;&#28982;&#21487;&#33021;&#26159;&#26356;&#21487;&#31227;&#26893;&#12289;&#26356;&#21487;&#25511;&#30340;&#36873;&#25321;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0126-08">SwiftUI Agent Skill</a></strong></h3><p>&#30001; <a href="https://x.com/twostraws">Paul Hudson</a> &#32534;&#20889;&#30340; SwiftUI Agent Skill&#65292;&#26088;&#22312;&#24110;&#21161;&#24320;&#21457;&#32773;&#32534;&#20889;&#26356;&#26234;&#33021;&#12289;&#26356;&#31616;&#27905;&#12289;&#26356;&#29616;&#20195;&#30340; SwiftUI &#20195;&#30721;&#12290;&#35813;&#39033;&#30446;&#21457;&#24067;&#20165;&#20004;&#22825;&#20415;&#33719;&#24471;&#20102; 1k+ Star&#12290;</p><blockquote><p>&#22312;&#36807;&#21435;&#20960;&#21608;&#20013;&#65292;&#26412;&#21608;&#25253;&#24050;&#32463;&#25512;&#33616;&#20102;&#19981;&#23569;&#30693;&#21517;&#24320;&#21457;&#32773;&#32534;&#20889;&#30340;&#21508;&#31867; Skill&#12290;&#23613;&#31649;&#36825;&#20123; Skill &#37117;&#20957;&#32858;&#20102;&#20316;&#32773;&#30340;&#32463;&#39564;&#65292;&#20294;&#25105;&#20173;&#19981;&#24314;&#35758;&#24320;&#21457;&#32773;&#30452;&#25509;&#8220;&#25343;&#26469;&#21363;&#29992;&#8221;&#12290;&#33267;&#23569;&#24212;&#22312;&#37319;&#29992;&#21069;&#23436;&#25972;&#38405;&#35835;&#19968;&#36941;&#65306;Skill &#26356;&#20687;&#26159;&#20316;&#32773;&#23545;&#33258;&#24049;&#25968;&#21313;&#29978;&#33267;&#19978;&#30334;&#31687;&#25991;&#31456;&#32463;&#39564;&#30340;&#25552;&#28860;&#65292;&#32780;&#19981;&#26159;&#21487;&#20197;&#30452;&#25509;&#26367;&#20195;&#24605;&#32771;&#30340;&#8220;&#26368;&#20339;&#23454;&#36341;&#8221;&#12290;&#24320;&#21457;&#32773;&#22312;&#29702;&#35299;&#20854;&#32972;&#21518;&#30340;&#35774;&#35745;&#24605;&#36335;&#21518;&#65292;&#20877;&#26681;&#25454;&#33258;&#24049;&#30340;&#24320;&#21457;&#20064;&#24815;&#19982;&#39033;&#30446;&#38656;&#27714;&#36827;&#34892;&#21462;&#33293;&#65292;&#36825;&#26679;&#25165;&#33021;&#26356;&#22823;&#22320;&#21457;&#25381;&#23427;&#20204;&#30340;&#20215;&#20540;&#12290;</p></blockquote><h2><strong>&#27963;&#21160;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-10">LET&#8217;S VISION 2026&#65292;&#24320;&#31080;&#21862;&#65281;</a></strong></h3><p>&#20316;&#20026;&#22312;&#20013;&#22269;&#20030;&#21150;&#12289;&#38754;&#21521;&#20840;&#29699;&#30340; Apple &#29983;&#24577;&#19979;&#30340;&#22823;&#20250;&#65292;&#20170;&#24180;&#30340; LET&#8217;S VISION &#23558;&#20250;&#26377;&#32422; 20 &#22330;&#28436;&#35762;&#12289;&#36229;&#36807; 80 &#20010;&#23637;&#20301;&#65292;&#27426;&#36814;&#21069;&#24448;&#23448;&#32593;&#21644;&#31080;&#21153;&#24179;&#21488;&#20102;&#35299;&#26356;&#22810;&#20449;&#24687;&#12290;</p><ul><li><p><strong>&#26102;&#38388;&#21450;&#22320;&#28857;</strong>&#65306;03.28 - 03.29&#65292;&#19978;&#28023;&#183;&#28437;&#27827;&#27902;&#20250;&#35758;&#20013;&#24515;</p></li><li><p><strong><a href="https://letsvision.swiftgg.team/">&#27963;&#21160;&#23448;&#32593;</a></strong></p></li><li><p><strong><a href="https://l.fatbobman.com/w0125-10">&#33719;&#21462;&#38376;&#31080;</a></strong></p></li></ul>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #125]]></title><description><![CDATA[OpenClaw Is Impressive &#8212; I Just Don&#8217;t Really Need It (Yet)]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-125</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-125</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 02 Mar 2026 12:02:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Ovah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.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_!Ovah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ovah!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 424w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 848w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 1272w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ovah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp" width="1436" height="672" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1436,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12152,&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/189608684?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.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_!Ovah!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 424w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 848w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.webp 1272w, https://substackcdn.com/image/fetch/$s_!Ovah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0adce669-0139-4c00-8084-17c45e975f1b_1436x672.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"><svg role="img" 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"><g><title></title><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"><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"><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>OpenClaw Is Impressive &#8212; I Just Don&#8217;t Really Need It (Yet)</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-125/">Read on web &#8594;</a></p><p>On the morning of March 1st, I received a message from OpenClaw. It was part of a scheduled task I had set up after installing it: on the first day of every month, it sends me a summary of the main tasks it executed on my behalf over the past month.</p><p>Reading through that rather sparse report, I found myself pausing. At this stage, I don&#8217;t think I actually need a personal AI agent. To be honest, if it hadn&#8217;t sent that message yesterday, I might have almost forgotten it was even there.</p><p>After the OpenClaw project name was finalized, I still couldn&#8217;t quite resist the stream of flashy demos filling my social media timeline. I dug out an idle Mac mini M4 and followed the setup guides to get everything running. During the first few days, I spent some time studying how others were using it, trying to see whether it could naturally fit into my own life and workflow.</p><p>Eventually, though, I came to realize that&#8212;at least given my current workload and habits&#8212;many traditional tools that have already matured are more than sufficient for my needs. Even when I do need an agent loop on mobile devices, using more focused, single-purpose tools often results in less configuration overhead and a lower cognitive burden overall.</p><p>A year ago, few people would have expected that CLI tools would see a resurgence at a time when GUIs have long been the default. In a similar way, before OpenClaw gained traction, hardly anyone anticipated the sudden emergence of so many OpenClaw-like projects. I have little doubt that most people will eventually have their own personal AI assistants. OpenClaw presents one possible vision of that future&#8212;very much from a hacker&#8217;s perspective. But what form these assistants will ultimately take, and how they will balance privacy, security, and efficiency, remains an open question.</p><p>From one angle, having an intelligent assistant does seem pretty cool. Still, life without one feels just as calm and comfortable. For now, I&#8217;ll let &#129438; rest quietly on my mini&#8212;until the day I truly need to wake it up.</p><p><a href="https://fatbobman.com/en/weekly/issue-124/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2><strong>This Week&#8217;s Sponsor</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-notepad">Notepad.exe &#8212; A Notepad for Developers</a></strong></h3><p>Notepad.exe is a lightweight coding scratchpad for macOS, built for experiments, snippets, and rapid prototyping. Open it, write your code, and run it &#8212; no project setup required.</p><p><a href="https://l.fatbobman.com/sb-notepad">&#128640; </a><strong><a href="https://l.fatbobman.com/sb-notepad">Download for macOS &#8594;</a></strong></p><div><hr></div><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-01">Building Lists: A High-Performance Diffable Data Source Framework</a></strong></h3><p>After integrating <code>UICollectionViewDiffableDataSource</code> with TCA, <a href="https://mastodon.social/@IronHam@hachyderm.io">Hesham Salman</a> noticed more than 100 UI stalls per minute. A deeper investigation revealed that <code>NSDiffableDataSourceSnapshot</code> heavily relies on Objective-C&#8217;s <code>NSOrderedSet</code> under the hood. In a reactive architecture where state updates frequently, repeated snapshot reconstruction leads to substantial hashing costs and Objective-C bridging overhead. To address this, Hesham built a pure Swift alternative, <a href="https://github.com/Iron-Ham/Lists">ListKit</a>. By leveraging <code>ContiguousArray</code>, a two-level diff algorithm, and lazily constructed reverse indices, snapshot construction performance improved by several hundred times.</p><blockquote><p>In imperative frameworks, developers can precisely control refresh timing, so diff performance issues may not be immediately obvious. But as reactive programming increasingly makes its way into UIKit, traditional assumptions and techniques must adapt to new refresh patterns. Yesterday&#8217;s &#8220;best practice APIs&#8221; can quietly become today&#8217;s performance bottlenecks.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-02">SwiftUI Charts caused major stutter in my app &#8212; replacing it with Path fixed everything</a></strong></h3><p>There is no doubt that Swift Charts provides a clean declarative API and polished visual output, making it a go-to choice for many developers. However, even years after its release, when dealing with large datasets and high-frequency interactions, its reliance on numerous fine-grained view components can amplify SwiftUI&#8217;s diffing and layout costs, resulting in noticeable performance degradation. After reassessing his needs, <a href="https://medium.com/@oscarberggren082">Oscar Berggren</a> replaced Charts with a custom <code>Shape</code> built on <code>Path</code>, completely eliminating drag-related stutters.</p><blockquote><p>As highlighted in the ListKit article above, when high-frequency state updates (such as gesture-driven refreshes) combine with heavyweight view construction (hundreds of <code>LineMark</code> instances), performance bottlenecks become almost inevitable. In such cases, stepping back to lower-level drawing APIs like <code>Path</code> often yields more predictable and stable results.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-03">We added an MCP server to our macOS app and learned a lot the hard way</a></strong></h3><p>Adding MCP support to a macOS app sounds like just exposing a few more interfaces &#8212; until you actually try it. <a href="https://medium.com/@charidimos">Charidimos Chaintoutis</a> discovered this firsthand while implementing native Swift MCP support for unclutr: the gap between &#8220;works in dev&#8221; and &#8220;users can configure, diagnose, and install it&#8221; is wider than expected.</p><p>The article details challenges around stdio transport, client handshakes, launcher configuration, and macOS sandbox restrictions&#8212;particularly the friction between sandboxing and spawning external processes. These constraints ultimately forced them to disable MCP support in the Mac App Store version and offer it only in the direct-download build. The security model they arrived at is especially instructive: separating read and write tools, requiring explicit deletion calls, enforcing absolute paths, supporting dry runs, and always moving files to Trash rather than permanently deleting them. These are lessons learned the hard way.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-04">Array expression trailing closures in Swift</a></strong></h3><p>In this article, <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> introduces the accepted Swift Evolution proposal <a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0508-array-expression-trailing-closures.md">SE-0508</a>. The proposal removes a long-standing syntactic special case: array and dictionary type expressions previously could not be followed directly by trailing closures. With this restriction lifted, building collections using result builders (for example, <code>let items = [String] { "First"; "Second" }</code>) becomes far more natural. It also enables calling <code>callAsFunction</code> directly after array literals, such as <code>["a", "b", "c"] { $0.uppercased() }</code>.</p><blockquote><p>At first glance, this may seem like a minor syntactic refinement. In reality, it eliminates inconsistencies between collection types and other types, further smoothing Swift&#8217;s surface. Language progress does not always come from bold new features&#8212;sometimes it comes from patiently sanding down long-standing rough edges.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-05">Mastering Geometry in SwiftUI - GeometryReader, GeometryProxy &amp; onGeometryChange</a></strong></h3><p>For a long time, developers relied almost exclusively on <code>GeometryReader</code> to obtain a view&#8217;s size or position. However, <code>GeometryReader</code> is itself a layout container that expands to fill all available space. This &#8220;greedy&#8221; behavior often causes unexpected layout issues for those unfamiliar with its mechanics. In this comprehensive article, <a href="https://www.linkedin.com/in/sdunagar/">Sagar Unagar</a> revisits SwiftUI&#8217;s geometry system from an architectural perspective. He compares the traditional <code>GeometryReader</code> + <code>PreferenceKey</code> pattern, the <code>Layout</code> protocol introduced in iOS 16, and the <code>.onGeometryChange</code> modifier introduced in iOS 18. Rather than merely listing APIs, the article explains how geometry fits into SwiftUI&#8217;s proposal-driven layout system.</p><blockquote><p>If you approach SwiftUI with a command-style mindset and attempt to &#8220;control&#8221; layout directly, it will likely feel awkward. But once your mental model aligns with its negotiation-based design, you begin to see that SwiftUI&#8217;s expressive ceiling is much higher than it first appears.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-07">Xcode Assistant Copilot Server</a></strong></h3><p>Xcode 26.3 introduced support for Codex and Claude Code, officially bringing agent capabilities into the IDE workflow. But not every developer uses those services. Developed by <a href="https://x.com/fercabj">Fernando Romiti</a>, Xcode Assistant Copilot Server offers an alternative for GitHub Copilot subscribers. It is a Swift-based local service that translates Xcode&#8217;s OpenAI-compatible requests into GitHub Copilot API calls. <strong>However, it should not be mistaken for a simple protocol adapter.</strong></p><p>In its default mode, it acts as a transparent proxy, forwarding Xcode&#8217;s <code>/v1/chat/completions</code> requests to Copilot. Once Agent mode is enabled and MCP is configured, it runs a full local agent loop. When the Copilot model issues tool calls, the server intercepts them, executes the corresponding operations locally (via <code>xcrun mcpbridge</code> or permitted CLI tools), appends the results to the conversation, re-queries the model, and continues this cycle until a final response is produced and returned to Xcode.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-08">Foundation Models SDK for Python</a></strong></h3><p>Foundation Models SDK for Python is a recently released open-source project from Apple. Through a Swift bridge, it enables developers to <strong>directly invoke Apple Intelligence foundation models running on macOS (on-device) from a Python environment</strong>.</p><p>In modern LLM application development, evaluation is critical. Developers need to run large test suites to measure the impact of prompt adjustments and tool-calling strategies. Data-driven analysis of this kind has long been dominated by the Python ecosystem. This SDK fills that gap: developers can export real transcripts (JSON) from Swift, then reproduce on-device inference behavior in Python and perform batch analysis, scoring, clustering, and error attribution as if processing ordinary datasets.</p><blockquote><p>In effect, Apple is signaling a standardized workflow for AI application development: <strong>Swift handles on-device integration and user experience, while Python powers offline evaluation and iterative optimization.</strong></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-09">vphone-cli: Running a Real iPhone on Your Mac</a></strong></h3><p>When Apple introduced Apple Intelligence in 2024, it also unveiled PCC (Private Cloud Compute), a privacy-focused infrastructure running on Apple Silicon servers. Its significance lies not merely in &#8220;offloading AI to the cloud&#8221;, but in extending the iPhone&#8217;s security model to server-side environments. Apple even released research materials and virtual research environments to allow security researchers to audit PCC nodes locally.</p><p>Starting with cloudOS 26, Apple added components related to <code>vphone600ap</code> in PCC firmware. The community quickly took notice. Building on <a href="https://github.com/wh1te4ever/super-tart-vphone-writeup">in-depth reverse engineering work</a> by <a href="https://x.com/wh1te4ever">Hyungyu Seo</a> and others, <a href="https://x.com/Lakr233">Lakr</a> developed vphone-cli, which operationalizes this virtualization mechanism. By leveraging private APIs from <code>Virtualization.framework</code>, it creates a fully functional virtual iPhone research environment on macOS. Unlike the Xcode Simulator, this setup runs real iOS firmware, executing the full boot chain from start to finish.</p><blockquote><p>What makes this development fascinating is not merely jailbreak research or firmware analysis, but the broader signal it sends: Apple appears to be externalizing the iOS security architecture it has refined for over a decade, extending it to reshape its cloud computing infrastructure.</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-125?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-125?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>OpenClaw &#19981;&#38169;&#65292;&#20294;&#25105;&#22909;&#20687;&#27809;&#26377;&#37027;&#20040;&#38656;&#35201;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-125/">&#32593;&#39029;&#29256;</a></strong></p><p>3 &#26376; 1 &#26085;&#26089;&#19978;&#65292;&#25105;&#25910;&#21040;&#20102; OpenClaw &#21457;&#26469;&#30340;&#20449;&#24687;&#12290;&#36825;&#26159;&#25105;&#22312;&#23433;&#35013;&#23427;&#20043;&#21518;&#35774;&#32622;&#30340;&#19968;&#20010;&#23450;&#26102;&#20219;&#21153;&#65306;&#27599;&#20010;&#26376;&#30340;&#31532;&#19968;&#22825;&#65292;&#21521;&#25105;&#27719;&#25253;&#36807;&#21435;&#19968;&#20010;&#26376;&#23427;&#20026;&#25105;&#25191;&#34892;&#36807;&#30340;&#20027;&#35201;&#20219;&#21153;&#27719;&#24635;&#12290;&#30475;&#30528;&#27719;&#24635;&#20013;&#23525;&#23525;&#25968;&#35821;&#65292;&#25105;&#19981;&#30001;&#24471;&#38519;&#20837;&#20102;&#24605;&#32771;&#8212;&#8212;&#29616;&#38454;&#27573;&#65292;&#25105;&#20284;&#20046;&#30495;&#30340;&#36824;&#19981;&#38656;&#35201;&#19968;&#20010;&#20010;&#20154;&#26234;&#33021;&#20307;&#12290;&#35828;&#23454;&#35805;&#65292;&#22914;&#26524;&#19981;&#26159;&#23427;&#26152;&#22825;&#21457;&#26469;&#30340;&#36825;&#26465;&#28040;&#24687;&#65292;&#25105;&#20960;&#20046;&#24050;&#32463;&#24573;&#30053;&#20102;&#23427;&#30340;&#23384;&#22312;&#12290;</p><p>&#22312; OpenClaw &#39033;&#30446;&#21517;&#31216;&#27491;&#24335;&#30830;&#23450;&#20043;&#21518;&#65292;&#25105;&#36824;&#26159;&#27809;&#33021;&#25269;&#25377;&#20303;&#31038;&#20132;&#23186;&#20307;&#26102;&#38388;&#32447;&#19978;&#37027;&#20123;&#28843;&#37239;&#28436;&#31034;&#30340;&#35825;&#24785;&#65292;&#32763;&#20986;&#20102;&#19968;&#21488;&#38386;&#32622;&#30340; Mac mini M4&#65292;&#29031;&#30528;&#25945;&#31243;&#25240;&#33150;&#20102;&#36215;&#26469;&#12290;&#26368;&#21021;&#20960;&#22825;&#65292;&#25105;&#20063;&#35748;&#30495;&#30740;&#31350;&#36807;&#20854;&#20182;&#20154;&#30340;&#20351;&#29992;&#22330;&#26223;&#65292;&#23581;&#35797;&#23558;&#23427;&#34701;&#20837;&#33258;&#24049;&#30340;&#29983;&#27963;&#21644;&#24037;&#20316;&#27969;&#20013;&#12290;&#20294;&#21518;&#26469;&#25105;&#36880;&#28176;&#24847;&#35782;&#21040;&#65292;&#33267;&#23569;&#20197;&#25105;&#30446;&#21069;&#30340;&#24037;&#20316;&#24378;&#24230;&#21644;&#20351;&#29992;&#20064;&#24815;&#26469;&#30475;&#65292;&#19968;&#20123;&#24050;&#32463;&#36275;&#22815;&#25104;&#29087;&#30340;&#20256;&#32479;&#24037;&#20855;&#65292;&#20381;&#28982;&#21487;&#20197;&#24456;&#22909;&#22320;&#28385;&#36275;&#25105;&#30340;&#38656;&#27714;&#12290;&#21363;&#20415;&#38656;&#35201;&#22312;&#31227;&#21160;&#35774;&#22791;&#19978;&#36827;&#34892; Agent loop&#65292;&#30452;&#25509;&#20351;&#29992;&#21151;&#33021;&#26356;&#32858;&#28966;&#30340;&#21333;&#19968;&#29992;&#36884;&#20135;&#21697;&#65292;&#21453;&#32780;&#33021;&#20943;&#23569;&#37197;&#32622;&#21644;&#20351;&#29992;&#19978;&#30340;&#24515;&#26234;&#36127;&#25285;&#12290;</p><p>&#19968;&#24180;&#21069;&#65292;&#25110;&#35768;&#27809;&#26377;&#22810;&#23569;&#20154;&#20250;&#24819;&#21040;&#65292;&#22312; GUI &#24050;&#32463;&#25104;&#20026;&#40664;&#35748;&#24418;&#24577;&#30340;&#20170;&#22825;&#65292;CLI &#20250;&#37325;&#26032;&#36814;&#26469;&#19968;&#36718;&#22238;&#28526;&#12290;&#21516;&#26679;&#65292;&#22312; OpenClaw &#28779;&#29190;&#20043;&#21069;&#65292;&#20063;&#24456;&#23569;&#26377;&#20154;&#39044;&#26009;&#21040;&#65292;&#22914;&#20170;&#20250;&#28044;&#29616;&#20986;&#22914;&#27492;&#22810;&#30340; OpenClaw-like &#39033;&#30446;&#12290;&#25105;&#24182;&#19981;&#24576;&#30097;&#65292;&#26410;&#26469;&#22823;&#22810;&#25968;&#20154;&#37117;&#20250;&#25317;&#26377;&#23646;&#20110;&#33258;&#24049;&#30340;&#20010;&#20154;&#26234;&#33021;&#21161;&#25163;&#12290;OpenClaw &#20197;&#19968;&#31181;&#30456;&#24403;&#26497;&#23458;&#30340;&#26041;&#24335;&#65292;&#23637;&#31034;&#20102;&#20854;&#20013;&#30340;&#19968;&#31181;&#21487;&#33021;&#24615;&#65307;&#20294;&#26234;&#33021;&#20307;&#21161;&#25163;&#26368;&#32456;&#20250;&#20197;&#24590;&#26679;&#30340;&#24418;&#24577;&#23384;&#22312;&#65292;&#21448;&#23558;&#22914;&#20309;&#22312;&#38544;&#31169;&#12289;&#23433;&#20840;&#19982;&#25928;&#29575;&#20043;&#38388;&#21462;&#24471;&#24179;&#34913;&#65292;&#30452;&#21040;&#29616;&#22312;&#20381;&#28982;&#27809;&#26377;&#19968;&#20010;&#30830;&#23450;&#30340;&#31572;&#26696;&#12290;</p><p>&#20174;&#26576;&#31181;&#35282;&#24230;&#26469;&#30475;&#65292;&#25317;&#26377;&#19968;&#20010;&#26234;&#33021;&#21161;&#25163;&#30830;&#23454;&#25402;&#37239;&#65307;&#20294;&#27809;&#26377;&#23427;&#65292;&#20063;&#19997;&#27627;&#19981;&#24433;&#21709;&#25105;&#20139;&#21463;&#24403;&#19979;&#30340;&#24179;&#38745;&#19982;&#23433;&#36920;&#12290;&#23601;&#35753; &#129438; &#22312;&#25105;&#30340; mini &#37324;&#22909;&#22909;&#20241;&#24687;&#21543;&#65292;&#31561;&#21040;&#25105;&#30495;&#27491;&#38656;&#35201;&#21796;&#37266;&#23427;&#30340;&#37027;&#19968;&#22825;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-124/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div><hr></div><h2><strong>&#26412;&#26399;&#36190;&#21161;</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-notepad">Notepad.exe &#8212; &#38543;&#24320;&#38543;&#29992;&#30340;&#20195;&#30721;&#33609;&#31295;&#26412;</a></strong></h3><p>&#36731;&#37327;&#32423; macOS &#20195;&#30721;&#33609;&#31295;&#24037;&#20855;&#65292;&#19987;&#20026;&#20195;&#30721;&#23454;&#39564;&#12289;&#29255;&#27573;&#35760;&#24405;&#21644;&#24555;&#36895;&#21407;&#22411;&#32780;&#29983;&#12290;&#25171;&#24320;&#21363;&#29992;&#65292;&#20889;&#20195;&#30721;&#12289;&#36305;&#20195;&#30721;&#65292;&#38646;&#39033;&#30446;&#37197;&#32622;&#12290;</p><p><strong><a href="https://l.fatbobman.com/sb-notepad">&#128640; &#20813;&#36153;&#19979;&#36733; &#8594;</a></strong></p><div><hr></div><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-01">Diffable &#30340;&#24615;&#33021;&#38519;&#38449;&#19982; ListKit &#30772;&#23616; (Building Lists: A High-Performance Diffable Data Source Framework)</a></strong></h3><p><a href="https://mastodon.social/@IronHam@hachyderm.io">Hesham Salman</a> &#22312;&#23558; <code>UICollectionViewDiffableDataSource</code> &#19982; TCA &#37197;&#21512;&#20351;&#29992;&#21518;&#65292;&#21457;&#29616;&#21407;&#29983; DiffableDataSource &#23548;&#33268;&#20102;&#27599;&#20998;&#38047; 100 &#22810;&#27425;&#30340;&#21345;&#39039;&#12290;&#28145;&#20837;&#20998;&#26512;&#21518;&#65292;&#20182;&#21457;&#29616; <code>NSDiffableDataSourceSnapshot</code> &#24213;&#23618;&#20854;&#23454;&#37325;&#24230;&#20381;&#36182; Objective-C &#30340; <code>NSOrderedSet</code>&#12290;&#22312;&#21709;&#24212;&#24335;&#26550;&#26500;&#20013;&#65292;&#30001;&#20110;&#29366;&#24577;&#30340;&#39640;&#39057;&#21047;&#26032;&#65292;Snapshot &#30340;&#39057;&#32321;&#37325;&#24314;&#24341;&#21457;&#20102;&#24040;&#22823;&#30340;&#21704;&#24076;&#35745;&#31639;&#19982; Obj-C &#26725;&#25509;&#24320;&#38144;&#12290;&#20026;&#27492;&#65292;Hesham &#24320;&#21457;&#20102;&#19968;&#20010;&#32431; Swift &#23454;&#29616;&#30340;&#26367;&#20195;&#21697; <a href="https://github.com/Iron-Ham/Lists">ListKit</a>&#12290;&#36890;&#36807;&#20351;&#29992; <code>ContiguousArray</code>&#12289;&#21452;&#23618; Diff &#31639;&#27861;&#20197;&#21450;&#24310;&#36831;&#26500;&#24314;&#21453;&#21521;&#32034;&#24341;&#65292;&#23558;&#26500;&#24314; Snapshot &#30340;&#36895;&#24230;&#25552;&#21319;&#20102;&#25968;&#30334;&#20493;&#12290;</p><blockquote><p>&#22312;&#21629;&#20196;&#24335;&#26694;&#26550;&#20013;&#65292;&#30001;&#20110;&#24320;&#21457;&#32773;&#21487;&#20197;&#31934;&#30830;&#25511;&#21046;&#21047;&#26032;&#26102;&#26426;&#65292;&#22240;&#27492; Diff &#30340;&#25928;&#29575;&#38382;&#39064;&#21487;&#33021;&#26292;&#38706;&#24471;&#24182;&#19981;&#26126;&#26174;&#12290;&#20294;&#38543;&#30528;&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#23558;&#21709;&#24212;&#24335;&#32534;&#31243;&#24341;&#20837; UIKit&#65292;&#19968;&#20123;&#20256;&#32479;&#30340;&#24605;&#32500;&#25110;&#25216;&#24039;&#38656;&#35201;&#26681;&#25454;&#26032;&#30340;&#21047;&#26032;&#26426;&#21046;&#26469;&#20570;&#35843;&#25972;&#65292;&#36807;&#21435;&#30340;&#8220;&#26368;&#20339;&#23454;&#36341; API&#8221;&#21487;&#33021;&#27491;&#22312;&#25104;&#20026;&#26032;&#30340;&#24615;&#33021;&#29942;&#39048;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-02">SwiftUI Charts &#24615;&#33021;&#36991;&#22353;&#65306;&#22238;&#24402;&#24213;&#23618; Path &#32472;&#21046; (SwiftUI Charts caused major stutter in my app &#8212; replacing it with Path fixed everything)</a></strong></h3><p>&#27595;&#24248;&#32622;&#30097;&#65292;Swift Charts &#25552;&#20379;&#20102;&#31616;&#27905;&#30340;&#22768;&#26126;&#24335;&#20307;&#39564;&#19982;&#31934;&#33268;&#30340;&#35270;&#35273;&#21576;&#29616;&#65292;&#33258;&#21457;&#24067;&#20197;&#26469;&#20415;&#25104;&#20026;&#19981;&#23569;&#24320;&#21457;&#32773;&#32472;&#21046;&#22270;&#34920;&#30340;&#39318;&#36873;&#12290;&#28982;&#32780;&#65292;&#21363;&#20415;&#22312;&#25512;&#20986;&#22810;&#24180;&#20043;&#21518;&#65292;&#24403;&#38754;&#23545;&#21253;&#21547;&#39640;&#39057;&#20132;&#20114;&#30340;&#22823;&#25968;&#25454;&#38598;&#22330;&#26223;&#26102;&#65292;&#20854;&#22522;&#20110;&#22823;&#37327;&#32454;&#31890;&#24230; View &#32452;&#21512;&#30340;&#23454;&#29616;&#26041;&#24335;&#65292;&#20173;&#21487;&#33021;&#25918;&#22823; SwiftUI &#30340; diff &#19982;&#24067;&#23616;&#25104;&#26412;&#65292;&#20174;&#32780;&#24341;&#21457;&#24615;&#33021;&#38382;&#39064;&#12290;<a href="https://medium.com/@oscarberggren082">Oscar Berggren</a> &#22312;&#35780;&#20272;&#33258;&#36523;&#38656;&#27714;&#21518;&#65292;&#25918;&#24323;&#20351;&#29992; Charts&#65292;&#20026;&#25240;&#32447;&#32472;&#21046;&#25913;&#29992;&#33258;&#23450;&#20041; <code>Shape</code> + <code>Path</code>&#65292;&#25104;&#21151;&#28040;&#38500;&#20102;&#25302;&#25341;&#36807;&#31243;&#20013;&#30340;&#21345;&#39039;&#12290;</p><blockquote><p>&#27491;&#22914;&#21069;&#25991; ListKit &#25152;&#25581;&#31034;&#30340;&#65292;&#24403;&#39640;&#39057;&#29366;&#24577;&#21464;&#26356;&#65288;&#20363;&#22914;&#25163;&#21183;&#39537;&#21160;&#30340;&#21047;&#26032;&#65289;&#21472;&#21152;&#22312;&#37325;&#37327;&#32423;&#23545;&#35937;&#26500;&#24314;&#65288;&#22823;&#37327; <code>LineMark</code>&#65289;&#20043;&#19978;&#26102;&#65292;&#24615;&#33021;&#29942;&#39048;&#24448;&#24448;&#19981;&#21487;&#36991;&#20813;&#12290;&#27492;&#26102;&#65292;&#36866;&#24230;&#22238;&#24402;&#26356;&#24213;&#23618;&#30340;&#32472;&#21046; API&#65288;&#22914; <code>Path</code>&#65289;&#65292;&#21453;&#32780;&#33021;&#22815;&#24102;&#26469;&#26356;&#31283;&#23450;&#12289;&#21487;&#25511;&#30340;&#34920;&#29616;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-03">&#32431; Swift MCP Server &#24320;&#21457;&#19982;&#20998;&#21457;&#36393;&#22353;&#23454;&#24405; (We added an MCP server to our macOS app and learned a lot the hard way)</a></strong></h3><p>&#20026; macOS &#24212;&#29992;&#28155;&#21152; MCP &#33021;&#21147;&#65292;&#21548;&#36215;&#26469;&#19981;&#36807;&#26159;&#22810;&#26292;&#38706;&#20960;&#20010;&#25509;&#21475;&#8212;&#8212;&#30452;&#21040;&#20320;&#30495;&#27491;&#21435;&#20570;&#12290;<a href="https://medium.com/@charidimos">Charidimos Chaintoutis</a> &#22312;&#20026;&#24212;&#29992; unclutr &#23454;&#29616;&#32431; Swift &#30340; MCP &#25903;&#25345;&#26102;&#21457;&#29616;&#65292;&#20174;&#8220;&#24320;&#21457;&#29615;&#22659;&#21487;&#36816;&#34892;&#8221;&#21040;&#8220;&#29992;&#25143;&#21487;&#37197;&#32622;&#12289;&#21487;&#35786;&#26029;&#12289;&#21487;&#20998;&#21457;&#8221;&#20043;&#38388;&#65292;&#20173;&#26377;&#30456;&#24403;&#38271;&#30340;&#19968;&#27573;&#36317;&#31163;&#12290;</p><p>&#25991;&#31456;&#35760;&#24405;&#20102;&#20182;&#22312; stdio &#36890;&#20449;&#12289;&#23458;&#25143;&#31471;&#25569;&#25163;&#12289;launcher &#37197;&#32622;&#20197;&#21450; macOS &#27801;&#30418;&#65288;Sandbox&#65289;&#38480;&#21046;&#31561;&#26041;&#38754;&#36935;&#21040;&#30340;&#38382;&#39064;&#65292;&#23588;&#20854;&#26159;&#27801;&#30418;&#29615;&#22659;&#19979;&#22806;&#37096;&#36827;&#31243;&#21796;&#36215;&#30340;&#26435;&#38480;&#20914;&#31361;&#65292;&#26368;&#32456;&#36843;&#20351;&#20182;&#20204;&#22312; Mac App Store &#29256;&#26412;&#20013;&#20851;&#38381; MCP &#21151;&#33021;&#65292;&#20165;&#22312;&#30452;&#35013;&#29256;&#26412;&#20013;&#25552;&#20379;&#25903;&#25345;&#12290;&#27492;&#22806;&#65292;&#22312;&#8220;&#22914;&#20309;&#23433;&#20840;&#22320;&#35753; AI &#25805;&#20316;&#29992;&#25143;&#25991;&#20214;&#8221;&#36825;&#19968;&#28857;&#19978;&#65292;&#20316;&#32773;&#24635;&#32467;&#20986;&#30340;&#23454;&#36341;&#32463;&#39564;&#23588;&#20026;&#20540;&#24471;&#21442;&#32771;&#65306;&#35835;&#20889;&#24037;&#20855;&#20998;&#31163;&#12289;&#21024;&#38500;&#24517;&#39035;&#26174;&#24335;&#35843;&#29992;&#12289;&#24378;&#21046;&#32477;&#23545;&#36335;&#24452;&#12289;&#25903;&#25345; Dry Run&#12289;&#32479;&#19968;&#20351;&#29992; Trash &#32780;&#38750;&#30828;&#21024;&#38500;&#12290;&#36825;&#20123;&#35774;&#35745;&#37117;&#26159;&#22312;&#36393;&#36807;&#36275;&#22815;&#22810;&#22353;&#20043;&#21518;&#25165;&#33021;&#24471;&#21040;&#30340;&#32463;&#39564;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-04">&#35299;&#38145;&#25968;&#32452;&#19982;&#23383;&#20856;&#30340;&#23614;&#38543;&#38381;&#21253;&#35821;&#27861; (Array expression trailing closures in Swift)</a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#20102;&#19968;&#20010;&#24050;&#32463;&#36890;&#36807;&#30340;&#25552;&#26696;&#65306;<a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0508-array-expression-trailing-closures.md">SE-0508</a>&#12290;&#35813;&#25552;&#26696;&#31227;&#38500;&#20102; Swift &#35821;&#27861;&#20013;&#30340;&#19968;&#20010;&#8220;&#21382;&#21490;&#29305;&#20363;&#8221;&#65306;&#25968;&#32452;&#19982;&#23383;&#20856;&#31867;&#22411;&#34920;&#36798;&#24335;&#27492;&#21069;&#26080;&#27861;&#30452;&#25509;&#36319;&#38543; trailing closure&#12290;&#38543;&#30528;&#36825;&#19968;&#38480;&#21046;&#34987;&#35299;&#38500;&#65292;&#21033;&#29992; Result Builder &#26500;&#24314;&#38598;&#21512;&#31867;&#22411;&#65288;&#20363;&#22914; <code>let items = [String] { "First"; "Second" }</code>&#65289;&#23558;&#21464;&#24471;&#26356;&#21152;&#33258;&#28982;&#65292;&#21516;&#26102;&#20063;&#20801;&#35768;&#22312;&#25968;&#32452;&#23383;&#38754;&#37327;&#21518;&#30452;&#25509;&#35302;&#21457; <code>callAsFunction</code>&#65288;&#22914; <code>["a", "b", "c"] { $0.uppercased() }</code>&#65289;&#12290;</p><blockquote><p>&#36825;&#30475;&#20284;&#21482;&#26159;&#19968;&#27425;&#35821;&#27861;&#23618;&#38754;&#30340;&#32454;&#33410;&#35843;&#25972;&#65292;&#21364;&#36827;&#19968;&#27493;&#28040;&#38500;&#20102;&#38598;&#21512;&#31867;&#22411;&#19982;&#26222;&#36890;&#31867;&#22411;&#20043;&#38388;&#30340;&#35299;&#26512;&#24046;&#24322;&#65292;&#35753;&#35821;&#35328;&#22312;&#34920;&#36798;&#19968;&#33268;&#24615;&#19978;&#26356;&#36827;&#19968;&#27493;&#12290;&#26377;&#26102;&#20505;&#65292;&#35821;&#35328;&#30340;&#36827;&#27493;&#24182;&#38750;&#26469;&#33258;&#23439;&#22823;&#30340;&#26032;&#29305;&#24615;&#65292;&#32780;&#26159;&#26469;&#33258;&#23545;&#37027;&#20123;&#23384;&#22312;&#22810;&#24180;&#30340;&#23567;&#29781;&#30133;&#30340;&#25345;&#32493;&#25171;&#30952;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-05">&#37325;&#22609; SwiftUI &#24067;&#23616;&#24515;&#26234;&#65306;&#21578;&#21035; GeometryReader &#28389;&#29992; (Mastering Geometry in SwiftUI - GeometryReader, GeometryProxy &amp; onGeometryChange)</a></strong></h3><p>&#24456;&#38271;&#19968;&#27573;&#26102;&#38388;&#37324;&#65292;&#24320;&#21457;&#32773;&#33509;&#24819;&#33719;&#21462;&#35270;&#22270;&#30340;&#23610;&#23544;&#25110;&#20301;&#32622;&#65292;&#20960;&#20046;&#21482;&#33021;&#20381;&#36182; <code>GeometryReader</code>&#12290;&#28982;&#32780;&#65292;<code>GeometryReader</code> &#26412;&#36136;&#19978;&#26159;&#19968;&#20010;&#20250;&#21344;&#28385;&#25152;&#26377;&#21487;&#29992;&#31354;&#38388;&#30340;&#24067;&#23616;&#23481;&#22120;&#65292;&#36825;&#31181;&#8220;&#36138;&#23146;&#8221;&#30340;&#29305;&#24615;&#65292;&#24120;&#24120;&#35753;&#19981;&#29087;&#24713;&#20854;&#34892;&#20026;&#30340;&#24320;&#21457;&#32773;&#38519;&#20837;&#24067;&#23616;&#22256;&#22659;&#12290;<a href="https://www.linkedin.com/in/sdunagar/">Sagar Unagar</a> &#22312;&#26412;&#25991;&#20013;&#31995;&#32479;&#26803;&#29702;&#20102; SwiftUI &#20960;&#20309;&#20307;&#31995;&#30340;&#28436;&#36827;&#36335;&#24452;&#19982;&#24515;&#26234;&#27169;&#22411;&#65292;&#23545;&#27604;&#20102;&#20256;&#32479;&#30340; <code>GeometryReader</code> + <code>PreferenceKey</code> &#32452;&#21512;&#12289;iOS 16 &#24341;&#20837;&#30340; <code>Layout</code> &#21327;&#35758;&#65292;&#20197;&#21450; iOS 18 &#24102;&#26469;&#30340; <code>.onGeometryChange</code> &#20462;&#39280;&#31526;&#12290;&#20174;&#26550;&#26500;&#35270;&#35282;&#35299;&#37322;&#20102;&#20960;&#20309;&#20449;&#24687;&#22312; proposal-driven &#24067;&#23616;&#31995;&#32479;&#20013;&#30340;&#20301;&#32622;&#65292;&#32780;&#19981;&#20165;&#20165;&#26159; API &#30340;&#20351;&#29992;&#26041;&#27861;&#12290;</p><blockquote><p>&#22312; SwiftUI &#20013;&#65292;&#22914;&#26524;&#20320;&#22987;&#32456;&#35797;&#22270;&#29992;&#21629;&#20196;&#24335;&#24605;&#32500;&#21435;&#8220;&#25511;&#21046;&#8221;&#24067;&#23616;&#65292;&#23427;&#24448;&#24448;&#20250;&#26174;&#24471;&#21035;&#25197;&#65307;&#20294;&#24403;&#20320;&#30340;&#29702;&#35299;&#19982;&#20854;&#21327;&#21830;&#24335;&#24067;&#23616;&#26426;&#21046;&#23545;&#40784;&#26102;&#65292;&#20320;&#20250;&#21457;&#29616;&#23427;&#30340;&#34920;&#36798;&#33021;&#21147;&#36828;&#27604;&#24819;&#35937;&#20013;&#26356;&#39640;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-06">iOS &#24320;&#21457; 2015-2025</a></strong></h3><p>&#36825;&#26159;&#19968;&#37096;&#29992;&#21313;&#24180;&#26102;&#20809;&#20889;&#23601;&#30340;&#20010;&#20154;&#25216;&#26415;&#32534;&#24180;&#21490;&#65292;&#20063;&#26159;&#19968;&#20221;&#20851;&#20110; iOS &#29983;&#24577;&#28436;&#36827;&#30340;&#29645;&#36149;&#35760;&#24405;&#12290;&#20174; 2015 &#24180;&#30340; Auto Layout &#36866;&#37197;&#12289;&#32452;&#20214;&#21270;&#28010;&#28526;&#65292;&#21040; 2025 &#24180;&#30340; Liquid Glass &#19982; AI Agent&#65292;<a href="https://x.com/daiming_cn">&#25140;&#38125;</a> &#20197;&#20146;&#21382;&#32773;&#30340;&#35270;&#35282;&#65292;&#20018;&#32852;&#36215;&#25216;&#26415;&#21464;&#36801;&#12289;&#31038;&#21306;&#25925;&#20107;&#19982;&#24037;&#31243;&#23454;&#36341;&#12290;&#25991;&#20013;&#26082;&#26377;&#23545;&#24213;&#23618;&#21407;&#29702;&#30340;&#28145;&#25366;&#65288;&#22914; dyld&#12289;Runtime&#12289;&#24615;&#33021;&#20248;&#21270;&#65289;&#65292;&#20063;&#26377;&#23545;&#25216;&#26415;&#21069;&#36744;&#30340;&#28145;&#20999;&#22238;&#26395;&#12290;&#20316;&#32773;&#35748;&#20026;&#65306;&#24213;&#23618;&#21407;&#29702;&#27704;&#36828;&#19981;&#36807;&#26102;&#65307;&#19981;&#35201;&#34987;&#26032;&#25216;&#26415;&#28966;&#34385;&#32465;&#26550;&#65307;&#25216;&#26415;&#22312;&#21464;&#65292;&#20294;&#23398;&#20064;&#30340;&#26041;&#27861;&#27809;&#21464;&#12290;&#20445;&#25345;&#22909;&#22855;&#19982;&#23398;&#20064;&#65292;&#26041;&#33021;&#22374;&#28982;&#38754;&#23545;&#26356;&#22810;&#30340;&#21313;&#24180;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-07">Xcode Assistant Copilot Server</a></strong></h3><p>Xcode 26.3 &#24341;&#20837;&#20102;&#23545; Codex &#19982; Claude Code &#30340;&#25903;&#25345;&#65292;&#23558;&#26234;&#33021;&#20307;&#33021;&#21147;&#27491;&#24335;&#24102;&#20837; IDE &#24037;&#20316;&#27969;&#12290;&#20294;&#24182;&#38750;&#27599;&#20301;&#24320;&#21457;&#32773;&#37117;&#20351;&#29992;&#36825;&#20123;&#26381;&#21153;&#12290;&#30001; <a href="https://x.com/fercabj">Fernando Romiti</a> &#24320;&#21457;&#30340; Xcode Assistant Copilot Server &#21017;&#20026; GitHub Copilot &#35746;&#38405;&#32773;&#25552;&#20379;&#20102;&#19968;&#26465;&#26367;&#20195;&#36335;&#24452;&#12290;&#23427;&#26159;&#19968;&#20010;&#22522;&#20110; Swift &#23454;&#29616;&#30340;&#26412;&#22320;&#26381;&#21153;&#65292;&#23558; Xcode &#30340; OpenAI &#20860;&#23481;&#35831;&#27714;&#36716;&#35793;&#20026; Copilot API &#35843;&#29992;&#12290;<strong>&#20294;&#19981;&#35201;&#23558;&#20854;&#35823;&#35299;&#20026;&#19968;&#20010;&#31616;&#21333;&#30340;&#25509;&#21475;&#36716;&#25442;&#23618;&#12290;</strong></p><p>&#22312;&#40664;&#35748;&#27169;&#24335;&#19979;&#65292;&#23427;&#30830;&#23454;&#20805;&#24403;&#36879;&#26126;&#20195;&#29702;&#65292;&#23558; Xcode &#30340; <code>/v1/chat/completions</code> &#35831;&#27714;&#36716;&#21457;&#33267; GitHub Copilot API&#65307;&#28982;&#32780;&#19968;&#26086;&#21551;&#29992; Agent &#27169;&#24335;&#24182;&#37197;&#32622; MCP&#65292;&#23427;&#20415;&#20250;&#22312;&#26412;&#22320;&#36816;&#34892;&#23436;&#25972;&#30340; agent loop&#12290;&#24403; Copilot &#27169;&#22411;&#21457;&#36215; tool call &#26102;&#65292;Server &#20250;&#22312;&#26412;&#22320;&#25318;&#25130;&#35843;&#29992;&#65292;&#36890;&#36807; <code>xcrun mcpbridge</code> &#25110;&#20801;&#35768;&#30340; CLI &#24037;&#20855;&#25191;&#34892;&#30456;&#24212;&#25805;&#20316;&#65292;&#23558;&#25191;&#34892;&#32467;&#26524;&#36861;&#21152;&#33267;&#23545;&#35805;&#19978;&#19979;&#25991;&#65292;&#20877;&#27425;&#35831;&#27714;&#27169;&#22411;&#25512;&#29702;&#65292;&#30452;&#33267;&#29983;&#25104;&#26368;&#32456;&#21709;&#24212;&#65292;&#26368;&#21518;&#25165;&#23558;&#32467;&#26524;&#36820;&#22238;&#32473; Xcode&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-08">Foundation Models SDK for Python</a></strong></h3><p>Foundation Models SDK for Python &#26159;&#33529;&#26524;&#23448;&#26041;&#36817;&#26399;&#25512;&#20986;&#30340;&#19968;&#20010;&#24320;&#28304;&#39033;&#30446;&#12290;&#23427;&#22312;&#24213;&#23618;&#36890;&#36807; Swift &#26725;&#25509;&#65292;&#35753;&#24320;&#21457;&#32773;&#33021;&#22815;<strong>&#30452;&#25509;&#22312; Python &#29615;&#22659;&#20013;&#35843;&#29992; macOS &#26412;&#22320;&#65288;On-Device&#65289;&#30340; Apple Intelligence &#22522;&#30784;&#27169;&#22411;</strong>&#12290;</p><p>&#22312;&#29616;&#20195;&#22823;&#27169;&#22411;&#24212;&#29992;&#24320;&#21457;&#20013;&#65292;&#35780;&#27979;&#65288;Evaluation&#65289;&#26159;&#26497;&#20854;&#37325;&#35201;&#30340;&#19968;&#29615;&#12290;&#24320;&#21457;&#32773;&#38656;&#35201;&#36816;&#34892;&#22823;&#37327;&#30340;&#27979;&#35797;&#29992;&#20363;&#65292;&#29992;&#21508;&#31181;&#27979;&#35797;&#38598;&#21435;&#39564;&#35777; Prompt &#35843;&#25972;&#25110;&#24037;&#20855;&#35843;&#29992;&#30340;&#20934;&#30830;&#29575;&#65292;&#32780;&#36825;&#20123;&#25968;&#25454;&#39537;&#21160;&#30340;&#24037;&#20316;&#22312;&#19994;&#30028;&#19968;&#30452;&#26159;&#30001; Python &#29983;&#24577;&#20027;&#23548;&#12290;&#35813; SDK &#24688;&#22909;&#22635;&#34917;&#20102;&#36825;&#19968;&#31354;&#30333;&#65306;&#24320;&#21457;&#32773;&#21487;&#20197;&#26080;&#32541;&#23454;&#29616;&#20174; Swift &#31471;&#23548;&#20986;&#30495;&#23454;&#36816;&#34892;&#30340; transcript&#65288;JSON&#65289;&#65292;&#28982;&#21518;&#22312; Python &#31471;&#21033;&#29992;&#35813; SDK &#21407;&#29983;&#22797;&#29616;&#31471;&#20391;&#30340;&#25512;&#29702;&#36807;&#31243;&#65292;&#24182;&#20687;&#22788;&#29702;&#26222;&#36890;&#25968;&#25454;&#19968;&#26679;&#36827;&#34892;&#25209;&#37327;&#20998;&#26512;&#12289;&#25171;&#20998;&#12289;&#32858;&#31867;&#19982;&#35823;&#24046;&#24402;&#22240;&#12290;</p><blockquote><p>&#36825;&#22522;&#26412;&#31561;&#20110; Apple &#22312;&#21521;&#24320;&#21457;&#32773;&#26126;&#31034;&#19968;&#31181;&#26631;&#20934;&#21270;&#30340; AI &#24212;&#29992;&#24320;&#21457;&#33539;&#24335;&#65306;<strong>Swift &#36127;&#36131;&#32447;&#19978;&#20307;&#39564;&#19982;&#31471;&#20391;&#38598;&#25104;&#65307;Python &#36127;&#36131;&#31163;&#32447;&#35780;&#27979;&#19982;&#36845;&#20195;&#20248;&#21270;&#12290;</strong></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0125-09">vphone-cli&#65306;&#22312; Mac &#19978;&#36816;&#34892;&#19968;&#21488;&#30495;&#23454;&#30340; iPhone</a></strong></h3><p>2024 &#24180; Apple &#21457;&#24067; Apple Intelligence &#26102;&#65292;&#21516;&#27493;&#25512;&#20986;&#20102; PCC&#65288;Private Cloud Compute&#65289;&#65306;&#19968;&#22871;&#36816;&#34892;&#22312; Apple Silicon &#26381;&#21153;&#22120;&#19978;&#30340;&#38544;&#31169;&#35745;&#31639;&#22522;&#30784;&#35774;&#26045;&#12290;&#23427;&#30340;&#29305;&#21035;&#20043;&#22788;&#19981;&#21482;&#26159;&#8221;&#25226; AI &#35831;&#27714;&#25918;&#21040;&#20113;&#31471;&#22788;&#29702;&#8221;&#65292;&#32780;&#26159;&#25226; iPhone&#37027;&#22871;&#23433;&#20840;&#27169;&#22411;&#24310;&#20280;&#21040;&#20102;&#26381;&#21153;&#22120;&#20391;&#12290;&#20026;&#27492;&#65292;Apple &#36824;&#32597;&#35265;&#22320;&#24320;&#25918;&#20102;&#30740;&#31350;&#26448;&#26009;&#21644;&#34394;&#25311;&#30740;&#31350;&#29615;&#22659;&#65292;&#20801;&#35768;&#23433;&#20840;&#30740;&#31350;&#21592;&#22312;&#26412;&#22320;&#23457;&#35745; PCC &#33410;&#28857;&#30340;&#36719;&#20214;&#26632;&#12290;</p><p>&#20174; cloudOS 26 &#24320;&#22987;&#65292;&#33529;&#26524;&#22312; PCC &#22266;&#20214;&#20013;&#26032;&#22686;&#20102;&#19982; vphone600ap &#30456;&#20851;&#30340;&#32452;&#20214;&#12290;&#31038;&#21306;&#30340;&#26497;&#23458;&#20204;&#25935;&#38160;&#22320;&#25235;&#20303;&#20102;&#36825;&#20010;&#22865;&#26426;&#65292;&#22522;&#20110; <a href="https://x.com/wh1te4ever">Hyungyu Seo</a> &#31561;&#20154; <a href="https://github.com/wh1te4ever/super-tart-vphone-writeup">&#23545;&#35813;&#34394;&#25311;&#21270;&#26426;&#21046;&#30340;&#30828;&#26680;&#36870;&#21521;&#30740;&#31350;</a>&#65292;<a href="https://x.com/Lakr233">Lakr</a> &#24320;&#21457;&#30340; vphone-cli &#23558;&#20854;&#24443;&#24213;&#24037;&#31243;&#21270;&#65306;&#36890;&#36807;&#35843;&#29992; <code>Virtualization.framework</code> &#30340;&#31169;&#26377; API&#65292;&#30452;&#25509;&#22312; Mac &#19978;&#25645;&#20986;&#19968;&#22871;&#23436;&#25972;&#30340;&#34394;&#25311; iPhone &#30740;&#31350;&#29615;&#22659;&#12290;&#21644; Xcode &#27169;&#25311;&#22120;&#19981;&#21516;&#65292;&#36825;&#37324;&#36305;&#30340;&#26159;&#30495;&#23454;&#30340; iOS &#22266;&#20214;&#65292;&#23436;&#25972;&#30340;&#21551;&#21160;&#38142;&#20250;&#20174;&#22836;&#36208;&#19968;&#36941;&#12290;</p><blockquote><p>&#26377;&#24847;&#24605;&#30340;&#22320;&#26041;&#19981;&#21482;&#26159;&#36234;&#29425;&#25110;&#22266;&#20214;&#30740;&#31350;&#26412;&#36523;&#65292;&#26356;&#22312;&#20110;&#20174; PCC &#21040;&#36825;&#19968;&#31867;&#34394;&#25311;&#21270;&#24037;&#20855;&#25152;&#36879;&#38706;&#20986;&#30340;&#24213;&#23618;&#26041;&#21521;&#65306;Apple &#27491;&#22312;&#25226;&#23427;&#21313;&#22810;&#24180;&#26469;&#22312;&#31227;&#21160;&#31471;&#31215;&#32047;&#30340; iOS &#23433;&#20840;&#26550;&#26500;&#65292;&#24443;&#24213;&#22806;&#28322;&#24182;&#37325;&#22609;&#20113;&#31471;&#35745;&#31639;&#22522;&#30784;&#35774;&#26045;&#12290;</p></blockquote><h2><strong>&#27963;&#21160;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0125-10">LET&#8217;S VISION 2026&#65292;&#24320;&#31080;&#21862;&#65281;</a></strong></h3><p>&#20316;&#20026;&#22312;&#20013;&#22269;&#20030;&#21150;&#12289;&#38754;&#21521;&#20840;&#29699;&#30340; Apple &#29983;&#24577;&#19979;&#30340;&#22823;&#20250;&#65292;&#20170;&#24180;&#30340; LET&#8217;S VISION &#23558;&#20250;&#26377;&#32422; 20 &#22330;&#28436;&#35762;&#12289;&#36229;&#36807; 80 &#20010;&#23637;&#20301;&#65292;&#27426;&#36814;&#21069;&#24448;&#23448;&#32593;&#21644;&#31080;&#21153;&#24179;&#21488;&#20102;&#35299;&#26356;&#22810;&#20449;&#24687;&#12290;</p><ul><li><p><strong>&#26102;&#38388;&#21450;&#22320;&#28857;</strong>&#65306;03.28 - 03.29&#65292;&#19978;&#28023;&#183;&#28437;&#27827;&#27902;&#20250;&#35758;&#20013;&#24515;</p></li><li><p><strong><a href="https://letsvision.swiftgg.team/">&#27963;&#21160;&#23448;&#32593;</a></strong></p></li><li><p><strong><a href="https://l.fatbobman.com/w0125-10">&#33719;&#21462;&#38376;&#31080;</a></strong></p></li></ul>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #124]]></title><description><![CDATA[The Spring Festival Gala, Robots, AI, and LLMs]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-124</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-124</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 23 Feb 2026 12:03:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PoXb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.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_!PoXb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PoXb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 424w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 848w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 1272w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PoXb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.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;:106124,&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/188874352?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.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_!PoXb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 424w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 848w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.webp 1272w, https://substackcdn.com/image/fetch/$s_!PoXb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fa3a993-5717-45e8-a908-a12bf5516b70_1622x912.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"><svg role="img" 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"><g><title></title><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"><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"><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>The Spring Festival Gala, Robots, AI, and LLMs</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-124/">Read on web &#8594;</a></p><p>As a television program with over a billion viewers, the China Central Television&#8217;s Spring Festival Gala is undoubtedly an exceptional showcase platform. In this year&#8217;s Gala, multiple Chinese robotics manufacturers presented their products in various performances, among which Unitree&#8217;s humanoid robots caught the most attention. During the show, multiple models of these humanoid robots executed a series of highly complex martial arts and dynamic movements. Compared to the more static, stationary displays of last year, the complexity and stability of their movements have seen a significant leap&#8212;a progress that has drawn attention from global media.</p><p>Following the Gala, discussions on social media showed a clear divide. Alongside the amazement at the technological progress, there was no shortage of skeptical voices dismissing the performance as &#8220;pre-programmed,&#8221; &#8220;lacking AI,&#8221; or &#8220;impractical.&#8221; To a certain extent, this reflects the public&#8217;s underestimation of the sheer complexity of robotics&#8212;especially a lack of awareness regarding the difficulties of motion control, real-time feedback systems, and system-level integration.</p><p>One point needs clarification: pre-trained does not equal &#8220;record-and-playback.&#8221; It is true that humanoid robots currently employ highly orchestrated movement sequences in such performances, but this shares a similar logic with the training of human dancers or athletes. Extensive offline training and rehearsal form the foundation of the movements, but during actual execution, the &#8220;body&#8221; must still rely on dynamic balance and real-time corrections to cope with real-world disturbances. It is precisely this fault tolerance and real-time repair capability that allows humanoid robots&#8212;a naturally unstable bipedal system&#8212;to pull off highly dynamic, continuous movements.</p><p>Meanwhile, the explosion of Large Language Models (LLMs) in recent years has led many to mistakenly equate LLMs with AI as a whole. In reality, AI, a field with decades of history, encompasses far more than just language understanding. Especially when interacting with the real physical world, the usage of specialized models&#8212;such as computer vision, path planning, motion control, and reinforcement learning&#8212;in industrial and physical systems still vastly exceeds that of LLMs. In the realm of robotics, the true ceiling of a system&#8217;s capability is typically determined by its perception systems, control systems, and low-latency feedback algorithms, rather than its language reasoning abilities.</p><p>Even if stronger &#8220;cognitive abilities&#8221; are introduced to humanoid robots in the future, the better path may not necessarily be directly plugging in an LLM. Instead, it will likely involve building World Models that inherently understand the laws of physics, paired with control systems capable of low-latency responses&#8212;two areas that happen to be inherent weaknesses of LLMs. The challenges of Embodied AI are fundamentally different from pure text reasoning.</p><p>As for the issue of &#8220;practicality,&#8221; kung fu or dancing indeed hardly correspond directly to real-world job scenarios. However, it is precisely these movements&#8212;which demand extreme balance, coordination, and dynamic response&#8212;that provide the perfect validation ground for highly complex and unstable systems like humanoid robots. They function as engineering stress tests, demonstrating the maturity of mechanical design, electronic control, and algorithmic integration, rather than proving short-term commercial viability.</p><p>Personally, I remain cautious about the future market size for humanoid robots. There is often a significant chasm between technological breakthroughs and widespread commercial adoption. Nevertheless, judging by the magnitude of progress showcased at this year&#8217;s Gala, it is reasonable to conclude that within the next decade, robots or smart machines integrating into our daily work and living environments is no longer just sci-fi imagination. Whether you like &#8220;robots&#8221; or not, the trajectory of technological evolution is unmistakably clear: we will eventually need to coexist with them.</p><p>As for the apocalyptic scenario of &#8220;robots enslaving humanity,&#8221; I&#8217;m not worried about that for now. My more realistic concern is this: if they encounter a bug at work and swing a punch at me, I genuinely couldn&#8217;t take the hit.</p><p><a href="https://fatbobman.com/en/weekly/issue-123/">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/w0124-01">How to Migrate to @Observable Without Breaking Your App</a></strong></h3><p>As more apps raise their minimum deployment target to iOS 17, <code>@Observable</code> is replacing <code>ObservableObject</code> as the new state management foundation. However, when a project has deeply relied on <code>ObservableObject</code> + <code>@Published</code>, migration is far from a simple macro substitution. <a href="https://x.com/PawelKozielecki">Pawel Kozielecki</a> draws on a real-world migration experience to systematically walk through the correct usage of property wrappers in the new system &#8212; using <code>@State</code> for lifecycle management, <code>@Bindable</code> for two-way bindings, and plain properties for read-only access &#8212; while highlighting easily overlooked details such as <code>@ObservationIgnored</code> and computed property tracking blind spots. The real challenge of migration was never about syntax; it&#8217;s about truly understanding who owns the view model&#8217;s lifecycle.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-02">Testing with Event Streams</a></strong></h3><p>Although Swift Testing offers a rich assertion API, in practice you&#8217;ll find there&#8217;s no single tool that fully corresponds to XCTest&#8217;s ability to verify that multiple callbacks are triggered in order (<code>fulfillment</code> + <code>enforceOrder</code>). <code>confirmation</code> requires nesting and cannot directly validate trigger order. <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> proposes an approach that better fits Swift&#8217;s concurrency model: using <code>AsyncStream</code> to collect events, wrapped in a lightweight <code>EventStream</code> type &#8212; yielding event identifiers when callbacks fire, then calling <code>collect</code> at the end to retrieve the full event sequence for comparison against an expected array. As for why not just use a plain array, Matt provides a compelling answer: when <code>@Sendable</code> constraints or inconsistent actor isolation are involved, writing directly to an array creates concurrency safety issues, whereas the <code>AsyncStream</code>-based approach naturally conforms to the concurrency model.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-03">If You&#8217;re Not Versioning Your SwiftData Schema, You&#8217;re Gambling</a></strong></h3><p>SwiftData&#8217;s declarative syntax and automatic migration capabilities make it easy to fall into the trap of thinking &#8220;the framework will handle everything.&#8221; The reality is that once your model structure changes &#8212; adding fields, renaming, adjusting relationships &#8212; without an explicit schema version and migration plan, you&#8217;re left relying on implicit inference. When that inference fails, the result is rarely a graceful migration; more often it&#8217;s crashes, data loss, or an app that won&#8217;t launch. <a href="https://x.com/azamsharp">Mohammad Azam</a> offers direct, pragmatic advice: explicitly declare <code>Schema</code> versions; prepare migration paths for future structural changes; and treat migration design as part of model design, not an afterthought.</p><blockquote><p>This advice applies equally to Core Data. Even when a model is fully compatible with lightweight migration, creating a corresponding model version file for each release (whenever structural changes occur) not only helps track the model&#8217;s evolution but also enables clear, controlled rollback when issues arise. Using explicit versioning to govern model evolution is fundamentally about establishing safety boundaries for long-term maintenance.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-04">How to build a simple CLI tool using Swift</a></strong></h3><p>There&#8217;s an interesting phenomenon in the age of AI Coding: CLI tools are experiencing a renaissance &#8212; more and more developers are building CLI tools to power their MCP and Agent workflows. <a href="https://x.com/tanaschita">Natascha Fadeeva</a> walks through how to build structured command-line tools using Swift Package Manager and Apple&#8217;s official ArgumentParser library: defining root commands and subcommands, handling async network requests, and compiling to a standalone distributable binary. For iOS developers already fluent in Swift, this path is more natural than maintaining a bash or Python script, and easier to evolve alongside the project.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-05">Navigation Notes &#8211; Agentic coding</a></strong></h3><p>As an experienced developer, <a href="https://mastodon.social/@heckj">Joseph Heck</a> observes that as AI becomes capable of executing tasks, generating code, and driving changes autonomously, the developer&#8217;s role shifts from &#8220;line-by-line implementer&#8221; to &#8220;path navigator.&#8221; The truly scarce skill is no longer coding speed, but navigation &#8212; how developers maintain their sense of direction in complex codebases and multi-agent environments. Joseph offers several practical suggestions: always include &#8220;ask me about anything ambiguous&#8221; in your prompts; have the agent draft a plan and get your approval before implementation; provide deterministic feedback loops (unit tests, compiler errors) that allow the agent to self-correct; and distill frequently reused instructions into Skill files.</p><p>Heck avoids amplifying the &#8220;AI will disrupt developers&#8221; narrative, instead emphasizing a more grounded reality: agentic coding amplifies existing engineering capabilities. If you&#8217;re already good at modular design and abstraction, AI will accelerate you. If your sense of boundaries is fuzzy, AI will just create chaos faster.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-06">Setting up a delivery pipeline for your agentic iOS projects</a></strong></h3><p>When code generation, modification, and refactoring begin to be driven by agents, is the traditional CI/CD pipeline still sufficient? <a href="https://x.com/donnywals">Donny Wals</a> opens with a real experience: his app crashed mid-workout at the gym, he handed the crash report to an agent for analysis, and by the time he finished training, a PR was waiting. After merging, a TestFlight build landed shortly after. Around this experience, he systematically outlines how to build a reliable delivery pipeline for agentic iOS projects &#8212; one that keeps automated changes controllable, verifiable, and releasable.</p><p>The article&#8217;s focus isn&#8217;t on any specific tool, but on pipeline design itself. Donny emphasizes that code generated by agents is fundamentally &#8220;a change that hasn&#8217;t been reviewed line by line,&#8221; which makes clear quality gates all the more important: automated testing, continuous integration, and the release pipeline must bear ultimate responsibility for delivery. Agents can significantly accelerate implementation, but engineering discipline cannot be relaxed in kind &#8212; when velocity increases, control mechanisms become even more critical.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-07">Tracking Token Usage in Foundation Models</a></strong></h3><p>Apple&#8217;s Foundation Models run on-device with a context window of just 4,096 tokens &#8212; once exceeded, the conversation cannot continue. iOS 26.4 introduces token usage tracking APIs to help developers monitor context consumption in real time. <a href="https://x.com/iosartem">Artem Novichkov</a> covers four key metrics: total model context capacity (<code>contextSize</code>), token consumption for Instructions, consumption for individual Prompts, and cumulative usage for the full conversation Transcript. The article also highlights an easily overlooked detail: when a Tool is introduced, its name, description, and argument schema are serialized and counted toward the token budget &#8212; the same Instructions jump from 16 to 79 tokens once a Tool is attached. For on-device models, token observability will become essential infrastructure for optimizing the user experience.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0124-08">App Store Connect CLI</a></strong></h3><p>App Store Connect CLI is an unofficial App Store Connect command-line tool developed by <a href="https://x.com/rudrank">Rudrank Riyam</a>, covering the full release pipeline: TestFlight management, build uploads, code signing, screenshot automation, localization sync, app review submission, notarization, and financial report downloads. The tool was designed from the ground up with agent scenarios in mind and includes dedicated documentation for agent-oriented workflows. If your release pipeline centers on TestFlight, metadata, submission, signing, and CI automation, ASC is worth considering as a lightweight alternative to fastlane.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-09">GRDB 7.10.0: Android, Linux, and Windows Support</a></strong></h3><p>GRDB 7.10.0 is a milestone release: it formally introduces support for Android, Linux, and Windows, and adds the ability to use SQLCipher (encrypted databases) via Swift Package Manager &#8212; two long-awaited features from the community. This marks a meaningful evolution for Swift&#8217;s most mature SQLite wrapper, from an Apple-platform tool into a truly cross-platform data layer solution.</p><p><a href="https://x.com/groue">Gwendal Rou&#233;</a> notes in the <a href="https://forums.swift.org/t/grdb-v7-10-0-android-linux-windows-and-sqlcipher-swiftpm/84754">release announcement</a> that because Xcode does not yet support package traits, SwiftPM will still download unused dependencies; until this is resolved, SQLCipher support will continue to require a fork.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-10">Swift System Metrics</a></strong></h3><p>Swift System Metrics provides Swift applications &#8212; particularly server-side projects &#8212; with unified system-level metrics collection: CPU utilization, memory usage, file descriptor counts, and more, exposed through a standardized Metrics interface that integrates with existing monitoring systems such as Prometheus. It is not a standalone monitoring system, but rather an infrastructure component driven by the Swift Server Work Group, designed to align with the Swift Metrics ecosystem and bring system resource metrics into the same observability stack as application-level metrics. The 1.0 release signals API stability and production readiness. For teams building Swift backend services or investing in Swift observability, this is a foundational piece of the puzzle.</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-124?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-124?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#26149;&#26202;&#12289;&#26426;&#22120;&#20154;&#12289;AI &#19982; LLM</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-124/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20316;&#20026;&#19968;&#20010;&#35266;&#20247;&#25968;&#37327;&#36229;&#21313;&#20159;&#30340;&#30005;&#35270;&#33410;&#30446;&#65292;&#22830;&#35270;&#26149;&#26202;&#26080;&#30097;&#26159;&#26497;&#20339;&#30340;&#23637;&#31034;&#24179;&#21488;&#12290;&#20170;&#24180;&#26149;&#26202;&#20013;&#65292;&#22810;&#23478;&#20013;&#22269;&#26426;&#22120;&#20154;&#21378;&#21830;&#22312;&#19981;&#21516;&#33410;&#30446;&#20013;&#23637;&#31034;&#20102;&#20854;&#20135;&#21697;&#65292;&#20854;&#20013;&#35752;&#35770;&#24230;&#26368;&#39640;&#30340;&#24403;&#23646;&#23431;&#26641;&#65288;Unitree&#65289;&#30340;&#20154;&#24418;&#26426;&#22120;&#20154;&#12290;&#22312;&#34920;&#28436;&#29615;&#33410;&#65292;&#22810;&#27454;&#22411;&#21495;&#30340;&#20154;&#24418;&#26426;&#22120;&#20154;&#23436;&#25104;&#20102;&#22823;&#37327;&#36739;&#20026;&#22797;&#26434;&#30340;&#27494;&#26415;&#19982;&#21160;&#24577;&#21160;&#20316;&#23637;&#31034;&#12290;&#19982;&#21435;&#24180;&#20559;&#38745;&#24577;&#12289;&#20559;&#31449;&#26729;&#24335;&#30340;&#21576;&#29616;&#30456;&#27604;&#65292;&#20170;&#24180;&#30340;&#21160;&#20316;&#22797;&#26434;&#24230;&#19982;&#31283;&#23450;&#24615;&#30830;&#23454;&#26377;&#26126;&#26174;&#25552;&#21319;&#65292;&#36825;&#19968;&#28857;&#20063;&#24471;&#21040;&#20102;&#20840;&#29699;&#23186;&#20307;&#30340;&#20851;&#27880;&#19982;&#25253;&#36947;&#12290;</p><p>&#26149;&#26202;&#20043;&#21518;&#65292;&#31038;&#20132;&#23186;&#20307;&#19978;&#30340;&#35752;&#35770;&#21576;&#29616;&#20986;&#26126;&#26174;&#20998;&#21270;&#12290;&#38500;&#20102;&#23545;&#25216;&#26415;&#36827;&#27493;&#30340;&#24778;&#21497;&#20043;&#22806;&#65292;&#8220;&#39044;&#32534;&#31243;&#8221;&#12289;&#8220;&#27809;&#26377; AI&#8221;&#12289;&#8220;&#32570;&#20047;&#23454;&#29992;&#24615;&#8221;&#31561;&#36136;&#30097;&#22768;&#38899;&#21516;&#26679;&#19981;&#23569;&#12290;&#36825;&#22312;&#19968;&#23450;&#31243;&#24230;&#19978;&#21453;&#26144;&#20102;&#20844;&#20247;&#23545;&#26426;&#22120;&#20154;&#25216;&#26415;&#22797;&#26434;&#24230;&#30340;&#20302;&#20272;&#8212;&#8212;&#23588;&#20854;&#26159;&#23545;&#36816;&#21160;&#25511;&#21046;&#12289;&#23454;&#26102;&#21453;&#39304;&#31995;&#32479;&#21644;&#31995;&#32479;&#32423;&#25972;&#21512;&#38590;&#24230;&#30340;&#35748;&#30693;&#19981;&#36275;&#12290;</p><p>&#38656;&#35201;&#28548;&#28165;&#30340;&#19968;&#28857;&#26159;&#65306;&#39044;&#35757;&#32451;&#24182;&#19981;&#31561;&#20110;&#8220;&#24405;&#21046;-&#22238;&#25918;&#8221;&#12290;&#24403;&#21069;&#20154;&#24418;&#26426;&#22120;&#20154;&#22312;&#27492;&#31867;&#34920;&#28436;&#20013;&#30340;&#30830;&#37319;&#29992;&#20102;&#39640;&#24230;&#35268;&#21010;&#30340;&#21160;&#20316;&#27969;&#31243;&#65292;&#36825;&#19982;&#20154;&#31867;&#33310;&#32773;&#12289;&#36816;&#21160;&#21592;&#30340;&#35757;&#32451;&#36923;&#36753;&#26377;&#30456;&#36890;&#20043;&#22788;&#8212;&#8212;&#22823;&#37327;&#30340;&#31163;&#32447;&#35757;&#32451;&#19982;&#35843;&#35797;&#26500;&#25104;&#20102;&#21160;&#20316;&#30340;&#22522;&#30784;&#65292;&#20294;&#22312;&#23454;&#38469;&#25191;&#34892;&#36807;&#31243;&#20013;&#65292;&#36523;&#20307;&#20173;&#38656;&#20381;&#36182;&#21160;&#24577;&#24179;&#34913;&#19982;&#21363;&#26102;&#20462;&#27491;&#26469;&#24212;&#23545;&#30495;&#23454;&#29615;&#22659;&#30340;&#25200;&#21160;&#12290;&#27491;&#26159;&#36825;&#31181;&#23481;&#38169;&#19982;&#23454;&#26102;&#20462;&#22797;&#33021;&#21147;&#65292;&#25165;&#35753;&#20154;&#24418;&#26426;&#22120;&#20154;&#36825;&#20010;&#22825;&#28982;&#19981;&#31283;&#23450;&#30340;&#21452;&#36275;&#31995;&#32479;&#24471;&#20197;&#23436;&#25104;&#39640;&#21160;&#24577;&#30340;&#36830;&#32493;&#21160;&#20316;&#12290;</p><p>&#19982;&#27492;&#21516;&#26102;&#65292;&#36817;&#24180;&#26469;&#22823;&#35821;&#35328;&#27169;&#22411;&#65288;LLM&#65289;&#30340;&#29190;&#21457;&#65292;&#35753;&#19981;&#23569;&#20154;&#23558; LLM &#19982; AI &#31561;&#21516;&#36215;&#26469;&#12290;&#20107;&#23454;&#19978;&#65292;AI &#20316;&#20026;&#19968;&#20010;&#24050;&#26377;&#25968;&#21313;&#24180;&#21457;&#23637;&#30340;&#39046;&#22495;&#65292;&#36828;&#36828;&#19981;&#27490;&#35821;&#35328;&#29702;&#35299;&#36825;&#19968;&#20998;&#25903;&#12290;&#23588;&#20854;&#26159;&#38754;&#23545;&#30495;&#23454;&#30340;&#29289;&#29702;&#19990;&#30028;&#26102;&#65292;&#35270;&#35273;&#35782;&#21035;&#12289;&#36335;&#24452;&#35268;&#21010;&#12289;&#36816;&#21160;&#25511;&#21046;&#12289;&#24378;&#21270;&#23398;&#20064;&#31561;&#19987;&#29992;&#27169;&#22411;&#22312;&#24037;&#19994;&#19982;&#23454;&#20307;&#31995;&#32479;&#20013;&#30340;&#20351;&#29992;&#37327;&#65292;&#20381;&#28982;&#36828;&#39640;&#20110; LLM&#12290;&#22312;&#26426;&#22120;&#20154;&#39046;&#22495;&#65292;&#30495;&#27491;&#20915;&#23450;&#33021;&#21147;&#19978;&#38480;&#30340;&#24448;&#24448;&#26159;&#24863;&#30693;&#31995;&#32479;&#12289;&#25511;&#21046;&#31995;&#32479;&#20197;&#21450;&#20302;&#24310;&#36831;&#21453;&#39304;&#31639;&#27861;&#65292;&#32780;&#19981;&#26159;&#35821;&#35328;&#25512;&#29702;&#33021;&#21147;&#12290;</p><p>&#21363;&#20415;&#26410;&#26469;&#20026;&#20154;&#24418;&#26426;&#22120;&#20154;&#24341;&#20837;&#26356;&#24378;&#30340;&#8221;&#35748;&#30693;&#33021;&#21147;&#8221;&#65292;&#26356;&#36866;&#21512;&#30340;&#36335;&#24452;&#20063;&#26410;&#24517;&#26159;&#30452;&#25509;&#25509;&#20837; LLM&#65292;&#32780;&#21487;&#33021;&#26159;&#26500;&#24314;&#33021;&#29702;&#35299;&#29289;&#29702;&#35268;&#24459;&#30340;&#19990;&#30028;&#27169;&#22411;&#65288;World Models&#65289;&#19982;&#20855;&#22791;&#20302;&#24310;&#36831;&#21709;&#24212;&#33021;&#21147;&#30340;&#25511;&#21046;&#31995;&#32479;&#8212;&#8212;&#36825;&#20004;&#28857;&#24688;&#24688;&#26159; LLM &#30340;&#22266;&#26377;&#30701;&#26495;&#12290;&#20855;&#36523;&#26234;&#33021;&#65288;Embodied AI&#65289;&#30340;&#25361;&#25112;&#65292;&#19982;&#32431;&#25991;&#26412;&#25512;&#29702;&#23384;&#22312;&#26412;&#36136;&#24046;&#24322;&#12290;</p><p>&#33267;&#20110;&#8220;&#23454;&#29992;&#24615;&#8221;&#30340;&#38382;&#39064;&#65292;&#21151;&#22827;&#25110;&#33310;&#36424;&#30830;&#23454;&#38590;&#20197;&#30452;&#25509;&#23545;&#24212;&#29616;&#23454;&#24037;&#20316;&#22330;&#26223;&#12290;&#20294;&#24688;&#24688;&#26159;&#36825;&#20123;&#23545;&#24179;&#34913;&#24615;&#12289;&#21327;&#35843;&#24615;&#19982;&#21160;&#24577;&#21709;&#24212;&#35201;&#27714;&#26497;&#39640;&#30340;&#21160;&#20316;&#65292;&#20026;&#20154;&#24418;&#26426;&#22120;&#20154;&#36825;&#31181;&#39640;&#24230;&#22797;&#26434;&#19988;&#19981;&#31283;&#23450;&#30340;&#31995;&#32479;&#25552;&#20379;&#20102;&#26497;&#20339;&#30340;&#39564;&#35777;&#22330;&#26223;&#12290;&#23427;&#20204;&#26356;&#20687;&#26159;&#24037;&#31243;&#33021;&#21147;&#30340;&#21387;&#21147;&#27979;&#35797;&#65292;&#23637;&#31034;&#30340;&#26159;&#26426;&#26800;&#35774;&#35745;&#12289;&#30005;&#23376;&#25511;&#21046;&#19982;&#31639;&#27861;&#31995;&#32479;&#25972;&#21512;&#30340;&#25104;&#29087;&#24230;&#65292;&#32780;&#38750;&#30701;&#26399;&#21830;&#19994;&#33853;&#22320;&#33021;&#21147;&#12290;</p><p>&#25105;&#20010;&#20154;&#23545;&#20110;&#20154;&#24418;&#26426;&#22120;&#20154;&#26410;&#26469;&#30340;&#24066;&#22330;&#35268;&#27169;&#20173;&#28982;&#25345;&#23457;&#24910;&#24577;&#24230;&#12290;&#25216;&#26415;&#36827;&#27493;&#19982;&#21830;&#19994;&#26222;&#21450;&#20043;&#38388;&#24448;&#24448;&#23384;&#22312;&#19981;&#23567;&#30340;&#40511;&#27807;&#12290;&#20294;&#20174;&#20170;&#24180;&#26149;&#26202;&#25152;&#21576;&#29616;&#30340;&#36827;&#27493;&#24133;&#24230;&#26469;&#30475;&#65292;&#21487;&#20197;&#21512;&#29702;&#21028;&#26029;&#65306;&#22312;&#26410;&#26469;&#21313;&#24180;&#20869;&#65292;&#26426;&#22120;&#20154;&#25110;&#26234;&#33021;&#26426;&#22120;&#20197;&#26576;&#31181;&#24418;&#24335;&#34701;&#20837;&#26085;&#24120;&#24037;&#20316;&#19982;&#29983;&#27963;&#22330;&#26223;&#65292;&#24050;&#19981;&#20877;&#26159;&#31185;&#24187;&#24819;&#35937;&#12290;&#26080;&#35770;&#20320;&#26159;&#21542;&#21916;&#27426;&#8220;&#26426;&#22120;&#20154;&#8221;&#65292;&#25216;&#26415;&#28436;&#36827;&#30340;&#36235;&#21183;&#24050;&#32463;&#21313;&#20998;&#26126;&#30830;&#65292;&#25105;&#20204;&#32456;&#23558;&#38656;&#35201;&#19982;&#23427;&#20204;&#20849;&#23384;&#12290;</p><p>&#33267;&#20110;&#8220;&#26426;&#22120;&#20154;&#22900;&#24441;&#20154;&#31867;&#8221;&#30340;&#24773;&#26223;&#65292;&#25105;&#26242;&#26102;&#24182;&#19981;&#25285;&#24515;&#12290;&#25105;&#26356;&#29616;&#23454;&#30340;&#25285;&#24551;&#26159;&#65306;&#22914;&#26524;&#23427;&#20204;&#22312;&#24037;&#20316;&#20013;&#20986;&#29616; Bug&#65292;&#32473;&#25105;&#19968;&#25331;&#65292;&#25105;&#30495;&#30340;&#25384;&#19981;&#20303;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-123/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0124-01">&#22914;&#20309;&#22312;&#19981;&#30772;&#22351; App &#30340;&#21069;&#25552;&#19979;&#36801;&#31227;&#21040; @Observable (How to Migrate to @Observable Without Breaking Your App)</a></strong></h3><p>&#38543;&#30528;&#36234;&#26469;&#36234;&#22810;&#30340;&#24212;&#29992;&#23558;&#26368;&#20302;&#31995;&#32479;&#29256;&#26412;&#25552;&#21319;&#33267; iOS 17&#65292;<code>@Observable</code> &#27491;&#22312;&#21462;&#20195; <code>ObservableObject</code> &#25104;&#20026;&#26032;&#30340;&#29366;&#24577;&#31649;&#29702;&#22522;&#30784;&#35774;&#26045;&#65292;&#20294;&#24403;&#39033;&#30446;&#24050;&#32463;&#28145;&#24230;&#20381;&#36182; <code>ObservableObject</code> + <code>@Published</code> &#26102;&#65292;&#36801;&#31227;&#36828;&#38750;&#31616;&#21333;&#26367;&#25442;&#23439;&#21363;&#21487;&#23436;&#25104;&#12290;<a href="https://x.com/PawelKozielecki">Pawel Kozielecki</a> &#32467;&#21512;&#19968;&#27425;&#30495;&#23454;&#30340;&#36801;&#31227;&#36393;&#22353;&#32463;&#21382;&#65292;&#20174;&#24213;&#23618;&#26426;&#21046;&#24046;&#24322;&#20986;&#21457;&#65292;&#31995;&#32479;&#26803;&#29702;&#20102;&#26032;&#20307;&#31995;&#19979;&#23646;&#24615;&#21253;&#35013;&#22120;&#30340;&#27491;&#30830;&#20351;&#29992;&#26041;&#24335;&#8212;&#8212;&#29992; <code>@State</code> &#31649;&#29702;&#29983;&#21629;&#21608;&#26399;&#12289;&#29992; <code>@Bindable</code> &#22788;&#29702;&#21452;&#21521;&#32465;&#23450;&#12289;&#21482;&#35835;&#22330;&#26223;&#30452;&#25509;&#20351;&#29992;&#26222;&#36890;&#23646;&#24615;&#65292;&#24182;&#29305;&#21035;&#25351;&#20986;&#20102; <code>@ObservationIgnored</code>&#12289;&#35745;&#31639;&#23646;&#24615;&#36861;&#36394;&#30450;&#28857;&#31561;&#23481;&#26131;&#34987;&#24573;&#35270;&#30340;&#32454;&#33410;&#12290;&#36801;&#31227;&#30340;&#38590;&#28857;&#20174;&#26469;&#19981;&#22312;&#35821;&#27861;&#23618;&#38754;&#65292;&#32780;&#22312;&#20110;&#30495;&#27491;&#21400;&#28165;&#8220;&#35841;&#25317;&#26377; view model &#30340;&#29983;&#21629;&#21608;&#26399;&#8221;&#36825;&#19968;&#26681;&#26412;&#38382;&#39064;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-02">&#39564;&#35777;&#22810;&#20010;&#22238;&#35843;&#25353;&#39034;&#24207;&#35302;&#21457; (Testing with Event Streams)</a></strong></h3><p>&#23613;&#31649; Swift Testing &#25552;&#20379;&#20102;&#20016;&#23500;&#30340;&#26029;&#35328; API&#65292;&#20294;&#22312;&#23454;&#38469;&#20351;&#29992;&#20013;&#20320;&#20250;&#21457;&#29616;&#65292;&#24182;&#27809;&#26377;&#19968;&#20010;&#24037;&#20855;&#33021;&#22815;&#23436;&#20840;&#23545;&#24212; XCTest &#20013;&#8220;&#39564;&#35777;&#22810;&#20010;&#22238;&#35843;&#25353;&#39034;&#24207;&#35302;&#21457;&#8221;&#65288;<code>fulfillment</code> + <code>enforceOrder</code>&#65289;&#30340;&#33021;&#21147;&#12290;<code>confirmation</code> &#26082;&#38656;&#35201;&#23884;&#22871;&#20351;&#29992;&#65292;&#20063;&#26080;&#27861;&#30452;&#25509;&#26657;&#39564;&#35302;&#21457;&#39034;&#24207;&#12290;&#23545;&#27492;&#65292;<a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#25552;&#20986;&#20102;&#19968;&#31181;&#26356;&#31526;&#21512; Swift &#24182;&#21457;&#27169;&#22411;&#30340;&#24605;&#36335;&#65306;&#20351;&#29992; <code>AsyncStream</code> &#25910;&#38598;&#20107;&#20214;&#65292;&#24182;&#23553;&#35013;&#20026;&#19968;&#20010;&#36731;&#37327;&#32423;&#30340; <code>EventStream</code> &#31867;&#22411;&#8212;&#8212;&#24403;&#22238;&#35843;&#35302;&#21457;&#26102; <code>yield</code> &#20107;&#20214;&#26631;&#35782;&#65292;&#27979;&#35797;&#32467;&#26463;&#21518;&#36890;&#36807; <code>collect</code> &#33719;&#21462;&#23436;&#25972;&#20107;&#20214;&#24207;&#21015;&#65292;&#20877;&#19982;&#39044;&#26399;&#25968;&#32452;&#36827;&#34892;&#23545;&#27604;&#12290;&#23545;&#20110;&#8220;&#20026;&#20160;&#20040;&#19981;&#30452;&#25509;&#20351;&#29992;&#25968;&#32452;&#8221;&#36825;&#19968;&#30097;&#38382;&#65292;Matt &#20063;&#32473;&#20986;&#20102;&#20805;&#20998;&#29702;&#30001;&#65306;&#22312;&#23384;&#22312; <code>@Sendable</code> &#32422;&#26463;&#25110; actor &#38548;&#31163;&#19981;&#19968;&#33268;&#30340;&#22330;&#26223;&#19979;&#65292;&#30452;&#25509;&#20889;&#20837;&#25968;&#32452;&#20250;&#35302;&#21457;&#24182;&#21457;&#23433;&#20840;&#38382;&#39064;&#65292;&#32780;&#22522;&#20110; <code>AsyncStream</code> &#30340;&#26041;&#26696;&#21017;&#22825;&#28982;&#31526;&#21512;&#24182;&#21457;&#27169;&#22411;&#30340;&#32422;&#26463;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-03">&#21153;&#24517;&#20026; SwiftData &#27169;&#22411;&#26174;&#24335;&#22768;&#26126; Schema &#29256;&#26412; (If You&#8217;re Not Versioning Your SwiftData Schema, You&#8217;re Gambling)</a></strong></h3><p>SwiftData &#30340;&#22768;&#26126;&#24335;&#20889;&#27861;&#19982;&#33258;&#21160;&#36801;&#31227;&#33021;&#21147;&#24456;&#23481;&#26131;&#35753;&#20154;&#20135;&#29983;&#8220;&#26694;&#26550;&#20250;&#26367;&#25105;&#22788;&#29702;&#19968;&#20999;&#8221;&#30340;&#38169;&#35273;&#65292;&#20294;&#29616;&#23454;&#26159;&#65292;&#19968;&#26086;&#27169;&#22411;&#32467;&#26500;&#21457;&#29983;&#21464;&#21270;&#65288;&#23383;&#27573;&#26032;&#22686;&#12289;&#37325;&#21629;&#21517;&#12289;&#20851;&#31995;&#35843;&#25972;&#65289;&#65292;&#22914;&#26524;&#27809;&#26377;&#26174;&#24335;&#30340; schema version &#19982; migration plan&#65292;&#23601;&#21482;&#33021;&#20381;&#36182;&#38544;&#24335;&#25512;&#26029;&#12290;&#19968;&#26086;&#25512;&#26029;&#22833;&#36133;&#65292;&#32467;&#26524;&#24448;&#24448;&#19981;&#26159;&#20248;&#38597;&#30340;&#36801;&#31227;&#65292;&#32780;&#26159;&#23849;&#28291;&#12289;&#25968;&#25454;&#20002;&#22833;&#65292;&#29978;&#33267;&#23548;&#33268;&#24212;&#29992;&#26080;&#27861;&#21551;&#21160;&#12290;<a href="https://x.com/azamsharp">Mohammad Azam</a> &#30340;&#24314;&#35758;&#30452;&#25509;&#32780;&#21153;&#23454;&#65306;&#26174;&#24335;&#22768;&#26126; <code>Schema</code> &#29256;&#26412;&#65307;&#20026;&#26410;&#26469;&#30340;&#32467;&#26500;&#21464;&#21270;&#39044;&#30041;&#36801;&#31227;&#36335;&#24452;&#65307;&#23558;&#8220;&#36801;&#31227;&#35774;&#35745;&#8221;&#35270;&#20026;&#27169;&#22411;&#35774;&#35745;&#30340;&#19968;&#37096;&#20998;&#65292;&#32780;&#19981;&#26159;&#20107;&#21518;&#34917;&#25937;&#12290;</p><blockquote><p>&#26412;&#25991;&#30340;&#35266;&#28857;&#21516;&#26679;&#36866;&#29992;&#20110; Core Data&#12290;&#21363;&#20415;&#27169;&#22411;&#23436;&#20840;&#20860;&#23481;&#36731;&#37327;&#36801;&#31227;&#65292;&#20026;&#27599;&#20010;&#21457;&#34892;&#29256;&#26412;&#21019;&#24314;&#23545;&#24212;&#30340;&#27169;&#22411;&#29256;&#26412;&#25991;&#20214;&#65288;&#21482;&#35201;&#21457;&#29983;&#32467;&#26500;&#20462;&#25913;&#65289;&#65292;&#19981;&#20165;&#26377;&#21161;&#20110;&#36861;&#36394;&#27169;&#22411;&#28436;&#21270;&#36712;&#36857;&#65292;&#20063;&#33021;&#22312;&#20986;&#29616;&#38382;&#39064;&#26102;&#23454;&#29616;&#28165;&#26224;&#32780;&#21487;&#25511;&#30340;&#22238;&#28378;&#12290;&#29992;&#26126;&#30830;&#30340;&#29256;&#26412;&#26426;&#21046;&#32422;&#26463;&#27169;&#22411;&#28436;&#36827;&#65292;&#26412;&#36136;&#19978;&#26159;&#22312;&#20026;&#38271;&#26399;&#32500;&#25252;&#24314;&#31435;&#23433;&#20840;&#36793;&#30028;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-04">&#29992; Swift &#24320;&#21457; CLI &#24037;&#20855; (How to build a simple CLI tool using Swift)</a></strong></h3><p>&#19968;&#20010;&#26377;&#36259;&#30340;&#29616;&#35937;&#26159;&#65292;&#22312; AI Coding &#26102;&#20195;&#65292;CLI &#27491;&#22312;&#37325;&#28949;&#38738;&#26149;&#8212;&#8212;&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#36890;&#36807;&#26500;&#24314; CLI &#24037;&#20855;&#26469;&#25215;&#36733;&#33258;&#24049;&#30340; MCP &#19982; Agent &#24037;&#20316;&#27969;&#12290;<a href="https://x.com/tanaschita">Natascha Fadeeva</a> &#20171;&#32461;&#20102;&#22914;&#20309;&#29992; Swift Package Manager &#21644; Apple &#23448;&#26041;&#30340; ArgumentParser &#24211;&#26500;&#24314;&#32467;&#26500;&#21270;&#30340;&#21629;&#20196;&#34892;&#24037;&#20855;&#65306;&#23450;&#20041;&#20027;&#21629;&#20196;&#19982;&#23376;&#21629;&#20196;&#12289;&#22788;&#29702;&#24322;&#27493;&#32593;&#32476;&#35831;&#27714;&#12289;&#26368;&#32456;&#32534;&#35793;&#20026;&#21487;&#29420;&#31435;&#20998;&#21457;&#30340;&#20108;&#36827;&#21046;&#25991;&#20214;&#12290;&#23545;&#20110;&#24050;&#32463;&#29087;&#24713; Swift &#30340; iOS &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26465;&#36335;&#24452;&#27604;&#32500;&#25252;&#19968;&#22871; bash/Python &#33050;&#26412;&#26356;&#33258;&#28982;&#65292;&#20063;&#26356;&#23481;&#26131;&#38543;&#39033;&#30446;&#19968;&#36215;&#28436;&#36827;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-05">&#22312; AI &#32534;&#31243;&#26102;&#20445;&#25345;&#26041;&#21521;&#24863; (Navigation Notes &#8211; Agentic coding)</a></strong></h3><p>&#20316;&#20026;&#19968;&#20010;&#25317;&#26377;&#20016;&#23500;&#32463;&#39564;&#30340;&#24320;&#21457;&#32773;&#65292;<a href="https://mastodon.social/@heckj">Joseph Heck</a> &#35748;&#20026;&#24403; AI &#33021;&#22815;&#20027;&#21160;&#25191;&#34892;&#20219;&#21153;&#12289;&#29983;&#25104;&#20195;&#30721;&#29978;&#33267;&#25512;&#21160;&#25913;&#21160;&#26102;&#65292;&#24320;&#21457;&#32773;&#30340;&#35282;&#33394;&#20174;&#8220;&#36880;&#34892;&#23454;&#29616;&#32773;&#8221;&#36716;&#21464;&#20026;&#8220;&#36335;&#24452;&#35268;&#21010;&#32773;&#8221;&#12290;&#30495;&#27491;&#31232;&#32570;&#30340;&#33021;&#21147;&#19981;&#20877;&#26159;&#20889;&#20195;&#30721;&#30340;&#36895;&#24230;&#65292;&#32780;&#22312;&#8220;&#23548;&#33322;&#8221;&#8212;&#8212;&#20063;&#23601;&#26159;&#24320;&#21457;&#32773;&#22312;&#22797;&#26434;&#20195;&#30721;&#19982;&#22810;&#20195;&#29702;&#29615;&#22659;&#20013;&#22914;&#20309;&#20445;&#25345;&#26041;&#21521;&#24863;&#12290;Joseph &#32473;&#20986;&#20102;&#20960;&#26465;&#24314;&#35758;&#65292;&#20363;&#22914;&#65306;&#22312;&#25552;&#31034;&#35789;&#20013;&#22987;&#32456;&#21152;&#20837;&#8221;&#23545;&#20219;&#20309;&#27169;&#31946;&#20043;&#22788;&#21521;&#25105;&#25552;&#38382;&#8221;&#65307;&#20808;&#35753; Agent &#21046;&#23450;&#35745;&#21010;&#24182;&#33719;&#24471;&#30830;&#35748;&#65292;&#20877;&#24320;&#22987;&#23454;&#26045;&#65307;&#25552;&#20379;&#30830;&#23450;&#24615;&#30340;&#21453;&#39304;&#22238;&#36335;&#65288;&#21333;&#20803;&#27979;&#35797;&#12289;&#32534;&#35793;&#22120;&#38169;&#35823;&#65289;&#65292;&#35753; Agent &#33021;&#22815;&#33258;&#25105;&#20462;&#27491;&#65307;&#20197;&#21450;&#23558;&#21453;&#22797;&#20351;&#29992;&#30340;&#25351;&#20196;&#38598;&#27785;&#28096;&#20026; Skill &#25991;&#20214;&#31561;&#12290;</p><p>Heck &#24182;&#27809;&#26377;&#36807;&#24230;&#28210;&#26579;&#8220;AI &#39072;&#35206;&#24320;&#21457;&#32773;&#8221;&#30340;&#21465;&#20107;&#65292;&#32780;&#26159;&#24378;&#35843;&#19968;&#31181;&#26356;&#20919;&#38745;&#30340;&#29616;&#23454;&#65306;agentic coding &#20250;&#25918;&#22823;&#24050;&#26377;&#30340;&#24037;&#31243;&#33021;&#21147;&#12290;&#22914;&#26524;&#20320;&#26412;&#26469;&#23601;&#21892;&#20110;&#27169;&#22359;&#21010;&#20998;&#19982;&#25277;&#35937;&#35774;&#35745;&#65292;AI &#20250;&#21152;&#36895;&#20320;&#65307;&#22914;&#26524;&#36793;&#30028;&#24863;&#27169;&#31946;&#65292;AI &#21482;&#20250;&#26356;&#24555;&#21046;&#36896;&#28151;&#20081;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-06">&#20026; Agent &#39537;&#21160;&#30340; iOS &#39033;&#30446;&#26500;&#24314;&#21487;&#38752;&#20132;&#20184;&#31649;&#32447; (Setting up a delivery pipeline for your agentic iOS projects)</a></strong></h3><p>&#24403;&#20195;&#30721;&#30340;&#29983;&#25104;&#12289;&#20462;&#25913;&#19982;&#37325;&#26500;&#24320;&#22987;&#30001; Agent &#39537;&#21160;&#26102;&#65292;&#20256;&#32479;&#30340; CI/CD &#27969;&#31243;&#26159;&#21542;&#20173;&#28982;&#36275;&#22815;&#65311;<a href="https://x.com/donnywals">Donny Wals</a> &#20197;&#19968;&#27425;&#30495;&#23454;&#32463;&#21382;&#23637;&#24320;&#65306;&#20581;&#36523;&#26102;&#24212;&#29992;&#23849;&#28291;&#65292;&#20182;&#23558; Crash Report &#20132;&#32473; Agent &#20998;&#26512;&#65292;&#35757;&#32451;&#32467;&#26463;&#21518; PR &#24050;&#32463;&#20934;&#22791;&#23601;&#32490;&#65292;&#21512;&#24182;&#21518; TestFlight &#26500;&#24314;&#38543;&#21363;&#33853;&#22320;&#12290;&#22260;&#32469;&#36825;&#19968;&#23454;&#36341;&#65292;&#20182;&#31995;&#32479;&#26803;&#29702;&#20102;&#22914;&#20309;&#20026;&#8220;agentic iOS &#39033;&#30446;&#8221;&#26500;&#24314;&#19968;&#26465;&#21487;&#38752;&#30340;&#20132;&#20184;&#31649;&#32447;&#65288;delivery pipeline&#65289;&#65292;&#30830;&#20445;&#33258;&#21160;&#21270;&#25913;&#21160;&#20381;&#28982;&#21487;&#25511;&#12289;&#21487;&#39564;&#35777;&#12289;&#21487;&#21457;&#24067;&#12290;</p><p>&#25991;&#31456;&#30340;&#37325;&#28857;&#24182;&#19981;&#22312;&#26576;&#20010;&#20855;&#20307;&#24037;&#20855;&#65292;&#32780;&#22312;&#27969;&#31243;&#35774;&#35745;&#26412;&#36523;&#12290;Donny &#24378;&#35843;&#65292;Agent &#29983;&#25104;&#30340;&#20195;&#30721;&#26412;&#36136;&#19978;&#20173;&#23646;&#20110;&#8220;&#26410;&#32463;&#20154;&#24037;&#36880;&#34892;&#23457;&#26597;&#30340;&#25913;&#21160;&#8221;&#65292;&#22240;&#27492;&#26356;&#38656;&#35201;&#26126;&#30830;&#30340;&#36793;&#30028;&#19982;&#36136;&#37327;&#38392;&#21475;&#65306;&#33258;&#21160;&#21270;&#27979;&#35797;&#12289;&#25345;&#32493;&#38598;&#25104;&#19982;&#21457;&#24067;&#27969;&#31243;&#24517;&#39035;&#25215;&#25285;&#26368;&#32456;&#30340;&#20132;&#20184;&#36131;&#20219;&#12290;Agent &#21487;&#20197;&#26174;&#33879;&#25552;&#21319;&#23454;&#29616;&#36895;&#24230;&#65292;&#20294;&#24037;&#31243;&#32426;&#24459;&#19981;&#33021;&#38543;&#20043;&#25918;&#26494;&#8212;&#8212;&#36895;&#24230;&#25552;&#21319;&#20043;&#21518;&#65292;&#25511;&#21046;&#26426;&#21046;&#21453;&#32780;&#26356;&#20026;&#20851;&#38190;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-07">&#23454;&#26102;&#25484;&#25569; Foundation Models &#30340;&#19978;&#19979;&#25991;&#28040;&#32791; (Tracking Token Usage in Foundation Models)</a></strong></h3><p>Apple &#30340; Foundation Models &#36816;&#34892;&#22312;&#35774;&#22791;&#31471;&#65292;&#19978;&#19979;&#25991;&#31383;&#21475;&#20165; 4096 &#20010; token&#65292;&#19968;&#26086;&#36229;&#20986;&#20415;&#26080;&#27861;&#32487;&#32493;&#23545;&#35805;&#12290;iOS 26.4 &#26032;&#22686;&#20102; token &#29992;&#37327;&#36861;&#36394; API&#65292;&#24110;&#21161;&#24320;&#21457;&#32773;&#23454;&#26102;&#25484;&#25569;&#19978;&#19979;&#25991;&#28040;&#32791;&#24773;&#20917;&#12290;<a href="https://x.com/iosartem">Artem Novichkov</a> &#31995;&#32479;&#20171;&#32461;&#20102;&#22235;&#20010;&#20851;&#38190;&#25351;&#26631;&#65306;&#27169;&#22411;&#19978;&#19979;&#25991;&#24635;&#23481;&#37327;&#65288;<code>contextSize</code>&#65289;&#12289;Instructions &#30340; token &#28040;&#32791;&#12289;&#21333;&#26465; Prompt &#30340;&#28040;&#32791;&#65292;&#20197;&#21450;&#23436;&#25972;&#23545;&#35805;&#35760;&#24405;&#65288;Transcript&#65289;&#30340;&#32047;&#35745;&#29992;&#37327;&#12290;&#25991;&#31456;&#36824;&#25581;&#31034;&#20102;&#19968;&#20010;&#23481;&#26131;&#34987;&#24573;&#35270;&#30340;&#32454;&#33410;&#65306;&#24403;&#24341;&#20837; Tool &#26102;&#65292;&#20854;&#21517;&#31216;&#12289;&#25551;&#36848;&#19982;&#21442;&#25968; Schema &#20250;&#34987;&#24207;&#21015;&#21270;&#24182;&#35745;&#20837; token&#65292;&#21516;&#19968;&#27573; Instructions &#22312;&#38468;&#21152; Tool &#21518; token &#25968;&#20174; 16 &#36291;&#21319;&#33267; 79&#12290;&#23545;&#20110;&#35774;&#22791;&#31471;&#27169;&#22411;&#32780;&#35328;&#65292;token &#30340;&#21487;&#35266;&#27979;&#24615;&#23558;&#25104;&#20026;&#20248;&#21270;&#20307;&#39564;&#30340;&#22522;&#30784;&#35774;&#26045;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0124-08">App Store Connect CLI</a></strong></h3><p>App Store Connect CLI &#26159;&#30001; <a href="https://x.com/rudrank">Rudrank Riyam</a> &#24320;&#21457;&#30340;&#38750;&#23448;&#26041; App Store Connect &#21629;&#20196;&#34892;&#24037;&#20855;&#65292;&#21151;&#33021;&#35206;&#30422; TestFlight &#31649;&#29702;&#12289;&#26500;&#24314;&#19978;&#20256;&#12289;&#20195;&#30721;&#31614;&#21517;&#12289;&#25130;&#22270;&#33258;&#21160;&#21270;&#12289;&#26412;&#22320;&#21270;&#21516;&#27493;&#12289;&#24212;&#29992;&#23457;&#26680;&#25552;&#20132;&#12289;notarization&#65292;&#20197;&#21450;&#36130;&#21153;&#25253;&#21578;&#19979;&#36733;&#31561;&#23436;&#25972;&#21457;&#24067;&#38142;&#36335;&#12290;&#23427;&#20174;&#35774;&#35745;&#38454;&#27573;&#23601;&#24378;&#35843; Agent &#22330;&#26223;&#65292;&#24182;&#25552;&#20379;&#20102;&#38754;&#21521; Agent &#30340;&#23454;&#36341;&#25991;&#26723;&#12290;&#33509;&#20320;&#30340;&#21457;&#24067;&#27969;&#31243;&#37325;&#24515;&#22312; TestFlight&#12289;&#20803;&#25968;&#25454;&#12289;&#25552;&#23457;&#12289;&#31614;&#21517;&#19982; CI &#33258;&#21160;&#21270;&#65292;ASC &#21487;&#20197;&#20316;&#20026; fastlane &#30340;&#36731;&#37327;&#26367;&#20195;&#26041;&#26696;&#20043;&#19968;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-09">GRDB 7.10.0: &#26032;&#22686; Android&#12289;Linux&#12289;Windows &#25903;&#25345;</a></strong></h3><p>GRDB 7.10.0 &#26159;&#19968;&#20010;&#20855;&#26377;&#37324;&#31243;&#30865;&#24847;&#20041;&#30340;&#29256;&#26412;&#26356;&#26032;&#65306;&#26412;&#27425;&#27491;&#24335;&#24341;&#20837;&#23545; Android&#12289;Linux&#12289;Windows &#30340;&#25903;&#25345;&#65292;&#24182;&#26032;&#22686;&#36890;&#36807; Swift Package Manager &#20351;&#29992; SQLCipher&#65288;&#21152;&#23494;&#25968;&#25454;&#24211;&#65289;&#30340;&#33021;&#21147;&#8212;&#8212;&#36825;&#20004;&#39033;&#21151;&#33021;&#37117;&#38271;&#26399;&#21463;&#21040;&#31038;&#21306;&#26399;&#24453;&#12290;&#36825;&#24847;&#21619;&#30528;&#36825;&#20010; Swift &#29983;&#24577;&#20013;&#26368;&#25104;&#29087;&#30340; SQLite &#23553;&#35013;&#24211;&#65292;&#27491;&#22312;&#20174; Apple &#24179;&#21488;&#24037;&#20855;&#28436;&#36827;&#20026;&#30495;&#27491;&#30340;&#36328;&#24179;&#21488;&#25968;&#25454;&#23618;&#35299;&#20915;&#26041;&#26696;&#12290;</p><p><a href="https://x.com/groue">Gwendal Rou&#233;</a> &#22312; <a href="https://forums.swift.org/t/grdb-v7-10-0-android-linux-windows-and-sqlcipher-swiftpm/84754">&#29256;&#26412;&#20844;&#21578;</a> &#20013;&#20063;&#29305;&#21035;&#35828;&#26126;&#65292;&#30001;&#20110; Xcode &#23578;&#26410;&#25903;&#25345; package traits&#65292;SwiftPM &#30446;&#21069;&#20173;&#20250;&#19979;&#36733;&#26410;&#23454;&#38469;&#20351;&#29992;&#30340;&#20381;&#36182;&#65307;&#22312;&#30456;&#20851;&#38382;&#39064;&#35299;&#20915;&#20043;&#21069;&#65292;SQLCipher &#25903;&#25345;&#23558;&#20197; fork &#24418;&#24335;&#38271;&#26399;&#32500;&#25252;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0124-10">Swift System Metrics</a></strong></h3><p>Swift System Metrics &#20026; Swift &#24212;&#29992;&#65288;&#23588;&#20854;&#26159;&#26381;&#21153;&#31471;&#39033;&#30446;&#65289;&#25552;&#20379;&#20102;&#32479;&#19968;&#30340;&#31995;&#32479;&#32423;&#25351;&#26631;&#37319;&#38598;&#33021;&#21147;&#65292;&#20363;&#22914; CPU &#20351;&#29992;&#29575;&#12289;&#20869;&#23384;&#21344;&#29992;&#12289;&#25991;&#20214;&#25551;&#36848;&#31526;&#25968;&#37327;&#31561;&#65292;&#24182;&#36890;&#36807;&#26631;&#20934;&#21270;&#30340; Metrics &#25509;&#21475;&#23545;&#22806;&#26292;&#38706;&#65292;&#20415;&#20110;&#25509;&#20837; Prometheus &#31561;&#29616;&#26377;&#30417;&#25511;&#20307;&#31995;&#12290;&#23427;&#24182;&#38750;&#19968;&#20010;&#29420;&#31435;&#30340;&#30417;&#25511;&#31995;&#32479;&#65292;&#32780;&#26159;&#30001; Swift Server Work Group &#25512;&#21160;&#30340;&#22522;&#30784;&#35774;&#26045;&#32452;&#20214;&#65292;&#26088;&#22312;&#19982; Swift Metrics &#29983;&#24577;&#23545;&#40784;&#65292;&#20351;&#31995;&#32479;&#36164;&#28304;&#25351;&#26631;&#19982;&#24212;&#29992;&#32423;&#25351;&#26631;&#32435;&#20837;&#21516;&#19968;&#21487;&#35266;&#27979;&#20307;&#31995;&#12290;1.0 &#30340;&#21457;&#24067;&#24847;&#21619;&#30528; API &#24050;&#36235;&#20110;&#31283;&#23450;&#65292;&#20855;&#22791;&#29983;&#20135;&#29615;&#22659;&#20351;&#29992;&#26465;&#20214;&#12290;&#23545;&#27491;&#22312;&#26500;&#24314; Swift &#21518;&#31471;&#26381;&#21153;&#12289;&#25110;&#25345;&#32493;&#23436;&#21892; Swift &#21487;&#35266;&#27979;&#24615;&#33021;&#21147;&#30340;&#22242;&#38431;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20010;&#22522;&#30784;&#35774;&#26045;&#23618;&#38754;&#30340;&#20851;&#38190;&#25340;&#22270;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #123]]></title><description><![CDATA[Wishing Everyone a Happy Year of the Horse!]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-123</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-123</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 16 Feb 2026 02:00:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!nb3y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_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_!nb3y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nb3y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nb3y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5937d52-2c9a-4021-8eb4-b360a12becd0_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;:94730,&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/188014594?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_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_!nb3y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!nb3y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5937d52-2c9a-4021-8eb4-b360a12becd0_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"><svg role="img" 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"><g><title></title><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"><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"><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>Wishing Everyone a Happy Year of the Horse!</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-123/">Read on web &#8594;</a></p><p>This Chinese New Year ushers in the <strong>Bingwu Year (&#19993;&#21320;)</strong> &#8212; a once&#8209;in&#8209;60&#8209;years <strong>&#8220;Red Horse Year&#8221; (&#36196;&#39532;&#24180;)</strong> .</p><p>In the traditional Chinese stem&#8209;branch calendar, the Heavenly Stem Bing (&#19993;) and the Earthly Branch Wu (&#21320;) both belong to the Fire element. This double&#8209;fire combination creates an exceptionally rare <strong>&#8220;Fire Horse&#8221; pattern</strong>. Since fire is associated with the colour red, this Year of the Horse is also called the <strong>&#8220;Red Horse Year&#8221; (&#32418;&#39532;&#24180;)</strong> . This red horse embodies pure vitality and soaring spirits, symbolising a year full of boundless energy and enterprising drive.</p><p>At this once&#8209;in&#8209;60&#8209;years auspicious moment, I wish all my readers: good health (CPU at full power), a soaring career (performance optimised), smooth sailing in everything (bug&#8209;free runtime), and immediate success (compilation passed)! &#127881;</p><p><a href="https://fatbobman.com/en/weekly/issue-122/">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/w0123-01">Swift Concurrency from Zero to Hero | Reading List</a></strong></h3><p>Setting AI aside&#8212;since it still struggles to handle complex Swift 6 concurrency code at an expert level&#8212;even as tools rapidly evolve, you shouldn&#8217;t remain a passive observer. A systematic and comprehensive understanding of Swift Concurrency&#8212;its concepts, usage patterns, and historical evolution&#8212;is essential for building safer and more resilient applications from the ground up. In this article, <a href="https://x.com/AlexOzun">Alex Ozun</a> organizes a structured learning roadmap for Swift Concurrency, divided by difficulty levels. Each stage is accompanied by publicly available, free resources, with complexity gradually increasing. The goal is simple: complete the journey and move from Zero to Hero.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-02">A Modern iOS Project Setup in 15 Steps</a></strong></h3><p>For many developers, starting a new project means repeating a series of tedious setup steps. In this thread, <a href="https://x.com/ertembiyik">Ertem Biyik</a> outlines a modern engineering baseline for iOS projects in 15 steps: using <a href="https://l.fatbobman.com/sb-tuist-substack">Tuist</a> to manage dependencies and project generation, centralizing configuration through <code>xcconfig</code>, simplifying onboarding with a Makefile, and validating builds with GitHub Actions. He also recommends standardizing AI context with <code>AGENTS.md</code> and leveraging <a href="https://sosumi.ai/">sosumi.ai</a> for LLM-friendly Apple documentation.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-04">Micelio: Growing Software Like Nature Grows Forests</a></strong></h3><p>As AI becomes deeply embedded in development workflows, many traditional tools are starting to show their limitations. Using the metaphor of a mycelium network, <a href="https://x.com/pepicrft">Pedro Pi&#241;era</a> argues that Git&#8217;s model&#8212;capturing <strong>what changed</strong> but rarely preserving <strong>why it changed</strong>&#8212;may no longer be sufficient in an AI-first world. This article presents his systematic reflection on a &#8220;post-Git era&#8221; and introduces an experimental approach to agent-first collaboration. The accompanying open-source forge project, <a href="https://github.com/pepicrft/micelio">Micelio</a>, centers around sessions as the core unit to capture context and reasoning, shifting code hosting from storing diffs to storing decisions. Though still early-stage, the problem framing and engineering direction are worth watching.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-05">Copy-on-Write in Swift - How It Works and Why It Optimizes Memory</a></strong></h3><p>Copy-on-Write (COW) is a fundamental mechanism in Swift and a key reason value types can achieve strong semantics without sacrificing performance. <a href="https://x.com/sagarunagar_">Sagar Unagar</a> explains how Swift balances value semantics and runtime efficiency through a &#8220;struct wrapper + reference storage&#8221; model: reads share storage, while writes trigger a real copy only when the reference is no longer unique, detected via <code>isKnownUniquelyReferenced</code>. The article also demonstrates how to implement COW in custom types.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-06">Taking First Steps into Metal Shaders</a></strong></h3><p>For many SwiftUI developers, Metal can feel distant and complex. In this article, <a href="https://www.linkedin.com/in/letizia-granata/">Letizia Granata</a> walks through the basics of working with shaders&#8212;from understanding CPU/GPU responsibilities to adding a <code>.metal</code> file in Xcode and applying a simple shader effect in SwiftUI. Rather than diving into rendering pipelines or graphics theory, the focus is on getting something running, lowering the barrier to entry for experimentation.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-07">Setting Up a Backend Server for Our Landmarks App</a></strong></h3><p>Landmarks is Apple&#8217;s classic SwiftUI tutorial app, but its reliance on local JSON data leaves a gap between example and real-world architecture. <a href="https://linkedin.com/in/kyle-browning-eng-manager">Kyle Browning</a> builds a simple backend using Vapor to serve data via API, transforming the static demo into a client-server structure. The article covers model definition, routing, data responses, and integration with SwiftUI&#8212;less about complex business logic and more about extending a teaching example into something closer to production reality.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-08">In the Background: Spotlight Indexing</a></strong></h3><p>After a system update, Macs often run hot and sluggish for a few days&#8212;commonly attributed to Spotlight reindexing. But how exactly does Spotlight scan files, decide when to rebuild its index, and manage system resources in the background? <a href="https://x.com/howardnoakley">Howard Oakley</a> analyzes logs and empirical data to explore Spotlight&#8217;s triggering mechanisms, process behavior, and impact on I/O and performance, offering a deeper technical look at macOS internals.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0123-09">ScreenStateKit: A Better MVVM for the SwiftUI Concurrency Era</a></strong></h3><p>If you appreciate TCA&#8217;s unidirectional data flow and predictable state management but don&#8217;t want to fully refactor your existing MVVM architecture, ScreenStateKit may offer a pragmatic middle ground. <a href="https://www.linkedin.com/in/quang-tran-7780a962/">Anthony Tran</a> splits the traditional ViewModel into two clearly defined components: a <code>@MainActor</code>-isolated <code>ScreenState</code> that holds UI state, and a Swift actor-based <code>ScreenActionStore</code> that handles business logic and async tasks. All mutations flow through strongly typed Actions, bringing compile-time concurrency safety and TCA-like discipline to MVVM. Built-in loading/error handling, duplicate request prevention (ActionLocker), parent-child state propagation, and pagination support round out the design. Anthony also provides a detailed design <a href="https://medium.com/@qquang269/screenstatekit-a-better-mvvm-for-the-swiftui-concurrency-era-0b25d2793d30">article</a> explaining the architecture and its rationale.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-10">GitHub Directory Downloader</a></strong></h3><p>If you&#8217;ve ever cloned an entire repository just to download a single folder from GitHub, this tool is for you. Developed by <a href="https://x.com/StewartLynch">Stewart Lynch</a>, this native macOS app lets you paste any GitHub repository or directory URL (including <code>tree/branch/path</code> formats), automatically detect the default branch, recursively download the selected directory, and preserve its original structure.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-11">SimTag: Branch Context for Your iOS Simulators</a></strong></h3><p>In parallel development workflows, it&#8217;s easy to lose track of which branch is running in which iOS Simulator. Developed by <a href="https://www.linkedin.com/in/aryaman-sharda-12753168/">Aryaman Sharda</a>, SimTag overlays a lightweight label on each Simulator window, showing the git branch and commit corresponding to the running build. For developers using worktrees, reviewing PRs, or collaborating with AI tools, it helps reduce cognitive friction and prevents debugging the wrong branch.</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-123?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-123?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#31069;&#22823;&#23478;&#39532;&#24180;&#26032;&#26149;&#24555;&#20048;&#65281;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-123/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20170;&#24180;&#30340;&#20013;&#22269;&#20892;&#21382;&#24180;&#26159;&#19993;&#21320;&#24180;&#65292;&#26159;&#19968;&#20010;60&#24180;&#19968;&#36935;&#30340;&#8220;&#36196;&#39532;&#24180;&#8221;&#12290;</p><p>&#22312;&#24178;&#25903;&#32426;&#24180;&#20013;&#65292;&#22825;&#24178;&#8220;&#19993;&#8221;&#19982;&#22320;&#25903;&#8220;&#21320;&#8221;&#20116;&#34892;&#30342;&#23646;&#28779;&#65292;&#21452;&#28779;&#21472;&#21152;&#65292;&#24418;&#25104;&#20102;&#26497;&#20026;&#32597;&#35265;&#30340;&#8220;&#28779;&#39532;&#8221;&#26684;&#23616;&#12290;&#22240;&#28779;&#33394;&#20026;&#36196;&#65292;&#25925;&#27492;&#39532;&#24180;&#21448;&#31216;&#8220;&#32418;&#39532;&#24180;&#8221;&#12290;&#36825;&#21305;&#8220;&#32418;&#39532;&#8221;&#25215;&#36733;&#30528;&#26368;&#32431;&#31929;&#30340;&#38451;&#21018;&#20043;&#27668;&#19982;&#34028;&#21187;&#27963;&#21147;&#65292;&#39044;&#31034;&#30528;&#25509;&#19979;&#26469;&#30340;&#19968;&#24180;&#23558;&#20805;&#28385;&#22868;&#25918;&#30340;&#33021;&#37327;&#19982;&#26114;&#25196;&#30340;&#36827;&#21462;&#24515;&#12290;</p><p>&#22312;&#36825;&#20010; 60 &#24180;&#19968;&#36935;&#30340;&#21513;&#24198;&#33410;&#28857;&#65292;&#25105;&#22312;&#27492;&#31069;&#21508;&#20301;&#35835;&#32773;&#26032;&#30340;&#19968;&#24180;&#65306;<strong>&#36523;&#20307;&#20581;&#24247;&#65288;CPU &#28385;&#34880;&#65289;&#65292;&#20107;&#19994;&#39536;&#39563;&#65288;&#24615;&#33021;&#20248;&#21270;&#65289;&#65292;&#19975;&#20107;&#39034;&#36930;&#65288;&#26080; Bug &#36816;&#34892;&#65289;&#65292;&#39532;&#21040;&#25104;&#21151;&#65288;&#32534;&#35793;&#36890;&#36807;&#65289;&#65281;</strong> &#127881;</p><p><a href="https://fatbobman.com/zh/weekly/issue-122/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/w0123-01">Swift &#24182;&#21457;&#36827;&#38454;&#38405;&#35835;&#36335;&#32447;&#22270; (Swift Concurrency from Zero to Hero | Reading List)</a></strong></h3><p>&#26242;&#19981;&#35828; AI &#30446;&#21069;&#36824;&#24456;&#38590;&#20687;&#19987;&#23478;&#19968;&#26679;&#22788;&#29702; Swift 6 &#24182;&#21457;&#30456;&#20851;&#30340;&#22797;&#26434;&#20195;&#30721;&#65292;&#21363;&#20415;&#24037;&#20855;&#33021;&#21147;&#31361;&#39134;&#29467;&#36827;&#65292;&#20316;&#20026;&#20351;&#29992;&#32773;&#30340;&#20320;&#20063;&#19981;&#35813;&#21482;&#24403;&#26049;&#35266;&#32773;&#65306;&#31995;&#32479;&#12289;&#20840;&#38754;&#22320;&#29702;&#35299; Swift &#24182;&#21457;&#30340;&#27010;&#24565;&#12289;&#29992;&#27861;&#19982;&#21382;&#21490;&#33033;&#32476;&#65292;&#25165;&#33021;&#20174;&#28304;&#22836;&#26500;&#24314;&#26356;&#23433;&#20840;&#12289;&#26356;&#24378;&#20581;&#30340;&#24212;&#29992;&#12290;<a href="https://x.com/AlexOzun">Alex Ozun</a> &#22312;&#26412;&#25991;&#20013;&#25353;&#38590;&#24230;&#21010;&#20998;&#20851;&#21345;&#65292;&#25972;&#29702;&#20102;&#19968;&#20221;&#8220;&#20174;&#20837;&#38376;&#21040;&#36827;&#38454;&#8221;&#30340; Swift Concurrency &#38405;&#35835;&#36335;&#32447;&#22270;&#65306;&#27599;&#19968;&#20851;&#37117;&#37197;&#22871;&#20102;&#20844;&#24320;&#19988;&#20813;&#36153;&#30340;&#21442;&#32771;&#36164;&#26009;&#65292;&#38590;&#24230;&#20063;&#20250;&#36880;&#32423;&#36882;&#22686;&#65292;&#24076;&#26395;&#20320;&#22312;&#23436;&#25104;&#36825;&#26465;&#20027;&#32447;&#20043;&#21518;&#65292;&#33021;&#20174; Zero &#36208;&#21040; Hero&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-02">15 &#27493;&#25171;&#36896;&#29616;&#20195; iOS &#39033;&#30446; (A Modern iOS Project Setup in 15 Steps)</a></strong></h3><p>&#23545;&#20110;&#19981;&#23569;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#26032;&#39033;&#30446;&#30340;&#24320;&#22987;&#24448;&#24448;&#20276;&#38543;&#30528;&#37325;&#22797;&#32780;&#29712;&#30862;&#30340;&#37197;&#32622;&#24037;&#20316;&#12290;<a href="https://x.com/ertembiyik">Ertem Biyik</a> &#22312;&#36825;&#26465;&#20018;&#36148;&#20013;&#29992; 15 &#20010;&#27493;&#39588;&#26803;&#29702;&#20102;&#19968;&#22871;&#29616;&#20195; iOS &#39033;&#30446;&#30340;&#24037;&#31243;&#21270;&#22522;&#32447;&#65306;&#20197; <a href="https://l.fatbobman.com/sb-tuist-substack">Tuist</a> &#20026;&#26680;&#24515;&#31649;&#29702;&#20381;&#36182;&#19982;&#29983;&#25104;&#65292;&#36890;&#36807; <code>xcconfig</code> &#32479;&#19968;&#29615;&#22659;&#37197;&#32622;&#19982;&#26500;&#24314;&#21442;&#25968;&#65292;&#20511;&#21161; Makefile &#31616;&#21270;&#21021;&#22987;&#21270;&#27969;&#31243;&#65292;&#24182;&#22312; GitHub Actions &#20013;&#23436;&#25104; lint &#19982;&#26500;&#24314;&#26657;&#39564;&#65307;&#21516;&#26102;&#65292;&#20182;&#36824;&#24314;&#35758;&#20351;&#29992; <code>AGENTS.md</code> &#32479;&#19968; AI &#19978;&#19979;&#25991;&#65292;&#24182;&#37197;&#21512; <a href="https://sosumi.ai/">sosumi.ai</a> &#33719;&#21462;&#26356;&#21033;&#20110; LLM &#38405;&#35835;&#30340; Apple &#25991;&#26723;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-04">Micelio&#65306;&#21518; Git &#26102;&#20195;&#30340;&#20195;&#30721;&#25176;&#31649;&#24037;&#20855; (Micelio: Growing Software Like Nature Grows Forests)</a></strong></h3><p>AI &#28145;&#24230;&#21442;&#19982;&#24320;&#21457;&#27969;&#31243;&#21518;&#65292;&#35768;&#22810;&#20256;&#32479;&#24037;&#20855;&#24320;&#22987;&#26174;&#38706;&#20986;&#8220;&#27700;&#22303;&#19981;&#26381;&#8221;&#12290;<a href="https://x.com/pepicrft">Pedro Pi&#241;era</a> &#20197;&#8220;&#33740;&#19997;&#32593;&#32476;&#65288;mycelium&#65289;&#8221;&#20026;&#38544;&#21947;&#65292;&#25351;&#20986;&#38543;&#30528; AI agent &#21442;&#19982;&#24320;&#21457;&#30340;&#35268;&#27169;&#19982;&#39057;&#29575;&#19981;&#26029;&#25552;&#21319;&#65292;Git &#36825;&#31181;&#21482;&#35760;&#24405; <strong>what changed</strong>&#12289;&#21364;&#38590;&#20197;&#20445;&#30041; <strong>why it changed</strong> &#30340;&#21382;&#21490;&#27169;&#22411;&#65292;&#27491;&#22312;&#21464;&#24471;&#19981;&#22815;&#20805;&#20998;&#12290;&#26412;&#25991;&#26159;&#20182;&#23545;&#8220;&#21518; Git &#26102;&#20195;&#8221;&#30340;&#19968;&#27425;&#31995;&#32479;&#24615;&#24605;&#32771;&#65292;&#20063;&#26159;&#23545;&#8220;agent-first &#21327;&#20316;&#26041;&#24335;&#8221;&#30340;&#20844;&#24320;&#23454;&#39564;&#12290;&#37197;&#22871;&#30340;&#24320;&#28304; git forge <a href="https://github.com/pepicrft/micelio">Micelio</a> &#39033;&#30446;&#23581;&#35797;&#20197; session &#20026;&#26680;&#24515;&#21333;&#20803;&#25429;&#33719;&#19978;&#19979;&#25991;&#19982;&#25512;&#29702;&#65292;&#23558;&#20195;&#30721;&#25176;&#31649;&#30340;&#37325;&#24515;&#20174;&#8220;&#23384; diff&#8221;&#36716;&#21521;&#8220;&#23384;&#20915;&#31574;&#8221;&#12290;&#39033;&#30446;&#20173;&#22788;&#20110;&#26089;&#26399;&#38454;&#27573;&#65292;&#20294;&#20854;&#38382;&#39064;&#24847;&#35782;&#19982;&#24037;&#31243;&#26041;&#21521;&#65292;&#37117;&#20540;&#24471;&#25345;&#32493;&#20851;&#27880;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-05">Swift &#20889;&#26102;&#22797;&#21046; (Copy-on-Write in Swift - How It Works and Why It Optimizes Memory)</a></strong></h3><p>&#20889;&#26102;&#22797;&#21046;&#65288;COW&#65289;&#26159; Swift &#30340;&#26680;&#24515;&#26426;&#21046;&#20043;&#19968;&#65292;&#20063;&#26159;&#20540;&#31867;&#22411;&#22312;&#20445;&#35777;&#35821;&#20041;&#19968;&#33268;&#24615;&#30340;&#21516;&#26102;&#33719;&#24471;&#33391;&#22909;&#24615;&#33021;&#30340;&#20851;&#38190;&#12290;<a href="https://x.com/sagarunagar_">Sagar Unagar</a> &#32467;&#21512;&#38598;&#21512;&#31867;&#22411;&#30340;&#20869;&#37096;&#23454;&#29616;&#65292;&#35299;&#37322;&#20102; Swift &#22914;&#20309;&#36890;&#36807;&#8220;&#32467;&#26500;&#20307;&#22806;&#22771; + &#24341;&#29992;&#23384;&#20648;&#8221;&#30340;&#26041;&#24335;&#23454;&#29616;&#35835;&#20849;&#20139;&#12289;&#20889;&#20998;&#31163;&#65306;&#21482;&#26377;&#22312;&#21457;&#29983;&#20889;&#20837;&#19988;&#26816;&#27979;&#21040;&#38750;&#21807;&#19968;&#24341;&#29992;&#26102;&#65292;&#25165;&#20250;&#20511;&#21161; <code>isKnownUniquelyReferenced</code> &#35302;&#21457;&#30495;&#27491;&#30340;&#25335;&#36125;&#12290;&#25991;&#31456;&#21516;&#26102;&#23637;&#31034;&#20102;&#33258;&#23450;&#20041;&#31867;&#22411;&#23454;&#29616; COW &#30340;&#22522;&#26412;&#27169;&#24335;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-06">Metal Shader &#20837;&#38376; (Taking First Steps into Metal Shaders)</a></strong></h3><p>&#23545;&#20110;&#22823;&#22810;&#25968; SwiftUI &#24320;&#21457;&#32773;&#32780;&#35328;&#65292;Metal &#24448;&#24448;&#26174;&#24471;&#36965;&#36828;&#32780;&#22797;&#26434;&#12290;<a href="https://www.linkedin.com/in/letizia-granata/">Letizia Granata</a> &#36890;&#36807;&#26412;&#25991;&#24102;&#20320;&#20174; 0 &#24320;&#22987;&#25509;&#35302; Shader&#65306;&#20174;&#29702;&#35299; GPU &#19982; CPU &#30340;&#20998;&#24037;&#65292;&#21040;&#22312; Xcode &#20013;&#28155;&#21152; <code>.metal</code> &#25991;&#20214;&#65292;&#20877;&#21040;&#32534;&#20889;&#24182;&#22312; SwiftUI &#20013;&#24212;&#29992;&#19968;&#20010;&#26368;&#31616;&#21333;&#30340; shader &#25928;&#26524;&#12290;Letizia &#27809;&#26377;&#28145;&#20837;&#28210;&#26579;&#31649;&#32447;&#25110;&#22270;&#24418;&#23398;&#32454;&#33410;&#65292;&#32780;&#26159;&#32858;&#28966;&#8220;&#22914;&#20309;&#30495;&#27491;&#36305;&#36215;&#26469;&#8221;&#65292;&#24110;&#21161;&#35835;&#32773;&#36328;&#36807;&#20837;&#38376;&#38376;&#27099;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-07">&#20026; Landmarks &#26500;&#24314; Vapor &#21518;&#31471; (Setting Up a Backend Server for Our Landmarks App)</a></strong></h3><p>Landmarks &#26159; Apple &#22312; SwiftUI &#25945;&#31243;&#20013;&#25552;&#20379;&#30340;&#32463;&#20856;&#31034;&#20363;&#24212;&#29992;&#65292;&#20294;&#30001;&#20110;&#23427;&#20351;&#29992;&#26412;&#22320; JSON &#25968;&#25454;&#65292;&#19982;&#30495;&#23454;&#39033;&#30446;&#30340;&#23458;&#25143;&#31471;&#8212;&#26381;&#21153;&#22120;&#26550;&#26500;&#20173;&#23384;&#22312;&#24046;&#36317;&#12290;<a href="https://linkedin.com/in/kyle-browning-eng-manager">Kyle Browning</a> &#20351;&#29992; Vapor &#20026; Landmarks &#26500;&#24314;&#20102;&#19968;&#20010;&#31616;&#21333;&#30340;&#21518;&#31471;&#26381;&#21153;&#65292;&#23558;&#38745;&#24577;&#31034;&#20363;&#21319;&#32423;&#20026;&#36890;&#36807; API &#33719;&#21462;&#25968;&#25454;&#30340;&#23436;&#25972;&#32467;&#26500;&#12290;&#25991;&#31456;&#22260;&#32469;&#27169;&#22411;&#23450;&#20041;&#12289;&#36335;&#30001;&#37197;&#32622;&#12289;&#25968;&#25454;&#21709;&#24212;&#20197;&#21450;&#19982; SwiftUI &#21069;&#31471;&#30340;&#23545;&#25509;&#23637;&#24320;&#65292;&#37325;&#28857;&#19981;&#22312;&#22797;&#26434;&#19994;&#21153;&#36923;&#36753;&#65292;&#32780;&#22312;&#20110;&#31034;&#33539;&#22914;&#20309;&#25226;&#19968;&#20010;&#8220;&#25945;&#23398;&#31034;&#20363;&#8221;&#25193;&#23637;&#20026;&#26356;&#36148;&#36817;&#30495;&#23454;&#19990;&#30028;&#30340;&#39033;&#30446;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-08">Spotlight &#21518;&#21488;&#32034;&#24341;&#26426;&#21046;&#35299;&#26512; (In the Background: Spotlight Indexing)</a></strong></h3><p>&#31995;&#32479;&#26356;&#26032;&#21518;&#30340;&#20960;&#22825;&#37324;&#26426;&#22120;&#21457;&#28909;&#12289;&#21345;&#39039;&#65292;&#24456;&#22810;&#20154;&#37117;&#30693;&#36947;&#36825;&#19982; Spotlight &#30340;&#37325;&#26032;&#32034;&#24341;&#26377;&#20851;&#65292;&#20294;&#23427;&#22312;&#21518;&#21488;&#22914;&#20309;&#25195;&#25551;&#25991;&#20214;&#12289;&#20309;&#26102;&#35302;&#21457;&#37325;&#24314;&#32034;&#24341;&#12289;&#21448;&#22914;&#20309;&#35843;&#24230;&#31995;&#32479;&#36164;&#28304;&#65292;&#21364;&#40092;&#23569;&#34987;&#31995;&#32479;&#24615;&#26803;&#29702;&#12290;<a href="https://x.com/howardnoakley">Howard Oakley</a> &#22522;&#20110;&#26085;&#24535;&#19982;&#23454;&#27979;&#25968;&#25454;&#65292;&#23545; Spotlight &#32034;&#24341;&#30340;&#35302;&#21457;&#26426;&#21046;&#12289;&#36827;&#31243;&#34892;&#20026;&#20197;&#21450;&#23545; I/O &#19982;&#24615;&#33021;&#30340;&#24433;&#21709;&#36827;&#34892;&#20102;&#32454;&#33268;&#20998;&#26512;&#65292;&#25552;&#20379;&#20102;&#19968;&#27425;&#20851;&#20110; macOS &#20869;&#37096;&#36816;&#34892;&#26426;&#21046;&#30340;&#28145;&#20837;&#25216;&#26415;&#35266;&#23519;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0123-09">ScreenStateKit&#65306;&#24182;&#21457;&#26102;&#20195;&#30340; MVVM &#28436;&#36827;</a></strong></h3><p>&#22914;&#26524;&#20320;&#27427;&#36175; TCA &#30340;&#21333;&#21521;&#25968;&#25454;&#27969;&#19982;&#21487;&#39044;&#27979;&#29366;&#24577;&#31649;&#29702;&#65292;&#21364;&#21448;&#19981;&#24819;&#22312;&#29616;&#26377; MVVM &#39033;&#30446;&#20013;&#24443;&#24213;&#37325;&#26500;&#26550;&#26500;&#65292;&#37027;&#20040; ScreenStateKit &#29366;&#24577;&#31649;&#29702;&#24211;&#20063;&#35768;&#26159;&#19968;&#20010;&#25240;&#20013;&#26041;&#26696;&#12290;&#20316;&#32773; <a href="https://www.linkedin.com/in/quang-tran-7780a962/">Anthony Tran</a> &#23558;&#20256;&#32479; ViewModel &#25286;&#20998;&#20026;&#20004;&#20010;&#32844;&#36131;&#28165;&#26224;&#30340;&#37096;&#20998;&#65306;&#19968;&#20010;&#36816;&#34892;&#22312; <code>@MainActor</code> &#19978;&#12289;&#21482;&#36127;&#36131;&#25345;&#26377; UI &#29366;&#24577;&#30340; <code>ScreenState</code>&#65292;&#20197;&#21450;&#19968;&#20010;&#20197; Swift actor &#23454;&#29616;&#12289;&#19987;&#38376;&#22788;&#29702;&#19994;&#21153;&#36923;&#36753;&#19982;&#24322;&#27493;&#20219;&#21153;&#30340; <code>ScreenActionStore</code>&#65292;&#25152;&#26377;&#29366;&#24577;&#21464;&#26356;&#37117;&#36890;&#36807;&#24378;&#31867;&#22411; Action &#20316;&#20026;&#21807;&#19968;&#20837;&#21475;&#65292;&#20174;&#32780;&#22312;&#20445;&#25345; MVVM &#32467;&#26500;&#30452;&#35266;&#24615;&#30340;&#21516;&#26102;&#65292;&#24341;&#20837;&#31867;&#20284; TCA &#30340;&#21333;&#21521;&#25968;&#25454;&#27969;&#19982;&#32534;&#35793;&#26399;&#24182;&#21457;&#23433;&#20840;&#12290;&#37197;&#21512;&#20869;&#24314;&#30340;&#21152;&#36733;&#19982;&#38169;&#35823;&#29366;&#24577;&#31649;&#29702;&#12289;&#37325;&#22797;&#35831;&#27714;&#38450;&#25252;&#65288;ActionLocker&#65289;&#12289;&#29238;&#23376;&#29366;&#24577;&#20256;&#25773;&#19982;&#20998;&#39029;&#25903;&#25345;&#12290;Anthony &#20134;&#25776;&#20889;&#20102;&#19968;&#31687;&#35814;&#23613;&#30340;&#35774;&#35745;&#35828;&#26126;<a href="https://medium.com/@qquang269/screenstatekit-a-better-mvvm-for-the-swiftui-concurrency-era-0b25d2793d30">&#25991;&#31456;</a>&#65292;&#23545;&#20854;&#26550;&#26500;&#29702;&#24565;&#19982;&#23454;&#36341;&#32454;&#33410;&#36827;&#34892;&#20102;&#31995;&#32479;&#38416;&#36848;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-10">GitHub &#23376;&#30446;&#24405;&#19979;&#36733;&#24037;&#20855;</a></strong></h3><p>&#22914;&#26524;&#20320;&#26366;&#20026;&#20102;&#19979;&#36733; GitHub &#19978;&#30340;&#26576;&#20010;&#31034;&#20363;&#30446;&#24405;&#32780;&#34987;&#36843; <code>git clone</code> &#25972;&#20010;&#20179;&#24211;&#65292;&#36825;&#27454; GitHub Downloader &#26174;&#28982;&#27491;&#26159;&#20026;&#27492;&#32780;&#29983;&#12290;&#23427;&#26159; <a href="https://x.com/StewartLynch">Stewart Lynch</a> &#24320;&#21457;&#30340;&#19968;&#27454;&#21407;&#29983; macOS &#24212;&#29992;&#65292;&#20801;&#35768;&#20320;&#31896;&#36148;&#20219;&#24847; GitHub &#20179;&#24211;&#25110;&#23376;&#30446;&#24405; URL&#65288;&#21253;&#25324; <code>tree/branch/path</code> &#24418;&#24335;&#65289;&#65292;&#33258;&#21160;&#35782;&#21035;&#40664;&#35748;&#20998;&#25903;&#65292;&#36882;&#24402;&#19979;&#36733;&#25152;&#36873;&#30446;&#24405;&#20869;&#23481;&#65292;&#24182;&#23436;&#25972;&#20445;&#30041;&#20854;&#21407;&#22987;&#23618;&#32423;&#32467;&#26500;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0123-11">SimTag&#65306;&#20026;&#27169;&#25311;&#22120;&#26631;&#27880;&#20998;&#25903;&#19978;&#19979;&#25991;</a></strong></h3><p>&#22312;&#24182;&#34892;&#24320;&#21457;&#25104;&#20026;&#24120;&#24577;&#30340;&#20170;&#22825;&#65292;&#38754;&#23545;&#22810;&#20010;&#22806;&#35266;&#20960;&#20046;&#30456;&#21516;&#30340; iOS Simulator&#65292;&#24320;&#21457;&#32773;&#24456;&#23481;&#26131;&#36855;&#22833;&#65306;&#21040;&#24213;&#21738;&#20010;&#20998;&#25903;&#27491;&#22312;&#36816;&#34892;&#65311;&#26159;&#21542;&#35843;&#35797;&#20102;&#38169;&#35823;&#30340;&#26500;&#24314;&#29256;&#26412;&#65311;<a href="https://www.linkedin.com/in/aryaman-sharda-12753168/">Aryaman Sharda</a> &#24320;&#21457;&#30340; SimTag &#20250;&#22312;&#27599;&#20010; Simulator &#31383;&#21475;&#19978;&#21472;&#21152;&#19968;&#20010;&#36731;&#37327;&#26631;&#35782;&#65292;&#26174;&#31034;&#24403;&#21069;&#26500;&#24314;&#23545;&#24212;&#30340; git &#20998;&#25903;&#19982;&#25552;&#20132;&#20449;&#24687;&#12290;&#23545;&#20110;&#20064;&#24815;&#20351;&#29992; worktrees&#12289;&#36827;&#34892; PR &#23457;&#26597;&#25110;&#32467;&#21512; AI &#21327;&#20316;&#24320;&#21457;&#30340;&#22242;&#38431;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20010;&#33021;&#22815;&#26174;&#33879;&#20943;&#23569;&#35748;&#30693;&#25705;&#25830;&#12289;&#36991;&#20813;&#8220;&#35843;&#38169;&#20998;&#25903;&#8221;&#30340;&#23454;&#29992;&#23567;&#24037;&#20855;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #122]]></title><description><![CDATA[Xcode Enters the Agent Era]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-122</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-122</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 09 Feb 2026 12:02:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9DDu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.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_!9DDu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9DDu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 424w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 848w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 1272w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9DDu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp" width="1400" height="931" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:931,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:87284,&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/187341335?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.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_!9DDu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 424w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 848w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.webp 1272w, https://substackcdn.com/image/fetch/$s_!9DDu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc60fecf0-96c8-475b-b818-a0005826a824_1400x931.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"><svg role="img" 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"><g><title></title><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"><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"><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/@tinkerman?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Immo Wegmann</a> on <a href="https://unsplash.com/photos/a-piece-of-cardboard-with-a-keyboard-appearing-through-it-vi1HXPw6hyw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Xcode Enters the Agent Era</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-122/">Read on web &#8594;</a></p><p>Although Apple had already incorporated AI-assisted programming capabilities in the initial version of Xcode 26, the experience felt more like ChatGPT being awkwardly embedded into the IDE: the functionality existed, but felt disconnected. Compared to the then-popular Cursor, it seemed like a product from a different era. As AI CLI tools like Claude Code gradually matured, Xcode appeared to fall further behind, leading many developers to question whether it could still serve as a &#8220;primary IDE&#8221; in the AI age.</p><p>The arrival of version 26.3, with almost no advance notice, responded to these doubts with concrete action. By integrating Claude Code/Codex, Apple&#8217;s answer was direct: with the right strategy, Xcode remains a highly promising development environment within the Apple ecosystem. This time, Xcode didn&#8217;t simply add a CLI tool panel; instead, it introduced a native set of Xcode Tools (MCP), coordinated with official technical documentation for Swift 6, SwiftUI, SwiftData, and more, creating a highly consistent experience aligned with the latest practices. Even for developers already proficient with CLI + XcodeBuildMCP + various Skills, this native solution remains highly competitive&#8212;especially with its near-zero configuration cost, which is significant for the vast majority of developers.</p><p>More notably, the Xcode Tools provided in this update don&#8217;t just serve Xcode itself; they can also function as standard MCP to provide capabilities for other AI tools. This open approach doesn&#8217;t entirely align with the outside world&#8217;s impression of Apple&#8217;s usual style.</p><p>Of course, from today&#8217;s vantage point, we cannot yet assert that Xcode has returned to the first tier. But what&#8217;s certain is that 26.3 has sent a very clear signal: Apple is willing to collaborate with mainstream tools and services to create development experiences that truly align with the times. For this reason, I have higher expectations for the next iteration of Siri&#8212;likely in iOS 27, Apple will provide more standardized interfaces for the system and apps beyond the existing Intent framework, allowing AI to integrate more naturally into the entire ecosystem.</p><p>Xcode + Agent is just the beginning.</p><p>Apple + Agent is the future worth paying more attention to.</p><p><a href="https://fatbobman.com/en/weekly/issue-121/">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/xcode-263-claude/?utm_source=fatbobman%20weekly%20issue%20122&amp;utm_medium=web">Xcode 26.3 + Claude Agent: Model Swapping, MCP, Skills, and Adaptive Configuration</a></strong></h3><p>Xcode 26.3 directly provides support for Claude Code/Codex. Finally, developers can conveniently use native AI Agents in Xcode. Over the past few days, I&#8217;ve conducted a series of experiments with the new version, including how to use the latest models, configure MCPs/Skills/Commands, and write adaptive <code>CLAUDE.md</code>. This article uses Claude Code as an example to share some tips beyond the documentation.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/screensage-from-pixel-to-meta/?utm_source=fatbobman%20weekly%20issue%20122&amp;utm_medium=web">From Pixel Capture to Metadata: Reimagining Screen Recording Architecture on macOS</a></strong></h3><p>Video is replacing text as a more popular form of expression, and good tools accelerate creation. <a href="https://x.com/s1ntone">Sintone</a>, developer of the macOS screen recording software <a href="https://screensage.pro/">ScreenSage Pro</a>, provides an in-depth retrospective on implementing &#8220;finished editing upon recording completion&#8221; based on ScreenCaptureKit and Metal. From solving the cryptic SCK -3821 error to migrating from ObservableObject to @Observable to optimize timeline performance, this article openly shares the entire process from pixel capture to high-performance composition.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-05">Which Method is Fastest for Checking if a String is in a Whitelist: Set, Array, Enum, Dictionary, or Switch?</a></strong></h3><p>In Swift, checking whether a string belongs to a set of keys can be written as <code>Set.contains</code>, <code>Array.contains</code>, RawRepresentable enum&#8217;s <code>init?(rawValue:)</code>, <code>switch</code> with multiple cases, or even using a <code>Dictionary</code> for mapping. They may look similar, but when placed in performance-sensitive paths, the results might not fully align with intuition. <a href="https://mastodon.social/@helge">Helge He&#223;</a> conducted a simple benchmark test: <code>Set.contains</code> leads without suspense, followed by <code>enum(rawValue:)</code> and <code>Dictionary</code> (very close to each other); while <code>switch</code>, which many would instinctively overestimate, actually ranks after <code>enum</code>, with <code>Array.contains</code> finishing last. As a small experiment, these results might be just what we need to calibrate our intuition about Swift performance.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-01">Migrating an iOS app from Paid up Front to Freemium</a></strong></h3><p>Paid download and free + in-app purchase are two fundamentally different business models, and as apps evolve, developers may need to transition between them. In this article, <a href="https://x.com/donnywals">Donny Wals</a> shares his complete experience converting the Practical Core Data app from a $4.99 paid download to freemium. The article not only covers StoreKit 2 technical implementation details (purchase flow, state management, family sharing), but more valuably, his deep thinking on business decisions: while the paid barrier can filter for serious users, it also blocks many potential users from experiencing the product&#8217;s value. For educational or utility indie apps, freemium may be a better balance between user growth and revenue.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-02">On-demand resources in iOS app</a></strong></h3><p>App size has always been a concern for developers, especially when apps contain large amounts of images, audio, or other resources. Although Apple introduced On-Demand Resources (ODR) in iOS early on to address this challenge, this feature has a weak presence and is often overlooked by developers. In this article, <a href="https://twitter.com/mecid">Majid Jabrayilov</a> systematically reviews ODR&#8217;s working mechanism and usage, including resource grouping, tag management, download lifecycle, and collaboration with system caching strategies.</p><p>While Apple is promoting Background Assets as a more modern solution, ODR still has unique value in scenarios requiring immediate response for on-demand downloads and fine-grained resource control.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-03">Objectively Better, Observably Trickier</a></strong></h3><p>When fully embracing the Observation framework, developers need to be aware that its working mechanism differs from Combine&#8217;s <code>@Published</code>, and simple replacement often introduces subtle issues. <a href="https://x.com/dbolella">Danny Bolella</a> summarizes four common pitfalls during migration: non-lazy initialization when <code>@State</code> holds reference types, update loss caused by nested <code>@Observable</code> objects, changes in array element binding methods, and conflicts with other property wrappers. The article provides solutions through clear code examples and repeatedly emphasizes a core principle: updates only trigger when properties currently being accessed (getter called) by the view change. Understanding and adapting to this &#8220;lazy observation&#8221; mindset is key to correctly using the Observation framework.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-04">Add an Open Recent Menu to a SwiftUI app</a></strong></h3><p>&#8220;Open Recent&#8221; is a standard macOS app feature, but for SwiftUI developers, correctly implementing this functionality is not intuitive. In this article, <a href="https://mastodon.world/@swiftdevjournal">Mark Szymczyk</a> demonstrates through a concise example how to use <code>NSDocumentController</code> to integrate system-level recent file management capabilities into your app: automatic list maintenance, menu updates, and seamless coordination with document lifecycle. For document or utility apps, this is a low-cost detail optimization that can significantly enhance the &#8220;native feel.&#8221;</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0122-06">Radioform: A Native, Open-Source macOS Audio Equalizer</a></strong></h3><p>macOS has long lacked a system-level audio equalizer. Radioform, developed by <a href="https://www.linkedin.com/in/matthew-porteous-23847a2b2/">Matthew Porteous</a>, fills this gap. The project employs a layered architecture of SwiftUI menu bar App + Swift Host + CoreAudio HAL Driver + C++ DSP, completely decoupling UI from real-time audio processing. The DSP portion implements 10-band parametric EQ, parameter smoothing, limiting, and real-time safety control; the engineering also includes complete CI, code signing notarization, and DMG release workflow. This isn&#8217;t a &#8220;just make it work&#8221; demo, but a production-grade audio engineering template approaching long-term maintainability.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-07">CircuitPro: Native macOS PCB Design Tool</a></strong></h3><p>This is a domain rarely explored by macOS native apps: PCB design. CircuitPro is a PCB EDA tool for macOS, aiming to make schematic, layout, and component library workflows more aligned with Apple platform conventions. (The project is still in early development stages)</p><p>What attracts me most about the project is the custom-built CanvasKit. It&#8217;s more like a 2D interaction engine for EDA scenarios rather than just a regular canvas component: the top layer is declarative <code>CanvasView</code>, the middle layer is the state hub <code>CanvasController</code>, and the bottom layer is input routing, render tree, and tool system. More critically, snapping, input handling, and wiring engine are all made into protocol-based pluggable points, allowing schematics and layout to share the same infrastructure while retaining their respective routing rules.</p><p>Even if you&#8217;re not interested in PCB design itself, CircuitPro is worth attention, especially for its engineering practices in SwiftUI + AppKit hybrid architecture.</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-122?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-122?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Xcode &#36808;&#20837; Agent &#26102;&#20195;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-122/">&#32593;&#39029;&#29256;</a></strong></p><p>&#23613;&#31649;&#22312; Xcode 26 &#30340;&#26368;&#21021;&#29256;&#26412;&#20013;&#65292;&#33529;&#26524;&#23601;&#24050;&#32463;&#21152;&#20837;&#20102;&#19968;&#23450;&#30340; AI &#36741;&#21161;&#32534;&#31243;&#33021;&#21147;&#65292;&#20294;&#24403;&#26102;&#30340;&#20307;&#39564;&#26356;&#20687;&#26159;&#25226; ChatGPT &#29983;&#30828;&#22320;&#23884;&#20837;&#21040; IDE &#20013;&#65306;&#21151;&#33021;&#23384;&#22312;&#65292;&#21364;&#24444;&#27492;&#21106;&#35010;&#12290;&#19982;&#24403;&#26102;&#39118;&#22836;&#27491;&#30427;&#30340; Cursor &#30456;&#27604;&#65292;&#23427;&#26356;&#20687;&#26159;&#20004;&#20010;&#26102;&#20195;&#30340;&#20135;&#29289;&#12290;&#38543;&#30528; Claude Code &#31561; AI CLI &#24037;&#20855;&#36880;&#28176;&#25104;&#29087;&#65292;Xcode &#26356;&#26174;&#24471;&#27493;&#20240;&#36831;&#32531;&#65292;&#29978;&#33267;&#35753;&#19981;&#23569;&#24320;&#21457;&#32773;&#24320;&#22987;&#24576;&#30097;&#65306;&#22312; AI &#26102;&#20195;&#65292;&#23427;&#26159;&#21542;&#36824;&#33021;&#32988;&#20219;&#8220;&#20027;&#21147; IDE&#8221;&#30340;&#35282;&#33394;&#12290;</p><p>26.3 &#29256;&#26412;&#30340;&#21040;&#26469;&#65292;&#20960;&#20046;&#27809;&#26377;&#20219;&#20309;&#39044;&#28909;&#65292;&#21364;&#29992;&#23454;&#38469;&#34892;&#21160;&#22238;&#24212;&#20102;&#36825;&#20123;&#36136;&#30097;&#12290;&#36890;&#36807;&#38598;&#25104; Claude Code / Codex&#65292;&#33529;&#26524;&#32473;&#20986;&#30340;&#31572;&#26696;&#24456;&#30452;&#25509;&#65306;&#21482;&#35201;&#31574;&#30053;&#24471;&#24403;&#65292;Xcode &#20381;&#28982;&#26159;&#33529;&#26524;&#29983;&#24577;&#20013;&#26497;&#20855;&#28508;&#21147;&#30340;&#24320;&#21457;&#29615;&#22659;&#12290;&#36825;&#19968;&#27425;&#65292;Xcode &#24182;&#27809;&#26377;&#31616;&#21333;&#22320;&#22622;&#36827;&#19968;&#20010; CLI &#24037;&#20855;&#38754;&#26495;&#65292;&#32780;&#26159;&#24341;&#20837;&#20102;&#19968;&#22871;&#21407;&#29983;&#30340; Xcode Tools&#65288;MCP&#65289;&#65292;&#24182;&#37197;&#21512; Swift 6&#12289;SwiftUI&#12289;SwiftData &#31561;&#23448;&#26041;&#25216;&#26415;&#25991;&#26723;&#65292;&#24418;&#25104;&#20102;&#39640;&#24230;&#19968;&#33268;&#12289;&#36148;&#21512;&#26368;&#26032;&#23454;&#36341;&#30340;&#25972;&#20307;&#20307;&#39564;&#12290;&#21363;&#20415;&#23545;&#20110;&#24050;&#32463;&#29087;&#32451;&#20351;&#29992; CLI + XcodeBuildMCP + &#21508;&#31867; Skills &#30340;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#36825;&#22871;&#21407;&#29983;&#26041;&#26696;&#20381;&#28982;&#20855;&#22791;&#24456;&#24378;&#30340;&#31454;&#20105;&#21147;&#8212;&#8212;&#23588;&#20854;&#26159;&#20960;&#20046;&#20026;&#38646;&#30340;&#37197;&#32622;&#25104;&#26412;&#65292;&#36825;&#23545;&#32477;&#22823;&#22810;&#25968;&#24320;&#21457;&#32773;&#26469;&#35828;&#24847;&#20041;&#37325;&#22823;&#12290;</p><p>&#26356;&#20540;&#24471;&#27880;&#24847;&#30340;&#26159;&#65292;&#36825;&#27425;&#25552;&#20379;&#30340; Xcode Tools &#24182;&#19981;&#21482;&#26159;&#26381;&#21153;&#20110; Xcode &#26412;&#36523;&#65292;&#23427;&#20204;&#21516;&#26679;&#21487;&#20197;&#20316;&#20026;&#26631;&#20934; MCP&#65292;&#20026;&#20854;&#20182; AI &#24037;&#20855;&#25552;&#20379;&#33021;&#21147;&#25903;&#25345;&#12290;&#36825;&#31181;&#24320;&#25918;&#23039;&#24577;&#65292;&#24182;&#19981;&#23436;&#20840;&#31526;&#21512;&#22806;&#30028;&#23545;&#33529;&#26524;&#19968;&#36143;&#39118;&#26684;&#30340;&#21360;&#35937;&#12290;</p><p>&#24403;&#28982;&#65292;&#31449;&#22312;&#20170;&#22825;&#36825;&#20010;&#26102;&#38388;&#28857;&#65292;&#25105;&#20204;&#36824;&#19981;&#33021;&#26029;&#35328; Xcode &#24050;&#32463;&#37325;&#26032;&#22238;&#21040;&#20102;&#31532;&#19968;&#38453;&#33829;&#12290;&#20294;&#21487;&#20197;&#32943;&#23450;&#30340;&#26159;&#65292;26.3 &#37322;&#25918;&#20102;&#19968;&#20010;&#38750;&#24120;&#26126;&#30830;&#30340;&#20449;&#21495;&#65306;&#33529;&#26524;&#24895;&#24847;&#19982;&#20027;&#27969;&#24037;&#20855;&#21644;&#26381;&#21153;&#21327;&#20316;&#65292;&#21435;&#25171;&#36896;&#30495;&#27491;&#31526;&#21512;&#26102;&#20195;&#30340;&#24320;&#21457;&#20307;&#39564;&#12290;&#20063;&#27491;&#22240;&#20026;&#22914;&#27492;&#65292;&#25105;&#23545;&#19979;&#19968;&#38454;&#27573;&#30340; Siri &#25265;&#26377;&#26356;&#39640;&#30340;&#26399;&#24453;&#8212;&#8212;&#24456;&#21487;&#33021;&#22312; iOS 27 &#20013;&#65292;&#33529;&#26524;&#20250;&#22312;&#29616;&#26377; Intent &#20307;&#31995;&#20043;&#22806;&#65292;&#20026;&#31995;&#32479;&#21644;&#24212;&#29992;&#25552;&#20379;&#26356;&#22810;&#26631;&#20934;&#21270;&#25509;&#21475;&#65292;&#35753; AI &#26356;&#33258;&#28982;&#22320;&#34701;&#20837;&#25972;&#20010;&#29983;&#24577;&#12290;</p><p>Xcode + Agent &#21482;&#26159;&#36215;&#28857;&#12290;</p><p>Apple + Agent&#65292;&#25165;&#26159;&#26356;&#20540;&#24471;&#20851;&#27880;&#30340;&#26410;&#26469;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-121/">&#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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/xcode-263-claude/?utm_source=fatbobman%20weekly%20issue%20122&amp;utm_medium=web">Xcode 26.3 + Claude Agent&#65306;&#27169;&#22411;&#26367;&#25442;&#12289;MCP&#12289;Skill &#19982;&#33258;&#36866;&#24212;&#37197;&#32622;</a></strong></h3><p>Xcode 26.3 &#29256;&#26412;&#20013;&#33529;&#26524;&#30452;&#25509;&#25552;&#20379;&#20102;&#23545; Claude Code/Codex &#30340;&#25903;&#25345;&#12290;&#33258;&#27492;&#65292;&#24320;&#21457;&#32773;&#32456;&#20110;&#21487;&#20197;&#22312; Xcode &#20013;&#26041;&#20415;&#30340;&#20351;&#29992;&#21407;&#29983; AI Agent &#20102;&#12290; &#36825;&#20004;&#22825;&#25105;&#38024;&#23545;&#26032;&#29256;&#26412;&#36827;&#34892;&#20102;&#19968;&#31995;&#21015;&#23581;&#35797;&#65292;&#21253;&#25324;&#22914;&#20309;&#20351;&#29992;&#26368;&#26032;&#27169;&#22411;&#12289;&#37197;&#32622; MCPs/Skill/Command&#12289;&#20197;&#21450;&#32534;&#20889;&#33258;&#36866;&#24212;&#30340; <code>CLAUDE.md</code>&#12290;&#26412;&#25991;&#20197; Claude Code &#20026;&#20363;&#65292;&#20998;&#20139;&#19968;&#20123;&#25991;&#26723;&#20043;&#22806;&#30340;&#25216;&#24039;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/screensage-from-pixel-to-meta/?utm_source=fatbobman%20weekly%20issue%20122&amp;utm_medium=web">macOS &#24405;&#23631;&#36719;&#20214;&#24320;&#21457;&#23454;&#24405;&#65306;&#20174;&#20687;&#32032;&#25235;&#21462;&#21040;&#20803;&#25968;&#25454;&#37325;&#29616;</a></strong></h3><p>&#35270;&#39057;&#27491;&#22312;&#21462;&#20195;&#25991;&#23383;&#25104;&#20026;&#26356;&#21463;&#27426;&#36814;&#30340;&#34920;&#36798;&#26041;&#24335;&#65292;&#32780;&#22909;&#24037;&#20855;&#26159;&#21019;&#20316;&#30340;&#21152;&#36895;&#22120;&#12290;macOS &#24405;&#23631;&#36719;&#20214; <a href="https://screensage.pro/zh">ScreenSage Pro</a> &#30340;&#24320;&#21457;&#32773; <a href="https://x.com/s1ntone">Sintone</a> &#28145;&#24230;&#22797;&#30424;&#20102;&#22914;&#20309;&#22522;&#20110; ScreenCaptureKit &#21644; Metal &#23454;&#29616;&#8220;&#24405;&#23436;&#21363;&#21098;&#23436;&#8221;&#12290;&#20174;&#35299;&#20915; SCK -3821 &#35809;&#24322;&#25253;&#38169;&#65292;&#21040;&#30001; ObservableObject &#36801;&#31227;&#33267; @Observable &#20248;&#21270;&#26102;&#38388;&#32447;&#24615;&#33021;&#65292;&#26412;&#25991;&#27627;&#26080;&#20445;&#30041;&#22320;&#20998;&#20139;&#20102;&#20174;&#20687;&#32032;&#25235;&#21462;&#21040;&#39640;&#24615;&#33021;&#21512;&#25104;&#30340;&#20840;&#36807;&#31243;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-05">&#21738;&#31181;&#26041;&#24335;&#21028;&#26029;&#23383;&#31526;&#20018;&#26159;&#21542;&#22312;&#30333;&#21517;&#21333;&#37324;&#26368;&#24555;&#65306;Set&#12289;Array&#12289;Enum&#12289;Dictionary &#36824;&#26159; switch?</a></strong></h3><p>&#22312; Swift &#37324;&#65292;&#21028;&#26029;&#19968;&#20010;&#23383;&#31526;&#20018;&#26159;&#21542;&#23646;&#20110;&#26576;&#20010;&#38190;&#38598;&#21512;&#65292;&#21487;&#20197;&#20889;&#25104; <code>Set.contains</code>&#12289;<code>Array.contains</code>&#12289;RawRepresentable enum &#30340; <code>init?(rawValue:)</code>&#12289;<code>switch</code> &#22810;&#20998;&#25903;&#65292;&#29978;&#33267;&#29992; <code>Dictionary</code> &#26469;&#20570;&#26144;&#23556;&#12290;&#30475;&#36215;&#26469;&#24046;&#21035;&#19981;&#22823;&#65292;&#20294;&#30495;&#35201;&#25918;&#36827;&#24615;&#33021;&#25935;&#24863;&#36335;&#24452;&#65292;&#32467;&#26524;&#21487;&#33021;&#24182;&#19981;&#23436;&#20840;&#31526;&#21512;&#30452;&#35273;&#12290;<a href="https://mastodon.social/@helge">Helge He&#223;</a> &#20570;&#20102;&#19968;&#27425;&#31616;&#21333;&#30340;&#22522;&#20934;&#27979;&#35797;&#65306;<code>Set.contains</code> &#27627;&#26080;&#24748;&#24565;&#22320;&#39046;&#20808;&#65292;&#20854;&#27425;&#26159; <code>enum(rawValue:)</code>&#21644; <code>Dictionary</code>&#65288;&#20004;&#32773;&#38750;&#24120;&#25509;&#36817;&#65289;&#65307;&#32780;&#24456;&#22810;&#20154;&#19979;&#24847;&#35782;&#20250;&#39640;&#20272;&#30340; <code>switch</code>&#65292;&#21453;&#32780;&#25490;&#22312; <code>enum</code> &#20043;&#21518;&#65292;<code>Array.contains</code> &#21017;&#22443;&#24213;&#25910;&#22330;&#12290;&#20316;&#20026;&#19968;&#20010;&#23567;&#23454;&#39564;&#65292;&#36825;&#20010;&#32467;&#26524;&#25110;&#35768;&#27491;&#22909;&#21487;&#20197;&#25343;&#26469;&#26657;&#20934;&#19968;&#19979;&#25105;&#20204;&#23545; Swift &#24615;&#33021;&#30340;&#30452;&#35273;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-01">&#20174;&#19968;&#27425;&#24615;&#20184;&#36153;&#21040; Freemium (Migrating an iOS app from Paid up Front to Freemium)</a></strong></h3><p>&#20184;&#36153;&#19979;&#36733;&#21644;&#20813;&#36153; + &#24212;&#29992;&#20869;&#36141;&#20080;&#26159;&#20004;&#31181;&#25130;&#28982;&#19981;&#21516;&#30340;&#21830;&#19994;&#27169;&#24335;&#65292;&#38543;&#30528;&#24212;&#29992;&#21457;&#23637;&#65292;&#24320;&#21457;&#32773;&#21487;&#33021;&#38656;&#35201;&#22312;&#20004;&#32773;&#20043;&#38388;&#36716;&#25442;&#12290;<a href="https://x.com/donnywals">Donny Wals</a> &#22312;&#26412;&#25991;&#20013;&#20998;&#20139;&#20102;&#20182;&#23558; Practical Core Data &#24212;&#29992;&#20174; $4.99 &#20184;&#36153;&#19979;&#36733;&#36716;&#20026; freemium &#30340;&#23436;&#25972;&#32463;&#21382;&#12290;&#25991;&#31456;&#19981;&#20165;&#28085;&#30422;&#20102; StoreKit 2 &#30340;&#25216;&#26415;&#23454;&#29616;&#32454;&#33410;&#65288;&#36141;&#20080;&#27969;&#31243;&#12289;&#29366;&#24577;&#31649;&#29702;&#12289;&#23478;&#24237;&#20849;&#20139;&#65289;&#65292;&#26356;&#26377;&#20215;&#20540;&#30340;&#26159;&#20182;&#23545;&#21830;&#19994;&#20915;&#31574;&#30340;&#28145;&#20837;&#24605;&#32771;&#65306;&#20184;&#36153;&#38376;&#27099;&#34429;&#28982;&#33021;&#31579;&#36873;&#20986;&#35748;&#30495;&#30340;&#29992;&#25143;&#65292;&#20294;&#20063;&#38459;&#25377;&#20102;&#22823;&#37327;&#28508;&#22312;&#29992;&#25143;&#20307;&#39564;&#20135;&#21697;&#20215;&#20540;&#30340;&#26426;&#20250;&#12290;&#23545;&#20110;&#25945;&#32946;&#31867;&#25110;&#24037;&#20855;&#31867;&#29420;&#31435;&#24212;&#29992;&#65292;freemium &#21487;&#33021;&#26159;&#29992;&#25143;&#22686;&#38271;&#21644;&#25910;&#20837;&#20043;&#38388;&#26356;&#22909;&#30340;&#24179;&#34913;&#28857;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-02">iOS &#24212;&#29992;&#20013;&#30340;&#25353;&#38656;&#36164;&#28304; (On-demand resources in iOS app)</a></strong></h3><p>&#24212;&#29992;&#20307;&#31215;&#19968;&#30452;&#26159;&#24320;&#21457;&#32773;&#38656;&#35201;&#20851;&#27880;&#30340;&#38382;&#39064;&#65292;&#23588;&#20854;&#26159;&#22312;&#24212;&#29992;&#21253;&#21547;&#22823;&#37327;&#22270;&#29255;&#12289;&#38899;&#39057;&#25110;&#20854;&#20182;&#36164;&#28304;&#26102;&#12290;&#23613;&#31649;&#33529;&#26524;&#24456;&#26089;&#23601;&#22312; iOS &#20013;&#25552;&#20379;&#20102; On-Demand Resources&#65288;ODR&#65289;&#26469;&#24212;&#23545;&#36825;&#19968;&#25361;&#25112;&#65292;&#20294;&#36825;&#19968;&#21151;&#33021;&#30340;&#23384;&#22312;&#24863;&#24182;&#19981;&#24378;&#65292;&#24120;&#34987;&#24320;&#21457;&#32773;&#24573;&#30053;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://twitter.com/mecid">Majid Jabrayilov</a> &#31995;&#32479;&#24615;&#22320;&#22238;&#39038;&#20102; ODR &#30340;&#24037;&#20316;&#26426;&#21046;&#19982;&#20351;&#29992;&#26041;&#24335;&#65292;&#21253;&#25324;&#36164;&#28304;&#20998;&#32452;&#12289;&#26631;&#31614;&#31649;&#29702;&#12289;&#19979;&#36733;&#29983;&#21629;&#21608;&#26399;&#65292;&#20197;&#21450;&#19982;&#31995;&#32479;&#32531;&#23384;&#31574;&#30053;&#20043;&#38388;&#30340;&#21327;&#20316;&#20851;&#31995;&#12290;</p><p>&#34429;&#28982;&#33529;&#26524;&#22312;&#25512;&#24191; Background Assets &#20316;&#20026;&#26356;&#29616;&#20195;&#30340;&#26041;&#26696;&#65292;&#20294; ODR &#22312;&#38656;&#35201;&#21363;&#26102;&#21709;&#24212;&#30340;&#25353;&#38656;&#19979;&#36733;&#12289;&#32454;&#31890;&#24230;&#36164;&#28304;&#25511;&#21046;&#31561;&#22330;&#26223;&#19979;&#20173;&#26377;&#20854;&#29420;&#29305;&#20215;&#20540;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-03">Observation &#22235;&#20010;&#24120;&#35265;&#38519;&#38449; (Objectively Better, Observably Trickier)</a></strong></h3><p>&#22312;&#20840;&#38754;&#25317;&#25265; Observation &#26694;&#26550;&#26102;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#35686;&#24789;&#20854;&#24037;&#20316;&#26426;&#21046;&#19982; Combine &#30340; <code>@Published</code> &#24182;&#19981;&#30456;&#21516;&#65292;&#31616;&#21333;&#26367;&#25442;&#24448;&#24448;&#20250;&#24341;&#20837;&#38544;&#34109;&#30340;&#38382;&#39064;&#12290;<a href="https://x.com/dbolella">Danny Bolella</a> &#24635;&#32467;&#20102;&#36801;&#31227;&#36807;&#31243;&#20013;&#22235;&#20010;&#24120;&#35265;&#38519;&#38449;&#65306;<code>@State</code> &#25345;&#26377;&#24341;&#29992;&#31867;&#22411;&#26102;&#30340;&#38750;&#24816;&#24615;&#21021;&#22987;&#21270;&#12289;&#23884;&#22871; <code>@Observable</code> &#23545;&#35937;&#23548;&#33268;&#30340;&#26356;&#26032;&#20002;&#22833;&#12289;&#25968;&#32452;&#20803;&#32032;&#32465;&#23450;&#26041;&#24335;&#30340;&#21464;&#21270;&#65292;&#20197;&#21450;&#19982;&#20854;&#20182;&#23646;&#24615;&#21253;&#35013;&#22120;&#20135;&#29983;&#30340;&#20914;&#31361;&#12290;&#25991;&#31456;&#36890;&#36807;&#28165;&#26224;&#30340;&#20195;&#30721;&#31034;&#20363;&#36880;&#19968;&#32473;&#20986;&#35299;&#20915;&#26041;&#26696;&#65292;&#24182;&#21453;&#22797;&#24378;&#35843;&#19968;&#20010;&#26680;&#24515;&#21407;&#21017;&#65306;&#21482;&#26377;&#35270;&#22270;&#24403;&#21069;&#27491;&#22312;&#35775;&#38382;&#65288;&#35843;&#29992; getter&#65289;&#30340;&#23646;&#24615;&#21457;&#29983;&#21464;&#21270;&#26102;&#65292;&#25165;&#20250;&#35302;&#21457;&#26356;&#26032;&#12290;&#29702;&#35299;&#24182;&#39034;&#24212;&#36825;&#31181;&#8220;&#24816;&#24615;&#35266;&#23519;&#8221;&#30340;&#24605;&#32500;&#26041;&#24335;&#65292;&#26159;&#27491;&#30830;&#20351;&#29992; Observation &#26694;&#26550;&#30340;&#20851;&#38190;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-04">&#22312; macOS &#24212;&#29992;&#20013;&#23454;&#29616; Open Recent &#33756;&#21333; (Add an Open Recent Menu to a SwiftUI app)</a></strong></h3><p>&#8220;Open Recent&#8221; &#26159; macOS &#24212;&#29992;&#30340;&#26631;&#20934;&#21151;&#33021;&#65292;&#20294;&#23545;&#20110; SwiftUI &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#27491;&#30830;&#23454;&#29616;&#36825;&#20010;&#21151;&#33021;&#24182;&#19981;&#30452;&#35266;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://mastodon.world/@swiftdevjournal">Mark Szymczyk</a> &#36890;&#36807;&#19968;&#20010;&#31616;&#27905;&#30340;&#31034;&#20363;&#65292;&#23637;&#31034;&#20102;&#22914;&#20309;&#21033;&#29992; <code>NSDocumentController</code> &#20026;&#24212;&#29992;&#25509;&#20837;&#31995;&#32479;&#32423;&#30340;&#26368;&#36817;&#25991;&#20214;&#31649;&#29702;&#33021;&#21147;&#65306;&#33258;&#21160;&#32500;&#25252;&#21015;&#34920;&#12289;&#26356;&#26032;&#33756;&#21333;&#65292;&#20197;&#21450;&#19982;&#25991;&#26723;&#29983;&#21629;&#21608;&#26399;&#30340;&#26080;&#32541;&#21327;&#20316;&#12290;&#23545;&#20110;&#25991;&#26723;&#22411;&#25110;&#24037;&#20855;&#31867;&#24212;&#29992;&#65292;&#36825;&#26159;&#19968;&#20010;&#20302;&#25104;&#26412;&#12289;&#21364;&#33021;&#26126;&#26174;&#25552;&#21319;&#8220;&#21407;&#29983;&#24863;&#8221;&#30340;&#32454;&#33410;&#20248;&#21270;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0122-06">Radioform&#65306;&#19968;&#20010;&#21407;&#29983;&#12289;&#24320;&#28304;&#30340; macOS &#38899;&#39057;&#22343;&#34913;&#22120;</a></strong></h3><p>macOS &#19968;&#30452;&#32570;&#23569;&#31995;&#32479;&#32423;&#30340;&#38899;&#39057;&#22343;&#34913;&#22120;&#65292;&#30001; <a href="https://www.linkedin.com/in/matthew-porteous-23847a2b2/">Matthew Porteous</a> &#24320;&#21457;&#30340; Radioform &#22635;&#34917;&#20102;&#36825;&#20010;&#31354;&#30333;&#12290;&#35813;&#39033;&#30446;&#37319;&#29992; SwiftUI &#33756;&#21333;&#26639; App + Swift Host + CoreAudio HAL Driver + C++ DSP &#30340;&#20998;&#23618;&#26550;&#26500;&#65292;&#25226; UI &#19982;&#23454;&#26102;&#38899;&#39057;&#22788;&#29702;&#24443;&#24213;&#35299;&#32806;&#12290;DSP &#37096;&#20998;&#23454;&#29616;&#20102; 10 &#27573;&#21442;&#25968; EQ&#12289;&#21442;&#25968;&#24179;&#28369;&#12289;&#38480;&#24133;&#19982;&#23454;&#26102;&#23433;&#20840;&#25511;&#21046;&#65307;&#24037;&#31243;&#19978;&#20063;&#26377;&#23436;&#25972; CI&#12289;&#31614;&#21517;&#20844;&#35777;&#19982; DMG &#21457;&#24067;&#27969;&#31243;&#12290;&#19981;&#26159;&#8220;&#33021;&#36305;&#23601;&#34892;&#8221;&#30340; Demo&#65292;&#32780;&#26159;&#25509;&#36817;&#21487;&#38271;&#26399;&#32500;&#25252;&#30340;&#29983;&#20135;&#32423;&#38899;&#39057;&#24037;&#31243;&#26679;&#26495;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0122-07">CircuitPro&#65306;macOS &#21407;&#29983;&#30340; PCB &#35774;&#35745;&#24037;&#20855;</a></strong></h3><p>&#36825;&#26159;&#19968;&#20010; macOS &#21407;&#29983;&#24212;&#29992;&#36739;&#23569;&#28041;&#36275;&#30340;&#39046;&#22495;&#65306;PCB &#35774;&#35745;&#12290;CircuitPro &#26159;&#19968;&#27454;&#38754;&#21521; macOS &#30340; PCB EDA &#24037;&#20855;&#65292;&#30446;&#26631;&#26159;&#25226;&#21407;&#29702;&#22270;&#12289;&#24067;&#23616;&#19982;&#20803;&#20214;&#24211;&#27969;&#31243;&#20570;&#25104;&#26356;&#31526;&#21512; Apple &#24179;&#21488;&#20064;&#24815;&#30340;&#20307;&#39564;&#12290;&#65288;&#39033;&#30446;&#20173;&#22788;&#20110;&#26089;&#26399;&#24320;&#21457;&#38454;&#27573;&#65289;</p><p>&#39033;&#30446;&#37324;&#26368;&#21560;&#24341;&#25105;&#30340;&#26159;&#33258;&#30740;&#30340; CanvasKit&#12290;&#23427;&#26356;&#20687;&#19968;&#20010;&#38754;&#21521; EDA &#22330;&#26223;&#30340; 2D &#20132;&#20114;&#24341;&#25806;&#65292;&#32780;&#19981;&#21482;&#26159;&#26222;&#36890;&#30011;&#24067;&#32452;&#20214;&#65306;&#19978;&#23618;&#26159;&#22768;&#26126;&#24335; <code>CanvasView</code>&#65292;&#20013;&#23618;&#26159;&#29366;&#24577;&#20013;&#26530; <code>CanvasController</code>&#65292;&#24213;&#23618;&#26159;&#36755;&#20837;&#36335;&#30001;&#12289;&#28210;&#26579;&#26641;&#19982;&#24037;&#20855;&#31995;&#32479;&#12290;&#26356;&#20851;&#38190;&#30340;&#26159;&#65292;&#21560;&#38468;&#12289;&#36755;&#20837;&#22788;&#29702;&#12289;&#36830;&#32447;&#24341;&#25806;&#37117;&#34987;&#20570;&#25104;&#20102;&#21327;&#35758;&#21270;&#25554;&#25300;&#28857;&#65292;&#35753;&#21407;&#29702;&#22270;&#21644;&#24067;&#23616;&#20849;&#20139;&#21516;&#19968;&#22522;&#30784;&#35774;&#26045;&#65292;&#21516;&#26102;&#20445;&#30041;&#21508;&#33258;&#30340;&#36335;&#30001;&#35268;&#21017;&#12290;</p><p>&#21363;&#20415;&#20320;&#23545; PCB &#35774;&#35745;&#26412;&#36523;&#19981;&#24863;&#20852;&#36259;&#65292;CircuitPro &#20063;&#24456;&#20540;&#24471;&#20851;&#27880;&#65292;&#23588;&#20854;&#26159;&#23427;&#22312; SwiftUI + AppKit &#34701;&#21512;&#26550;&#26500;&#19978;&#30340;&#24037;&#31243;&#23454;&#36341;&#12290;</p><h2><strong>&#27714;&#36132;</strong></h2><h3><strong><a href="mailto:xx2bab@gmail.com">&#20102;&#35299;&#20108;&#27425;&#20803;&#30340; iOS &#24037;&#31243;&#24072;</a></strong></h3><p>&#26412;&#20844;&#21496;&#26159;&#20108;&#27425;&#20803;&#25991;&#29983;&#22270;&#22836;&#37096;&#20225;&#19994;&#65288;&#24635;&#37096;&#26032;&#21152;&#22369;&#65289;&#65292;&#25307;&#32856;&#23703;&#20301;&#20026;&#22823;&#38470;&#20840;&#32844; remote&#12290;&#27714;&#32844;&#32773;&#38656;&#35201;&#20102;&#35299;&#20108;&#27425;&#20803;&#25991;&#21270;&#65292;&#25026;&#24471;&#20108;&#27425;&#20803;&#29992;&#35821;&#65288;&#40657;&#35805;&#65289;&#12290;</p><h4><strong>&#23703;&#20301;&#32844;&#36131; (Responsibilities):</strong></h4><ul><li><p>&#25105;&#20204;&#27491;&#22312;&#23547;&#25214;&#19968;&#20301;&#32463;&#39564;&#20016;&#23500;&#30340; iOS &#24037;&#31243;&#24072;&#65288;&#20013;&#39640;&#32423;&#65289;&#65292;&#36127;&#36131;&#20027;&#23548;&#25105;&#20204; iOS &#24212;&#29992;&#30340;&#24320;&#21457;&#19982;&#20248;&#21270;&#24037;&#20316;&#12290;</p></li><li><p>&#29702;&#24819;&#30340;&#20505;&#36873;&#20154;&#24212;&#20855;&#22791;&#28145;&#21402;&#30340; Swift &#25216;&#26415;&#21151;&#24213;&#65292;&#20986;&#33394;&#30340;&#27979;&#35797;&#19982;&#22242;&#38431;&#21327;&#20316;&#33021;&#21147;&#65292;&#24182;&#25317;&#26377;&#29616;&#20195; iOS &#26550;&#26500;&#21450;&#24037;&#20855;&#38142;&#30340;&#23454;&#25112;&#32463;&#39564;&#12290;</p></li></ul><h4><strong>&#20219;&#32844;&#35201;&#27714; (Requirements):</strong></h4><ul><li><p><strong>3 &#24180;&#20197;&#19978; iOS &#24320;&#21457;&#32463;&#39564;</strong>&#65292;&#20027;&#35201;&#20351;&#29992; Swift&#65292;&#21516;&#26102;&#20855;&#22791;&#19968;&#23450;&#30340; Objective-C &#20195;&#30721;&#32500;&#25252;&#33021;&#21147;&#12290;</p></li><li><p><strong>&#33267;&#23569; 1 &#24180;&#30340; SwiftUI &#21644; SPM (Swift Package Manager) &#23454;&#25112;&#32463;&#39564;</strong>&#65292;&#29087;&#24713;&#20854;&#29983;&#24577;&#31995;&#32479;&#21450;&#26368;&#20339;&#23454;&#36341;&#12290;</p></li><li><p><strong>&#29087;&#24713; iOS 15+ &#26032;&#29305;&#24615;</strong>&#65292;&#33021;&#22815;&#38024;&#23545;&#19981;&#21516;&#30340; iOS &#29256;&#26412;&#21644;&#35774;&#22791;&#23631;&#24149;&#23610;&#23544;&#36827;&#34892;&#36866;&#37197;&#21450;&#24615;&#33021;&#20248;&#21270;&#12290;</p></li><li><p><strong>&#25484;&#25569;&#21333;&#20803;&#27979;&#35797;&#21644; UI &#33258;&#21160;&#21270;&#27979;&#35797;</strong> (XCTest, XCUITest)&#65292;&#26377;&#33021;&#21147;&#32534;&#20889;&#21487;&#32500;&#25252;&#30340;&#20195;&#30721;&#65292;&#20197;&#30830;&#20445;&#39033;&#30446;&#30340;&#31283;&#23450;&#24615;&#21644;&#21487;&#25193;&#23637;&#24615;&#12290;</p></li><li><p><strong>&#31934;&#36890; Git &#24037;&#20316;&#27969;</strong>&#65288;Git Flow, &#20027;&#24178;&#24320;&#21457;/Trunk-Based Development&#65289;&#65292;&#24182;&#20855;&#22791;&#22522;&#26412;&#30340;&#20195;&#30721;&#23457;&#26597; (Code Review) &#25216;&#33021;&#12290;</p></li><li><p><strong>&#29702;&#35299;&#22522;&#30784;&#30340; iOS &#24212;&#29992;&#27169;&#22359;&#21270;&#35774;&#35745;&#12289;&#22810;&#31181;&#21333;&#39029;&#38754;&#26550;&#26500;&#27169;&#24335;</strong>&#20197;&#21450;&#24615;&#33021;&#20248;&#21270;&#26041;&#27861;&#65292;&#24182;&#20855;&#22791;&#22312;&#39033;&#30446;&#20013;&#33853;&#22320;&#30340;&#33021;&#21147;&#12290;</p></li></ul><h4><strong>&#21152;&#20998;&#39033;/&#20248;&#20808;&#32771;&#34385; (We will give priority to who):</strong></h4><ul><li><p><strong>&#25317;&#26377;&#36328;&#24179;&#21488;&#24320;&#21457;&#32463;&#39564;</strong>&#65288;&#28385;&#36275;&#20197;&#19979;&#20219;&#24847;&#19968;&#39033;&#21363;&#21487;&#65289;&#65306;</p><ul><li><p>6 &#20010;&#26376;&#20197;&#19978;&#30340;&#20219;&#24847;&#21069;&#31471;&#25216;&#26415;&#26632;&#32463;&#39564; (TypeScript/JavaScript, React, React Native)&#12290;</p></li><li><p>6 &#20010;&#26376;&#20197;&#19978;&#20351;&#29992; Kotlin &#21450;&#30456;&#20851;&#26694;&#26550;&#30340; Android &#24320;&#21457;&#32463;&#39564;&#12290;</p></li><li><p>6 &#20010;&#26376;&#20197;&#19978;&#30340;&#20219;&#24847;&#21518;&#31471;&#24320;&#21457;&#26694;&#26550;&#32463;&#39564;&#12290;</p></li></ul></li><li><p><strong>&#25317;&#26377;&#33267;&#23569; 6 &#20010;&#26376;&#30340; iOS &#22522;&#30784;&#35774;&#26045;&#24037;&#20855;&#25110;&#26694;&#26550;&#25645;&#24314;&#32463;&#39564;</strong>&#65292;&#21253;&#25324;&#20195;&#30721;&#36136;&#37327;&#25552;&#21319;&#65288;Linting, &#38745;&#24577;&#20998;&#26512;, CI/CD&#65289;&#12289;&#25928;&#29575;&#20248;&#21270;&#65288;&#27169;&#22359;&#21270;&#65292;Gradle &#32452;&#20214;&#21270;*&#65289;&#12289;&#20197;&#21450;&#24615;&#33021;&#35843;&#20248;&#65288;&#21551;&#21160;&#36895;&#24230;&#12289;&#24103;&#29575;&#12289;&#31163;&#32447;&#27169;&#24335;&#12289;&#22810;&#32447;&#31243;&#65289;&#12290;</p></li><li><p><strong>&#25317;&#26377; 1 &#24180;&#20197;&#19978; SDK &#24320;&#21457;&#32463;&#39564;</strong>&#65292;&#21253;&#25324;&#36890;&#29992;&#24211;&#24320;&#21457;&#65292;&#22914;&#22270;&#29255;&#21152;&#36733;&#24211; (SDWebImage, Kingfisher)&#12289;&#23500;&#25991;&#26412;&#32534;&#36753;&#22120;&#12289;&#32593;&#32476;&#23618;&#25110;&#25345;&#20037;&#21270;&#23618; (SQLite, Realm, Core Data)&#12290;</p></li><li><p><strong>&#20855;&#22791; UI/UX &#30456;&#20851;&#32463;&#39564;</strong>&#65306;</p><ul><li><p>&#29087;&#24713; Apple &#20154;&#26426;&#20132;&#20114;&#25351;&#21335; (HIG)&#65292;&#33021;&#22815;&#22312;&#29702;&#35299;&#36328;&#24179;&#21488;&#35774;&#35745;&#24046;&#24322;&#30340;&#21516;&#26102;&#65292;&#23454;&#29616;&#31526;&#21512; Apple &#35774;&#35745;&#26631;&#20934;&#30340; UI&#12290;</p></li><li><p>&#25317;&#26377;&#25166;&#23454;&#30340;&#21160;&#30011;&#21644;&#20132;&#20114;&#21160;&#25928;&#24320;&#21457;&#32463;&#39564;&#65292;&#29087;&#24713; Core Animation, UIKit Dynamics &#31561;&#12290;</p></li><li><p>&#26377;<strong>&#28145;&#33394;&#27169;&#24335; (Dark Mode)</strong> &#21450;&#20027;&#39064;&#20999;&#25442;&#21151;&#33021;&#30340;&#24320;&#21457;&#32463;&#39564;&#12290;</p></li></ul></li><li><p><strong>&#20855;&#22791;&#26497;&#24378;&#30340;&#23457;&#32654;&#24863;&#30693;&#21147;</strong>&#65292;&#25317;&#26377;&#32472;&#30011;&#12289;&#25668;&#24433;&#25110;&#35774;&#35745;&#30456;&#20851;&#30340;&#25216;&#33021;&#25110;&#29233;&#22909;&#65288;&#38468;&#24102;&#20316;&#21697;&#38598;&#32773;&#20248;&#20808;&#65289;&#12290;</p></li><li><p><strong>&#25317;&#26377;&#23436;&#25972;&#30340; App &#29983;&#21629;&#21608;&#26399;&#32463;&#39564;</strong>&#65306;&#26366;&#29420;&#31435;&#24320;&#21457;&#12289;&#21457;&#24067;&#24182;&#32500;&#25252;&#36807;&#25903;&#25345;&#22810;&#22269;/&#22810;&#35821;&#35328;&#30340; iOS &#24212;&#29992;&#12290;</p></li><li><p><strong>&#31215;&#26497;&#21442;&#19982;&#25216;&#26415;&#31038;&#21306;</strong>&#65292;&#20363;&#22914;&#65306;</p><ul><li><p>&#20855;&#26377;&#20027;&#21160;&#23398;&#20064;&#21644;&#20998;&#20139;&#30340;&#24515;&#24577;&#65292;&#26377;&#36827;&#34892;&#25216;&#26415;&#28436;&#35762;&#30340;&#32463;&#39564;&#12290;</p></li><li><p>&#26377;&#25216;&#26415;&#20889;&#20316;&#32463;&#39564;&#65288;&#21338;&#23458;&#12289;&#25991;&#31456;&#65289;&#12290;</p></li><li><p>&#26377;&#24320;&#28304;&#39033;&#30446;&#36129;&#29486;&#32463;&#21382;&#12290;</p></li></ul></li><li><p><strong>&#26377;&#20351;&#29992; AI &#32534;&#31243;&#24037;&#20855;&#30340;&#32463;&#39564;</strong>&#65292;&#22914; Claude, ChatGPT, GitHub Copilot, Cursor &#25110; Windsurf&#12290;</p></li><li><p><strong>&#20855;&#22791;&#27969;&#21033;&#30340;&#33521;&#35821;&#27807;&#36890;&#33021;&#21147;&#25110;&#25345;&#26377;&#26085;&#35821; N2 &#35777;&#20070;&#12290;</strong></p></li></ul><h4><strong>&#32852;&#31995;&#20154;</strong></h4><p><a href="mailto:xx2bab@gmail.com">xx2bab@gmail.com</a></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #121]]></title><description><![CDATA[Shifting Light, Unchanging Haystacks]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-121</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-121</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 02 Feb 2026 12:03:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2lY2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.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_!2lY2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2lY2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 424w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 848w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 1272w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2lY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp" width="1456" height="684" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:684,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:47796,&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/186581582?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.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_!2lY2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 424w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 848w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.webp 1272w, https://substackcdn.com/image/fetch/$s_!2lY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F927028ca-950c-40ea-91ac-181dd002a27a_1915x899.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"><svg role="img" 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"><g><title></title><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"><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"><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>Shifting Light, Unchanging Haystacks</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-121/">Read on web &#8594;</a></p><p>Two weeks ago, taking the opportunity of attending iOS Conf SG 2026, I visited the National Gallery Singapore and had the pleasure of viewing the special exhibition <em>&#8220;Into the Modern: Impressionism from the Museum of Fine Arts, Boston&#8221;</em>. Although I have seen many excellent exhibitions in the past, this experience resonated with me in a distinct and unexpected way.</p><p>The National Gallery Singapore is formed by merging two historically significant national monuments&#8212;the former Supreme Court and the City Hall. Architects connected these two classical structures with a minimalist metal and glass roof, creating a striking sense of place architecturally: history and modernity intertwined within the same physical space. The ongoing exhibition <em>&#8220;Into the Modern&#8221;</em>, which features over one hundred original works by masters such as Monet, Renoir, Manet, C&#233;zanne, and Degas, elevates this cross-temporal dialogue to the realm of art.</p><p>The exhibition does not simply follow a chronological timeline; instead, it uses &#8220;modernity&#8221; as its core narrative thread, unfolding layer by layer through themes like &#8220;Cities and Change&#8221;, &#8220;Light and Moments,&#8221; and &#8220;Class and Leisure&#8221;. Although the &#8220;modern&#8221; here refers to the late 19th century, the urban renewal of Paris, the evolution of lighting techniques, and the rise of new forms of leisure depicted in the paintings all demonstrate, from multiple dimensions, the rhythm of social progress in that era. In this space where time and geography cross, the exhibition goes far beyond the mere level of &#8220;viewing art.&#8221; For someone like me, who is swept along daily by the torrent of &#8220;new tech&#8221; information on social media, this was a rare moment of tranquility and introspection.</p><p>Returning to reality, in just the past few days, the names of the hottest AI projects have shifted from Clawdbot to Moltbot, and then rapidly evolved into OpenClaw. From a microscopic perspective, we seem to be living in an era of change measured in minutes and seconds. However, if we were to look back at the current AI fever from a longer time scale years from now, we might discover that the world did not undergo the radical, fundamental mutations that we perceive while caught in the current.</p><p>Immersed in this environment, it is inevitable that we feel excitement&#8212;or even anxiety&#8212;over the endless stream of new technologies and tools. Perhaps, beyond these emotions, what we need is a deeper sense of grounding. History repeatedly reminds us that any &#8220;high tech&#8221; has its temporal limitations. Just as Monet repeatedly depicted the same haystack under different times and lighting conditions: the painting techniques may evolve, but the core object remains unchanged. What truly changes is often the way of seeing, the depth of understanding, and the creator&#8217;s own state of mind.</p><p>When facing the &#8220;present and future&#8221;, perhaps we can afford to be less frantic in our pursuit of change, and more composed in our contemplation of the moment.</p><p><a href="https://fatbobman.com/en/weekly/issue-120/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2><strong>This Week&#8217;s Sponsor</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-proxyman">Need to debug HTTPS on your iPhone?</a></strong></h3><p>Try Proxyman! The best-in-class macOS that helps you capture/debug HTTP(s) with a few clicks. Support iOS devices and Simulator.</p><p><a href="https://l.fatbobman.com/sb-proxyman">&#128640; Get Started Now &#8594;</a></p><div><hr></div><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0121-01">DebugReplaceableView and Swift 6.2&#8217;s Multiple Type Erasers</a></strong></h3><p>You may still find Xcode Previews less than ideal, but Apple has been actively optimizing this experience over the past few years with notable progress. Starting with Xcode 16, views are automatically converted to <code>AnyView</code> via <code>@_typeEraser</code> in preview and debug modes to provide richer debugging information. From Xcode 26 onwards, the enhanced <code>@_typeEraser</code>now supports multiple type erasers, converting views to <code>DebugReplaceableView</code> on macOS/iOS 26+ platforms. This enables hot-swapping of views without rebuilding the entire view hierarchy, further improving preview performance. In this article, <a href="https://x.com/KyleSwifter">Kyle Ye</a> dives deep into the compiler source code to analyze the implementation, explaining how the compiler automatically selects the appropriate type eraser based on platform availability.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-02">Tiered Caching in Swift</a></strong></h3><p>When you need to balance performance, memory footprint, and data consistency simultaneously, a single caching strategy often falls short. In this article, <a href="https://linkedin.com/in/kyle-browning-eng-manager">Kyle Browning</a> provides a practical guide to implementing tiered caching in Swift: organizing memory and disk caches into a clear hierarchical structure, combined with flexible cache policies (such as <code>cacheThenFetch</code>, <code>cacheElseFetch</code>, etc.) to enable data to flow smoothly between different access cost tiers.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-03">SwiftUI: Realtime, Multi-User Content Collaboration With CloudFlare +YJS-Swift</a></strong></h3><p>Despite the availability of numerous services and frameworks, implementing real-time collaborative editing remains a significant engineering challenge. In this article, <a href="https://x.com/itsuki68391179">Itsuki</a> demonstrates how to build a low-cost, scalable, multi-user real-time collaborative content editing system in SwiftUI using Cloudflare Durable Objects + WebSocket Hibernation API + YJS-Swift.</p><p>Particularly noteworthy is the author&#8217;s detailed explanation of how to properly maintain text cursor and selection positions when receiving remote content updates in SwiftUI&#8212;this is closely aligned with real-world product development and clearly represents hard-won experience from actual implementation.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-04">Swift Actors: 6 pitfalls that will catch even experienced developers</a></strong></h3><p>Actors are one of the most important&#8212;and most easily misunderstood&#8212;features in Swift&#8217;s concurrency model. Reality, however, is far more complex than it appears. In this article, <a href="https://pl.linkedin.com/in/rafa%C5%82-dubiel-86317013b">Rafa&#322; Dubiel</a> summarizes 6 Actor pitfalls that even experienced developers commonly encounter: state inconsistency caused by reentrancy, the performance cost of Actor hopping, thread-safety vulnerabilities when <code>@MainActor</code> interacts with Objective-C callbacks, the risks of misusing <code>@unchecked Sendable</code>, misconceptions about <code>nonisolated</code>, and the counterintuitive fact that Actors don&#8217;t guarantee execution order.</p><p>Rafa&#322; doesn&#8217;t stop at conceptual warnings&#8212;he explains through concrete scenarios why these issues genuinely exist and why they&#8217;re so easy to overlook.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-05">Designing a Scalable App-Wide Theming System in SwiftUI</a></strong></h3><p>Implementing app-wide theming in SwiftUI may seem like a simple &#8220;style management&#8221; problem, but it easily touches on deeper design decisions involving state propagation, dependency injection, and view refresh boundaries. <a href="https://x.com/SagarUnagar_">Sagar Unagar</a>approaches this from a real-world requirement, demonstrating a comprehensive theming system design based on SwiftUI&#8217;s Environment: using <code>EnvironmentKey</code> to make themes accessible like built-in environment values, and replacing scattered hardcoded values with semantic Design Tokens.</p><p>Sagar&#8217;s focus isn&#8217;t just on &#8220;how to do it,&#8221; but on &#8220;which approach is more maintainable in the long run&#8221;&#8212;this solution doesn&#8217;t depend on any specific library, with its core philosophy being &#8220;semantic + reactive,&#8221; easily extensible to fonts, spacing, corner radius, and other design elements.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-06">Call Once</a></strong></h3><p>&#8220;Ensuring a closure executes only once&#8221; sounds like a basic requirement, but in real systems, it&#8217;s often not as simple as adding a boolean flag. In this article, <a href="https://hachyderm.io/@paulio87">Paul Samuels</a> demonstrates how to encapsulate this behavior using <code>@propertyWrapper</code>, progressively evolving the solution: from a basic version supporting only <code>() -&gt; Void</code>, to introducing generics for return values, and finally leveraging Swift&#8217;s Parameter Packs (<code>each Argument</code>) to support arbitrary function signatures.</p><p>This is a thought-provoking article whose value lies not only in the final <code>CallOnce</code> implementation, but in demonstrating how to progressively combine multiple Swift language features to solve a seemingly simple yet representative engineering problem.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0121-07">SwiftUI-Agent-Skill: Making AI Write More Reliable SwiftUI Code</a></strong></h3><p>If you&#8217;re using AI coding assistants (like Claude Code, Cursor, or Codex), you&#8217;ve likely encountered this problem: AI-generated SwiftUI code uses <strong>deprecated APIs</strong>, or deviates from best practices in state management and view organization&#8212;even when you&#8217;ve repeatedly emphasized these requirements in your base rules.</p><p><strong>SwiftUI-Agent-Skill</strong>, released by <a href="https://x.com/twannl">Antoine van der Lee</a>, is designed to bridge this &#8220;last mile&#8221; gap. It provides AI tools with expert-level SwiftUI guidance covering state management trade-offs, modern API replacements, performance and maintainability checks, and iOS 26+ Liquid Glass usage boundaries&#8212;turning &#8220;the places where SwiftUI code most commonly goes wrong&#8221; into a reusable, executable review workflow.</p><blockquote><p>In addition to this skill, Antoine also provides skills for <a href="https://github.com/AvdLee/Swift-Concurrency-Agent-Skill">Swift Concurrency</a> and <a href="https://github.com/AvdLee/Core-Data-Agent-Skill">Core Data</a>.</p><p>I recommend that developers don&#8217;t just configure these into their AI environment and call it done&#8212;these skill documents themselves are structured summaries of practical experience in specific domains. Reading through them carefully benefits not just your AI, but elevates your own understanding as well.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-08">PierreDiffsSwift: Render Beautiful Code Diff Views in macOS Apps</a></strong></h3><p>PierreDiffsSwift, developed by <a href="https://x.com/jamesrochabrun">James Rochabrun</a>, helps developers render beautiful, syntax-highlighted code diff views in macOS applications.</p><p>The library provides an out-of-the-box solution: built on the <a href="https://www.npmjs.com/package/@pierre/diffs">@pierre/diffs</a> JavaScript library, wrapped into SwiftUI-native views via WKWebView, supporting syntax highlighting for 40+ languages, Split/Unified view modes, inline word-level change highlighting, and automatic dark/light theme switching.</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-121?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-121?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#21464;&#24187;&#30340;&#20809;&#24433;&#65292;&#19981;&#21464;&#30340;&#24178;&#33609;&#22534;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-121/">&#32593;&#39029;&#29256;</a></strong></p><p>&#20004;&#21608;&#21069;&#65292;&#20511;&#30528;&#21442;&#21152; iOS Conf SG 2026 &#30340;&#22865;&#26426;&#65292;&#25105;&#36896;&#35775;&#20102;&#26032;&#21152;&#22369;&#22269;&#31435;&#32654;&#26415;&#39302;&#65292;&#24182;&#26377;&#24184;&#21442;&#35266;&#20102;&#12298;&#36208;&#36827;&#29616;&#20195;&#65306;&#27874;&#22763;&#39039;&#32654;&#26415;&#21338;&#29289;&#39302;&#21360;&#35937;&#27966;&#22823;&#24072;&#23637;&#12299;&#12290;&#23613;&#31649;&#27492;&#21069;&#20063;&#30475;&#36807;&#19981;&#23569;&#20248;&#31168;&#30340;&#23637;&#35272;&#65292;&#20294;&#36825;&#27425;&#32463;&#21382;&#20173;&#24102;&#26469;&#20102;&#26576;&#31181;&#19981;&#21516;&#23547;&#24120;&#30340;&#35302;&#21160;&#12290;</p><p>&#26032;&#21152;&#22369;&#22269;&#31435;&#32654;&#26415;&#39302;&#30001;&#20004;&#24231;&#26497;&#20855;&#21382;&#21490;&#20998;&#37327;&#30340;&#22269;&#23478;&#21476;&#36857;&#8212;&#8212;&#21069;&#26368;&#39640;&#27861;&#38498;&#19982;&#21069;&#24066;&#25919;&#21381;&#8212;&#8212;&#21512;&#24182;&#32780;&#25104;&#12290;&#35774;&#35745;&#24072;&#20197;&#26497;&#31616;&#30340;&#37329;&#23646;&#19982;&#29627;&#29827;&#23627;&#39030;&#23558;&#20004;&#24231;&#21476;&#20856;&#24314;&#31569;&#36830;&#25509;&#22312;&#19968;&#36215;&#65292;&#22312;&#24314;&#31569;&#23618;&#38754;&#20415;&#33829;&#36896;&#20986;&#19968;&#31181;&#24378;&#28872;&#30340;&#20020;&#22330;&#24863;&#65306;&#21382;&#21490;&#19982;&#29616;&#20195;&#22312;&#21516;&#19968;&#29289;&#29702;&#31354;&#38388;&#20013;&#24444;&#27492;&#20132;&#32455;&#12290;&#32780;&#27491;&#22312;&#23637;&#20986;&#30340;&#29305;&#23637;&#12298;Into the Modern&#12299;&#65292;&#27719;&#38598;&#20102;&#33707;&#22856;&#12289;&#38647;&#35834;&#38463;&#12289;&#39532;&#22856;&#12289;&#22622;&#23578;&#12289;&#24503;&#21152;&#31561; 25 &#20301;&#22823;&#24072;&#30340;&#19968;&#30334;&#20313;&#24133;&#21407;&#20316;&#65292;&#21017;&#23558;&#36825;&#31181;&#36328;&#36234;&#26102;&#38388;&#30340;&#23545;&#35805;&#36827;&#19968;&#27493;&#25512;&#21521;&#20102;&#33402;&#26415;&#23618;&#38754;&#12290;</p><p>&#23637;&#35272;&#24182;&#26410;&#31616;&#21333;&#20381;&#24490;&#26102;&#38388;&#32447;&#23637;&#24320;&#65292;&#32780;&#26159;&#20197;&#8220;&#29616;&#20195;&#24615;&#8221;&#20026;&#26680;&#24515;&#21465;&#20107;&#32447;&#32034;&#65292;&#36890;&#36807;&#8220;&#22478;&#24066;&#19982;&#21464;&#38761;&#8221;&#8220;&#20809;&#24433;&#19982;&#30636;&#38388;&#8221;&#8220;&#38454;&#32423;&#19982;&#20241;&#38386;&#8221;&#31561;&#20027;&#39064;&#23618;&#23618;&#38138;&#38472;&#12290;&#23613;&#31649;&#36825;&#37324;&#30340;&#8220;&#29616;&#20195;&#8221;&#25351;&#21521;&#30340;&#26159; 19 &#19990;&#32426;&#26411;&#65292;&#20294;&#30011;&#20316;&#20013;&#25152;&#21576;&#29616;&#30340;&#24052;&#40654;&#22478;&#24066;&#25913;&#36896;&#12289;&#20809;&#24433;&#25216;&#27861;&#30340;&#28436;&#21464;&#65292;&#20197;&#21450;&#26032;&#20852;&#20241;&#38386;&#19982;&#23089;&#20048;&#26041;&#24335;&#30340;&#20852;&#36215;&#65292;&#26080;&#19981;&#20174;&#22810;&#20010;&#32500;&#24230;&#23637;&#29616;&#20102;&#37027;&#20010;&#26102;&#20195;&#31038;&#20250;&#21069;&#34892;&#30340;&#33410;&#22863;&#12290;&#22312;&#36825;&#26679;&#19968;&#20010;&#26102;&#31354;&#20132;&#38169;&#30340;&#22330;&#22495;&#20013;&#65292;&#23637;&#35272;&#26089;&#24050;&#36229;&#36234;&#20102;&#21333;&#32431;&#8220;&#35266;&#30475;&#33402;&#26415;&#21697;&#8221;&#30340;&#23618;&#27425;&#12290;&#23545;&#20110;&#27599;&#22825;&#37117;&#34987;&#31038;&#20132;&#23186;&#20307;&#26102;&#38388;&#32447;&#20013;&#28023;&#37327;&#8220;&#26032;&#25216;&#26415;&#8221;&#20449;&#24687;&#35065;&#25375;&#30340;&#25105;&#32780;&#35328;&#65292;&#36825;&#26080;&#30097;&#26159;&#19968;&#27573;&#38590;&#24471;&#30340;&#24179;&#38745;&#19982;&#21453;&#24605;&#26102;&#21051;&#12290;</p><p>&#22238;&#21040;&#29616;&#23454;&#65292;&#20165;&#20165;&#22312;&#36807;&#21435;&#30340;&#20960;&#22825;&#37324;&#65292;&#22823;&#28909; AI &#39033;&#30446;&#30340;&#21517;&#23383;&#23601;&#20174; Clawdbot &#21464;&#25104; Moltbot&#65292;&#21448;&#36805;&#36895;&#28436;&#21270;&#20026; OpenClaw&#12290;&#20174;&#24494;&#35266;&#35270;&#35282;&#30475;&#65292;&#25105;&#20204;&#20223;&#20315;&#27491;&#36523;&#22788;&#19968;&#20010;&#20197;&#20998;&#31186;&#35745;&#37327;&#30340;&#21464;&#38761;&#26102;&#20195;&#65307;&#20294;&#33509;&#22312;&#33509;&#24178;&#24180;&#21518;&#65292;&#20174;&#26356;&#38271;&#30340;&#26102;&#38388;&#23610;&#24230;&#37325;&#26032;&#23457;&#35270;&#24403;&#19979;&#30340; AI &#28909;&#28526;&#65292;&#25110;&#35768;&#20250;&#21457;&#29616;&#65292;&#19990;&#30028;&#24182;&#26410;&#22914;&#27946;&#27969;&#20043;&#20013;&#30340;&#25105;&#20204;&#25152;&#24863;&#30693;&#30340;&#37027;&#26679;&#65292;&#21457;&#29983;&#30528;&#26412;&#36136;&#19978;&#30340;&#31361;&#21464;&#12290;</p><p>&#36523;&#22788;&#20854;&#20013;&#65292;&#25105;&#20204;&#38590;&#20813;&#20250;&#22240;&#23618;&#20986;&#19981;&#31351;&#30340;&#26032;&#25216;&#26415;&#12289;&#26032;&#24037;&#20855;&#32780;&#20852;&#22859;&#65292;&#29978;&#33267;&#28966;&#34385;&#12290;&#25110;&#35768;&#65292;&#22312;&#36825;&#31181;&#24773;&#32490;&#20043;&#22806;&#65292;&#26356;&#38656;&#35201;&#19968;&#31181;&#26356;&#28145;&#23618;&#30340;&#23450;&#21147;&#12290;&#21382;&#21490;&#21453;&#22797;&#25552;&#37266;&#25105;&#20204;&#65292;&#20219;&#20309;&#8220;&#39640;&#25216;&#26415;&#8221;&#37117;&#20855;&#26377;&#20854;&#26102;&#38388;&#23616;&#38480;&#24615;&#12290;&#27491;&#22914;&#33707;&#22856;&#22312;&#19981;&#21516;&#26102;&#38388;&#12289;&#19981;&#21516;&#20809;&#32447;&#19979;&#21453;&#22797;&#25551;&#32472;&#21516;&#19968;&#24231;&#24178;&#33609;&#22534;&#65306;&#32472;&#30011;&#25216;&#27861;&#22312;&#21464;&#21270;&#65292;&#20294;&#26680;&#24515;&#23545;&#35937;&#22987;&#32456;&#26410;&#21464;&#65307;&#30495;&#27491;&#21457;&#29983;&#21464;&#21270;&#30340;&#65292;&#24448;&#24448;&#26159;&#35266;&#30475;&#26041;&#24335;&#12289;&#29702;&#35299;&#23618;&#27425;&#19982;&#21019;&#20316;&#32773;&#33258;&#36523;&#30340;&#24515;&#22659;&#12290;</p><p>&#22312;&#38754;&#23545;&#8220;&#29616;&#22312;&#19982;&#26410;&#26469;&#8221;&#26102;&#65292;&#20063;&#35768;&#25105;&#20204;&#21487;&#20197;&#23569;&#19968;&#20123;&#36861;&#36880;&#21464;&#38761;&#30340;&#24908;&#24352;&#65292;&#22810;&#19968;&#20123;&#20957;&#35270;&#30636;&#38388;&#30340;&#20174;&#23481;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-120/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div><hr></div><h2><strong>&#26412;&#26399;&#36190;&#21161;</strong></h2><h3><strong><a href="https://l.fatbobman.com/sb-proxyman">&#35843;&#35797; iOS &#32593;&#32476;&#35831;&#27714;&#24635;&#26159;&#34987;&#35777;&#20070;&#37197;&#32622;&#38590;&#20303;&#65311;</a></strong></h3><p>Proxyman &#26159;&#19968;&#27454;&#20026; iOS &#24320;&#21457;&#32773;&#25171;&#36896;&#30340;&#29616;&#20195; HTTP &#25235;&#21253;&#24037;&#20855;&#12290;&#25903;&#25345; SSL &#20195;&#29702;&#12289;GraphQL&#12289;WebSocket &#21450;&#24378;&#22823;&#30340;&#33050;&#26412;&#27880;&#20837;&#21151;&#33021;&#12290;&#21578;&#21035;&#31528;&#37325;&#30340;&#20256;&#32479;&#24037;&#20855;&#65292;&#20307;&#39564;&#19987;&#20026; macOS &#20248;&#21270;&#30340;&#26497;&#33268;&#35843;&#35797;&#25928;&#29575;&#12290;</p><p><a href="https://l.fatbobman.com/sb-proxyman">&#128640; &#31435;&#21363;&#35797;&#29992; &#8594;</a></p><div><hr></div><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0121-01">SwiftUI &#35843;&#35797;&#32972;&#21518;&#30340;&#22810;&#37325;&#31867;&#22411;&#25830;&#38500;&#26426;&#21046; (DebugReplaceableView and Swift 6.2&#8217;s Multiple Type Erasers)</a></strong></h3><p>&#25110;&#35768;&#20320;&#21487;&#33021;&#23545; Xcode &#30340; Preview &#20173;&#19981;&#29978;&#28385;&#24847;&#65292;&#20294;&#20854;&#23454;&#22312;&#36807;&#21435;&#20960;&#24180;&#38388;&#65292;&#33529;&#26524;&#19968;&#30452;&#22312;&#36825;&#26041;&#38754;&#31215;&#26497;&#22320;&#36827;&#34892;&#30528;&#20248;&#21270;&#24037;&#20316;&#65292;&#24182;&#19988;&#21462;&#24471;&#20102;&#19981;&#23569;&#30340;&#36827;&#23637;&#12290;&#27604;&#22914;&#65292;&#20174; Xcode 16 &#24320;&#22987;&#65292;&#20415;&#22312;&#39044;&#35272;&#21644;&#35843;&#35797;&#27169;&#24335;&#19979;&#65292;&#36890;&#36807; <code>@_typeEraser</code> &#33258;&#21160;&#23558;&#35270;&#22270;&#36716;&#25442;&#20026; <code>AnyView</code> &#20197;&#22686;&#21152;&#26356;&#22810;&#30340;&#35843;&#35797;&#20449;&#24687;&#12290;&#32780;&#20174; Xcode 26 &#24320;&#22987;&#65292;&#36890;&#36807;&#22686;&#24378; <code>@_typeEraser</code> &#20351;&#20854;&#25903;&#25345;&#22810;&#37325;&#31867;&#22411;&#25830;&#38500;&#22120;&#65292;&#22312; macOS/iOS 26+ &#24179;&#21488;&#19978;&#23558;&#35270;&#22270;&#36716;&#25442;&#25104; <code>DebugReplaceableView</code>&#65292;&#23454;&#29616;&#35270;&#22270;&#30340;&#28909;&#26367;&#25442;&#32780;&#26080;&#38656;&#37325;&#24314;&#25972;&#20010;&#35270;&#22270;&#23618;&#32423;&#65292;&#36827;&#19968;&#27493;&#25913;&#21892;&#39044;&#35272;&#24615;&#33021;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://x.com/KyleSwifter">Kyle Ye</a> &#20174;&#32534;&#35793;&#22120;&#28304;&#30721;&#23618;&#38754;&#28145;&#20837;&#21078;&#26512;&#20102;&#36825;&#19968;&#26426;&#21046;&#30340;&#23454;&#29616;&#21407;&#29702;&#65292;&#35299;&#37322;&#20102;&#32534;&#35793;&#22120;&#22914;&#20309;&#26681;&#25454;&#24179;&#21488;&#21487;&#29992;&#24615;&#33258;&#21160;&#36873;&#25321;&#21512;&#36866;&#30340;&#31867;&#22411;&#25830;&#38500;&#22120;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-02">Swift &#20013;&#30340;&#20998;&#23618;&#32531;&#23384;&#35774;&#35745; (Tiered Caching in Swift)</a></strong></h3><p>&#22312;&#38656;&#35201;&#21516;&#26102;&#20860;&#39038;&#24615;&#33021;&#12289;&#20869;&#23384;&#21344;&#29992;&#19982;&#25968;&#25454;&#19968;&#33268;&#24615;&#30340;&#22330;&#26223;&#20013;&#65292;&#21333;&#19968;&#32531;&#23384;&#31574;&#30053;&#24448;&#24448;&#24456;&#24555;&#23601;&#20250;&#25417;&#35167;&#35265;&#32920;&#12290;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;<a href="https://linkedin.com/in/kyle-browning-eng-manager">Kyle Browning</a> &#20197;&#23454;&#36341;&#35270;&#35282;&#31995;&#32479;&#20171;&#32461;&#20102;&#20998;&#23618;&#32531;&#23384;&#65288;Tiered Caching&#65289;&#22312; Swift &#20013;&#30340;&#23454;&#29616;&#24605;&#36335;&#65306;&#36890;&#36807;&#23558;&#20869;&#23384;&#32531;&#23384;&#19982;&#30913;&#30424;&#32531;&#23384;&#32452;&#32455;&#25104;&#28165;&#26224;&#30340;&#23618;&#32423;&#32467;&#26500;&#65292;&#37197;&#21512;&#28789;&#27963;&#30340;&#32531;&#23384;&#31574;&#30053;&#65288;&#22914; <code>cacheThenFetch</code>&#12289;<code>cacheElseFetch</code> &#31561;&#65289;&#65292;&#35753;&#25968;&#25454;&#22312;&#19981;&#21516;&#35775;&#38382;&#25104;&#26412;&#20043;&#38388;&#26377;&#24207;&#27969;&#21160;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-03">&#22522;&#20110; Cloudflare &#30340; SwiftUI &#23454;&#26102;&#21327;&#20316;&#32534;&#36753;&#23454;&#36341; (SwiftUI: Realtime, Multi-User Content Collaboration With CloudFlare +YJS-Swift)</a></strong></h3><p>&#23613;&#31649;&#24066;&#38754;&#19978;&#24050;&#32463;&#23384;&#22312;&#19981;&#23569;&#29616;&#25104;&#30340;&#26381;&#21153;&#19982;&#26694;&#26550;&#65292;&#23454;&#26102;&#21327;&#20316;&#32534;&#36753;&#22312;&#24037;&#31243;&#23618;&#38754;&#20381;&#28982;&#26159;&#19968;&#36947;&#19981;&#20302;&#30340;&#38376;&#27099;&#12290;&#26412;&#25991;&#20013;&#65292;<a href="https://x.com/itsuki68391179">Itsuki</a> &#31995;&#32479;&#24615;&#22320;&#23637;&#31034;&#20102;&#22914;&#20309;&#22312; SwiftUI &#20013;&#65292;&#20511;&#21161; Cloudflare Durable Objects + WebSocket Hibernation API + YJS-Swift&#65292;&#26500;&#24314;&#19968;&#20010;&#20302;&#25104;&#26412;&#12289;&#21487;&#25193;&#23637;&#12289;&#25903;&#25345;&#22810;&#29992;&#25143;&#23454;&#26102;&#21327;&#20316;&#30340;&#20869;&#23481;&#32534;&#36753;&#31995;&#32479;&#12290;</p><p>&#23588;&#20854;&#20540;&#24471;&#19968;&#25552;&#30340;&#26159;&#65292;&#20316;&#32773;&#35814;&#32454;&#20998;&#20139;&#20102;&#22312; SwiftUI &#25509;&#25910;&#36828;&#31243;&#20869;&#23481;&#26356;&#26032;&#26102;&#65292;&#22914;&#20309;&#27491;&#30830;&#32500;&#25252;&#25991;&#26412;&#20809;&#26631;&#19982;&#36873;&#21306;&#20301;&#32622;&#30340;&#22788;&#29702;&#25216;&#24039;&#8212;&#8212;&#36825;&#19968;&#37096;&#20998;&#38750;&#24120;&#36148;&#36817;&#30495;&#23454;&#20135;&#21697;&#24320;&#21457;&#65292;&#26126;&#26174;&#23646;&#20110;&#8220;&#36393;&#36807;&#22353;&#20043;&#21518;&#25165;&#20250;&#20889;&#20986;&#26469;&#8221;&#30340;&#32463;&#39564;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-04">Swift Actor &#30340; 6 &#20010;&#24120;&#35265;&#38519;&#38449; (Swift Actors: 6 pitfalls that will catch even experienced developers)</a></strong></h3><p>Actor &#26159; Swift &#24182;&#21457;&#27169;&#22411;&#20013;&#26368;&#37325;&#35201;&#12289;&#20063;&#26368;&#23481;&#26131;&#34987;&#8220;&#24819;&#24403;&#28982;&#8221;&#20351;&#29992;&#30340;&#35821;&#35328;&#29305;&#24615;&#20043;&#19968;&#65292;&#28982;&#32780;&#29616;&#23454;&#36828;&#27604;&#36825;&#22797;&#26434;&#12290;<a href="https://pl.linkedin.com/in/rafa%C5%82-dubiel-86317013b">Rafa&#322; Dubiel</a> &#22312;&#26412;&#25991;&#20013;&#24635;&#32467;&#20102; 6 &#20010;&#21363;&#20351;&#26159;&#36164;&#28145;&#24320;&#21457;&#32773;&#20063;&#24120;&#36393;&#30340; Actor &#38519;&#38449;&#65306;&#21487;&#37325;&#20837;&#24615;&#23548;&#33268;&#30340;&#29366;&#24577;&#19981;&#19968;&#33268;&#12289;Actor Hopping &#30340;&#24615;&#33021;&#20195;&#20215;&#12289;<code>@MainActor</code> &#19982; Objective-C &#22238;&#35843;&#20132;&#20114;&#26102;&#30340;&#32447;&#31243;&#23433;&#20840;&#28431;&#27934;&#12289;<code>@unchecked Sendable</code> &#30340;&#28389;&#29992;&#39118;&#38505;&#12289;<code>nonisolated</code> &#30340;&#35823;&#35299;&#65292;&#20197;&#21450; Actor &#24182;&#19981;&#20445;&#35777;&#25191;&#34892;&#39034;&#24207;&#36825;&#19968;&#21453;&#30452;&#35273;&#30340;&#20107;&#23454;&#12290;</p><p>Rafa&#322; &#24182;&#26410;&#20572;&#30041;&#22312;&#27010;&#24565;&#23618;&#38754;&#30340;&#25552;&#37266;&#65292;&#32780;&#26159;&#32467;&#21512;&#20855;&#20307;&#22330;&#26223;&#35299;&#37322;&#36825;&#20123;&#38382;&#39064;&#20026;&#20309;&#30495;&#23454;&#23384;&#22312;&#12289;&#21448;&#20026;&#20309;&#23481;&#26131;&#34987;&#24573;&#35270;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-05">SwiftUI &#20840;&#23616;&#20027;&#39064;&#31995;&#32479;&#30340;&#21487;&#25193;&#23637;&#35774;&#35745; (Designing a Scalable App-Wide Theming System in SwiftUI)</a></strong></h3><p>&#22312; SwiftUI &#20013;&#23454;&#29616;&#20840;&#23616;&#20027;&#39064;&#65288;Theming&#65289;&#65292;&#30475;&#20284;&#26159;&#20010;&#8220;&#26679;&#24335;&#31649;&#29702;&#8221;&#38382;&#39064;&#65292;&#23454;&#21017;&#24456;&#23481;&#26131;&#29301;&#25199;&#21040;&#29366;&#24577;&#20256;&#25773;&#12289;&#20381;&#36182;&#27880;&#20837;&#20197;&#21450;&#35270;&#22270;&#21047;&#26032;&#36793;&#30028;&#31561;&#26356;&#28145;&#23618;&#30340;&#35774;&#35745;&#36873;&#25321;&#12290;<a href="https://x.com/SagarUnagar_">Sagar Unagar</a> &#20174;&#19968;&#20010;&#29616;&#23454;&#38656;&#27714;&#20986;&#21457;&#65292;&#31995;&#32479;&#23637;&#31034;&#20102;&#19968;&#22871;&#22522;&#20110; SwiftUI Environment &#30340;&#20840;&#23616;&#20027;&#39064;&#31995;&#32479;&#35774;&#35745;&#65306;&#36890;&#36807; <code>EnvironmentKey</code> &#35753;&#20027;&#39064;&#20687;&#20869;&#32622;&#29615;&#22659;&#20540;&#19968;&#26679;&#35775;&#38382;&#65292;&#20197;&#35821;&#20041;&#21270;&#30340; Design Tokens &#21462;&#20195;&#25955;&#33853;&#21508;&#22788;&#30340;&#30828;&#32534;&#30721;&#20540;&#12290;</p><p>Sagar &#20851;&#27880;&#30340;&#24182;&#19981;&#20165;&#26159;&#8220;&#22914;&#20309;&#20570;&#8221;&#65292;&#32780;&#26159;&#8220;&#21738;&#31181;&#26041;&#24335;&#22312;&#38271;&#26399;&#26356;&#21487;&#25511;&#8221;&#8212;&#8212;&#36825;&#22871;&#26041;&#26696;&#19981;&#20381;&#36182;&#29305;&#23450;&#24211;&#65292;&#26680;&#24515;&#24605;&#24819;&#26159;&#8220;&#35821;&#20041;&#21270; + &#21709;&#24212;&#24335;&#8221;&#65292;&#21487;&#20197;&#36731;&#26494;&#25193;&#23637;&#21040;&#23383;&#20307;&#12289;&#38388;&#36317;&#12289;&#22278;&#35282;&#31561;&#35774;&#35745;&#35201;&#32032;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-06">&#22312; Swift &#20013;&#23454;&#29616;&#8220;&#21482;&#25191;&#34892;&#19968;&#27425;&#8221;&#30340;&#20248;&#38597;&#26041;&#24335; (Call Once)</a></strong></h3><p>&#8220;&#30830;&#20445;&#38381;&#21253;&#21482;&#25191;&#34892;&#19968;&#27425;&#8221;&#21548;&#36215;&#26469;&#20687;&#26159;&#19968;&#20010;&#20877;&#22522;&#30784;&#19981;&#36807;&#30340;&#38656;&#27714;&#65292;&#20294;&#22312;&#30495;&#23454;&#31995;&#32479;&#37324;&#65292;&#36825;&#24448;&#24448;&#24182;&#19981;&#21482;&#26159;&#21152;&#19968;&#20010;&#24067;&#23572;&#20540;&#37027;&#20040;&#31616;&#21333;&#12290;<a href="https://hachyderm.io/@paulio87">Paul Samuels</a> &#22312;&#26412;&#25991;&#20013;&#23637;&#31034;&#20102;&#22914;&#20309;&#29992; <code>@propertyWrapper</code> &#23553;&#35013;&#36825;&#19968;&#34892;&#20026;&#65292;&#24182;&#36880;&#27493;&#28436;&#36827;&#65306;&#20174;&#21482;&#25903;&#25345; <code>() -&gt; Void</code> &#30340;&#22522;&#30784;&#29256;&#26412;&#65292;&#21040;&#24341;&#20837;&#27867;&#22411;&#25903;&#25345;&#36820;&#22238;&#20540;&#65292;&#26368;&#32456;&#20511;&#21161; Swift &#30340; Parameter Packs&#65288;<code>each Argument</code>&#65289;&#23454;&#29616;&#23545;&#20219;&#24847;&#20989;&#25968;&#31614;&#21517;&#30340;&#25903;&#25345;&#12290;</p><p>&#36825;&#26159;&#19968;&#31687;&#20559;&#24605;&#32771;&#22411;&#30340;&#25991;&#31456;&#65292;&#20854;&#20215;&#20540;&#19981;&#20165;&#22312;&#20110;&#26368;&#32456;&#30340; <code>CallOnce</code> &#23454;&#29616;&#65292;&#26356;&#22312;&#20110;&#23637;&#31034;&#20102;&#22914;&#20309;&#23558;&#22810;&#20010; Swift &#35821;&#35328;&#29305;&#24615;&#36880;&#27493;&#32452;&#21512;&#36215;&#26469;&#65292;&#35299;&#20915;&#19968;&#20010;&#30475;&#20284;&#31616;&#21333;&#21364;&#39047;&#20855;&#20195;&#34920;&#24615;&#30340;&#24037;&#31243;&#38382;&#39064;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0121-07">SwiftUI-Agent-Skill&#65306;&#35753; AI &#20889;&#20986;&#26356;&#8220;&#38752;&#35889;&#8221;&#30340; SwiftUI &#20195;&#30721;</a></strong></h3><p>&#22914;&#26524;&#20320;&#27491;&#22312;&#20351;&#29992; AI &#32534;&#31243;&#21161;&#25163;&#65288;&#22914; Claude Code&#12289;Cursor&#12289;Codex&#65289;&#65292;&#24456;&#21487;&#33021;&#36935;&#21040;&#36807;&#31867;&#20284;&#30340;&#38382;&#39064;&#65306;AI &#29983;&#25104;&#30340; SwiftUI &#20195;&#30721;&#20351;&#29992;&#20102;<strong>&#36807;&#26102;&#30340; API</strong>&#65292;&#25110;&#22312;&#29366;&#24577;&#31649;&#29702;&#12289;&#35270;&#22270;&#32452;&#32455;&#19978;&#20559;&#31163;&#26368;&#20339;&#23454;&#36341;&#8212;&#8212;&#21363;&#20415;&#20320;&#24050;&#32463;&#22312;&#22522;&#30784;&#35268;&#21017;&#20013;&#21453;&#22797;&#24378;&#35843;&#36807;&#36825;&#20123;&#35201;&#27714;&#12290;</p><p><a href="https://x.com/twannl">Antoine van der Lee</a> &#21457;&#24067;&#30340; <strong>SwiftUI-Agent-Skill</strong>&#65292;&#27491;&#26159;&#20026;&#20102;&#35299;&#20915;&#36825;&#19968;&#8220;&#26368;&#21518;&#19968;&#20844;&#37324;&#8221;&#30340;&#33853;&#24046;&#12290;&#23427;&#20026; AI &#24037;&#20855;&#25552;&#20379;&#20102;&#19968;&#22871;&#19987;&#23478;&#32423;&#30340; SwiftUI &#25351;&#23548;&#35268;&#33539;&#65292;&#28085;&#30422;&#29366;&#24577;&#31649;&#29702;&#21462;&#33293;&#12289;&#29616;&#20195; API &#26367;&#25442;&#12289;&#24615;&#33021;&#19982;&#21487;&#32500;&#25252;&#24615;&#26816;&#26597;&#65292;&#20197;&#21450; iOS 26+ &#30340; Liquid Glass &#20351;&#29992;&#36793;&#30028;&#31561;&#20869;&#23481;&#65292;&#25226;&#8220;SwiftUI &#26368;&#23481;&#26131;&#20889;&#27498;&#30340;&#22320;&#26041;&#8221;&#25972;&#29702;&#25104;&#21487;&#22797;&#29992;&#12289;&#21487;&#25191;&#34892;&#30340;&#23457;&#26597;&#27969;&#31243;&#12290;</p><blockquote><p>&#38500;&#20102;&#36825;&#22871; skill &#22806;&#65292;Antoine &#36824;&#25552;&#20379;&#20102;&#38754;&#21521; <a href="https://github.com/AvdLee/Swift-Concurrency-Agent-Skill">Swift Concurrency</a> &#21644; <a href="https://github.com/AvdLee/Core-Data-Agent-Skill">Core Data</a> &#30340; skill&#12290;</p><p>&#25105;&#24314;&#35758;&#24320;&#21457;&#32773;&#19981;&#35201;&#21482;&#26159;&#25226;&#23427;&#20204;&#31616;&#21333;&#37197;&#32622;&#36827; AI &#29615;&#22659;&#20013;&#23601;&#32467;&#26463;&#20102;&#8212;&#8212;&#36825;&#20123; skill &#25991;&#26723;&#26412;&#36523;&#23601;&#26159;&#23545;&#26576;&#19968;&#39046;&#22495;&#23454;&#36341;&#32463;&#39564;&#30340;&#32467;&#26500;&#21270;&#24635;&#32467;&#12290;&#35748;&#30495;&#35835;&#19968;&#36941;&#65292;&#21463;&#30410;&#30340;&#19981;&#21482;&#26159; AI&#65292;&#20320;&#33258;&#24049;&#20063;&#20250;&#38543;&#20043;&#36827;&#38454;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0121-08">PierreDiffsSwift&#65306;&#22312; macOS &#24212;&#29992;&#20013;&#28210;&#26579;&#31934;&#32654;&#30340;&#20195;&#30721; Diff &#35270;&#22270;</a></strong></h3><p><a href="https://x.com/jamesrochabrun">James Rochabrun</a> &#24320;&#21457;&#30340; PierreDiffsSwift&#65292;&#24110;&#21161;&#24320;&#21457;&#32773;&#22312; macOS &#24212;&#29992;&#20013;&#28210;&#26579;&#28418;&#20142;&#30340;&#12289;&#24102;&#35821;&#27861;&#39640;&#20142;&#30340;&#20195;&#30721; Diff &#35270;&#22270;&#12290;</p><p>&#35813;&#24211;&#25552;&#20379;&#20102;&#19968;&#20010;&#24320;&#31665;&#21363;&#29992;&#30340;&#35299;&#20915;&#26041;&#26696;&#65306;&#22522;&#20110; <a href="https://www.npmjs.com/package/@pierre/diffs">@pierre/diffs</a> JavaScript &#24211;&#65292;&#36890;&#36807; WKWebView &#23553;&#35013;&#25104; SwiftUI &#21407;&#29983;&#35270;&#22270;&#65292;&#25903;&#25345; 40+ &#31181;&#35821;&#35328;&#30340;&#35821;&#27861;&#39640;&#20142;&#12289;Split/Unified &#20004;&#31181;&#35270;&#22270;&#27169;&#24335;&#12289;&#34892;&#20869;&#21333;&#35789;&#32423;&#21464;&#26356;&#39640;&#20142;&#65292;&#20197;&#21450;&#28145;&#33394;/&#27973;&#33394;&#20027;&#39064;&#33258;&#21160;&#20999;&#25442;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #120]]></title><description><![CDATA[Skip Goes Open Source: A High-Stakes Bet from &#8220;Selling Tools&#8221; to &#8220;Selling Trust&#8221;]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-120</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-120</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 26 Jan 2026 12:03:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YdV4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.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_!YdV4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YdV4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 424w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 848w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 1272w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YdV4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp" width="1456" height="873" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:873,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54068,&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/185721747?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.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_!YdV4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 424w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 848w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.webp 1272w, https://substackcdn.com/image/fetch/$s_!YdV4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6888d7b-2cf7-48bf-b0c6-b757ec77f7a0_1530x917.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"><svg role="img" 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"><g><title></title><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"><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"><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/@markuswinkler?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Markus Winkler</a> on <a href="https://unsplash.com/photos/a-typewriter-on-a-table-NdhQbeGTA58?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Skip Goes Open Source: A High-Stakes Bet from &#8220;Selling Tools&#8221; to &#8220;Selling Trust&#8221;</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-120/">Read on web &#8594;</a></p><p>Just two months after announcing that <a href="https://fatbobman.com/en/weekly/issue-110/">the Fuse edition would be free for indie developers</a>, Skip Tools made another bold move: <a href="https://skip.dev/blog/skip-is-free/?utm_source=fatbobman%20weekly%20issue%20120&amp;utm_medium=web">making its core engine, skipstone, completely free and open source</a>. This decision marks a fundamental shift in Skip&#8217;s business model&#8212;from selling a product to relying on services and community sponsorships. The change reflects both the pressure of an underperforming commercial strategy and the team&#8217;s willingness to take risks. In an era dominated by AI and a largely entrenched developer tooling landscape, Skip chose to actively pivot rather than stand still.</p><p>Many technically strong and distinctive products fail to gain traction not because of their technology, but because of a lack of trust. As Skip itself points out, companies fear a &#8220;rug pull&#8221;: if the vendor shuts down or gets acquired, the products and tech stacks built on top of that tool may need to be rebuilt from scratch. By going open source, Skip aims to eliminate this trust barrier&#8212;placing itself on equal footing with other cross-platform tools, while also activating the community to help grow the ecosystem.</p><p>That said, while the community has largely praised Skip&#8217;s open-source decision, concerns remain. After giving up license keys as a stable revenue stream, can sponsorship alone sustain long-term development? History shows that while some open-source business models succeed, many do not. This concern is hardly unfounded. At the time of writing this issue&#8212;just days after the open-source announcement&#8212;discussion on social media was lively, yet Skip had only a handful of individual sponsors on GitHub. The gap between enthusiastic conversation and real financial support appears wider than expected. This may also explain why Skip ultimately chose to go open source: if developers cannot be convinced to pay for the tool, at least they might be persuaded to use it.</p><p>An interesting shift has emerged amid this mix of optimism and anxiety. The conversation has quietly moved from &#8220;Why pay for Skip instead of using free KMP?&#8221; to &#8220;Do you prefer writing Swift or Kotlin?&#8221; This change is significant. It suggests that Skip has successfully reframed the competition&#8212;from a debate over business models to one centered on language ecosystems. In doing so, the competitive arena expands from a single company to the entire Swift community. In this language-level contest, Skip has&#8212;perhaps intentionally, perhaps not&#8212;repositioned itself from a central protagonist to underlying infrastructure.</p><p>From the beginning, Skip was driven by the belief that there was a real commercial opportunity with sufficient returns. Without such expectations, it is unlikely that either the company or the community alone could have pushed Swift forward on non-Apple platforms so quickly. This path closely resembles how The Browser Company aggressively promoted Swift on Windows in pursuit of building the Arc browser.</p><p>As a Swift developer, I sincerely hope this pivot delivers the results Skip is aiming for. Open source is both an experiment in trust and an investment in the ecosystem. If you, too, hope to see Swift thrive beyond iOS, consider starting by <a href="https://github.com/sponsors/skiptools">becoming a individual sponsor</a> ($10/month). This is not just support for Skip&#8212;it is a vote for the broader Swift cross-platform ecosystem. How far open-source Skip can go ultimately depends on how many people are willing to move from being observers to active participants.</p><p><a href="https://fatbobman.com/en/weekly/issue-119/">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/letting-swift-closures-automatically-inherit-isolation/?utm_source=fatbobman%20weekly%20issue%20120&amp;utm_medium=web">isolated(any) and #isolation: Letting Swift Closures Automatically Inherit Isolation</a></strong></h3><p>Swift 6 introduces many new features and keywords to its concurrency model. While some of them may rarely be used in day-to-day development, lacking an understanding of these concepts can leave you stuck in specific scenarios&#8212;even with AI assistance. This article walks through a real concurrency issue encountered during development and testing, demonstrating how <code>@isolated(any)</code> and the <code>#isolation</code> macro can be used to let functions inherit isolation automatically, allowing the compiler to infer the execution context of closures.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0120-01">A Deep Dive into SwiftData migrations</a></strong></h3><p>As apps evolve, changes to data models are almost inevitable, and performing safe data migrations remains a significant challenge for many developers. In this article, <a href="https://x.com/donnywals">Donny Wals</a> provides a comprehensive overview of SwiftData&#8217;s migration system, covering everything from basic versioning to complex custom migration strategies. He also shares several particularly valuable recommendations: even a V1 model should be wrapped in a <code>VersionedSchema</code> to prepare for future changes; new schema versions should be introduced only between App Store release cycles, rather than being modified repeatedly during development; and for lightweight migrations, even when SwiftData can handle them automatically, it is still advisable to explicitly define them in a <code>SchemaMigrationPlan</code> to make intentions clearer and easier to test.</p><p>One of the highlights of the article is its detailed explanation of when to use <code>willMigrate</code> versus <code>didMigrate</code> in <code>MigrationStage.custom</code>, along with a &#8220;bridge version&#8221; strategy for handling complex refactors, such as splitting entities.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-02">Why MVVM-C with Coordinators does Scale -&gt; A real-world SwiftUI perspective</a></strong></h3><p>Despite the title referencing &#8220;MVVM-C,&#8221; this is not simply an article defending a specific architectural pattern. <a href="https://www.linkedin.com/in/valentebruno/">Bruno Valente Pimentel</a> redefines what &#8220;scalability&#8221; really means&#8212;arguing that it should not be measured by the number of screens or files, but by how well an architecture supports efficient collaboration and independent feature evolution. As the author puts it, &#8220;architecture is not about patterns, but about reducing fear&#8221;&#8212;the fear of changing code, collaborating with others, and evolving features.</p><blockquote><p>No matter which architecture you prefer, when building SwiftUI apps you should seriously ask yourself: are we leveraging SwiftUI&#8217;s strengths, or trying to bend SwiftUI into the shape of UIKit as we know it?</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-03">TCA (Composable Architecture): The Honest Review</a></strong></h3><p>Following Bruno&#8217;s reevaluation of MVVM-C, <a href="https://www.linkedin.com/in/chandrawelim/">Chandra Welim</a> offers an objective assessment of another highly debated architecture: TCA. The article summarizes five key strengths of TCA (predictable state management, excellent testability, time-travel debugging, composability, and strong type safety) alongside five major challenges (learning curve, boilerplate, team adoption, overengineering for simple apps, and third-party dependencies). It also provides pragmatic guidance: TCA is a powerful tool, but it is not suitable for every scenario. For simple MVPs or teams without a functional programming background, traditional MVVM may be a more practical choice; for large-scale projects with complex state and a need for time-travel debugging, TCA can offer unmatched control. The core takeaway: TCA is worth it when you truly need it&#8212;but most apps don&#8217;t.</p><blockquote><p>There is no silver bullet in architecture&#8212;only trade-offs in a specific context.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-04">Improving the usability of C libraries in Swift</a></strong></h3><p>Although Swift is designed to interoperate with C, calling C APIs directly often results in a poor developer experience&#8212;exposing raw pointers, requiring manual memory management, and using naming conventions that feel foreign to Swift. To achieve a more &#8220;native&#8221; experience, developers often have to write and maintain cumbersome wrapper layers. In this article, <a href="https://sfba.social/@dgregor79">Doug Gregor</a> explains how API Notes and Clang Attributes can be used to &#8220;guide&#8221; the Swift compiler into generating Swift-friendly interfaces without modifying the underlying C library implementation.</p><p>The significance of this improvement lies in shifting the cost of &#8220;wrapping C libraries&#8221; from the logic layer (writing Swift glue code) to the declaration layer (authoring API Notes or adding annotations to headers). This is particularly important for the adoption of Embedded Swift, where existing C libraries are fundamental to the ecosystem. As the toolchain matures, developers may eventually need only a few annotations to use C libraries in Swift as if they were native. The article also provides regex-based automation scripts for generating API Notes in bulk from structured C headers.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-05">Introduction to Building Swift for Yocto</a></strong></h3><p>For most iOS developers, Yocto may be unfamiliar, but it is the de facto standard in the embedded Linux world&#8212;offering precise control over every component included in a system. As Embedded Swift advances, integrating Swift into the Yocto ecosystem becomes a key challenge. <a href="https://x.com/xtremekforever">Jesse L. Zamora</a> demonstrates how to build a Swift runtime for Yocto using the recently revived <code>meta-swift</code> layer. Using a Raspberry Pi Zero 2 as an example, the article walks through the entire workflow, from setting up a Docker environment and building Yocto, to flashing the image and running Swift code on the device.</p><p>It is worth noting that a full build can take several hours and requires some familiarity with Yocto&#8217;s build system. However, the provided <a href="https://github.com/swift-embedded-linux/meta-swift-examples">meta-swift-examples</a> repository includes a Dockerized environment and one-click scripts that significantly lower the barrier to entry.</p><blockquote><p><a href="https://github.com/jeremy-prater/meta-swift">meta-swift</a> is the Yocto layer for Swift. It had long been stalled at Swift 5.7, but thanks to community efforts, it now supports Swift 6.1.3.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-06">TIL how to auto-move Xcode DEBUG builds to Applications</a></strong></h3><p>When developing apps that include App Intents, you may run into this issue: App Intents only appear in Shortcuts.app when the app is located in the <code>/Applications</code> directory. Since DEBUG builds are placed in DerivedData by default, this makes testing Shortcuts integration difficult. <a href="https://norden.social/@czottmann">Carlo Zottmann</a> previously relied on complex post-build scripts to move apps around, but in this article he shares a more &#8220;native&#8221; solution&#8212;using just three lines of <code>.xcconfig</code> to have Xcode automatically deploy build artifacts to a specified directory and clean them up properly when builds are removed.</p><blockquote><p>This trick is useful not only for testing App Intents, but for any scenario where DEBUG builds need to live in a specific location.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-07">Visualise anything with SwiftUI Charts</a></strong></h3><p>If you needed to build a custom, animated, and interactive circular stress indicator in SwiftUI, how would you approach it&#8212;using <code>Shape</code>, or <code>Canvas</code>? In this article, <a href="https://www.linkedin.com/in/kyryl-horbushko-67936bb5/">Kyryl Horbushko</a> presents a creative solution by leveraging Swift Charts&#8217; <code>SectorMark</code> to implement the component elegantly and efficiently.</p><p>Kyryl&#8217;s approach challenges the common assumption that Swift Charts are only suitable for traditional data visualization. For developers building complex dashboards in health or finance apps, this represents a highly instructive &#8220;dimensionality reduction&#8221; strategy&#8212;solving custom UI problems with a data visualization framework, while benefiting from built-in animations and interaction support.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0120-08">Commander: A Focused Yet Flexible AI Coding Experience</a></strong></h3><p>I enjoy using CLI tools on macOS (such as Claude Code and Codex), but the visual experience of native terminal apps leaves much to be desired, so I usually rely on VS Code extensions to improve the workflow. However, one design choice in VS Code has consistently bothered me: even when the Claude Code panel is maximized, any file modifications made by the AI will still open new editor tabs or windows, disrupting the existing interaction flow.</p><p><a href="https://x.com/krzyzanowskim">Marcin Krzy&#380;anowski</a>&#8217;s macOS-native app Commander offers a compelling alternative. It provides a more polished interface than the terminal while preserving my &#8220;flow&#8221;&#8212;files are opened only when needed, and system-default apps can be used for viewing. Commander currently supports Claude Code and Codex, includes Git worktrees and code diff features, and is completely free. It occupies a sweet spot between the &#8220;focus&#8221; of the terminal and the &#8220;flexibility&#8221; of VS Code.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-09">Oh My Agents: Centrally Managing Configuration for All AI Coding Assistants</a></strong></h3><p>With the rise of AI coding assistants like Claude Code, Cursor, Codex, and Windsurf, developers are facing a new challenge: managing scattered prompts, skills, and rules across multiple projects. Each agent has its own configuration format (<code>CLAUDE.md</code>, <code>CURSOR.md</code>, etc.), and manual copying is both inefficient and error-prone. Oh My Agents, created by <a href="https://x.com/onevcat">Wei Wang (onevcat)</a>, addresses this problem directly.</p><p>Core features:</p><ul><li><p>Centralized management of all AI agent configurations</p></li><li><p>Rule-based distribution with one-click syncing across projects</p></li><li><p>Bidirectional sync, allowing project-level improvements to flow back into the central repository</p></li><li><p>Change previews to prevent accidental overwrites</p></li></ul><p>Note: Currently macOS-only (Windows/Linux support in progress). Free during the beta period.</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-120?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-120?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Skip &#24320;&#28304;&#65306;&#20174;&#8220;&#21334;&#24037;&#20855;&#8221;&#21040;&#8220;&#21334;&#20449;&#20219;&#8221;&#30340;&#35946;&#36172;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-120/">&#32593;&#39029;&#29256;</a></strong></p><p>&#22312;&#23459;&#24067; <a href="https://fatbobman.com/zh/weekly/issue-110/">Fuse &#29256;&#26412;&#23545;&#29420;&#31435;&#24320;&#21457;&#32773;&#20813;&#36153;</a> &#20165;&#20004;&#20010;&#26376;&#21518;&#65292;Skip Tools &#20877;&#27425;&#20570;&#20986;&#24778;&#20154;&#20043;&#20030;&#8212;&#8212;<a href="https://skip.dev/blog/skip-is-free/?utm_source=fatbobman%20weekly%20issue%20120&amp;utm_medium=web">&#20840;&#38754;&#20813;&#36153;&#24182;&#24320;&#28304;&#26680;&#24515;&#24341;&#25806; skipstone</a>&#12290;&#36825;&#24847;&#21619;&#30528; Skip &#24443;&#24213;&#25913;&#21464;&#20102;&#32463;&#33829;&#26041;&#24335;&#65306;&#20174;&#8220;&#21334;&#20135;&#21697;&#8221;&#36716;&#21521;&#8220;&#21334;&#26381;&#21153;+&#31038;&#21306;&#36190;&#21161;&#8221;&#12290;&#36825;&#27425;&#21464;&#21270;&#65292;&#26082;&#26377;&#23545;&#20043;&#21069;&#21830;&#19994;&#27169;&#24335;&#25191;&#34892;&#19981;&#20339;&#32780;&#34987;&#36843;&#35843;&#25972;&#30340;&#26080;&#22856;&#65292;&#20063;&#20307;&#29616;&#20102; Skip &#22242;&#38431;&#30340;&#26524;&#25954;&#8212;&#8212;&#22312;&#24403;&#21069; AI &#30427;&#34892;&#12289;&#24320;&#21457;&#24037;&#20855;&#26684;&#23616;&#22266;&#21270;&#30340;&#32972;&#26223;&#19979;&#65292;&#20027;&#21160;&#27714;&#21464;&#65292;&#21147;&#27714;&#31361;&#30772;&#12290;</p><p>&#24456;&#22810;&#20248;&#31168;&#19988;&#26377;&#29305;&#28857;&#30340;&#20135;&#21697;&#27809;&#33021;&#33719;&#24471;&#24212;&#26377;&#30340;&#20351;&#29992;&#37327;&#65292;&#26368;&#22823;&#30340;&#38459;&#30861;&#24448;&#24448;&#19981;&#26159;&#25216;&#26415;&#65292;&#32780;&#26159;&#8220;&#20449;&#20219;&#8221;&#12290;&#27491;&#22914; Skip &#23448;&#26041;&#25152;&#35328;&#65292;&#20225;&#19994;&#26368;&#25285;&#24515;&#30340;&#26159;&#8220;rug pull&#8221;&#8212;&#8212;&#19975;&#19968;&#20844;&#21496;&#20498;&#38381;&#25110;&#34987;&#25910;&#36141;&#65292;&#25276;&#27880;&#22312;&#36825;&#20010;&#24037;&#20855;&#19978;&#30340;&#20135;&#21697;&#21644;&#25216;&#26415;&#26632;&#23558;&#38754;&#20020;&#25512;&#20498;&#37325;&#26469;&#30340;&#39118;&#38505;&#12290;Skip &#24076;&#26395;&#36890;&#36807;&#24320;&#28304;&#28040;&#38500;&#36825;&#31181;&#20449;&#20219;&#21361;&#26426;&#65292;&#35753;&#33258;&#24049;&#21644;&#20854;&#20182;&#36328;&#24179;&#21488;&#24037;&#20855;&#31449;&#22312;&#21516;&#19968;&#36215;&#36305;&#32447;&#19978;&#65292;&#21516;&#26102;&#28608;&#27963;&#31038;&#21306;&#21147;&#37327;&#65292;&#21152;&#36895;&#29983;&#24577;&#24314;&#35774;&#12290;</p><p>&#23613;&#31649;&#31038;&#21306;&#23545; Skip &#30340;&#24320;&#28304;&#20915;&#23450;&#32473;&#20104;&#20102;&#20805;&#20998;&#32943;&#23450;&#65292;&#20294;&#20063;&#26377;&#19981;&#23569;&#20154;&#25285;&#24515;&#65306;&#22312;&#25918;&#24323;&#20102; license key &#36825;&#19968;&#31283;&#23450;&#25910;&#20837;&#26469;&#28304;&#21518;&#65292;&#20165;&#38752;&#36190;&#21161;&#27169;&#24335;&#33021;&#21542;&#25903;&#25745;&#25345;&#32493;&#24320;&#21457;&#25104;&#26412;&#65311;&#27605;&#31455;&#65292;&#25104;&#21151;&#30340;&#24320;&#28304;&#21830;&#19994;&#26696;&#20363;&#34429;&#26377;&#65292;&#20294;&#22833;&#36133;&#30340;&#20063;&#19981;&#23569;&#12290;&#36825;&#31181;&#25285;&#24551;&#24182;&#38750;&#26462;&#20154;&#24551;&#22825;&#12290;&#22312;&#25105;&#25776;&#20889;&#26412;&#26399;&#21608;&#25253;&#26102;&#65288;&#23459;&#24067;&#24320;&#28304;&#25968;&#22825;&#21518;&#65289;&#65292;&#23613;&#31649;&#24320;&#28304;&#28040;&#24687;&#22312;&#31038;&#20132;&#23186;&#20307;&#19978;&#24341;&#21457;&#20102;&#28909;&#35758;&#65292;&#20294;&#22312; GitHub &#19978;&#65292;Skip &#30340;&#20010;&#20154;&#36190;&#21161;&#32773;&#20165;&#26377;&#21313;&#20960;&#20301;&#12290;&#20174;&#8220;&#28909;&#38393;&#30340;&#35752;&#35770;&#8221;&#21040;&#8220;&#30495;&#37329;&#30333;&#38134;&#30340;&#25903;&#25345;&#8221;&#65292;&#20013;&#38388;&#30340;&#40511;&#27807;&#20284;&#20046;&#27604;&#24819;&#35937;&#20013;&#36824;&#35201;&#28145;&#12290;&#36825;&#25110;&#35768;&#20063;&#35299;&#37322;&#20102;&#20026;&#20160;&#20040; Skip &#26368;&#32456;&#36873;&#25321;&#20102;&#24320;&#28304;&#8212;&#8212;&#22312;&#26080;&#27861;&#35828;&#26381;&#24320;&#21457;&#32773;&#8221;&#20184;&#36153;&#20351;&#29992;&#8221;&#26102;&#65292;&#33267;&#23569;&#35201;&#20105;&#21462;&#21040;&#20182;&#20204;&#8221;&#20813;&#36153;&#20351;&#29992;&#8221;&#30340;&#26426;&#20250;&#12290;</p><p>&#19968;&#20010;&#26377;&#36259;&#30340;&#29616;&#35937;&#26159;&#65292;&#22312;&#32943;&#23450;&#19982;&#24551;&#34385;&#24182;&#23384;&#30340;&#24773;&#32490;&#20013;&#65292;&#35752;&#35770;&#30340;&#28966;&#28857;&#24708;&#28982;&#21457;&#29983;&#20102;&#21464;&#21270;&#65306;&#20174;&#8220;&#20026;&#20160;&#20040;&#35201;&#33457;&#38065;&#20080; Skip &#32780;&#19981;&#26159;&#29992;&#20813;&#36153;&#30340; KMP?&#8221;&#21464;&#25104;&#20102;&#8220;&#20320;&#26159;&#26356;&#21916;&#27426;&#20889; Swift &#36824;&#26159; Kotlin?&#8221;&#12290;&#36825;&#20010;&#36716;&#21464;&#24847;&#20041;&#37325;&#22823;&#8212;&#8212;&#23427;&#24847;&#21619;&#30528; Skip &#24050;&#32463;&#25104;&#21151;&#23558;&#31454;&#20105;&#32500;&#24230;&#20174;&#8220;&#21830;&#19994;&#27169;&#24335;&#8221;&#36716;&#31227;&#21040;&#20102;&#8220;&#35821;&#35328;&#29983;&#24577;&#8221;&#65292;&#32780;&#21442;&#19982;&#31454;&#20105;&#30340;&#20027;&#20307;&#20063;&#20174;&#8220;&#19968;&#23478;&#23567;&#20844;&#21496;&#8221;&#25193;&#23637;&#20026;&#8220;&#25972;&#20010; Swift &#31038;&#21306;&#8221;&#12290;&#22312;&#36825;&#22330;&#35821;&#35328;&#20043;&#20105;&#20013;&#65292;Skip &#32874;&#26126;&#22320;&#65288;&#25110;&#35768;&#26159;&#26080;&#24847;&#38388;&#65289;&#23558;&#33258;&#24049;&#30340;&#35282;&#33394;&#20174;&#8220;&#20027;&#35282;&#8221;&#21464;&#25104;&#20102;&#8220;&#22522;&#30784;&#35774;&#26045;&#8221;&#12290;</p><p>Skip &#26368;&#26089;&#30340;&#20986;&#21457;&#28857;&#26159;&#30475;&#21040;&#20102;&#19968;&#20010;&#21830;&#19994;&#26426;&#20250;&#65292;&#35748;&#20026;&#26377;&#36275;&#22815;&#30340;&#21830;&#19994;&#22238;&#25253;&#12290;&#22914;&#26524;&#19981;&#26159;&#26377;&#36825;&#26679;&#30340;&#39044;&#26399;&#65292;&#20165;&#38752;&#23448;&#26041;&#25110;&#31038;&#21306;&#30340;&#21147;&#37327;&#65292;Swift &#21487;&#33021;&#26080;&#27861;&#24555;&#36895;&#25512;&#36827;&#22312;&#20854;&#20182;&#24179;&#21488;&#19978;&#30340;&#36827;&#23637;&#12290;&#36825;&#19968;&#36335;&#24452;&#19982; The Browser Company &#20026;&#20102;&#25171;&#36896; Arc &#27983;&#35272;&#22120;&#32780;&#22823;&#21147;&#25512;&#21160; Swift &#22312; Windows &#24179;&#21488;&#19978;&#30340;&#36866;&#37197;&#22914;&#20986;&#19968;&#36761;&#12290;</p><p>&#20316;&#20026;&#19968;&#20010; Swift &#24320;&#21457;&#32773;&#65292;&#25105;&#30001;&#34935;&#24076;&#26395; Skip &#30340;&#36825;&#27425;&#35843;&#25972;&#33021;&#22815;&#21462;&#24471;&#39044;&#26399;&#25928;&#26524;&#12290;&#24320;&#28304;&#26159;&#19968;&#22330;&#20449;&#20219;&#30340;&#23454;&#39564;&#65292;&#20063;&#26159;&#19968;&#27425;&#29983;&#24577;&#30340;&#25237;&#36164;&#12290;&#22914;&#26524;&#20320;&#20063;&#26399;&#24453; Swift &#33021;&#22312; iOS &#20043;&#22806;&#30340;&#24179;&#21488;&#19978;&#25317;&#26377;&#26356;&#22810;&#21487;&#33021;&#65292;&#19981;&#22952;&#20174;&#25104;&#20026;&#19968;&#20010;<a href="https://github.com/sponsors/skiptools">&#29420;&#31435;&#36190;&#21161;&#32773;</a>($10/&#26376;)&#20570;&#36215;&#8212;&#8212;&#36825;&#19981;&#20165;&#26159;&#23545; Skip &#30340;&#25903;&#25345;&#65292;&#26356;&#26159;&#23545;&#25972;&#20010; Swift &#36328;&#24179;&#21488;&#29983;&#24577;&#30340;&#25237;&#31080;&#12290;&#24320;&#28304;&#30340; Skip &#33021;&#36208;&#22810;&#36828;&#65292;&#21462;&#20915;&#20110;&#26377;&#22810;&#23569;&#20154;&#24895;&#24847;&#20174;&#26049;&#35266;&#32773;&#21464;&#25104;&#21442;&#19982;&#32773;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-119/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div><hr></div><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://afdian.com/a/fatbobman">&#29233;&#21457;&#30005;</a>&#65292;<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/letting-swift-closures-automatically-inherit-isolation/?utm_source=fatbobman%20weekly%20issue%20120&amp;utm_medium=web">isolated(any) &#19982; #isolation&#65306;&#35753; Swift &#38381;&#21253;&#33258;&#21160;&#32487;&#25215;&#38548;&#31163;&#22495;</a></strong></h3><p>Swift 6 &#20026;&#24182;&#21457;&#24341;&#20837;&#20102;&#35768;&#22810;&#26032;&#21151;&#33021;&#19982;&#20851;&#38190;&#23383;&#12290;&#34429;&#28982;&#20854;&#20013;&#19981;&#23569;&#20869;&#23481;&#22312;&#26085;&#24120;&#24320;&#21457;&#20013;&#21487;&#33021;&#40092;&#23569;&#29992;&#21040;&#65292;&#20294;&#19968;&#26086;&#36973;&#36935;&#29305;&#23450;&#22330;&#26223;&#65292;&#33509;&#23545;&#36825;&#20123;&#26032;&#27010;&#24565;&#32570;&#20047;&#20102;&#35299;&#65292;&#21363;&#20415;&#26377; AI &#36741;&#21161;&#20063;&#21487;&#33021;&#38519;&#20837;&#20725;&#23616;&#12290;&#26412;&#25991;&#23558;&#36890;&#36807;&#19968;&#20010;&#22312;&#24320;&#21457;&#27979;&#35797;&#20013;&#36935;&#21040;&#30340;&#23454;&#38469;&#24182;&#21457;&#38382;&#39064;&#65292;&#26469;&#20171;&#32461;&#22914;&#20309;&#21033;&#29992; <code>@isolated(any)</code> &#20197;&#21450; <code>#isolation</code> &#23439;&#65292;&#23454;&#29616;&#20989;&#25968;&#30340;&#38548;&#31163;&#22495;&#32487;&#25215;&#65292;&#20174;&#32780;&#35753;&#32534;&#35793;&#22120;&#33258;&#21160;&#25512;&#26029;&#38381;&#21253;&#30340;&#36816;&#34892;&#29615;&#22659;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0120-01">SwiftData &#25968;&#25454;&#36801;&#31227;&#20840;&#35299;&#26512; (A Deep Dive into SwiftData migrations)</a></strong></h3><p>&#38543;&#30528;&#24212;&#29992;&#30340;&#21457;&#23637;&#65292;&#25968;&#25454;&#27169;&#22411;&#20960;&#20046;&#26080;&#21487;&#36991;&#20813;&#22320;&#20250;&#20986;&#29616;&#21464;&#21270;&#65292;&#22914;&#20309;&#23433;&#20840;&#22320;&#36827;&#34892;&#25968;&#25454;&#36801;&#31227;&#23545;&#24456;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#37117;&#26159;&#19968;&#20010;&#19981;&#23567;&#30340;&#25361;&#25112;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;<a href="https://x.com/donnywals">Donny Wals</a> &#20840;&#38754;&#35762;&#35299;&#20102; SwiftData &#30340;&#25968;&#25454;&#36801;&#31227;&#26426;&#21046;&#65292;&#20174;&#22522;&#30784;&#30340;&#29256;&#26412;&#25511;&#21046;&#21040;&#22797;&#26434;&#30340;&#33258;&#23450;&#20041;&#36801;&#31227;&#31574;&#30053;&#12290;&#20854;&#20013;&#65292;Donny &#32473;&#20986;&#20102;&#20960;&#20010;&#29305;&#21035;&#26377;&#20215;&#20540;&#30340;&#24314;&#35758;&#65306;&#21363;&#20351;&#26159; V1 &#29256;&#26412;&#20063;&#24212;&#35813;&#20351;&#29992; <code>VersionedSchema</code> &#36827;&#34892;&#23553;&#35013;&#65292;&#20026;&#26410;&#26469;&#30340;&#36801;&#31227;&#25171;&#22909;&#22522;&#30784;&#65307;&#21482;&#22312; App Store &#21457;&#24067;&#21608;&#26399;&#20043;&#38388;&#24341;&#20837;&#26032;&#30340; Schema &#29256;&#26412;&#65292;&#32780;&#19981;&#26159;&#22312;&#24320;&#21457;&#36807;&#31243;&#20013;&#39057;&#32321;&#20462;&#25913;&#65307;&#23545;&#20110;&#36731;&#37327;&#36801;&#31227;&#65292;&#21363;&#20351; SwiftData &#21487;&#20197;&#33258;&#21160;&#23436;&#25104;&#65292;&#20063;&#24314;&#35758;&#26174;&#24335;&#22320;&#20889;&#20837; <code>SchemaMigrationPlan</code> &#20013;&#65292;&#20351;&#24847;&#22270;&#26356;&#21152;&#26126;&#30830;&#19988;&#26131;&#20110;&#27979;&#35797;&#12290;</p><p>&#25991;&#31456;&#30340;&#19968;&#22823;&#20142;&#28857;&#26159;&#35814;&#32454;&#35299;&#37322;&#20102; <code>MigrationStage.custom</code> &#20013; <code>willMigrate</code> &#19982; <code>didMigrate</code> &#30340;&#36866;&#29992;&#22330;&#26223;&#65292;&#24182;&#25552;&#20986;&#20102;&#24212;&#23545;&#22797;&#26434;&#37325;&#26500;&#65288;&#20363;&#22914;&#25286;&#20998;&#23454;&#20307;&#65289;&#30340;&#8220;&#26725;&#25509;&#29256;&#26412;&#65288;Bridge Version&#65289;&#8221;&#31574;&#30053;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-02">&#20026;&#20160;&#20040; MVVM-C &#22312; SwiftUI &#39033;&#30446;&#20013;&#20381;&#28982;&#33021;&#25193;&#23637; (Why MVVM-C with Coordinators does Scale -&gt; A real-world SwiftUI perspective)</a></strong></h3><p>&#23613;&#31649;&#26631;&#39064;&#20013;&#21253;&#21547;&#8220;MVVM-C&#8221;&#65292;&#20294;&#36825;&#24182;&#38750;&#19968;&#31687;&#21333;&#32431;&#20026;&#26576;&#31181;&#26550;&#26500;&#27169;&#24335;&#36777;&#25252;&#30340;&#25991;&#31456;&#12290;<a href="https://www.linkedin.com/in/valentebruno/">Bruno Valente Pimentel</a> &#22312;&#25991;&#20013;&#37325;&#26032;&#23450;&#20041;&#20102;&#8220;&#25193;&#23637;&#24615;&#8221;&#30340;&#20869;&#28085;&#8212;&#8212;&#23427;&#19981;&#24212;&#20165;&#20197;&#23631;&#24149;&#25110;&#25991;&#20214;&#30340;&#25968;&#37327;&#26469;&#34913;&#37327;&#65292;&#32780;&#24212;&#30475;&#20854;&#26159;&#21542;&#25903;&#25345;&#39640;&#25928;&#30340;&#22810;&#20154;&#21327;&#20316;&#21450;&#21151;&#33021;&#30340;&#29420;&#31435;&#28436;&#36827;&#12290;&#27491;&#22914;&#20316;&#32773;&#25152;&#35328;&#65306;&#8220;&#26550;&#26500;&#26080;&#20851;&#20046;&#27169;&#24335;&#65292;&#32780;&#20851;&#20046;&#20943;&#23569;&#24656;&#24807;&#8221;&#8212;&#8212;&#20943;&#23569;&#20462;&#25913;&#20195;&#30721;&#12289;&#22242;&#38431;&#21327;&#20316;&#20197;&#21450;&#21151;&#33021;&#28436;&#36827;&#26102;&#30340;&#24656;&#24807;&#12290;</p><blockquote><p>&#26080;&#35770;&#20320;&#20542;&#21521;&#20110;&#21738;&#31181;&#26550;&#26500;&#27169;&#24335;&#65292;&#22312;&#29992;&#23427;&#26500;&#24314; SwiftUI &#39033;&#30446;&#26102;&#65292;&#37117;&#24212;&#35813;&#35748;&#30495;&#24605;&#32771;&#65306;&#25105;&#20204;&#21040;&#24213;&#26159;&#22312;&#21033;&#29992; SwiftUI &#30340;&#29305;&#24615;&#65292;&#36824;&#26159;&#22312;&#35797;&#22270;&#25226; SwiftUI &#25913;&#36896;&#25104;&#25105;&#20204;&#29087;&#24713;&#30340; UIKit&#65311;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-03">TCA &#26550;&#26500;&#30340;&#30495;&#23454;&#35780;&#20272; (TCA (Composable Architecture): The Honest Review)</a></strong></h3><p>&#32487; Bruno &#20026; MVVM-C &#8220;&#27491;&#21517;&#8221;&#21518;&#65292;<a href="https://www.linkedin.com/in/chandrawelim/">Chandra Welim</a> &#23545;&#21478;&#19968;&#20010;&#26497;&#20855;&#20105;&#35758;&#30340;&#26550;&#26500;&#8212;&#8212;TCA &#36827;&#34892;&#20102;&#23458;&#35266;&#35780;&#20272;&#12290;&#20316;&#32773;&#24635;&#32467;&#20102; TCA &#30340;&#20116;&#22823;&#20248;&#21183;&#65288;&#21487;&#39044;&#27979;&#30340;&#29366;&#24577;&#31649;&#29702;&#12289;&#20248;&#31168;&#30340;&#21487;&#27979;&#35797;&#24615;&#12289;&#26102;&#38388;&#26053;&#34892;&#35843;&#35797;&#12289;&#32452;&#21512;&#24615;&#12289;&#24378;&#31867;&#22411;&#23433;&#20840;&#65289;&#21644;&#20116;&#22823;&#25361;&#25112;&#65288;&#23398;&#20064;&#26354;&#32447;&#12289;&#26679;&#26495;&#20195;&#30721;&#12289;&#22242;&#38431;&#37319;&#32435;&#12289;&#23545;&#31616;&#21333;&#24212;&#29992;&#36807;&#24230;&#35774;&#35745;&#12289;&#31532;&#19977;&#26041;&#20381;&#36182;&#65289;&#65292;&#21516;&#26102;&#32473;&#20986;&#20102;&#21153;&#23454;&#30340;&#24314;&#35758;&#65306;TCA &#26159;&#19968;&#20010;&#24378;&#22823;&#30340;&#24037;&#20855;&#65292;&#20294;&#32477;&#38750;&#36866;&#29992;&#20110;&#25152;&#26377;&#22330;&#26223;&#12290;&#23545;&#20110;&#31616;&#21333;&#30340; MVP &#25110;&#32570;&#20047;&#20989;&#25968;&#24335;&#32534;&#31243;&#32972;&#26223;&#30340;&#22242;&#38431;&#65292;&#20256;&#32479;&#30340; MVVM &#25110;&#35768;&#26159;&#26356;&#21153;&#23454;&#30340;&#36873;&#25321;&#65307;&#32780;&#23545;&#20110;&#29366;&#24577;&#38169;&#32508;&#22797;&#26434;&#12289;&#38656;&#35201;&#8220;&#26102;&#38388;&#26053;&#34892;&#8221;&#35843;&#35797;&#30340;&#22823;&#22411;&#39033;&#30446;&#65292;TCA &#21017;&#33021;&#25552;&#20379;&#26080;&#19982;&#20262;&#27604;&#30340;&#25484;&#25511;&#21147;&#12290;&#26680;&#24515;&#32467;&#35770;&#65306;TCA &#22312;&#20320;&#38656;&#35201;&#26102;&#24456;&#20540;&#24471;&#65292;&#20294;&#22823;&#22810;&#25968;&#24212;&#29992;&#24182;&#19981;&#38656;&#35201;&#23427;&#12290;</p><blockquote><p>&#26550;&#26500;&#36873;&#25321;&#27809;&#26377;&#38134;&#24377;&#65292;&#21482;&#26377;&#22312;&#29305;&#23450;&#19978;&#19979;&#25991;&#20013;&#30340;&#26435;&#34913;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-04">&#35753; C &#24211;&#22312; Swift &#20013;&#8220;&#20687;&#21407;&#29983; API &#19968;&#26679;&#22909;&#29992;&#8221; (Improving the usability of C libraries in Swift)</a></strong></h3><p>Swift &#34429;&#28982;&#29983;&#26469;&#23601;&#20860;&#23481; C&#65292;&#20294;&#30452;&#25509;&#35843;&#29992; C API &#24448;&#24448;&#20307;&#39564;&#19981;&#20339;&#8212;&#8212;&#24320;&#21457;&#32773;&#36890;&#24120;&#38656;&#35201;&#38754;&#23545;&#35064;&#25351;&#38024;&#12289;&#25163;&#21160;&#20869;&#23384;&#31649;&#29702;&#20197;&#21450;&#19981;&#31526;&#21512; Swift &#21629;&#21517;&#20064;&#24815;&#30340;&#20989;&#25968;&#12290;&#20026;&#20102;&#33719;&#24471;&#8220;&#21407;&#29983;&#8221;&#20307;&#39564;&#65292;&#24320;&#21457;&#32773;&#19981;&#24471;&#19981;&#32534;&#20889;&#21644;&#32500;&#25252;&#32321;&#29712;&#30340; Wrapper &#23618;&#12290;&#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;<a href="https://sfba.social/@dgregor79">Doug Gregor</a> &#35814;&#32454;&#20171;&#32461;&#20102;&#22914;&#20309;&#21033;&#29992; API Notes &#21644; Clang Attributes &#26426;&#21046;&#65292;&#22312;&#19981;&#20462;&#25913; C &#24211;&#23454;&#29616;&#20195;&#30721;&#30340;&#21069;&#25552;&#19979;&#65292;&#8220;&#25351;&#23548;&#8221; Swift &#32534;&#35793;&#22120;&#29983;&#25104;&#31526;&#21512; Swift &#39118;&#26684;&#30340;&#25509;&#21475;&#12290;</p><p>&#36825;&#39033;&#25913;&#36827;&#30340;&#24847;&#20041;&#22312;&#20110;&#65292;&#23427;&#23558;&#8220;&#23553;&#35013; C &#24211;&#8221;&#30340;&#25104;&#26412;&#20174;&#36923;&#36753;&#23618;&#65288;&#32534;&#20889; Swift &#33014;&#27700;&#20195;&#30721;&#65289;&#36716;&#31227;&#21040;&#20102;&#22768;&#26126;&#23618;&#65288;&#32534;&#20889; API Notes &#25110;&#28155;&#21152;&#22836;&#25991;&#20214;&#27880;&#35299;&#65289;&#12290;&#36825;&#23545;&#20110; Embedded Swift &#30340;&#26222;&#21450;&#33267;&#20851;&#37325;&#35201;&#65292;&#22240;&#20026;&#23884;&#20837;&#24335;&#24320;&#21457;&#39640;&#24230;&#20381;&#36182;&#29616;&#26377;&#30340; C &#24211;&#29983;&#24577;&#12290;&#38543;&#30528;&#24037;&#20855;&#38142;&#30340;&#23436;&#21892;&#65292;&#26410;&#26469;&#24320;&#21457;&#32773;&#21487;&#33021;&#21482;&#38656;&#35201;&#32473; C &#24211;&#21152;&#20960;&#20010;&#27880;&#35299;&#65292;&#23601;&#33021;&#30452;&#25509;&#22312; Swift &#20013;&#20687;&#20351;&#29992;&#21407;&#29983;&#24211;&#19968;&#26679;&#35843;&#29992;&#23427;&#12290;&#25991;&#31456;&#36824;&#25552;&#20379;&#20102;&#22522;&#20110;&#27491;&#21017;&#34920;&#36798;&#24335;&#30340;&#33258;&#21160;&#21270;&#33050;&#26412;&#65292;&#21487;&#20197;&#20026;&#32467;&#26500;&#21270;&#30340; C &#22836;&#25991;&#20214;&#25209;&#37327;&#29983;&#25104; API Notes&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-05">&#22312; Yocto &#31995;&#32479;&#20013;&#26500;&#24314; Swift (Introduction to Building Swift for Yocto)</a></strong></h3><p>&#23545;&#20110;&#22823;&#22810;&#25968; iOS &#24320;&#21457;&#32773;&#26469;&#35828;&#65292;Yocto &#21487;&#33021;&#27604;&#36739;&#38476;&#29983;&#65292;&#20294;&#23427;&#26159;&#23884;&#20837;&#24335; Linux &#39046;&#22495;&#30340;&#20107;&#23454;&#26631;&#20934;&#8212;&#8212;&#23427;&#33021;&#22815;&#31934;&#30830;&#25511;&#21046;&#31995;&#32479;&#20013;&#21253;&#21547;&#30340;&#27599;&#19968;&#20010;&#32452;&#20214;&#12290;&#38543;&#30528; Embedded Swift &#30340;&#25512;&#36827;&#65292;&#22914;&#20309;&#22312; Yocto &#29983;&#24577;&#20013;&#38598;&#25104; Swift &#25104;&#20026;&#20102;&#19968;&#20010;&#20851;&#38190;&#38382;&#39064;&#12290;<a href="https://x.com/xtremekforever">Jesse L. Zamora</a> &#35814;&#32454;&#28436;&#31034;&#20102;&#22914;&#20309;&#20351;&#29992;&#36817;&#26399;&#37325;&#33719;&#26356;&#26032;&#30340; <code>meta-swift</code> &#22312; Yocto &#31995;&#32479;&#20013;&#26500;&#24314; Swift &#36816;&#34892;&#29615;&#22659;&#12290;&#25991;&#31456;&#20197; Raspberry Pi Zero 2 &#20026;&#20363;&#65292;&#20174; Docker &#29615;&#22659;&#25645;&#24314;&#12289;Yocto &#26500;&#24314;&#12289;&#38236;&#20687;&#28903;&#24405;&#21040;&#23454;&#38469;&#36816;&#34892;&#65292;&#28436;&#31034;&#20102;&#23436;&#25972;&#30340;&#24037;&#20316;&#27969;&#12290;</p><p>&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;&#23436;&#25972;&#26500;&#24314;&#36807;&#31243;&#38656;&#35201;&#25968;&#23567;&#26102;&#65292;&#19988;&#35201;&#27714;&#23545; Yocto &#26500;&#24314;&#31995;&#32479;&#26377;&#22522;&#26412;&#20102;&#35299;&#12290;&#19981;&#36807;&#65292;&#25991;&#31456;&#25552;&#20379;&#30340; <a href="https://github.com/swift-embedded-linux/meta-swift-examples">meta-swift-examples</a> &#20179;&#24211;&#24050;&#32463;&#21253;&#21547;&#20102; Docker &#21270;&#30340;&#26500;&#24314;&#29615;&#22659;&#21644;&#19968;&#38190;&#33050;&#26412;&#65292;&#22823;&#22823;&#38477;&#20302;&#20102;&#19978;&#25163;&#38376;&#27099;&#12290;</p><blockquote><p><a href="https://github.com/jeremy-prater/meta-swift">meta-swift</a> &#26159; Swift &#35821;&#35328;&#30340; Yocto &#23618;&#65292;&#27492;&#21069;&#26366;&#38271;&#26399;&#20572;&#28382;&#20110; Swift 5.7&#65292;&#20294;&#22312;&#31038;&#21306;&#30340;&#21162;&#21147;&#19979;&#65292;&#30446;&#21069;&#24050;&#25903;&#25345;&#21040; Swift 6.1.3&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-06">&#35753; Xcode &#30340; DEBUG &#26500;&#24314;&#33258;&#21160;&#37096;&#32626;&#21040; /Applications (TIL how to auto-move Xcode DEBUG builds to Applications)</a></strong></h3><p>&#24320;&#21457;&#21253;&#21547; App Intents &#30340;&#24212;&#29992;&#26102;&#65292;&#20320;&#21487;&#33021;&#36935;&#21040;&#36807;&#36825;&#20010;&#38382;&#39064;&#65306;App Intents &#24517;&#39035;&#22312; <code>/Applications</code> &#30446;&#24405;&#19979;&#25165;&#33021;&#22312; Shortcuts.app &#20013;&#26174;&#31034;&#12290;&#36825;&#24847;&#21619;&#30528; DEBUG &#26500;&#24314;&#40664;&#35748;&#25918;&#22312; DerivedData &#20013;&#26102;&#65292;&#24320;&#21457;&#32773;&#26080;&#27861;&#27979;&#35797; Shortcuts &#38598;&#25104;&#12290; <a href="https://norden.social/@czottmann">Carlo Zottmann</a> &#26366;&#38271;&#26399;&#20351;&#29992;&#22797;&#26434;&#30340; Post-build &#33050;&#26412;&#26469;&#25644;&#36816; App&#65292;&#20294;&#20182;&#22312;&#26412;&#25991;&#20013;&#20998;&#20139;&#20102;&#19968;&#20010;&#26356;&#8220;&#21407;&#29983;&#8221;&#30340;&#26041;&#26696;&#8212;&#8212;&#36890;&#36807;&#19977;&#34892; <code>.xcconfig</code> &#37197;&#32622;&#35753; Xcode &#33258;&#21160;&#23558;&#26500;&#24314;&#20135;&#29289;&#37096;&#32626;&#21040;&#25351;&#23450;&#30446;&#24405;&#65292;&#24182;&#22312;&#28165;&#29702;&#26500;&#24314;&#26102;&#27491;&#30830;&#21024;&#38500;&#24050;&#37096;&#32626;&#30340;&#25991;&#20214;&#12290;</p><blockquote><p>&#36825;&#20010;&#25216;&#24039;&#19981;&#20165;&#36866;&#29992;&#20110; App Intents &#27979;&#35797;&#65292;&#20063;&#36866;&#29992;&#20110;&#20219;&#20309;&#38656;&#35201;&#23558; DEBUG &#26500;&#24314;&#25918;&#21040;&#29305;&#23450;&#20301;&#32622;&#30340;&#22330;&#26223;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-07">&#29992; Swift Charts &#26500;&#24314;&#33258;&#23450;&#20041;&#21487;&#20132;&#20114;&#20202;&#34920;&#30424; (Visualise anything with SwiftUI Charts)</a></strong></h3><p>&#22914;&#26524;&#20320;&#38656;&#35201;&#33258;&#23450;&#20041;&#19968;&#20010;&#21487;&#21160;&#30011;&#12289;&#21487;&#20132;&#20114;&#30340;&#29615;&#24418;&#21387;&#21147;&#20202;&#34920;&#30424;&#65288;Stress Indicator&#65289;&#30340; SwiftUI &#32452;&#20214;&#65292;&#20320;&#20250;&#22914;&#20309;&#36827;&#34892;&#65311;&#26159;&#20351;&#29992; Shape&#65292;&#36824;&#26159; Canvas&#65311;<a href="https://www.linkedin.com/in/kyryl-horbushko-67936bb5/">Kyryl Horbushko</a> &#22312;&#26412;&#25991;&#20013;&#23637;&#31034;&#20102;&#19968;&#20010;&#38750;&#24120;&#26377;&#21019;&#24847;&#30340;&#35299;&#27861;&#8212;&#8212;&#21033;&#29992; Swift Charts &#30340; <code>SectorMark</code>&#65292;&#20248;&#38597;&#19988;&#39640;&#25928;&#22320;&#23454;&#29616;&#20102;&#38656;&#27714;&#12290;</p><p>Kyryl &#30340;&#23454;&#29616;&#25171;&#30772;&#20102;&#25105;&#20204;&#23545; Swift Charts &#20165;&#29992;&#20110;&#8220;&#25968;&#25454;&#21487;&#35270;&#21270;&#8221;&#30340;&#21051;&#26495;&#21360;&#35937;&#12290;&#23545;&#20110;&#38656;&#35201;&#24320;&#21457;&#20581;&#24247;&#31867;&#12289;&#37329;&#34701;&#31867;&#22797;&#26434; Dashboard &#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#31181;&#26497;&#20855;&#21442;&#32771;&#20215;&#20540;&#30340;&#8221;&#38477;&#32500;&#25171;&#20987;&#8221;&#24335;&#26041;&#26696;&#8212;&#8212;&#29992;&#25968;&#25454;&#21487;&#35270;&#21270;&#26694;&#26550;&#35299;&#20915;&#33258;&#23450;&#20041; UI &#38382;&#39064;&#65292;&#26082;&#20943;&#23569;&#20195;&#30721;&#37327;&#65292;&#21448;&#33719;&#24471;&#20869;&#32622;&#30340;&#21160;&#30011;&#21644;&#20132;&#20114;&#25903;&#25345;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0120-08">Commander&#65306;&#20860;&#39038;&#19987;&#27880;&#19982;&#28789;&#27963;&#30340; AI &#21464;&#25104;&#20307;&#39564;</a></strong></h3><p>&#25105;&#21916;&#27426;&#22312; macOS &#19978;&#20351;&#29992; CLI &#24037;&#20855;(Claude Code&#12289;Codex)&#65292;&#20294;&#21407;&#29983;&#32456;&#31471;&#24212;&#29992;&#30340;&#35270;&#35273;&#20307;&#39564;&#23454;&#22312;&#19981;&#25954;&#24685;&#32500;&#65292;&#22240;&#27492;&#22810;&#25968;&#24773;&#20917;&#19979;&#25105;&#37117;&#22312; VSCode &#20013;&#36890;&#36807;&#25554;&#20214;&#26469;&#25913;&#21892;&#20307;&#39564;&#12290;&#28982;&#32780;&#65292;VSCode &#30340;&#19968;&#20010;&#35774;&#35745;&#22987;&#32456;&#35753;&#25105;&#22256;&#25200;&#65306;&#21363;&#20415;&#23558; Claude Code &#30340;&#23545;&#35805;&#26639;&#26368;&#22823;&#21270;&#65292;AI &#20462;&#25913;&#25991;&#20214;&#26102;&#20173;&#20250;&#33258;&#21160;&#25171;&#24320;&#26032;&#30340;&#25991;&#20214;&#26639;&#25110;&#31383;&#21475;&#65292;&#25171;&#26029;&#26082;&#26377;&#30340;&#20132;&#20114;&#33410;&#22863;&#12290;</p><p><a href="https://x.com/krzyzanowskim">Marcin Krzy&#380;anowski</a> &#24320;&#21457;&#30340; macOS &#21407;&#29983;&#24212;&#29992; Commander &#32473;&#20102;&#25105;&#19968;&#20010;&#26032;&#30340;&#36873;&#25321;&#12290;&#23427;&#25552;&#20379;&#20102;&#19968;&#20010;&#27604;&#32456;&#31471;&#26356;&#20248;&#30340;&#20132;&#20114;&#30028;&#38754;&#65292;&#21516;&#26102;&#20445;&#25252;&#20102;&#25105;&#30340;&#8220;&#24515;&#27969;&#8221;&#8212;&#8212;&#25991;&#20214;&#21482;&#22312;&#38656;&#35201;&#26102;&#25165;&#24320;&#21551;&#65292;&#24182;&#33021;&#35843;&#29992;&#31995;&#32479;&#40664;&#35748;&#24212;&#29992;&#26597;&#30475;&#12290;Commander &#30446;&#21069;&#25903;&#25345; Claude Code &#21644; Codex&#65292;&#20869;&#32622;&#20102; Git worktrees &#21644; Code diff &#25903;&#25345;&#65292;&#19988;&#23436;&#20840;&#20813;&#36153;&#12290;&#23427;&#22312;&#32456;&#31471;&#30340;&#8220;&#19987;&#27880;&#8221;&#19982; VSCode &#30340;&#8220;&#28789;&#27963;&#8221;&#20043;&#38388;&#65292;&#26500;&#24314;&#20102;&#19968;&#20010;&#32477;&#20339;&#30340;&#20013;&#38388;&#22320;&#24102;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0120-09">Oh My Agents: &#32479;&#19968;&#31649;&#29702;&#25152;&#26377; AI &#32534;&#31243;&#21161;&#25163;&#30340;&#37197;&#32622;</a></strong></h3><p>&#38543;&#30528; Claude Code&#12289;Cursor&#12289;Codex&#12289;Windsurf &#31561; AI &#32534;&#31243;&#21161;&#25163;&#30340;&#28044;&#29616;&#65292;&#24320;&#21457;&#32773;&#38754;&#20020;&#30528;&#19968;&#20010;&#26032;&#38382;&#39064;&#65306;&#22914;&#20309;&#31649;&#29702;&#25955;&#33853;&#22312;&#21508;&#20010;&#39033;&#30446;&#20013;&#30340; prompts&#12289;skills &#21644; rules? &#27599;&#20010; Agent &#37117;&#26377;&#33258;&#24049;&#30340;&#37197;&#32622;&#35268;&#33539;(<code>CLAUDE.md</code>&#12289;<code>CURSOR.md</code>...)&#65292;&#25163;&#21160;&#22797;&#21046;&#31896;&#36148;&#19981;&#20165;&#20302;&#25928;&#65292;&#36824;&#23481;&#26131;&#23548;&#33268;&#29256;&#26412;&#28151;&#20081;&#12290;<a href="https://x.com/onevcat">&#29579;&#24013;(onevcat)</a> &#24320;&#21457;&#30340; Oh My Agents &#25552;&#20379;&#20102;&#35299;&#20915;&#26041;&#26696;&#12290;</p><p>&#26680;&#24515;&#21151;&#33021;:</p><ul><li><p>&#38598;&#20013;&#31649;&#29702;&#25152;&#26377; AI Agent &#37197;&#32622;</p></li><li><p>&#23450;&#20041;&#20998;&#21457;&#35268;&#21017;&#65292;&#19968;&#38190;&#21516;&#27493;&#21040;&#22810;&#20010;&#39033;&#30446;</p></li><li><p>&#21452;&#21521;&#21516;&#27493;&#65292;&#39033;&#30446;&#25913;&#36827;&#21487;&#25289;&#22238;&#20013;&#22830;&#24211;&#24182;&#26356;&#26032;&#25152;&#26377;&#20851;&#32852;&#39033;&#30446;</p></li><li><p>&#39044;&#35272;&#21464;&#26356;&#65292;&#36991;&#20813;&#24847;&#22806;&#35206;&#30422;</p></li></ul><p>&#27880;&#65306;&#30446;&#21069;&#20165;&#25903;&#25345; macOS (Windows/Linux &#24320;&#21457;&#20013;)&#65292;Beta &#26399;&#38388;&#20813;&#36153;&#12290;</p>]]></content:encoded></item></channel></rss>