<?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>Wed, 14 Oct 2026 09:44:37 GMT</lastBuildDate><atom:link href="https://weekly.fatbobman.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[fatbobman]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[fatbobman@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[fatbobman@substack.com]]></itunes:email><itunes:name><![CDATA[Fatbobman(东坡肘子)]]></itunes:name></itunes:owner><itunes:author><![CDATA[Fatbobman(东坡肘子)]]></itunes:author><googleplay:owner><![CDATA[fatbobman@substack.com]]></googleplay:owner><googleplay:email><![CDATA[fatbobman@substack.com]]></googleplay:email><googleplay:author><![CDATA[Fatbobman(东坡肘子)]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Fatbobman's Swift Weekly #157]]></title><description><![CDATA[When Build in Public Goes Back Underground]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-157</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-157</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 12 Oct 2026 12:01:33 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ymSg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_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_!ymSg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ymSg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ymSg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3babf911-f149-4e99-b563-006f6490967c_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;:78920,&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/219838007?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_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_!ymSg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!ymSg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3babf911-f149-4e99-b563-006f6490967c_1536x1024.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>When Build in Public Goes Back Underground</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-157/">Read on web &#8594;</a></p><p>Over the past few months, the community has seen a growing number of cases where AI is used to quickly reverse-engineer commercial products or create pixel-perfect replicas of popular apps. With enough tokens to burn, building a free &#8220;shadow version&#8221; no longer seems particularly difficult.</p><p>At the same time, many indie developers who embrace Build in Public are facing a new challenge: while the original product is still being refined, imitators can take the screenshots and ideas its creator has shared on social media, feed them to AI, and launch a clone before the original is even ready. Some do it out of technical curiosity and experimentation; others simply want to showcase what AI tools can produce. But there are also those who see it as an easy shortcut.</p><p>Watching this trend unfold, I can&#8217;t help feeling a little uneasy.</p><p>Cloning and imitation have existed for decades, but AI has dramatically reduced the time and cost required for implementation. An original creator may spend months discovering an idea worth pursuing, while an imitator can look at the finished result, skip much of the trial and error, and produce something remarkably similar in appearance and functionality in a very short time.</p><p>Competition, of course, needs challengers, and AI can be just as helpful to original creators. If lower implementation costs push teams to innovate faster, improve the experience, or offer better value, that is something consumers should welcome. After all, copying an interface or a feature set is not the same as copying the product itself. The design judgments hidden in the details and the deep understanding of users&#8217; needs cannot be reproduced through a pixel-perfect clone alone.</p><p>But not every creator has enough time and resources to wait for the market to recognize those differences. For an established commercial product, a few AI-generated clones may not pose much of a threat. For an indie developer still trying to find a place in the market, however, a lead of just a few weeks or months can matter enormously.</p><p>Build in Public used to be a way for indie developers to build a community and gather feedback by sharing their ideas, designs, and development process. More importantly, it encouraged people to share ideas, experiments, and even failures with other developers while their products were still rough and unfinished.</p><p>That kind of culture didn&#8217;t just appear out of nowhere. It was built gradually over the years.</p><p>But when publicly shared information also becomes a shortcut for others to find targets to clone and bypass the exploration process, the risks of sharing begin to change. If more developers conclude that staying quiet until a product is ready is safer than sharing openly, Build in Public may genuinely start turning back into Build in Private.</p><p>That is what makes me most uneasy.</p><p>What we stand to lose may not just be a few original products that never make it to market, but the hard-won culture among indie developers of sharing unfinished ideas with one another&#8212;and inspiring each other in the process.</p><p><a href="https://fatbobman.com/en/weekly/issue-156/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/ai-friendly-framework/?utm_source=fatbobman%20weekly%20issue%20157&amp;utm_medium=web">AI-Friendly Frameworks: As Abstraction Moves Up, How Can Verification Keep Pace?</a></strong></h3><p>With the rise of AI Coding, a growing number of people have begun to favor the idea that imperative frameworks like UIKit may be better suited to Coding Agents than SwiftUI. The reasoning is intuitive&#8212;UIKit&#8217;s logic is direct and explicit: create objects, set properties, add them to the hierarchy, establish constraints. Every step operates on something concrete. SwiftUI, by contrast, folds a great deal of implementation detail behind declarative syntax, where state, environment, identity, layout, and rendering together determine the final result. Once the rendered result deviates from expectations, an Agent is left facing a black box, trying to infer what happened internally from limited external observations.</p><p>But perhaps the problem is not abstraction itself. Rather, as abstraction moves up, we have neglected the other half of the work: observation and verification. When abstraction hides lower-level details, we need mechanisms at the new level that can make intent explicit and verify that it has been preserved.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0157-01">Revisiting &#8220;Split Isolation&#8221;</a></strong></h3><p>In a non-Sendable type with no actor isolation of its own, adding <code>@MainActor</code> to only some methods gives the same instance different isolation requirements. <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> calls this pattern &#8220;split isolation.&#8221; Many developers, including Matt himself, have considered it a poor design.</p><p>In this article, Matt revisits his earlier assessment: while split isolation should still generally be avoided, it can have value in certain situations. In particular, when only a small amount of independent functionality depends on MainActor, or when migrating to Swift 6 and trying to prevent isolation requirements from rapidly spreading through a large existing codebase, adding <code>@MainActor</code> locally can be a reasonable or even necessary trade-off. Whether to use split isolation depends on whether it is obscuring the type&#8217;s true isolation requirements or deliberately expressing a localized constraint.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-02">The Task Is Not the Unit of Work: Ownership, Isolation, and Cancellation Beyond async/await</a></strong></h3><p>SwiftUI&#8217;s <code>.task</code> automatically cancels a task when the view disappears. That&#8217;s convenient, but it can also make it all too easy for developers to tie the lifetimes of various business operations to the UI lifecycle. A disappearing screen, however, does not necessarily mean that the user&#8217;s intent has become irrelevant.</p><p>&#8288;<a href="https://www.linkedin.com/in/valentebruno/">Bruno Valente Pimentel</a> points out that a Task is a unit of execution, but not necessarily a unit of product work; an Actor solves isolation, but does not decide who should own the work; structured concurrency can propagate cancellation, but cannot determine whether that parent-child relationship matches the product&#8217;s semantics. Rather than first asking &#8220;Where should I put my Task?&#8221;, Bruno suggests first defining the operation&#8217;s intent, owner, resource, and lifetime, and only then choosing the appropriate implementation mechanism. The compiler can help us ensure concurrency safety, but it cannot decide for us when a piece of work truly &#8220;stops mattering.&#8221;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-03">A SwiftUI calendar with custom days and event indicators</a></strong></h3><p>When implementing a calendar UI, drawing the date grid is often not the difficult part. The real challenges lie in the state and edge cases behind it: separating the currently displayed date from the selected range; consistently using <code>Calendar</code> for date arithmetic and day boundaries; correctly handling the first weekday, month boundaries, daylight saving time, and non-Gregorian calendars; making taps and drags work together for continuous range selection; avoiding repeated scans of the event list in every cell; and preventing unnecessary cell view reconstruction. <a href="https://www.linkedin.com/in/szymon-lorenz-8b9b6b8b/">Szymon Lorenz</a> shares what he learned while developing the calendar component for &#8288;<a href="https://github.com/shial4/SwiftUIComponents">SwiftUIComponents</a>, an open-source project that also provides Android compatibility through &#8288;<a href="https://skip.dev/docs/modules/skip-fuse-ui/">Skip Fuse</a>.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-04">SwiftUI Profiling with Instruments: 100,000 Calendar Events</a></strong></h3><p>When a SwiftUI app with a large dataset starts to stutter, is the problem in the database, data processing, or view updates? <a href="https://x.com/szamski">Maciej Szamowski</a> stress-tested hora Calendar with a database containing 100,000 events. Using Instruments&#8217; SwiftUI, Hangs, Hitches, and Time Profiler tools, he found that a large amount of main-thread time during stalls was being spent on SwiftUI graph updates, shifting the optimization focus away from the database and toward data preparation and the view update path.</p><blockquote><p>Both of these calendar articles adopt similar optimization principles for improving rendering performance: avoid making individual cells perform repetitive work that can be handled at a higher level. Prepare data and interaction context upstream &#8594; let downstream Views receive values that are as stable and as close to their final presentation form as possible &#8594; keep information unrelated to rendering out of the SwiftUI observation/update graph.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-05">Why your fastlane snapshot screenshots are all in English(and how to check every language)</a></strong></h3><p>When using fastlane snapshot to generate localized App Store screenshots in bulk, you may encounter a frustrating problem: the language directories are all created correctly, yet every screenshot still appears in English. What makes the issue particularly troublesome is that there is no single cause, making it difficult to diagnose.</p><p><a href="https://www.linkedin.com/in/manulorenzo/">Manuel Lorenzo Parejo&#8288;</a> lists five areas to investigate: when <code>setupSnapshot</code> is called; how snapshot is launched; <code>localize_simulator</code>; whether the App Bundle contains the corresponding <code>.lproj</code>; and whether residual app state is affecting the language setting. He also provides the free <code>shotfleet check</code> command, which recognizes text in screenshots and compares it against the app&#8217;s own localized strings, allowing you to verify in bulk whether the generated screenshots actually use the expected language.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0157-06">Redlamp: A Native RAW Editor Built by a Photography Enthusiast with AI</a></strong></h3><p>Redlamp is an open-source macOS RAW photo editor built with Swift and Metal under the MPL-2.0 license, with a development-panel workflow familiar to Lightroom users. Its creator, <a href="https://x.com/pedrogomes">Pedro Gomes</a>, is both an engineer and a photography enthusiast who has &#8288;<a href="https://redlamp.app/blog/why-im-building-redlamp">long wanted more tools that fit the way he prefers to work</a>.</p><p>Even though AI has played a significant role in developing the project, Redlamp still reflects clear personal intent and judgment. Pedro chose to make the photo library database a rebuildable index while keeping important information alongside the photos themselves. When measurements showed that an optimization around mask edges was sacrificing detail, he narrowed the scope where the algorithm would be applied. Decisions like these give Redlamp a distinct authorial imprint.</p><p>The project&#8217;s blog documents many of the ideas and trade-offs that emerged during development, while the repository also makes its collaboration rules and verification mechanisms for coding agents public. Pedro is exploring how multiple agents can participate in the continuous development of complex native software&#8212;and how to determine whether the results they deliver are actually reliable.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-07">AnnotateIt: Closing the Loop from Annotation to Create ML Training on Mac</a></strong></h3><p>For developers who want to train custom Object Detection models with Create ML, the training itself is often not the most troublesome part. Data preparation is where much of the time goes: the Create ML app itself does not provide annotation tools, so developers typically need another tool to draw bounding boxes and then organize the results into a data format Create ML can use.</p><p>AnnotateIt brings these steps together in a single <a href="https://apps.apple.com/us/app/annotateit-ai/id6751442622?platform=mac">Mac app</a>. After annotating images, you can train an Object Detector locally using Apple Create ML. The resulting model can then be applied to new images and videos to generate suggested annotations, which can be reviewed and corrected manually. For Swift developers, this not only lowers the barrier to experimenting with local Object Detection, but also connects &#8220;annotation &#8594; training &#8594; prediction &#8594; correction&#8221; into a complete workflow.</p><p>In the official parking-lot example, a model trained on 292 images completes in under a minute. The entire process requires neither a Python environment nor a cloud GPU, and the data can remain entirely on the local machine.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-08">InnoDI: Turning the Dependency Graph into a Verifiable Build Artifact</a></strong></h3><p>InnoDI, developed by &#8288;<a href="https://github.com/InnoSquadCorp">Ethan Parker</a>, is a dependency injection framework built around Swift Macros. It turns the initialization and parameter-passing logic that would otherwise be written manually in an object graph into explicit dependency declarations, while generating container initializers and type-safe test override interfaces. Macros handle local diagnostics, an SPM Build Plugin validates the dependency graph across files and modules, and a companion CLI can inspect and analyze that graph.</p><p>InnoSquad&#8217;s InnoFlow, InnoRouter, and InnoNetwork follow a similar philosophy, reducing implicit behavior through explicit boundaries and repeatable verification: declare constraints up front wherever possible, and leave runtime behavior to unified execution policies.</p><blockquote><p>In the age of AI Coding, framework authors need to rethink who their consumers are. &#8220;Making code easier for developers to write&#8221; may no longer be the only top priority. When the cost of learning is no longer borne entirely by human developers, &#8220;making the intent and behavior of code easier to verify&#8221; is rapidly becoming more important.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-09">SimAgentation: Annotate the iOS Simulator in Your Browser and Hand the Work to AI</a></strong></h3><p>When using AI to adjust an interface, accurately expressing &#8220;this is what needs to change&#8221; can often take more effort than describing the change itself. SimAgentation, developed by <a href="https://x.com/vanillaCitron">citron</a>, lets developers interact with the iOS Simulator from a browser (IOSurface -&gt; VideoToolbox -&gt; WebCodecs), select UI elements or draw a box around a region, and write modification requests directly. The tool sends the feedback, along with element information, source-code search hints, full-screen screenshots, and cropped screenshots, to a coding assistant through MCP, while displaying the processing status in the browser.</p><p>The optional SimAgentationPlus adds <code>.simTag()</code> for attaching names, files, and line numbers to views. This shares some similarities with the element-anchor approach I used in <a href="https://fatbobman.com/en/posts/letting-ai-see-swiftui/">FlowCanvas</a>: combining visual output with structured information so that AI can understand the target of feedback more precisely.</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-157?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-157?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#24403; Build in Public &#37325;&#26032;&#36716;&#20837;&#22320;&#19979;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-157/">&#32593;&#39029;&#29256;</a></strong></p><p>&#36807;&#21435;&#19968;&#27573;&#26102;&#38388;&#65292;&#31038;&#21306;&#37324;&#39057;&#32321;&#20986;&#29616;&#29992; AI &#24555;&#36895;&#36870;&#21521;&#21830;&#19994;&#20135;&#21697;&#25110;&#20687;&#32032;&#32423;&#22797;&#21051;&#28909;&#38376;&#24212;&#29992;&#30340;&#26696;&#20363;&#12290;&#21482;&#35201; Token &#20805;&#36275;&#65292;&#25645;&#24314;&#19968;&#20010;&#20813;&#36153;&#30340;&#8220;&#24433;&#23376;&#29256;&#26412;&#8221;&#20284;&#20046;&#24050;&#19981;&#20877;&#26159;&#38590;&#20107;&#12290;</p><p>&#19982;&#27492;&#21516;&#26102;&#65292;&#35768;&#22810;&#22362;&#25345;&#8220;&#20844;&#24320;&#26500;&#24314;&#8221;&#65288;Build in Public&#65289;&#30340;&#29420;&#31435;&#24320;&#21457;&#32773;&#20063;&#36973;&#36935;&#20102;&#26032;&#30340;&#25361;&#25112;&#65306;&#21407;&#21019;&#20135;&#21697;&#23578;&#22312;&#25171;&#30952;&#20043;&#20013;&#65292;&#19968;&#20123;&#20223;&#21046;&#32773;&#20165;&#20973;&#20316;&#32773;&#22312;&#31038;&#20132;&#23186;&#20307;&#19978;&#25259;&#38706;&#30340;&#35774;&#35745;&#25130;&#22270;&#21644;&#24605;&#36335;&#65292;&#20415;&#20511;&#21161; AI &#25250;&#20808;&#19968;&#27493;&#19978;&#32447;&#20102;&#8220;&#20811;&#38534;&#21697;&#8221;&#12290;&#26377;&#30340;&#28304;&#20110;&#25216;&#26415;&#25506;&#32034;&#19982;&#22909;&#22855;&#65292;&#26377;&#30340;&#21482;&#26159;&#24819;&#23637;&#31034; AI &#24037;&#20855;&#30340;&#29983;&#20135;&#21147;&#65292;&#20294;&#20063;&#19981;&#20047;&#25237;&#26426;&#21462;&#24039;&#30340;&#25463;&#24452;&#24515;&#24577;&#12290;</p><p>&#30475;&#30528;&#36825;&#32929;&#39118;&#27668;&#65292;&#25105;&#22987;&#32456;&#24863;&#21040;&#19968;&#19997;&#19981;&#23433;&#12290;</p><p>&#22797;&#21051;<strong>&#19982;</strong>&#27169;&#20223;&#22312;&#36807;&#21435;&#20960;&#21313;&#24180;&#20013;&#19968;&#30452;&#37117;&#23384;&#22312;&#65292;&#20294; AI &#22823;&#24133;&#21387;&#32553;&#20102;&#23454;&#29616;&#25152;&#38656;&#35201;&#30340;&#26102;&#38388;&#19982;&#25104;&#26412;&#12290;&#21407;&#21019;&#32773;&#21487;&#33021;&#33457;&#36153;&#25968;&#26376;&#25165;&#25214;&#21040;&#19968;&#20010;&#20540;&#24471;&#20570;&#30340;&#26041;&#21521;&#65292;&#27169;&#20223;&#32773;&#21364;&#21487;&#20197;&#35266;&#23519;&#26368;&#32456;&#32467;&#26524;&#65292;&#36339;&#36807;&#22823;&#37327;&#35797;&#38169;&#65292;&#22312;&#26497;&#30701;&#26102;&#38388;&#20869;&#20570;&#20986;&#19968;&#20010;&#22806;&#35266;&#21644;&#21151;&#33021;&#37117;&#39047;&#20026;&#30456;&#20284;&#30340;&#29256;&#26412;&#12290;</p><p>&#21830;&#19994;&#31454;&#20105;&#24403;&#28982;&#38656;&#35201;&#40118;&#40060;&#65292;AI &#23545;&#21407;&#21019;&#32773;&#21516;&#26679;&#26377;&#25152;&#24110;&#21161;&#12290;&#22914;&#26524;&#26356;&#20302;&#30340;&#23454;&#29616;&#38376;&#27099;&#33021;&#22815;&#20419;&#20351;&#21407;&#21019;&#22242;&#38431;&#21152;&#24555;&#21019;&#26032;&#12289;&#25913;&#21892;&#20307;&#39564;&#65292;&#25110;&#32773;&#25552;&#20379;&#26356;&#20855;&#24615;&#20215;&#27604;&#30340;&#26381;&#21153;&#65292;&#33258;&#28982;&#26159;&#28040;&#36153;&#32773;&#20048;&#20110;&#30475;&#21040;&#30340;&#32467;&#26524;&#12290;&#26356;&#20309;&#20917;&#65292;&#22797;&#21046;&#30028;&#38754;&#19982;&#21151;&#33021;&#24182;&#19981;&#31561;&#20110;&#22797;&#21046;&#20135;&#21697;&#26412;&#36523;&#65292;&#37027;&#20123;&#38544;&#34255;&#22312;&#32454;&#33410;&#20013;&#30340;&#35774;&#35745;&#21028;&#26029;&#21644;&#23545;&#29992;&#25143;&#38656;&#27714;&#30340;&#29702;&#35299;&#65292;&#24182;&#19981;&#26159;&#19968;&#27425;&#20687;&#32032;&#32423;&#22797;&#21051;&#23601;&#33021;&#33719;&#24471;&#30340;&#12290;</p><p>&#20294;&#24182;&#19981;&#26159;&#27599;&#20010;&#21407;&#21019;&#32773;&#37117;&#26377;&#36275;&#22815;&#30340;&#26102;&#38388;&#21644;&#36164;&#28304;&#65292;&#31561;&#24453;&#24066;&#22330;&#35748;&#35782;&#21040;&#36825;&#20123;&#24046;&#24322;&#12290;&#23545;&#20110;&#25104;&#29087;&#30340;&#21830;&#19994;&#20135;&#21697;&#65292;&#20960;&#20010; AI &#20223;&#21046;&#21697;&#25110;&#35768;&#19981;&#36275;&#20197;&#26500;&#25104;&#30495;&#27491;&#30340;&#23041;&#32961;&#65307;&#20294;&#23545;&#20110;&#20173;&#22312;&#23547;&#25214;&#24066;&#22330;&#20301;&#32622;&#30340;&#29420;&#31435;&#24320;&#21457;&#32773;&#65292;&#20960;&#21608;&#29978;&#33267;&#20960;&#20010;&#26376;&#30340;&#26102;&#38388;&#24046;&#23601;&#21487;&#33021;&#38750;&#24120;&#37325;&#35201;&#12290;</p><p>&#26366;&#32463;&#65292;&#36890;&#36807; Build in Public &#20998;&#20139;&#21019;&#24847;&#12289;&#35774;&#35745;&#19982;&#24320;&#21457;&#36807;&#31243;&#65292;&#26159;&#29420;&#31435;&#24320;&#21457;&#32773;&#24314;&#31435;&#31038;&#21306;&#12289;&#33719;&#24471;&#21453;&#39304;&#30340;&#19968;&#31181;&#26041;&#24335;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#23427;&#35753;&#22823;&#23478;&#24895;&#24847;&#22312;&#20135;&#21697;&#36824;&#19981;&#25104;&#29087;&#30340;&#26102;&#20505;&#65292;&#23601;&#25343;&#20986;&#33258;&#24049;&#30340;&#24819;&#27861;&#12289;&#23581;&#35797;&#29978;&#33267;&#22833;&#36133;&#65292;&#19982;&#20854;&#20182;&#24320;&#21457;&#32773;&#20132;&#27969;&#12290;</p><p>&#36825;&#31181;&#27675;&#22260;&#24182;&#19981;&#26159;&#22825;&#28982;&#23384;&#22312;&#30340;&#65292;&#32780;&#26159;&#36825;&#20123;&#24180;&#19968;&#28857;&#28857;&#24418;&#25104;&#30340;&#12290;</p><p>&#20294;&#24403;&#20844;&#24320;&#30340;&#20449;&#24687;&#21516;&#26102;&#25104;&#20026;&#21035;&#20154;&#23547;&#25214;&#22797;&#21051;&#30446;&#26631;&#12289;&#24555;&#36895;&#36339;&#36807;&#25506;&#32034;&#38454;&#27573;&#30340;&#25463;&#24452;&#65292;&#20998;&#20139;&#25152;&#38656;&#35201;&#25215;&#25285;&#30340;&#39118;&#38505;&#20063;&#21457;&#29983;&#20102;&#21464;&#21270;&#12290;&#22914;&#26524;&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#21457;&#29616;&#65292;&#22312;&#20135;&#21697;&#30495;&#27491;&#20934;&#22791;&#22909;&#20043;&#21069;&#65292;&#20445;&#25345;&#27785;&#40664;&#27604;&#20844;&#24320;&#20998;&#20139;&#26356;&#21152;&#23433;&#20840;&#65292;&#37027;&#20040; Build in Public &#25110;&#35768;&#30495;&#30340;&#20250;&#37325;&#26032;&#21464;&#25104; Build in Private&#12290;</p><p>&#36825;&#25165;&#26159;&#26368;&#35753;&#25105;&#19981;&#23433;&#30340;&#22320;&#26041;&#12290;</p><p>&#25105;&#20204;&#22833;&#21435;&#30340;&#21487;&#33021;&#19981;&#21482;&#26159;&#20960;&#20010;&#23578;&#26410;&#38382;&#19990;&#30340;&#21407;&#21019;&#20135;&#21697;&#65292;&#32780;&#26159;&#29420;&#31435;&#24320;&#21457;&#32773;&#22909;&#19981;&#23481;&#26131;&#24418;&#25104;&#30340;&#12289;&#24895;&#24847;&#24444;&#27492;&#23637;&#31034;&#19981;&#25104;&#29087;&#24819;&#27861;&#24182;&#30456;&#20114;&#21551;&#21457;&#30340;&#20132;&#27969;&#27675;&#22260;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-156/">&#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/ai-friendly-framework/?utm_source=fatbobman%20weekly%20issue%20157&amp;utm_medium=web">AI-Friendly Framework&#65306;&#24403;&#25277;&#35937;&#19978;&#31227;&#65292;&#39564;&#35777;&#22914;&#20309;&#36319;&#19978;&#65311;</a></strong></h3><p>&#38543;&#30528; AI Coding &#30340;&#26222;&#21450;&#65292;&#19981;&#23569;&#20154;&#24320;&#22987;&#20542;&#21521;&#19968;&#31181;&#35266;&#28857;&#65306;UIKit &#36825;&#26679;&#30340;&#21629;&#20196;&#24335;&#26694;&#26550;&#65292;&#21487;&#33021;&#27604; SwiftUI &#26356;&#36866;&#21512; Coding Agent&#12290;&#29702;&#30001;&#24456;&#30452;&#35266;&#8212;&#8212;UIKit &#30340;&#36923;&#36753;&#30452;&#25509;&#26126;&#30830;&#65306;&#21019;&#24314;&#23545;&#35937;&#12289;&#35774;&#32622;&#23646;&#24615;&#12289;&#21152;&#20837;&#23618;&#32423;&#12289;&#24314;&#31435;&#32422;&#26463;&#65292;&#27599;&#19968;&#27493;&#37117;&#26377;&#20855;&#20307;&#25805;&#20316;&#30340;&#23454;&#20307;&#65307;&#32780; SwiftUI &#25226;&#22823;&#37327;&#23454;&#29616;&#32454;&#33410;&#25910;&#26463;&#22312;&#22768;&#26126;&#24335;&#35821;&#27861;&#20043;&#21518;&#65292;&#29366;&#24577;&#12289;&#29615;&#22659;&#12289;&#36523;&#20221;&#12289;&#24067;&#23616;&#19982;&#28210;&#26579;&#20849;&#21516;&#20915;&#23450;&#20102;&#26368;&#32456;&#32467;&#26524;&#12290;&#19968;&#26086;&#21576;&#29616;&#25928;&#26524;&#20559;&#31163;&#39044;&#26399;&#65292;Agent &#21482;&#33021;&#23545;&#30528;&#40657;&#30418;&#65292;&#20174;&#26377;&#38480;&#30340;&#22806;&#37096;&#29616;&#35937;&#21435;&#21453;&#25512;&#20869;&#37096;&#31350;&#31455;&#21457;&#29983;&#20102;&#20160;&#20040;&#12290;</p><p>&#20294;&#38382;&#39064;&#25110;&#35768;&#24182;&#19981;&#22312;&#25277;&#35937;&#26412;&#36523;&#65292;&#32780;&#22312;&#20110;&#25277;&#35937;&#20043;&#21518;&#25105;&#20204;&#28431;&#25481;&#20102;&#21478;&#19968;&#21322;&#24037;&#20316;&#65306;&#35266;&#23519;&#19982;&#39564;&#35777;&#12290;&#24403;&#25277;&#35937;&#38544;&#34255;&#20102;&#24213;&#23618;&#32454;&#33410;&#65292;&#25105;&#20204;&#24517;&#39035;&#22312;&#26032;&#30340;&#23618;&#32423;&#19978;&#65292;&#34917;&#40784;&#33021;&#22815;&#22266;&#23450;&#24182;&#39564;&#35777;&#24847;&#22270;&#30340;&#25163;&#27573;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0157-01">&#37325;&#23457;&#12300;&#23616;&#37096;&#38548;&#31163;&#12301;&#30340;&#21033;&#24330;&#19982;&#26435;&#34913; (Revisiting &#8220;Split Isolation&#8221;)</a></strong></h3><p>&#22312;&#19968;&#20010;&#26412;&#36523;&#27809;&#26377; actor isolation&#12289;&#19988; non-Sendable &#30340;&#31867;&#22411;&#20013;&#65292;&#21482;&#32473;&#37096;&#20998;&#26041;&#27861;&#28155;&#21152; <code>@MainActor</code>&#65292;&#20250;&#35753;&#21516;&#19968;&#20010;&#23454;&#20363;&#21516;&#26102;&#20855;&#26377;&#19981;&#21516;&#30340;&#38548;&#31163;&#35201;&#27714;&#12290;<a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#23558;&#36825;&#31181;&#27169;&#24335;&#31216;&#20026; &#8220;split isolation&#8221;&#12290;&#21253;&#25324; Matt &#33258;&#24049;&#22312;&#20869;&#65292;&#19981;&#23569;&#24320;&#21457;&#32773;&#37117;&#35748;&#20026;&#36825;&#24182;&#38750;&#19968;&#20010;&#22909;&#30340;&#35774;&#35745;&#12290;</p><p>&#22312;&#26412;&#25991;&#20013;&#65292;Matt &#37325;&#26032;&#23457;&#35270;&#20102;&#33258;&#24049;&#36807;&#21435;&#30340;&#21028;&#26029;&#65306;split isolation &#34429;&#28982;&#20173;&#24212;&#23613;&#37327;&#36991;&#20813;&#65292;&#20294;&#22312;&#29305;&#23450;&#22330;&#26223;&#20173;&#26377;&#23384;&#22312;&#20215;&#20540;&#12290;&#23588;&#20854;&#22312;&#21482;&#26377;&#23569;&#37327;&#29420;&#31435;&#21151;&#33021;&#20381;&#36182; MainActor&#65292;&#25110;&#32773;&#27491;&#22312;&#21521; Swift 6 &#36801;&#31227;&#12289;&#19981;&#24076;&#26395;&#38548;&#31163;&#35201;&#27714;&#36805;&#36895;&#25193;&#25955;&#21040;&#22823;&#37327;&#26082;&#26377;&#20195;&#30721;&#26102;&#65292;&#23616;&#37096;&#28155;&#21152; <code>@MainActor</code> &#20063;&#21487;&#33021;&#26159;&#19968;&#31181;&#21512;&#29702;&#29978;&#33267;&#24517;&#35201;&#30340;&#26435;&#34913;&#12290;&#26159;&#21542;&#37319;&#29992; split isolation&#65292;&#20851;&#38190;&#22312;&#20110;&#23427;&#26159;&#22312;&#25513;&#30422;&#31867;&#22411;&#30495;&#27491;&#30340;&#38548;&#31163;&#38656;&#27714;&#65292;&#36824;&#26159;&#22312;&#26377;&#24847;&#35782;&#22320;&#34920;&#36798;&#19968;&#20010;&#23616;&#37096;&#32422;&#26463;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-02">&#36229;&#36234; async/await&#65306;Task &#19981;&#26159;&#19994;&#21153;&#24037;&#20316;&#30340;&#22522;&#26412;&#21333;&#20803; (The Task Is Not the Unit of Work: Ownership, Isolation, and Cancellation Beyond async/await)</a></strong></h3><p>SwiftUI &#30340; <code>.task</code> &#20250;&#38543;&#30528;&#35270;&#22270;&#28040;&#22833;&#33258;&#21160;&#21462;&#28040;&#20219;&#21153;&#65292;&#36825;&#24456;&#26041;&#20415;&#65292;&#20294;&#20063;&#24456;&#23481;&#26131;&#35753;&#24320;&#21457;&#32773;&#39034;&#25163;&#23558;&#21508;&#31867;&#19994;&#21153;&#25805;&#20316;&#30340;&#29983;&#21629;&#21608;&#26399;&#32465;&#23450;&#21040; UI &#30340;&#29983;&#21629;&#21608;&#26399;&#12290;&#19981;&#36807;&#65292;&#39029;&#38754;&#28040;&#22833;&#24182;&#19981;&#24847;&#21619;&#30528;&#29992;&#25143;&#30340;&#24847;&#22270;&#24050;&#32463;&#22833;&#25928;&#12290;</p><p>&#8288;<a href="https://www.linkedin.com/in/valentebruno/">Bruno Valente Pimentel</a> &#25351;&#20986;&#65306;Task &#26159;&#25191;&#34892;&#21333;&#20803;&#65292;&#21364;&#19981;&#19968;&#23450;&#26159;&#20135;&#21697;&#24037;&#20316;&#30340;&#21333;&#20803;&#65307;Actor &#35299;&#20915; isolation&#65292;&#21364;&#19981;&#20250;&#20915;&#23450;&#35841;&#24212;&#35813;&#25317;&#26377;&#36825;&#39033;&#24037;&#20316;&#65307;&#32467;&#26500;&#21270;&#24182;&#21457;&#33021;&#22815;&#20256;&#25773; cancellation&#65292;&#21364;&#26080;&#27861;&#21028;&#26029;&#36825;&#31181;&#29238;&#23376;&#20851;&#31995;&#26159;&#21542;&#31526;&#21512;&#20135;&#21697;&#35821;&#20041;&#12290;&#30456;&#27604;&#20808;&#32771;&#34385;&#8220;Task &#24212;&#35813;&#25918;&#22312;&#21738;&#37324;&#8221;&#65292;Bruno &#24314;&#35758;&#39318;&#20808;&#26126;&#30830;&#25805;&#20316;&#30340; intent&#12289;owner&#12289;resource &#21644; lifetime&#65292;&#28982;&#21518;&#20877;&#36873;&#25321;&#20855;&#20307;&#30340;&#23454;&#29616;&#26426;&#21046;&#12290;&#32534;&#35793;&#22120;&#21487;&#20197;&#24110;&#21161;&#25105;&#20204;&#20445;&#35777;&#24182;&#21457;&#23433;&#20840;&#65292;&#20294;&#26080;&#27861;&#26367;&#25105;&#20204;&#20915;&#23450;&#19968;&#39033;&#24037;&#20316;&#20160;&#20040;&#26102;&#20505;&#25165;&#30495;&#27491;&#8220;&#19981;&#20877;&#37325;&#35201;&#8221;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-03">SwiftUI &#26085;&#21382;&#32452;&#20214;&#30340;&#36793;&#30028;&#19982;&#29366;&#24577;&#35774;&#35745; (A SwiftUI calendar with custom days and event indicators)</a></strong></h3><p>&#23454;&#29616;&#19968;&#20010;&#26085;&#21382; UI&#65292;&#30495;&#27491;&#40635;&#28902;&#30340;&#24448;&#24448;&#19981;&#26159;&#30011;&#20986;&#26085;&#26399;&#32593;&#26684;&#65292;&#32780;&#26159;&#22788;&#29702;&#32972;&#21518;&#30340;&#29366;&#24577;&#19982;&#36793;&#30028;&#26465;&#20214;&#65306;&#22914;&#20309;&#23558;&#24403;&#21069;&#26174;&#31034;&#26085;&#26399;&#19982;&#36873;&#25321;&#33539;&#22260;&#20998;&#31163;&#65307;&#32479;&#19968;&#36890;&#36807; <code>Calendar</code> &#22788;&#29702;&#26085;&#26399;&#36816;&#31639;&#21644; day boundary&#65307;&#27491;&#30830;&#24212;&#23545; first weekday&#12289;&#36328;&#26376;&#20221;&#12289;&#22799;&#20196;&#26102;&#20197;&#21450;&#38750; Gregorian Calendar&#65307;&#28857;&#20987;&#19982;&#25302;&#21160;&#22914;&#20309;&#20849;&#21516;&#23436;&#25104;&#36830;&#32493;&#30340;&#33539;&#22260;&#36873;&#25321;&#65307;&#36991;&#20813;&#27599;&#20010; cell &#37325;&#22797;&#25195;&#25551;&#20107;&#20214;&#21015;&#34920;&#65307;&#36991;&#20813;&#19981;&#24517;&#35201;&#30340; cell &#35270;&#22270;&#37325;&#24314;&#31561;&#25361;&#25112;&#12290;<a href="https://www.linkedin.com/in/szymon-lorenz-8b9b6b8b/">Szymon Lorenz</a> &#20998;&#20139;&#20102;&#20182;&#20026; &#8288;<a href="https://github.com/shial4/SwiftUIComponents">SwiftUIComponents</a> &#24320;&#21457;&#26085;&#21382;&#32452;&#20214;&#30340;&#32463;&#39564;&#65292;&#36825;&#20010;&#24320;&#28304;&#39033;&#30446;&#36890;&#36807; &#8288;<a href="https://skip.dev/docs/modules/skip-fuse-ui/">Skip Fuse</a> &#36824;&#25552;&#20379;&#20102; Android &#31471;&#30340;&#20860;&#23481;&#24615;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-04">100,000 &#20010;&#20107;&#20214;&#19979;&#30340; SwiftUI &#24615;&#33021;&#25490;&#26597;&#23454;&#25112; (SwiftUI Profiling with Instruments: 100,000 Calendar Events)</a></strong></h3><p>&#24403;&#19968;&#20010;&#21253;&#21547;&#22823;&#37327;&#25968;&#25454;&#30340; SwiftUI &#24212;&#29992;&#20986;&#29616;&#21345;&#39039;&#26102;&#65292;&#38382;&#39064;&#31350;&#31455;&#26469;&#33258;&#25968;&#25454;&#24211;&#12289;&#25968;&#25454;&#22788;&#29702;&#65292;&#36824;&#26159;&#35270;&#22270;&#26356;&#26032;&#65311;<a href="https://x.com/szamski">Maciej Szamowski</a> &#20351;&#29992;&#21253;&#21547; 100,000 &#20010;&#20107;&#20214;&#30340;&#27979;&#35797;&#25968;&#25454;&#24211;&#23545; hora Calendar &#36827;&#34892;&#21387;&#21147;&#27979;&#35797;&#65292;&#36890;&#36807; Instruments &#30340; SwiftUI&#12289;Hangs&#12289;Hitches &#21644; Time Profiler&#65292;&#21457;&#29616;&#21345;&#39039;&#26399;&#38388;&#22823;&#37327;&#20027;&#32447;&#31243;&#26102;&#38388;&#28040;&#32791;&#22312; SwiftUI graph updates &#19978;&#65292;&#20174;&#32780;&#23558;&#20248;&#21270;&#37325;&#28857;&#20174;&#25968;&#25454;&#24211;&#36716;&#21521;&#20102;&#25968;&#25454;&#20934;&#22791;&#21644;&#35270;&#22270;&#26356;&#26032;&#36335;&#24452;&#12290;</p><blockquote><p>&#21069;&#21518;&#20004;&#31687;&#26377;&#20851;&#26085;&#21382;&#30340;&#25991;&#31456;&#22312;&#25913;&#21892;&#28210;&#26579;&#24615;&#33021;&#19978;&#37117;&#37319;&#29992;&#20102;&#31867;&#20284;&#30340;&#20248;&#21270;&#21407;&#21017;&#65306;&#23613;&#37327;&#19981;&#35201;&#35753; cell &#33258;&#24049;&#25215;&#25285;&#37027;&#20123;&#21487;&#20197;&#22312;&#26356;&#39640;&#23618;&#32423;&#23436;&#25104;&#30340;&#37325;&#22797;&#24037;&#20316;&#12290;&#19978;&#23618;&#20934;&#22791;&#25968;&#25454;&#21644;&#20132;&#20114;&#19978;&#19979;&#25991; &#8594; &#19979;&#23618; View &#25509;&#25910;&#23613;&#21487;&#33021;&#31283;&#23450;&#12289;&#25509;&#36817;&#26368;&#32456;&#23637;&#31034;&#24418;&#24335;&#30340;&#20540; &#8594; &#19982; rendering &#26080;&#20851;&#30340;&#20449;&#24687;&#19981;&#35201;&#36827;&#20837; SwiftUI observation/update graph&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-05">&#25490;&#26597; fastlane snapshot &#22810;&#35821;&#35328;&#25130;&#22270;&#20840;&#37096;&#21464;&#25104;&#33521;&#35821;&#30340;&#38382;&#39064; (Why your fastlane snapshot screenshots are all in English)</a></strong></h3><p>&#20351;&#29992; fastlane snapshot &#25209;&#37327;&#29983;&#25104; App Store &#22810;&#35821;&#35328;&#25130;&#22270;&#26102;&#65292;&#26377;&#26102;&#20250;&#36935;&#21040;&#19968;&#20010;&#35753;&#20154;&#22836;&#30171;&#30340;&#38382;&#39064;&#65306;&#35821;&#35328;&#30446;&#24405;&#37117;&#27491;&#30830;&#21019;&#24314;&#20102;&#65292;&#25130;&#22270;&#20869;&#23481;&#21364;&#20840;&#37096;&#26174;&#31034;&#20026;&#33521;&#35821;&#12290;&#30495;&#27491;&#40635;&#28902;&#30340;&#26159;&#65292;&#23548;&#33268;&#36825;&#19968;&#29616;&#35937;&#30340;&#21407;&#22240;&#24182;&#19981;&#21807;&#19968;&#65292;&#25490;&#26597;&#36215;&#26469;&#20063;&#27604;&#36739;&#22256;&#38590;&#12290;</p><p><a href="https://www.linkedin.com/in/manulorenzo/">Manuel Lorenzo Parejo&#8288;</a> &#21015;&#20986;&#20102;&#20116;&#20010;&#25490;&#26597;&#28857;&#65306;<code>setupSnapshot</code> &#30340;&#35843;&#29992;&#26102;&#26426;&#65307;snapshot &#30340;&#21551;&#21160;&#26041;&#24335;&#65307;<code>localize_simulator</code>&#65307;App Bundle &#20013;&#26159;&#21542;&#21253;&#21547;&#23545;&#24212;&#30340; <code>.lproj</code>&#65307;&#27531;&#30041;&#30340; App &#29366;&#24577;&#26159;&#21542;&#24433;&#21709;&#35821;&#35328;&#35774;&#32622;&#12290;&#21516;&#26102;&#36824;&#25552;&#20379;&#20102;&#20813;&#36153;&#30340; <code>shotfleet check</code> &#21629;&#20196;&#65292;&#36890;&#36807;&#35782;&#21035;&#25130;&#22270;&#25991;&#23383;&#24182;&#19982; App &#33258;&#36523;&#30340;&#26412;&#22320;&#21270;&#23383;&#31526;&#20018;&#36827;&#34892;&#27604;&#23545;&#65292;&#25209;&#37327;&#26816;&#26597;&#29983;&#25104;&#30340;&#25130;&#22270;&#26159;&#21542;&#30495;&#30340;&#20351;&#29992;&#20102;&#39044;&#26399;&#35821;&#35328;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0157-06">Redlamp&#65306;&#19968;&#20301;&#25668;&#24433;&#29233;&#22909;&#32773;&#20511;&#21161; AI &#25171;&#36896;&#30340;&#21407;&#29983; RAW &#32534;&#36753;&#22120;</a></strong></h3><p>Redlamp &#26159;&#19968;&#27454;&#37319;&#29992; Swift &#21644; Metal &#24320;&#21457;&#30340;&#24320;&#28304; macOS RAW &#29031;&#29255;&#32534;&#36753;&#22120;&#65292;&#20351;&#29992; MPL-2.0 &#35768;&#21487;&#35777;&#65292;&#27839;&#29992;&#20102; Lightroom &#29992;&#25143;&#29087;&#24713;&#30340;&#26174;&#24433;&#38754;&#26495;&#19982;&#25805;&#20316;&#20064;&#24815;&#12290;&#20316;&#32773; <a href="https://x.com/pedrogomes">Pedro Gomes</a> &#26082;&#26159;&#19968;&#21517;&#24037;&#31243;&#24072;&#65292;&#20063;&#26159;&#19968;&#21517;&#25668;&#24433;&#29233;&#22909;&#32773;&#65292;&#8288;<a href="https://redlamp.app/blog/why-im-building-redlamp">&#19968;&#30452;&#24076;&#26395;&#26377;&#26356;&#22810;&#31526;&#21512;&#33258;&#24049;&#20351;&#29992;&#26041;&#24335;&#30340;&#24037;&#20855;&#36873;&#25321;</a>&#12290;</p><p>&#22312;&#36825;&#20010;&#22823;&#37327;&#20511;&#21161; AI &#36827;&#34892;&#24320;&#21457;&#30340;&#39033;&#30446;&#20013;&#65292;&#20173;&#33021;&#30475;&#21040;&#40092;&#26126;&#30340;&#20010;&#20154;&#24847;&#22270;&#19982;&#21028;&#26029;&#65306;Pedro &#36873;&#25321;&#35753;&#29031;&#29255;&#24211;&#30340;&#25968;&#25454;&#24211;&#25104;&#20026;&#21487;&#37325;&#24314;&#30340;&#32034;&#24341;&#65292;&#23558;&#37325;&#35201;&#20449;&#24687;&#20445;&#23384;&#22312;&#29031;&#29255;&#26049;&#65307;&#20063;&#20250;&#22312;&#27979;&#37327;&#21457;&#29616;&#33945;&#29256;&#36793;&#32536;&#20248;&#21270;&#25439;&#22833;&#20102;&#32454;&#33410;&#21518;&#65292;&#25910;&#32039;&#31639;&#27861;&#30340;&#36866;&#29992;&#33539;&#22260;&#12290;&#36825;&#20123;&#20855;&#20307;&#21462;&#33293;&#65292;&#35753; Redlamp &#24102;&#26377;&#40092;&#26126;&#30340;&#20316;&#32773;&#21360;&#35760;&#12290;</p><p>&#39033;&#30446;&#21338;&#23458;&#35760;&#24405;&#20102;&#19981;&#23569;&#24320;&#21457;&#36807;&#31243;&#20013;&#30340;&#24605;&#32771;&#65292;&#20195;&#30721;&#24211;&#20063;&#20844;&#24320;&#20102;&#38754;&#21521;&#32534;&#31243;&#20195;&#29702;&#30340;&#21327;&#20316;&#35268;&#21017;&#19982;&#39564;&#35777;&#26426;&#21046;&#12290;Pedro &#27491;&#22312;&#25506;&#32034;&#65292;&#22914;&#20309;&#35753;&#22810;&#20010;&#20195;&#29702;&#22312;&#25345;&#32493;&#36845;&#20195;&#20013;&#21442;&#19982;&#22797;&#26434;&#21407;&#29983;&#36719;&#20214;&#30340;&#24320;&#21457;&#65292;&#20197;&#21450;&#22914;&#20309;&#21028;&#26029;&#23427;&#20204;&#20132;&#20184;&#30340;&#25104;&#26524;&#26159;&#21542;&#21487;&#38752;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-07">AnnotateIt&#65306;&#22312; Mac &#19978;&#23436;&#25104;&#20174;&#26631;&#27880;&#21040; Create ML &#35757;&#32451;&#30340;&#38381;&#29615;</a></strong></h3><p>&#23545;&#24819;&#29992; Create ML &#35757;&#32451;&#33258;&#23450;&#20041; Object Detection &#27169;&#22411;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#35757;&#32451;&#26412;&#36523;&#24448;&#24448;&#19981;&#26159;&#26368;&#40635;&#28902;&#30340;&#37096;&#20998;&#12290;&#30495;&#27491;&#32791;&#26102;&#30340;&#26159;&#25968;&#25454;&#20934;&#22791;&#65306;Create ML &#24212;&#29992;&#26412;&#36523;&#19981;&#25552;&#20379;&#26631;&#27880;&#21151;&#33021;&#65292;&#24320;&#21457;&#32773;&#36890;&#24120;&#38656;&#35201;&#20511;&#21161;&#20854;&#20182;&#24037;&#20855;&#30011;&#26694;&#65292;&#20877;&#23558;&#32467;&#26524;&#25972;&#29702;&#25104; Create ML &#21487;&#20197;&#20351;&#29992;&#30340;&#25968;&#25454;&#26684;&#24335;&#12290;</p><p>AnnotateIt &#25226;&#36825;&#20123;&#27493;&#39588;&#25918;&#36827;&#20102;&#21516;&#19968;&#20010; <a href="https://apps.apple.com/us/app/annotateit-ai/id6751442622?platform=mac">Mac &#24212;&#29992;</a>&#12290;&#23436;&#25104;&#22270;&#29255;&#26631;&#27880;&#21518;&#65292;&#21487;&#20197;&#30452;&#25509;&#36890;&#36807; Apple Create ML &#22312;&#26412;&#22320;&#35757;&#32451; Object Detector&#65307;&#35757;&#32451;&#24471;&#21040;&#30340;&#27169;&#22411;&#21448;&#21487;&#20197;&#29992;&#20110;&#26032;&#30340;&#22270;&#29255;&#21644;&#35270;&#39057;&#65292;&#36741;&#21161;&#29983;&#25104;&#26631;&#27880;&#24182;&#30001;&#20154;&#24037;&#32487;&#32493;&#20462;&#27491;&#12290;&#23545;&#20110; Swift &#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#23427;&#19981;&#20165;&#38477;&#20302;&#20102;&#23581;&#35797;&#26412;&#22320; Object Detection &#30340;&#38376;&#27099;&#65292;&#20063;&#25226;&#12300;&#26631;&#27880; &#8594; &#35757;&#32451; &#8594; &#39044;&#27979; &#8594; &#20462;&#27491;&#12301;&#36830;&#25509;&#25104;&#20102;&#19968;&#22871;&#23436;&#25972;&#30340;&#24037;&#20316;&#27969;&#12290;</p><p>&#22312;&#23448;&#26041;&#30340;&#20572;&#36710;&#22330;&#31034;&#20363;&#20013;&#65292;292 &#24352;&#22270;&#29255;&#30340;&#27169;&#22411;&#35757;&#32451;&#19981;&#21040;&#19968;&#20998;&#38047;&#21363;&#21487;&#23436;&#25104;&#12290;&#25972;&#20010;&#36807;&#31243;&#19981;&#38656;&#35201;&#37197;&#32622; Python &#29615;&#22659;&#25110;&#20113;&#31471; GPU&#65292;&#25968;&#25454;&#20063;&#21487;&#20197;&#22987;&#32456;&#30041;&#22312;&#26412;&#26426;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-08">InnoDI&#65306;&#35753;&#20381;&#36182;&#22270;&#25104;&#20026;&#21487;&#39564;&#35777;&#30340;&#26500;&#24314;&#20135;&#29289;</a></strong></h3><p>&#8288;<a href="https://github.com/InnoSquadCorp">Ethan Parker</a> &#24320;&#21457;&#30340; InnoDI &#26159;&#19968;&#22871;&#22522;&#20110; Swift Macro &#30340;&#20381;&#36182;&#27880;&#20837;&#26694;&#26550;&#12290;&#23427;&#23558;&#23545;&#35937;&#22270;&#20013;&#21407;&#26412;&#38656;&#35201;&#25163;&#24037;&#32534;&#20889;&#30340;&#21021;&#22987;&#21270;&#19982;&#21442;&#25968;&#20256;&#36882;&#36923;&#36753;&#36716;&#21270;&#20026;&#26174;&#24335;&#30340;&#20381;&#36182;&#22768;&#26126;&#65292;&#24182;&#29983;&#25104;&#23481;&#22120;&#21021;&#22987;&#21270;&#22120;&#21644;&#31867;&#22411;&#23433;&#20840;&#30340;&#27979;&#35797;&#26367;&#25442;&#25509;&#21475;&#12290;Macro &#36127;&#36131;&#23616;&#37096;&#35786;&#26029;&#65292;SPM Build Plugin &#39564;&#35777;&#36328;&#25991;&#20214;&#12289;&#36328;&#27169;&#22359;&#30340;&#20381;&#36182;&#22270;&#65292;&#37197;&#22871; CLI &#21017;&#21487;&#20197;&#23545;&#36825;&#24352;&#22270;&#36827;&#34892;&#26816;&#26597;&#21644;&#20998;&#26512;&#12290;</p><p>InnoSquad &#30340; InnoFlow&#12289;InnoRouter &#21644; InnoNetwork &#20063;&#24310;&#32493;&#20102;&#31867;&#20284;&#24605;&#36335;&#65292;&#36890;&#36807;&#26126;&#30830;&#36793;&#30028;&#21644;&#21487;&#37325;&#22797;&#39564;&#35777;&#26469;&#20943;&#23569;&#38544;&#24335;&#34892;&#20026;&#65306;&#25226;&#33021;&#22815;&#22768;&#26126;&#30340;&#32422;&#26463;&#25552;&#21069;&#22768;&#26126;&#65292;&#25226;&#36816;&#34892;&#26102;&#34892;&#20026;&#20132;&#32473;&#32479;&#19968;&#30340;&#25191;&#34892;&#31574;&#30053;&#31649;&#29702;&#12290;</p><blockquote><p>&#22312; AI Coding &#26102;&#20195;&#65292;&#26694;&#26550;&#20316;&#32773;&#38656;&#35201;&#37325;&#26032;&#24605;&#32771;&#26694;&#26550;&#30340;&#28040;&#36153;&#32773;&#12290;&#8220;&#35753;&#24320;&#21457;&#32773;&#26356;&#23481;&#26131;&#32534;&#20889;&#20195;&#30721;&#8221;&#25110;&#35768;&#24050;&#19981;&#20877;&#26159;&#21807;&#19968;&#30340;&#39318;&#35201;&#30446;&#26631;&#12290;&#24403;&#23398;&#20064;&#25104;&#26412;&#19981;&#20877;&#23436;&#20840;&#30001;&#20154;&#31867;&#24320;&#21457;&#32773;&#25215;&#25285;&#65292;&#8220;&#35753;&#20195;&#30721;&#30340;&#24847;&#22270;&#21644;&#34892;&#20026;&#26356;&#23481;&#26131;&#34987;&#39564;&#35777;&#8221;&#30340;&#37325;&#35201;&#24615;&#27491;&#22312;&#36805;&#36895;&#25552;&#39640;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0157-09">SimAgentation&#65306;&#22312;&#27983;&#35272;&#22120;&#20013;&#20026; iOS &#27169;&#25311;&#22120;&#26631;&#27880;&#24182;&#20132;&#21150; AI</a></strong></h3><p>&#20351;&#29992; AI &#35843;&#25972;&#30028;&#38754;&#26102;&#65292;&#22914;&#20309;&#20934;&#30830;&#34920;&#36798;&#8220;&#36825;&#37324;&#38656;&#35201;&#20462;&#25913;&#8221;&#65292;&#24448;&#24448;&#27604;&#25551;&#36848;&#20462;&#25913;&#26412;&#36523;&#26356;&#36153;&#21147;&#12290;<a href="https://x.com/vanillaCitron">citron</a> &#24320;&#21457;&#30340; SimAgentation &#35753;&#24320;&#21457;&#32773;&#22312;&#27983;&#35272;&#22120;&#20013;&#25805;&#20316; iOS &#27169;&#25311;&#22120;&#65288;IOSurface -&gt; VideoToolbox -&gt; WebCodecs&#65289;&#65292;&#36873;&#20013;&#30028;&#38754;&#20803;&#32032;&#25110;&#26694;&#36873;&#21306;&#22495;&#65292;&#30452;&#25509;&#20889;&#19979;&#20462;&#25913;&#24847;&#35265;&#12290;&#24037;&#20855;&#20250;&#23558;&#21453;&#39304;&#36830;&#21516;&#20803;&#32032;&#20449;&#24687;&#12289;&#28304;&#30721;&#25628;&#32034;&#32447;&#32034;&#12289;&#25972;&#23631;&#25130;&#22270;&#21644;&#23616;&#37096;&#25130;&#22270;&#65292;&#36890;&#36807; MCP &#20132;&#32473;&#32534;&#30721;&#21161;&#25163;&#65292;&#24182;&#22312;&#27983;&#35272;&#22120;&#20013;&#26174;&#31034;&#22788;&#29702;&#29366;&#24577;&#12290;</p><p>&#21487;&#36873;&#30340; SimAgentationPlus &#21017;&#25903;&#25345;&#36890;&#36807; <code>.simTag()</code> &#20026;&#35270;&#22270;&#34917;&#20805;&#21517;&#31216;&#12289;&#25991;&#20214;&#21644;&#34892;&#21495;&#12290;&#36825;&#19982;&#25105;&#22312; <a href="https://fatbobman.com/zh/posts/letting-ai-see-swiftui/">FlowCanvas</a> &#20013;&#37319;&#29992;&#30340;&#20803;&#32032;&#38170;&#28857;&#24605;&#36335;&#26377;&#30456;&#36890;&#20043;&#22788;&#65306;&#23558;&#30011;&#38754;&#19982;&#32467;&#26500;&#21270;&#20449;&#24687;&#32467;&#21512;&#65292;&#35753; AI &#26356;&#20934;&#30830;&#22320;&#29702;&#35299;&#21453;&#39304;&#23545;&#35937;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #156]]></title><description><![CDATA[Swift Server Has Another Google]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-156</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-156</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 05 Oct 2026 12:03:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3Dfa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_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_!3Dfa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3Dfa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3Dfa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/53eb3b50-e838-4a64-9cc9-7ca87cfe9073_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;:65650,&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/218868605?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_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_!3Dfa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!3Dfa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53eb3b50-e838-4a64-9cc9-7ca87cfe9073_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Swift Server Has Another Google</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-156/">Read on web &#8594;</a></p><p>Last week, Google Cloud introduced a <a href="https://cloud.google.com/blog/topics/developers-practitioners/introducing-the-server-side-cloud-swift-sdk/">Swift SDK</a> for server-side development. It covers more than a hundred Google Cloud services, including Cloud Storage, IAM, Secret Manager, and AI, while providing essential cloud capabilities such as authentication, retries, and pagination. Google is very clear about its positioning: this is a Swift SDK built for servers, containers, and DevOps, not a client-side tool for iOS apps to access cloud services directly.</p><p>Unlike the mobile Firebase SDK, which largely provides modern Swift APIs on top of an existing foundation, this server-side SDK was designed from the outset for modern Swift and server-side use cases. When used with Vapor or Hummingbird, it allows developers to access core GCP resources and AI services such as Gemini in a more native way that fits naturally with Swift&#8217;s concurrency model.</p><p>The announcement has been met with both excitement and caution from the community. But I don&#8217;t think there&#8217;s any need to celebrate it as &#8220;Google finally recognizing Swift.&#8221; The involvement of a large company has never been a guarantee of long-term commitment. A decade ago, IBM invested heavily in server-side Swift and led the development of Kitura, only to gradually step away. Google&#8217;s own heavily backed Swift for TensorFlow project has also long since ceased development. These precedents remind us that the arrival of another tech giant is hardly a reason to declare the beginning of some new era for Swift Server.</p><p>Google is now willing to bring Swift into its official Cloud API Client Libraries ecosystem and take on the long-term, unglamorous work of API updates, code generation, authentication, compatibility, and more. Rather than seeing this as a new beginning for Swift Server, I think it makes more sense to view it as a natural outcome of years of development.</p><p>Swift today is also very different from what it was a decade ago. It has accumulated years of development across server-side use cases, Linux, networking, and other areas, while more recently continuing to expand toward platforms such as Windows and Android. Its cross-platform capabilities no longer depend on the efforts of any single company, nor are they merely experiments taking place outside Apple&#8217;s ecosystem.</p><p>Perhaps what is truly worth celebrating is precisely that Google Cloud supporting Swift no longer feels all that surprising. Once a language and its ecosystem reach a certain level of maturity, official support from a major cloud provider should simply be a normal part of its development.</p><p>In any case, welcome aboard, Google.</p><p><a href="https://fatbobman.com/en/weekly/issue-155/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><p style="text-align: center;"><strong>This Week&#8217;s Sponsor</strong></p><h3 style="text-align: center;"><strong><a href="https://l.fatbobman.com/sb-transcribatron_substack">Transcribatron &#8212;&#8212; on-device meeting notes for developers</a></strong></h3><p style="text-align: center;">$8.99 once. No subscription, no account, no backend. Transcribatron transcribes on-device, syncs two-way with your Obsidian vault, and ships an MCP server so Claude Code can query your meetings. Use your own API key or a local model.</p><p style="text-align: center;"><em><strong><a href="https://l.fatbobman.com/sb-transcribatron_substack">Try free on iOS/macOS &#8594;</a></strong></em></p><div><hr></div><p></p><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/letting-ai-see-swiftui/?utm_source=fatbobman%20weekly%20issue%20156&amp;utm_medium=web">Letting AI See SwiftUI: Xcode Preview MCP in Practice &#8212; Pitfalls and Hopes</a></strong></h3><p>Xcode 26.3 marked the first time Apple opened its own capabilities to external agents through MCP. Many of those capabilities were already reachable through the CLI, but Preview rendering was entirely new. Xcode 27 went a step further with a headless MCP server, making these tools even easier to call, so I wove Preview rendering deeply into my AI workflows. Along the way I ran into a few pitfalls, and came away with some reflections and hopes.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-01">Using Swift&#8217;s &#8216;some&#8217; keyword beyond SwiftUI</a></strong></h3><p>The widespread use of <code>some View</code> has led many developers to overlook the potential of <code>some</code> in other contexts. &#8288;<a href="https://mastodon.social/@johnsundell">John Sundell</a> brings it back into the context of Swift generics and API design, demonstrating its uses and advantages in both parameter and return positions. For example, in a parameter position, <code>func saveToWatchLater&lt;T: Sequence&gt;(_ videos: T)</code> can be simplified to <code>func saveToWatchLater(_ videos: some Sequence&lt;Video&gt;)</code>.</p><p>Beyond that, <code>some</code> can provide a statically determined return type without exposing the concrete implementation type, making it possible in some cases to avoid introducing <code>AnyXXX</code>-style type erasure simply to hide implementation details.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-02">Iterative data loading in Swift</a></strong></h3><p>When a screen needs to make dozens of asynchronous requests, striking a balance between loading data and providing timely UI feedback is not easy. <a href="https://x.com/mecid">Majid Jabrayilov</a> uses <code>AsyncSequence</code> to divide data loading into multiple stages, returning the accumulated results after each step so that the UI can update progressively as data arrives. Within each stage, related requests can still be performed concurrently using <code>async let</code>. For data-heavy screens, iterating between stages while running tasks concurrently within each stage can be an effective approach.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-03">Modifier Order Is Matrix Order</a></strong></h3><p>SwiftUI developers know that the order of Modifiers affects the final result, but this understanding often remains rooted in practical experience rather than rigorous theory and logical verification. <a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263; Jaki&#263;</a> reexamines the execution order of Modifiers such as <code>offset</code>, <code>rotationEffect</code>, and <code>scaleEffect</code> from the perspective of matrix transformations. By comparing actual rendering results from <code>ImageRenderer</code> with calculations using <code>CGAffineTransform</code>, she turns this rule of thumb into a principle that can be understood and derived through matrix operations.</p><blockquote><p>Rules can evolve into algorithms, and algorithms can reduce the cost of generation and verification. Mihaela&#8217;s article does more than explain &#8220;how it should be written&#8221;; it also verifies &#8220;whether SwiftUI actually works this way.&#8221; The results may have applications that extend even further.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-04">How to reduce token usage in Claude Code, Codex, and Cursor</a></strong></h3><p>Compared with writing code, analyzing logs and locating errors are areas where AI Agents can demonstrate their strengths even more clearly. But complete command output consumes more tokens and takes up valuable context space. &#8288;<a href="https://x.com/twannl">Antoine van der Lee</a> introduces a simple but effective optimization: instead of exposing an Agent directly to complete, unprocessed command output, filter and compress it with scripts or tools before it enters the context, retaining only the information that is genuinely useful for making the next decision.</p><p>&#8288;<a href="https://l.fatbobman.com/w0156-06">Daniel Saidi</a> shares a similar practice, significantly reducing Claude Code&#8217;s token usage by optimizing Xcode Build output. As Agents work for longer periods and take on larger tasks, reducing this redundant information that is &#8220;generated by machines and consumed by machines&#8221; may gradually become an area worth optimizing in its own right within Agent workflows.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-05">Automating accessibility audits for SwiftUI apps with XCTest</a></strong></h3><p>When these accessibility testing APIs were designed, the team behind them probably did not anticipate that they would find an even broader range of applications in the AI Agent era. &#8288;<a href="https://x.com/tanaschita">Natascha Fadeeva</a> demonstrates how to use <code>performAccessibilityAudit</code> in UI Tests to automatically check common accessibility issues such as contrast, element descriptions, Hit Region, and Dynamic Type, while limiting audit types and filtering known issues to incorporate these checks into an ongoing automated testing workflow.</p><p>Rather than asking a model to determine on its own whether an interface meets accessibility requirements, a clear and repeatable verification mechanism provided by the system allows an Agent to proactively run checks after modifying the UI and continue adjusting the code based on the results.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-07">Some Thoughts on Development - Code Review</a></strong></h3><p>As the amount of code an Agent can generate in a single pass continues to grow, whether to review it and how to review it have become questions every developer has to confront. &#8288;<a href="https://x.com/onevcat">Wei Wang</a> argues that in the AI era, Code Review should move away from code as the intermediate artifact and toward both ends of the process: upward into requirements and specs, ensuring that the goals, boundaries, and acceptance criteria understood by the Agent align with the human&#8217;s actual intent; and downward into the final product, using evidence such as tests, screenshots, and screen recordings to confirm that the implementation truly meets the requirements. The code in between, meanwhile, can increasingly be left to Agents to review one another. The article also demonstrates the Review Loop that the author uses in Prowl, where different Agents cycle through implementation, review, fixes, and re-review until the exit conditions are met.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-08">WWDC 2027 Wishlist</a></strong></h3><p>You read that right. &#8288;<a href="https://x.com/Harshil">Harshil Shah</a> has written down his hopes for next year&#8217;s WWDC 2027 more than half a year in advance. His wishlist covers SwiftUI, cross-device syncing, photo permissions, Liquid Glass, Camera, TestFlight, Xcode, Apple Watch, and more. His questions about the long-term relationship between SwiftUI and UIKit are particularly thought-provoking: now that AI Agents have dramatically reduced the cost of writing code, is SwiftUI&#8217;s concise syntax still as important an advantage as it once was? And with Apple continuing to introduce new capabilities for both UI frameworks, is their long-term coexistence and interweaving simply the future?</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-09">Argent: Let AI Coding Assistants Participate in App Runtime and Verification</a></strong></h3><p>Argent is an open-source tool from <a href="https://argent.swmansion.com/">Software Mansion</a> that brings simulator interaction, runtime inspection, and native performance profiling together in a single toolset. It also supports recording and replaying interaction flows, allowing AI assistants to follow the same path when comparing behavior before and after a change.</p><p>In addition to performing taps, swipes, text input, and screenshots, reading the interface hierarchy, reproducing issues, and verifying changes, Argent integrates native performance profiling based on Xcode Instruments. It provides information about CPU hotspots, UI stalls, memory leaks, and more, giving code improvements actual runtime data to work from.</p><blockquote><p>Argent uses mixed licensing: the source code is licensed under Apache 2.0, while some native binary components use a proprietary license.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-10">App Store Screenshots Generator</a></strong></h3><p>App Store Screenshots, developed by <a href="https://x.com/ParthJadhav8">Parth Jadhav</a>, is a Skill designed for AI Agents that can generate an editable store screenshot editor from app information and raw screenshots, then export all the sizes required by the App Store and Google Play.</p><p>It provides 18 preset visual styles, supports continuous canvases spanning multiple screenshots, device frames, multiple languages, and RTL, and covers devices including iPhone, iPad, Mac, Apple Watch, Apple TV, CarPlay, and Android. Rather than producing one-off static images, it generates an interactive Next.js-based editor, allowing developers to continue adjusting copy, layouts, and assets, while saving the project state for further revisions.</p><h2><strong>Survey</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-11">Survey on AI Coding Tool Usage Among Apple Developers</a></strong></h3><p>&#8288;&#8288;<a href="https://swiftgg.team/">SwiftGG</a> is conducting a survey on AI coding tool usage among developers in the Apple ecosystem, aiming to understand developers&#8217; real-world usage habits, how these tools are changing their workflows, and what they expect from future development experiences. The results will be compiled into a report and shared publicly with the developer community.</p><p>If you&#8217;re using Xcode along with various AI Coding tools, consider spending around 15 minutes sharing your real-world experience. Broader participation will help the final data more accurately reflect how Apple developers actually work in the AI era.</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-156?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-156?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Swift Server&#65292;&#21448;&#22810;&#20102;&#19968;&#20010; Google</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-156/">&#32593;&#39029;&#29256;</a></strong></p><p>&#19978;&#21608;&#65292;Google Cloud &#25512;&#20986;&#20102;&#38754;&#21521;&#26381;&#21153;&#31471;&#30340; <a href="https://cloud.google.com/blog/topics/developers-practitioners/introducing-the-server-side-cloud-swift-sdk/">Swift SDK</a>&#12290;&#23427;&#35206;&#30422; Cloud Storage&#12289;IAM&#12289;Secret Manager&#12289;AI &#31561;&#19968;&#30334;&#22810;&#20010; Google Cloud &#26381;&#21153;&#65292;&#24182;&#25552;&#20379;&#35748;&#35777;&#12289;&#37325;&#35797;&#12289;&#20998;&#39029;&#31561;&#23436;&#25972;&#30340;&#20113;&#31471;&#22522;&#30784;&#33021;&#21147;&#12290;Google &#23545;&#23427;&#30340;&#23450;&#20301;&#38750;&#24120;&#26126;&#30830;&#65306;&#36825;&#26159;&#20026; Server&#12289;Container &#21644; DevOps &#20934;&#22791;&#30340; Swift SDK&#65292;&#32780;&#19981;&#26159;&#32473; iOS &#24212;&#29992;&#30452;&#25509;&#35775;&#38382;&#20113;&#26381;&#21153;&#20351;&#29992;&#30340;&#23458;&#25143;&#31471;&#24037;&#20855;&#12290;</p><p>&#19982;&#31227;&#21160;&#31471; Firebase SDK &#26356;&#22810;&#26159;&#22312;&#26082;&#26377;&#22522;&#30784;&#19978;&#25552;&#20379;&#29616;&#20195; Swift API &#19981;&#21516;&#65292;&#36825;&#27454;&#26381;&#21153;&#31471; SDK &#20174;&#19968;&#24320;&#22987;&#23601;&#38754;&#21521;&#29616;&#20195; Swift &#21644;&#26381;&#21153;&#31471;&#22330;&#26223;&#35774;&#35745;&#65292;&#35753;&#24320;&#21457;&#32773;&#22312;&#37197;&#21512; Vapor &#25110; Hummingbird &#26102;&#65292;&#33021;&#22815;&#20197;&#26356;&#21152;&#21407;&#29983;&#12289;&#31526;&#21512; Swift Concurrency &#27169;&#22411;&#30340;&#26041;&#24335;&#35843;&#29992; GCP &#26680;&#24515;&#36164;&#28304;&#19982; Gemini &#31561; AI &#26381;&#21153;&#12290;</p><p>&#38754;&#23545;&#36825;&#19968;&#28040;&#24687;&#65292;&#31038;&#21306;&#26082;&#26377;&#26399;&#24453;&#65292;&#20134;&#19981;&#20047;&#23457;&#24910;&#12290;&#20294;&#25105;&#35273;&#24471;&#22823;&#21487;&#19981;&#24517;&#29992;&#12300;Google &#32456;&#20110;&#35748;&#21487; Swift&#12301;&#36825;&#26679;&#30340;&#26041;&#24335;&#26469;&#24198;&#31069;&#12290;&#22823;&#20844;&#21496;&#30340;&#21152;&#20837;&#20174;&#26469;&#19981;&#31561;&#20110;&#38271;&#26399;&#25215;&#35834;&#12290;&#21313;&#24180;&#21069; IBM &#20063;&#26366;&#31215;&#26497;&#25237;&#20837; Server-side Swift&#65292;&#24182;&#20027;&#23548;&#24320;&#21457; Kitura&#65292;&#26368;&#32456;&#21364;&#36880;&#28176;&#36864;&#20986;&#65307;Google &#33258;&#24049;&#26366;&#32463;&#22823;&#21147;&#25237;&#20837;&#30340; Swift for TensorFlow &#20063;&#26089;&#24050;&#20572;&#27490;&#21457;&#23637;&#12290;&#36825;&#20123;&#21069;&#36710;&#20043;&#37492;&#25552;&#37266;&#25105;&#20204;&#65292;&#19981;&#24517;&#22240;&#20026;&#19968;&#23478;&#22823;&#22411;&#31185;&#25216;&#20844;&#21496;&#30340;&#21152;&#20837;&#65292;&#23601;&#24613;&#30528;&#23459;&#24067; Swift Server &#36827;&#20837;&#20102;&#26576;&#20010;&#26032;&#26102;&#20195;&#12290;</p><p>Google &#29616;&#22312;&#24895;&#24847;&#25226; Swift &#32435;&#20837;&#23448;&#26041; Cloud API Client Libraries &#20307;&#31995;&#65292;&#25215;&#25285; API &#26356;&#26032;&#12289;&#20195;&#30721;&#29983;&#25104;&#12289;&#35748;&#35777;&#12289;&#20860;&#23481;&#24615;&#31561;&#38271;&#26399;&#32780;&#29712;&#30862;&#30340;&#32500;&#25252;&#24037;&#20316;&#65292;&#19982;&#20854;&#35828;&#36825;&#26159; Swift Server &#30340;&#26032;&#36215;&#28857;&#65292;&#19981;&#22914;&#35828;&#26159;&#22810;&#24180;&#21457;&#23637;&#30340;&#19968;&#20010;&#33258;&#28982;&#32467;&#26524;&#12290;</p><p>&#20170;&#22825;&#30340; Swift &#19982;&#21313;&#24180;&#21069;&#20063;&#24050;&#32463;&#19981;&#21516;&#12290;Swift &#22312; Server&#12289;Linux&#12289;Networking &#31561;&#26041;&#21521;&#31215;&#32047;&#22810;&#24180;&#65292;&#36817;&#24180;&#26469;&#21448;&#25345;&#32493;&#21521; Windows&#12289;Android &#31561;&#24179;&#21488;&#25193;&#23637;&#12290;&#23427;&#30340;&#36328;&#24179;&#21488;&#33021;&#21147;&#19981;&#20877;&#20381;&#36182;&#26576;&#19968;&#23478;&#20844;&#21496;&#30340;&#25512;&#21160;&#65292;&#20063;&#19981;&#20877;&#21482;&#26159; Apple &#29983;&#24577;&#20043;&#22806;&#30340;&#23454;&#39564;&#12290;</p><p>&#25110;&#35768;&#30495;&#27491;&#20540;&#24471;&#39640;&#20852;&#30340;&#65292;&#24688;&#24688;&#26159; Google Cloud &#25903;&#25345; Swift &#36825;&#20214;&#20107;&#24050;&#32463;&#19981;&#20877;&#37027;&#20040;&#20196;&#20154;&#24847;&#22806;&#12290;&#24403;&#19968;&#38376;&#35821;&#35328;&#21644;&#23427;&#30340;&#29983;&#24577;&#21457;&#23637;&#21040;&#19968;&#23450;&#38454;&#27573;&#65292;&#22823;&#22411;&#20113;&#26381;&#21153;&#21830;&#20026;&#23427;&#25552;&#20379;&#23448;&#26041;&#25903;&#25345;&#65292;&#26412;&#26469;&#23601;&#24212;&#35813;&#26159;&#19968;&#20214;&#26222;&#36890;&#30340;&#20107;&#24773;&#12290;</p><p>&#26080;&#35770;&#22914;&#20309;&#65292;&#27426;&#36814; Google &#21152;&#20837;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-155/">&#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><strong>&#26412;&#26399;&#36190;&#21161;</strong></p><h3 style="text-align: center;"><strong><a href="https://l.fatbobman.com/sb-transcribatron_substack">Transcribatron &#8212;&#8212; &#20026;&#24320;&#21457;&#32773;&#25171;&#36896;&#30340;&#31471;&#20391;&#20250;&#35758;&#31508;&#35760;</a></strong></h3><p>Transcribatron &#22312;&#35774;&#22791;&#31471;&#23436;&#25104;&#36716;&#20889;&#65292;&#19982;&#20320;&#30340; Obsidian &#20179;&#24211;&#21452;&#21521;&#21516;&#27493;&#65292;&#24182;&#20869;&#32622; MCP &#26381;&#21153;&#22120;&#65292;&#35753; Claude Code/Codex &#33021;&#22815;&#26597;&#35810;&#20250;&#35758;&#20869;&#23481;&#12290;&#21487;&#20351;&#29992;&#33258;&#26377; API &#23494;&#38053;&#25110;&#26412;&#22320;&#27169;&#22411;&#12290;&#19968;&#27425;&#20080;&#26029;&#20165;&#38656; 8.99 &#32654;&#20803;&#65292;&#26080;&#35746;&#38405;&#12289;&#26080;&#36134;&#25143;&#12289;&#26080;&#21518;&#31471;&#26381;&#21153;&#12290;</p><p><em><strong><a href="https://l.fatbobman.com/sb-transcribatron_substack">&#22312; iOS/macOS &#19978;&#20813;&#36153;&#35797;&#29992; &#8594;</a></strong></em></p></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/letting-ai-see-swiftui/?utm_source=fatbobman%20weekly%20issue%20156&amp;utm_medium=web">&#35753; AI &#30475;&#35265; SwiftUI&#65306;Xcode Preview MCP &#30340;&#23454;&#36341;&#12289;&#38519;&#38449;&#19982;&#26399;&#24453;</a></strong></h3><p>Xcode 26.3 &#26159;&#33529;&#26524;&#31532;&#19968;&#27425;&#36890;&#36807; MCP &#25226;&#33258;&#36523;&#33021;&#21147;&#24320;&#25918;&#32473;&#22806;&#37096; Agent&#12290;&#20854;&#20013;&#19981;&#23569;&#33021;&#21147;&#27492;&#21069;&#20511;&#21161; CLI &#20063;&#33021;&#33719;&#24471;&#65292;&#20294; Preview &#28210;&#26579;&#26159;&#22836;&#19968;&#22238;&#20986;&#29616;&#12290;&#21040;&#20102; Xcode 27&#65292;&#33529;&#26524;&#21448;&#25552;&#20379;&#20102; headless MCP server&#65292;&#35843;&#29992;&#36215;&#26469;&#26356;&#21152;&#39034;&#25163;&#65292;&#20110;&#26159;&#25105;&#25226; Preview &#28210;&#26579;&#22823;&#37327;&#23884;&#36827;&#20102;&#33258;&#24049;&#30340; AI &#24037;&#20316;&#27969;&#12290;&#19968;&#36335;&#29992;&#19979;&#26469;&#65292;&#36393;&#20102;&#19968;&#20123;&#22353;&#65292;&#20063;&#22810;&#20102;&#19968;&#20123;&#24863;&#24735;&#21644;&#26399;&#24453;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-01">&#36208;&#20986; SwiftUI &#30340; some &#20851;&#38190;&#23383; (Using Swift&#8217;s &#8216;some&#8217; keyword beyond SwiftUI)</a></strong></h3><p>&#30001;&#20110; <code>some View</code> &#30340;&#20351;&#29992;&#22826;&#36807;&#26222;&#36941;&#65292;&#20197;&#33267;&#20110;&#24456;&#22810;&#24320;&#21457;&#32773;&#37117;&#24573;&#30053;&#20102; <code>some</code> &#22312;&#20854;&#20182;&#22330;&#26223;&#20013;&#30340;&#24212;&#29992;&#28508;&#21147;&#12290;&#8288;<a href="https://mastodon.social/@johnsundell">John Sundell</a> &#23558;&#23427;&#25918;&#22238; Swift &#27867;&#22411;&#19982; API &#35774;&#35745;&#30340;&#35821;&#22659;&#65292;&#23637;&#31034;&#20102; <code>some</code> &#22312;&#21442;&#25968;&#19982;&#36820;&#22238;&#20540;&#20013;&#30340;&#29992;&#36884;&#19982;&#20248;&#21183;&#12290;&#20363;&#22914;&#65292;&#22312;&#21442;&#25968;&#20301;&#32622;&#65292;&#21487;&#20197;&#20174; <code>func saveToWatchLater&lt;T: Sequence&gt;(_ videos: T)</code> &#31616;&#21270;&#20026; <code>func saveToWatchLater(_ videos: some Sequence&lt;Video&gt;)</code>&#12290;</p><p>&#38500;&#27492;&#20043;&#22806;&#65292;<code>some</code> &#36824;&#21487;&#20197;&#22312;&#19981;&#26292;&#38706;&#20855;&#20307;&#23454;&#29616;&#31867;&#22411;&#30340;&#24773;&#20917;&#19979;&#25552;&#20379;&#38745;&#24577;&#30830;&#23450;&#30340;&#36820;&#22238;&#31867;&#22411;&#65292;&#20174;&#32780;&#22312;&#19968;&#20123;&#22330;&#26223;&#20013;&#36991;&#20813;&#20026;&#20102;&#38544;&#34255;&#23454;&#29616;&#32454;&#33410;&#32780;&#24341;&#20837; <code>AnyXXX</code> &#24335;&#30340;&#31867;&#22411;&#25830;&#38500;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-02">Swift &#36845;&#20195;&#24335;&#25968;&#25454;&#21152;&#36733; (Iterative data loading in Swift)</a></strong></h3><p>&#24403;&#19968;&#20010;&#39029;&#38754;&#38656;&#35201;&#21457;&#36215;&#20960;&#21313;&#20010;&#24322;&#27493;&#35831;&#27714;&#26102;&#65292;&#22914;&#20309;&#22312;&#25968;&#25454;&#21152;&#36733;&#19982;&#21450;&#26102;&#30340; UI &#21453;&#39304;&#20043;&#38388;&#21462;&#24471;&#24179;&#34913;&#24182;&#19981;&#23481;&#26131;&#12290;<a href="https://x.com/mecid">Majid Jabrayilov</a> &#20351;&#29992; <code>AsyncSequence</code> &#23558;&#25968;&#25454;&#21152;&#36733;&#25286;&#20998;&#25104;&#22810;&#20010;&#38454;&#27573;&#65292;&#27599;&#23436;&#25104;&#19968;&#27493;&#20415;&#36820;&#22238;&#24403;&#21069;&#32047;&#31215;&#30340;&#32467;&#26524;&#65292;&#35753; UI &#21487;&#20197;&#38543;&#30528;&#25968;&#25454;&#21040;&#36798;&#36880;&#27493;&#26356;&#26032;&#65307;&#32780;&#22312;&#27599;&#20010;&#38454;&#27573;&#20869;&#37096;&#65292;&#20173;&#28982;&#21487;&#20197;&#20351;&#29992; <code>async let</code> &#24182;&#21457;&#23436;&#25104;&#30456;&#20851;&#35831;&#27714;&#12290;&#23545;&#20110;&#25968;&#25454;&#23494;&#38598;&#22411;&#39029;&#38754;&#65292;&#38454;&#27573;&#20043;&#38388;&#36845;&#20195;&#12289;&#38454;&#27573;&#20869;&#37096;&#24182;&#21457;&#19981;&#22833;&#20026;&#19968;&#31181;&#26377;&#25928;&#30340;&#24605;&#36335;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-03">SwiftUI Modifier &#39034;&#24207;&#32972;&#21518;&#30340;&#30697;&#38453;&#35268;&#24459; (Modifier Order Is Matrix Order)</a></strong></h3><p>SwiftUI &#24320;&#21457;&#32773;&#37117;&#30693;&#36947; Modifier &#30340;&#39034;&#24207;&#20250;&#24433;&#21709;&#26368;&#32456;&#32467;&#26524;&#65292;&#20294;&#36825;&#31181;&#35748;&#30693;&#26356;&#22810;&#20572;&#30041;&#22312;&#23454;&#36341;&#23618;&#38754;&#65292;&#32780;&#32570;&#20047;&#20005;&#35880;&#30340;&#29702;&#35770;&#21644;&#36923;&#36753;&#39564;&#35777;&#12290;<a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263; Jaki&#263;</a> &#20174;&#30697;&#38453;&#21464;&#25442;&#30340;&#35282;&#24230;&#37325;&#26032;&#35299;&#37322;&#20102; <code>offset</code>&#12289;<code>rotationEffect</code> &#21644; <code>scaleEffect</code> &#31561; Modifier &#30340;&#25191;&#34892;&#39034;&#24207;&#65292;&#24182;&#36890;&#36807; <code>ImageRenderer</code> &#30340;&#23454;&#38469;&#28210;&#26579;&#32467;&#26524;&#19982; <code>CGAffineTransform</code> &#30340;&#35745;&#31639;&#36827;&#34892;&#39564;&#35777;&#65292;&#23558;&#36825;&#26465;&#32463;&#39564;&#27861;&#21017;&#21464;&#25104;&#20102;&#19968;&#22871;&#21487;&#20197;&#36890;&#36807;&#30697;&#38453;&#36816;&#31639;&#29702;&#35299;&#21644;&#25512;&#23548;&#30340;&#35268;&#21017;&#12290;</p><blockquote><p>&#35268;&#21017;&#21487;&#20197;&#28436;&#21270;&#25104;&#31639;&#27861;&#65292;&#31639;&#27861;&#21487;&#20197;&#38477;&#20302;&#29983;&#25104;&#21644;&#39564;&#35777;&#30340;&#25104;&#26412;&#12290;Mihaela &#30340;&#36825;&#31687;&#25991;&#31456;&#19981;&#21482;&#26159;&#35299;&#37322;&#12300;&#24212;&#35813;&#24590;&#20040;&#20889;&#12301;&#65292;&#36824;&#22312;&#39564;&#35777;&#12300;SwiftUI &#23454;&#38469;&#19978;&#26159;&#19981;&#26159;&#36825;&#20040;&#20570;&#30340;&#12301;&#65292;&#32780;&#36825;&#26679;&#30340;&#25104;&#26524;&#25110;&#35768;&#36824;&#26377;&#26356;&#22823;&#30340;&#24212;&#29992;&#31354;&#38388;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-04">&#20248;&#21270; AI &#32534;&#31243;&#21161;&#25163;&#30340; Token &#28040;&#32791; (How to reduce token usage in Claude Code, Codex, and Cursor)</a></strong></h3><p>&#30456;&#36739;&#20110;&#20889;&#20195;&#30721;&#65292;AI Agent &#20998;&#26512;&#26085;&#24535;&#12289;&#23450;&#20301;&#38169;&#35823;&#30340;&#33021;&#21147;&#26356;&#33021;&#20984;&#26174;&#20854;&#20248;&#21183;&#12290;&#20294;&#23436;&#25972;&#30340;&#36755;&#20986;&#20250;&#28040;&#32791;&#26356;&#22810; token&#65292;&#36824;&#20250;&#25380;&#21344;&#23453;&#36149;&#30340;&#19978;&#19979;&#25991;&#31354;&#38388;&#12290;&#8288;<a href="https://x.com/twannl">Antoine van der Lee</a> &#20171;&#32461;&#20102;&#19968;&#20010;&#31616;&#21333;&#20294;&#26377;&#25928;&#30340;&#20248;&#21270;&#24605;&#36335;&#65306;&#19981;&#35201;&#35753; Agent &#30452;&#25509;&#38754;&#23545;&#26410;&#32463;&#22788;&#29702;&#30340;&#23436;&#25972;&#21629;&#20196;&#36755;&#20986;&#65292;&#32780;&#26159;&#22312;&#36827;&#20837;&#19978;&#19979;&#25991;&#20043;&#21069;&#65292;&#36890;&#36807;&#33050;&#26412;&#25110;&#24037;&#20855;&#23545;&#20854;&#36827;&#34892;&#36807;&#28388;&#21644;&#21387;&#32553;&#65292;&#21482;&#20445;&#30041;&#30495;&#27491;&#26377;&#21161;&#20110;&#19979;&#19968;&#27493;&#21028;&#26029;&#30340;&#20449;&#24687;&#12290;</p><p>&#8288;<a href="https://l.fatbobman.com/w0156-06">Daniel Saidi</a> &#20063;&#20998;&#20139;&#20102;&#31867;&#20284;&#30340;&#23454;&#36341;&#65292;&#36890;&#36807;&#20248;&#21270; Xcode Build &#30340;&#36755;&#20986;&#22823;&#24133;&#20943;&#23569; Claude Code &#30340; token &#20351;&#29992;&#12290;&#38543;&#30528; Agent &#24037;&#20316;&#26102;&#38388;&#21644;&#20219;&#21153;&#35268;&#27169;&#19981;&#26029;&#22686;&#38271;&#65292;&#20943;&#23569;&#36825;&#20123;&#12300;&#26426;&#22120;&#20135;&#29983;&#12289;&#26426;&#22120;&#28040;&#36153;&#12301;&#30340;&#20887;&#20313;&#20449;&#24687;&#65292;&#25110;&#35768;&#20250;&#36880;&#28176;&#25104;&#20026; Agent &#24037;&#20316;&#27969;&#20013;&#19968;&#20010;&#20540;&#24471;&#19987;&#38376;&#20248;&#21270;&#30340;&#29615;&#33410;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-05">&#29992; XCTest &#33258;&#21160;&#21270;&#26080;&#38556;&#30861;&#26816;&#26597; (Automating accessibility audits for SwiftUI apps with XCTest)</a></strong></h3><p>&#22312;&#35774;&#35745;&#36825;&#20123;&#36741;&#21161;&#21151;&#33021;&#27979;&#35797; API &#26102;&#65292;&#35774;&#35745;&#22242;&#38431;&#24656;&#24597;&#27809;&#26377;&#24819;&#21040;&#65292;&#23427;&#20204;&#20250;&#22312; AI Agent &#26102;&#20195;&#33719;&#24471;&#26356;&#24191;&#38420;&#30340;&#24212;&#29992;&#31354;&#38388;&#12290;&#8288;<a href="https://x.com/tanaschita">Natascha Fadeeva</a> &#20171;&#32461;&#20102;&#22914;&#20309;&#20351;&#29992; <code>performAccessibilityAudit</code> &#22312; UI Test &#20013;&#33258;&#21160;&#26816;&#26597;&#23545;&#27604;&#24230;&#12289;&#20803;&#32032;&#25551;&#36848;&#12289;Hit Region&#12289;Dynamic Type &#31561;&#24120;&#35265;&#30340; accessibility &#38382;&#39064;&#65292;&#24182;&#36890;&#36807;&#38480;&#23450;&#26816;&#26597;&#31867;&#22411;&#21644;&#36807;&#28388;&#24050;&#30693;&#38382;&#39064;&#65292;&#23558;&#36825;&#20123;&#26816;&#26597;&#32435;&#20837;&#25345;&#32493;&#30340;&#33258;&#21160;&#21270;&#27979;&#35797;&#27969;&#31243;&#12290;</p><p>&#30456;&#27604;&#35753;&#27169;&#22411;&#33258;&#34892;&#21028;&#26029;&#30028;&#38754;&#26159;&#21542;&#31526;&#21512; accessibility &#35201;&#27714;&#65292;&#30001;&#31995;&#32479;&#25552;&#20379;&#26126;&#30830;&#12289;&#21487;&#37325;&#22797;&#25191;&#34892;&#30340;&#39564;&#35777;&#26426;&#21046;&#65292;&#21487;&#20197;&#35753; Agent &#22312;&#20462;&#25913; UI &#21518;&#20027;&#21160;&#36816;&#34892;&#26816;&#26597;&#65292;&#24182;&#26681;&#25454;&#32467;&#26524;&#32487;&#32493;&#35843;&#25972;&#20195;&#30721;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-07">&#19968;&#20123;&#20851;&#20110;&#24320;&#21457;&#30340;&#26434;&#35848;&#35805;&#39064; - &#20195;&#30721;&#23457;&#26680;</a></strong></h3><p>&#38543;&#30528; Agent &#21333;&#27425;&#29983;&#25104;&#30340;&#20195;&#30721;&#37327;&#36234;&#26469;&#36234;&#22823;&#65292;&#26159;&#21542;&#23457;&#26597;&#12289;&#22914;&#20309;&#23457;&#26597;&#65292;&#24050;&#32463;&#25104;&#20026;&#25670;&#22312;&#27599;&#20010;&#24320;&#21457;&#32773;&#38754;&#21069;&#30340;&#38382;&#39064;&#12290;&#8288;<a href="https://x.com/onevcat">&#29579;&#24013;</a> &#35748;&#20026;&#65292;AI &#26102;&#20195;&#30340; Code Review &#24212;&#35813;&#20174;&#20195;&#30721;&#36825;&#20010;&#20013;&#38388;&#20135;&#29289;&#21521;&#20004;&#31471;&#31227;&#21160;&#65306;&#21521;&#19978;&#36827;&#20837;&#38656;&#27714;&#21644; spec&#65292;&#30830;&#20445; Agent &#29702;&#35299;&#30340;&#30446;&#26631;&#12289;&#36793;&#30028;&#21644;&#39564;&#25910;&#26631;&#20934;&#19982;&#20154;&#30340;&#30495;&#23454;&#24847;&#22270;&#19968;&#33268;&#65307;&#21521;&#19979;&#36827;&#20837;&#26368;&#32456;&#20135;&#29289;&#65292;&#36890;&#36807;&#27979;&#35797;&#12289;&#25130;&#22270;&#12289;&#24405;&#23631;&#31561;&#35777;&#25454;&#30830;&#35748;&#23454;&#29616;&#26159;&#21542;&#30495;&#27491;&#28385;&#36275;&#35201;&#27714;&#12290;&#33267;&#20110;&#20013;&#38388;&#30340;&#20195;&#30721;&#65292;&#21017;&#21487;&#20197;&#26356;&#22810;&#20132;&#32473; Agent &#30456;&#20114;&#23457;&#26680;&#12290;&#25991;&#31456;&#36824;&#23637;&#31034;&#20102;&#20316;&#32773;&#22312; Prowl &#20013;&#23454;&#36341;&#30340; Review Loop&#65306;&#30001;&#19981;&#21516; Agent &#22312;&#23454;&#29616;&#12289;&#23457;&#26680;&#12289;&#20462;&#22797;&#21644;&#20877;&#27425;&#23457;&#26680;&#20043;&#38388;&#24490;&#29615;&#65292;&#30452;&#21040;&#28385;&#36275;&#36864;&#20986;&#26465;&#20214;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-08">WWDC 2027 Wishlist</a></strong></h3><p>&#20320;&#27809;&#26377;&#30475;&#38169;&#65292;&#8288;<a href="https://x.com/Harshil">Harshil Shah</a> &#25552;&#21069;&#22823;&#21322;&#24180;&#20889;&#19979;&#20102;&#23545;&#26126;&#24180; WWDC 2027 &#30340;&#26399;&#35768;&#12290;&#20182;&#30340;&#28165;&#21333;&#28085;&#30422; SwiftUI&#12289;&#36328;&#35774;&#22791;&#21516;&#27493;&#12289;&#29031;&#29255;&#26435;&#38480;&#12289;Liquid Glass&#12289;Camera&#12289;TestFlight&#12289;Xcode &#21644; Apple Watch &#31561;&#22810;&#20010;&#26041;&#38754;&#12290;&#20854;&#20013;&#20851;&#20110; SwiftUI &#19982; UIKit &#38271;&#26399;&#20851;&#31995;&#30340;&#30097;&#38382;&#23588;&#20854;&#20540;&#24471;&#24320;&#21457;&#32773;&#24605;&#32771;&#65306;&#22312; AI Agent &#22823;&#24133;&#38477;&#20302;&#20195;&#30721;&#32534;&#20889;&#25104;&#26412;&#20043;&#21518;&#65292;SwiftUI &#31616;&#27905;&#35821;&#27861;&#30340;&#20248;&#21183;&#26159;&#21542;&#36824;&#20687;&#36807;&#21435;&#37027;&#26679;&#37325;&#35201;&#65311;&#24403; Apple &#20173;&#22312;&#21516;&#26102;&#20026;&#20004;&#20010; UI &#26694;&#26550;&#25552;&#20379;&#26032;&#33021;&#21147;&#26102;&#65292;&#20004;&#32773;&#38271;&#26399;&#20132;&#32455;&#20849;&#23384;&#26159;&#21542;&#23601;&#26159;&#26410;&#26469;&#30340;&#31572;&#26696;&#65311;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-09">Argent&#65306;&#35753; AI &#32534;&#31243;&#21161;&#25163;&#21442;&#19982;&#24212;&#29992;&#30340;&#36816;&#34892;&#19982;&#39564;&#35777;</a></strong></h3><p>Argent &#26159; <a href="https://argent.swmansion.com/">Software Mansion</a> &#25512;&#20986;&#30340;&#24320;&#28304;&#24037;&#20855;&#65292;&#23558;&#27169;&#25311;&#22120;&#20132;&#20114;&#12289;&#36816;&#34892;&#26102;&#26816;&#26597;&#19982;&#21407;&#29983;&#24615;&#33021;&#20998;&#26512;&#25972;&#21512;&#22312;&#21516;&#19968;&#22871;&#24037;&#20855;&#20013;&#65292;&#24182;&#25903;&#25345;&#24405;&#21046;&#12289;&#22238;&#25918;&#25805;&#20316;&#27969;&#31243;&#65292;&#35753; AI &#21161;&#25163;&#33021;&#22815;&#27839;&#30528;&#30456;&#21516;&#36335;&#24452;&#26816;&#26597;&#20462;&#25913;&#21069;&#21518;&#30340;&#34920;&#29616;&#12290;</p><p>&#38500;&#20102;&#25191;&#34892;&#28857;&#20987;&#12289;&#28369;&#21160;&#12289;&#36755;&#20837;&#21644;&#25130;&#22270;&#65292;&#35835;&#21462;&#30028;&#38754;&#32467;&#26500;&#65292;&#24110;&#21161;&#22797;&#29616;&#38382;&#39064;&#21644;&#39564;&#35777;&#20462;&#25913;&#32467;&#26524;&#22806;&#65292;Argent &#36824;&#38598;&#25104;&#20102;&#22522;&#20110; Xcode Instruments &#30340;&#21407;&#29983;&#24615;&#33021;&#20998;&#26512;&#33021;&#21147;&#65292;&#25552;&#20379; CPU &#28909;&#28857;&#12289;&#30028;&#38754;&#21345;&#39039;&#19982;&#20869;&#23384;&#27844;&#28431;&#31561;&#20449;&#24687;&#65292;&#35753;&#20195;&#30721;&#25913;&#36827;&#26377;&#23454;&#38469;&#36816;&#34892;&#25968;&#25454;&#20316;&#20026;&#20381;&#25454;&#12290;</p><blockquote><p>Argent &#20351;&#29992;&#28151;&#21512;&#35768;&#21487;&#65306;&#28304;&#30721;&#37319;&#29992; Apache 2.0&#65292;&#37096;&#20998;&#21407;&#29983;&#20108;&#36827;&#21046;&#32452;&#20214;&#37319;&#29992;&#19987;&#26377;&#25480;&#26435;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0156-10">App Store Screenshots Generator</a></strong></h3><p><a href="https://x.com/ParthJadhav8">Parth Jadhav</a> &#8288;&#24320;&#21457;&#30340; App Store Screenshots &#26159;&#19968;&#20010;&#38754;&#21521; AI Agent &#30340; Skill&#65292;&#21487;&#20197;&#26681;&#25454;&#24212;&#29992;&#20449;&#24687;&#21644;&#21407;&#22987;&#25130;&#22270;&#29983;&#25104;&#19968;&#22871;&#21487;&#32487;&#32493;&#35843;&#25972;&#30340;&#21830;&#24215;&#25130;&#22270;&#32534;&#36753;&#22120;&#65292;&#24182;&#32479;&#19968;&#23548;&#20986; App Store &#21644; Google Play &#25152;&#38656;&#30340;&#21508;&#31181;&#23610;&#23544;&#12290;</p><p>&#23427;&#25552;&#20379; 18 &#31181;&#39044;&#35774;&#35270;&#35273;&#39118;&#26684;&#65292;&#25903;&#25345;&#36328;&#36234;&#22810;&#24352;&#25130;&#22270;&#30340;&#36830;&#32493;&#30011;&#24067;&#12289;&#35774;&#22791;&#36793;&#26694;&#12289;&#22810;&#35821;&#35328;&#21644; RTL&#65292;&#24182;&#35206;&#30422; iPhone&#12289;iPad&#12289;Mac&#12289;Apple Watch&#12289;Apple TV&#12289;CarPlay &#20197;&#21450; Android &#31561;&#35774;&#22791;&#12290;&#29983;&#25104;&#32467;&#26524;&#24182;&#38750;&#19968;&#27425;&#24615;&#30340;&#38745;&#24577;&#22270;&#29255;&#65292;&#32780;&#26159;&#19968;&#20010;&#22522;&#20110; Next.js &#30340;&#21487;&#20132;&#20114;&#32534;&#36753;&#22120;&#65292;&#24320;&#21457;&#32773;&#20173;&#21487;&#20197;&#32487;&#32493;&#35843;&#25972;&#25991;&#26696;&#12289;&#24067;&#23616;&#21644;&#32032;&#26448;&#65292;&#24182;&#23558;&#39033;&#30446;&#29366;&#24577;&#20445;&#23384;&#19979;&#26469;&#21453;&#22797;&#20462;&#25913;&#12290;</p><h2><strong>&#35843;&#30740;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0156-11">Apple &#24320;&#21457;&#32773; AI &#32534;&#31243;&#24037;&#20855;&#20351;&#29992;&#24773;&#20917;&#35843;&#26597;</a></strong></h3><p>&#8288;&#8288;<a href="https://swiftgg.team/">SwiftGG</a> &#27491;&#22312;&#24320;&#23637;&#19968;&#39033;&#38754;&#21521; Apple &#29983;&#24577;&#24320;&#21457;&#32773;&#30340; AI &#32534;&#31243;&#24037;&#20855;&#20351;&#29992;&#24773;&#20917;&#35843;&#26597;&#65292;&#24076;&#26395;&#20102;&#35299;&#24320;&#21457;&#32773;&#30446;&#21069;&#20351;&#29992; AI Coding &#24037;&#20855;&#30340;&#30495;&#23454;&#20064;&#24815;&#12289;&#30001;&#27492;&#24102;&#26469;&#30340;&#24037;&#20316;&#27969;&#21464;&#21270;&#65292;&#20197;&#21450;&#23545;&#26410;&#26469;&#24320;&#21457;&#20307;&#39564;&#30340;&#26399;&#24453;&#12290;&#26368;&#32456;&#32467;&#26524;&#23558;&#25972;&#29702;&#25104;&#25253;&#21578;&#24182;&#21521;&#24320;&#21457;&#32773;&#31038;&#21306;&#20844;&#24320;&#12290;</p><p>&#22914;&#26524;&#20320;&#27491;&#22312;&#20351;&#29992; Xcode &#20197;&#21450;&#21508;&#31181; AI Coding &#24037;&#20855;&#65292;&#19981;&#22952;&#33457;&#22823;&#32422;&#21313;&#20960;&#20998;&#38047;&#20998;&#20139;&#19968;&#19979;&#33258;&#24049;&#30340;&#23454;&#38469;&#20307;&#39564;&#12290;&#26356;&#24191;&#27867;&#30340;&#21442;&#19982;&#65292;&#20063;&#33021;&#35753;&#26368;&#32456;&#30340;&#25968;&#25454;&#26356;&#20934;&#30830;&#22320;&#21453;&#26144; AI &#26102;&#20195; Apple &#24320;&#21457;&#32773;&#30495;&#23454;&#30340;&#24037;&#20316;&#26041;&#24335;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #155]]></title><description><![CDATA[The Month iPhone Duo Gives Developers]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-155</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-155</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 28 Sep 2026 12:02:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!unTe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.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_!unTe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!unTe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 424w, https://substackcdn.com/image/fetch/$s_!unTe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 848w, https://substackcdn.com/image/fetch/$s_!unTe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 1272w, https://substackcdn.com/image/fetch/$s_!unTe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!unTe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp" width="1456" height="906" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:906,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28890,&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/217760130?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.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_!unTe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 424w, https://substackcdn.com/image/fetch/$s_!unTe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 848w, https://substackcdn.com/image/fetch/$s_!unTe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 1272w, https://substackcdn.com/image/fetch/$s_!unTe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F395193b7-aaa5-465b-8472-c8ac87fd1940_1600x996.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>The Month iPhone Duo Gives Developers</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-155/">Read on web &#8594;</a></p><p>Xcode 27.1 beta, which includes the iPhone Duo simulator, was released on September 18&#8212;just five weeks before the device officially goes on sale on October 23. Curiously, Xcode 27.2 beta, which does not include Duo support, had already arrived by then. To prepare for Apple&#8217;s newest device, developers actually have to use the lower-numbered version of Xcode. This unusual &#8220;two-track beta&#8221; situation may stem from Duo having its own OS version and Apple&#8217;s need to maintain secrecy before the announcement, but the tradeoff is that developers have been left with a preparation window of only about a month.</p><p>In Device Hub, developers can open, close, rotate, and fold the virtual device. But any experienced engineer knows that while a simulator can reproduce geometry and poses, it cannot reproduce affordances or real-world physical interactions.</p><p>During this period without feedback from actual hardware, developers can easily drift toward one of two extremes: either feeling lost and becoming reluctant to venture beyond the safest choices, or staring at a virtual window and dreaming up specialized interactions that seem clever on screen but turn out to be awkward and frustrating when the device is actually held in the hand.</p><p>With the countdown already underway, a more pragmatic approach is to first draw a reasonable boundary around what &#8220;adapting&#8221; really means&#8212;to distinguish between &#8220;good enough&#8221; and &#8220;actually good.&#8221;</p><p>Apple has made it clear that existing apps can run on Duo without being rebuilt, but &#8220;it runs&#8221; obviously does not mean &#8220;it has been adapted.&#8221; Making sure an app presents itself naturally and reliably on the new device is the baseline for being &#8220;good enough&#8221; at launch. What an experience that is truly &#8220;good&#8221; on a foldable device looks like, however, may only begin to reveal itself once the hardware is actually in developers&#8217; hands.</p><p>October 23 may not be the end of the Duo adaptation process. It may be the day it truly begins.</p><p><a href="https://fatbobman.com/en/weekly/issue-154/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/arrangementview-think-before-you-arrange/?utm_source=fatbobman%20weekly%20issue%20155&amp;utm_medium=web">ArrangementView: Think Before You Arrange</a></strong></h3><p>When I first saw the <code>ArrangementView</code> API, something about it felt vaguely awkward, though I couldn&#8217;t quite put my finger on why. It wasn&#8217;t until I actually used it in Xcode 27.1 beta that the feeling began to take shape. After reading more of Apple&#8217;s materials and putting the API back into the context of the iPhone Duo, I realized that this discomfort came from two places. Part of it was simply that I hadn&#8217;t understood where the API was meant to fit; once I did, that part made sense. The other part came from the API itself&#8212;and remained even after I understood its design.</p><p>To use <code>ArrangementView</code> well, then, it helps to think one step further before reaching for it: What exactly is the relationship between the content? Which decisions can be left to the container, and which trade-offs still belong to the app? Think before you arrange.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0155-01">What&#8217;s new in Swift 6.4&#8217;s from Apple&#8217;s engineers</a></strong></h3><p>Taking the answers Apple engineers gave at the WWDC26 Swift Group Lab as his starting point, <a href="https://x.com/budo_coder">Xiangyu</a> cross-checks each one against Evolution proposals, compiler source code, and official documentation. He clarifies which capabilities have actually shipped and which are still in transition, and corrects several version and implementation details from the live answers.</p><p>The most thought-provoking topic is &#8220;if we could do it over again.&#8221; In early Swift Concurrency, <code>nonisolated async</code> functions automatically left the caller&#8217;s actor and ran on the global concurrent executor. After years of real-world use, the Swift team now believes it makes more sense for them to stay on the caller&#8217;s actor by default. Had they been designing from scratch, that is what they would have shipped from day one. Although this behavior still requires explicit opt-in in Swift 6.4, it clearly shows how Swift Concurrency keeps recalibrating its defaults based on real migration experience.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-02">withTaskCancellationShield: Swift 6.4 new feature</a></strong></h3><p><code>withTaskCancellationShield</code> (SE-0504), introduced in Swift 6.4, lets a block of code run unaffected by its task&#8217;s existing cancellation state, which makes it well suited to wrap-up and cleanup logic that must complete. It does not undo the cancellation itself. Instead, code inside the shield (including any child tasks created there) temporarily cannot &#8220;see&#8221; the cancellation, and once execution leaves the shield, the original cancellation state becomes visible again. Because the API relies on the concurrency runtime that ships with the operating system, it is only available on the 27-series OSes and, unfortunately, cannot be back-deployed.</p><p><a href="https://www.linkedin.com/in/engomarelsayed">Omar Elsayed</a> offers a transitional workaround: create an unstructured task and <code>await</code> its <code>value</code>. Cancellation does not automatically propagate to the new task, and awaiting its <code>value</code> ensures the current task waits for the cleanup to finish before moving on, so the result closely approximates the real shield. Omar also stresses that this is only a stopgap. It adds overhead and requires captured values to be <code>Sendable</code>. Once your minimum deployment target allows it, you should switch to the official API.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-03">Running iOS Background Tasks Reliably, Part 2</a></strong></h3><p>In <a href="https://calcopilot.app/blog/posts/running-ios-background-tasks-reliably-part1/">Part 1</a>, <a href="https://www.linkedin.com/in/irvingpop/">Irving Popovetsky</a> drew on long-term, on-device observation to develop a set of practices for making <code>BGTaskScheduler</code> more reliable. One problem, however, remained unsolved: when a user goes a long time without opening the app, the execution opportunities granted to background tasks gradually dwindle.</p><p>This time, he found a breakthrough in a single remark from WWDC20: the system does not throttle silent pushes based on how often an app is used. So he set up a Cloudflare Worker that writes a <code>WakePing</code> record to the CloudKit public database every hour, then uses a <code>CKQuerySubscription</code> to trigger a silent push that wakes the app. The whole process requires no device token management and touches no user data. After several months in production, syncs still fire almost exactly on the hour, even after three consecutive weeks without opening the app. This certainly doesn&#8217;t turn iOS background execution into a true cron, but it is an excellent demonstration of how combining <code>BGTaskScheduler</code>, CloudKit, and background notifications can meaningfully improve the reliability of background work.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-04">Dissecting Xcode 27&#8217;s mcpbridge: Apple Skipped swift-sdk and Built Its Own MCP Stack</a></strong></h3><p>Although Apple also takes part in maintaining the official Swift MCP SDK, Xcode 27&#8217;s own MCP implementation takes a different path entirely. <a href="https://x.com/rbbtsn0w">Snow Wu</a> exported and examined the symbol tables of <code>mcpbridge</code>, <code>mcp-server</code>, and related private frameworks, and found that nearly everything, from JSON-RPC and the MCP semantic layer to command-line argument parsing, is built in-house.</p><p>This &#8220;start from scratch&#8221; approach isn&#8217;t merely about avoiding third-party dependencies. <code>mcpbridge</code> itself doesn&#8217;t even contain any tool definitions. It only handles protocol translation and routing between external agents and Xcode, while the actual tool capabilities remain inside Xcode. Combined with a three-process architecture, XPC communication, and a three-layer permission gate, it becomes clear that Apple isn&#8217;t simply embedding an MCP server in Xcode. Rather, it treats MCP as a system architecture problem: how to let untrusted external agents safely connect to a GUI application with complex state.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-05">Apple Watch brings distributed system headaches to your app</a></strong></h3><p>When both iPhone and Apple Watch can read and modify the same state, what you&#8217;re dealing with is effectively a small distributed system: two independent nodes that may lose contact at any moment, keep modifying data on their own, and reconnect only hours or even days later. <a href="https://x.com/jacobtechtavern">Jacob Bartlett</a> revisits Watch Connectivity from this perspective, using the CAP theorem to dissect the trade-offs behind each <code>WCSession</code> API. <code>sendMessage</code> requires the counterpart to be immediately reachable, sacrificing availability during a partition in exchange for real-time, acknowledged interaction. <code>updateApplicationContext</code> and <code>transferUserInfo</code>, by contrast, tolerate temporary inconsistency in favor of availability; the former keeps only the latest state, while the latter delivers every change in order.</p><p>This perspective also turns &#8220;which Watch Connectivity API should I use?&#8221; from a question of interface capabilities into a question of product semantics. Login state, settings sync, recording controls, and other kinds of data have different requirements for consistency and availability, and different features within the same app can perfectly well make different choices.</p><div><hr></div><h3><strong>iPhone Duo &amp; AnyOS 27 Adaptation</strong></h3><ul><li><p><a href="https://l.fatbobman.com/w0155-06">codelaby</a> introduces the Reserved Regions API added in iOS 27.1, and shows how to obtain the crease (division) and camera occlusion regions through <code>GeometryProxy</code>. For custom layouts that system containers can&#8217;t handle automatically, it offers a reliable way to keep important content out of the crease and camera areas.</p></li><li><p><a href="https://l.fatbobman.com/w0155-07">Antoine van der Lee</a> takes a practical, adaptation-first approach, systematically walking through the new capabilities: the iPhone Duo Simulator, resizable layouts, <code>ArrangementView</code>, Reserved Regions, hinge state, and the vertical toolbar. The core idea is not to design a separate interface for Duo, but to first make your app genuinely adapt to variable space, then use Duo-specific APIs to enhance special cases.</p></li><li><p><a href="https://l.fatbobman.com/w0155-08">Ronnie W.</a> discovered that macOS 27 re-decides how SwiftUI toolbar items are grouped: even with <code>ToolbarSpacer</code>, items you intended to keep separate may still be merged into the same navigation island. The fix is refreshingly direct: when you need precise control over grouping, let AppKit&#8217;s <code>NSToolbarItemGroup</code> take over the macOS toolbar structure.</p></li><li><p><a href="https://l.fatbobman.com/w0155-09">Anton Gubarenko</a> compiled Apple engineers&#8217; answers to developer questions from two iPhone Duo Group Labs (<a href="https://l.fatbobman.com/w0155-10">Part 2</a>), covering a wide range of practical issues including adaptive layout, fold postures, the vertical toolbar, multiple windows, the camera, accessibility, and the Simulator. The advice running through it all is remarkably consistent: treat Duo as an iPhone with more variable space, rely first on system containers and adaptive layout, and only intervene with creases, hinges, and specific postures when truly necessary.</p></li><li><p><a href="https://l.fatbobman.com/w0155-11">Sarunw</a> explains how the system decides whether a toolbar item on iPhone Duo goes into the horizontal or vertical toolbar: provide both an icon and a title so the system can choose the presentation based on available space, and only when the default judgment isn&#8217;t right should you use <code>axisBehavior</code> to explicitly specify <code>.horizontalOnly</code> or <code>.verticalPreferred</code>.</p></li></ul><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0155-12">PaintKit: A Swift Raster Drawing and Image Processing Engine</a></strong></h3><p>Developed by <a href="https://github.com/joshlin2201">Josh Lin</a>, PaintKit is a standalone Swift raster drawing engine extracted from the ItsPaint project. It covers pixel storage and blending, rasterization, brushes and shapes, selections, undo, text rendering, and image and PDF encoding/decoding. The engine is built on premultiplied-alpha RGBA8 pixels, and every edit returns the region that actually changed, so both screen refreshes and undo records only need to process the pixels that matter. Undo history isn&#8217;t simply capped by operation count either; it is managed by actual memory usage through local pixel patches. PaintKit has no dependencies on AppKit, SwiftUI, or third-party libraries, adopts Swift 6 strict concurrency, and most of its functionality can be verified with <code>swift test</code> without launching an app or an Xcode project.</p><p><a href="https://itspaintmac.com/">ItsPaint</a> is the complete application and real-world proving ground for PaintKit. It is a lightweight, native macOS drawing and screenshot annotation tool offering 13 tools, including pencil, brush, shapes, text, selection, pixelate, and spotlight. It supports 15 shapes, nine export formats, and PDF annotation, and can remove simple backgrounds without using machine learning models or network services. ItsPaint is also open source and available as a <a href="https://apps.apple.com/us/app/itspaint/id6796493980?utm_source=fatbobman%20weekly%20issue%20155&amp;utm_medium=web">free download on the App Store</a>.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-13">SwiftFairy: A SwiftUI Review Tool That Keeps Agents from Forgetting What They&#8217;ve Read</a></strong></h3><p>A macOS tool built by <a href="https://x.com/natpanferova">Natalia Panferova</a> and <a href="https://x.com/hishnash">Matthaus Woolard</a> that provides Swift and SwiftUI code review for coding agents through a local MCP server.</p><p>Rather than writing a large set of rules into a Skill or <code>AGENTS.md</code> and hoping the agent recalls them at the right moment, SwiftFairy hands &#8220;finding problems&#8221; over to deterministic static analysis. It parses code into a partial graph, matches it against declarative issue patterns, pinpoints findings to specific lines, and then passes the corresponding explanations and fix examples to the agent. Knowledge only enters the context when an issue is actually hit, which both keeps the agent from &#8220;forgetting what it read&#8221; and reduces token usage.</p><p>Much of SwiftFairy&#8217;s value also comes from the rules themselves. The knowledge is currently organized into &#8220;Scrolls,&#8221; with the first batch covering Proper SwiftUI, Performant Swift Charts, and Modern Swift. The content draws on the two authors&#8217; years of books and articles, as well as Natalia&#8217;s experience working on Apple&#8217;s core SwiftUI team. Compared with having another LLM do the review, SwiftFairy is more like adding a layer of domain-aware, reproducible static review to the agent workflow.</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-155?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-155?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>iPhone Duo &#30041;&#32473;&#24320;&#21457;&#32773;&#30340;&#19968;&#20010;&#26376;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-155/">&#32593;&#39029;&#29256;</a></strong></p><p>&#21253;&#21547; iPhone Duo &#27169;&#25311;&#22120;&#30340; Xcode 27.1 beta &#20110; 9 &#26376; 18 &#26085;&#21457;&#24067;&#65292;&#36317;&#31163; 10 &#26376; 23 &#26085;&#27491;&#24335;&#21457;&#21806;&#20165;&#20116;&#21608;&#12290;&#39047;&#20026;&#24494;&#22937;&#30340;&#26159;&#65292;&#24444;&#26102;&#19981;&#21547; Duo &#25903;&#25345;&#30340; Xcode 27.2 beta &#24050;&#20808;&#34892;&#25512;&#20986;&#8212;&#8212;&#24819;&#36866;&#37197;&#33529;&#26524;&#26368;&#26032;&#30340;&#35774;&#22791;&#65292;&#21453;&#32780;&#35201;&#20351;&#29992;&#29256;&#26412;&#21495;&#26356;&#20302;&#30340; Xcode&#12290;&#36825;&#31181;&#8220;&#21452;&#36712; Beta&#8221;&#25110;&#28304;&#20110; Duo &#29420;&#31435;&#30340;&#31995;&#32479;&#29256;&#26412;&#19982;&#21457;&#24067;&#21069;&#30340;&#20445;&#23494;&#38656;&#35201;&#65292;&#20195;&#20215;&#21017;&#26159;&#24320;&#21457;&#32773;&#30340;&#20934;&#22791;&#31383;&#21475;&#34987;&#21387;&#32553;&#21040;&#20102;&#19968;&#20010;&#26376;&#24038;&#21491;&#12290;</p><p>&#24320;&#21457;&#32773;&#21487;&#20197;&#22312; Device Hub &#20013;&#24320;&#21512;&#12289;&#26059;&#36716;&#12289;&#25240;&#21472;&#36825;&#21488;&#34394;&#25311;&#35774;&#22791;&#12290;&#20294;&#20219;&#20309;&#26377;&#32463;&#39564;&#30340;&#24037;&#31243;&#24072;&#37117;&#28165;&#26970;&#65306;&#27169;&#25311;&#22120;&#33021;&#22815;&#36824;&#21407;&#20960;&#20309;&#24418;&#24577;&#19982;&#23039;&#24577;&#65292;&#21364;&#26080;&#27861;&#36824;&#21407;&#21487;&#20379;&#24615;&#19982;&#30495;&#23454;&#30340;&#29289;&#29702;&#20132;&#20114;&#12290;</p><p>&#22312;&#32570;&#20047;&#23454;&#20307;&#21453;&#39304;&#30340;&#36825;&#27573;&#30495;&#31354;&#26399;&#65292;&#24320;&#21457;&#32773;&#24456;&#23481;&#26131;&#28369;&#21521;&#20004;&#20010;&#26497;&#31471;&#65306;&#35201;&#20040;&#26080;&#25152;&#36866;&#20174;&#65292;&#19981;&#25954;&#36234;&#38647;&#27744;&#19968;&#27493;&#65307;&#35201;&#20040;&#23545;&#30528;&#34394;&#25311;&#31383;&#21475;&#20973;&#31354;&#26500;&#24819;&#20986;&#35768;&#22810;&#30475;&#20284;&#31934;&#24039;&#12289;&#22312;&#30495;&#23454;&#25569;&#25345;&#19979;&#21364;&#21035;&#25197;&#38590;&#29992;&#30340;&#19987;&#23646;&#20132;&#20114;&#12290;</p><p>&#38754;&#23545;&#32039;&#36843;&#30340;&#20498;&#35745;&#26102;&#65292;&#26356;&#21153;&#23454;&#30340;&#20570;&#27861;&#26159;&#20808;&#20026;&#8220;&#36866;&#37197;&#8221;&#21010;&#23450;&#29702;&#24615;&#30340;&#36793;&#30028;&#65292;&#20998;&#28165;&#20160;&#20040;&#26159;&#8220;&#22815;&#29992;&#8221;&#65292;&#20160;&#20040;&#26159;&#8220;&#22909;&#29992;&#8221;&#12290;</p><p>Apple &#24050;&#26126;&#30830;&#34920;&#31034;&#65292;&#29616;&#26377;&#24212;&#29992;&#21363;&#20351;&#19981;&#37325;&#26032;&#26500;&#24314;&#20063;&#21487;&#20197;&#22312; Duo &#19978;&#36816;&#34892;&#65292;&#20294;&#8220;&#33021;&#22815;&#36816;&#34892;&#8221;&#26174;&#28982;&#19981;&#31561;&#20110;&#8220;&#24050;&#32463;&#36866;&#37197;&#8221;&#12290;&#30830;&#20445;&#24212;&#29992;&#22312;&#26032;&#35774;&#22791;&#19978;&#33258;&#28982;&#12289;&#31283;&#23450;&#22320;&#21576;&#29616;&#65292;&#26159;&#19978;&#24066;&#21069;&#8220;&#22815;&#29992;&#8221;&#30340;&#21450;&#26684;&#32447;&#65307;&#33267;&#20110;&#20160;&#20040;&#25165;&#26159;&#30495;&#27491;&#23646;&#20110;&#25240;&#21472;&#35774;&#22791;&#30340;&#8220;&#22909;&#29992;&#8221;&#20307;&#39564;&#65292;&#24656;&#24597;&#35201;&#31561;&#35774;&#22791;&#26469;&#21040;&#24320;&#21457;&#32773;&#25163;&#20013;&#21518;&#65292;&#25165;&#20250;&#36880;&#28176;&#28014;&#29616;&#31572;&#26696;&#12290;</p><p>10 &#26376; 23 &#26085;&#65292;&#25110;&#35768;&#25165;&#26159; Duo &#36866;&#37197;&#30495;&#27491;&#24320;&#22987;&#30340;&#37027;&#19968;&#22825;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-154/">&#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/arrangementview-think-before-you-arrange/?utm_source=fatbobman%20weekly%20issue%20155&amp;utm_medium=web">ArrangementView&#65306;&#35851;&#32780;&#21518;&#23450;</a></strong></h3><p>&#31532;&#19968;&#27425;&#30475;&#21040; <code>ArrangementView</code> &#30340; API &#26102;&#65292;&#25105;&#26377;&#19968;&#31181;&#35828;&#19981;&#20986;&#30340;&#21035;&#25197;&#24863;&#12290;&#30452;&#21040;&#22312; Xcode 27.1 beta &#20013;&#23454;&#38469;&#20351;&#29992;&#21518;&#65292;&#36825;&#31181;&#24863;&#35273;&#25165;&#36880;&#28176;&#28165;&#26224;&#12290;&#26597;&#38405;&#26356;&#22810;&#30340;&#33529;&#26524;&#36164;&#26009;&#65292;&#20877;&#25226;&#23427;&#25918;&#22238; iPhone Duo &#30340;&#20351;&#29992;&#22330;&#26223;&#65292;&#25105;&#21457;&#29616;&#36825;&#20221;&#21035;&#25197;&#20854;&#23454;&#26469;&#33258;&#20004;&#20010;&#26041;&#38754;&#65306;&#19968;&#37096;&#20998;&#28304;&#20110;&#25105;&#23545;&#23427;&#30340;&#23450;&#20301;&#19981;&#22815;&#28165;&#26970;&#65292;&#29702;&#35299;&#20043;&#21518;&#20415;&#37322;&#28982;&#20102;&#65307;&#21478;&#19968;&#37096;&#20998;&#21017;&#26469;&#33258; API &#26412;&#36523;&#65292;&#21363;&#20415;&#24819;&#26126;&#30333;&#20102;&#65292;&#20381;&#28982;&#23384;&#22312;&#12290;</p><p>&#22240;&#27492;&#65292;&#24819;&#29992;&#22909; <code>ArrangementView</code> &#38656;&#35201;&#22312;&#20351;&#29992;&#21069;&#22810;&#24819;&#19968;&#27493;&#65306;&#20869;&#23481;&#20043;&#38388;&#31350;&#31455;&#26159;&#20160;&#20040;&#20851;&#31995;&#65311;&#21738;&#20123;&#32467;&#26524;&#21487;&#20197;&#20132;&#32473;&#23481;&#22120;&#65292;&#21738;&#20123;&#21462;&#33293;&#20173;&#39035;&#30001;&#24212;&#29992;&#25215;&#25285;&#65311;&#35851;&#32780;&#21518;&#23450;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0155-01">What&#8217;s new in Swift 6.4&#8217;s from Apple&#8217;s engineers</a></strong></h3><p><a href="https://x.com/budo_coder">Xiangyu</a> &#20197; WWDC26 Swift Group Lab &#19978; Apple &#24037;&#31243;&#24072;&#30340;&#29616;&#22330;&#31572;&#30097;&#20026;&#32447;&#32034;&#65292;&#36880;&#19968;&#23545;&#29031; Evolution &#25552;&#26696;&#12289;&#32534;&#35793;&#22120;&#28304;&#30721;&#19982;&#23448;&#26041;&#25991;&#26723;&#65292;&#21400;&#28165;&#20102;&#21738;&#20123;&#33021;&#21147;&#24050;&#32463;&#33853;&#22320;&#12289;&#21738;&#20123;&#20173;&#22788;&#20110;&#36807;&#28193;&#38454;&#27573;&#65292;&#24182;&#35746;&#27491;&#20102;&#29616;&#22330;&#22238;&#31572;&#20013;&#33509;&#24178;&#29256;&#26412;&#19982;&#23454;&#29616;&#32454;&#33410;&#19978;&#30340;&#20986;&#20837;&#12290;</p><p>&#20854;&#20013;&#26368;&#32784;&#20154;&#23547;&#21619;&#30340;&#65292;&#26159;&#8220;&#22914;&#26524;&#37325;&#26469;&#19968;&#27425;&#8221;&#36825;&#20010;&#35805;&#39064;&#65306;&#26089;&#26399;&#30340; Swift Concurrency &#20250;&#35753; <code>nonisolated async</code> &#20989;&#25968;&#33258;&#21160;&#31163;&#24320;&#35843;&#29992;&#32773;&#25152;&#22312;&#30340; actor&#65292;&#36716;&#21040;&#20840;&#23616;&#24182;&#21457;&#25191;&#34892;&#22120;&#65288;Global Concurrent Executor&#65289;&#19978;&#36816;&#34892;&#65307;&#32463;&#36807;&#25968;&#24180;&#30340;&#23454;&#36341;&#65292;Swift &#22242;&#38431;&#35748;&#20026;&#65292;&#35753;&#23427;&#40664;&#35748;&#30041;&#22312;&#35843;&#29992;&#32773;&#30340; actor &#19978;&#25165;&#26356;&#20026;&#21512;&#29702;&#8212;&#8212;&#33509;&#33021;&#20174;&#22836;&#35774;&#35745;&#65292;&#20182;&#20204;&#24076;&#26395;&#19968;&#24320;&#22987;&#20415;&#26159;&#22914;&#27492;&#12290;&#23613;&#31649;&#36825;&#19968;&#34892;&#20026;&#22312; Swift 6.4 &#20013;&#20173;&#38656;&#26174;&#24335;&#21551;&#29992;&#65292;&#21364;&#28165;&#26224;&#22320;&#23637;&#29616;&#20102; Swift Concurrency &#22914;&#20309;&#20381;&#25454;&#30495;&#23454;&#30340;&#36801;&#31227;&#32463;&#39564;&#65292;&#19981;&#26029;&#26657;&#20934;&#33258;&#36523;&#30340;&#40664;&#35748;&#36873;&#25321;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-02">withTaskCancellationShield: Swift 6.4 new feature</a></strong></h3><p>Swift 6.4 &#24341;&#20837;&#30340; <code>withTaskCancellationShield</code>&#65288;SE-0504&#65289;&#21487;&#20197;&#35753;&#19968;&#27573;&#20195;&#30721;&#19981;&#21463;&#25152;&#23646;&#20219;&#21153;&#24050;&#26377;&#21462;&#28040;&#29366;&#24577;&#30340;&#24433;&#21709;&#65292;&#38750;&#24120;&#36866;&#21512;&#24517;&#39035;&#23436;&#25104;&#30340;&#25910;&#23614;&#21644;&#28165;&#29702;&#36923;&#36753;&#12290;&#23427;&#24182;&#19981;&#20250;&#25764;&#38144;&#21462;&#28040;&#26412;&#36523;&#65292;&#21482;&#26159;&#35753;&#23631;&#34109;&#33539;&#22260;&#20869;&#30340;&#20195;&#30721;&#65288;&#21253;&#25324;&#20854;&#20013;&#21019;&#24314;&#30340;&#23376;&#20219;&#21153;&#65289;&#26242;&#26102;&#8220;&#30475;&#19981;&#21040;&#8221;&#21462;&#28040;&#29366;&#24577;&#65307;&#31163;&#24320;&#23631;&#34109;&#21306;&#22495;&#21518;&#65292;&#21407;&#26377;&#21462;&#28040;&#29366;&#24577;&#20250;&#37325;&#26032;&#21487;&#35265;&#12290;&#30001;&#20110;&#35813; API &#20381;&#36182;&#38543;&#31995;&#32479;&#20998;&#21457;&#30340;&#24182;&#21457;&#36816;&#34892;&#26102;&#65288;Concurrency Runtime&#65289;&#65292;&#22240;&#27492;&#21482;&#33021;&#22312; 27 &#31995;&#21015;&#31995;&#32479;&#19978;&#20351;&#29992;&#65292;&#24456;&#36951;&#25022;&#26080;&#27861;&#21521;&#19979;&#37096;&#32626;&#12290;</p><p><a href="https://www.linkedin.com/in/engomarelsayed">Omar Elsayed</a> &#22312;&#25991;&#20013;&#32473;&#20986;&#20102;&#19968;&#20010;&#36807;&#28193;&#26041;&#26696;&#65306;&#21019;&#24314;&#19968;&#20010;&#38750;&#32467;&#26500;&#21270;&#20219;&#21153;&#65288;Unstructured Task&#65289;&#24182; <code>await</code> &#20854; <code>value</code>&#12290;&#30001;&#20110;&#21462;&#28040;&#29366;&#24577;&#19981;&#20250;&#33258;&#21160;&#20256;&#25773;&#21040;&#36825;&#20010;&#26032;&#20219;&#21153;&#65292;&#32780;&#31561;&#24453; <code>value</code> &#21448;&#33021;&#35753;&#24403;&#21069;&#20219;&#21153;&#31561;&#21040;&#28165;&#29702;&#32467;&#26463;&#21518;&#20877;&#32487;&#32493;&#65292;&#22240;&#27492;&#21487;&#20197;&#23454;&#29616;&#36817;&#20284;&#30340;&#25928;&#26524;&#12290;Omar &#20063;&#24378;&#35843;&#65292;&#36825;&#21482;&#26159;&#26435;&#23452;&#20043;&#35745;&#65306;&#19981;&#20165;&#23384;&#22312;&#39069;&#22806;&#24320;&#38144;&#65292;&#36824;&#35201;&#27714;&#25429;&#33719;&#30340;&#20540;&#28385;&#36275; <code>Sendable</code>&#65307;&#24453;&#26368;&#20302;&#37096;&#32626;&#29256;&#26412;&#25552;&#21319;&#21518;&#65292;&#20173;&#24212;&#25913;&#29992;&#27491;&#24335; API&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-03">Running iOS Background Tasks Reliably, Part 2</a></strong></h3><p>&#22312; <a href="https://calcopilot.app/blog/posts/running-ios-background-tasks-reliably-part1/">Part 1</a> &#20013;&#65292;<a href="https://www.linkedin.com/in/irvingpop/">Irving Popovetsky</a> &#36890;&#36807;&#38271;&#26399;&#30340;&#30495;&#26426;&#35266;&#23519;&#65292;&#24635;&#32467;&#20986;&#19968;&#22871;&#25552;&#21319; <code>BGTaskScheduler</code> &#21487;&#38752;&#24615;&#30340;&#23454;&#36341;&#65292;&#20294;&#26377;&#19968;&#20010;&#38382;&#39064;&#22987;&#32456;&#26080;&#35299;&#65306;&#24403;&#29992;&#25143;&#36739;&#38271;&#26102;&#38388;&#19981;&#25171;&#24320; App&#65292;&#21518;&#21488;&#20219;&#21153;&#33719;&#24471;&#30340;&#25191;&#34892;&#26426;&#20250;&#20415;&#20250;&#36880;&#28176;&#34928;&#20943;&#12290;</p><p>&#36825;&#19968;&#27425;&#65292;&#20182;&#20174; WWDC20 &#30340;&#19968;&#21477;&#25552;&#31034;&#20013;&#25214;&#21040;&#20102;&#31361;&#30772;&#21475;&#8212;&#8212;&#31995;&#32479;&#19981;&#20250;&#20381;&#25454; App &#30340;&#20351;&#29992;&#39057;&#29575;&#26469;&#38480;&#21046;&#38745;&#40664;&#25512;&#36865;&#65288;Silent Push&#65289;&#12290;&#20110;&#26159;&#65292;&#20182;&#35753; Cloudflare Worker &#27599;&#23567;&#26102;&#21521; CloudKit &#20844;&#20849;&#25968;&#25454;&#24211;&#65288;Public Database&#65289;&#20889;&#20837;&#19968;&#26465; <code>WakePing</code> &#35760;&#24405;&#65292;&#20877;&#20511;&#21161; <code>CKQuerySubscription</code> &#35302;&#21457;&#38745;&#40664;&#25512;&#36865;&#21796;&#37266; App&#12290;&#25972;&#20010;&#36807;&#31243;&#26080;&#38656;&#32500;&#25252;&#35774;&#22791;&#20196;&#29260;&#65288;Device Token&#65289;&#65292;&#20063;&#19981;&#35302;&#21450;&#20219;&#20309;&#29992;&#25143;&#25968;&#25454;&#12290;&#32463;&#36807;&#25968;&#26376;&#30340;&#23454;&#38469;&#36816;&#34892;&#65292;&#21363;&#20415;&#36830;&#32493;&#19977;&#21608;&#26410;&#25171;&#24320; App&#65292;&#21516;&#27493;&#20381;&#28982;&#33021;&#36817;&#20046;&#20934;&#28857;&#22320;&#25353;&#23567;&#26102;&#35302;&#21457;&#12290;&#36825;&#24403;&#28982;&#26080;&#27861;&#35753; iOS &#30340;&#21518;&#21488;&#25191;&#34892;&#21464;&#25104;&#30495;&#27491;&#30340; cron&#65292;&#21364;&#24456;&#22909;&#22320;&#31034;&#33539;&#20102;&#22914;&#20309;&#23558; <code>BGTaskScheduler</code>&#12289;CloudKit &#19982;&#21518;&#21488;&#36890;&#30693;&#65288;Background Notification&#65289;&#32452;&#21512;&#36215;&#26469;&#65292;&#20999;&#23454;&#25552;&#21319;&#21518;&#21488;&#20219;&#21153;&#30340;&#21487;&#38752;&#24615;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-04">&#25286;&#35299; Xcode 27 mcpbridge&#65306;Apple &#27809;&#26377;&#29992; swift-sdk&#65292;&#32780;&#26159;&#33258;&#30740;&#20102;&#19968;&#25972;&#22871; MCP &#26632;</a></strong></h3><p>&#23613;&#31649; Apple &#20063;&#21442;&#19982;&#20102;&#32500;&#25252;&#23448;&#26041;&#30340; Swift MCP SDK&#65292;&#20294; Xcode 27 &#33258;&#36523;&#30340; MCP &#23454;&#29616;&#21364;&#21478;&#36767;&#36426;&#24452;&#12290;<a href="https://x.com/rbbtsn0w">Snow Wu</a> &#23548;&#20986;&#24182;&#26680;&#23545;&#20102; <code>mcpbridge</code>&#12289;<code>mcp-server</code> &#21450;&#30456;&#20851;&#31169;&#26377;&#26694;&#26550;&#30340;&#31526;&#21495;&#34920;&#65292;&#21457;&#29616;&#20174; JSON-RPC&#12289;MCP &#35821;&#20041;&#23618;&#21040;&#21629;&#20196;&#34892;&#21442;&#25968;&#35299;&#26512;&#65292;Xcode &#20960;&#20046;&#20840;&#37096;&#37319;&#29992;&#33258;&#30740;&#23454;&#29616;&#12290;</p><p>&#36825;&#31181;&#8220;&#21478;&#36215;&#28809;&#28790;&#8221;&#24182;&#19981;&#21482;&#26159;&#20026;&#20102;&#35268;&#36991;&#31532;&#19977;&#26041;&#20381;&#36182;&#12290;<code>mcpbridge</code> &#26412;&#36523;&#29978;&#33267;&#19981;&#21253;&#21547;&#20219;&#20309;&#24037;&#20855;&#23450;&#20041;&#65292;&#21482;&#36127;&#36131;&#22312;&#22806;&#37096; Agent &#19982; Xcode &#20043;&#38388;&#23436;&#25104;&#21327;&#35758;&#36716;&#25442;&#19982;&#36335;&#30001;&#65292;&#30495;&#27491;&#30340;&#24037;&#20855;&#33021;&#21147;&#20173;&#30001; Xcode &#25552;&#20379;&#12290;&#20877;&#32467;&#21512;&#19977;&#36827;&#31243;&#26550;&#26500;&#12289;XPC &#36890;&#20449;&#19982;&#19977;&#23618;&#26435;&#38480;&#38392;&#38376;&#65292;&#21487;&#20197;&#30475;&#20986; Apple &#24182;&#19981;&#21482;&#26159;&#22312; Xcode &#37324;&#23884;&#20837;&#19968;&#20010; MCP Server&#65292;&#32780;&#26159;&#23558; MCP &#35270;&#20026;&#19968;&#20010;&#31995;&#32479;&#26550;&#26500;&#38382;&#39064;&#65306;&#22914;&#20309;&#35753;&#19981;&#21487;&#20449;&#30340;&#22806;&#37096; Agent &#23433;&#20840;&#22320;&#25509;&#20837;&#19968;&#20010;&#29366;&#24577;&#22797;&#26434;&#30340; GUI &#24212;&#29992;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-05">Apple Watch brings distributed system headaches to your app</a></strong></h3><p>&#24403; iPhone &#19982; Apple Watch &#37117;&#33021;&#35835;&#21462;&#24182;&#20462;&#25913;&#21516;&#19968;&#20221;&#29366;&#24577;&#26102;&#65292;&#20320;&#38754;&#23545;&#30340;&#20854;&#23454;&#24050;&#26159;&#19968;&#20010;&#23567;&#22411;&#20998;&#24067;&#24335;&#31995;&#32479;&#65306;&#20004;&#20010;&#29420;&#31435;&#33410;&#28857;&#38543;&#26102;&#21487;&#33021;&#22833;&#32852;&#65292;&#21508;&#33258;&#32487;&#32493;&#20462;&#25913;&#25968;&#25454;&#65292;&#24182;&#22312;&#25968;&#23567;&#26102;&#29978;&#33267;&#25968;&#22825;&#21518;&#25165;&#37325;&#26032;&#36830;&#25509;&#12290;<a href="https://x.com/jacobtechtavern">Jacob Bartlett</a> &#20174;&#36825;&#19968;&#35270;&#35282;&#37325;&#26032;&#23457;&#35270; Watch Connectivity&#65292;&#20511; CAP &#29702;&#35770;&#21078;&#26512;&#21508;&#20010; <code>WCSession</code> API &#32972;&#21518;&#30340;&#21462;&#33293;&#65306;<code>sendMessage</code> &#35201;&#27714;&#23545;&#31471;&#21363;&#26102;&#21487;&#36798;&#65292;&#20197;&#29306;&#29298;&#20998;&#21306;&#26102;&#30340;&#21487;&#29992;&#24615;&#25442;&#21462;&#23454;&#26102;&#12289;&#21487;&#30830;&#35748;&#30340;&#20132;&#20114;&#65307;<code>updateApplicationContext</code> &#19982; <code>transferUserInfo</code> &#21017;&#23481;&#24525;&#30701;&#26242;&#30340;&#19981;&#19968;&#33268;&#65292;&#20248;&#20808;&#20445;&#35777;&#21487;&#29992;&#24615;&#65292;&#21069;&#32773;&#21482;&#20445;&#30041;&#26368;&#26032;&#29366;&#24577;&#65292;&#21518;&#32773;&#25353;&#24207;&#25237;&#36882;&#27599;&#19968;&#27425;&#21464;&#26356;&#12290;</p><p>&#36825;&#31181;&#35270;&#35282;&#20063;&#35753;&#8220;&#35813;&#36873;&#25321;&#21738;&#20010; Watch Connectivity API&#8221;&#20174;&#25509;&#21475;&#33021;&#21147;&#38382;&#39064;&#21464;&#25104;&#20102;&#20135;&#21697;&#35821;&#20041;&#38382;&#39064;&#65306;&#30331;&#24405;&#29366;&#24577;&#12289;&#35774;&#32622;&#21516;&#27493;&#12289;&#24405;&#38899;&#25511;&#21046;&#31561;&#25968;&#25454;&#65292;&#23545;&#19968;&#33268;&#24615;&#21644;&#21487;&#29992;&#24615;&#30340;&#35201;&#27714;&#24182;&#19981;&#30456;&#21516;&#65292;&#21516;&#19968;&#20010; App &#30340;&#19981;&#21516;&#21151;&#33021;&#23436;&#20840;&#21487;&#20197;&#20570;&#20986;&#19981;&#21516;&#36873;&#25321;&#12290;</p><div><hr></div><h3><strong>iPhone Duo &#21644; AnyOS 27 &#36866;&#37197;</strong></h3><ul><li><p><a href="https://l.fatbobman.com/w0155-06">codelaby</a> &#20171;&#32461;&#20102; iOS 27.1 &#26032;&#22686;&#30340; Reserved Regions API&#65292;&#20197;&#21450;&#22914;&#20309;&#36890;&#36807; <code>GeometryProxy</code> &#33719;&#21462;&#25240;&#30165;&#65288;division&#65289;&#21644;&#25668;&#20687;&#22836;&#36974;&#25377;&#65288;occlusion&#65289;&#21306;&#22495;&#12290;&#23545;&#20110;&#31995;&#32479;&#23481;&#22120;&#26080;&#27861;&#33258;&#21160;&#22788;&#29702;&#30340;&#33258;&#23450;&#20041;&#24067;&#23616;&#65292;&#23427;&#25552;&#20379;&#20102;&#19968;&#31181;&#36991;&#20813;&#37325;&#35201;&#20869;&#23481;&#33853;&#20837;&#25240;&#30165;&#25110;&#25668;&#20687;&#22836;&#21306;&#22495;&#30340;&#21487;&#38752;&#26041;&#24335;&#12290;</p></li><li><p><a href="https://l.fatbobman.com/w0155-07">Antoine van der Lee</a> &#20174;&#23454;&#38469;&#36866;&#37197;&#20986;&#21457;&#65292;&#31995;&#32479;&#26803;&#29702;&#20102; iPhone Duo Simulator&#12289;&#21487;&#35843;&#25972;&#24067;&#23616;&#12289;<code>ArrangementView</code>&#12289;Reserved Regions&#12289;&#38128;&#38142;&#29366;&#24577;&#21644;&#22402;&#30452;&#24037;&#20855;&#26639;&#31561;&#26032;&#33021;&#21147;&#12290;&#26680;&#24515;&#24605;&#36335;&#24182;&#19981;&#26159;&#20026; Duo &#21333;&#29420;&#35774;&#35745;&#19968;&#22871;&#30028;&#38754;&#65292;&#32780;&#26159;&#20808;&#35753;&#24212;&#29992;&#30495;&#27491;&#36866;&#24212;&#21487;&#21464;&#31354;&#38388;&#65292;&#20877;&#29992; Duo &#19987;&#23646; API &#23545;&#29305;&#27530;&#22330;&#26223;&#36827;&#34892;&#22686;&#24378;&#12290;</p></li><li><p><a href="https://l.fatbobman.com/w0155-08">Ronnie W.</a> &#21457;&#29616; macOS 27 &#20250;&#37325;&#26032;&#20915;&#23450; SwiftUI Toolbar &#30340;&#20998;&#32452;&#65292;&#21363;&#20351;&#20351;&#29992; <code>ToolbarSpacer</code>&#65292;&#21407;&#26412;&#24076;&#26395;&#20998;&#24320;&#30340;&#39033;&#30446;&#20173;&#21487;&#33021;&#34987;&#21512;&#24182;&#36827;&#21516;&#19968;&#20010; navigation island&#12290;&#25991;&#31456;&#32473;&#20986;&#30340;&#35299;&#20915;&#26041;&#26696;&#30456;&#24403;&#30452;&#25509;&#65306;&#22312;&#38656;&#35201;&#31934;&#30830;&#25511;&#21046;&#20998;&#32452;&#26102;&#65292;&#35753; AppKit &#30340; <code>NSToolbarItemGroup</code> &#25509;&#31649; macOS &#24037;&#20855;&#26639;&#32467;&#26500;&#12290;</p></li><li><p><a href="https://l.fatbobman.com/w0155-09">Anton Gubarenko</a> &#25972;&#29702;&#20102;&#20004;&#22330; iPhone Duo Group Lab &#20013; Apple &#24037;&#31243;&#24072;&#23545;&#24320;&#21457;&#32773;&#38382;&#39064;&#30340;&#22238;&#31572;&#65288;<a href="https://l.fatbobman.com/w0155-10">&#31532;&#20108;&#37096;&#20998;</a>&#65289;&#65292;&#28085;&#30422;&#33258;&#36866;&#24212;&#24067;&#23616;&#12289;&#25240;&#21472;&#23039;&#24577;&#12289;&#22402;&#30452;&#24037;&#20855;&#26639;&#12289;&#22810;&#31383;&#21475;&#12289;&#25668;&#20687;&#22836;&#12289;&#26080;&#38556;&#30861;&#20197;&#21450; Simulator &#31561;&#22823;&#37327;&#23454;&#38469;&#38382;&#39064;&#12290;&#36143;&#31359;&#20854;&#20013;&#30340;&#24314;&#35758;&#21313;&#20998;&#19968;&#33268;&#65306;&#25226; Duo &#24403;&#20316;&#25317;&#26377;&#26356;&#22810;&#21487;&#21464;&#31354;&#38388;&#30340; iPhone&#65292;&#20248;&#20808;&#20381;&#36182;&#31995;&#32479;&#23481;&#22120;&#21644;&#33258;&#36866;&#24212;&#24067;&#23616;&#65292;&#21482;&#26377;&#30830;&#26377;&#38656;&#35201;&#26102;&#20877;&#20171;&#20837;&#25240;&#30165;&#12289;&#38128;&#38142;&#21644;&#29305;&#23450;&#23039;&#24577;&#12290;</p></li><li><p><a href="https://l.fatbobman.com/w0155-11">Sarunw</a> &#35299;&#37322;&#20102; iPhone Duo &#19978;&#31995;&#32479;&#22914;&#20309;&#20915;&#23450; Toolbar Item &#24212;&#36827;&#20837;&#27700;&#24179;&#36824;&#26159;&#22402;&#30452;&#24037;&#20855;&#26639;&#65306;&#20026;&#39033;&#30446;&#21516;&#26102;&#25552;&#20379;&#22270;&#26631;&#21644;&#26631;&#39064;&#65292;&#35753;&#31995;&#32479;&#26681;&#25454;&#31354;&#38388;&#36873;&#25321;&#34920;&#29616;&#24418;&#24335;&#65307;&#21482;&#26377;&#22312;&#40664;&#35748;&#21028;&#26029;&#19981;&#21512;&#36866;&#26102;&#65292;&#25165;&#36890;&#36807; <code>axisBehavior</code> &#26126;&#30830;&#25351;&#23450; <code>.horizontalOnly</code> &#25110; <code>.verticalPreferred</code>&#12290;</p></li></ul><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0155-12">PaintKit&#65306;Swift &#26629;&#26684;&#32472;&#22270;&#19982;&#22270;&#20687;&#22788;&#29702;&#24341;&#25806;</a></strong></h3><p><a href="https://github.com/joshlin2201">Josh Lin</a> &#24320;&#21457;&#30340; PaintKit&#65292;&#26159; ItsPaint &#39033;&#30446;&#20013;&#19968;&#22871;&#21487;&#20197;&#29420;&#31435;&#20351;&#29992;&#30340; Swift &#26629;&#26684;&#32472;&#22270;&#24341;&#25806;&#65292;&#28085;&#30422;&#20687;&#32032;&#23384;&#20648;&#19982;&#28151;&#21512;&#12289;&#20809;&#26629;&#21270;&#12289;&#30011;&#31508;&#19982;&#24418;&#29366;&#12289;&#36873;&#21306;&#12289;&#25764;&#38144;&#12289;&#25991;&#23383;&#28210;&#26579;&#65292;&#20197;&#21450;&#22270;&#29255;&#21644; PDF &#32534;&#35299;&#30721;&#31561;&#33021;&#21147;&#12290;&#24341;&#25806;&#20197;&#39044;&#20056; Alpha &#30340; RGBA8 &#20687;&#32032;&#20026;&#22522;&#30784;&#65292;&#27599;&#27425;&#32534;&#36753;&#37117;&#20250;&#36820;&#22238;&#23454;&#38469;&#21457;&#29983;&#21464;&#21270;&#30340;&#21306;&#22495;&#65292;&#20351;&#30011;&#38754;&#21047;&#26032;&#21644;&#25764;&#38144;&#35760;&#24405;&#37117;&#21482;&#38656;&#22788;&#29702;&#24517;&#35201;&#30340;&#20687;&#32032;&#65307;&#25764;&#38144;&#21382;&#21490;&#20063;&#19981;&#26159;&#31616;&#21333;&#38480;&#21046;&#25805;&#20316;&#27425;&#25968;&#65292;&#32780;&#26159;&#36890;&#36807;&#23616;&#37096;&#20687;&#32032;&#34917;&#19969;&#25353;&#23454;&#38469;&#20869;&#23384;&#21344;&#29992;&#31649;&#29702;&#12290;PaintKit &#19981;&#20381;&#36182; AppKit&#12289;SwiftUI &#25110;&#31532;&#19977;&#26041;&#24211;&#65292;&#37319;&#29992; Swift 6 &#20005;&#26684;&#24182;&#21457;&#27169;&#24335;&#65292;&#22823;&#37096;&#20998;&#21151;&#33021;&#26080;&#38656;&#21551;&#21160;&#24212;&#29992;&#25110; Xcode &#24037;&#31243;&#21363;&#21487;&#36890;&#36807; swift test &#39564;&#35777;&#12290;</p><p><a href="https://itspaintmac.com/">ItsPaint</a> &#21017;&#26159; PaintKit &#30340;&#23436;&#25972;&#24212;&#29992;&#19982;&#23454;&#36341;&#39564;&#35777;&#12290;&#23427;&#26159;&#19968;&#27454;&#38754;&#21521; macOS &#30340;&#36731;&#37327;&#32423;&#21407;&#29983;&#32472;&#22270;&#21450;&#25130;&#22270;&#26631;&#27880;&#24037;&#20855;&#65292;&#25552;&#20379;&#38085;&#31508;&#12289;&#30011;&#31508;&#12289;&#24418;&#29366;&#12289;&#25991;&#23383;&#12289;&#36873;&#21306;&#12289;&#20687;&#32032;&#21270;&#21644;&#32858;&#20809;&#28783;&#31561; 13 &#31181;&#24037;&#20855;&#65292;&#25903;&#25345; 15 &#31181;&#24418;&#29366;&#12289;&#20061;&#31181;&#23548;&#20986;&#26684;&#24335;&#21644; PDF &#26631;&#27880;&#65292;&#22312;&#19981;&#20351;&#29992;&#26426;&#22120;&#23398;&#20064;&#27169;&#22411;&#19982;&#32593;&#32476;&#26381;&#21153;&#30340;&#24773;&#20917;&#19979;&#31227;&#38500;&#31616;&#21333;&#32972;&#26223;&#12290;ItsPaint &#21516;&#26679;&#24320;&#28304;&#65292;&#24182;&#21487;&#22312; <a href="https://apps.apple.com/us/app/itspaint/id6796493980?utm_source=fatbobman%20weekly%20issue%20155&amp;utm_medium=web">App Store &#20813;&#36153;&#19979;&#36733;</a>&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0155-13">SwiftFairy&#65306;&#35753; Agent &#19981;&#20877;&#8220;&#35835;&#36807;&#23601;&#24536;&#8221;&#30340; SwiftUI &#23457;&#26597;&#24037;&#20855;</a></strong></h3><p>&#30001; <a href="https://x.com/natpanferova">Natalia Panferova</a> &#19982; <a href="https://x.com/hishnash">Matthaus Woolard</a> &#25171;&#36896;&#30340; macOS &#24037;&#20855;&#65292;&#36890;&#36807;&#26412;&#22320; MCP &#26381;&#21153;&#22120;&#20026;&#32534;&#30721; Agent &#25552;&#20379; Swift &#19982; SwiftUI &#20195;&#30721;&#23457;&#26597;&#12290;</p><p>&#19982;&#25226;&#22823;&#37327;&#35268;&#21017;&#20889;&#36827; Skill &#25110; <code>AGENTS.md</code>&#12289;&#20877;&#26399;&#24453; Agent &#22312;&#27491;&#30830;&#30340;&#26102;&#20505;&#24819;&#36215;&#23427;&#20204;&#19981;&#21516;&#65292;SwiftFairy &#23558;&#8220;&#21457;&#29616;&#38382;&#39064;&#8221;&#20132;&#32473;&#30830;&#23450;&#24615;&#30340;&#38745;&#24577;&#20998;&#26512;&#65306;&#23427;&#25226;&#20195;&#30721;&#35299;&#26512;&#20026;&#23616;&#37096;&#22270;&#65292;&#19982;&#22768;&#26126;&#24335;&#30340;&#38382;&#39064;&#27169;&#24335;&#36827;&#34892;&#21305;&#37197;&#65292;&#23558;&#21457;&#29616;&#31934;&#30830;&#23450;&#20301;&#21040;&#20195;&#30721;&#34892;&#65292;&#20877;&#25226;&#23545;&#24212;&#30340;&#35299;&#37322;&#21644;&#20462;&#22797;&#31034;&#20363;&#20132;&#32473; Agent&#12290;&#30693;&#35782;&#21482;&#22312;&#30495;&#27491;&#21629;&#20013;&#38382;&#39064;&#26102;&#25165;&#36827;&#20837;&#19978;&#19979;&#25991;&#65292;&#26082;&#36991;&#20813;&#20102; Agent &#8220;&#35835;&#36807;&#23601;&#24536;&#8221;&#65292;&#20063;&#20943;&#23569;&#20102; Token &#28040;&#32791;&#12290;</p><p>SwiftFairy &#30340;&#20215;&#20540;&#20063;&#24456;&#22823;&#31243;&#24230;&#26469;&#33258;&#35268;&#21017;&#26412;&#36523;&#12290;&#30446;&#21069;&#36825;&#20123;&#30693;&#35782;&#20197;&#8220;&#21367;&#36724;&#8221;&#65288;Scrolls&#65289;&#30340;&#24418;&#24335;&#32452;&#32455;&#65292;&#39318;&#25209;&#21253;&#25324; Proper SwiftUI&#12289;Performant Swift Charts &#19982; Modern Swift&#65292;&#20869;&#23481;&#26469;&#33258;&#20004;&#20301;&#20316;&#32773;&#22810;&#24180;&#31215;&#32047;&#30340;&#20070;&#31821;&#19982;&#25991;&#31456;&#65292;&#20197;&#21450; Natalia &#26366;&#21442;&#19982; Apple SwiftUI &#26680;&#24515;&#22242;&#38431;&#24037;&#20316;&#30340;&#32463;&#39564;&#12290;&#19982;&#35753;&#21478;&#19968;&#20010; LLM &#26469; Review &#30456;&#27604;&#65292;SwiftFairy &#26356;&#20687;&#26159;&#22312; Agent &#24037;&#20316;&#27969;&#20013;&#21152;&#20837;&#20102;&#19968;&#23618;&#20855;&#26377;&#39046;&#22495;&#30693;&#35782;&#12289;&#32467;&#26524;&#21487;&#37325;&#22797;&#30340;&#38745;&#24577;&#23457;&#26597;&#12290;</p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #154]]></title><description><![CDATA[A &#8220;Native&#8221; Debate Over SwiftUI Animation]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 21 Sep 2026 12:01:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4WJy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4WJy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4WJy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54560,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/216668352?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4WJy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!4WJy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe85bd61f-2905-4c7b-b26b-e54615b5a4fd_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@haroldjonker?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Harold Jonker</a><span> on </span><a href="https://unsplash.com/photos/yellow-and-black-pendant-lamp-cTwocNh2slg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>A &#8220;Native&#8221; Debate Over SwiftUI Animation</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-154/">Read on web &#8594;</a></p><p><span>Last week, a </span><a href="https://x.com/kzzzf/status/2099985361271144686"><span>post</span></a><span> by React Native core developer Krzysztof Magiera sparked a lively discussion across the Apple developer community. In the post, he demonstrated an example where, with the main thread blocked, a back-and-forth animation in UIKit continued to run normally while the equivalent SwiftUI animation came to a halt. He attributed this to SwiftUI not using Core Animation&#8217;s render-server animation model and instead advancing animations within the app process, raising the question of whether SwiftUI is truly &#8220;native.&#8221; He later added that, in React Native, developers can still use Core Animation to create animations that continue running even when the main thread is blocked.</span></p><p><span>SwiftUI co-creator and early core developer Kyle Macomber responded with a different </span><a href="https://x.com/kylemacomber/status/2100029347419877794"><span>perspective</span></a><span>. He explained that, from the beginning, SwiftUI deliberately moved away from server-side animation&#8212;where Core Animation advances animations on the render server&#8212;and instead chose to compute and advance animation values in the client/app process in exchange for better interruptibility and interactivity. This was not a technical regression, but a deliberate design trade-off. (SwiftUI did not abandon Core Animation itself; Core Animation still participates in the subsequent rendering process. What changed is who advances the animation.)</span></p><p><span>Ease of animation has always been one of SwiftUI&#8217;s signature strengths, and the continued evolution of its spring animations in recent years has further improved the naturalness of transitions and the expressiveness of interactive motion. For a reactive framework, I think advancing animations on the client side is entirely understandable. The trade-off, of course, is equally clear: as Krzysztof&#8217;s example demonstrates, when animation advancement depends on the app process, it becomes more susceptible to a busy main thread and also consumes more computational resources on the client side.</span></p><p><span>That said, client-side animation does not mean that all animation sampling calculations must happen on the main thread. As SwiftUI has evolved, some computationally intensive work involving animations and </span><code>Shape</code><span> can now be moved to background threads, reducing pressure on the main thread. Still, because animation advancement remains within the app process, and asynchronous computation is subject to constraints such as state updates and the rendering pipeline, animations can still stall when the main thread is completely blocked. Despite this &#8220;drawback,&#8221; starting with iOS 18, UIKit and AppKit also began adopting this client-side animation model: their new animation APIs can directly use SwiftUI&#8217;s </span><code>Animation</code><span> and are driven by the same underlying animation infrastructure rather than generating traditional </span><code>CAAnimation</code><span> objects.</span></p><p><span>This discussion presented an interesting situation: on the surface, the debate was about whether SwiftUI is truly &#8220;native,&#8221; but underneath it revealed a difference in framework design philosophies.</span></p><p><span>As Apple&#8217;s UI framework for the future, SwiftUI chose to depart from the established path, moving away from dependence on Core Animation&#8217;s render-server animation model in exchange for more flexible and expressive animation capabilities. In fact, John Harper, the creator of Core Animation, was himself one of SwiftUI&#8217;s co-creators. So this choice clearly wasn&#8217;t made out of unfamiliarity with Core Animation, but rather as an architectural decision made with an understanding of both its strengths and limitations. It also brought a less obvious advantage: some of SwiftUI&#8217;s core capabilities became further decoupled from the specific implementation details of Apple platforms. Although Apple has not open-sourced SwiftUI, architecturally, some of its core ideas are not inherently limited to Apple platforms.</span></p><p><span>From the React Native perspective, Krzysztof&#8217;s argument also has its rationale. As a cross-platform framework, one of React Native&#8217;s important goals is to make the best possible use of the capabilities each platform already provides, allowing apps to behave and perform more like &#8220;locals&#8221; on each platform.</span></p><p><span>What began as a discussion about &#8220;what counts as native&#8221; ultimately led core developers from both sides to explain how they think about UI animation architecture. As someone happily watching from the sidelines, I learned quite a bit from it as well.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-153/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-pbxproj-to-xcproj/?utm_source=fatbobman%20weekly%20issue%20154&amp;utm_medium=web"><span>From pbxproj to xcproj: Xcode Project Configuration Gets a JSON Format</span></a></strong></h3><p><span>I&#8217;ve been waiting for Xcode 27.1, hoping to test how my apps adapt in the iPhone Duo simulator. Amusingly, 27.1 never arrived &#8212; Apple shipped 27.2 beta first instead. The iPhone Duo simulator is still missing, but the new </span><code>project.xcproj</code><span> caught my eye. What it replaces is </span><code>project.pbxproj</code><span>, the build graph inside the </span><code>.xcodeproj</code><span> bundle, not the bundle itself. What&#8217;s good about it, what does it fix, and what stays the same? This article takes a look.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-01"><span>How we built Devin&#8217;s Mac</span></a></strong></h3><p><span>When an AI agent runs locally, permissions have long since been granted, the toolchain is ready, and a human can dismiss any dialog that appears. Move to the cloud and every one of those assumptions has to be rebuilt. The payoff isn&#8217;t doing something the local machine can&#8217;t &#8212; it&#8217;s turning the development environment itself into a resource you can assign to an agent: tasks run asynchronously, stay isolated from one another, pause and preserve their state when idle, resume on demand, and scale more easily to several agents working in parallel. </span><a href="https://x.com/jkelleyrtp"><span>Jon Kelley</span></a><span> walks through building Devin&#8217;s macOS cloud environment, covering virtual machines on Virtualization.framework, disk snapshots, network isolation, pre-configured environments and permissions, live streaming of the desktop and Simulator, and computer use driven by the accessibility tree. That last point is especially instructive for Apple developers: good accessibility support also gives agents a structured interface for automated verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-02"><span>iOS 27: CrashReportExtension Framework</span></a></strong></h3><p><span>Traditional crash handling has an awkward problem: by the time the signal handler runs, the process it lives in may already be unreliable &#8212; memory may be corrupted, locks may still be held, and many everyday APIs can&#8217;t be called safely. The new CrashReportExtension in iOS 27 changes that execution model. After the app crashes, the system launches a separate extension and hands it a read-only </span><code>CrashedProcess</code><span> for inspecting the crashed process.</span></p><p><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> demonstrates how to create and use the extension, along with several practical judgments. The API complements Apple&#8217;s </span><code>.ips</code><span> reports rather than replacing them, and suits teams that need their own backend, correlation with business context, or on-device pre-analysis. The extension itself should stay small, doing nothing more than generating and persisting a report; uploads and retries belong in the host app, with the two sharing storage through an App Group. For most indie developers, system crash reports plus MetricKit remain sufficient.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-03"><span>How SwiftUI animation works</span></a></strong></h3><p><span>For animation, developers only change state and specify an animation function, leaving the rest to SwiftUI. But how do those declarations become a continuous sequence of frames on screen? Starting from Transaction and AttributeGraph, and drawing on his work on OpenSwiftUI, </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> analyzes step by step how SwiftUI creates an animation context, computes intermediate states, and keeps updating views and layout as the animation runs.</span></p><p><span>Unlike the conventional approach of leaving interpolation mostly to the render server, many SwiftUI animations advance within the app process. Because interpolation happens inside the view graph, any value conforming to Animatable can be sampled, which lets layout, Shape, and much more participate in animation, while the render server mainly handles layer properties. The analysis of the </span><code>CABasicAnimation</code><span> on the asynchronous commit path is particularly worth reading: it carries only the current frame&#8217;s sampled value and is replaced on the next frame &#8212; the presence of a CA animation object on screen does not mean the animation&#8217;s clock has been handed to Core Animation. This adds useful detail to the debate over whether SwiftUI animation is &#8220;native,&#8221; discussed in this issue&#8217;s editorial.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-04"><span>SwiftUI: Some New APIs/ContainerViews Useful For Duo!</span></a></strong></h3><p><span>The many poses of iPhone Duo present new challenges for toolbars. To make full use of the wider screen while preserving vertical space for content, the system moves controls normally placed at the top and bottom to the side of the screen in certain poses. But text buttons, custom views, and other traditional toolbar content don&#8217;t always suit a vertical arrangement, and the toolbar and tab bar may have to compete for limited side space. iOS 27.1 addresses this with APIs including </span><code>ToolbarItemAxisBehavior</code><span>, </span><code>ToolbarVerticalBehavior</code><span>, </span><code>ToolbarVerticalCompressionBehavior</code><span>, and </span><code>toolbarVerticalEdge</code><span>, giving developers finer control over a toolbar&#8217;s orientation, placement, and compression strategy when space runs short. </span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> demonstrates how these new APIs behave, with code and videos.</span></p><p><span>What these APIs have in common is that they let developers declare a preference rather than dictate a result. Faced with the range of poses Duo introduces, describing the relationships between pieces of content and your layout preferences &#8212; and letting SwiftUI decide the final presentation based on the actual environment &#8212; beats writing layouts for specific device states.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-05"><span>Sheets and fold avoidance on iPhone Duo</span></a></strong></h3><p><span>When iPhone Duo is partially folded, the crease down the middle forms a region poorly suited to interaction, and buttons or other controls that land there become awkward to operate. Using sheets as his example, </span><a href="https://x.com/sarunw"><span>Sarun Wongpatcharapakorn</span></a><span> shows how a single interface adjusts its size, position, and toolbar across Duo&#8217;s closed, open, landscape, portrait, and partially folded poses. System components including sheets, alerts, and menus already avoid the fold without developer intervention. For developers, that means reaching for system components first also means inheriting this adaptive behavior across device poses for free.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-06"><span>Vapor 5 Beta Released</span></a></strong></h3><p><span>Ten years after Vapor was born and six and a half years after Vapor 4 shipped, the community finally has the first beta of Vapor 5. It amounts to a near-complete rewrite &#8212; two years of work and roughly 49,000 lines changed. The central change is saying goodbye to </span><code>EventLoop</code><span> and </span><code>EventLoopFuture</code><span> and moving fully to Swift Concurrency built on structured concurrency, with NIO now largely hidden from the public APIs.</span></p><p><span>Vapor 5 also integrates more deeply with Swift HTTP Types, Swift Configuration, and Swift Service Lifecycle, and adds the experimental </span><code>VaporMacros</code><span> for compile-time type checking of routes and authentication. It requires Swift 6.4 and remains in beta. For a fuller account of what changed, see </span><a href="https://hachyderm.io/@0xTim"><span>Tim Condon</span></a><span>&#8216;s </span><a href="https://blog.vapor.codes/posts/whats-new-in-vapor-5-beta/"><span>What&#8217;s New in Vapor 5 Beta</span></a><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-07"><span>Hinge: Set the Duo Simulator&#8217;s Fold Angle from the Command Line</span></a></strong></h3><p><span>Xcode 27.1&#8217;s Device Hub can adjust the fold angle of the iPhone Duo Simulator (hold Option to reveal it), but neither </span><code>simctl</code><span> nor </span><code>devicectl</code><span> offers a corresponding command. Hinge, from </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span>, fills the gap: it sets fold angles from 0 to 180&#176; on the command line, and supports opening, closing, half-folding, and sweeping continuously between angles. Hinge also ships an Agent Skill, letting a coding agent change Duo&#8217;s fold state itself while verifying an app.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-08"><span>Enriched Markdown: Cross-Platform Markdown Rendering and Editing Without a WebView</span></a></strong></h3><p><span>The usual way to handle Markdown on mobile is to wrap it in a WebView. Enriched Markdown, from Software Mansion, takes a more thorough route: it renders Markdown and supports rich-text editing through each platform&#8217;s native text capabilities, and can emit clean Markdown again once the content has been edited.</span></p><p><span>It offers a standalone SwiftUI SDK, rendering Markdown with TextKit 2 and md4c, and also covers React Native, Android, and the web. Rather than settling for &#8220;Markdown that displays,&#8221; Enriched Markdown emphasizes a native feel: text selects normally, links, images, and code blocks hook into system menus, and the library supports VoiceOver, TalkBack, Dynamic Type, and right-to-left writing.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-154?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#19968;&#22330;&#20851;&#20110; SwiftUI &#21160;&#30011;&#30340;&#8220;&#21407;&#29983;&#8221;&#20043;&#20105;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-154/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#21608;&#65292;React Native &#26680;&#24515;&#24320;&#21457;&#32773; Krzysztof Magiera &#30340;&#19968;&#26465; &#8288;</span><a href="https://x.com/kzzzf/status/2099985361271144686"><span>&#25512;&#25991;</span></a><span> &#22312;&#33529;&#26524;&#24320;&#21457;&#29983;&#24577;&#20013;&#24341;&#21457;&#28909;&#28872;&#35752;&#35770;&#12290;&#25512;&#25991;&#20013;&#20182;&#23637;&#31034;&#20102;&#19968;&#20010;&#31034;&#20363;&#65306;&#22312;&#20027;&#32447;&#31243;&#38459;&#22622;&#30340;&#24773;&#20917;&#19979;&#65292;UIKit &#30340;&#19968;&#20010;&#24448;&#36820;&#21160;&#30011;&#20173;&#33021;&#27491;&#24120;&#25191;&#34892;&#65292;&#32780; SwiftUI &#30340;&#21160;&#30011;&#21017;&#20572;&#28382;&#20102;&#12290;&#20182;&#35748;&#20026;&#21407;&#22240;&#22312;&#20110; SwiftUI &#27809;&#26377;&#20351;&#29992; Core Animation &#30340; render-server animation&#65292;&#32780;&#26159;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#25512;&#36827;&#21160;&#30011;&#65292;&#22240;&#27492;&#23545; SwiftUI &#26159;&#21542;&#36275;&#22815;&#8220;&#21407;&#29983;&#8221;&#25552;&#20986;&#20102;&#36136;&#30097;&#65307;&#38543;&#21518;&#21448;&#34920;&#31034;&#65292;&#22312; React Native &#20013;&#65292;&#24320;&#21457;&#32773;&#20173;&#21487;&#36890;&#36807; Core Animation &#21019;&#24314;&#19981;&#21463;&#20027;&#32447;&#31243;&#38459;&#22622;&#24433;&#21709;&#30340;&#21160;&#30011;&#12290;</span></p><p><span>SwiftUI &#20849;&#21516;&#21019;&#36896;&#32773;&#12289;&#26089;&#26399;&#26680;&#24515;&#24320;&#21457;&#32773; Kyle Macomber &#23545;&#27492;&#22238;&#24212;&#20102;&#19981;&#21516;&#30340; &#8288;</span><a href="https://x.com/kylemacomber/status/2100029347419877794"><span>&#35266;&#28857;</span></a><span>&#12290;&#20182;&#35299;&#37322;&#35828;&#65292;SwiftUI &#22312;&#35774;&#35745;&#20043;&#21021;&#23601;&#26377;&#24847;&#25918;&#24323;&#20102; Server-side Animation&#65288;&#30001; Core Animation &#22312; render server &#20013;&#25512;&#36827;&#21160;&#30011;&#65289;&#65292;&#32780;&#36873;&#25321;&#35753;&#21160;&#30011;&#20540;&#22312; client / app process &#20013;&#35745;&#31639;&#21644;&#25512;&#36827;&#65292;&#20197;&#25442;&#21462;&#26356;&#22909;&#30340;&#21487;&#20013;&#26029;&#24615;&#19982;&#20132;&#20114;&#24615;&#12290;&#36825;&#24182;&#38750;&#25216;&#26415;&#19978;&#30340;&#36864;&#27493;&#65292;&#32780;&#26159;&#19968;&#39033;&#35774;&#35745;&#21462;&#33293;&#65288;SwiftUI &#24182;&#27809;&#26377;&#25918;&#24323; Core Animation&#65292;&#23427;&#20173;&#28982;&#21442;&#19982;&#21518;&#32493;&#30340;&#28210;&#26579;&#36807;&#31243;&#65292;&#25913;&#21464;&#30340;&#21482;&#26159;&#21160;&#30011;&#30001;&#35841;&#26469;&#25512;&#36827;&#65289;&#12290;</span></p><p><span>&#21160;&#30011;&#30340;&#26131;&#29992;&#24615;&#19968;&#30452;&#26159; SwiftUI &#30340;&#26631;&#24535;&#24615;&#29305;&#33394;&#20043;&#19968;&#65292;&#36817;&#24180;&#26469;&#19981;&#26029;&#23436;&#21892;&#30340;&#24377;&#31783;&#21160;&#30011;&#65292;&#21448;&#36827;&#19968;&#27493;&#25552;&#21319;&#20102;&#21160;&#30011;&#34900;&#25509;&#30340;&#33258;&#28982;&#31243;&#24230;&#21644;&#20132;&#20114;&#34920;&#29616;&#21147;&#12290;&#20316;&#20026;&#19968;&#20010;&#21709;&#24212;&#24335;&#26694;&#26550;&#65292;&#25226;&#21160;&#30011;&#25512;&#36827;&#25918;&#22312; client &#31471;&#65292;&#25105;&#35748;&#20026;&#23436;&#20840;&#21487;&#20197;&#29702;&#35299;&#12290;&#24403;&#28982;&#65292;&#20195;&#20215;&#20063;&#24456;&#26126;&#30830;&#65306;&#27491;&#22914; Krzysztof &#30340;&#31034;&#20363;&#25152;&#31034;&#65292;&#24403;&#21160;&#30011;&#25512;&#36827;&#20381;&#36182;&#24212;&#29992;&#36827;&#31243;&#26102;&#65292;&#23427;&#26356;&#23481;&#26131;&#21463;&#21040;&#20027;&#32447;&#31243;&#32321;&#24537;&#30340;&#24433;&#21709;&#65292;&#20063;&#20250;&#21344;&#29992;&#26356;&#22810; client &#31471;&#30340;&#35745;&#31639;&#36164;&#28304;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;client-side animation &#24182;&#19981;&#24847;&#21619;&#30528;&#25152;&#26377;&#25554;&#20540;&#35745;&#31639;&#37117;&#24517;&#39035;&#21457;&#29983;&#22312;&#20027;&#32447;&#31243;&#12290;&#38543;&#30528; SwiftUI &#19981;&#26029;&#28436;&#36827;&#65292;&#37096;&#20998;&#21160;&#30011;&#20197;&#21450; Shape &#31561;&#35745;&#31639;&#23494;&#38598;&#22411;&#24037;&#20316;&#24050;&#32463;&#21487;&#20197;&#31227;&#21040;&#21518;&#21488;&#32447;&#31243;&#65292;&#20197;&#20943;&#36731;&#20027;&#32447;&#31243;&#30340;&#21387;&#21147;&#12290;&#19981;&#36807;&#65292;&#30001;&#20110;&#21160;&#30011;&#30340;&#25512;&#36827;&#20173;&#28982;&#23646;&#20110;&#24212;&#29992;&#36827;&#31243;&#65292;&#24322;&#27493;&#35745;&#31639;&#20063;&#21463;&#21040;&#29366;&#24577;&#26356;&#26032;&#21644;&#28210;&#26579;&#27969;&#31243;&#31561;&#26465;&#20214;&#30340;&#38480;&#21046;&#65292;&#22240;&#27492;&#24403;&#20027;&#32447;&#31243;&#34987;&#23436;&#20840;&#38459;&#22622;&#26102;&#65292;&#21160;&#30011;&#20381;&#28982;&#21487;&#33021;&#20572;&#28382;&#12290;&#23613;&#31649;&#23384;&#22312;&#36825;&#31181;&#8220;&#24330;&#31471;&#8221;&#65292;&#20294;&#20174; iOS 18 &#24320;&#22987;&#65292;UIKit &#21644; AppKit &#20063;&#24320;&#22987;&#37319;&#32435;&#36825;&#22871; client-side animation &#27169;&#22411;&#65306;&#26032;&#30340;&#21160;&#30011; API &#21487;&#20197;&#30452;&#25509;&#20351;&#29992; SwiftUI &#30340; Animation&#65292;&#24182;&#30001;&#21516;&#19968;&#22871;&#21160;&#30011;&#22522;&#30784;&#35774;&#26045;&#39537;&#21160;&#65292;&#32780;&#19981;&#20877;&#29983;&#25104;&#20256;&#32479;&#30340; CAAnimation&#12290;</span></p><p><span>&#26412;&#27425;&#35752;&#35770;&#21576;&#29616;&#20986;&#19968;&#20010;&#26377;&#36259;&#30340;&#22330;&#26223;&#65306;&#34920;&#38754;&#19978;&#22312;&#20105;&#35770; SwiftUI &#26159;&#21542;&#8220;&#21407;&#29983;&#8221;&#65292;&#23454;&#38469;&#23637;&#29616;&#30340;&#21364;&#26159;&#20004;&#31181;&#26694;&#26550;&#35774;&#35745;&#29702;&#24565;&#30340;&#24046;&#24322;&#12290;</span></p><p><span>&#20316;&#20026;&#33529;&#26524;&#38754;&#21521;&#26410;&#26469;&#30340; UI &#26694;&#26550;&#65292;SwiftUI &#22312;&#35774;&#35745;&#26102;&#36873;&#25321;&#36208;&#20986;&#26082;&#26377;&#36335;&#24452;&#65292;&#25918;&#24323;&#23545; Core Animation render-server animation &#27169;&#22411;&#30340;&#20381;&#36182;&#65292;&#20197;&#25442;&#21462;&#26356;&#28789;&#27963;&#12289;&#26356;&#24378;&#22823;&#30340;&#21160;&#30011;&#34920;&#36798;&#33021;&#21147;&#12290;&#20107;&#23454;&#19978;&#65292;Core Animation &#30340;&#21019;&#36896;&#32773; John Harper &#26412;&#20154;&#20063;&#26159; SwiftUI &#30340;&#20849;&#21516;&#21019;&#36896;&#32773;&#20043;&#19968;&#65292;&#36825;&#39033;&#36873;&#25321;&#26174;&#28982;&#19981;&#26159;&#22240;&#20026;&#19981;&#20102;&#35299; Core Animation&#65292;&#32780;&#26159;&#22312;&#29702;&#35299;&#20854;&#20248;&#21183;&#19982;&#23616;&#38480;&#20043;&#21518;&#20570;&#20986;&#30340;&#26550;&#26500;&#20915;&#23450;&#12290;&#36825;&#36824;&#24102;&#26469;&#20102;&#19968;&#20010;&#38544;&#24418;&#20248;&#21183;&#65306;SwiftUI &#30340;&#37096;&#20998;&#26680;&#24515;&#33021;&#21147;&#19982;&#33529;&#26524;&#24179;&#21488;&#30340;&#20855;&#20307;&#23454;&#29616;&#24471;&#20197;&#36827;&#19968;&#27493;&#35299;&#32806;&#12290;&#23613;&#31649;&#33529;&#26524;&#24182;&#26410;&#23558; SwiftUI &#24320;&#28304;&#65292;&#20294;&#20174;&#26550;&#26500;&#19978;&#30475;&#65292;&#23427;&#30340;&#19968;&#20123;&#26680;&#24515;&#24605;&#24819;&#24182;&#19981;&#22825;&#28982;&#23616;&#38480;&#20110;&#33529;&#26524;&#24179;&#21488;&#12290;</span></p><p><span>&#32780;&#20174; React Native &#30340;&#35282;&#24230;&#30475;&#65292;Krzysztof &#30340;&#34920;&#36848;&#20063;&#26377;&#20854;&#21512;&#29702;&#24615;&#12290;&#20316;&#20026;&#19968;&#20010;&#36328;&#24179;&#21488;&#26694;&#26550;&#65292;React Native &#30340;&#37325;&#35201;&#30446;&#26631;&#20043;&#19968;&#65292;&#23601;&#26159;&#22312;&#19981;&#21516;&#24179;&#21488;&#19978;&#23613;&#21487;&#33021;&#21033;&#29992;&#24179;&#21488;&#24050;&#32463;&#25552;&#20379;&#30340;&#33021;&#21147;&#65292;&#35753;&#24212;&#29992;&#22312;&#34892;&#20026;&#21644;&#24615;&#33021;&#19978;&#26356;&#20687;&#8220;&#26412;&#22320;&#20154;&#8221;&#12290;</span></p><p><span>&#19968;&#20010;&#26368;&#21021;&#22260;&#32469;&#8220;&#20160;&#20040;&#25165;&#31639;&#21407;&#29983;&#8221;&#30340;&#35752;&#35770;&#65292;&#26368;&#32456;&#24341;&#20986;&#20102;&#20004;&#36793;&#26680;&#24515;&#24320;&#21457;&#32773;&#23545; UI &#21160;&#30011;&#26550;&#26500;&#30340;&#29702;&#35299;&#19982;&#38416;&#36848;&#12290;&#20316;&#20026;&#19968;&#20010;&#21507;&#29916;&#32676;&#20247;&#65292;&#25105;&#20063;&#20174;&#20013;&#25910;&#33719;&#19981;&#23569;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-153/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-pbxproj-to-xcproj/?utm_source=fatbobman%20weekly%20issue%20154&amp;utm_medium=web"><span>&#20174; pbxproj &#21040; xcproj&#65306;Xcode &#24037;&#31243;&#37197;&#32622;&#36814;&#26469; JSON &#26684;&#24335;</span></a></strong></h3><p><span>&#26368;&#36817;&#19968;&#30452;&#22312;&#31561;&#24453; Xcode 27.1 &#30340;&#21040;&#26469;&#65292;&#20197;&#20415;&#22312; iPhone Duo &#30340;&#27169;&#25311;&#22120;&#20013;&#27979;&#35797;&#19968;&#19979;&#24212;&#29992;&#30340;&#36866;&#37197;&#24773;&#20917;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;27.1 &#27809;&#31561;&#21040;&#65292;&#33529;&#26524;&#29575;&#20808;&#21457;&#24067;&#20102; 27.2 beta&#12290;&#23613;&#31649; iPhone Duo &#27169;&#25311;&#22120;&#20381;&#28982;&#32570;&#24109;&#65292;&#20294;&#26032;&#22686;&#30340; </span><code>project.xcproj</code><span> &#20196;&#20154;&#30524;&#21069;&#19968;&#20142;&#12290;&#23427;&#26367;&#20195;&#30340;&#26159; </span><code>.xcodeproj</code><span> &#21253;&#37324;&#30340;&#37027;&#20221;&#26500;&#24314;&#22270; </span><code>project.pbxproj</code><span>&#65292;&#32780;&#19981;&#26159;&#25972;&#20010;&#24037;&#31243;&#21253;&#12290;&#23427;&#26377;&#21738;&#20123;&#20142;&#28857;&#65292;&#35299;&#20915;&#20102;&#20160;&#20040;&#38382;&#39064;&#65292;&#21448;&#26377;&#21738;&#20123;&#20107;&#24773;&#27809;&#26377;&#25913;&#21464;&#65292;&#26412;&#25991;&#23558;&#23545;&#27492;&#36827;&#34892;&#25506;&#35752;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-01"><span>&#20026; Devin &#26500;&#24314;&#20113;&#19978; Mac &#24320;&#21457;&#29615;&#22659; (How we built Devin&#8217;s Mac)</span></a></strong></h3><p><span>&#24403; AI Agent &#22312;&#26412;&#22320;&#36816;&#34892;&#26102;&#65292;&#26435;&#38480;&#26089;&#24050;&#25480;&#20104;&#65292;&#24037;&#20855;&#38142;&#24050;&#32463;&#23601;&#32490;&#65292;&#36935;&#21040;&#24377;&#31383;&#20063;&#21487;&#20197;&#20154;&#24037;&#24178;&#39044;&#12290;&#25644;&#21040;&#20113;&#31471;&#21518;&#65292;&#36825;&#20123;&#29702;&#25152;&#24403;&#28982;&#30340;&#26465;&#20214;&#37117;&#38656;&#35201;&#37325;&#26032;&#26500;&#24314;&#12290;&#25442;&#26469;&#30340;&#22909;&#22788;&#24182;&#19981;&#22312;&#20110;&#33021;&#20570;&#21040;&#26412;&#22320;&#20570;&#19981;&#21040;&#30340;&#20107;&#65292;&#32780;&#26159;&#35753;&#24320;&#21457;&#29615;&#22659;&#26412;&#36523;&#25104;&#20026;&#21487;&#20197;&#20998;&#37197;&#32473; Agent &#30340;&#36164;&#28304;&#65306;&#20219;&#21153;&#21487;&#20197;&#24322;&#27493;&#36816;&#34892;&#12289;&#24444;&#27492;&#38548;&#31163;&#65292;&#38386;&#32622;&#26102;&#26242;&#20572;&#24182;&#20445;&#23384;&#29366;&#24577;&#65292;&#38656;&#35201;&#26102;&#20877;&#24674;&#22797;&#65292;&#20063;&#26356;&#23481;&#26131;&#25903;&#25345;&#22810;&#20010; Agent &#24182;&#34892;&#24037;&#20316;&#12290;</span><a href="https://x.com/jkelleyrtp"><span>Jon Kelley</span></a><span> &#22312;&#25991;&#20013;&#20171;&#32461;&#20102;&#20026; Devin &#26500;&#24314; macOS &#20113;&#31471;&#29615;&#22659;&#30340;&#36807;&#31243;&#65292;&#28085;&#30422;&#22522;&#20110; Virtualization.framework &#30340;&#34394;&#25311;&#26426;&#12289;&#30913;&#30424;&#24555;&#29031;&#12289;&#32593;&#32476;&#38548;&#31163;&#12289;&#29615;&#22659;&#19982;&#26435;&#38480;&#39044;&#37197;&#32622;&#12289;&#26700;&#38754;&#19982; Simulator &#30340;&#23454;&#26102;&#20018;&#27969;&#65292;&#20197;&#21450;&#20511;&#21161;&#26080;&#38556;&#30861;&#26641;&#23454;&#29616;&#30340;&#35745;&#31639;&#26426;&#25805;&#20316;&#12290;&#26368;&#21518;&#19968;&#28857;&#23545;&#33529;&#26524;&#24320;&#21457;&#32773;&#23588;&#20854;&#26377;&#21551;&#21457;&#65306;&#20570;&#22909;&#26080;&#38556;&#30861;&#25903;&#25345;&#65292;&#20063;&#26159;&#22312;&#20026; Agent &#30340;&#33258;&#21160;&#21270;&#39564;&#35777;&#25552;&#20379;&#32467;&#26500;&#21270;&#25509;&#21475;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-02"><span>iOS 27: CrashReportExtension Framework</span></a></strong></h3><p><span>&#20256;&#32479;&#30340;&#23849;&#28291;&#22788;&#29702;&#26377;&#19968;&#20010;&#26840;&#25163;&#30340;&#38382;&#39064;&#65306;&#24403; signal handler &#24320;&#22987;&#24037;&#20316;&#26102;&#65292;&#23427;&#25152;&#22312;&#30340;&#36827;&#31243;&#26412;&#36523;&#21487;&#33021;&#24050;&#32463;&#22788;&#20110;&#19981;&#21487;&#38752;&#29366;&#24577;&#65292;&#20869;&#23384;&#21487;&#33021;&#25439;&#22351;&#12289;&#38145;&#21487;&#33021;&#27809;&#26377;&#37322;&#25918;&#65292;&#24456;&#22810;&#24179;&#26102;&#20351;&#29992;&#30340; API &#20063;&#26080;&#27861;&#23433;&#20840;&#35843;&#29992;&#12290;iOS 27 &#26032;&#22686;&#30340; CrashReportExtension &#25913;&#21464;&#20102;&#36825;&#19968;&#25191;&#34892;&#27169;&#22411;&#12290;&#24403; App &#23849;&#28291;&#21518;&#65292;&#31995;&#32479;&#20250;&#21551;&#21160;&#19968;&#20010;&#29420;&#31435;&#30340; Extension&#65292;&#24182;&#36890;&#36807;&#21482;&#35835;&#30340; </span><code>CrashedProcess</code><span> &#35753;&#23427;&#26816;&#26597;&#24050;&#32463;&#23849;&#28291;&#30340;&#36827;&#31243;&#12290;</span></p><p><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> &#22312;&#25991;&#20013;&#23436;&#25972;&#28436;&#31034;&#20102;&#36825;&#20010;&#25193;&#23637;&#30340;&#21019;&#24314;&#19982;&#20351;&#29992;&#65292;&#20063;&#32473;&#20986;&#20102;&#20960;&#26465;&#21153;&#23454;&#30340;&#21028;&#26029;&#12290;&#35813; API &#26159;&#23545;&#31995;&#32479; </span><code>.ips</code><span> &#25253;&#21578;&#30340;&#34917;&#20805;&#32780;&#38750;&#26367;&#20195;&#65292;&#36866;&#21512;&#38656;&#35201;&#33258;&#26377;&#21518;&#31471;&#12289;&#19994;&#21153;&#19978;&#19979;&#25991;&#20851;&#32852;&#25110;&#35774;&#22791;&#31471;&#39044;&#20998;&#26512;&#30340;&#22242;&#38431;&#12290;&#25193;&#23637;&#26412;&#36523;&#24212;&#23613;&#37327;&#31934;&#31616;&#65292;&#21482;&#36127;&#36131;&#29983;&#25104;&#24182;&#25345;&#20037;&#21270;&#25253;&#21578;&#65292;&#19978;&#20256;&#12289;&#37325;&#35797;&#31561;&#24037;&#20316;&#20132;&#32473;&#20027;&#24212;&#29992;&#65292;&#20004;&#32773;&#36890;&#36807; App Group &#20849;&#20139;&#23384;&#20648;&#12290;&#23545;&#22810;&#25968;&#29420;&#31435;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#31995;&#32479;&#23849;&#28291;&#25253;&#21578;&#21152;&#19978; MetricKit &#20381;&#28982;&#36275;&#22815;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-03"><span>SwiftUI &#21160;&#30011;&#30340;&#36816;&#20316;&#26426;&#21046; (How SwiftUI animation works)</span></a></strong></h3><p><span>&#23545;&#20110;&#21160;&#30011;&#65292;&#24320;&#21457;&#32773;&#21482;&#38656;&#25913;&#21464;&#29366;&#24577;&#24182;&#35774;&#32622;&#21160;&#30011;&#20989;&#25968;&#65292;&#21097;&#19979;&#30340;&#24037;&#20316;&#20415;&#20132;&#32473; SwiftUI&#12290;&#20294;&#36825;&#20123;&#22768;&#26126;&#26368;&#32456;&#26159;&#22914;&#20309;&#36716;&#21270;&#25104;&#23631;&#24149;&#19978;&#19968;&#24103;&#24103;&#36830;&#32493;&#21464;&#21270;&#30340;&#30011;&#38754;&#65311;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#20174; Transaction &#21644; AttributeGraph &#20986;&#21457;&#65292;&#32467;&#21512; OpenSwiftUI &#30340;&#24320;&#21457;&#32463;&#39564;&#65292;&#36880;&#27493;&#20998;&#26512; SwiftUI &#22914;&#20309;&#21019;&#24314;&#21160;&#30011;&#19978;&#19979;&#25991;&#12289;&#35745;&#31639;&#20013;&#38388;&#29366;&#24577;&#65292;&#24182;&#22312;&#21160;&#30011;&#36807;&#31243;&#20013;&#25345;&#32493;&#26356;&#26032;&#35270;&#22270;&#19982;&#24067;&#23616;&#12290;</span></p><p><span>&#19982;&#23558;&#21160;&#30011;&#25554;&#20540;&#20027;&#35201;&#20132;&#32473; render server &#30340;&#20256;&#32479;&#26041;&#24335;&#19981;&#21516;&#65292;SwiftUI &#30340;&#35768;&#22810;&#21160;&#30011;&#38656;&#35201;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#25345;&#32493;&#25512;&#36827;&#12290;&#30001;&#20110;&#25554;&#20540;&#21457;&#29983;&#22312;&#35270;&#22270;&#22270;&#20869;&#37096;&#65292;&#20219;&#20309;&#28385;&#36275; Animatable &#30340;&#20540;&#37117;&#33021;&#34987;&#37319;&#26679;&#65292;&#24067;&#23616;&#12289;Shape &#31561;&#26356;&#22810;&#29366;&#24577;&#22240;&#27492;&#24471;&#20197;&#21442;&#19982;&#21160;&#30011;&#65292;&#32780; render server &#20027;&#35201;&#22788;&#29702;&#22270;&#23618;&#23646;&#24615;&#12290;&#25991;&#20013;&#23545;&#24322;&#27493;&#25552;&#20132;&#36335;&#24452;&#20013; </span><code>CABasicAnimation</code><span> &#30340;&#20998;&#26512;&#23588;&#20854;&#20540;&#24471;&#19968;&#35835;&#65306;&#23427;&#21482;&#25215;&#36733;&#24403;&#21069;&#24103;&#30340;&#37319;&#26679;&#32467;&#26524;&#65292;&#19979;&#19968;&#24103;&#20415;&#20250;&#34987;&#26367;&#25442;&#8212;&#8212;&#23631;&#24149;&#19978;&#20986;&#29616;&#20102; CA &#21160;&#30011;&#23545;&#35937;&#65292;&#24182;&#19981;&#24847;&#21619;&#30528;&#21160;&#30011;&#30340;&#26102;&#38047;&#24050;&#32463;&#20132;&#32473;&#20102; Core Animation&#12290;&#36825;&#20063;&#20026;&#26412;&#26399;&#21608;&#35780;&#20013;&#25552;&#21040;&#30340; SwiftUI &#21160;&#30011;&#26159;&#21542;&#20026;&#8220;&#21407;&#29983;&#8221;&#20043;&#20105;&#25552;&#20379;&#20102;&#26356;&#22810;&#32454;&#33410;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-04"><span>&#20026; iPhone Duo &#20934;&#22791;&#30340;&#26032; API (SwiftUI: Some New APIs/ContainerViews Useful For Duo!)</span></a></strong></h3><p><span>iPhone Duo &#30340;&#22810;&#31181;&#20351;&#29992;&#24418;&#24577;&#32473; Toolbar &#24102;&#26469;&#20102;&#26032;&#30340;&#25361;&#25112;&#12290;&#20026;&#20102;&#20805;&#20998;&#21033;&#29992;&#26356;&#23485;&#30340;&#23631;&#24149;&#24182;&#20445;&#30041;&#32437;&#21521;&#20869;&#23481;&#31354;&#38388;&#65292;&#31995;&#32479;&#20250;&#22312;&#37096;&#20998;&#24418;&#24577;&#19979;&#23558;&#21407;&#26412;&#20301;&#20110;&#39030;&#37096;&#21644;&#24213;&#37096;&#30340;&#25511;&#20214;&#31227;&#21040;&#23631;&#24149;&#20391;&#36793;&#12290;&#20294;&#20256;&#32479; Toolbar &#20013;&#30340;&#25991;&#26412;&#25353;&#38062;&#12289;&#33258;&#23450;&#20041;&#35270;&#22270;&#31561;&#20869;&#23481;&#24182;&#19981;&#19968;&#23450;&#36866;&#21512;&#32437;&#21521;&#25490;&#21015;&#65292;Toolbar &#19982; Tab Bar &#36824;&#21487;&#33021;&#38656;&#35201;&#20105;&#22842;&#26377;&#38480;&#30340;&#20391;&#36793;&#31354;&#38388;&#12290;iOS 27.1 &#20026;&#27492;&#22686;&#21152;&#20102; </span><code>ToolbarItemAxisBehavior</code><span>&#12289;</span><code>ToolbarVerticalBehavior</code><span>&#12289;</span><code>ToolbarVerticalCompressionBehavior</code><span> &#21644; </span><code>toolbarVerticalEdge</code><span> &#31561; API&#65292;&#35753;&#24320;&#21457;&#32773;&#21487;&#20197;&#36827;&#19968;&#27493;&#25511;&#21046; Toolbar &#30340;&#26041;&#21521;&#12289;&#20301;&#32622;&#20197;&#21450;&#31354;&#38388;&#19981;&#36275;&#26102;&#30340;&#21387;&#32553;&#31574;&#30053;&#12290;&#8288;</span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> &#36890;&#36807;&#20195;&#30721;&#21644;&#28436;&#31034;&#23637;&#31034;&#20102;&#36825;&#20123;&#26032; API &#30340;&#20855;&#20307;&#34892;&#20026;&#12290;</span></p><p><span>&#36825;&#25209; API &#30340;&#20849;&#21516;&#29305;&#24449;&#65292;&#26159;&#35753;&#24320;&#21457;&#32773;&#22768;&#26126;&#20559;&#22909;&#32780;&#38750;&#25351;&#23450;&#32467;&#26524;&#12290;&#38754;&#23545; Duo &#24102;&#26469;&#30340;&#22810;&#31181;&#24418;&#24577;&#65292;&#19982;&#20854;&#38024;&#23545;&#29305;&#23450;&#35774;&#22791;&#29366;&#24577;&#32534;&#20889;&#24067;&#23616;&#65292;&#19981;&#22914;&#25551;&#36848;&#20869;&#23481;&#20043;&#38388;&#30340;&#20851;&#31995;&#21644;&#24067;&#23616;&#20559;&#22909;&#65292;&#20877;&#30001; SwiftUI &#26681;&#25454;&#23454;&#38469;&#29615;&#22659;&#20915;&#23450;&#26368;&#32456;&#21576;&#29616;&#26041;&#24335;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-05"><span>iPhone Duo &#19978;&#30340; Sheet &#19982;&#25240;&#30165;&#35268;&#36991; (Sheets and fold avoidance on iPhone Duo)</span></a></strong></h3><p><span>&#24403; iPhone Duo &#22788;&#20110;&#37096;&#20998;&#25240;&#21472;&#29366;&#24577;&#26102;&#65292;&#20013;&#22830;&#25240;&#30165;&#24418;&#25104;&#20102;&#19968;&#22359;&#19981;&#36866;&#21512;&#20132;&#20114;&#30340;&#21306;&#22495;&#65292;&#25353;&#38062;&#31561;&#25511;&#20214;&#22914;&#26524;&#24688;&#22909;&#33853;&#22312;&#36825;&#37324;&#65292;&#20250;&#21464;&#24471;&#38590;&#20197;&#25805;&#20316;&#12290;&#8288;</span><a href="https://x.com/sarunw"><span>Sarun Wongpatcharapakorn</span></a><span> &#20197; Sheet &#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#21516;&#19968;&#20010;&#30028;&#38754;&#22914;&#20309;&#22312; Duo &#30340;&#20851;&#38381;&#12289;&#23637;&#24320;&#12289;&#27178;&#23631;&#12289;&#31446;&#23631;&#20197;&#21450;&#37096;&#20998;&#25240;&#21472;&#31561;&#19981;&#21516;&#24418;&#24577;&#19979;&#35843;&#25972;&#23610;&#23544;&#12289;&#20301;&#32622;&#21644; Toolbar&#12290;Sheet&#12289;Alert &#21644;&#33756;&#21333;&#31561;&#31995;&#32479;&#32452;&#20214;&#24050;&#32463;&#20869;&#32622;&#25240;&#30165;&#35268;&#36991;&#33021;&#21147;&#65292;&#26080;&#38656;&#24320;&#21457;&#32773;&#24178;&#39044;&#12290;&#22240;&#27492;&#23545;&#20110;&#24320;&#21457;&#32773;&#32780;&#35328;&#65292;&#20248;&#20808;&#20351;&#29992;&#31995;&#32479;&#32452;&#20214;&#65292;&#20063;&#24847;&#21619;&#30528;&#21487;&#20197;&#30452;&#25509;&#33719;&#24471;&#36825;&#20123;&#38024;&#23545;&#19981;&#21516;&#35774;&#22791;&#24418;&#24577;&#30340;&#33258;&#36866;&#24212;&#34892;&#20026;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0154-06"><span>Vapor 5 Beta &#21457;&#24067;</span></a></strong></h3><p><span>&#22312; Vapor &#35806;&#29983;&#21313;&#21608;&#24180;&#12289;&#36317;&#31163; Vapor 4 &#21457;&#24067;&#20845;&#24180;&#21322;&#20043;&#38469;&#65292;&#31038;&#21306;&#32456;&#20110;&#36814;&#26469;&#20102; Vapor 5 &#30340;&#39318;&#20010; Beta &#29256;&#26412;&#12290;&#27492;&#27425;&#20960;&#20046;&#26159;&#19968;&#27425;&#24443;&#24213;&#37325;&#20889;&#8212;&#8212;&#21382;&#26102;&#20004;&#24180;&#12289;&#21464;&#26356;&#32422; 49,000 &#34892;&#20195;&#30721;&#12290;&#26368;&#26680;&#24515;&#30340;&#25913;&#21160;&#26159;&#24443;&#24213;&#21578;&#21035; </span><code>EventLoop</code><span> &#19982; </span><code>EventLoopFuture</code><span>&#65292;&#20840;&#38754;&#36716;&#21521; Swift Concurrency&#65292;&#24182;&#20197;&#32467;&#26500;&#21270;&#24182;&#21457;&#20026;&#22522;&#30784;&#65292;NIO &#20063;&#22522;&#26412;&#20174;&#20844;&#24320; API &#20013;&#38544;&#21435;&#12290;</span></p><p><span>&#21516;&#26102;&#65292;Vapor 5 &#36827;&#19968;&#27493;&#25972;&#21512; Swift HTTP Types&#12289;Swift Configuration &#21644; Swift Service Lifecycle&#65292;&#24182;&#21152;&#20837;&#23454;&#39564;&#24615;&#30340; </span><code>VaporMacros</code><span>&#65292;&#20026;&#36335;&#30001;&#21644;&#35748;&#35777;&#25552;&#20379;&#26356;&#22810;&#32534;&#35793;&#26399;&#31867;&#22411;&#26816;&#26597;&#12290;Vapor 5 &#35201;&#27714; Swift 6.4&#65292;&#30446;&#21069;&#20173;&#22788;&#20110; Beta &#38454;&#27573;&#12290;&#26377;&#20851;&#26356;&#22810;&#21464;&#21270;&#65292;&#21487;&#20197;&#26597;&#30475; &#8288;</span><a href="https://hachyderm.io/@0xTim"><span>Tim Condon</span></a><span> &#30340; &#8288;</span><a href="https://blog.vapor.codes/posts/whats-new-in-vapor-5-beta/"><span>What&#8217;s New in Vapor 5 Beta</span></a><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-07"><span>Hinge&#65306;&#21629;&#20196;&#34892;&#35843;&#33410; Duo &#27169;&#25311;&#22120;&#25240;&#21472;&#35282;&#24230;</span></a></strong></h3><p><span>Xcode 27.1 &#30340; Device Hub &#21487;&#20197;&#35843;&#25972; iPhone Duo Simulator &#30340;&#25240;&#21472;&#35282;&#24230;&#65288;&#25353;&#20303; Option &#38190;&#21487;&#35265;&#65289;&#65292;&#20294; </span><code>simctl</code><span> &#21644; </span><code>devicectl</code><span> &#24182;&#27809;&#26377;&#25552;&#20379;&#23545;&#24212;&#30340;&#25511;&#21046;&#21629;&#20196;&#12290;&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#24320;&#21457;&#30340; Hinge &#34917;&#19978;&#20102;&#36825;&#20010;&#32570;&#21475;&#65292;&#21487;&#20197;&#36890;&#36807;&#21629;&#20196;&#34892;&#35774;&#32622; 0&#8211;180&#176; &#30340;&#25240;&#21472;&#35282;&#24230;&#65292;&#20063;&#25903;&#25345;&#25171;&#24320;&#12289;&#20851;&#38381;&#12289;&#21322;&#25240;&#21472;&#20197;&#21450;&#36830;&#32493;&#25913;&#21464;&#35282;&#24230;&#31561;&#25805;&#20316;&#12290;Hinge &#36824;&#25552;&#20379;&#20102; Agent Skill&#65292;&#35753; Coding Agent &#21487;&#20197;&#22312;&#27979;&#35797;&#36807;&#31243;&#20013;&#20027;&#21160;&#25913;&#21464; Duo &#30340;&#25240;&#21472;&#29366;&#24577;&#24182;&#39564;&#35777; App&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0154-08"><span>Enriched Markdown&#65306;&#19981;&#20381;&#36182; WebView &#30340;&#36328;&#24179;&#21488; Markdown &#28210;&#26579;&#19982;&#32534;&#36753;&#26041;&#26696;</span></a></strong></h3><p><span>&#22312;&#31227;&#21160;&#31471;&#23454;&#29616; Markdown&#65292;&#24120;&#35265;&#26041;&#26696;&#26159;&#22871;&#19968;&#23618; WebView&#12290;Software Mansion &#25512;&#20986;&#30340; Enriched Markdown &#36873;&#25321;&#20102;&#19968;&#26465;&#26356;&#24443;&#24213;&#30340;&#36335;&#32447;&#65306;&#22522;&#20110;&#21508;&#24179;&#21488;&#30340;&#21407;&#29983;&#25991;&#26412;&#33021;&#21147;&#23436;&#25104; Markdown &#28210;&#26579;&#19982;&#23500;&#25991;&#26412;&#32534;&#36753;&#65292;&#24182;&#21487;&#20197;&#23558;&#32534;&#36753;&#21518;&#30340;&#20869;&#23481;&#37325;&#26032;&#36755;&#20986;&#20026;&#24178;&#20928;&#30340; Markdown&#12290;</span></p><p><span>&#23427;&#25552;&#20379;&#29420;&#31435;&#30340; SwiftUI SDK&#65292;&#22522;&#20110; TextKit 2 &#19982; md4c &#23454;&#29616; Markdown &#28210;&#26579;&#65292;&#21516;&#26102;&#20063;&#35206;&#30422; React Native&#12289;Android &#21644; Web&#12290;&#30456;&#27604;&#21333;&#32431;&#36861;&#27714;&#8220;&#33021;&#26174;&#31034; Markdown&#8221;&#65292;Enriched Markdown &#26356;&#37325;&#35270;&#21407;&#29983;&#20307;&#39564;&#65306;&#25991;&#26412;&#21487;&#20197;&#27491;&#24120;&#36873;&#25321;&#65292;&#38142;&#25509;&#12289;&#22270;&#29255;&#19982;&#20195;&#30721;&#22359;&#33021;&#22815;&#25509;&#20837;&#31995;&#32479;&#33756;&#21333;&#65292;&#24182;&#36866;&#37197; VoiceOver&#12289;TalkBack&#12289;&#21160;&#24577;&#23383;&#20307;&#21644;&#20174;&#21491;&#21040;&#24038;&#20070;&#20889;&#65288;RTL&#65289;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #153]]></title><description><![CDATA[The Opportunities and Challenges of iPhone Duo]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 14 Sep 2026 12:04:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!UL9K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UL9K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UL9K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 424w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 848w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1272w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp" width="1456" height="852" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:852,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:403894,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/215610459?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UL9K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 424w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 848w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1272w, https://substackcdn.com/image/fetch/$s_!UL9K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8c12932-74e8-4278-a340-bd1b39d32476_2304x1348.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong><span>The Opportunities and Challenges of iPhone Duo</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-153/">Read on web &#8594;</a></p><p><span>Although some details of the iPhone Duo&#8217;s design had already leaked months ago, and Apple is a latecomer to the foldable phone market, its ability to tightly integrate hardware and software&#8212;and the interaction changes that integration enables&#8212;still managed to surprise quite a few consumers.</span></p><p><span>Different research firms have offered forecasts for the iPhone Duo&#8217;s early sales using different time frames. Counterpoint expects shipments to reach as many as 6 million units by the end of 2026, while IDC estimates that the device could reach around 10 million units in its first 12 months on the market. That would still represent only a small fraction of total iPhone sales. But compared with the hundreds of thousands of Vision Pro units sold over its first two and a half years, it is already a large enough market to support quite a few apps designed specifically for this device. Over the past few days, I&#8217;ve already seen plenty of creative ideas on social media built around the Duo&#8217;s form factor. If even a few of them turn into breakout hits, they could further drive device sales. More importantly, the Duo has far greater social visibility than Vision Pro. The sense of being &#8220;different&#8221; that comes from distinctive hardware paired with distinctive apps is exactly what many early adopters of products like this are looking for.</span></p><p><span>For most developers, however, the adaptation pressure created by the iPhone Duo&#8217;s unique form factor is very real. The Duo has both outer and inner displays, while the inner display can be used fully open, partially folded, and in other poses. It is arguably one of the most challenging devices in the iPhone family to design for. Apple does provide a number of APIs specifically for adapting to these configurations, and standard containers already handle different poses reasonably well. But those things mainly solve the UI problem. The real challenge is UX: an API can tell you how much space is available and where the hinge is, but it cannot tell you what users actually want to see when the device is partially folded. Every additional pose means another experience that needs to be designed.</span></p><p><span>For teams using third-party frameworks such as Flutter and React Native, the problem starts one step earlier: it is not just about how well you can adapt, but whether you can access the necessary information in the first place. Flutter&#8217;s </span><code>MediaQuery.displayFeatures</code><span> returns an empty list on the Duo regardless of the fold angle, while React Native still provides no official API for accessing fold state. Once the hardware itself becomes part of the interaction model, cross-platform frameworks have to make more tradeoffs between hiding platform differences and exposing platform capabilities. And those tradeoffs are difficult for a framework to absorb on its own&#8212;it will always lag behind the platform.</span></p><p><span>In fact, the trend toward reevaluating cross-platform approaches had already begun before the Duo was announced, driven by several changes happening at the same time. AI coding agents have substantially reduced the cost of native development and maintenance, while changes such as Liquid Glass and Duo continue to raise the value of taking full advantage of platform-specific capabilities. The cost-benefit equation for cross-platform development is being squeezed from both directions. Notion is migrating its Apple-platform UI from a web-based technology stack to SwiftUI. Around the same time, Shopify announced that it was moving its mobile apps from React Native back to Swift and Kotlin. One reason it cited was that advances in coding models are eroding one of the key cost advantages of cross-platform development: avoiding having to &#8220;build the same feature twice.&#8221; Alongside that transition, Shopify is also handing off its React Native open-source libraries.</span></p><p><span>For the Apple ecosystem, iPhone Duo is a product that brings genuine change. Over the past few years, most changes to Apple&#8217;s platforms have taken place in software and design language. Duo, by contrast, changes the physical form factor developers have to design for. Its significance to the ecosystem may not lie in selling a few million more devices, but in what happens when the device itself once again becomes part of application design: &#8220;using the platform&#8217;s native frameworks&#8221; is starting to shift from a matter of preference to a matter of cost.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-152/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>5,000</strong>+ subscribers, <strong>50</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-01"><span>Module Tracking in Swift Debug Info</span></a></strong></h3><p><span>Have you ever hit a breakpoint, typed a seemingly trivial LLDB expression, and then waited... and waited? To evaluate a computed property or call a method, LLDB sometimes has to spin up the Swift compiler and locate and load the relevant modules. In the past, that lookup couldn&#8217;t always find the exact module your code was built from, and it might even recompile some dependencies along the way, turning a simple debugging step into a long pause.</span></p><p><a href="https://github.com/adrian-prantl/"><span>Adrian Prantl</span></a><span> introduces Module Tracking, a mechanism that began in Swift 6.3 and is further refined in 6.4. The new approach lets debug info tell LLDB precisely: &#8220;these are the modules the build actually used, and here is where they live,&#8221; cutting out unnecessary searching and recompilation. Swift 6.4 also improves bridging header handling and noticeably slims down debug artifacts &#8212; dSYM bundles on Darwin no longer carry binary Swift modules, and binaries built with debug info on Windows and Linux benefit as well.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-02"><span>New Hashable conformances in Swift 6.4</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span> walks through several standard library types that gain </span><code>Hashable</code><span> conformance in Swift 6.4, coming from two proposals: SE-0514 (</span><code>Dictionary.Keys</code><span>, </span><code>CollectionOfOne</code><span>, </span><code>EmptyCollection</code><span>) and SE-0523 (</span><code>UnownedTaskExecutor</code><span>). The one closest to everyday development is </span><code>Dictionary.Keys</code><span>, which can now go straight into a </span><code>Set</code><span> or serve as a dictionary key without first being converted to another type.</span></p><p><span>The semantics are worth noting: two </span><code>Dictionary.Keys</code><span> values are equal as long as they contain the same keys &#8212; order participates in neither comparison nor hashing, which is consistent with how a dictionary&#8217;s own identity is defined. </span><code>Dictionary.Values</code><span> did not receive the same treatment, because values can repeat, and expressing that correctly would require multiset semantics that Swift doesn&#8217;t currently have. A small piece of completion work, but one that makes these types sit more naturally in generic and collection contexts.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-03"><span>How to list big models cheaply: Vein vs SwiftData</span></a></strong></h3><p><span>Two weeks ago, in </span><a href="https://fatbobman.com/en/posts/swiftdata-optimization-starts-with-modeling/"><span>SwiftData: Optimization Starts with Modeling</span></a><span>, I discussed the memory and performance pressure that &#8220;fat models&#8221; put on SwiftData lists, and tried to reduce how much data a single query actually loads by splitting the model. </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia K&#246;ring</span></a><span> took the benchmark code from that article and used it to show how </span><a href="https://github.com/amethystsoft/vein"><span>Vein</span></a><span>, the persistence framework she is building, performs with field-level lazy loading.</span></p><p><span>Vein declares models much the way SwiftData does, and by default behaves similarly too: properties are eagerly loaded, relationships lazily. The difference is that marking a property with </span><code>@LazyField</code><span> defers reading it until it is actually accessed. As a result, in a &#8220;title-only list&#8221; scenario, Vein reaches good numbers without any model splitting at all.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-04"><span>Sad But True: Localized App Store Screenshots That Verify Themselves</span></a></strong></h3><p><span>Automation keeps working its way into every stage of app development. But in practice, the hard part often isn&#8217;t implementing the automation &#8212; it&#8217;s getting it to prove that it did the right thing.</span></p><p><span>While generating localized App Store screenshots automatically, </span><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> discovered that his Spanish screenshots had quietly fallen back to English, while the entire test run still reported success. The cause turned out to be </span><code>-testLanguage</code><span> not reliably reaching the app under Xcode 27. Wesley switched to setting the simulator&#8217;s language through </span><code>simctl</code><span>, and added a check that compares the SHA-256 of the captured screenshots to catch cases where two languages, or two different screens, unexpectedly produce byte-identical images.</span></p><blockquote><p><span>Wesley&#8217;s screenshot-hashing approach transfers to any pipeline where you hand a request to a black box and then accept whatever comes back at face value.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-05"><span>Transition or ContentTransition</span></a></strong></h3><p><code>transition</code><span> and </span><code>contentTransition</code><span> have remarkably similar names, but they solve two different problems: the former animates a view being inserted into or removed from the view hierarchy, the latter applies when the view stays put and only the content it displays changes. </span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> compares them side by side using conditional views, changing numbers, and SF Symbols, and covers common content transitions such as </span><code>.numericText</code><span>, </span><code>.interpolate</code><span>, and </span><code>.symbolEffect</code><span>.</span></p><blockquote><p><span>SwiftUI has supported custom </span><code>transition</code><span> values for a long time, but that capability has never extended to higher-level scenarios like sheets or navigation changes. Those situations resemble </span><code>contentTransition</code><span>, and still rely mostly on the handful of transitions the system provides. It would be good to see SwiftUI eventually connect these different levels of the transition concept &#8212; or at least give developers more room to customize them.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-06"><span>Abstracting SwiftUI state with scopes</span></a></strong></h3><p><span>When a SwiftUI view holds several </span><code>@State</code><span> properties, we often abstract them into a single </span><code>@Observable</code><span>. But what if the view also depends on environment values or other </span><code>Observable</code><span> instances? Is there a way to organize state coming from different sources while reducing the view&#8217;s coupling to any particular one of them? </span><a href="https://twitter.com/auramagi"><span>Mike Apurin</span></a><span> proposes thinking in scopes: his library </span><a href="https://github.com/auramagi/swift-scoped-state"><span>ScopedState</span></a><span> gathers multiple state sources behind a unified access boundary, exposing to a view only the state and actions that screen genuinely needs. The view doesn&#8217;t need to know where any of it comes from, and swapping the data source in previews and tests becomes much easier. Worth noting: this isn&#8217;t an attempt to build yet another state management model along the lines of TCA or MVVM &#8212; it&#8217;s a way of organizing and abstracting existing state sources at the view layer.</span></p><div><hr></div><h3><strong><span>Before the Fold: Adapting for iPhone Duo</span></strong></h3><p><span>The arrival of iPhone Duo has consumers marveling at the new form factor, and developers facing a new set of challenges: how to make use of the extra display space, how to make existing layouts adapt across device configurations, and how to take advantage of new interaction capabilities like the fold and multiple display regions. Over the past week, a number of writers offered their perspectives.</span></p><ul><li><p><span>Apple published six Tech Talks on announcement day: </span><a href="https://developer.apple.com/videos/play/tech-talks/111466/"><span>Design for iPhone Duo</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111461/"><span>Prepare your app</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111462/"><span>Raise the bar</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111463/"><span>Strike a pose with adaptive layouts</span></a><span>, </span><a href="https://developer.apple.com/videos/play/tech-talks/111464/"><span>Leverage multiple displays and scenes</span></a><span>, and </span><a href="https://developer.apple.com/videos/play/tech-talks/111465/"><span>Build a great camera experience</span></a><span>, along with a new </span><a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo"><span>Designing for iPhone Duo</span></a><span> page in the HIG.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-07"><span>Florian Schweizer</span></a><span> makes the case for not fighting the framework: don&#8217;t start by asking whether the device is an iPhone Duo, ask how much space this view has been given. He has also distilled these principles, along with Duo&#8217;s new APIs and Apple&#8217;s developer material, into a </span><a href="https://github.com/FloWritesCode/fwc-swiftui-skills/tree/main/skills/swiftui-iphone-duo"><span>SwiftUI iPhone Duo Skill</span></a><span> for coding agents working on existing apps.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-08"><span>Lee young-jun</span></a><span> approaches it from hands-on adaptation work, using </span><code>NavigationSplitView</code><span>, </span><code>sidebarAdaptable</code><span>, and Device Hub&#8217;s Resizing Mode to inspect and improve how an app behaves across iPhone Duo&#8217;s different display configurations ahead of time.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-09"><span>Sagar Unagar</span></a><span> draws on Apple&#8217;s latest HIG and developer material to summarize the main design principles for iPhone Duo: adaptive layout, system controls, the fold region, and the various display configurations.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-10"><span>Jordan Morgan</span></a><span> rounds up the changes developers should look at first &#8212; layout, system bars, safe areas, camera, and multiple display regions.</span></p></li><li><p><a href="https://l.fatbobman.com/w0153-11"><span>Artem Mirzabekian</span></a><span> introduces the new </span><code>ArrangementView</code><span>, which lets you describe the relationship between two related pieces of content and leaves it to SwiftUI to pick a suitable layout based on available space and the fold region.</span></p></li></ul><blockquote><p><span>Many of the features covered above exist only in Xcode 27.1, so experiencing them in full will take a little while yet.</span></p></blockquote><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-12"><span>SwiftMusic: Declaring Music in Swift</span></a></strong></h3><p><span>SwiftMusic, from </span><a href="https://x.com/1amageek"><span>Norikazu Muramoto</span></a><span>, is a declarative music composition framework for Apple platform developers. It borrows SwiftUI&#8217;s design sensibility, bringing familiar Swift constructs &#8212; </span><code>Music</code><span>, </span><code>Sound</code><span>, </span><code>body</code><span>, result builders, and modifiers &#8212; into music creation, so that rhythm, melody, harmony, timbre, effects, and mixing relationships can all be described by composing code.</span></p><p><span>Drums, bass, and synths, for instance, can be written as Swift code that reads musically:</span></p><pre><code><span>struct Session: Music {</span>
<span>      var body: some Sound {</span>
<span>          Track(&#8221;Drums&#8221;) {</span>
<span>              Sample(&#8221;kick&#8221;)</span>
<span>                  .rhythm(&#8221;x ~ x ~&#8221;)</span>
<span>          }</span>
<span>&#8203;</span>
<span>          Track(&#8221;Bass&#8221;) {</span>
<span>              Synthesizer(.saw)</span>
<span>                  .notes(&#8221;C2 ~ Eb2 G2&#8221;)</span>
<span>                  .gain(0.3)</span>
<span>          }</span>
<span>      }</span>
<span>  }</span></code></pre><p><span>SwiftMusic makes no sound on its own: it only compiles your declarations into beat-domain events and an ordered render plan. It neither opens an audio device nor draws an editor &#8212; actual audio rendering is the host&#8217;s responsibility. The author provides </span><a href="https://github.com/1amageek/MusicPlaygournd"><span>MusicPlaygournd</span></a><span>, a live editor for macOS, to fill that role.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-13"><span>Homebrew 7: The Release That Says Goodbye to Intel</span></a></strong></h3><p><span>Homebrew 7.0.0 is out. Alongside a range of features and internal changes, this major release brings compatibility changes worth paying attention to. On Apple Silicon Macs, macOS 15&#8211;27 currently falls within the fully supported range, while Intel Macs have all been moved down to Tier 3 &#8212; no full CI support, no new bottles, and a plan to end support entirely in or after September 2027. If you are still running Homebrew on an Intel Mac or an older version of macOS, this one deserves a closer look.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-153?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>iPhone Duo &#24102;&#26469;&#30340;&#26426;&#36935;&#19982;&#25361;&#25112;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-153/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#23613;&#31649; iPhone Duo &#30340;&#35774;&#35745;&#36164;&#26009;&#26089;&#22312;&#20960;&#20010;&#26376;&#21069;&#23601;&#24050;&#37096;&#20998;&#27844;&#28431;&#65292;&#32780;&#19988;&#33529;&#26524;&#20063;&#26159;&#25240;&#21472;&#26426;&#39046;&#22495;&#30340;&#21518;&#26469;&#32773;&#65292;&#20294;&#20973;&#20511;&#36719;&#30828;&#20214;&#25972;&#21512;&#33021;&#21147;&#65292;&#23427;&#25152;&#24102;&#26469;&#30340;&#20132;&#20114;&#21464;&#21270;&#36824;&#26159;&#32473;&#19981;&#23569;&#28040;&#36153;&#32773;&#24102;&#26469;&#20102;&#24778;&#21916;&#12290;</span></p><p><span>&#19981;&#21516;&#26426;&#26500;&#23545; iPhone Duo &#30340;&#21021;&#26399;&#38144;&#37327;&#32473;&#20986;&#20102;&#19981;&#21516;&#21475;&#24452;&#30340;&#39044;&#27979;&#65306;Counterpoint &#39044;&#35745;&#20854; 2026 &#24180;&#20869;&#20986;&#36135;&#37327;&#26368;&#39640;&#32422; 600 &#19975;&#37096;&#65307;IDC &#21017;&#39044;&#35745;&#19978;&#24066;&#21518;&#21069; 12 &#20010;&#26376;&#21487;&#33021;&#36798;&#21040;&#32422; 1000 &#19975;&#37096;&#12290;&#22312;&#25972;&#20010; iPhone &#38144;&#37327;&#20013;&#65292;&#36825;&#20173;&#28982;&#21482;&#21344;&#19968;&#23567;&#37096;&#20998;&#65292;&#20294;&#19982; Vision Pro &#19978;&#24066;&#20004;&#24180;&#21322;&#30340;&#20960;&#21313;&#19975;&#38144;&#37327;&#30456;&#27604;&#65292;&#36825;&#20010;&#25968;&#37327;&#24050;&#32463;&#36275;&#20197;&#25903;&#25745;&#19981;&#23569;&#29305;&#21035;&#38024;&#23545;&#36825;&#27454;&#35774;&#22791;&#24320;&#21457;&#30340;&#24212;&#29992;&#20102;&#12290;&#36825;&#20960;&#22825;&#65292;&#25105;&#24050;&#32463;&#22312;&#31038;&#20132;&#23186;&#20307;&#19978;&#30475;&#21040;&#19981;&#23569;&#38024;&#23545; Duo &#24418;&#24577;&#30340;&#21019;&#24847;&#65292;&#30456;&#20449;&#19968;&#26086;&#20854;&#20013;&#20986;&#29616;&#20960;&#20010;&#29190;&#27454;&#65292;&#20063;&#20250;&#36827;&#19968;&#27493;&#25512;&#21160;&#35774;&#22791;&#30340;&#38144;&#37327;&#12290;&#23588;&#20854;&#26159;&#65292;Duo &#30456;&#27604; Vision Pro &#20855;&#22791;&#26356;&#24378;&#30340;&#31038;&#20132;&#23637;&#31034;&#24615;&#65292;&#29305;&#21035;&#30340;&#30828;&#20214;&#12289;&#29305;&#21035;&#30340;&#24212;&#29992;&#25152;&#24102;&#26469;&#30340;&#8220;&#29305;&#21035;&#24863;&#8221;&#65292;&#27491;&#26159;&#19981;&#23569;&#39318;&#25209;&#36141;&#20080;&#36825;&#31867;&#20135;&#21697;&#30340;&#29992;&#25143;&#25152;&#36861;&#27714;&#30340;&#12290;</span></p><p><span>&#20294;&#23545;&#20110;&#26356;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;iPhone Duo &#29420;&#29305;&#24418;&#24577;&#24102;&#26469;&#30340;&#36866;&#37197;&#21387;&#21147;&#20063;&#26159;&#30495;&#23454;&#30340;&#12290;Duo &#21253;&#25324;&#20869;&#22806;&#20004;&#22359;&#23631;&#24149;&#65292;&#20869;&#23631;&#21448;&#21487;&#20197;&#20197;&#23637;&#24320;&#12289;&#21322;&#25240;&#21472;&#31561;&#22810;&#31181;&#23039;&#24577;&#23384;&#22312;&#65292;&#21487;&#20197;&#35828;&#26159; iPhone &#23478;&#26063;&#20013;&#36866;&#37197;&#38590;&#24230;&#26368;&#39640;&#30340;&#20135;&#21697;&#20043;&#19968;&#12290;&#33529;&#26524;&#30830;&#23454;&#25552;&#20379;&#20102;&#19981;&#23569;&#26377;&#38024;&#23545;&#24615;&#30340;&#36866;&#37197; API&#65292;&#26631;&#20934;&#23481;&#22120;&#22312;&#21508;&#31181;&#23039;&#24577;&#19979;&#20063;&#24050;&#22522;&#26412;&#33258;&#36866;&#24212;&#65292;&#20294;&#36825;&#20123;&#21482;&#35299;&#20915;&#20102; UI &#23618;&#38754;&#30340;&#38382;&#39064;&#12290;&#30495;&#27491;&#38590;&#30340;&#26159; UX&#65306;API &#33021;&#21578;&#35785;&#20320;&#21487;&#29992;&#31354;&#38388;&#26377;&#22810;&#22823;&#12289;&#38128;&#38142;&#33853;&#22312;&#21738;&#37324;&#65292;&#21364;&#26080;&#27861;&#21578;&#35785;&#20320;&#21322;&#25240;&#21472;&#26102;&#29992;&#25143;&#31350;&#31455;&#24819;&#30475;&#21040;&#20160;&#20040;&#12290;&#22810;&#19968;&#31181;&#23039;&#24577;&#65292;&#23601;&#22810;&#19968;&#27425;&#38656;&#35201;&#37325;&#26032;&#35774;&#35745;&#30340;&#20307;&#39564;&#12290;</span></p><p><span>&#23545;&#20110;&#20351;&#29992; Flutter&#12289;React Native &#31561;&#31532;&#19977;&#26041;&#26694;&#26550;&#30340;&#22242;&#38431;&#65292;&#38382;&#39064;&#36824;&#35201;&#26356;&#38752;&#21069;&#19968;&#27493;&#65306;&#19981;&#26159;&#36866;&#37197;&#24471;&#22909;&#19981;&#22909;&#65292;&#32780;&#26159;&#25343;&#19981;&#25343;&#24471;&#21040;&#20449;&#24687;&#12290;Flutter &#30340; </span><code>MediaQuery.displayFeatures</code><span> &#22312; Duo &#19978;&#26080;&#35770;&#25240;&#21472;&#21040;&#20160;&#20040;&#35282;&#24230;&#37117;&#36820;&#22238;&#31354;&#21015;&#34920;&#65292;React Native &#21017;&#33267;&#20170;&#27809;&#26377;&#20219;&#20309;&#19982;&#25240;&#21472;&#29366;&#24577;&#30456;&#20851;&#30340;&#23448;&#26041; API&#12290;&#24403;&#30828;&#20214;&#26412;&#36523;&#24320;&#22987;&#25104;&#20026;&#20132;&#20114;&#30340;&#19968;&#37096;&#20998;&#65292;&#36328;&#24179;&#21488;&#26694;&#26550;&#23601;&#24517;&#39035;&#22312;&#23631;&#34109;&#24179;&#21488;&#24046;&#24322;&#19982;&#26292;&#38706;&#24179;&#21488;&#33021;&#21147;&#20043;&#38388;&#20570;&#20986;&#26356;&#22810;&#21462;&#33293;&#65292;&#32780;&#36825;&#31181;&#21462;&#33293;&#24456;&#38590;&#30001;&#26694;&#26550;&#21333;&#26041;&#38754;&#28040;&#21270;&#8212;&#8212;&#23427;&#24635;&#26159;&#28382;&#21518;&#20110;&#24179;&#21488;&#12290;</span></p><p><span>&#20107;&#23454;&#19978;&#65292;&#22312; Duo &#21457;&#24067;&#20043;&#21069;&#65292;&#37325;&#26032;&#35780;&#20272;&#36328;&#24179;&#21488;&#26041;&#26696;&#30340;&#36235;&#21183;&#23601;&#24050;&#32463;&#20986;&#29616;&#65292;&#20854;&#32972;&#21518;&#26159;&#19968;&#32452;&#27491;&#22312;&#21516;&#26102;&#21457;&#29983;&#30340;&#21464;&#21270;&#65306;AI Coding Agent &#22823;&#24133;&#38477;&#20302;&#20102;&#21407;&#29983;&#24320;&#21457;&#19982;&#32500;&#25252;&#30340;&#25104;&#26412;&#65292;&#32780; Liquid Glass&#12289;Duo &#36825;&#26679;&#30340;&#21464;&#21270;&#21448;&#22312;&#19981;&#26029;&#25260;&#39640;&#29992;&#36275;&#24179;&#21488;&#29305;&#24615;&#30340;&#20215;&#20540;&#12290;&#36328;&#24179;&#21488;&#26041;&#26696;&#30340;&#24615;&#20215;&#27604;&#65292;&#27491;&#34987;&#36825;&#20004;&#22836;&#21516;&#26102;&#25380;&#21387;&#12290;Notion &#27491;&#22312;&#23558;&#22522;&#20110; Web &#25216;&#26415;&#26632;&#30340;&#33529;&#26524;&#31471; UI &#36801;&#31227;&#21040; SwiftUI&#65307;Shopify &#21017;&#22312;&#20960;&#20046;&#21516;&#19968;&#26102;&#38388;&#23459;&#24067;&#23558;&#31227;&#21160;&#31471;&#20174; React Native &#36801;&#22238; Swift &#19982; Kotlin&#65292;&#29702;&#30001;&#20043;&#19968;&#26159;&#32534;&#30721;&#27169;&#22411;&#30340;&#36827;&#27493;&#27491;&#22312;&#21066;&#24369;&#8220;&#36991;&#20813;&#25226;&#21516;&#19968;&#20010;&#21151;&#33021;&#36896;&#20004;&#36941;&#8221;&#36825;&#19968;&#36328;&#24179;&#21488;&#24320;&#21457;&#30340;&#37325;&#35201;&#25104;&#26412;&#20248;&#21183;&#12290;&#19982;&#20043;&#19968;&#24182;&#21457;&#29983;&#30340;&#65292;&#26159;&#23427;&#23545;&#26071;&#19979; React Native &#24320;&#28304;&#24211;&#30340;&#20132;&#25509;&#12290;</span></p><p><span>&#23545;&#20110;&#33529;&#26524;&#29983;&#24577;&#26469;&#35828;&#65292;iPhone Duo &#26159;&#19968;&#20010;&#30495;&#27491;&#24102;&#26469;&#21464;&#21270;&#30340;&#20135;&#21697;&#12290;&#36807;&#21435;&#20960;&#24180;&#65292;&#33529;&#26524;&#24179;&#21488;&#30340;&#21464;&#21270;&#26356;&#22810;&#21457;&#29983;&#22312;&#36719;&#20214;&#21644;&#35774;&#35745;&#35821;&#35328;&#19978;&#65292;&#32780; Duo &#21017;&#37325;&#26032;&#25913;&#21464;&#20102;&#24320;&#21457;&#32773;&#38754;&#23545;&#30340;&#30828;&#20214;&#24418;&#24577;&#12290;&#23427;&#30340;&#29983;&#24577;&#24847;&#20041;&#25110;&#35768;&#24182;&#19981;&#22312;&#20110;&#22810;&#21334;&#20986;&#20960;&#30334;&#19975;&#21488;&#35774;&#22791;&#65292;&#32780;&#22312;&#20110;&#24403;&#35774;&#22791;&#26412;&#36523;&#20877;&#27425;&#25104;&#20026;&#24212;&#29992;&#35774;&#35745;&#30340;&#19968;&#37096;&#20998;&#26102;&#65292;&#8220;&#20351;&#29992;&#24179;&#21488;&#21407;&#29983;&#26694;&#26550;&#8221;&#36825;&#20214;&#20107;&#65292;&#27491;&#22312;&#20174;&#19968;&#36947;&#20559;&#22909;&#39064;&#21464;&#25104;&#19968;&#36947;&#25104;&#26412;&#39064;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-152/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-01"><span>&#35843;&#35797;&#21345;&#39039;&#30340;&#26681;&#28304;&#65306;Swift &#22914;&#20309;&#36861;&#36394; Module (Module Tracking in Swift Debug Info)</span></a></strong></h3><p><span>&#20320;&#26159;&#21542;&#30896;&#21040;&#36807;&#36825;&#26679;&#30340;&#24773;&#20917;&#65306;&#19968;&#20010;&#30475;&#20284;&#31616;&#21333;&#30340; LLDB &#34920;&#36798;&#24335;&#65292;&#22312;&#26029;&#28857;&#35843;&#35797;&#26102;&#21364;&#36831;&#36831;&#27809;&#26377;&#21453;&#39304;&#65311;&#20026;&#20102;&#35745;&#31639;&#23646;&#24615;&#12289;&#35843;&#29992;&#26041;&#27861;&#31561;&#25805;&#20316;&#65292;LLDB &#26377;&#26102;&#38656;&#35201;&#21551;&#21160; Swift &#32534;&#35793;&#22120;&#65292;&#24182;&#23547;&#25214;&#21644;&#21152;&#36733;&#30456;&#20851; Module&#12290;&#36807;&#21435;&#36825;&#22871;&#36807;&#31243;&#24182;&#19981;&#24635;&#33021;&#20934;&#30830;&#25214;&#21040;&#26500;&#24314;&#26102;&#23454;&#38469;&#20351;&#29992;&#30340; Module&#65292;&#29978;&#33267;&#21487;&#33021;&#37325;&#26032;&#32534;&#35793;&#37096;&#20998;&#20381;&#36182;&#65292;&#35753;&#19968;&#20010;&#21407;&#26412;&#31616;&#21333;&#30340;&#35843;&#35797;&#25805;&#20316;&#21464;&#25104;&#38271;&#26102;&#38388;&#31561;&#24453;&#12290;</span></p><p><a href="https://github.com/adrian-prantl/"><span>Adrian Prantl</span></a><span> &#20171;&#32461;&#20102;&#19968;&#20010;&#20174; Swift 6.3 &#24320;&#22987;&#24341;&#20837;&#12289;&#24182;&#22312; 6.4 &#20013;&#36827;&#19968;&#27493;&#23436;&#21892;&#30340;&#26426;&#21046;&#65306;Module Tracking&#12290;&#26032;&#30340;&#26426;&#21046;&#35753;&#35843;&#35797;&#20449;&#24687;&#33021;&#22815;&#26356;&#26126;&#30830;&#22320;&#21578;&#35785; LLDB&#65306;&#8221;&#26500;&#24314;&#26102;&#29992;&#30340;&#23601;&#26159;&#36825;&#20123; Module&#65292;&#23427;&#20204;&#23601;&#22312;&#36825;&#37324;&#8221;&#65292;&#20174;&#32780;&#20943;&#23569;&#19981;&#24517;&#35201;&#30340;&#23547;&#25214;&#21644;&#37325;&#26032;&#32534;&#35793;&#12290;Swift 6.4 &#36824;&#20250;&#25913;&#21892; bridging header &#30340;&#22788;&#29702;&#65292;&#24182;&#35753;&#35843;&#35797;&#20135;&#29289;&#26126;&#26174;&#30246;&#36523;&#8212;&#8212;Darwin &#19978;&#30340; dSYM &#19981;&#20877;&#25171;&#21253;&#20108;&#36827;&#21046; Swift Module&#65292;Windows &#19982; Linux &#19978;&#24102;&#35843;&#35797;&#20449;&#24687;&#30340;&#20108;&#36827;&#21046;&#21516;&#26679;&#21463;&#30410;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-02"><span>Swift 6.4 &#20013;&#34917;&#40784;&#30340;&#20960;&#22788; Hashable (New Hashable conformances in Swift 6.4)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span> &#20171;&#32461;&#20102; Swift 6.4 &#20013;&#20960;&#20010;&#26032;&#22686; </span><code>Hashable</code><span> &#25903;&#25345;&#30340;&#26631;&#20934;&#24211;&#31867;&#22411;&#65292;&#23427;&#20204;&#20998;&#21035;&#26469;&#33258; SE-0514&#65288;</span><code>Dictionary.Keys</code><span>&#12289;</span><code>CollectionOfOne</code><span>&#12289;</span><code>EmptyCollection</code><span>&#65289;&#21644; SE-0523&#65288;</span><code>UnownedTaskExecutor</code><span>&#65289;&#12290;&#20854;&#20013;&#26368;&#36148;&#36817;&#26085;&#24120;&#24320;&#21457;&#30340;&#26159; </span><code>Dictionary.Keys</code><span>&#65306;&#29616;&#22312;&#21487;&#20197;&#30452;&#25509;&#25918;&#20837; </span><code>Set</code><span> &#25110;&#20316;&#20026; Dictionary &#30340; key&#65292;&#32780;&#19981;&#24517;&#20808;&#36716;&#25442;&#25104;&#20854;&#20182;&#31867;&#22411;&#12290;</span></p><p><span>&#20540;&#24471;&#30041;&#24847;&#23427;&#30340;&#35821;&#20041;&#65306;&#20004;&#20010; </span><code>Dictionary.Keys</code><span> &#21482;&#35201;&#21253;&#21547;&#30456;&#21516;&#30340;&#38190;&#23601;&#35270;&#20026;&#30456;&#31561;&#65292;&#39034;&#24207;&#19981;&#21442;&#19982;&#27604;&#36739;&#19982;&#21704;&#24076;&#8212;&#8212;&#36825;&#19982;&#23383;&#20856;&#26412;&#36523;&#30340;&#36523;&#20221;&#35748;&#23450;&#26159;&#19968;&#33268;&#30340;&#12290;</span><code>Dictionary.Values</code><span> &#27809;&#26377;&#19968;&#24182;&#33719;&#24471;&#35813;&#33021;&#21147;&#65292;&#22240;&#20026;&#20540;&#21487;&#20197;&#37325;&#22797;&#65292;&#38656;&#35201;&#30340;&#26159; Swift &#30446;&#21069;&#27809;&#26377;&#30340;&#22810;&#37325;&#38598;&#21512;&#35821;&#20041;&#12290;&#34429;&#28982;&#21482;&#26159;&#19968;&#27425;&#23567;&#24133;&#34917;&#20840;&#65292;&#20294;&#20063;&#35753;&#36825;&#20123;&#31867;&#22411;&#22312;&#27867;&#22411;&#21644;&#38598;&#21512;&#22330;&#26223;&#20013;&#30340;&#20351;&#29992;&#26356;&#21152;&#33258;&#28982;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-03"><span>Vein &#20013;&#30340;&#24816;&#20540;&#24615;&#33021; (How to list big models cheaply: Vein vs SwiftData)</span></a></strong></h3><p><span>&#20004;&#21608;&#21069;&#25105;&#22312; </span><a href="https://fatbobman.com/zh/posts/swiftdata-optimization-starts-with-modeling/"><span>SwiftData&#65306;&#20248;&#21270;&#20174;&#24314;&#27169;&#24320;&#22987;</span></a><span> &#20013;&#35752;&#35770;&#20102;&#8220;&#32982;&#27169;&#22411;&#8221;&#32473; SwiftData &#21015;&#34920;&#24102;&#26469;&#30340;&#20869;&#23384;&#21644;&#24615;&#33021;&#21387;&#21147;&#65292;&#24182;&#23581;&#35797;&#36890;&#36807;&#27169;&#22411;&#25286;&#20998;&#20943;&#23569;&#19968;&#27425;&#26597;&#35810;&#30495;&#27491;&#21152;&#36733;&#30340;&#25968;&#25454;&#12290;</span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia K&#246;ring</span></a><span> &#20351;&#29992;&#20102;&#25105;&#25991;&#31456;&#20013;&#30340;&#27979;&#35797;&#20195;&#30721;&#65292;&#23637;&#31034;&#20102;&#22905;&#24320;&#21457;&#30340; </span><a href="https://github.com/amethystsoft/vein"><span>Vein</span></a><span> &#25345;&#20037;&#21270;&#26694;&#26550;&#22312;&#23383;&#27573;&#32423;&#24816;&#24615;&#21152;&#36733;&#19979;&#30340;&#34920;&#29616;&#12290;</span></p><p><span>Vein &#37319;&#29992;&#20102;&#19982; SwiftData Model &#31867;&#20284;&#30340;&#22768;&#26126;&#26041;&#24335;&#65292;&#40664;&#35748;&#21516;&#26679;&#26159;&#23646;&#24615;&#39044;&#21152;&#36733;&#12289;&#20851;&#31995;&#24816;&#24615;&#21152;&#36733;&#65307;&#19981;&#21516;&#20043;&#22788;&#22312;&#20110;&#65292;&#32473;&#26576;&#20010;&#23646;&#24615;&#26631;&#27880; </span><code>@LazyField</code><span> &#21518;&#65292;&#23427;&#20250;&#25512;&#36831;&#21040;&#30495;&#27491;&#34987;&#35775;&#38382;&#26102;&#25165;&#21435;&#35835;&#21462;&#12290;&#22240;&#27492;&#22312;&#8220;&#21482;&#26174;&#31034;&#26631;&#39064;&#8221;&#30340;&#21015;&#34920;&#22330;&#26223;&#20013;&#65292;&#26080;&#38656;&#25286;&#20998;&#27169;&#22411;&#20063;&#33021;&#21462;&#24471;&#19981;&#38169;&#30340;&#25104;&#32489;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-04"><span>&#35753;&#33258;&#21160;&#21270;&#33258;&#24049;&#35777;&#26126;&#23427;&#20570;&#23545;&#20102; (Sad But True: Localized App Store Screenshots That Verify Themselves)</span></a></strong></h3><p><span>&#33258;&#21160;&#21270;&#34987;&#36234;&#26469;&#36234;&#22810;&#22320;&#24212;&#29992;&#21040; App &#24320;&#21457;&#30340;&#21508;&#20010;&#29615;&#33410;&#65292;&#20294;&#26377;&#26102;&#23454;&#36341;&#20013;&#30340;&#38590;&#28857;&#24182;&#38750;&#22914;&#20309;&#23454;&#29616;&#33258;&#21160;&#21270;&#65292;&#32780;&#26159;&#22914;&#20309;&#35753;&#23427;&#33258;&#24049;&#35777;&#26126;&#8220;&#25105;&#20570;&#23545;&#20102;&#8221;&#12290;</span></p><p><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> &#22312;&#36890;&#36807;&#33258;&#21160;&#21270;&#26041;&#24335;&#20026; App Store &#29983;&#25104;&#22810;&#35821;&#35328;&#25130;&#22270;&#26102;&#65292;&#21457;&#29616;&#35199;&#29677;&#29273;&#35821;&#25130;&#22270;&#24708;&#24708;&#22238;&#36864;&#25104;&#20102;&#33521;&#25991;&#65292;&#32780;&#25972;&#20010;&#27979;&#35797;&#27969;&#31243;&#20381;&#28982;&#36890;&#36807;&#12290;&#26816;&#26597;&#21518;&#21457;&#29616;&#65292;&#21407;&#22240;&#26469;&#33258; Xcode 27 &#19979; </span><code>-testLanguage</code><span> &#27809;&#26377;&#21487;&#38752;&#22320;&#24212;&#29992;&#21040; App&#12290;Wesley &#38543;&#21518;&#25913;&#29992; </span><code>simctl</code><span> &#35774;&#32622; Simulator &#30340;&#35821;&#35328;&#65292;&#24182;&#36890;&#36807;&#27604;&#36739;&#25130;&#22270;&#30340; SHA-256&#65292;&#33258;&#21160;&#26816;&#26597;&#19981;&#21516;&#35821;&#35328;&#25110;&#19981;&#21516;&#39029;&#38754;&#26159;&#21542;&#24847;&#22806;&#29983;&#25104;&#20102;&#23436;&#20840;&#30456;&#21516;&#30340;&#22270;&#29255;&#12290;</span></p><blockquote><p><span>Wesley &#22522;&#20110;&#25130;&#22270;&#21704;&#24076;&#30340;&#27604;&#36739;&#24605;&#36335;&#21487;&#20197;&#36801;&#31227;&#21040;&#20219;&#20309;&#8220;&#25226;&#35831;&#27714;&#20132;&#32473;&#40657;&#30418;&#12289;&#20877;&#25226;&#20135;&#20986;&#29031;&#21333;&#20840;&#25910;&#8221;&#30340;&#27969;&#31243;&#37324;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-05"><span>Transition or ContentTransition</span></a></strong></h3><p><code>transition</code><span> &#21644; </span><code>contentTransition</code><span> &#21517;&#23383;&#24456;&#20687;&#65292;&#20294;&#35299;&#20915;&#30340;&#26159;&#20004;&#31867;&#19981;&#21516;&#30340;&#38382;&#39064;&#65306;&#21069;&#32773;&#29992;&#20110; View &#34987;&#25554;&#20837;&#25110;&#31227;&#20986;&#35270;&#22270;&#23618;&#32423;&#26102;&#30340;&#21160;&#30011;&#65292;&#21518;&#32773;&#21017;&#29992;&#20110; View &#20173;&#28982;&#23384;&#22312;&#12289;&#21482;&#26159;&#26174;&#31034;&#20869;&#23481;&#21457;&#29983;&#21464;&#21270;&#30340;&#24773;&#20917;&#12290;</span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> &#36890;&#36807;&#26465;&#20214;&#35270;&#22270;&#12289;&#25968;&#23383;&#21464;&#21270;&#21644; SF Symbols &#31561;&#20363;&#23376;&#23545;&#20004;&#32773;&#36827;&#34892;&#20102;&#30452;&#35266;&#27604;&#36739;&#65292;&#24182;&#20171;&#32461;&#20102; </span><code>.numericText</code><span>&#12289;</span><code>.interpolate</code><span>&#12289;</span><code>.symbolEffect</code><span> &#31561;&#24120;&#29992;&#30340;&#20869;&#23481;&#36807;&#28193;&#25928;&#26524;&#12290;</span></p><blockquote><p><span>&#22312; SwiftUI &#20013;&#65292;</span><code>transition</code><span> &#24456;&#26089;&#23601;&#25903;&#25345;&#33258;&#23450;&#20041;&#65292;&#20294;&#36825;&#31181;&#33021;&#21147;&#22987;&#32456;&#27809;&#26377;&#24310;&#20280;&#21040; Sheet&#12289;&#23548;&#33322;&#20999;&#25442;&#31561;&#26356;&#39640;&#23618;&#32423;&#30340;&#22330;&#26223;&#12290;&#36825;&#20123;&#22330;&#26223;&#19982; </span><code>contentTransition</code><span> &#31867;&#20284;&#65292;&#30446;&#21069;&#20173;&#20027;&#35201;&#20381;&#36182;&#31995;&#32479;&#25552;&#20379;&#30340;&#26377;&#38480;&#20960;&#31181;&#36807;&#28193;&#26041;&#24335;&#12290;&#26399;&#24453;&#26410;&#26469; SwiftUI &#33021;&#36827;&#19968;&#27493;&#25171;&#36890;&#36825;&#20123;&#19981;&#21516;&#23618;&#32423;&#30340; transition &#27010;&#24565;&#65292;&#25110;&#32773;&#33267;&#23569;&#20026;&#24320;&#21457;&#32773;&#25552;&#20379;&#26356;&#22810;&#33258;&#23450;&#20041;&#31354;&#38388;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-06"><span>&#29992; Scope &#20026;&#35270;&#22270;&#29366;&#24577;&#21010;&#19968;&#26465;&#36793;&#30028; (Abstracting SwiftUI state with scopes)</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#65292;&#22914;&#26524;&#35270;&#22270;&#20013;&#26377;&#22810;&#20010; </span><code>@State</code><span>&#65292;&#25105;&#20204;&#21487;&#33021;&#20250;&#23558;&#23427;&#20204;&#25277;&#35937;&#21040;&#19968;&#20010; </span><code>@Observable</code><span> &#20013;&#12290;&#20294;&#22914;&#26524;&#35270;&#22270;&#36824;&#20381;&#36182;&#20854;&#20182;&#29615;&#22659;&#20540;&#25110;&#20854;&#20182; </span><code>Observable</code><span> &#23454;&#20363;&#21602;&#65311;&#26159;&#21542;&#26377;&#19968;&#31181;&#26041;&#24335;&#65292;&#21487;&#20197;&#23558;&#26469;&#33258;&#19981;&#21516;&#25968;&#25454;&#28304;&#30340;&#29366;&#24577;&#32452;&#32455;&#21040;&#19968;&#36215;&#65292;&#21516;&#26102;&#20943;&#23569;&#35270;&#22270;&#23545;&#20855;&#20307;&#25968;&#25454;&#28304;&#30340;&#32806;&#21512;&#65311;&#8288;</span><a href="https://twitter.com/auramagi"><span>Mike Apurin</span></a><span> &#25552;&#20986;&#20102; Scope &#24605;&#36335;&#65306;&#36890;&#36807;&#20182;&#24320;&#21457;&#30340; &#8288;</span><a href="https://github.com/auramagi/swift-scoped-state"><span>ScopedState</span></a><span> &#23558;&#22810;&#20010;&#29366;&#24577;&#28304;&#32452;&#32455;&#21040;&#32479;&#19968;&#30340;&#35775;&#38382;&#36793;&#30028;&#20013;&#65292;&#21482;&#21521; View &#26292;&#38706;&#24403;&#21069;&#30028;&#38754;&#30495;&#27491;&#38656;&#35201;&#30340;&#29366;&#24577;&#21644;&#25805;&#20316;&#12290;View &#26080;&#38656;&#20102;&#35299;&#36825;&#20123;&#29366;&#24577;&#23454;&#38469;&#26469;&#33258;&#21738;&#37324;&#65292;&#20063;&#26356;&#23481;&#26131;&#22312; Preview &#21644;&#27979;&#35797;&#20013;&#26367;&#25442;&#25968;&#25454;&#26469;&#28304;&#12290;&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;&#36825;&#24182;&#19981;&#26159;&#35797;&#22270;&#21019;&#24314;&#21478;&#19968;&#22871;&#31867;&#20284; TCA &#25110; MVVM &#30340;&#29366;&#24577;&#31649;&#29702;&#27169;&#22411;&#65292;&#32780;&#26159;&#19968;&#31181;&#20316;&#29992;&#20110; View &#23618;&#32423;&#12289;&#23545;&#29616;&#26377;&#29366;&#24577;&#28304;&#36827;&#34892;&#32452;&#32455;&#21644;&#25277;&#35937;&#30340;&#26041;&#24335;&#12290;</span></p><div><hr></div><h3><strong><span>&#25240;&#21472;&#20043;&#21069;&#65306;iPhone Duo &#36866;&#37197;</span></strong></h3><p><span>iPhone Duo &#30340;&#25512;&#20986;&#35753;&#28040;&#36153;&#32773;&#22312;&#24778;&#21497;&#35774;&#22791;&#24418;&#24577;&#21464;&#21270;&#30340;&#21516;&#26102;&#65292;&#20063;&#32473;&#24320;&#21457;&#32773;&#24102;&#26469;&#20102;&#26032;&#30340;&#25361;&#25112;&#65306;&#22914;&#20309;&#21033;&#29992;&#26356;&#22823;&#30340;&#26174;&#31034;&#31354;&#38388;&#65292;&#22914;&#20309;&#35753;&#29616;&#26377;&#24067;&#23616;&#36866;&#24212;&#19981;&#21516;&#30340;&#35774;&#22791;&#24418;&#24577;&#65292;&#20197;&#21450;&#22914;&#20309;&#21033;&#29992;&#25240;&#21472;&#12289;&#22810;&#26174;&#31034;&#21306;&#22495;&#31561;&#26032;&#30340;&#20132;&#20114;&#33021;&#21147;&#12290;&#19978;&#21608;&#65292;&#19981;&#23569;&#20869;&#23481;&#21019;&#20316;&#32773;&#37117;&#20174;&#19981;&#21516;&#35282;&#24230;&#32473;&#20986;&#20102;&#33258;&#24049;&#30340;&#24314;&#35758;&#12290;</span></p><ul><li><p><span>&#33529;&#26524;&#22312;&#21457;&#24067;&#24403;&#22825;&#25918;&#20986;&#20102;&#20845;&#20010; Tech Talk&#65306;</span><a href="https://developer.apple.com/videos/play/tech-talks/111466/"><span>Design for iPhone Duo</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111461/"><span>Prepare your app</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111462/"><span>Raise the bar</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111463/"><span>Strike a pose with adaptive layouts</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111464/"><span>Leverage multiple displays and scenes</span></a><span>&#12289;</span><a href="https://developer.apple.com/videos/play/tech-talks/111465/"><span>Build a great camera experience</span></a><span>&#65292;&#24182;&#22312; HIG &#20013;&#22686;&#21152;&#20102; </span><a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo"><span>Designing for iPhone Duo</span></a><span> &#19968;&#39029;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-07"><span>Florian Schweizer</span></a><span> &#24378;&#35843;&#8220;&#19981;&#35201;&#19982;&#26694;&#26550;&#23545;&#25239;&#8221;&#65306;&#19981;&#35201;&#20174;&#21028;&#26029;&#8220;&#26159;&#19981;&#26159; iPhone Duo&#8221;&#24320;&#22987;&#65292;&#32780;&#24212;&#35813;&#38382;&#8220;&#36825;&#20010;&#35270;&#22270;&#25343;&#21040;&#20102;&#22810;&#23569;&#31354;&#8221;&#12290;&#20182;&#36824;&#23558;&#36825;&#20123;&#21407;&#21017;&#20197;&#21450; Duo &#30340;&#26032; API&#12289;Apple &#24320;&#21457;&#32773;&#36164;&#26009;&#25972;&#29702;&#25104;&#20102;&#19968;&#20010; &#8288;</span><a href="https://github.com/FloWritesCode/fwc-swiftui-skills/tree/main/skills/swiftui-iphone-duo"><span>SwiftUI iPhone Duo Skill</span></a><span>&#65292;&#20379; Coding Agent &#22312;&#36866;&#37197;&#29616;&#26377; App &#26102;&#20351;&#29992;&#12290;</span></p></li></ul><ul><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-08"><span>Lee young-jun</span></a><span> &#20174;&#29616;&#26377; App &#30340;&#23454;&#38469;&#36866;&#37197;&#20986;&#21457;&#65292;&#36890;&#36807; </span><code>NavigationSplitView</code><span>&#12289;</span><code>sidebarAdaptable</code><span>&#12289;Device Hub &#30340; Resizing Mode &#31561;&#26041;&#24335;&#65292;&#25552;&#21069;&#26816;&#26597;&#21644;&#25913;&#21892; App &#22312; iPhone Duo &#19981;&#21516;&#26174;&#31034;&#24418;&#24577;&#19979;&#30340;&#34920;&#29616;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-09"><span>Sagar Unagar</span></a><span> &#26681;&#25454; &#8288;Apple &#26368;&#26032;&#30340; HIG &#21644;&#24320;&#21457;&#32773;&#36164;&#26009;&#65292;&#26803;&#29702;&#20102; iPhone Duo &#22312;&#33258;&#36866;&#24212;&#24067;&#23616;&#12289;&#31995;&#32479;&#25511;&#20214;&#12289;&#25240;&#21472;&#21306;&#22495;&#20197;&#21450;&#19981;&#21516;&#26174;&#31034;&#24418;&#24577;&#19979;&#30340;&#20027;&#35201;&#35774;&#35745;&#21407;&#21017;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-10"><span>Jordan Morgan</span></a><span> &#24635;&#32467;&#20102;&#24320;&#21457;&#32773;&#39318;&#20808;&#38656;&#35201;&#20851;&#27880;&#30340;&#24067;&#23616;&#12289;&#31995;&#32479;&#26639;&#12289;safe area&#12289;&#30456;&#26426;&#20197;&#21450;&#22810;&#26174;&#31034;&#21306;&#22495;&#31561;&#21464;&#21270;&#12290;</span></p></li><li><p><span>&#8288;</span><a href="https://l.fatbobman.com/w0153-11"><span>Artem Mirzabekian</span></a><span> &#20171;&#32461;&#20102;&#26032;&#30340; </span><code>ArrangementView</code><span>&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#25551;&#36848;&#20004;&#32452;&#30456;&#20851;&#20869;&#23481;&#20043;&#38388;&#30340;&#20851;&#31995;&#65292;&#35753; SwiftUI &#26681;&#25454;&#21487;&#29992;&#31354;&#38388;&#21644;&#25240;&#21472;&#21306;&#22495;&#33258;&#21160;&#36873;&#25321;&#21512;&#36866;&#30340;&#24067;&#23616;&#26041;&#24335;&#12290;</span></p></li></ul><blockquote><p><span>&#19978;&#38754;&#20171;&#32461;&#30340;&#21151;&#33021;&#19981;&#23569;&#37117;&#21482;&#23384;&#22312;&#20110; Xcode 27.1 &#20013;&#65292;&#24819;&#23436;&#25972;&#20307;&#39564;&#36824;&#38656;&#35201;&#19968;&#27573;&#26102;&#38388;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0153-12"><span>SwiftMusic&#65306;&#29992; Swift &#22768;&#26126;&#38899;&#20048;</span></a></strong></h3><p><a href="https://x.com/1amageek"><span>Norikazu Muramoto</span></a><span> &#24320;&#21457;&#30340; SwiftMusic &#26159;&#19968;&#22871;&#38754;&#21521; Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#30340;&#22768;&#26126;&#24335;&#38899;&#20048;&#21019;&#20316;&#26694;&#26550;&#12290;&#23427;&#20511;&#37492;&#20102; SwiftUI &#30340;&#35774;&#35745;&#29702;&#24565;&#65292;&#23558; </span><code>Music</code><span>&#12289;</span><code>Sound</code><span>&#12289;</span><code>body</code><span>&#12289;Result Builder &#21644; Modifier &#31561;&#29087;&#24713;&#30340; Swift &#34920;&#36798;&#26041;&#24335;&#24102;&#20837;&#38899;&#20048;&#21019;&#20316;&#65292;&#35753;&#33410;&#22863;&#12289;&#26059;&#24459;&#12289;&#21644;&#22768;&#12289;&#38899;&#33394;&#12289;&#25928;&#26524;&#22120;&#21644;&#28151;&#38899;&#20851;&#31995;&#37117;&#21487;&#20197;&#36890;&#36807;&#32452;&#21512;&#20195;&#30721;&#26469;&#25551;&#36848;&#12290;</span></p><p><span>&#20363;&#22914;&#65292;&#40723;&#28857;&#12289;&#36125;&#26031;&#21644;&#21512;&#25104;&#22120;&#21487;&#20197;&#30452;&#25509;&#20889;&#25104;&#20855;&#26377;&#38899;&#20048;&#21547;&#20041;&#30340; Swift &#20195;&#30721;&#65306;</span></p><pre><code><span>struct Session: Music {</span>
<span>      var body: some Sound {</span>
<span>          Track(&#8221;Drums&#8221;) {</span>
<span>              Sample(&#8221;kick&#8221;)</span>
<span>                  .rhythm(&#8221;x ~ x ~&#8221;)</span>
<span>          }</span>
<span>&#8203;</span>
<span>          Track(&#8221;Bass&#8221;) {</span>
<span>              Synthesizer(.saw)</span>
<span>                  .notes(&#8221;C2 ~ Eb2 G2&#8221;)</span>
<span>                  .gain(0.3)</span>
<span>          }</span>
<span>      }</span>
<span>  }</span></code></pre><p><span>SwiftMusic &#26412;&#36523;&#24182;&#19981;&#21457;&#22768;&#65306;&#23427;&#21482;&#25226;&#22768;&#26126;&#32534;&#35793;&#25104;&#33410;&#25293;&#22495;&#20107;&#20214;&#19982;&#28210;&#26579;&#35745;&#21010;&#65292;&#26082;&#19981;&#25171;&#24320;&#38899;&#39057;&#35774;&#22791;&#65292;&#20063;&#19981;&#32472;&#21046;&#32534;&#36753;&#22120;&#65292;&#23454;&#38469;&#30340;&#38899;&#39057;&#28210;&#26579;&#30001;&#23487;&#20027;&#36127;&#36131;&#8212;&#8212;&#20316;&#32773;&#21478;&#22806;&#25552;&#20379;&#20102; macOS &#31471;&#30340;&#23454;&#26102;&#32534;&#36753;&#22120; </span><a href="https://github.com/1amageek/MusicPlaygournd"><span>MusicPlaygournd</span></a><span> &#26469;&#25215;&#25285;&#36825;&#37096;&#20998;&#24037;&#20316;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0153-13"><span>Homebrew 7&#65306;&#19968;&#27425;&#21578;&#21035; Intel &#30340;&#22823;&#29256;&#26412;</span></a></strong></h3><p><span>Homebrew 7.0.0 &#27491;&#24335;&#21457;&#24067;&#65292;&#38500;&#20102;&#22810;&#39033;&#21151;&#33021;&#21644;&#20869;&#37096;&#23454;&#29616;&#35843;&#25972;&#65292;&#26412;&#27425;&#22823;&#29256;&#26412;&#20063;&#24102;&#26469;&#20102;&#20540;&#24471;&#20851;&#27880;&#30340;&#20860;&#23481;&#24615;&#21464;&#21270;&#12290;&#30446;&#21069; Apple Silicon Mac &#19978;&#30340; macOS 15&#8211;27 &#23646;&#20110;&#23436;&#25972;&#25903;&#25345;&#33539;&#22260;&#65292;&#32780; Intel Mac &#24050;&#20840;&#37096;&#38477;&#20026; Tier 3&#65292;&#19981;&#20877;&#33719;&#24471;&#23436;&#25972; CI &#25903;&#25345;&#21644;&#26032;&#30340; bottles&#65292;&#24182;&#35745;&#21010;&#22312; 2027 &#24180; 9 &#26376;&#25110;&#20043;&#21518;&#24443;&#24213;&#20572;&#27490;&#25903;&#25345;&#12290;&#20173;&#22312; Intel Mac &#25110;&#36739;&#26087; macOS &#19978;&#20351;&#29992; Homebrew &#30340;&#24320;&#21457;&#32773;&#38656;&#35201;&#29305;&#21035;&#30041;&#24847;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #152]]></title><description><![CDATA[When the Mac mini&#8217;s Price Is No Longer Mini]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 07 Sep 2026 12:03:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6KxT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6KxT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6KxT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:258674,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/214512423?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6KxT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 424w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 848w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1272w, https://substackcdn.com/image/fetch/$s_!6KxT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd270a81c-deba-49f6-8fc1-3317eb6cc477_1920x1080.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@amanz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Amanz</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-an-apple-mouse-and-keyboard-oiWNsvv_oAI?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When the Mac mini&#8217;s Price Is No Longer Mini</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-152/">Read on web &#8594;</a></p><p><span>Late last month, Apple released the new Mac mini and Mac Studio. Alongside the impressive performance upgrades, the noticeably higher prices were just as striking. Rising memory and storage costs are undoubtedly a major factor, but in the AI era, developers&#8217; hardware needs are also quietly changing. More memory and more storage keep raising our idea of what counts as a &#8220;good enough&#8221; configuration&#8212;and pushing the price we actually pay even higher.</span></p><p><span>Over the past few months, one of the biggest annoyances in my development work has been the constant noise of my MacBook Pro&#8217;s fans. For years, I would only really notice them under a handful of heavy workloads. But in the age of AI agents, having the fans running has become almost routine. Limited by the space inside a laptop and the size of its fans, the noise under sustained load also tends to be more noticeable&#8212;and more irritating&#8212;than on a desktop machine like the Mac mini.</span></p><p><span>At the same time, I&#8217;ve realized that the MacBook no longer feels as indispensable to my workflow as it once did. Unless I have a specific need, a phone and a tablet are already enough for quite a few Vibe Coding scenarios on short trips. Even when I do need a laptop, a lighter and less powerful model would probably be more than sufficient. So I&#8217;ve started seriously considering moving my primary development environment from a MacBook Pro to a Mac mini or Mac Studio.</span></p><p><span>That brings up another problem: for a primary development machine, memory capacity is a hard requirement. I have almost no need to run LLMs locally, but if I&#8217;m upgrading my computer, the new machine needs to offer meaningfully more than the 64GB I already have for the upgrade to feel worthwhile. That essentially rules out the M5 Pro Mac mini, leaving me with the M5 Max and M5 Ultra Mac Studio.</span></p><p><span>Interestingly, the next memory tier above 64GB is 128GB on one and 96GB on the other, yet the final prices are remarkably close. One gives me more memory; the other, a more powerful chip. I&#8217;m not usually someone who struggles to make a choice, but this one has genuinely left me undecided.</span></p><p><span>Meanwhile, OpenClaw&#8217;s popularity has drawn the attention of many consumers who previously had little interest in the Mac mini. OpenAI has also reportedly purchased tens of thousands of Mac minis and Mac Studios for reinforcement learning and training computer-use agents. AI-driven demand at one point grew far faster than Apple had anticipated. Combined with pressure on memory supply and advanced chip manufacturing capacity, this has kept the Mac mini and Mac Studio in short supply over the past few months. Even with the new generation now available, getting the exact configuration you want quickly is still not necessarily easy.</span></p><p><span>The productivity gains brought by AI may not yet be fully visible across society, but its appetite for compute, memory, and storage resources is already showing up in the hardware market. From components to complete systems, a wide range of consumer hardware is facing new pricing pressure. The old upgrade cycle&#8212;waiting a few years and spending roughly the same amount for a substantially more powerful computer&#8212;seems increasingly difficult to sustain, at least for now.</span></p><p><span>But there&#8217;s another side to the story: we can&#8217;t blame everything on rising prices. While AI is pushing hardware costs upward, it is also changing how we develop software and quietly raising our definition of what counts as a &#8220;good enough computer.&#8221; Hardware has become more expensive, but we&#8217;ve also started asking more of it.</span></p><p><span>Hopefully, one day we&#8217;ll get back to a time when buying a Mac mini doesn&#8217;t require quite so much mental preparation.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-151/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/swiftdata-optimization-starts-with-modeling/?utm_source=fatbobman%20weekly%20issue%20152&amp;utm_medium=web"><span>SwiftData: Optimization Starts with Modeling</span></a></strong></h3><p><span>Once the dataset grows large, SwiftData lists start to lag. This is one of the performance complaints I&#8217;ve heard most often over the past few years. Developers&#8217; first instinct is usually to blame SwiftUI&#8217;s </span><code>List</code><span>. It certainly bears some responsibility, but it isn&#8217;t the main culprit. A closer look reveals that long loading times aren&#8217;t the only thing dragging down performance&#8212;massive memory consumption is just as important. In this article, I&#8217;ll explore why these problems arise in SwiftData and why optimization should start with data modeling.</span></p><blockquote><p><span>Some capabilities that appear to be missing from SwiftData may actually have been left out intentionally, reducing the learning curve by exposing fewer APIs and abstraction layers. Therefore, when optimizing SwiftData applications, it&#8217;s also worth letting go of some habits carried over from the Core Data era.</span></p></blockquote><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-01"><span>The End of Swift Talk</span></a></strong></h3><p><span>After ten years and 500 episodes, </span><a href="https://x.com/chriseidhof"><span>Chris Eidhof</span></a><span> and </span><a href="https://x.com/floriankugler"><span>Florian Kugler</span></a><span> have announced the end of Swift Talk. Since its launch in June 2016, Swift Talk has accompanied Swift through nearly its entire journey toward maturity, while also witnessing SwiftUI grow from its introduction into a core UI framework for Apple platform development. Through a long series of deep and highly experimental episodes, the two explored Swift, SwiftUI, layout, animation, concurrency, and many lower-level topics rarely covered in conventional tutorials. They hope to make the complete archive of more than 500 episodes available to the community by the end of this year.</span></p><p><span>For me, objc.io and Swift Talk have always occupied a very special place in the Swift community. Chris and Florian were rarely satisfied with simply telling developers how an API &#8220;should be used.&#8221; Instead, they would experiment, refactor, and sometimes even reimplement things to understand why a framework works the way it does. This approach to exploration has influenced many Swift developers, myself included. Thank you, Chris and Florian, for the time, knowledge, and curiosity you&#8217;ve contributed to the Swift community over all these years, and for the invaluable archive Swift Talk leaves behind.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-02"><span>What&#8217;s new in Swift: August 2026 Edition</span></a></strong></h3><p><span>Swift has published its August ecosystem update, curated by </span><a href="https://github.com/sliemeobn/"><span>Simon Leeb</span></a><span> and </span><a href="https://www.linkedin.com/in/davelester-dev/"><span>Dave Lester</span></a><span>, covering noteworthy community projects, package updates, and Swift Evolution developments. What interests me most is Swift&#8217;s progress on the Web: Simon Leeb demonstrated a </span><a href="https://cloudflare-worker.examples.elementary.codes/"><span>Full-Stack Swift on Cloudflare Demo</span></a><span>, with Swift running in the browser through ElementaryUI and WebAssembly, a backend running on an edge worker, and message types shared between the two sides. From Embedded Swift and Wasm to an increasingly capable cross-platform toolchain, Swift continues to expand its reach beyond Apple platforms.</span></p><p><span>At the language level, the recently accepted </span><a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0516-borrowing-sequence.md"><span>Iterable</span></a><span> is also worth watching. </span><code>Sequence</code><span> produces independent element values one by one during iteration, but this model doesn&#8217;t work for data structures such as </span><code>Span</code><span> and </span><code>InlineArray</code><span> that may contain non-copyable elements. </span><code>Iterable</code><span> allows elements to be borrowed rather than copied during iteration, giving these data structures a natural way to be traversed as well. It may look like just another iteration abstraction, but it is also another sign of Swift&#8217;s ownership capabilities gradually moving from the language&#8217;s lower levels into everyday API design.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-03"><span>OpenSwiftUI on ESP32-C3</span></a></strong></h3><p><span>The Swift update above showed how Swift continues to push beyond the boundaries of Apple platforms, and a recent experiment by OpenSwiftUI developer </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> provides a very tangible example of that trend. After receiving an </span><a href="https://ai-passport.folotoy.cn/"><span>ESP32-C3 development device</span></a><span> from TraeAI, Kyle completed his first Embedded Swift project: deploying an embedded version of OpenSwiftUI to this RISC-V-based microcontroller. On its 240 &#215; 320 LCD, he built interfaces using familiar APIs such as </span><code>View</code><span>, </span><code>@ViewBuilder</code><span>, </span><code>Text</code><span>, </span><code>Image</code><span>, </span><code>VStack</code><span>, </span><code>HStack</code><span>, and </span><code>ZStack</code><span>. Even </span><code>@State</code><span> can respond to physical button input and trigger UI updates.</span></p><p><span>The experiment uses Embedded Swift to compile native RISC-V code, with OpenSwiftUI handling view composition and layout before passing drawing through a thin rendering boundary to LVGL and the underlying hardware. In other words, a lean but complete UI pipeline has been established, from declarative views and layout calculation to state updates and final pixel output.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-04"><span>Multiplatform Swift, with C++ dependencies via XCFramework, apt and vcpkg</span></a></strong></h3><p><span>Whether a Swift application can truly become cross-platform often depends on whether its underlying C/C++ dependencies can make the journey as well. </span><a href="https://www.linkedin.com/in/harald-achitz/"><span>Harald Achitz</span></a><span> uses his own ZeroMQ Swift bindings as an example to show how a Swift/C++ project targeting macOS, Linux, and Windows can organize its native dependencies: XCFrameworks on Apple platforms, system packages on Linux, and vcpkg to install ZeroMQ on Windows.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-05"><span>Connecting two iOS simulators over BLE</span></a></strong></h3><p><span>CoreBluetooth is completely unavailable in the iOS Simulator, which has long made BLE app development and testing dependent on physical devices. While developing </span><a href="https://github.com/kylebrowning/BLESwift"><span>BLESwift 2.0</span></a><span>, </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> took a different approach: instead of calling CoreBluetooth, the central and peripheral devices in the Simulator forward their operations over localhost TCP to </span><code>bleswift-provider</code><span> running on the Mac, which creates a &#8220;virtual radio.&#8221; This allows two Simulators to discover, connect to, read from, write to, and receive notifications from each other much like two real BLE devices. A passthrough mode can even use the Mac&#8217;s Bluetooth hardware to communicate with real BLE devices.</span></p><blockquote><p><span>What interests me more than BLE itself is the testing pattern behind this approach: when the Simulator lacks a particular system or hardware capability, instead of scattering mocks throughout the app, we can establish a replaceable backend between system capabilities and business logic, then use a proxy process on the Mac to recreate a controllable external world. This design not only addresses missing system or hardware capabilities in the Simulator, but also makes features that once depended heavily on real-world environments much easier to bring into automated testing and CI.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-06"><span>Reorder all the things in SwiftUI</span></a></strong></h3><p><span>SwiftUI has long lacked a general-purpose API for drag-to-reorder interactions in arbitrary containers, a limitation that was finally addressed after WWDC 2026. </span><a href="https://x.com/SwiftyAlex"><span>Alexander Logan</span></a><span> introduces SwiftUI&#8217;s new reordering APIs. With APIs such as </span><code>reorderable</code><span> and </span><code>reorderableContainer</code><span>, developers can directly declare which content can be reordered and its associated data model. Reordering is no longer limited to </span><code>List</code><span>, nor do developers need to manage drop positions and data updates themselves through </span><code>DropDelegate</code><span>. More importantly, the new APIs provide a higher-level interaction semantic, separating &#8220;reordering&#8221; from drag and drop as a specific implementation mechanism. Developers describe the intent that &#8220;this content can be reordered,&#8221; while the system can take greater responsibility for whether that interaction is performed with a mouse, touch, or another input method.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-07"><span>Building a sunburst diagram in Swift Charts</span></a></strong></h3><p><span>A Sunburst Diagram is a chart that uses concentric rings to represent hierarchical data&#8212;for example, moving from &#8220;Work&#8221; to &#8220;Development&#8221; and then to a specific project, with each outward ring representing a deeper level of detail. </span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to use Swift Charts&#8217; </span><code>SectorMark</code><span> to start with a regular pie chart and gradually build a three-level sunburst diagram. The implementation also nicely demonstrates the flexibility of Swift Charts: when the framework doesn&#8217;t directly provide a particular chart type, Marks such as </span><code>SectorMark</code><span> can be treated as lower-level visualization primitives, allowing more complex charts to be constructed by calculating angular ranges and data mappings manually.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-08"><span>CoreDataBrowser: Quickly Inspect Local Data in the Simulator</span></a></strong></h3><p><span>When debugging Core Data or SwiftData apps, you typically need to locate the relevant data files buried deep within the Simulator&#8217;s directory hierarchy, then open them in a SQLite manager to inspect the data. CoreDataBrowser, developed by </span><a href="https://www.linkedin.com/in/csaba-turdesan-880182251/"><span>Csaba Turdesan</span></a><span>, aims to simplify this process: after selecting the currently running Simulator, it automatically locates Core Data, SwiftData, and UserDefaults data sources in app containers and presents them together in a native macOS interface.</span></p><p><span>CoreDataBrowser supports browsing tables and records, searching and highlighting matches, and attempting to decode certain binary data (BLOBs) as NSKeyedArchive, JSON, Property List, or UTF-8 text. The tool is tiny (2.5 MB), and its </span><a href="https://github.com/kyletaylor94/CoreDataBrowser"><span>source code is publicly available</span></a><span>.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-152?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403; Mac mini &#30340;&#20215;&#26684;&#19981;&#20877; mini</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-152/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#26376;&#24213;&#65292;&#33529;&#26524;&#21457;&#24067;&#20102;&#26032;&#30340; Mac mini &#21644; Mac Studio&#12290;&#38500;&#20102;&#24378;&#24717;&#30340;&#24615;&#33021;&#26356;&#26032;&#65292;&#26126;&#26174;&#19978;&#28072;&#30340;&#20215;&#26684;&#21516;&#26679;&#32473;&#20154;&#24102;&#26469;&#20102;&#19981;&#23567;&#30340;&#38663;&#25788;&#12290;&#20869;&#23384;&#19982;&#23384;&#20648;&#25104;&#26412;&#19978;&#28072;&#26080;&#30097;&#26159;&#26412;&#36718;&#28072;&#20215;&#30340;&#37325;&#35201;&#21407;&#22240;&#65292;&#20294;&#22312; AI &#26102;&#20195;&#65292;&#24320;&#21457;&#32773;&#23545;&#30828;&#20214;&#30340;&#38656;&#27714;&#20063;&#22312;&#24708;&#28982;&#21457;&#29983;&#21464;&#21270;&#12290;&#26356;&#22823;&#30340;&#20869;&#23384;&#12289;&#26356;&#39640;&#30340;&#23384;&#20648;&#23481;&#37327;&#65292;&#19981;&#26029;&#25512;&#39640;&#25105;&#20204;&#24515;&#30446;&#20013;&#8220;&#22815;&#29992;&#37197;&#32622;&#8221;&#30340;&#26631;&#20934;&#65292;&#26368;&#32456;&#20063;&#35753;&#23454;&#38469;&#36141;&#20080;&#20215;&#26684;&#21464;&#24471;&#26356;&#21152;&#22840;&#24352;&#12290;</span></p><p><span>&#36807;&#21435;&#20960;&#20010;&#26376;&#65292;&#24320;&#21457;&#20013;&#26368;&#35753;&#25105;&#22836;&#30171;&#30340;&#19968;&#20214;&#20107;&#65292;&#26159; MacBook Pro &#39118;&#25159;&#25345;&#32493;&#36716;&#21160;&#24102;&#26469;&#30340;&#22122;&#38899;&#12290;&#36807;&#21435;&#22810;&#24180;&#30340;&#20351;&#29992;&#20013;&#65292;&#21482;&#26377;&#22312;&#23569;&#25968;&#39640;&#36127;&#36733;&#22330;&#26223;&#19979;&#65292;&#25105;&#25165;&#20250;&#26126;&#26174;&#24847;&#35782;&#21040;&#39118;&#25159;&#30340;&#23384;&#22312;&#12290;&#20294;&#21040;&#20102; AI Agent &#26102;&#20195;&#65292;&#39118;&#25159;&#24120;&#36716;&#20960;&#20046;&#25104;&#20102;&#23478;&#24120;&#20415;&#39277;&#12290;&#21463;&#38480;&#20110;&#26426;&#36523;&#31354;&#38388;&#21644;&#39118;&#25159;&#23610;&#23544;&#65292;&#31508;&#35760;&#26412;&#22312;&#25345;&#32493;&#39640;&#36127;&#36733;&#19979;&#20135;&#29983;&#30340;&#22122;&#38899;&#65292;&#24448;&#24448;&#20063;&#27604; Mac mini &#36825;&#31867;&#26700;&#38754;&#35774;&#22791;&#26356;&#23481;&#26131;&#35753;&#20154;&#24863;&#21040;&#19981;&#36866;&#12290;</span></p><p><span>&#19982;&#27492;&#21516;&#26102;&#65292;&#25105;&#21457;&#29616; MacBook &#22312;&#33258;&#24049;&#30340;&#24037;&#20316;&#27969;&#20013;&#20284;&#20046;&#20063;&#27809;&#26377;&#20197;&#21069;&#37027;&#20040;&#19981;&#21487;&#26367;&#20195;&#20102;&#12290;&#38500;&#38750;&#26377;&#29305;&#27530;&#38656;&#35201;&#65292;&#30701;&#36884;&#20986;&#24046;&#26102;&#65292;&#25163;&#26426;&#21644;&#24179;&#26495;&#24050;&#32463;&#36275;&#20197;&#24212;&#20184;&#19981;&#23569; Vibe Coding &#22330;&#26223;&#12290;&#21363;&#20415;&#20173;&#28982;&#38656;&#35201;&#19968;&#21488;&#31508;&#35760;&#26412;&#65292;&#19968;&#21488;&#26356;&#36731;&#12289;&#37197;&#32622;&#26356;&#20302;&#30340;&#35774;&#22791;&#20284;&#20046;&#20063;&#23436;&#20840;&#22815;&#29992;&#12290;&#22240;&#27492;&#65292;&#25105;&#24320;&#22987;&#35748;&#30495;&#32771;&#34385;&#25226;&#20027;&#21147;&#24320;&#21457;&#35774;&#22791;&#20174; MacBook Pro &#36716;&#31227;&#21040; Mac mini &#25110; Mac Studio &#19978;&#12290;</span></p><p><span>&#38382;&#39064;&#38543;&#20043;&#32780;&#26469;&#65306;&#20316;&#20026;&#20027;&#21147;&#24320;&#21457;&#35774;&#22791;&#65292;&#20869;&#23384;&#23481;&#37327;&#24517;&#28982;&#26159;&#19968;&#36947;&#30828;&#38376;&#27099;&#12290;&#23613;&#31649;&#25105;&#20960;&#20046;&#27809;&#26377;&#36816;&#34892;&#26412;&#22320; LLM &#30340;&#38656;&#27714;&#65292;&#20294;&#26082;&#28982;&#26159;&#19968;&#27425;&#35774;&#22791;&#26356;&#26032;&#65292;&#26032;&#26426;&#22120;&#30340;&#20869;&#23384;&#33267;&#23569;&#24212;&#35813;&#26126;&#26174;&#39640;&#20110;&#24403;&#21069;&#30340; 64GB&#65292;&#25165;&#33021;&#35753;&#25105;&#24863;&#21463;&#21040;&#36275;&#22815;&#30340;&#21319;&#32423;&#20215;&#20540;&#12290;&#22914;&#27492;&#19968;&#26469;&#65292;&#37319;&#29992; M6 &#25110; M5 Pro &#30340; Mac mini &#22522;&#26412;&#23601;&#34987;&#25490;&#38500;&#20102;&#65292;&#21097;&#19979;&#30340;&#36873;&#25321;&#21482;&#26377; M5 Max &#21644; M5 Ultra &#30340; Mac Studio&#12290;</span></p><p><span>&#26377;&#36259;&#30340;&#26159;&#65292;&#20004;&#27454;&#26426;&#22411;&#22312; 64GB &#20043;&#19978;&#30340;&#19979;&#19968;&#26723;&#20869;&#23384;&#20998;&#21035;&#26159; 128GB &#21644; 96GB&#65292;&#32780;&#26368;&#32456;&#20215;&#26684;&#21364;&#30456;&#24046;&#26080;&#20960;&#12290;&#19968;&#20010;&#32473;&#26356;&#22810;&#20869;&#23384;&#65292;&#19968;&#20010;&#32473;&#26356;&#24378;&#33455;&#29255;&#12290;&#21363;&#20415;&#25105;&#24179;&#26102;&#24182;&#19981;&#31639;&#26377;&#36873;&#25321;&#22256;&#38590;&#65292;&#36825;&#27425;&#20063;&#30830;&#23454;&#26377;&#20123;&#29359;&#38590;&#12290;</span></p><p><span>&#19982;&#27492;&#21516;&#26102;&#65292;OpenClaw &#30340;&#39118;&#34892;&#35753;&#19981;&#23569;&#21407;&#26412;&#24182;&#19981;&#20851;&#27880; Mac mini &#30340;&#28040;&#36153;&#32773;&#24320;&#22987;&#23558;&#30446;&#20809;&#25237;&#21521;&#36825;&#21488;&#23567;&#26426;&#22120;&#12290;&#25454;&#25253;&#36947;&#65292;OpenAI &#20063;&#37319;&#36141;&#20102;&#25968;&#19975;&#21488; Mac mini &#21644; Mac Studio&#65292;&#29992;&#20110;&#24378;&#21270;&#23398;&#20064;&#21644; Computer-use Agent &#30340;&#35757;&#32451;&#12290;AI &#24102;&#26469;&#30340;&#38656;&#27714;&#22686;&#38271;&#19968;&#24230;&#36828;&#36229;&#33529;&#26524;&#30340;&#39044;&#26399;&#65292;&#20877;&#21152;&#19978;&#20869;&#23384;&#20379;&#24212;&#21644;&#20808;&#36827;&#21046;&#31243;&#20135;&#33021;&#30340;&#21387;&#21147;&#65292;&#35753; Mac mini &#21644; Mac Studio &#22312;&#36807;&#21435;&#20960;&#20010;&#26376;&#19968;&#30452;&#22788;&#20110;&#20379;&#19981;&#24212;&#27714;&#30340;&#29366;&#24577;&#12290;&#26032;&#19968;&#20195;&#20135;&#21697;&#21457;&#24067;&#20043;&#21518;&#65292;&#24819;&#35201;&#23613;&#24555;&#25343;&#21040;&#33258;&#24049;&#24515;&#20202;&#30340;&#37197;&#32622;&#65292;&#20381;&#28982;&#19981;&#26159;&#19968;&#20214;&#23481;&#26131;&#30340;&#20107;&#12290;</span></p><p><span>AI &#24102;&#26469;&#30340;&#25928;&#29575;&#25552;&#21319;&#25110;&#35768;&#36824;&#27809;&#26377;&#22312;&#25972;&#20010;&#31038;&#20250;&#20013;&#20805;&#20998;&#26174;&#29616;&#65292;&#20294;&#23427;&#23545;&#31639;&#21147;&#12289;&#20869;&#23384;&#21644;&#23384;&#20648;&#36164;&#28304;&#30340;&#20105;&#22842;&#65292;&#24050;&#32463;&#29575;&#20808;&#21453;&#26144;&#21040;&#20102;&#30828;&#20214;&#24066;&#22330;&#12290;&#20174;&#38646;&#37096;&#20214;&#21040;&#25972;&#26426;&#65292;&#22823;&#37327;&#28040;&#36153;&#32423;&#30828;&#20214;&#37117;&#22312;&#25215;&#21463;&#26032;&#30340;&#20215;&#26684;&#21387;&#21147;&#12290;&#36807;&#21435;&#37027;&#31181;&#38548;&#20960;&#24180;&#29992;&#24046;&#19981;&#22810;&#30340;&#38065;&#65292;&#23601;&#33021;&#20080;&#21040;&#19968;&#21488;&#26126;&#26174;&#26356;&#24378;&#30005;&#33041;&#30340;&#26356;&#26032;&#33410;&#22863;&#65292;&#33267;&#23569;&#22312;&#29616;&#38454;&#27573;&#20284;&#20046;&#36234;&#26469;&#36234;&#38590;&#32500;&#25345;&#20102;&#12290;</span></p><p><span>&#20294;&#26356;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#25105;&#20204;&#21448;&#19981;&#33021;&#25226;&#36825;&#19968;&#20999;&#23436;&#20840;&#24402;&#21646;&#20110;&#28072;&#20215;&#12290;AI &#22312;&#25512;&#39640;&#30828;&#20214;&#25104;&#26412;&#30340;&#21516;&#26102;&#65292;&#20063;&#25913;&#21464;&#20102;&#25105;&#20204;&#30340;&#24320;&#21457;&#26041;&#24335;&#65292;&#24182;&#24708;&#24708;&#25260;&#39640;&#20102;&#25105;&#20204;&#23545;&#19968;&#21488;&#8220;&#22815;&#29992;&#30005;&#33041;&#8221;&#30340;&#23450;&#20041;&#12290;&#30828;&#20214;&#21464;&#36149;&#20102;&#65292;&#25105;&#20204;&#24819;&#35201;&#30340;&#20063;&#26356;&#22810;&#20102;&#12290;</span></p><p><span>&#24076;&#26395;&#26410;&#26469;&#26576;&#19968;&#22825;&#65292;&#25105;&#20204;&#36824;&#33021;&#25214;&#22238;&#37027;&#20010;&#19981;&#29992;&#20570;&#22826;&#22810;&#24515;&#29702;&#24314;&#35774;&#65292;&#23601;&#33021;&#36731;&#26494;&#36873;&#36141;&#19968;&#21488; Mac mini &#30340;&#26102;&#20195;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-151/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/swiftdata-optimization-starts-with-modeling/?utm_source=fatbobman%20weekly%20issue%20152&amp;utm_medium=web"><span>SwiftData&#65306;&#20248;&#21270;&#20174;&#24314;&#27169;&#24320;&#22987;</span></a></strong></h3><p><span>&#25968;&#25454;&#38598;&#19968;&#22823;&#65292;SwiftData &#30340;&#21015;&#34920;&#23601;&#24320;&#22987;&#21345;&#12290;&#36825;&#26159;&#36825;&#20960;&#24180;&#37324;&#25105;&#21548;&#21040;&#26368;&#22810;&#30340;&#24615;&#33021;&#25265;&#24616;&#12290;&#24320;&#21457;&#32773;&#30340;&#31532;&#19968;&#21453;&#24212;&#36890;&#24120;&#20250;&#25351;&#21521; SwiftUI &#30340; </span><code>List</code><span>&#12290;&#23427;&#30830;&#23454;&#26377;&#36131;&#20219;&#65292;&#20294;&#24182;&#38750;&#26368;&#20027;&#35201;&#30340;&#38382;&#39064;&#12290;&#36827;&#19968;&#27493;&#20998;&#26512;&#20250;&#21457;&#29616;&#65292;&#30495;&#27491;&#25302;&#22446;&#24615;&#33021;&#30340;&#19981;&#21482;&#26159;&#21152;&#36733;&#26102;&#38388;&#65292;&#24040;&#22823;&#30340;&#20869;&#23384;&#21344;&#29992;&#21516;&#26679;&#19981;&#23481;&#24573;&#35270;&#12290;&#26412;&#25991;&#23558;&#32842;&#32842; SwiftData &#20026;&#20160;&#20040;&#20250;&#20986;&#29616;&#36825;&#20123;&#38382;&#39064;&#65292;&#20197;&#21450;&#20248;&#21270;&#20026;&#20160;&#20040;&#24212;&#35813;&#20174;&#25968;&#25454;&#24314;&#27169;&#24320;&#22987;&#12290;</span></p><blockquote><p><span>SwiftData &#20013;&#19968;&#20123;&#30475;&#20284;&#32570;&#22833;&#30340;&#33021;&#21147;&#65292;&#25110;&#35768;&#26412;&#23601;&#26159;&#26377;&#24847;&#20026;&#20043;&#65306;&#36890;&#36807;&#20943;&#23569;&#26292;&#38706;&#30340; API &#21644;&#36923;&#36753;&#23618;&#26469;&#38477;&#20302;&#23398;&#20064;&#26354;&#32447;&#12290;&#22240;&#27492;&#65292;&#22312;&#20248;&#21270; SwiftData &#24212;&#29992;&#26102;&#65292;&#20063;&#24212;&#35813;&#36866;&#24403;&#25918;&#19979; Core Data &#26102;&#20195;&#24418;&#25104;&#30340;&#19968;&#20123;&#24815;&#24615;&#24605;&#32500;&#12290;</span></p></blockquote><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-01"><span>&#21313;&#24180;&#32456;&#31456;&#65306;Swift Talk &#23459;&#24067;&#20572;&#26356; (The End of Swift Talk)</span></a></strong></h3><p><span>&#22312;&#24320;&#22987;&#21313;&#24180;&#12289;&#23436;&#25104; 500 &#26399;&#33410;&#30446;&#21518;&#65292;&#8288;</span><a href="https://x.com/chriseidhof"><span>Chris Eidhof</span></a><span> &#21644; &#8288;</span><a href="https://x.com/floriankugler"><span>Florian Kugler</span></a><span> &#23459;&#24067; Swift Talk &#27491;&#24335;&#32467;&#26463;&#12290;&#20174; 2016 &#24180; 6 &#26376;&#24320;&#22987;&#65292;Swift Talk &#20960;&#20046;&#23436;&#25972;&#38506;&#20276;&#20102; Swift &#36208;&#21521;&#25104;&#29087;&#30340;&#36807;&#31243;&#65292;&#20063;&#35265;&#35777;&#20102; SwiftUI &#20174;&#35806;&#29983;&#21040;&#36880;&#28176;&#25104;&#20026; Apple &#24179;&#21488; UI &#24320;&#21457;&#26680;&#24515;&#26694;&#26550;&#30340;&#36825;&#20123;&#24180;&#12290;&#20004;&#20154;&#36890;&#36807;&#19968;&#31995;&#21015;&#28145;&#20837;&#32780;&#21448;&#20805;&#28385;&#23454;&#39564;&#24615;&#30340;&#33410;&#30446;&#65292;&#25506;&#32034;&#20102; Swift&#12289;SwiftUI&#12289;&#24067;&#23616;&#12289;&#21160;&#30011;&#12289;&#24182;&#21457;&#20197;&#21450;&#22823;&#37327;&#24456;&#38590;&#22312;&#26222;&#36890;&#25945;&#31243;&#20013;&#30475;&#21040;&#30340;&#24213;&#23618;&#38382;&#39064;&#12290;&#23448;&#26041;&#34920;&#31034;&#65292;&#24076;&#26395;&#22312;&#20170;&#24180;&#24180;&#24213;&#35753;&#23436;&#25972;&#30340; 500 &#22810;&#26399;&#33410;&#30446;&#24402;&#26723;&#33021;&#22815;&#32487;&#32493;&#25552;&#20379;&#32473;&#31038;&#21306;&#12290;</span></p><p><span>&#23545;&#25105;&#32780;&#35328;&#65292;objc.io &#21644; Swift Talk &#19968;&#30452;&#26159; Swift &#31038;&#21306;&#20013;&#38750;&#24120;&#29305;&#21035;&#30340;&#23384;&#22312;&#12290;Chris &#21644; Florian &#24456;&#23569;&#28385;&#36275;&#20110;&#21578;&#35785;&#24320;&#21457;&#32773;&#19968;&#20010; API &#8220;&#24212;&#35813;&#24590;&#20040;&#29992;&#8221;&#65292;&#32780;&#26159;&#20064;&#24815;&#36890;&#36807;&#23454;&#39564;&#12289;&#37325;&#26500;&#29978;&#33267;&#37325;&#26032;&#23454;&#29616;&#65292;&#21435;&#36861;&#38382;&#26694;&#26550;&#20026;&#20160;&#20040;&#20250;&#36825;&#26679;&#24037;&#20316;&#12290;&#36825;&#31181;&#25506;&#32034;&#26041;&#24335;&#24433;&#21709;&#20102;&#35768;&#22810; Swift &#24320;&#21457;&#32773;&#65292;&#20063;&#21253;&#25324;&#25105;&#33258;&#24049;&#12290;&#24863;&#35874; Chris &#21644; Florian &#36825;&#20123;&#24180;&#26469;&#20026; Swift &#31038;&#21306;&#25237;&#20837;&#30340;&#26102;&#38388;&#12289;&#30693;&#35782;&#19982;&#22909;&#22855;&#24515;&#65292;&#20063;&#24863;&#35874; Swift Talk &#30041;&#19979;&#30340;&#36825;&#20221;&#29645;&#36149;&#26723;&#26696;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-02"><span>Swift &#23448;&#26041; 8 &#26376;&#25253; (What&#8217;s new in Swift: August 2026 Edition)</span></a></strong></h3><p><span>Swift &#23448;&#26041;&#21457;&#24067;&#20102; 8 &#26376;&#29983;&#24577;&#26376;&#25253;&#65292;&#30001; &#8288;</span><a href="https://github.com/sliemeobn/"><span>Simon Leeb</span></a><span> &#21644; &#8288;</span><a href="https://www.linkedin.com/in/davelester-dev/"><span>Dave Lester</span></a><span> &#25972;&#29702;&#65292;&#27719;&#24635;&#20102;&#36817;&#26399;&#20540;&#24471;&#20851;&#27880;&#30340;&#31038;&#21306;&#39033;&#30446;&#12289;Package &#26356;&#26032;&#21644; Swift Evolution &#36827;&#23637;&#12290;&#20854;&#20013;&#26368;&#35753;&#25105;&#24863;&#20852;&#36259;&#30340;&#26159; Swift &#22312; Web &#26041;&#21521;&#19978;&#30340;&#25512;&#36827;&#65306;Simon Leeb &#23637;&#31034;&#20102;&#19968;&#20010; &#8288;</span><a href="https://cloudflare-worker.examples.elementary.codes/"><span>Full-Stack Swift on Cloudflare Demo</span></a><span>&#65292;&#27983;&#35272;&#22120;&#31471;&#36890;&#36807; ElementaryUI &#21644; WebAssembly &#36816;&#34892; Swift&#65292;&#21518;&#31471;&#21017;&#36816;&#34892;&#22312; edge worker &#19978;&#65292;&#20004;&#31471;&#36824;&#33021;&#20849;&#20139;&#28040;&#24687;&#31867;&#22411;&#12290;&#20174; Embedded Swift&#12289;Wasm &#21040;&#36234;&#26469;&#36234;&#23436;&#21892;&#30340;&#36328;&#24179;&#21488;&#24037;&#20855;&#38142;&#65292;Swift &#30340;&#20351;&#29992;&#36793;&#30028;&#27491;&#22312;&#32487;&#32493;&#21521; Apple &#24179;&#21488;&#20043;&#22806;&#25193;&#23637;&#12290;</span></p><p><span>&#35821;&#35328;&#23618;&#38754;&#65292;&#21018;&#21018;&#33719;&#25209;&#30340; &#8288;&#8288;</span><a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0516-borrowing-sequence.md"><span>Iterable</span></a><span> &#20063;&#24456;&#20540;&#24471;&#20851;&#27880;&#12290;</span><code>Sequence</code><span> &#22312;&#36941;&#21382;&#26102;&#20250;&#36880;&#20010;&#20135;&#29983;&#29420;&#31435;&#30340;&#20803;&#32032;&#20540;&#65292;&#20294;&#23545;&#20110; </span><code>Span</code><span>&#12289;</span><code>InlineArray</code><span> &#31561;&#21487;&#33021;&#21253;&#21547; non-copyable &#20803;&#32032;&#30340;&#25968;&#25454;&#32467;&#26500;&#65292;&#36825;&#22871;&#27169;&#22411;&#24182;&#19981;&#36866;&#29992;&#12290;</span><code>Iterable</code><span> &#20801;&#35768;&#30452;&#25509;&#20511;&#29992;&#32780;&#38750;&#22797;&#21046;&#20803;&#32032;&#36827;&#34892;&#36941;&#21382;&#65292;&#35753;&#36825;&#20123;&#25968;&#25454;&#32467;&#26500;&#20063;&#33021;&#25317;&#26377;&#33258;&#28982;&#30340;&#36941;&#21382;&#26041;&#24335;&#12290;&#23427;&#30475;&#36215;&#26469;&#21482;&#26159;&#19968;&#20010;&#26032;&#30340;&#36941;&#21382;&#25277;&#35937;&#65292;&#21364;&#20063;&#26159; Swift ownership &#33021;&#21147;&#36880;&#28176;&#20174;&#35821;&#35328;&#24213;&#23618;&#36208;&#21521;&#26085;&#24120; API &#35774;&#35745;&#30340;&#21448;&#19968;&#20010;&#20307;&#29616;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-03"><span>&#22312;&#23884;&#20837;&#24335;&#35774;&#22791;&#19978;&#36816;&#34892; OpenSwiftUI (OpenSwiftUI on ESP32-C3)</span></a></strong></h3><p><span>&#19978;&#38754;&#30340; Swift &#26376;&#25253;&#23637;&#31034;&#20102; Swift &#27491;&#22312;&#19981;&#26029;&#31361;&#30772; Apple &#24179;&#21488;&#30340;&#36793;&#30028;&#65292;&#32780; OpenSwiftUI &#24320;&#21457;&#32773; &#8288;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#26368;&#36817;&#30340;&#19968;&#27425;&#23581;&#35797;&#65292;&#21017;&#32473;&#36825;&#20010;&#36235;&#21183;&#25552;&#20379;&#20102;&#19968;&#20010;&#24456;&#30452;&#35266;&#30340;&#20363;&#23376;&#12290;&#22312;&#25910;&#21040; TraeAI &#36192;&#36865;&#30340; </span><a href="https://ai-passport.folotoy.cn/"><span>ESP32-C3 &#24320;&#21457;&#35774;&#22791;</span></a><span>&#21518;&#65292;Kyle &#23436;&#25104;&#20102;&#33258;&#24049;&#30340;&#31532;&#19968;&#20010; Embedded Swift &#39033;&#30446;&#65306;&#23558; OpenSwiftUI &#30340;&#23884;&#20837;&#24335;&#29256;&#26412;&#37096;&#32626;&#21040;&#36825;&#22359;&#37319;&#29992; RISC-V &#26550;&#26500;&#30340;&#24494;&#25511;&#21046;&#22120;&#19978;&#65292;&#24182;&#22312; 240 &#215; 320 &#30340; LCD &#19978;&#20351;&#29992;&#25105;&#20204;&#29087;&#24713;&#30340; </span><code>View</code><span>&#12289;</span><code>@ViewBuilder</code><span>&#12289;</span><code>Text</code><span>&#12289;</span><code>Image</code><span>&#12289;</span><code>VStack</code><span>&#12289;</span><code>HStack</code><span>&#12289;</span><code>ZStack</code><span> &#31561; API &#26500;&#24314;&#30028;&#38754;&#65292;&#29978;&#33267; </span><code>@State</code><span> &#20063;&#33021;&#21709;&#24212;&#23454;&#20307;&#25353;&#38190;&#24182;&#35302;&#21457;&#30028;&#38754;&#26356;&#26032;&#12290;</span></p><p><span>&#36825;&#20010;&#23454;&#39564;&#21033;&#29992; Embedded Swift &#32534;&#35793;&#21407;&#29983; RISC-V &#20195;&#30721;&#65292;&#30001; OpenSwiftUI &#36127;&#36131;&#35270;&#22270;&#32452;&#21512;&#21644;&#24067;&#23616;&#65292;&#20877;&#36890;&#36807;&#19968;&#20010;&#24456;&#34180;&#30340;&#28210;&#26579;&#36793;&#30028;&#23558;&#32472;&#21046;&#20132;&#32473; LVGL &#21644;&#24213;&#23618;&#30828;&#20214;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#20174;&#22768;&#26126;&#24335; View&#12289;&#24067;&#23616;&#35745;&#31639;&#12289;&#29366;&#24577;&#26356;&#26032;&#21040;&#26368;&#32456;&#20687;&#32032;&#36755;&#20986;&#65292;&#19968;&#22871;&#31934;&#31616;&#20294;&#23436;&#25972;&#30340; UI &#38142;&#36335;&#24050;&#32463;&#24314;&#31435;&#36215;&#26469;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-04"><span>Swift &#36328;&#24179;&#21488;&#23454;&#36341;&#65306;&#22810;&#24179;&#21488;&#19979;&#30340; C++ &#20381;&#36182;&#31649;&#29702; (Multiplatform Swift, with C++ dependencies via XCFramework, apt and vcpkg)</span></a></strong></h3><p><span>&#19968;&#20010; Swift &#24212;&#29992;&#33021;&#21542;&#30495;&#27491;&#23454;&#29616;&#36328;&#24179;&#21488;&#65292;&#24456;&#22810;&#26102;&#20505;&#21462;&#20915;&#20110;&#20854;&#32972;&#21518;&#30340; C/C++ &#20381;&#36182;&#33021;&#21542;&#36319;&#30528;&#36328;&#24179;&#21488;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/harald-achitz/"><span>Harald Achitz</span></a><span> &#20197;&#33258;&#24049;&#30340; ZeroMQ Swift bindings &#20026;&#20363;&#65292;&#23637;&#31034;&#20102;&#19968;&#20010;&#21516;&#26102;&#25903;&#25345; macOS&#12289;Linux &#21644; Windows &#30340; Swift/C++ &#39033;&#30446;&#22914;&#20309;&#32452;&#32455;&#21407;&#29983;&#20381;&#36182;&#65306;Apple &#24179;&#21488;&#20351;&#29992; XCFramework&#65292;Linux &#20351;&#29992;&#31995;&#32479; package&#65292;Windows &#21017;&#36890;&#36807; vcpkg &#23433;&#35013; ZeroMQ&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-05"><span>&#22312; iOS &#27169;&#25311;&#22120;&#38388;&#23454;&#29616;&#34394;&#25311;&#34013;&#29273;&#36890;&#20449; (Connecting two iOS simulators over BLE)</span></a></strong></h3><p><span>CoreBluetooth &#22312; iOS Simulator &#20013;&#23436;&#20840;&#19981;&#21487;&#29992;&#65292;&#36825;&#35753; BLE App &#30340;&#24320;&#21457;&#21644;&#27979;&#35797;&#38271;&#26399;&#20381;&#36182;&#30495;&#26426;&#12290;&#8288;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#22312;&#24320;&#21457; &#8288;</span><a href="https://github.com/kylebrowning/BLESwift"><span>BLESwift 2.0</span></a><span> &#26102;&#25442;&#20102;&#19968;&#31181;&#24605;&#36335;&#65306;Simulator &#20013;&#30340;&#20013;&#24515;&#35774;&#22791;&#65288;Central&#65289;&#21644;&#22806;&#22260;&#35774;&#22791;&#65288;Peripheral&#65289;&#19981;&#20877;&#35843;&#29992; CoreBluetooth&#65292;&#32780;&#26159;&#36890;&#36807; localhost TCP &#23558;&#25805;&#20316;&#36716;&#21457;&#32473;&#36816;&#34892;&#22312; Mac &#19978;&#30340; </span><code>bleswift-provider</code><span>&#65292;&#30001;&#23427;&#26500;&#24314;&#19968;&#20010;&#8220;&#34394;&#25311;&#26080;&#32447;&#30005;&#8221;&#12290;&#36825;&#26679;&#65292;&#20004;&#20010; Simulator &#23601;&#33021;&#20687;&#20004;&#21488;&#30495;&#23454; BLE &#35774;&#22791;&#19968;&#26679;&#23436;&#25104;&#21457;&#29616;&#12289;&#36830;&#25509;&#12289;&#35835;&#20889;&#21644; notification&#65292;&#29978;&#33267;&#36824;&#21487;&#20197;&#36890;&#36807; passthrough &#27169;&#24335;&#20511;&#29992; Mac &#30340;&#34013;&#29273;&#65292;&#19982;&#30495;&#23454; BLE &#35774;&#22791;&#36890;&#20449;&#12290;</span></p><blockquote><p><span>&#27604; BLE &#26412;&#36523;&#26356;&#35753;&#25105;&#24863;&#20852;&#36259;&#30340;&#26159;&#36825;&#31181;&#27979;&#35797;&#33539;&#24335;&#65306;&#24403; Simulator &#32570;&#23569;&#26576;&#39033;&#31995;&#32479;&#25110;&#30828;&#20214;&#33021;&#21147;&#26102;&#65292;&#19981;&#19968;&#23450;&#35201;&#22312; App &#20869;&#21040;&#22788;&#28155;&#21152; mock&#65292;&#32780;&#26159;&#21487;&#20197;&#22312;&#31995;&#32479;&#33021;&#21147;&#19982;&#19994;&#21153;&#20195;&#30721;&#20043;&#38388;&#24314;&#31435;&#21487;&#26367;&#25442;&#30340; backend&#65292;&#20877;&#36890;&#36807; Mac &#19978;&#30340;&#20195;&#29702;&#36827;&#31243;&#37325;&#24314;&#19968;&#20010;&#21487;&#25511;&#30340;&#22806;&#37096;&#19990;&#30028;&#12290;&#36825;&#31181;&#35774;&#35745;&#19981;&#20165;&#35299;&#20915;&#20102;&#8220;Simulator &#32570;&#23569;&#26576;&#20123;&#31995;&#32479;&#25110;&#30828;&#20214;&#33021;&#21147;&#8221;&#30340;&#38382;&#39064;&#65292;&#20063;&#35753;&#21407;&#26412;&#39640;&#24230;&#20381;&#36182;&#30495;&#23454;&#29615;&#22659;&#30340;&#21151;&#33021;&#26356;&#23481;&#26131;&#36827;&#20837;&#33258;&#21160;&#21270;&#27979;&#35797;&#21644; CI&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-06"><span>&#25506;&#32034; SwiftUI &#20840;&#26032;&#30340;&#20219;&#24847;&#23481;&#22120;&#25302;&#25341;&#25490;&#24207; API (Reorder all the things in SwiftUI)</span></a></strong></h3><p><span>SwiftUI &#38271;&#26399;&#20197;&#26469;&#27809;&#26377;&#25552;&#20379;&#22312;&#20219;&#24847;&#23481;&#22120;&#20013;&#23454;&#29616;&#25302;&#25341;&#25490;&#24207;&#30340;&#36890;&#29992; API&#65292;&#36825;&#20010;&#36951;&#25022;&#22312; WWDC 2026 &#21518;&#24471;&#21040;&#20102;&#35299;&#20915;&#12290;&#8288;&#8288;</span><a href="https://x.com/SwiftyAlex"><span>Alexander Logan</span></a><span> &#20171;&#32461;&#20102; SwiftUI &#26032;&#30340; reordering API&#12290;&#36890;&#36807; </span><code>reorderable</code><span>&#12289;</span><code>reorderableContainer</code><span> &#31561;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#30452;&#25509;&#22768;&#26126;&#21738;&#20123;&#20869;&#23481;&#21487;&#20197;&#34987;&#37325;&#26032;&#25490;&#24207;&#20197;&#21450;&#23545;&#24212;&#30340;&#25968;&#25454;&#27169;&#22411;&#65292;&#35753;&#25302;&#25341;&#25490;&#24207;&#19981;&#20877;&#23616;&#38480;&#20110; </span><code>List</code><span>&#65292;&#20063;&#19981;&#24517;&#33258;&#24049;&#36890;&#36807; </span><code>DropDelegate</code><span> &#31649;&#29702;&#25302;&#25341;&#20301;&#32622;&#21644;&#25968;&#25454;&#26356;&#26032;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#26032; API &#25552;&#20379;&#20102;&#26356;&#39640;&#23618;&#30340;&#20132;&#20114;&#35821;&#20041;&#65292;&#23558;&#8220;reordering&#8221;&#20174; drag &amp; drop &#36825;&#19968;&#20855;&#20307;&#23454;&#29616;&#26041;&#24335;&#20013;&#25277;&#31163;&#20986;&#26469;&#12290;&#24320;&#21457;&#32773;&#25551;&#36848;&#30340;&#26159;&#8220;&#36825;&#20123;&#20869;&#23481;&#21487;&#20197;&#37325;&#26032;&#25490;&#24207;&#8221;&#65292;&#33267;&#20110;&#36890;&#36807;&#40736;&#26631;&#12289;&#35302;&#25511;&#36824;&#26159;&#20854;&#20182;&#36755;&#20837;&#26041;&#24335;&#23436;&#25104;&#25805;&#20316;&#65292;&#21017;&#21487;&#20197;&#26356;&#22810;&#22320;&#20132;&#32473;&#31995;&#32479;&#22788;&#29702;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0152-07"><span>Swift Charts &#36827;&#38454;&#65306;&#22914;&#20309;&#32472;&#21046;&#22810;&#23618;&#26093;&#26085;&#22270; (Building a sunburst diagram in Swift Charts)</span></a></strong></h3><p><span>&#26093;&#26085;&#22270;&#65288;Sunburst Diagram&#65289;&#26159;&#19968;&#31181;&#29992;&#21516;&#24515;&#22278;&#29615;&#23637;&#31034;&#23618;&#32423;&#25968;&#25454;&#30340;&#22270;&#34920;&#65292;&#20363;&#22914;&#20174;&#8220;&#24037;&#20316;&#8221;&#21040;&#8220;&#24320;&#21457;&#8221;&#65292;&#20877;&#21040;&#26576;&#20010;&#20855;&#20307;&#39033;&#30446;&#65292;&#36234;&#21521;&#22806;&#20195;&#34920;&#36234;&#32454;&#30340;&#25968;&#25454;&#23618;&#32423;&#12290;&#8288;&#8288;</span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#23637;&#31034;&#20102;&#22914;&#20309;&#21033;&#29992; Swift Charts &#30340; </span><code>SectorMark</code><span>&#65292;&#20174;&#26222;&#36890;&#39292;&#22270;&#24320;&#22987;&#65292;&#36880;&#27493;&#26500;&#24314;&#19968;&#20010;&#21253;&#21547;&#19977;&#23618;&#25968;&#25454;&#30340;&#26093;&#26085;&#22270;&#12290;&#36825;&#20010;&#23454;&#29616;&#20063;&#24456;&#22909;&#22320;&#23637;&#31034;&#20102; Swift Charts &#30340;&#28789;&#27963;&#24615;&#65306;&#24403;&#26694;&#26550;&#27809;&#26377;&#30452;&#25509;&#25552;&#20379;&#26576;&#31181;&#22270;&#34920;&#26102;&#65292;&#21487;&#20197;&#23558; </span><code>SectorMark</code><span> &#31561; Mark &#35270;&#20026;&#26356;&#22522;&#30784;&#30340;&#21487;&#35270;&#21270;&#21407;&#35821;&#65292;&#36890;&#36807;&#33258;&#34892;&#35745;&#31639;&#35282;&#24230;&#21306;&#38388;&#21644;&#25968;&#25454;&#26144;&#23556;&#26469;&#26500;&#24314;&#26356;&#22797;&#26434;&#30340;&#22270;&#34920;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0152-08"><span>CoreDataBrowser&#65306;&#24555;&#36895;&#26597;&#30475; Simulator &#20013;&#30340;&#26412;&#22320;&#25968;&#25454;</span></a></strong></h3><p><span>&#35843;&#35797; Core Data &#25110; SwiftData &#24212;&#29992;&#26102;&#65292;&#36890;&#24120;&#38656;&#35201;&#20808;&#22312;&#23618;&#23618;&#23884;&#22871;&#30340; Simulator &#30446;&#24405;&#20013;&#25214;&#21040;&#23545;&#24212;&#30340;&#25968;&#25454;&#25991;&#20214;&#65292;&#20877;&#29992; SQLite &#31649;&#29702;&#22120;&#25171;&#24320;&#24182;&#27983;&#35272;&#25968;&#25454;&#12290;&#30001; &#8288;</span><a href="https://www.linkedin.com/in/csaba-turdesan-880182251/"><span>Csaba Turdesan</span></a><span> &#24320;&#21457;&#30340; CoreDataBrowser &#23581;&#35797;&#25226;&#36825;&#20010;&#36807;&#31243;&#21464;&#24471;&#31616;&#21333;&#65306;&#36873;&#25321;&#24403;&#21069;&#21551;&#21160;&#30340;&#27169;&#25311;&#22120;&#21518;&#65292;&#23427;&#20250;&#33258;&#21160;&#26597;&#25214;&#24212;&#29992;&#23481;&#22120;&#20013;&#30340; Core Data&#12289;SwiftData &#20197;&#21450; UserDefaults &#25968;&#25454;&#28304;&#65292;&#24182;&#36890;&#36807;&#21407;&#29983; macOS &#30028;&#38754;&#32479;&#19968;&#21576;&#29616;&#12290;</span></p><p><span>CoreDataBrowser &#25903;&#25345;&#26597;&#30475;&#34920;&#19982;&#35760;&#24405;&#12289;&#25628;&#32034;&#24182;&#39640;&#20142;&#21305;&#37197;&#20869;&#23481;&#65292;&#20063;&#33021;&#23545;&#37096;&#20998;&#20108;&#36827;&#21046;&#25968;&#25454;&#65288;BLOB&#65289;&#23581;&#35797;&#35299;&#26512; NSKeyedArchive&#12289;JSON&#12289;Property List &#21644; UTF-8 &#25991;&#26412;&#12290;&#24037;&#20855;&#20307;&#37327;&#24456;&#23567;&#65288;2.5 MB&#65289;&#65292;&#24182;&#19988;&#8288;</span><a href="https://github.com/kyletaylor94/CoreDataBrowser"><span>&#28304;&#30721;&#20844;&#24320;</span></a><span>&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #151]]></title><description><![CDATA[Just a Few Keystrokes]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 31 Aug 2026 12:01:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!KvhQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KvhQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 424w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 848w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1272w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp" width="1391" height="620" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:620,&quot;width&quot;:1391,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:379890,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/213490700?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KvhQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 424w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 848w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1272w, https://substackcdn.com/image/fetch/$s_!KvhQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F403292b3-c72d-4cf2-a428-45010564e1f3_1391x620.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@paws_and_prints?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">&#120161;&#120146;&#120168;&#120164; &#120146;&#120159;&#120149; &#120161;&#120163;&#120154;&#120159;&#120165;&#120164;</a><span> on </span><a href="https://unsplash.com/photos/pink-and-blue-textured-wall-divided-vertically-smHN6OX-hEQ?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Just a Few Keystrokes</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-151/">Read on web &#8594;</a></p><p><span>Last weekend, I attended an App Accelerator event hosted by Apple in Beijing. The event focused primarily on app development, operations, and business models in the age of AI. Most of the attendees were managers at tech companies or app developers. Throughout the event, enthusiasm for AI was high, with people exchanging their own perspectives on AI and sharing how they were putting it to use. I learned a great deal from those conversations.</span></p><p><span>After the event, I had dinner with a friend who works in a traditional industry. He knew almost nothing about AI. As an emerging concept, it was something he wanted to understand, but he had never really seen what tangible benefits AI could bring to his business. During dinner, he received a phone call: a client needed a proposal revised immediately. It was the weekend, and even if he assigned the task right away, it would have been difficult to get it done within a short period of time. After hearing roughly what was needed, I realized that the task happened to fall squarely within AI&#8217;s comfort zone. So I pulled out my phone and had AI handle it for him. A few minutes later, the result was ready.</span></p><p><span>He was impressed not only by how quickly AI completed the task, but also by the quality of the result. And at his company, there happened to be a team of five or six people whose work largely consisted of handling similar tasks.</span></p><p><span>He immediately started asking me for more details and calculating how much headcount he could reduce, and how much money he could save, if the company adopted AI.</span></p><p><span>The speed of that shift caught me somewhat off guard. I immediately brought up another possibility: if AI can accomplish existing work at a much lower cost, could those newly available capabilities also be used to pursue opportunities that had previously been too expensive to explore? Cutting costs is certainly one of AI&#8217;s most obvious benefits, but generating new revenue is just as much a field where AI can make a difference.</span></p><p><span>On the way home, I kept thinking about those five or six people. Right now they are probably enjoying a quiet weekend, unaware that their jobs had just been repriced over the course of a single meal. And what prompted that repricing was a demo I ran a few minutes earlier.</span></p><p><span>The next time I find myself in a similar situation, I will probably still pull out my phone and show someone what AI can do. But I think I should at least remember this: what takes just a few keystrokes on one side of the screen may mean something very different on the other.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-150/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-01"><span>Why Swift is introducing a warning for weak captures within nested closures</span></a></strong></h3><p><span>Weak captures are an important memory management mechanism in Swift. Historically, if a weak capture is used only in the inner closure of a nested closure, the Swift compiler may implicitly insert a strong capture in the parent closure. Even though this behavior can lead to a retain cycle in certain situations, the compiler previously provided no warning. Starting with Swift 6.4, the compiler will issue a warning when it detects a mismatch between a weak capture in an inner closure and an implicit strong capture in the outer closure.</span></p><p><a href="https://mastodon.social/@johnsundell"><span>John Sundell</span></a><span> explains this change and offers several solutions: depending on the situation, explicitly declare the capture semantics in the parent closure; if both closures need to manage their lifetimes independently, declare the appropriate capture semantics for each one. This may be a small update to the Swift compiler, but it helps developers express ownership relationships between nested closures that could otherwise be easily overlooked.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-02"><span>Running iOS Background Tasks Reliably</span></a></strong></h3><p><code>BGTaskScheduler</code><span> has never been cron for iOS. When a background task actually runs depends on system scheduling, device state, energy budgets, and how users interact with the app. </span><a href="https://www.linkedin.com/in/irvingpop/"><span>Irving Popovetsky</span></a><span> used telemetry from a real device to observe background task behavior over an extended period and shared a number of lessons learned along the way: frequently resubmitting tasks in an attempt to improve reliability can actually keep pushing back a task that was close to getting an execution opportunity; user behavior and system conditions such as force quitting, not opening the app for a long time, Low Power Mode, and device reboots can all affect whether background tasks get a chance to run; and a task running later than requested does not necessarily mean that scheduling has gone wrong.</span></p><p><span>For background tasks, developers should not try to precisely schedule execution. Instead, the goal should be to make the most efficient and correct use of the opportunities the system chooses to provide.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-03"><span>The Memory Remains: TipKit in a Shipping App</span></a></strong></h3><p><span>TipKit is easy to learn, but using it well in a real project is much harder. The real challenges are knowing when tips should not appear, avoiding disruptions to the user experience, and ensuring that the underlying logic remains testable and maintainable. </span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> shares lessons from using TipKit in a shipping app: </span><code>@Parameter</code><span> is better suited to current state that can be recomputed at any time, while </span><code>Tips.Event</code><span> is appropriate for historical behavior that cannot be reconstructed from current state; every tip should avoid periods when onboarding or other launch UI may still appear; and because </span><code>Tips.configure</code><span> only takes effect once per process, initialization order, debug tooling, and test environments all need to be designed around that constraint.</span></p><p><span>The essence of TipKit lies not in its visual presentation, but in its internal logic. It helps developers declaratively describe the rules that determine when tips should appear, while leaving the actual presentation entirely customizable. We can think of TipKit as a rules engine that determines whether a tip should be displayed; how those rules are visualized is up to the developer. For more discussion from this perspective, see </span><a href="https://fatbobman.com/en/posts/mastering-tipkit-advance/"><span>Mastering TipKit: Advanced</span></a><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-04"><span>Building an accessible calendar chart with Swift Charts</span></a></strong></h3><p><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to build a calendar chart similar to GitHub Contributions using Swift Charts. The more interesting part of the article, however, is its approach to accessibility. Because the same weekday across different weeks shares a normalized x value, VoiceOver groups an entire column of data together instead of allowing users to navigate day by day. The author solves this by using </span><code>accessibilityChildren</code><span> to construct a separate accessibility hierarchy for the plot area that corresponds to the visual layout.</span></p><p><a href="https://books.nilcoalescing.com/swift-charts-beyond-the-basics"><span>Swift Charts Beyond the Basics</span></a><span>, co-authored by Matthaus Woolard and </span><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>, was officially released last week. For developers looking to create advanced data visualizations with Swift Charts, it is a rare and valuable advanced guide.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-05"><span>Mac App Direct Distribution, DMG Signing &amp; Notarization Guide</span></a></strong></h3><p><span>Compared with publishing through the Mac App Store, distributing a macOS app directly requires developers to handle more of the release process themselves: Developer ID signing, DMG creation, notarization, stapling, and final Gatekeeper verification. A problem at any one of these stages can prevent users from installing the app successfully. </span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> walks through the complete release workflow, from creating an Xcode Archive and building the DMG to final signing, notarization, and verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-06"><span>Consuming SKIE Flows in SwiftUI</span></a></strong></h3><p><span>In projects that use Kotlin Multiplatform (KMP) to share business logic while building native UIs with SwiftUI, making Kotlin APIs integrate naturally into the Swift ecosystem has always been an important challenge. SKIE (Swift Kotlin Interface Enhancer) was created to improve this interoperability experience. It can convert Kotlin </span><code>Flow</code><span> into Swift </span><code>AsyncSequence</code><span>, allowing Swift code to consume data using familiar Swift Concurrency patterns.</span></p><p><a href="https://x.com/faogustavo"><span>Gustavo F&#227;o Valvassori</span></a><span> introduces a set of SwiftUI-specific APIs provided by SKIE: besides consuming data directly from an </span><code>AsyncSequence</code><span> inside </span><code>.task</code><span>, developers can use </span><code>.collect</code><span> to bind Flow updates to SwiftUI state, or use the </span><code>Observing</code><span> wrapper to hide state management and let the latest value from a Kotlin </span><code>StateFlow</code><span> directly participate in building the View.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-07"><span>Sarunw&#8217;s How-to Series Returns</span></a></strong></h3><p><a href="https://x.com/sarunw"><span>Sarunw</span></a><span>&#8217;s blog has long been an excellent resource for developers looking for practical tips on Apple platform development. However, the blog stopped receiving updates at the end of 2023. Last week, Sarunw resumed writing and published several new articles in his How-to series within just one week. It&#8217;s great to see an excellent content creator return after nearly three years away.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-08"><span>JindoKit: Preview Dynamic Island presentations in your app</span></a></strong></h3><p><span>WidgetKit&#8217;s Live Activity previews are primarily intended for development and debugging within Xcode. For apps that allow users to choose themes or customize displayed content, however, the system does not provide an equivalent way to preview those presentations directly inside the app.</span></p><p><span>Developed by </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span>, JindoKit brings WidgetKit-style Dynamic Island APIs into regular SwiftUI Views, allowing apps to directly preview expanded, compact, and minimal Dynamic Island presentations. Since its API closely mirrors WidgetKit&#8217;s structure, developers can organize content for each region in a similar way and reuse related views and data between the app&#8217;s configuration UI and its WidgetKit Extension. For more information, see the author&#8217;s introductory article: </span><a href="https://openswiftuiproject.org/blog/preview-dynamic-island-presentations-with-jindokit/"><span>Preview Dynamic Island presentations in your app with JindoKit</span></a><span>.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-151?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#20030;&#25163;&#20043;&#21171;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-151/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#20010;&#21608;&#26411;&#65292;&#25105;&#22312;&#21271;&#20140;&#21442;&#21152;&#20102;&#30001;&#33529;&#26524;&#20030;&#21150;&#30340; App &#23413;&#21270;&#22120;&#27963;&#21160;&#65292;&#26412;&#27425;&#30340;&#20027;&#39064;&#20027;&#35201;&#22260;&#32469; AI &#26102;&#20195;&#30340;&#24212;&#29992;&#24320;&#21457;&#12289;&#36816;&#33829;&#21644;&#21830;&#19994;&#27169;&#24335;&#23637;&#24320;&#12290;&#19982;&#20250;&#32773;&#22823;&#22810;&#26159; IT &#20844;&#21496;&#30340;&#31649;&#29702;&#32773;&#21644;&#24212;&#29992;&#24320;&#21457;&#32773;&#65292;&#25972;&#20010;&#27963;&#21160;&#26399;&#38388;&#65292;&#22823;&#23478;&#23545; AI &#30340;&#28909;&#24773;&#37117;&#24456;&#39640;&#65292;&#20063;&#32439;&#32439;&#35752;&#35770;&#21508;&#33258;&#23545;&#20110; AI &#30340;&#29702;&#35299;&#21644;&#24212;&#29992;&#25216;&#24039;&#65292;&#25105;&#20174;&#20013;&#25910;&#33719;&#19981;&#23569;&#12290;</span></p><p><span>&#20250;&#35758;&#32467;&#26463;&#21518;&#65292;&#25105;&#21644;&#19968;&#20301;&#20174;&#20107;&#20256;&#32479;&#34892;&#19994;&#30340;&#26379;&#21451;&#21507;&#39277;&#12290;&#20182;&#23545; AI &#22522;&#26412;&#19968;&#31373;&#19981;&#36890;&#12290;&#20316;&#20026;&#19968;&#20010;&#26032;&#20852;&#27010;&#24565;&#65292;&#20182;&#20063;&#24819;&#20102;&#35299;&#65292;&#20294;&#19968;&#30452;&#27809;&#26377;&#20999;&#23454;&#24863;&#21463;&#21040; AI &#31350;&#31455;&#33021;&#32473;&#20182;&#30340;&#20225;&#19994;&#24102;&#26469;&#20160;&#20040;&#12290;&#23601;&#39184;&#36807;&#31243;&#20013;&#65292;&#20182;&#25509;&#21040;&#19968;&#20010;&#30005;&#35805;&#65292;&#19968;&#20010;&#23458;&#25143;&#35201;&#27714;&#31435;&#21051;&#35843;&#25972;&#26041;&#26696;&#12290;&#24403;&#26102;&#27491;&#20540;&#21608;&#26411;&#65292;&#21363;&#20415;&#39532;&#19978;&#25226;&#20219;&#21153;&#23433;&#25490;&#19979;&#21435;&#65292;&#20063;&#24456;&#38590;&#22312;&#30701;&#26102;&#38388;&#20869;&#23436;&#25104;&#12290;&#25105;&#22312;&#20102;&#35299;&#22823;&#33268;&#38656;&#27714;&#21518;&#65292;&#21457;&#29616;&#36825;&#24688;&#22909;&#23646;&#20110; AI &#30340;&#33298;&#36866;&#21306;&#65292;&#20110;&#26159;&#30452;&#25509;&#29992;&#25163;&#26426;&#35753; AI &#24110;&#20182;&#22788;&#29702;&#12290;&#20960;&#20998;&#38047;&#21518;&#65292;&#32467;&#26524;&#23601;&#20986;&#26469;&#20102;&#12290;</span></p><p><span>&#20182;&#19981;&#20165;&#24778;&#21497;&#20110; AI &#23436;&#25104;&#20219;&#21153;&#30340;&#25928;&#29575;&#65292;&#20063;&#23545;&#32467;&#26524;&#30340;&#36136;&#37327;&#24863;&#21040;&#24847;&#22806;&#12290;&#32780;&#22312;&#20182;&#30340;&#20844;&#21496;&#37324;&#65292;&#24688;&#22909;&#26377;&#19968;&#20010;&#30001;&#20116;&#20845;&#20154;&#32452;&#25104;&#30340;&#37096;&#38376;&#65292;&#22823;&#37096;&#20998;&#24037;&#20316;&#23601;&#26159;&#22788;&#29702;&#31867;&#20284;&#30340;&#20219;&#21153;&#12290;</span></p><p><span>&#20110;&#26159;&#65292;&#20182;&#39532;&#19978;&#24320;&#22987;&#21521;&#25105;&#35810;&#38382;&#26356;&#22810;&#32454;&#33410;&#65292;&#24182;&#35745;&#31639;&#22914;&#26524;&#24341;&#20837; AI&#65292;&#21487;&#20197;&#32553;&#20943;&#22810;&#23569;&#20154;&#21147;&#12289;&#38477;&#20302;&#22810;&#23569;&#25104;&#26412;&#12290;</span></p><p><span>&#36825;&#20010;&#36716;&#21464;&#20043;&#24555;&#35753;&#25105;&#26377;&#20123;&#35815;&#24322;&#12290;&#25105;&#38543;&#21363;&#21644;&#20182;&#35752;&#35770;&#20102;&#21478;&#19968;&#31181;&#21487;&#33021;&#65306;&#26082;&#28982; AI &#33021;&#20197;&#26356;&#20302;&#30340;&#25104;&#26412;&#23436;&#25104;&#36807;&#21435;&#30340;&#24037;&#20316;&#65292;&#37027;&#20040;&#26159;&#21542;&#20063;&#21487;&#20197;&#21033;&#29992;&#36825;&#20123;&#26032;&#22686;&#30340;&#33021;&#21147;&#21435;&#23581;&#35797;&#20197;&#21069;&#22240;&#20026;&#25104;&#26412;&#36807;&#39640;&#32780;&#26080;&#27861;&#24320;&#23637;&#30340;&#19994;&#21153;&#65311;&#33410;&#27969;&#24403;&#28982;&#26159; AI &#26368;&#30452;&#35266;&#30340;&#20215;&#20540;&#65292;&#20294;&#24320;&#28304;&#21516;&#26679;&#26159;&#23427;&#21487;&#20197;&#26045;&#23637;&#30340;&#26041;&#21521;&#12290;</span></p><p><span>&#22312;&#21442;&#21152;&#27963;&#21160;&#26399;&#38388;&#65292;&#25105;&#20063;&#26366;&#22312;&#31169;&#19979;&#20132;&#27969;&#20013;&#34920;&#36798;&#36807;&#23545; AI &#20914;&#20987;&#23601;&#19994;&#30340;&#25285;&#24551;&#65292;&#19981;&#36807;&#26356;&#22810;&#36824;&#26159;&#20174;&#38271;&#26399;&#36235;&#21183;&#20986;&#21457;&#30340;&#19968;&#31181;&#24605;&#32771;&#12290;&#24403;&#36825;&#31181;&#8220;&#25285;&#24551;&#8221;&#31361;&#28982;&#20197;&#22914;&#27492;&#20855;&#20307;&#30340;&#26041;&#24335;&#20986;&#29616;&#22312;&#30524;&#21069;&#26102;&#65292;&#25105;&#36824;&#26159;&#24863;&#21040;&#20102;&#19968;&#20123;&#19981;&#36866;&#12290;&#19968;&#20010;&#23545;&#25105;&#32780;&#35328;&#21482;&#26159;&#20030;&#25163;&#20043;&#21171;&#30340;&#28436;&#31034;&#65292;&#22312;&#21478;&#19968;&#20010;&#20154;&#30340;&#35270;&#35282;&#37324;&#65292;&#21364;&#21487;&#33021;&#36805;&#36895;&#21464;&#25104;&#19968;&#36947;&#20851;&#20110;&#20960;&#20010;&#20154;&#26159;&#21542;&#36824;&#26377;&#24517;&#35201;&#32487;&#32493;&#30041;&#22312;&#23703;&#20301;&#19978;&#30340;&#31639;&#26415;&#39064;&#12290;</span></p><p><span>&#36820;&#31243;&#36884;&#20013;&#65292;&#25105;&#24819;&#30340;&#19968;&#30452;&#26159;&#37027;&#20116;&#20845;&#20010;&#20154;&#12290;&#20182;&#20204;&#27492;&#21051;&#22823;&#27010;&#27491;&#23433;&#31283;&#22320;&#36807;&#30528;&#21608;&#26411;&#65292;&#21364;&#24182;&#19981;&#30693;&#36947;&#33258;&#24049;&#30340;&#23703;&#20301;&#21018;&#21018;&#22312;&#19968;&#39039;&#39277;&#30340;&#26102;&#38388;&#37324;&#34987;&#37325;&#26032;&#20272;&#20215;&#12290;&#32780;&#20419;&#25104;&#36825;&#27425;&#20272;&#20215;&#30340;&#65292;&#26159;&#25105;&#20960;&#20998;&#38047;&#21069;&#30340;&#19968;&#27425;&#28436;&#31034;&#12290;</span></p><p><span>&#19979;&#19968;&#27425;&#36935;&#21040;&#31867;&#20284;&#30340;&#22330;&#21512;&#65292;&#25105;&#22823;&#27010;&#36824;&#26159;&#20250;&#25171;&#24320;&#25163;&#26426;&#28436;&#31034;&#32473;&#23545;&#26041;&#30475;&#12290;&#20294;&#25105;&#24819;&#65292;&#25105;&#33267;&#23569;&#24212;&#35813;&#35760;&#24471;&#65306;&#23631;&#24149;&#36825;&#19968;&#20391;&#30340;&#20030;&#25163;&#20043;&#21171;&#65292;&#22312;&#23631;&#24149;&#30340;&#21478;&#19968;&#20391;&#65292;&#25110;&#35768;&#26159;&#21478;&#19968;&#30058;&#22659;&#22320;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-150/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-01"><span>Swift &#23884;&#22871;&#38381;&#21253;&#24369;&#25429;&#33719;&#35686;&#21578; (Why Swift is introducing a warning for weak captures within nested closures)</span></a></strong></h3><p><span>&#24369;&#25429;&#33719;&#26159; Swift &#20013;&#37325;&#35201;&#30340;&#20869;&#23384;&#31649;&#29702;&#26426;&#21046;&#12290;&#19968;&#30452;&#20197;&#26469;&#65292;&#22914;&#26524;&#21482;&#22312;&#23884;&#22871;&#38381;&#21253;&#30340;&#20869;&#23618;&#36827;&#34892;&#24369;&#25429;&#33719;&#65292;Swift &#32534;&#35793;&#22120;&#21487;&#33021;&#20250;&#22312;&#29238;&#38381;&#21253;&#20013;&#38544;&#24335;&#25554;&#20837;&#24378;&#25429;&#33719;&#12290;&#21363;&#20415;&#36825;&#31181;&#34892;&#20026;&#22312;&#26576;&#20123;&#22330;&#26223;&#19979;&#21487;&#33021;&#23548;&#33268; retain cycle&#65292;&#32534;&#35793;&#22120;&#27492;&#21069;&#20063;&#19981;&#20250;&#32473;&#20986;&#25552;&#37266;&#12290;&#20174; Swift 6.4 &#24320;&#22987;&#65292;&#24403;&#32534;&#35793;&#22120;&#21457;&#29616;&#20869;&#23618;&#38381;&#21253;&#30340;&#24369;&#25429;&#33719;&#19982;&#22806;&#23618;&#38381;&#21253;&#30340;&#38544;&#24335;&#24378;&#25429;&#33719;&#23384;&#22312;&#24046;&#24322;&#26102;&#65292;&#23558;&#32473;&#20986;&#35686;&#21578;&#12290;</span></p><p><a href="https://mastodon.social/@johnsundell"><span>John Sundell</span></a><span> &#20171;&#32461;&#20102;&#36825;&#19968;&#21464;&#21270;&#65292;&#24182;&#32473;&#20986;&#20102;&#35299;&#20915;&#26041;&#26696;&#65306;&#26681;&#25454;&#20855;&#20307;&#22330;&#26223;&#65292;&#22312;&#29238;&#38381;&#21253;&#20013;&#26174;&#24335;&#22768;&#26126;&#24341;&#29992;&#26041;&#24335;&#65307;&#22914;&#26524;&#20004;&#23618;&#38381;&#21253;&#37117;&#38656;&#35201;&#29420;&#31435;&#25511;&#21046;&#29983;&#21629;&#21608;&#26399;&#65292;&#21017;&#21487;&#20197;&#20998;&#21035;&#22768;&#26126;&#21508;&#33258;&#30340;&#25429;&#33719;&#26041;&#24335;&#12290;&#36825;&#25110;&#35768;&#21482;&#26159; Swift &#32534;&#35793;&#22120;&#30340;&#19968;&#39033;&#23567;&#26356;&#26032;&#65292;&#20294;&#23427;&#33021;&#22815;&#24110;&#21161;&#24320;&#21457;&#32773;&#26356;&#26126;&#30830;&#22320;&#34920;&#36798;&#23884;&#22871;&#38381;&#21253;&#20043;&#38388;&#21407;&#26412;&#24456;&#23481;&#26131;&#34987;&#24573;&#30053;&#30340; ownership &#20851;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-02"><span>&#25552;&#21319; iOS &#21518;&#21488;&#20219;&#21153;&#21487;&#38752;&#24615;&#25351;&#21335; (Running iOS Background Tasks Reliably)</span></a></strong></h3><p><code>BGTaskScheduler</code><span> &#20174;&#26469;&#37117;&#19981;&#26159; iOS &#19978;&#30340; cron&#12290;&#21518;&#21488;&#20219;&#21153;&#30495;&#27491;&#20309;&#26102;&#25191;&#34892;&#65292;&#21462;&#20915;&#20110;&#31995;&#32479;&#35843;&#24230;&#12289;&#35774;&#22791;&#29366;&#24577;&#12289;&#33021;&#28304;&#39044;&#31639;&#20197;&#21450;&#29992;&#25143;&#20351;&#29992; App &#30340;&#20064;&#24815;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/irvingpop/"><span>Irving Popovetsky</span></a><span> &#36890;&#36807;&#23454;&#38469;&#35774;&#22791;&#19978;&#30340; telemetry &#38271;&#26399;&#35266;&#23519;&#21518;&#21488;&#20219;&#21153;&#30340;&#36816;&#34892;&#35268;&#24459;&#65292;&#20998;&#20139;&#20102;&#19981;&#23569;&#23454;&#36341;&#20013;&#36393;&#36807;&#30340;&#22353;&#65306;&#20026;&#20102;&#25552;&#39640;&#21487;&#38752;&#24615;&#32780;&#39057;&#32321;&#37325;&#26032;&#25552;&#20132;&#20219;&#21153;&#65292;&#21487;&#33021;&#21453;&#32780;&#25226;&#19968;&#20010;&#21363;&#23558;&#33719;&#24471;&#25191;&#34892;&#26426;&#20250;&#30340;&#20219;&#21153;&#19981;&#26029;&#21521;&#21518;&#25512;&#65307;force quit&#12289;&#38271;&#26102;&#38388;&#19981;&#25171;&#24320; App&#12289;Low Power Mode&#12289;&#35774;&#22791;&#37325;&#21551;&#31561;&#29992;&#25143;&#34892;&#20026;&#21644;&#31995;&#32479;&#29366;&#24577;&#65292;&#37117;&#20250;&#24433;&#21709;&#21518;&#21488;&#20219;&#21153;&#33719;&#24471;&#25191;&#34892;&#26426;&#20250;&#65307;&#36229;&#36807;&#39044;&#23450;&#26102;&#38388;&#20173;&#26410;&#25191;&#34892;&#65292;&#20063;&#24182;&#19981;&#24847;&#21619;&#30528;&#35843;&#24230;&#20986;&#29616;&#20102;&#24322;&#24120;&#12290;</span></p><p><span>&#23545;&#20110;&#21518;&#21488;&#20219;&#21153;&#65292;&#24320;&#21457;&#32773;&#21162;&#21147;&#30340;&#26041;&#21521;&#19981;&#24212;&#35813;&#26159;&#23581;&#35797;&#31934;&#30830;&#23433;&#25490;&#25191;&#34892;&#26102;&#38388;&#65292;&#32780;&#26159;&#22312;&#31995;&#32479;&#24895;&#24847;&#25552;&#20379;&#25191;&#34892;&#26426;&#20250;&#26102;&#65292;&#23613;&#21487;&#33021;&#39640;&#25928;&#12289;&#27491;&#30830;&#22320;&#21033;&#29992;&#23427;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-03"><span>TipKit &#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#33853;&#22320;&#23454;&#36341; (The Memory Remains: TipKit in a Shipping App)</span></a></strong></h3><p><span>TipKit &#23398;&#36215;&#26469;&#24456;&#23481;&#26131;&#65292;&#20294;&#24819;&#22312;&#23454;&#38469;&#39033;&#30446;&#20013;&#29992;&#22909;&#24182;&#19981;&#23481;&#26131;&#12290;&#30495;&#27491;&#30340;&#38590;&#28857;&#22312;&#20110;&#65306;&#20160;&#20040;&#26102;&#20505;&#19981;&#24212;&#35813;&#26174;&#31034;&#12289;&#22914;&#20309;&#36991;&#20813;&#24178;&#25200;&#29992;&#25143;&#65292;&#20197;&#21450;&#24590;&#26679;&#20445;&#35777;&#36825;&#22871;&#36923;&#36753;&#21487;&#27979;&#35797;&#12289;&#21487;&#32500;&#25252;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> &#22312;&#26412;&#25991;&#20013;&#20998;&#20139;&#20102;&#20182;&#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#20351;&#29992;&#32463;&#39564;&#65306;</span><code>@Parameter</code><span> &#26356;&#36866;&#21512;&#34920;&#31034;&#33021;&#22815;&#38543;&#26102;&#37325;&#26032;&#35745;&#31639;&#20986;&#30340;&#24403;&#21069;&#29366;&#24577;&#65292;&#32780; </span><code>Tips.Event</code><span> &#21017;&#36866;&#21512;&#35760;&#24405;&#26080;&#27861;&#20174;&#29616;&#26377;&#29366;&#24577;&#36824;&#21407;&#30340;&#21382;&#21490;&#34892;&#20026;&#65307;&#25152;&#26377; tip &#37117;&#24212;&#35813;&#36991;&#24320;&#20173;&#21487;&#33021;&#20986;&#29616; onboarding &#25110;&#20854;&#20182;&#21551;&#21160; UI &#30340;&#38454;&#27573;&#65307;</span><code>Tips.configure</code><span> &#27599;&#20010;&#36827;&#31243;&#21482;&#33021;&#29983;&#25928;&#19968;&#27425;&#65292;&#22240;&#27492;&#21021;&#22987;&#21270;&#39034;&#24207;&#12289;Debug &#24037;&#20855;&#21644;&#27979;&#35797;&#29615;&#22659;&#37117;&#38656;&#35201;&#22260;&#32469;&#36825;&#19968;&#38480;&#21046;&#35774;&#35745;&#12290;</span></p><blockquote><p><span>TipKit &#30340;&#31934;&#39635;&#19981;&#22312;&#20110;&#22806;&#22312;&#30340;&#35270;&#35273;&#25928;&#26524;&#65292;&#32780;&#22312;&#20110;&#20869;&#22312;&#30340;&#36923;&#36753;&#34920;&#36798;&#12290;&#23427;&#24110;&#21161;&#24320;&#21457;&#32773;&#20197;&#22768;&#26126;&#30340;&#26041;&#24335;&#25551;&#36848;&#25552;&#31034;&#29983;&#25104;&#30340;&#35268;&#21017;&#65292;&#32780;&#25552;&#31034;&#30340;&#20855;&#20307;&#23454;&#29616;&#23436;&#20840;&#21487;&#20197;&#33258;&#23450;&#20041;&#12290;&#25105;&#20204;&#21487;&#20197;&#25226; TipKit &#24819;&#35937;&#25104;&#19968;&#20010;&#21028;&#26029;&#25552;&#31034;&#26174;&#31034;&#38656;&#27714;&#30340;&#35268;&#21017;&#24341;&#25806;&#65292;&#33267;&#20110;&#22914;&#20309;&#21487;&#35270;&#21270;&#36825;&#20123;&#35268;&#21017;&#65292;&#21017;&#21462;&#20915;&#20110;&#24320;&#21457;&#32773;&#33258;&#24049;&#12290;&#26356;&#22810;&#20851;&#20110;&#36825;&#19968;&#35270;&#35282;&#30340;&#35752;&#35770;&#65292;&#21487;&#20197;&#21442;&#38405; &#8288;</span><a href="https://fatbobman.com/zh/posts/mastering-tipkit-advance/"><span>&#25484;&#25569; TipKit&#65306;&#36827;&#38454;</span></a><span>&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-04"><span>&#20351;&#29992; Swift Charts &#26500;&#24314;&#26080;&#38556;&#30861;&#26085;&#21382;&#22270;&#34920; (Building an accessible calendar chart with Swift Charts)</span></a></strong></h3><p><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Swift Charts &#23454;&#29616;&#31867;&#20284; GitHub Contributions &#30340;&#26085;&#21382;&#22270;&#34920;&#12290;&#19981;&#36807;&#65292;&#25991;&#31456;&#26356;&#31934;&#24425;&#30340;&#37096;&#20998;&#22312;&#20110;&#23545; accessibility &#30340;&#22788;&#29702;&#12290;&#30001;&#20110;&#19981;&#21516;&#21608;&#30340;&#30456;&#21516; weekday &#20849;&#20139;&#32463;&#36807;&#24402;&#19968;&#21270;&#30340; x &#20540;&#65292;VoiceOver &#20250;&#23558;&#25972;&#21015;&#25968;&#25454;&#32452;&#21512;&#36215;&#26469;&#65292;&#32780;&#26080;&#27861;&#36880;&#26085;&#27983;&#35272;&#12290;&#20316;&#32773;&#36890;&#36807; </span><code>accessibilityChildren</code><span> &#20026; plot area &#21478;&#22806;&#26500;&#24314;&#20102;&#19968;&#22871;&#19982;&#35270;&#35273;&#24067;&#23616;&#23545;&#24212;&#30340; accessibility hierarchy&#65292;&#20174;&#32780;&#35299;&#20915;&#20102;&#36825;&#19968;&#38382;&#39064;&#12290;</span></p><blockquote><p><span>&#30001; Matthaus Woolard &#21644; &#8288;</span><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> &#21512;&#33879;&#30340; &#8288;</span><a href="https://books.nilcoalescing.com/swift-charts-beyond-the-basics"><span>Swift Charts Beyond the Basics</span></a><span> &#19968;&#20070;&#24050;&#20110;&#19978;&#21608;&#27491;&#24335;&#21457;&#24067;&#12290;&#23545;&#20110;&#24076;&#26395;&#20351;&#29992; Swift Charts &#21019;&#24314;&#39640;&#32423;&#25968;&#25454;&#21487;&#35270;&#21270;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#26412;&#19981;&#21487;&#22810;&#24471;&#30340;&#36827;&#38454;&#25945;&#31243;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-05"><span>Mac &#24212;&#29992;&#29420;&#31435;&#20998;&#21457;&#19982; DMG &#31614;&#21517;&#20844;&#35777;&#25351;&#21335; (Mac App Direct Distribution, DMG Signing &amp; Notarization Guide)</span></a></strong></h3><p><span>&#30456;&#27604;&#36890;&#36807; Mac App Store &#21457;&#24067;&#24212;&#29992;&#65292;&#30452;&#25509;&#20998;&#21457; macOS App &#38656;&#35201;&#24320;&#21457;&#32773;&#33258;&#24049;&#22788;&#29702;&#26356;&#22810;&#21457;&#24067;&#29615;&#33410;&#65306;Developer ID &#31614;&#21517;&#12289;DMG &#21046;&#20316;&#12289;notarization&#12289;staple &#20197;&#21450;&#26368;&#32456;&#30340; Gatekeeper &#39564;&#35777;&#65292;&#20219;&#20309;&#19968;&#20010;&#27493;&#39588;&#20986;&#29616;&#38382;&#39064;&#65292;&#37117;&#21487;&#33021;&#23548;&#33268;&#29992;&#25143;&#26080;&#27861;&#27491;&#24120;&#23433;&#35013;&#12290;&#8288;</span><a href="https://x.com/StewartLynch"><span>Stewart Lynch</span></a><span> &#23436;&#25972;&#28436;&#31034;&#20102;&#19968;&#22871;&#20174; Xcode Archive&#12289;&#21046;&#20316; DMG&#65292;&#21040;&#26368;&#32456;&#31614;&#21517;&#12289;notarization &#21644;&#39564;&#35777;&#30340;&#21457;&#24067;&#24037;&#20316;&#27969;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-06"><span>&#22312; SwiftUI &#20013;&#20248;&#38597;&#28040;&#36153; SKIE Flow (Consuming SKIE Flows in SwiftUI)</span></a></strong></h3><p><span>&#22312;&#37319;&#29992; Kotlin Multiplatform&#65288;KMP&#65289;&#20849;&#20139;&#19994;&#21153;&#36923;&#36753;&#12289;&#20351;&#29992; SwiftUI &#26500;&#24314;&#21407;&#29983; UI &#30340;&#39033;&#30446;&#20013;&#65292;&#22914;&#20309;&#35753; Kotlin API &#26356;&#33258;&#28982;&#22320;&#34701;&#20837; Swift &#29983;&#24577;&#19968;&#30452;&#26159;&#19968;&#20010;&#37325;&#35201;&#38382;&#39064;&#12290;SKIE&#65288;Swift Kotlin Interface Enhancer&#65289;&#27491;&#26159;&#20026;&#25913;&#21892;&#36825;&#19968;&#20114;&#25805;&#20316;&#20307;&#39564;&#32780;&#29983;&#65292;&#23427;&#21487;&#20197;&#23558; Kotlin </span><code>Flow</code><span> &#36716;&#25442;&#20026; Swift </span><code>AsyncSequence</code><span>&#65292;&#35753; Swift &#31471;&#36890;&#36807;&#29087;&#24713;&#30340; Swift Concurrency &#26041;&#24335;&#28040;&#36153;&#25968;&#25454;&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/faogustavo"><span>Gustavo F&#227;o Valvassori</span></a><span> &#20171;&#32461;&#20102; SKIE &#38024;&#23545; SwiftUI &#25552;&#20379;&#30340;&#19968;&#32452; API&#65306;&#38500;&#20102;&#30452;&#25509;&#22312; </span><code>.task</code><span> &#20013;&#36890;&#36807; </span><code>AsyncSequence</code><span> &#33719;&#21462;&#25968;&#25454;&#65292;&#36824;&#21487;&#20197;&#20351;&#29992; </span><code>.collect</code><span> &#23558; Flow &#30340;&#21464;&#21270;&#32465;&#23450;&#21040; SwiftUI state&#65292;&#25110;&#32773;&#36890;&#36807; </span><code>Observing</code><span> wrapper &#38544;&#34255;&#29366;&#24577;&#31649;&#29702;&#65292;&#35753; Kotlin </span><code>StateFlow</code><span> &#30340;&#26368;&#26032;&#20540;&#30452;&#25509;&#21442;&#19982; View &#30340;&#26500;&#24314;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-07"><span>Sarunw &#30340; How to &#31995;&#21015;&#22238;&#24402;</span></a></strong></h3><p><span>&#8288;</span><a href="https://x.com/sarunw"><span>Sarunw</span></a><span> &#30340;&#21338;&#23458;&#19968;&#30452;&#26159;&#24456;&#22810;&#24320;&#21457;&#32773;&#33719;&#21462; Apple &#29983;&#24577;&#24320;&#21457;&#25216;&#24039;&#30340;&#20248;&#31168;&#36164;&#28304;&#12290;&#19981;&#36807;&#20174; 2023 &#24180;&#24213;&#24320;&#22987;&#65292;&#21338;&#23458;&#20415;&#20572;&#27490;&#20102;&#26356;&#26032;&#12290;&#19978;&#21608;&#65292;Sarunw &#37325;&#26032;&#24320;&#22987;&#21019;&#20316;&#65292;&#24182;&#22312;&#19968;&#21608;&#20869;&#36830;&#32493;&#25512;&#20986;&#20102;&#25968;&#31687; How to &#31995;&#21015;&#25991;&#31456;&#12290;&#24456;&#24320;&#24515;&#30475;&#21040;&#19968;&#20301;&#20248;&#31168;&#20869;&#23481;&#21019;&#20316;&#32773;&#22312;&#27785;&#23490;&#36817;&#19977;&#24180;&#21518;&#37325;&#26032;&#22238;&#24402;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0151-08"><span>JindoKit&#65306;&#22312; App &#20869;&#39044;&#35272;&#28789;&#21160;&#23707;&#30028;&#38754;</span></a></strong></h3><p><span>WidgetKit &#25552;&#20379;&#30340; Live Activity &#39044;&#35272;&#20027;&#35201;&#26381;&#21153;&#20110; Xcode &#20013;&#30340;&#24320;&#21457;&#19982;&#35843;&#35797;&#65307;&#23545;&#20110;&#20801;&#35768;&#29992;&#25143;&#36873;&#25321;&#20027;&#39064;&#12289;&#35843;&#25972;&#23637;&#31034;&#20869;&#23481;&#30340;&#24212;&#29992;&#65292;&#31995;&#32479;&#24182;&#26410;&#25552;&#20379;&#30456;&#24212;&#30340; App &#20869;&#39044;&#35272;&#26041;&#26696;&#12290;</span></p><p><span>&#30001; &#8288;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#24320;&#21457;&#30340; JindoKit&#65292;&#23558; WidgetKit &#39118;&#26684;&#30340; Dynamic Island API &#24102;&#20837;&#26222;&#36890; SwiftUI View&#65292;&#35753; App &#33021;&#22815;&#30452;&#25509;&#39044;&#35272;&#23637;&#24320;&#12289;&#32039;&#20945;&#21644;&#26368;&#23567;&#19977;&#31181;&#28789;&#21160;&#23707;&#24418;&#24577;&#12290;&#30001;&#20110;&#20854; API &#19982; WidgetKit &#30340;&#32467;&#26500;&#39640;&#24230;&#19968;&#33268;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#29992;&#30456;&#36817;&#30340;&#26041;&#24335;&#32452;&#32455;&#21508;&#20010;&#21306;&#22495;&#30340;&#20869;&#23481;&#65292;&#24182;&#22312; App &#37197;&#32622;&#30028;&#38754;&#19982; WidgetKit Extension &#20043;&#38388;&#22797;&#29992;&#30456;&#20851;&#35270;&#22270;&#21644;&#25968;&#25454;&#12290;&#26356;&#22810;&#20449;&#24687;&#35831;&#21442;&#38405;&#20316;&#32773;&#30340;&#20171;&#32461;&#25991;&#31456;&#65306;&#8288;</span><a href="https://openswiftuiproject.org/blog/preview-dynamic-island-presentations-with-jindokit/"><span>Preview Dynamic Island presentations in your app with JindoKit</span></a><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0151-09"><span>&#21807;&#38899;&#36755;&#20837;&#27861;</span></a></strong></h3><p><span>&#30001; &#8288;</span><a href="https://x.com/ShikiSuen"><span>Shiki Suen</span></a><span> &#24320;&#21457;&#30340;&#21807;&#38899;&#36755;&#20837;&#27861;&#65292;&#26159;&#19968;&#27454;&#38754;&#21521; macOS &#30340;&#24320;&#28304;&#20013;&#25991;&#36755;&#20837;&#27861;&#12290;&#36817;&#26399;&#25512;&#20986;&#30340;&#12300;&#29378;&#25340;&#27169;&#24335;&#12301;&#65292;&#25552;&#20379;&#20102;&#31867;&#20284;&#20013;&#25991;&#20043;&#26143;&#26234;&#33021;&#29378;&#25340;&#12289;&#25628;&#29399;&#25340;&#38899;&#12289;&#32043;&#20809;&#25340;&#38899;&#21644;&#21319;&#38451;&#25340;&#38899;&#65288;SunPinyin&#65289;&#30340;&#20813;&#36755;&#22768;&#35843;&#25171;&#23383;&#20307;&#39564;&#65292;&#37096;&#20998;&#35789;&#35821;&#36824;&#25903;&#25345;&#26356;&#28608;&#36827;&#30340;&#19981;&#23436;&#20840;&#25340;&#20889;&#12290;</span></p><p><span>&#23613;&#31649;&#25903;&#25345;&#31867;&#20284;&#29378;&#25340;&#27169;&#24335;&#30340;&#24320;&#28304;&#25340;&#38899;&#36755;&#20837;&#27861;&#24182;&#19981;&#23569;&#35265;&#65292;&#20294;&#22823;&#22810;&#21482;&#25903;&#25345;&#27721;&#35821;&#25340;&#38899;&#12290;&#21807;&#38899;&#20511;&#21161;&#33258;&#30740;&#30340;&#12300;&#40784;&#38081;&#24680;&#65288;Tekkon&#65289;&#12301;&#27880;&#25340;&#24341;&#25806;&#65292;&#23454;&#29616;&#20102;&#23545;&#33267;&#23569;&#20116;&#31181;&#26222;&#36890;&#35805;&#25340;&#38899;&#26041;&#26696;&#30340;&#29378;&#25340;&#25171;&#23383;&#25903;&#25345;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #150]]></title><description><![CDATA[AI Wanted to Give Up. The Human Didn&#8217;t.]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 24 Aug 2026 12:03:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!tevE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tevE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tevE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 424w, https://substackcdn.com/image/fetch/$s_!tevE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 848w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1272w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp" width="1456" height="723" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/562962cc-e86a-4353-a789-ce4060881555_1918x953.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:723,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213936,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/212506288?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tevE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 424w, https://substackcdn.com/image/fetch/$s_!tevE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 848w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1272w, https://substackcdn.com/image/fetch/$s_!tevE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F562962cc-e86a-4353-a789-ce4060881555_1918x953.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@orhakim?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Or Hakim</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-a-wooden-door-with-writing-on-it-C9ouVi19R6E?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>AI Wanted to Give Up. The Human Didn&#8217;t.</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-150/">Read on web &#8594;</a></p><p><span>Recently, while debugging an issue in the Intel Xe GPU driver, Linus Torvalds went through what he himself called a &#8220;&#8288;</span><a href="https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/%2B/818bebeb63dd6bf5f4e07e145f6cdbace520a34c"><span>debug session from hell</span></a><span>.&#8221; The eventual fix was almost absurdly simple: changing a </span><code>round_up()</code><span> to a </span><code>round_down()</code><span>. But finding that single line took 24 debugging patches and 18 kernel boots. Much of the tedious work along the way was done with the help of AI.</span></p><p><span>The most interesting part of the story, however, isn&#8217;t that &#8220;AI helped Linus fix a Linux kernel bug.&#8221; It&#8217;s that the AI tried to give up several times along the way. At one point, it explicitly told Linus that the problem was &#8220;impossible and unsolvable&#8221; and suggested ending the investigation. Linus rejected that conclusion. At his insistence, the AI kept faithfully carrying out new tasks despite repeatedly concluding that the problem could not be solved, and together they eventually traced the cause to something that required changing just a single line of code.</span></p><p><span>This offers a revealing glimpse into the rather subtle relationship between humans and AI today. As agents become more capable, we can delegate increasingly complete pieces of work to them: reading code, forming hypotheses, writing debugging tools, running validations, and even adjusting the next step based on new evidence. Much of the repetitive work that developers once had to perform themselves is being compressed, gradually pulling humans away from the details of execution.</span></p><p><span>But that doesn&#8217;t mean the human role is shrinking at the same pace. Quite the opposite. As AI begins to participate in analysis, make recommendations, and even offer judgments such as &#8220;this problem cannot be solved,&#8221; the responsibilities that remain with humans become clearer: deciding what is worth pursuing, knowing when to trust AI, and recognizing when to reject its conclusions.</span></p><p><span>Not every instance of human persistence will end as neatly as this one did. But sometimes, the reason to keep going just a little longer should not be so easily erased by an AI saying, &#8220;impossible.&#8221;</span></p><p><a href="https://fatbobman.com/en/weekly/issue-149/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-using-ai-to-delegating-work-to-ai/?utm_source=fatbobman%20weekly%20issue%20150&amp;utm_medium=web"><span>From Using AI to Delegating Work to AI: Some Thoughts</span></a></strong></h3><p><span>When a task already has clear goals, boundaries, and acceptance criteria, how can we truly hand it over to AI? The more complex the work an Agent can handle, the more prominent this question becomes. Model outputs can vary; as context grows longer, goals and rules may gradually fade; splitting work across multiple contexts introduces information loss and handoff drift. Having another model review the result does not necessarily mean things will naturally converge. All of these issues ultimately point to the same concept: delegatability.</span></p><p><span>This article presents some of my thoughts on AI delegatability: whether the scope of execution remains stable, whether the results can be trusted, whether the required investment is predictable, and when human intervention is necessary. Rather than pursuing the best possible result from any single run, I am more interested in how clear boundaries, acceptance criteria, externalized authoritative records, and sensible human-AI division of labor can help Agents remain stable across longer and more complex tasks, while ensuring that failures can be detected and corrected. The article concludes with the Task-Driven workflow I currently use, showing how these principles can be applied in practical AI-assisted development.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-1"><span>What is a package registry?</span></a></strong></h3><p><span>After </span><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>Swift Package Index joined Apple</span></a><span>, the two announced that they would work together to build a package registry for the Swift community. But how does a package registry differ from SwiftPM, which we have used for years, and the Package Index, which helps us discover and evaluate packages? </span><a href="https://mastodon.social/@daveverwer"><span>Dave Verwer</span></a><span> starts with SwiftPM&#8217;s current Git-based dependency model: traditional dependencies require fetching source code from a Git repository and checking out the appropriate version, while a registry can distribute published source archives directly through package IDs, without carrying Git history, while also making published versions immutable.</span></p><p><span>But the significance of a registry goes beyond making package downloads more lightweight. More importantly, it introduces a formal package publishing model and raises broader questions around developer identity, package scope ownership, version publishing, and software supply chain security. This article offers both a concise introduction to how Package Registry works and useful background for understanding the Swift package infrastructure that Apple and Swift Package Index are preparing to build.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-2"><span>Handling CoreBluetooth Timeouts and Task Cancellation Correctly</span></a></strong></h3><p><span>Wrapping CoreBluetooth&#8217;s delegate APIs in async/await with </span><code>withCheckedThrowingContinuation</code><span> is not particularly difficult. The real trouble begins with the exceptional paths: What happens if the callback never arrives? After a Task is cancelled, does the underlying Bluetooth operation keep running? And when a normal result, timeout, and cancellation occur almost simultaneously, which one should resume the continuation?</span></p><p><a href="https://juejin.cn/user/1865252320578487/posts"><span>ilawsonlu</span></a><span> explores these practical problems and explains how to build a more complete timeout and cancellation mechanism for asynchronous CoreBluetooth wrappers. The article clearly distinguishes between cancelling a Swift Task and cancelling the underlying operation, while the open-source library </span><a href="https://github.com/ilawsonlu/ArcBLEKit"><span>ArcBLEKit</span></a><span> demonstrates an approach to wrapping traditional delegate APIs in more robust Swift Concurrency APIs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-3"><span>What Is CloudKit? Apple&#8217;s Backend Explained</span></a></strong></h3><p><span>CloudKit is an important yet often underestimated piece of infrastructure in the Apple ecosystem. From simple cross-device data synchronization to shared data and public databases, it allows developers to provide their apps with backend capabilities deeply integrated with Apple platforms through iCloud, without having to build and maintain their own servers. With both SwiftData and Core Data able to integrate directly with CloudKit, many developers are already using it without necessarily interacting with the CloudKit API itself.</span></p><p><span>Starting from the basic requirements of a backend, </span><a href="https://x.com/seanallen_dev"><span>Sean Allen</span></a><span> systematically introduces CloudKit&#8217;s private, shared, and public databases, along with core concepts such as Container, Record, and Schema, and compares three approaches: SwiftData, Core Data, and using the CloudKit API directly. The article does not shy away from CloudKit&#8217;s limitations, including its dependence on the Apple ecosystem and iCloud, schema migration, cross-platform support, and constraints around complex server-side logic.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-4"><span>OCR Doesn&#8217;t Give You Text. It Gives You a Map</span></a></strong></h3><p><span>Vision OCR does not return a neatly organized block of text. Instead, it gives you a collection of observations with bounding boxes: array order does not represent reading order, word boundaries do not inherently exist, and relationships between fields cannot simply be inferred from what comes before or after. While developing a record-sleeve scanning feature, </span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> encountered four bugs in a single day that appeared different but all stemmed from the same mistaken assumption. Through these real-world cases, the article shows how to use coordinates to determine reading order, reconstruct word boundaries from spacing, and associate fields through spatial proximity. Even more instructive is the author&#8217;s testing approach: saving bounding boxes exposed by real images as fixtures, using pure geometric data to lock down each layout assumption, while retaining the original photos for end-to-end tests. As the title says, OCR does not give you text&#8212;it gives you a &#8220;map.&#8221; The actual text structure has to be reconstructed from spatial relationships.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-5"><span>6 ways to promote your app without spending a penny</span></a></strong></h3><p><span>For indie developers, finishing an app is often only the first step. Getting more people to discover it can be even harder. Kickstart, created by </span><a href="https://x.com/twostraws"><span>Paul Hudson</span></a><span>, outlines six promotional strategies in this article that require little to no financial investment: submitting to channels such as Indie App Showcase, cross-promoting with other indie developers through Kickstart Exchange, participating in communities where your target users gather, building your own mailing list, building in public, and continuously improving your App Store product page.</span></p><p><span>In addition, MacStories&#8217; </span><a href="https://x.com/viticci/status/2090835901538541640"><span>Federico Viticci</span></a><span> is looking for noteworthy new apps and app updates for his annual iOS 27 Review. If you are preparing an iOS 27 release, you can recommend your app to him via DM or email at </span><code>viticci@macstories.net</code><span>.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-6"><span>Amethyst Vein: An Open-Source, Cross-Platform Local Persistence Framework with SwiftData-Style APIs</span></a></strong></h3><p><span>Developed by </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia Koring</span></a><span>, Amethyst Vein is a local-first Swift ORM built on SQLite and SQLCipher, with APIs clearly inspired by SwiftData. It aims to bring SwiftData-style @Model, @Query, relationships, and migration APIs to Apple platforms, Linux, Android, and Windows. The project uses explicit versioned migrations, an Identity Map, and field-level synchronization, while supporting both SwiftUI and SwiftCrossUI.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-7"><span>DynamicNotch: Building Polished Notch and Screen-Edge Interactions for macOS</span></a></strong></h3><p><span>Developed by </span><a href="https://x.com/kirtandopamine"><span>Govi</span></a><span>, DynamicNotch is a macOS Swift Package designed for developers to create SwiftUI interfaces attached to the edges of the screen. It can present recording status, media controls, build progress, action confirmations, and compact views similar to Dynamic Island.</span></p><p><span>It properly handles safe areas, multiple displays, and the physical notch on MacBooks, supports all four screen edges, and can transition between compact and expanded states. DynamicNotch keeps its implementation deliberately focused: it handles geometry, clipping, positioning, and window presentation without imposing product-level logic such as gestures, notifications, or state management on developers.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-8"><span>SwiftTUI: Building Terminal Interfaces the SwiftUI Way</span></a></strong></h3><p><span>Developed by </span><a href="https://x.com/adam_zethraeus"><span>Adam Zethraeus</span></a><span>, SwiftTUI is a terminal user interface framework for Swift developers. It brings SwiftUI&#8217;s declarative programming model to the terminal: developers can build interactive interfaces using </span><code>View</code><span>, </span><code>@State</code><span>, </span><code>@Observable</code><span>, layout containers, focus, gestures, and animations, while the framework handles layout, input processing, and partial updates.</span></p><p><span>What makes SwiftTUI interesting is not simply that it lets you &#8220;write TUIs in Swift.&#8221; The same view code can run in macOS, Linux, and Windows terminals, and can also be deployed to the browser, WASI, and native SwiftUI containers. The counter on its </span><a href="https://swifttui.sh/"><span>official website</span></a><span> is itself a real SwiftTUI application, compiled to WebAssembly and running directly in the browser.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-150?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>AI &#24819;&#25918;&#24323;&#20102;&#65292;&#20154;&#27809;&#26377;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-150/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;Linus Torvalds &#22312;&#35843;&#35797;&#19968;&#20010; Intel Xe GPU &#39537;&#21160;&#38382;&#39064;&#26102;&#65292;&#32463;&#21382;&#20102;&#19968;&#22330;&#34987;&#20182;&#33258;&#24049;&#31216;&#20026;&#8220;</span><a href="https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git/%2B/818bebeb63dd6bf5f4e07e145f6cdbace520a34c"><span>debug session from hell</span></a><span>&#8221;&#30340;&#28459;&#38271;&#25490;&#26597;&#12290;&#26368;&#32456;&#30340;&#20462;&#22797;&#31616;&#21333;&#24471;&#26377;&#20123;&#19981;&#21487;&#24605;&#35758;&#65306;&#25226;&#19968;&#22788; </span><code>round_up()</code><span> &#25913;&#25104; </span><code>round_down()</code><span>&#12290;&#20294;&#20026;&#20102;&#25214;&#21040;&#36825;&#19968;&#34892;&#20195;&#30721;&#65292;&#20182;&#21069;&#21518;&#28155;&#21152;&#20102; 24 &#20010;&#35843;&#35797; patch&#65292;&#21551;&#21160;&#20102; 18 &#27425; kernel&#12290;&#20854;&#20013;&#22823;&#37327;&#32321;&#29712;&#24037;&#20316;&#65292;&#37117;&#26159;&#22312; AI &#30340;&#24110;&#21161;&#19979;&#23436;&#25104;&#30340;&#12290;</span></p><p><span>&#36825;&#20010;&#25925;&#20107;&#26368;&#26377;&#24847;&#24605;&#30340;&#22320;&#26041;&#24182;&#19981;&#26159;&#8220;AI &#24110; Linus &#20462;&#22797;&#20102; Linux Kernel Bug&#8221;&#65292;&#32780;&#26159; AI &#22312;&#36807;&#31243;&#20013;&#25968;&#27425;&#24819;&#35201;&#25918;&#24323;&#12290;&#23427;&#26366;&#26126;&#30830;&#21578;&#35785; Linus&#65292;&#36825;&#20010;&#38382;&#39064;&#8220;impossible and unsolvable&#8221;&#65292;&#24314;&#35758;&#20572;&#27490;&#32487;&#32493;&#35843;&#26597;&#12290;Linus &#27809;&#26377;&#25509;&#21463;&#36825;&#20010;&#21028;&#26029;&#12290;&#22312;&#20182;&#30340;&#22362;&#25345;&#19979;&#65292;AI &#34429;&#28982;&#25968;&#27425;&#35748;&#20026;&#38382;&#39064;&#24050;&#32463;&#26080;&#27861;&#35299;&#20915;&#65292;&#21364;&#20173;&#28982;&#24544;&#23454;&#22320;&#25191;&#34892;&#26032;&#30340;&#20219;&#21153;&#65292;&#26368;&#32456;&#21644;&#20182;&#19968;&#36215;&#25214;&#21040;&#20102;&#37027;&#20010;&#21482;&#38656;&#35201;&#20462;&#25913;&#19968;&#34892;&#20195;&#30721;&#30340;&#21407;&#22240;&#12290;</span></p><p><span>&#36825;&#20854;&#23454;&#24456;&#22909;&#22320;&#23637;&#29616;&#20102;&#29616;&#38454;&#27573;&#20154;&#19982; AI &#20043;&#38388;&#19968;&#31181;&#39047;&#20026;&#24494;&#22937;&#30340;&#20851;&#31995;&#12290;&#38543;&#30528; Agent &#33021;&#21147;&#19981;&#26029;&#22686;&#24378;&#65292;&#25105;&#20204;&#24050;&#32463;&#21487;&#20197;&#25226;&#36234;&#26469;&#36234;&#23436;&#25972;&#30340;&#24037;&#20316;&#20132;&#32473; AI&#65306;&#38405;&#35835;&#20195;&#30721;&#12289;&#25552;&#20986;&#20551;&#35774;&#12289;&#32534;&#20889;&#35843;&#35797;&#24037;&#20855;&#12289;&#25191;&#34892;&#39564;&#35777;&#65292;&#29978;&#33267;&#26681;&#25454;&#26032;&#30340;&#32467;&#26524;&#19981;&#26029;&#35843;&#25972;&#19979;&#19968;&#27493;&#34892;&#21160;&#12290;&#36807;&#21435;&#38656;&#35201;&#24320;&#21457;&#32773;&#20146;&#33258;&#23436;&#25104;&#30340;&#22823;&#37327;&#37325;&#22797;&#21171;&#21160;&#27491;&#22312;&#34987;&#21387;&#32553;&#65292;&#20154;&#20063;&#22240;&#27492;&#36880;&#28176;&#20174;&#20855;&#20307;&#30340;&#25191;&#34892;&#36807;&#31243;&#20013;&#25277;&#31163;&#20986;&#26469;&#12290;</span></p><p><span>&#20294;&#36825;&#24182;&#19981;&#24847;&#21619;&#30528;&#20154;&#30340;&#20316;&#29992;&#27491;&#22312;&#20197;&#21516;&#26679;&#30340;&#36895;&#24230;&#32553;&#23567;&#12290;&#24688;&#24688;&#30456;&#21453;&#65292;&#24403; AI &#24320;&#22987;&#21442;&#19982;&#20998;&#26512;&#12289;&#25552;&#20986;&#24314;&#35758;&#65292;&#29978;&#33267;&#32473;&#20986;&#8220;&#36825;&#20010;&#38382;&#39064;&#26080;&#27861;&#35299;&#20915;&#8221;&#36825;&#26679;&#30340;&#21028;&#26029;&#26102;&#65292;&#20154;&#30495;&#27491;&#38656;&#35201;&#25215;&#25285;&#30340;&#32844;&#36131;&#21453;&#32780;&#21464;&#24471;&#26356;&#21152;&#28165;&#26224;&#65306;&#20915;&#23450;&#20160;&#20040;&#20540;&#24471;&#20570;&#65292;&#21028;&#26029;&#20160;&#20040;&#26102;&#20505;&#24212;&#35813;&#30456;&#20449; AI&#65292;&#21448;&#22312;&#20160;&#20040;&#26102;&#20505;&#25298;&#32477;&#23427;&#30340;&#32467;&#35770;&#12290;</span></p><p><span>&#23613;&#31649;&#24182;&#38750;&#25152;&#26377;&#20154;&#31867;&#30340;&#22362;&#25345;&#37117;&#20250;&#33719;&#24471;&#31867;&#20284;&#26412;&#27425;&#30340;&#22278;&#28385;&#32467;&#26524;&#65292;&#20294;&#26377;&#26102;&#20505;&#65292;&#20877;&#22362;&#25345;&#19968;&#19979;&#30340;&#29702;&#30001;&#65292;&#33267;&#23569;&#19981;&#24212;&#35813;&#34987; AI &#30340;&#19968;&#21477;&#8220;&#19981;&#21487;&#33021;&#8221;&#36731;&#26131;&#25273;&#21435;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-149/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-using-ai-to-delegating-work-to-ai/?utm_source=fatbobman%20weekly%20issue%20150&amp;utm_medium=web"><span>&#20174;&#20351;&#29992; AI &#21040;&#22996;&#25176; AI&#65306;&#25105;&#30340;&#19968;&#20123;&#24605;&#32771;</span></a></strong></h3><p><span>&#24403;&#19968;&#39033;&#24037;&#20316;&#24050;&#32463;&#26377;&#26126;&#30830;&#30446;&#26631;&#12289;&#36793;&#30028;&#21644;&#39564;&#25910;&#35201;&#27714;&#26102;&#65292;&#24590;&#26679;&#25226;&#23427;&#30495;&#27491;&#20132;&#32473; AI&#65311;Agent &#33021;&#23436;&#25104;&#30340;&#24037;&#20316;&#36234;&#22797;&#26434;&#65292;&#36825;&#20010;&#38382;&#39064;&#23601;&#36234;&#31361;&#20986;&#12290;&#27169;&#22411;&#30340;&#36755;&#20986;&#23384;&#22312;&#27874;&#21160;&#65307;&#19978;&#19979;&#25991;&#21464;&#38271;&#21518;&#65292;&#30446;&#26631;&#21644;&#35268;&#21017;&#21487;&#33021;&#36880;&#28176;&#28129;&#21270;&#65307;&#25286;&#36827;&#22810;&#20010;&#19978;&#19979;&#25991;&#65292;&#21448;&#20250;&#24102;&#26469;&#20449;&#24687;&#25439;&#22833;&#21644;&#20132;&#25509;&#20559;&#31227;&#12290;&#35753;&#21478;&#19968;&#20010;&#27169;&#22411;&#22797;&#26680;&#65292;&#20063;&#19981;&#24847;&#21619;&#30528;&#32467;&#26524;&#19968;&#23450;&#20250;&#33258;&#28982;&#25910;&#25947;&#12290;&#36825;&#20123;&#38382;&#39064;&#26368;&#32456;&#25351;&#21521;&#21516;&#19968;&#20010;&#35789;&#65306;&#21487;&#22996;&#25176;&#24615;&#12290;</span></p><p><span>&#26412;&#25991;&#26159;&#25105;&#23545; AI &#21487;&#22996;&#25176;&#24615;&#30340;&#19968;&#20123;&#24605;&#32771;&#65306;&#25191;&#34892;&#33539;&#22260;&#26159;&#21542;&#31283;&#23450;&#65292;&#32467;&#26524;&#33021;&#21542;&#34987;&#20449;&#20219;&#65292;&#25237;&#20837;&#26159;&#21542;&#21487;&#20197;&#39044;&#26399;&#65292;&#20197;&#21450;&#20160;&#20040;&#26102;&#20505;&#38656;&#35201;&#20154;&#20171;&#20837;&#12290;&#30456;&#27604;&#36861;&#27714;&#26576;&#19968;&#27425;&#25191;&#34892;&#30340;&#26368;&#22909;&#32467;&#26524;&#65292;&#25105;&#26356;&#20851;&#24515;&#22914;&#20309;&#36890;&#36807;&#26126;&#30830;&#36793;&#30028;&#12289;&#39564;&#25910;&#26631;&#20934;&#12289;&#22806;&#32622;&#30340;&#26435;&#23041;&#35760;&#24405;&#20197;&#21450;&#21512;&#29702;&#30340;&#20154;&#26426;&#20998;&#24037;&#65292;&#35753; Agent &#22312;&#26356;&#38271;&#12289;&#26356;&#22797;&#26434;&#30340;&#20219;&#21153;&#20013;&#20445;&#25345;&#31283;&#23450;&#65292;&#24182;&#35753;&#22833;&#36133;&#33021;&#22815;&#34987;&#21457;&#29616;&#21644;&#32416;&#27491;&#12290;&#25991;&#31456;&#26368;&#21518;&#20063;&#32467;&#21512;&#25105;&#30446;&#21069;&#20351;&#29992;&#30340; Task-Driven &#24037;&#20316;&#27969;&#65292;&#23637;&#31034;&#36825;&#20123;&#21407;&#21017;&#22914;&#20309;&#33853;&#23454;&#21040;&#23454;&#38469;&#30340; AI &#24320;&#21457;&#36807;&#31243;&#20013;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-1"><span>&#35748;&#35782; Swift &#21253;&#27880;&#20876;&#34920; (What is a package registry?)</span></a></strong></h3><p><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>Swift Package Index &#21152;&#20837; Apple</span></a><span> &#21518;&#65292;&#21452;&#26041;&#23459;&#24067;&#23558;&#20849;&#21516;&#24314;&#35774;&#19968;&#20010;&#38754;&#21521; Swift &#31038;&#21306;&#30340; package registry&#12290;&#20294; package registry &#19982;&#25105;&#20204;&#24050;&#32463;&#20351;&#29992;&#22810;&#24180;&#30340; SwiftPM&#65292;&#20197;&#21450;&#29992;&#20110;&#21457;&#29616;&#21644;&#35780;&#20272;&#21253;&#30340; Package Index&#65292;&#31350;&#31455;&#26377;&#20160;&#20040;&#21306;&#21035;&#65311;&#8288;</span><a href="https://mastodon.social/@daveverwer"><span>Dave Verwer</span></a><span> &#20174; SwiftPM &#24403;&#21069;&#22522;&#20110; Git &#30340;&#20381;&#36182;&#26041;&#24335;&#35762;&#36215;&#65306;&#20256;&#32479;&#20381;&#36182;&#38656;&#35201;&#20174; Git &#20179;&#24211;&#33719;&#21462;&#28304;&#30721;&#24182; checkout &#23545;&#24212;&#29256;&#26412;&#65292;&#32780; registry &#21487;&#20197;&#36890;&#36807; package ID &#30452;&#25509;&#20998;&#21457;&#24050;&#32463;&#21457;&#24067;&#30340;&#28304;&#30721; archive&#65292;&#26080;&#38656;&#25658;&#24102; Git history&#65292;&#21516;&#26102;&#21457;&#24067;&#21518;&#30340;&#29256;&#26412;&#20063;&#20855;&#26377;&#19981;&#21487;&#21464;&#24615;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;registry &#30340;&#24847;&#20041;&#24182;&#19981;&#21482;&#26159;&#35753; package &#19979;&#36733;&#21464;&#24471;&#26356;&#36731;&#37327;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;registry &#36824;&#24341;&#20837;&#20102;&#19968;&#22871;&#27491;&#24335;&#30340; package publishing &#27169;&#22411;&#65292;&#24182;&#36827;&#19968;&#27493;&#28041;&#21450;&#24320;&#21457;&#32773;&#36523;&#20221;&#12289;package scope &#25152;&#26377;&#26435;&#12289;&#29256;&#26412;&#21457;&#24067;&#20197;&#21450;&#36719;&#20214;&#20379;&#24212;&#38142;&#23433;&#20840;&#31561;&#38382;&#39064;&#12290;&#36825;&#31687;&#25991;&#31456;&#26082;&#26159;&#19968;&#31687;&#23545; Package Registry &#24037;&#20316;&#26041;&#24335;&#30340;&#31616;&#26126;&#20171;&#32461;&#65292;&#20063;&#20026;&#29702;&#35299; Apple &#19982; Swift Package Index &#25509;&#19979;&#26469;&#20934;&#22791;&#24314;&#35774;&#30340; Swift &#21253;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#25552;&#20379;&#20102;&#24456;&#22909;&#30340;&#32972;&#26223;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-2"><span>&#22914;&#20309;&#27491;&#30830;&#22788;&#29702; CoreBluetooth &#36229;&#26102;&#19982; Task Cancellation</span></a></strong></h3><p><span>&#29992; </span><code>withCheckedThrowingContinuation</code><span> &#23558; CoreBluetooth &#30340; delegate API &#23553;&#35013;&#25104; async/await &#24182;&#19981;&#22256;&#38590;&#65292;&#30495;&#27491;&#40635;&#28902;&#30340;&#26159;&#20043;&#21518;&#30340;&#24322;&#24120;&#36335;&#24452;&#65306;&#22914;&#26524; callback &#36831;&#36831;&#27809;&#26377;&#36820;&#22238;&#24590;&#20040;&#21150;&#65311;Task &#34987;&#21462;&#28040;&#21518;&#65292;&#24213;&#23618;&#34013;&#29273;&#25805;&#20316;&#26159;&#21542;&#20173;&#22312;&#32487;&#32493;&#65311;&#24403;&#27491;&#24120;&#32467;&#26524;&#12289;&#36229;&#26102;&#21644;&#21462;&#28040;&#20960;&#20046;&#21516;&#26102;&#21457;&#29983;&#26102;&#65292;&#21448;&#35813;&#30001;&#35841;&#26469; resume continuation&#65311;</span></p><p><a href="https://juejin.cn/user/1865252320578487/posts"><span>ilawsonlu</span></a><span> &#22260;&#32469;&#36825;&#20123;&#23454;&#38469;&#38382;&#39064;&#65292;&#20171;&#32461;&#20102;&#22914;&#20309;&#20026; CoreBluetooth &#30340;&#24322;&#27493;&#23553;&#35013;&#24314;&#31435;&#26356;&#23436;&#25972;&#30340; timeout &#19982; cancellation &#26426;&#21046;&#65292;&#24182;&#26126;&#30830;&#21306;&#20998;&#12300;&#21462;&#28040; Swift Task&#12301;&#19982;&#12300;&#21462;&#28040;&#24213;&#23618;&#25805;&#20316;&#12301;&#65292;&#21516;&#26102;&#36890;&#36807;&#24320;&#28304;&#24211; </span><a href="https://github.com/ilawsonlu/ArcBLEKit"><span>ArcBLEKit</span></a><span> &#23637;&#31034;&#20102;&#23558;&#20256;&#32479; delegate API &#23553;&#35013;&#25104;&#26356;&#20581;&#22766;&#30340; Swift Concurrency API &#30340;&#24605;&#36335;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-3"><span>&#35814;&#35299; CloudKit&#65306;Apple &#29983;&#24577;&#30340;&#21518;&#31471;&#26381;&#21153; (What Is CloudKit? Apple&#8217;s Backend Explained)</span></a></strong></h3><p><span>CloudKit &#26159; Apple &#29983;&#24577;&#20013;&#38750;&#24120;&#37325;&#35201;&#12289;&#21364;&#24120;&#24120;&#34987;&#20302;&#20272;&#30340;&#19968;&#22359;&#22522;&#30784;&#35774;&#26045;&#12290;&#20174;&#31616;&#21333;&#30340;&#36328;&#35774;&#22791;&#25968;&#25454;&#21516;&#27493;&#65292;&#21040;&#20849;&#20139;&#25968;&#25454;&#21644;&#20844;&#20849;&#25968;&#25454;&#24211;&#65292;&#23427;&#35753;&#24320;&#21457;&#32773;&#26080;&#38656;&#33258;&#34892;&#25645;&#24314;&#26381;&#21153;&#22120;&#65292;&#23601;&#33021;&#20381;&#25176; iCloud &#20026; App &#25552;&#20379;&#19968;&#22871;&#19982; Apple &#24179;&#21488;&#28145;&#24230;&#38598;&#25104;&#30340;&#21518;&#31471;&#33021;&#21147;&#12290;&#23588;&#20854;&#38543;&#30528; SwiftData &#21644; Core Data &#37117;&#33021;&#22815;&#30452;&#25509;&#25509;&#20837; CloudKit&#65292;&#35768;&#22810;&#24320;&#21457;&#32773;&#23454;&#38469;&#19978;&#24050;&#32463;&#22312;&#20351;&#29992;&#23427;&#65292;&#21482;&#26159;&#19981;&#19968;&#23450;&#38656;&#35201;&#30452;&#25509;&#38754;&#23545; CloudKit API&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/seanallen_dev"><span>Sean Allen</span></a><span> &#20174; backend &#30340;&#22522;&#26412;&#38656;&#27714;&#20986;&#21457;&#65292;&#31995;&#32479;&#20171;&#32461;&#20102; CloudKit &#30340; private&#12289;shared &#21644; public database&#65292;&#20197;&#21450; Container&#12289;Record&#12289;Schema &#31561;&#26680;&#24515;&#27010;&#24565;&#65292;&#24182;&#27604;&#36739;&#20102; SwiftData&#12289;Core Data &#21644;&#30452;&#25509;&#20351;&#29992; CloudKit API &#19977;&#31181;&#25509;&#20837;&#26041;&#24335;&#12290;&#25991;&#31456;&#24182;&#27809;&#26377;&#22238;&#36991;&#23427;&#30340;&#36793;&#30028;&#65292;&#21253;&#25324;&#23545; Apple &#29983;&#24577;&#21644; iCloud &#30340;&#20381;&#36182;&#12289;schema migration&#12289;&#36328;&#24179;&#21488;&#33021;&#21147;&#20197;&#21450;&#22797;&#26434;&#26381;&#21153;&#31471;&#36923;&#36753;&#30340;&#38480;&#21046;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-4"><span>&#37325;&#26032;&#35748;&#35782; OCR&#65306;&#23427;&#26159;&#31354;&#38388;&#22320;&#22270;&#65292;&#32780;&#38750;&#32431;&#25991;&#26412; (OCR Doesn&#8217;t Give You Text. It Gives You a Map)</span></a></strong></h3><p><span>Vision OCR &#36820;&#22238;&#30340;&#24182;&#19981;&#26159;&#19968;&#27573;&#24050;&#32463;&#32452;&#32455;&#22909;&#30340;&#25991;&#26412;&#65292;&#32780;&#26159;&#19968;&#32452;&#24102;&#26377; bounding box &#30340; observations&#65306;&#25968;&#32452;&#39034;&#24207;&#19981;&#20195;&#34920;&#38405;&#35835;&#39034;&#24207;&#12289;&#21333;&#35789;&#36793;&#30028;&#24182;&#19981;&#23384;&#22312;&#65292;&#23383;&#27573;&#20043;&#38388;&#30340;&#20851;&#31995;&#20063;&#19981;&#33021;&#31616;&#21333;&#36890;&#36807;&#21069;&#21518;&#20301;&#32622;&#21028;&#26029;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/wesmatlock/"><span>Wesley Matlock</span></a><span> &#22312;&#24320;&#21457;&#21809;&#29255;&#23553;&#22871;&#25195;&#25551;&#21151;&#33021;&#26102;&#65292;&#19968;&#22825;&#20869;&#36830;&#32493;&#36935;&#21040;&#20102;&#22235;&#20010;&#30475;&#20284;&#19981;&#21516;&#12289;&#23454;&#21017;&#26469;&#33258;&#21516;&#19968;&#38169;&#35823;&#20551;&#35774;&#30340; Bug&#12290;&#26412;&#25991;&#36890;&#36807;&#36825;&#20123;&#30495;&#23454;&#26696;&#20363;&#23637;&#31034;&#20102;&#22914;&#20309;&#21033;&#29992;&#22352;&#26631;&#35745;&#31639;&#38405;&#35835;&#39034;&#24207;&#12289;&#26681;&#25454;&#38388;&#36317;&#24674;&#22797;&#21333;&#35789;&#36793;&#30028;&#65292;&#24182;&#36890;&#36807;&#31354;&#38388;&#37051;&#36817;&#20851;&#31995;&#20851;&#32852;&#23383;&#27573;&#12290;&#26356;&#20540;&#24471;&#20511;&#37492;&#30340;&#26159;&#20316;&#32773;&#30340;&#27979;&#35797;&#26041;&#24335;&#65306;&#23558;&#30495;&#23454;&#22270;&#29255;&#26292;&#38706;&#20986;&#30340; bounding box &#20445;&#23384;&#20026; fixture&#65292;&#29992;&#32431;&#20960;&#20309;&#25968;&#25454;&#22266;&#23450;&#27599;&#19968;&#39033;&#24067;&#23616;&#20551;&#35774;&#65292;&#21516;&#26102;&#20445;&#30041;&#30495;&#23454;&#29031;&#29255;&#20316;&#20026;&#31471;&#21040;&#31471;&#27979;&#35797;&#12290;&#27491;&#22914;&#26631;&#39064;&#25152;&#35828;&#65292;OCR &#32473;&#20320;&#30340;&#19981;&#26159;&#25991;&#26412;&#65292;&#32780;&#26159;&#19968;&#24352;&#12300;&#22320;&#22270;&#12301;&#65292;&#30495;&#27491;&#30340;&#25991;&#26412;&#32467;&#26500;&#38656;&#35201;&#20174;&#31354;&#38388;&#20851;&#31995;&#20013;&#37325;&#26032;&#26500;&#24314;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-5"><span>&#29420;&#31435;&#24212;&#29992;&#38646;&#25104;&#26412;&#25512;&#24191;&#30340; 6 &#20010;&#31574;&#30053; (6 ways to promote your app without spending a penny)</span></a></strong></h3><p><span>&#23545;&#20110;&#29420;&#31435;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#20889;&#23436; App &#24448;&#24448;&#21482;&#26159;&#31532;&#19968;&#27493;&#65292;&#22914;&#20309;&#35753;&#26356;&#22810;&#20154;&#30693;&#36947;&#23427;&#21487;&#33021;&#26356;&#21152;&#22256;&#38590;&#12290;&#30001; &#8288;</span><a href="https://x.com/twostraws"><span>Paul Hudson</span></a><span> &#21019;&#24314;&#30340; Kickstart &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#25972;&#29702;&#20102;&#20845;&#31181;&#20960;&#20046;&#19981;&#38656;&#35201;&#36164;&#37329;&#25237;&#20837;&#30340;&#25512;&#24191;&#26041;&#24335;&#65306;&#21521; Indie App Showcase &#31561;&#28192;&#36947;&#25237;&#31295;&#12289;&#36890;&#36807; Kickstart Exchange &#19982;&#20854;&#20182;&#29420;&#31435;&#24320;&#21457;&#32773;&#20132;&#21449;&#25512;&#24191;&#12289;&#21442;&#19982;&#30446;&#26631;&#29992;&#25143;&#25152;&#22312;&#30340;&#31038;&#21306;&#12289;&#24314;&#31435;&#33258;&#24049;&#30340;&#37038;&#20214;&#21015;&#34920;&#12289;Build in Public&#65292;&#20197;&#21450;&#25345;&#32493;&#20248;&#21270; App Store &#20135;&#21697;&#39029;&#38754;&#12290;</span></p><p><span>&#21478;&#22806;&#65292;MacStories &#30340; </span><a href="https://x.com/viticci/status/2090835901538541640"><span>Federico Viticci</span></a><span> &#27491;&#22312;&#20026;&#24180;&#24230; iOS 27 Review &#23547;&#25214;&#20540;&#24471;&#20851;&#27880;&#30340;&#26032; App &#21644; App &#26356;&#26032;&#12290;&#22914;&#26524;&#20320;&#27491;&#22312;&#20934;&#22791; iOS 27 &#29256;&#26412;&#65292;&#21487;&#20197;&#36890;&#36807; DM &#25110;&#37038;&#20214; </span><code>viticci@macstories.net</code><span> &#21521;&#20182;&#25512;&#33616;&#33258;&#24049;&#30340;&#20316;&#21697;&#12290; &#8288;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0150-6"><span>Amethyst Vein&#65306;&#36328;&#24179;&#21488;&#12289;SwiftData &#39118;&#26684; API &#30340;&#24320;&#28304;&#26412;&#22320;&#25345;&#20037;&#21270;&#26694;&#26550;</span></a></strong></h3><p><span>&#30001; </span><a href="https://www.linkedin.com/in/mia-koring-06a796307/"><span>Mia Koring</span></a><span> &#24320;&#21457;&#30340; Amethyst Vein &#26159;&#19968;&#20010;&#26412;&#22320;&#20248;&#20808;&#30340; Swift ORM&#65292;&#37319;&#29992; SQLite &#19982; SQLCipher &#20316;&#20026;&#23384;&#20648;&#22522;&#30784;&#65292;API &#21017;&#26126;&#26174;&#20511;&#37492;&#20102; SwiftData&#12290;&#23427;&#35797;&#22270;&#25226; SwiftData &#39118;&#26684;&#30340; @Model&#12289;@Query&#12289;&#20851;&#31995;&#21644;&#36801;&#31227; API &#24102;&#21040; Apple&#12289;Linux&#12289;Android &#19982; Windows&#12290;&#39033;&#30446;&#37319;&#29992;&#26174;&#24335;&#29256;&#26412;&#21270;&#36801;&#31227;&#12289;Identity Map &#21644;&#23383;&#27573;&#32423;&#21516;&#27493;&#65292;&#24182;&#21516;&#26102;&#25903;&#25345; SwiftUI &#19982; SwiftCrossUI&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-7"><span>DynamicNotch&#65306;&#24110;&#21161;&#24320;&#21457;&#32773;&#20026; macOS &#26500;&#24314;&#31934;&#33268;&#30340;&#21016;&#28023;&#19982;&#23631;&#24149;&#36793;&#32536;&#20132;&#20114;</span></a></strong></h3><p><span>&#30001; </span><a href="https://x.com/kirtandopamine"><span>Govi</span></a><span> &#24320;&#21457;&#30340; DynamicNotch &#26159;&#19968;&#20010;&#19987;&#20026;&#24320;&#21457;&#32773;&#25171;&#36896;&#30340; macOS Swift Package&#65292;&#29992;&#20110;&#21019;&#24314;&#36148;&#38468;&#20110;&#23631;&#24149;&#36793;&#32536;&#30340; SwiftUI &#30028;&#38754;&#65292;&#21487;&#21576;&#29616;&#24405;&#38899;&#29366;&#24577;&#12289;&#23186;&#20307;&#25511;&#21046;&#12289;&#26500;&#24314;&#36827;&#24230;&#12289;&#25805;&#20316;&#30830;&#35748;&#65292;&#20197;&#21450;&#31867;&#20284; Dynamic Island &#30340;&#32039;&#20945;&#35270;&#22270;&#12290;</span></p><p><span>&#23427;&#33021;&#22949;&#21892;&#22788;&#29702;&#23433;&#20840;&#21306;&#22495;&#12289;&#22810;&#26174;&#31034;&#22120;&#21644; MacBook &#23454;&#20307;&#21016;&#28023;&#65292;&#25903;&#25345;&#19978;&#19979;&#24038;&#21491;&#22235;&#20010;&#26041;&#21521;&#65292;&#20063;&#21487;&#20197;&#22312;&#32039;&#20945;&#19982;&#23637;&#24320;&#29366;&#24577;&#20043;&#38388;&#20999;&#25442;&#12290;DynamicNotch &#30340;&#23454;&#29616;&#27604;&#36739;&#20811;&#21046;&#65292;&#21482;&#36127;&#36131;&#20960;&#20309;&#12289;&#35009;&#21098;&#12289;&#23450;&#20301;&#19982;&#31383;&#21475;&#21576;&#29616;&#65292;&#24182;&#26410;&#23558;&#25163;&#21183;&#12289;&#36890;&#30693;&#12289;&#29366;&#24577;&#31649;&#29702;&#31561;&#20135;&#21697;&#36923;&#36753;&#24378;&#21152;&#32473;&#20351;&#29992;&#32773;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0150-8"><span>SwiftTUI&#65306;&#29992; SwiftUI &#30340;&#26041;&#24335;&#26500;&#24314;&#32456;&#31471;&#30028;&#38754;</span></a></strong></h3><p><span>&#30001; </span><a href="https://x.com/adam_zethraeus"><span>Adam Zethraeus</span></a><span> &#24320;&#21457;&#30340; SwiftTUI &#26159;&#19968;&#20010;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#32456;&#31471;&#29992;&#25143;&#30028;&#38754;&#26694;&#26550;&#12290;&#23427;&#23558; SwiftUI &#30340;&#22768;&#26126;&#24335;&#32534;&#31243;&#27169;&#22411;&#24102;&#36827;&#32456;&#31471;&#65306;&#24320;&#21457;&#32773;&#21487;&#20197;&#20351;&#29992; </span><code>View</code><span>&#12289;</span><code>@State</code><span>&#12289;</span><code>@Observable</code><span>&#12289;&#24067;&#23616;&#23481;&#22120;&#12289;&#28966;&#28857;&#12289;&#25163;&#21183;&#19982;&#21160;&#30011;&#26500;&#24314;&#20132;&#20114;&#30028;&#38754;&#65292;&#30001;&#26694;&#26550;&#36127;&#36131;&#24067;&#23616;&#12289;&#36755;&#20837;&#22788;&#29702;&#21644;&#23616;&#37096;&#21047;&#26032;&#12290;</span></p><p><span>SwiftTUI &#30340;&#26377;&#36259;&#20043;&#22788;&#65292;&#19981;&#21482;&#26159;&#8220;&#29992; Swift &#20889; TUI&#8221;&#12290;&#21516;&#19968;&#22871;&#35270;&#22270;&#20195;&#30721;&#36824;&#21487;&#20197;&#36816;&#34892;&#20110; macOS&#12289;Linux &#21644; Windows &#32456;&#31471;&#65292;&#24182;&#36827;&#19968;&#27493;&#37096;&#32626;&#21040;&#27983;&#35272;&#22120;&#12289;WASI&#65292;&#20197;&#21450;&#21407;&#29983; SwiftUI &#23481;&#22120;&#65307;</span><a href="https://swifttui.sh/"><span>&#23448;&#32593;</span></a><span>&#25552;&#20379;&#30340;&#35745;&#25968;&#22120;&#23601;&#26159;&#19968;&#20010;&#30495;&#23454;&#30340; SwiftTUI &#24212;&#29992;&#65292;&#32463; WebAssembly &#32534;&#35793;&#21518;&#30452;&#25509;&#36816;&#34892;&#22312;&#32593;&#39029;&#20013;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #149]]></title><description><![CDATA[Who Is the Slower App Review Process Actually Stopping?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 17 Aug 2026 12:03:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uzTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uzTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uzTo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 424w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 848w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1272w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp" width="1456" height="753" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:753,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:240752,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/211500446?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uzTo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 424w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 848w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1272w, https://substackcdn.com/image/fetch/$s_!uzTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52d06369-9c42-4f2d-bc13-505e83872443_1915x990.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@worldsbetweenlines?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Patrick Hendry</a><span> on </span><a href="https://unsplash.com/photos/two-silver-swords-on-shield-6CfpUEmNWAU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Who Is the Slower App Review Process Actually Stopping?</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-149/">Read on web &#8594;</a></p><p><span>Slower App Store reviews have become something more and more developers can clearly feel. In the age of vibe coding, the cost of building and iterating on apps has dropped dramatically, so it is not hard to understand why the review system is under greater pressure. The problem is that longer review times seem to be little more than a system overwhelmed by a growing volume of submissions, without a corresponding increase in the barriers that keep scam apps out of the store.</span></p><p><span>Recently, Jeff Johnson came across a highly suspicious Safari extension in the Mac App Store: its screenshots appeared to be AI-generated, advertised a nonexistent &#8220;4.9 out of 5&#8221; rating, and some of its five-star reviews were even dated before the app itself was released. Looking further, he found that the developer behind the extension had 41 apps on the App Store and had accumulated at least 368 approved review submissions over the past year&#8212;nearly one per day on average. Meanwhile, well-known developer Marco Arment&#8217;s new app had already been sitting in the review queue for 12 days.</span></p><p><span>This creates a rather awkward situation. On one hand, suspicious and potentially fraudulent apps can make it through review and climb the charts. On the other, AI has made rapid development and frequent iteration easier than ever, sending large numbers of both legitimate and high-risk submissions through the same review system and consuming its limited resources.</span></p><p><span>An &#8288;</span><a href="https://mjtsai.com/blog/2026/08/14/tabcontrol-scam-and-the-app-review-queue/"><span>urgent question</span></a><span> is becoming difficult to avoid: Should App Review continue to treat each submission in isolation?</span></p><p><span>Johnson suggests introducing something akin to a trust system, allowing developers with a long history of following the rules and maintaining a good review record to receive faster reviews, while directing more resources toward accounts that submit at unusually high volumes, publish apps in bulk, or exhibit other suspicious patterns. Critics worry that such a system could eventually turn into preferential treatment for well-known developers or those willing to pay, further raising the barrier to entry for newcomers to the App Store.</span></p><p><span>Now that AI has dramatically reduced the cost of producing apps, a review model that treats every submission as an isolated case is becoming increasingly difficult to sustain. I see nothing unreasonable about incorporating factors such as a developer&#8217;s history, submission frequency, similarities among their apps, and metadata anomalies into risk assessment. A strong track record should not mean exemption from review, but rather fewer repetitive, low-value checks; suspicious accounts should not be barred from submitting, but should receive greater scrutiny.</span></p><p><span>Perhaps what App Review truly needs is not simply greater efficiency, but a shift from reviewing individual submissions in isolation toward evaluating patterns of developer behavior.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-148/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/contentbuilder-explained/?utm_source=fatbobman%20weekly%20issue%20149&amp;utm_medium=web"><span>ContentBuilder Explained: The Secret Behind SwiftUI&#8217;s Type-Checking Speedup</span></a></strong></h3><p><span>In the WWDC 2026 session on what&#8217;s new in SwiftUI, Apple engineers introduced a new SwiftUI feature: </span><code>ContentBuilder</code><span>. Judging by how you use it, it looks like nothing more than a </span><code>ViewBuilder</code><span> with a wider reach &#8212; APIs that previously accepted </span><code>ViewBuilder</code><span>, </span><code>ToolbarContentBuilder</code><span>, or </span><code>CommandsBuilder</code><span> separately can now share a single builder. Apple also claims the change delivers a significant improvement in type-checking performance. This article digs into what </span><code>ContentBuilder</code><span> actually is, and where that performance comes from.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-01"><span>Headless Xcode: From Prompt to Simulator with MCP</span></a></strong></h3><p><span>Xcode 27 beta 5 introduces </span><code>xcrun mcp-server</code><span>, allowing Xcode&#8217;s MCP capabilities to be exposed to external coding agents as a background service without launching the Xcode UI. </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> uses Claude Code to demonstrate a complete Headless Xcode workflow: creating an Xcode project, generating SwiftUI code, building the project and rendering previews, launching the Simulator, reading the accessibility hierarchy, performing interactions, and finally verifying app state through screenshots and OSLog. This means a complete development loop&#8212;from prompt to code, then execution and verification&#8212;is beginning to take shape without relying on the Xcode UI.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-02"><span>iOS 26: Data Detector</span></a></strong></h3><p><span>iOS 26 introduces the new </span><code>DataDetector</code><span>, providing a more modern, Swift-native alternative to the long-standing </span><code>NSDataDetector</code><span>. </span><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> walks through the new API with numerous examples: developers can obtain an </span><code>AsyncSequence</code><span> directly through </span><code>StringProtocol.dataDetectorMatches</code><span>, then use native Swift ranges and strongly typed semantic results to identify email addresses, phone numbers, dates, addresses, monetary amounts, measurements, flight numbers, shipment tracking numbers, and more. The new API not only feels more natural to use, but can also recognize a richer set of semantic objects.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-03"><span>Measuring Elapsed Time in Swift with ContinuousClock</span></a></strong></h3><p><span>Many developers still habitually use </span><code>Date()</code><span> to record start and end times, but </span><code>Date</code><span> isn&#8217;t the ideal tool for answering &#8220;how long did this operation take?&#8221; </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> explores the </span><code>Clock</code><span> system introduced in Swift 5.7 and explains two more reliable ways to measure time: </span><code>ContinuousClock</code><span> and </span><code>SuspendingClock</code><span>.</span></p><p><code>ContinuousClock</code><span> increases monotonically and continues counting while the device is asleep, making it suitable for measuring real-world elapsed time. </span><code>SuspendingClock</code><span>, by contrast, pauses while the device is asleep, making it more appropriate for measuring actual execution time. Kyle offers a simple rule of thumb: if </span><code>Date()</code><span> in your code is being used to &#8220;measure time&#8221; rather than &#8220;record a point in time,&#8221; you should probably consider replacing it with </span><code>ContinuousClock</code><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-04"><span>From XCUITest to Promo Video</span></a></strong></h3><p><span>Every change to an app&#8217;s interface can mean recreating App Store screenshots, promotional videos, and assets for different languages. </span><a href="https://x.com/No_Wham"><span>Noam Efergan</span></a><span> proposes an interesting solution: treat marketing assets as reproducible build artifacts. Using launch arguments and fixed test data, he makes the real app enter deterministic UI states on demand, then uses XCUITest to automatically capture screenshots across different locales before passing the results to Remotion to generate promotional videos. Rather than maintaining a separate mock UI for marketing, the entire workflow keeps the actual running SwiftUI interface as its source material. It also demonstrates another value of testability beyond testing: when an app can reliably and precisely reproduce a given state, the same capability can support debugging, demos, localization, and automated marketing content production.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-05"><span>Software Engineering fundamentals matter more than ever</span></a></strong></h3><p><span>As coding agents become capable of rapidly generating code, completing tests, and even independently implementing fairly complex features, &#8220;can it be built?&#8221; is gradually becoming one of the easier questions in software development. </span><a href="https://x.com/heckj"><span>Joseph Heck</span></a><span> argues that the genuinely difficult parts have not disappeared: designing clear boundaries and abstractions, making software debuggable, maintainable, and composable, and making sensible tradeoffs among competing constraints. AI can significantly reduce implementation costs, but it cannot replace the software engineering skills built on experience, judgment, and a long-term perspective. In a sense, as &#8220;writing code that works&#8221; becomes easier, software engineering fundamentals matter more than ever.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-06"><span>Why Soft Skills Matter More Than Technical Skills in the Age of AI</span></a></strong></h3><p><span>If the previous article discusses &#8220;how to build software well&#8221; in the age of AI, </span><a href="https://twitter.com/azamsharp"><span>Mohammad Azam</span></a><span> takes the question one step further: first, we need to decide &#8220;what should be built.&#8221; As AI continues to reduce the cost of implementation, understanding the business, clarifying requirements, asking the right questions, communicating and collaborating, and evaluating tradeoffs become even more important. AI can produce ten implementation approaches in seconds, but it doesn&#8217;t know why a particular business rule exists within a company, nor can it take responsibility for the final product on behalf of the developer. Technical skills have not lost their value&#8212;they remain the foundation for judging whether AI-generated results are sound. What may become scarcer in the future is not the ability to &#8220;write more code,&#8221; but the ability to understand the problem, make sound judgments, and ultimately solve the right problem.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-07"><span>GlyphKit: Precise Glyph Layout in SwiftUI with Vector Outlines</span></a></strong></h3><p><span>Displaying a character in SwiftUI is easy, but making a glyph precisely occupy a specified region is not. </span><code>Text</code><span> is designed primarily for text layout, where baselines, font metrics, and Dynamic Type can all influence the final result.</span></p><p><span>GlyphKit takes a different approach by treating glyphs as graphics: it extracts the vector outline (</span><code>CGPath</code><span>) of an individual character through Core Text and renders it with SwiftUI Canvas, providing more direct control over size and positioning. GlyphKit is not a replacement for </span><code>Text</code><span>. It is better suited to individual decorative glyphs, while complex graphemes, ligatures, and content that requires text accessibility should still be handled by a full text layout system.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-149?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#36234;&#26469;&#36234;&#24930;&#30340; App Review&#65292;&#25318;&#20303;&#20102;&#35841;&#65311;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-149/">&#32593;&#39029;&#29256;</a></strong></p><p><span>App Store &#23457;&#26680;&#21464;&#24930;&#65292;&#24050;&#32463;&#26159;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#33021;&#22815;&#26126;&#26174;&#24863;&#21463;&#21040;&#30340;&#21464;&#21270;&#12290;&#22312; Vibe Coding &#26102;&#20195;&#65292;App &#30340;&#24320;&#21457;&#21644;&#36845;&#20195;&#25104;&#26412;&#22823;&#24133;&#38477;&#20302;&#65292;&#23457;&#26680;&#21387;&#21147;&#38543;&#20043;&#22686;&#21152;&#24182;&#19981;&#38590;&#29702;&#35299;&#12290;&#20294;&#38382;&#39064;&#22312;&#20110;&#65292;&#26356;&#24930;&#30340;&#23457;&#26680;&#20284;&#20046;&#21482;&#26159;&#34987;&#19981;&#26029;&#22686;&#38271;&#30340;&#25552;&#20132;&#25968;&#37327;&#25302;&#22446;&#65292;&#21364;&#27809;&#26377;&#30456;&#24212;&#25552;&#39640;&#35784;&#39575; App &#36827;&#20837;&#21830;&#24215;&#30340;&#38376;&#27099;&#12290;</span></p><p><span>&#26368;&#36817;&#65292;Jeff Johnson &#22312; Mac App Store &#20013;&#21457;&#29616;&#20102;&#19968;&#27454;&#39047;&#20026;&#21487;&#30097;&#30340; Safari &#25193;&#23637;&#65306;&#25130;&#22270;&#30097;&#20284; AI &#29983;&#25104;&#65292;&#23637;&#31034;&#30528;&#24182;&#19981;&#23384;&#22312;&#30340;&#8220;4.9 &#20998;&#8221;&#35780;&#20998;&#65292;&#37096;&#20998;&#20116;&#26143;&#35780;&#35770;&#29978;&#33267;&#26089;&#20110; App &#30340;&#19978;&#26550;&#26102;&#38388;&#12290;&#32487;&#32493;&#35843;&#26597;&#21518;&#65292;&#20182;&#21457;&#29616;&#35813;&#25193;&#23637;&#30340;&#24320;&#21457;&#32773;&#22312; App Store &#20013;&#25317;&#26377; 41 &#27454; App&#65292;&#36807;&#21435;&#19968;&#24180;&#33267;&#23569;&#20135;&#29983;&#20102; 368 &#27425;&#33719;&#25209;&#30340;&#23457;&#26680;&#25552;&#20132;&#65292;&#24179;&#22343;&#20960;&#20046;&#27599;&#22825;&#19968;&#27425;&#12290;&#32780;&#22312;&#21516;&#19968;&#26102;&#38388;&#65292;&#33879;&#21517;&#24320;&#21457;&#32773; Marco Arment &#30340;&#26032; App &#21364;&#24050;&#32463;&#22312;&#23457;&#26680;&#38431;&#21015;&#20013;&#31561;&#24453;&#20102; 12 &#22825;&#12290;</span></p><p><span>&#36825;&#24418;&#25104;&#20102;&#19968;&#31181;&#39047;&#20026;&#23604;&#23596;&#30340;&#23616;&#38754;&#65306;&#19968;&#26041;&#38754;&#65292;&#21487;&#30097;&#29978;&#33267;&#28041;&#23244;&#35784;&#39575;&#30340; App &#33021;&#22815;&#36890;&#36807;&#23457;&#26680;&#24182;&#22312;&#25490;&#34892;&#27036;&#19978;&#39640;&#27468;&#29467;&#36827;&#65307;&#21478;&#19968;&#26041;&#38754;&#65292;AI &#21448;&#35753;&#24555;&#36895;&#24320;&#21457;&#12289;&#39057;&#32321;&#36845;&#20195;&#21464;&#24471;&#21069;&#25152;&#26410;&#26377;&#22320;&#23481;&#26131;&#65292;&#22823;&#37327;&#27491;&#24120;&#25552;&#20132;&#19982;&#39640;&#39118;&#38505;&#25552;&#20132;&#20849;&#21516;&#28044;&#20837;&#21516;&#19968;&#22871;&#23457;&#26680;&#26426;&#21046;&#65292;&#25345;&#32493;&#28040;&#32791;&#26377;&#38480;&#30340;&#23457;&#26680;&#36164;&#28304;&#12290;</span></p><p><span>&#19968;&#20010;</span><a href="https://mjtsai.com/blog/2026/08/14/tabcontrol-scam-and-the-app-review-queue/"><span>&#32039;&#36843;&#30340;&#38382;&#39064;</span></a><span>&#25670;&#22312;&#30524;&#21069;&#65306;App Review &#26159;&#21542;&#36824;&#24212;&#35813;&#23396;&#31435;&#22320;&#23545;&#24453;&#27599;&#19968;&#27425;&#25552;&#20132;&#65311;</span></p><p><span>Johnson &#24314;&#35758;&#24341;&#20837;&#31867;&#20284;&#20449;&#29992;&#20307;&#31995;&#30340;&#26426;&#21046;&#65292;&#35753;&#38271;&#26399;&#36981;&#23432;&#35268;&#21017;&#12289;&#20445;&#25345;&#33391;&#22909;&#23457;&#26680;&#35760;&#24405;&#30340;&#24320;&#21457;&#32773;&#33719;&#24471;&#26356;&#24555;&#30340;&#23457;&#26680;&#65292;&#23558;&#26356;&#22810;&#36164;&#28304;&#25237;&#20837;&#39640;&#39057;&#12289;&#25209;&#37327;&#21644;&#23384;&#22312;&#24322;&#24120;&#34892;&#20026;&#30340;&#36134;&#21495;&#12290;&#21453;&#23545;&#32773;&#21017;&#25285;&#24515;&#65292;&#36825;&#26368;&#32456;&#21487;&#33021;&#28436;&#21464;&#25104;&#23545;&#30693;&#21517;&#24320;&#21457;&#32773;&#25110;&#20184;&#36153;&#24320;&#21457;&#32773;&#30340;&#20248;&#24453;&#65292;&#36827;&#19968;&#27493;&#25260;&#39640;&#26032;&#20154;&#36827;&#20837; App Store &#30340;&#38376;&#27099;&#12290;</span></p><p><span>&#22312; AI &#22823;&#24133;&#38477;&#20302; App &#29983;&#20135;&#25104;&#26412;&#20043;&#21518;&#65292;&#20165;&#20165;&#25226;&#27599;&#19968;&#27425; submission &#24403;&#20316;&#24444;&#27492;&#23396;&#31435;&#30340;&#23545;&#35937;&#36827;&#34892;&#23457;&#26680;&#65292;&#36825;&#31181;&#27169;&#24335;&#24050;&#32463;&#36234;&#26469;&#36234;&#38590;&#20197;&#20026;&#32487;&#12290;&#23558;&#24320;&#21457;&#32773;&#21382;&#21490;&#12289;&#25552;&#20132;&#39057;&#29575;&#12289;App &#20043;&#38388;&#30340;&#30456;&#20284;&#24230;&#12289;metadata &#24322;&#24120;&#31561;&#32435;&#20837;&#39118;&#38505;&#35780;&#20272;&#65292;&#25105;&#35748;&#20026;&#24182;&#26080;&#19981;&#22949;&#12290;&#20449;&#29992;&#33391;&#22909;&#19981;&#24847;&#21619;&#30528;&#20813;&#23457;&#65292;&#32780;&#26159;&#20943;&#23569;&#37325;&#22797;&#12289;&#20302;&#20215;&#20540;&#30340;&#26816;&#26597;&#65307;&#24322;&#24120;&#36134;&#21495;&#20063;&#19981;&#26159;&#31105;&#27490;&#25552;&#20132;&#65292;&#32780;&#26159;&#25509;&#21463;&#26356;&#28145;&#20837;&#30340;&#23457;&#26597;&#12290;</span></p><p><span>&#25110;&#35768; App Review &#30495;&#27491;&#38656;&#35201;&#21319;&#32423;&#30340;&#65292;&#19981;&#21482;&#26159;&#23457;&#26680;&#25928;&#29575;&#65292;&#32780;&#26159;&#20174;&#21333;&#28857;&#8220;&#23457;&#26680;&#8221;&#36808;&#21521;&#8220;&#34892;&#20026;&#21028;&#26029;&#8221;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-147/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/contentbuilder-explained/?utm_source=fatbobman%20weekly%20issue%20149&amp;utm_medium=web"><span>ContentBuilder &#35299;&#26512;&#65306;SwiftUI &#31867;&#22411;&#26816;&#26597;&#24615;&#33021;&#25552;&#21319;&#30340;&#31192;&#23494;</span></a></strong></h3><p><span>&#22312; WWDC 2026 &#30340; SwiftUI &#26032;&#21151;&#33021; Session &#20013;&#65292;&#33529;&#26524;&#24037;&#31243;&#24072;&#20171;&#32461;&#20102; SwiftUI &#30340;&#19968;&#20010;&#26032;&#29305;&#24615;&#8212;&#8212;</span><code>ContentBuilder</code><span>&#12290;&#20174;&#20351;&#29992;&#26041;&#24335;&#30475;&#65292;&#23427;&#20284;&#20046;&#21482;&#26159;&#19968;&#20010;&#35206;&#30422;&#33539;&#22260;&#26356;&#24191;&#30340; </span><code>ViewBuilder</code><span>&#65306;&#36807;&#21435;&#20998;&#21035;&#25509;&#21463; </span><code>ViewBuilder</code><span>&#12289;</span><code>ToolbarContentBuilder</code><span>&#12289;</span><code>CommandsBuilder</code><span> &#30340; API&#65292;&#22914;&#20170;&#21487;&#20197;&#20849;&#20139;&#21516;&#19968;&#20010; builder&#12290;&#33529;&#26524;&#21516;&#26102;&#23459;&#31216;&#65292;&#36825;&#39033;&#35843;&#25972;&#33021;&#22815;&#26174;&#33879;&#25913;&#21892;&#31867;&#22411;&#26816;&#26597;&#24615;&#33021;&#12290;&#26412;&#25991;&#23558;&#35299;&#26512; </span><code>ContentBuilder</code><span> &#30340;&#26412;&#36136;&#65292;&#25506;&#32034;&#24615;&#33021;&#25552;&#21319;&#32972;&#21518;&#30340;&#22885;&#22937;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-01"><span>&#26080;&#30028;&#38754; Xcode&#65306;&#21033;&#29992; MCP &#24314;&#31435; AI &#36741;&#21161;&#24320;&#21457;&#30340;&#20840;&#33258;&#21160;&#27969;&#31243; (Headless Xcode: From Prompt to Simulator with MCP)</span></a></strong></h3><p><span>Xcode 27 beta 5 &#26032;&#22686;&#20102; </span><code>xcrun mcp-server</code><span>&#65292;&#35753; Xcode &#30340; MCP &#33021;&#21147;&#21487;&#20197;&#22312;&#19981;&#21551;&#21160; Xcode UI &#30340;&#24773;&#20917;&#19979;&#65292;&#20197;&#21518;&#21488;&#26381;&#21153;&#30340;&#24418;&#24335;&#25552;&#20379;&#32473;&#22806;&#37096; Coding Agent&#12290;&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#20197; Claude Code &#20026;&#20363;&#65292;&#23436;&#25972;&#23637;&#31034;&#20102;&#19968;&#26465; Headless Xcode &#24037;&#20316;&#27969;&#65306;&#20174;&#21019;&#24314; Xcode &#24037;&#31243;&#12289;&#29983;&#25104; SwiftUI &#20195;&#30721;&#12289;&#26500;&#24314;&#39033;&#30446;&#21644;&#28210;&#26579; Preview&#65292;&#21040;&#21551;&#21160; Simulator&#12289;&#35835;&#21462; accessibility hierarchy&#12289;&#25191;&#34892;&#20132;&#20114;&#65292;&#24182;&#26368;&#32456;&#32467;&#21512;&#25130;&#22270;&#19982; OSLog &#39564;&#35777;&#24212;&#29992;&#29366;&#24577;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;&#20174; Prompt &#21040;&#20195;&#30721;&#65292;&#20877;&#21040;&#36816;&#34892;&#21644;&#39564;&#35777;&#65292;&#19968;&#20010;&#19981;&#20381;&#36182; Xcode UI &#30340;&#23436;&#25972;&#24320;&#21457;&#38381;&#29615;&#24050;&#32463;&#21021;&#20855;&#38607;&#24418;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-02"><span>iOS 26: Data Detector</span></a></strong></h3><p><span>iOS 26 &#24341;&#20837;&#20102;&#20840;&#26032;&#30340; </span><code>DataDetector</code><span>&#65292;&#20026;&#24050;&#32463;&#26381;&#24441;&#22810;&#24180;&#30340; </span><code>NSDataDetector</code><span> &#25552;&#20379;&#20102;&#19968;&#22871;&#26356;&#31526;&#21512;&#29616;&#20195; Swift &#39118;&#26684;&#30340;&#26367;&#20195;&#26041;&#26696;&#12290;&#8288;</span><a href="https://x.com/AntonGubarenko"><span>Anton Gubarenko</span></a><span> &#36890;&#36807;&#22823;&#37327;&#31034;&#20363;&#20171;&#32461;&#20102;&#26032; API &#30340;&#20351;&#29992;&#26041;&#24335;&#65306;&#24320;&#21457;&#32773;&#21487;&#20197;&#30452;&#25509;&#36890;&#36807; </span><code>StringProtocol.dataDetectorMatches</code><span> &#33719;&#24471; </span><code>AsyncSequence</code><span>&#65292;&#24182;&#20351;&#29992; Swift &#21407;&#29983; Range &#21644;&#24378;&#31867;&#22411;&#30340;&#35821;&#20041;&#32467;&#26524;&#35782;&#21035;&#25991;&#26412;&#20013;&#30340;&#37038;&#31665;&#12289;&#30005;&#35805;&#21495;&#30721;&#12289;&#26085;&#26399;&#12289;&#22320;&#22336;&#12289;&#37329;&#39069;&#12289;&#24230;&#37327;&#20540;&#12289;&#33322;&#29677;&#21495;&#12289;&#29289;&#27969;&#21333;&#21495;&#31561;&#20869;&#23481;&#12290;&#26032; API &#19981;&#20165;&#20351;&#29992;&#36215;&#26469;&#26356;&#21152;&#33258;&#28982;&#65292;&#33021;&#22815;&#35782;&#21035;&#30340;&#35821;&#20041;&#23545;&#35937;&#20063;&#26356;&#21152;&#20016;&#23500;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-03"><span>&#29992; ContinuousClock &#26367;&#20195; Date() &#27979;&#37327;&#25345;&#32493;&#26102;&#38388; (Measuring Elapsed Time in Swift with ContinuousClock)</span></a></strong></h3><p><span>&#24456;&#22810;&#24320;&#21457;&#32773;&#20173;&#20064;&#24815;&#20351;&#29992; </span><code>Date()</code><span> &#35760;&#24405;&#24320;&#22987;&#21644;&#32467;&#26463;&#26102;&#38388;&#65292;&#20294; </span><code>Date</code><span> &#24182;&#19981;&#26159;&#22238;&#31572;&#8220;&#36825;&#27573;&#25805;&#20316;&#25345;&#32493;&#20102;&#22810;&#20037;&#8221;&#30340;&#29702;&#24819;&#24037;&#20855;&#12290;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#22260;&#32469; Swift 5.7 &#24341;&#20837;&#30340; </span><code>Clock</code><span> &#20307;&#31995;&#65292;&#20171;&#32461;&#20102;&#20004;&#31181;&#26356;&#21152;&#21487;&#38752;&#30340;&#26102;&#38388;&#27979;&#37327;&#26041;&#24335;&#65306;</span><code>ContinuousClock</code><span> &#21644; </span><code>SuspendingClock</code><span>&#12290;</span></p><p><code>ContinuousClock</code><span> &#21333;&#35843;&#36882;&#22686;&#65292;&#24182;&#21253;&#21547;&#35774;&#22791;&#20241;&#30496;&#26399;&#38388;&#32463;&#36807;&#30340;&#26102;&#38388;&#65292;&#36866;&#21512;&#34913;&#37327;&#30495;&#23454;&#19990;&#30028;&#20013;&#30340; elapsed time&#65307;</span><code>SuspendingClock</code><span> &#21017;&#20250;&#22312;&#35774;&#22791;&#20241;&#30496;&#26102;&#26242;&#20572;&#65292;&#26356;&#36866;&#21512;&#34913;&#37327;&#23454;&#38469;&#36816;&#34892;&#26102;&#38388;&#12290;Kyle &#32473;&#20986;&#20102;&#19968;&#20010;&#31616;&#21333;&#30340;&#24314;&#35758;&#65306;&#22914;&#26524;&#20195;&#30721;&#20013;&#30340; </span><code>Date()</code><span> &#26159;&#29992;&#26469;&#8220;&#35745;&#26102;&#8221;&#32780;&#19981;&#26159;&#8220;&#35760;&#24405;&#26102;&#38388;&#28857;&#8221;&#65292;&#36890;&#24120;&#23601;&#24212;&#35813;&#32771;&#34385;&#25442;&#25104; </span><code>ContinuousClock</code><span>&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-04"><span>&#29992; XCUITest &#33258;&#21160;&#29983;&#25104; App &#23459;&#20256;&#35270;&#39057; (From XCUITest to Promo Video)</span></a></strong></h3><p><span>&#27599;&#27425;&#20462;&#25913; App &#30028;&#38754;&#65292;&#37117;&#21487;&#33021;&#24847;&#21619;&#30528; App Store &#25130;&#22270;&#12289;&#23459;&#20256;&#35270;&#39057;&#20197;&#21450;&#19981;&#21516;&#35821;&#35328;&#29256;&#26412;&#30340;&#32032;&#26448;&#38656;&#35201;&#37325;&#26032;&#21046;&#20316;&#12290;&#8288;</span><a href="https://x.com/No_Wham"><span>Noam Efergan</span></a><span> &#25552;&#20986;&#20102;&#19968;&#20010;&#24456;&#26377;&#24847;&#24605;&#30340;&#35299;&#20915;&#24605;&#36335;&#65306;&#23558;&#33829;&#38144;&#32032;&#26448;&#20063;&#35270;&#20026;&#21487;&#20197;&#37325;&#22797;&#29983;&#25104;&#30340; build artifacts&#12290;&#20182;&#36890;&#36807; launch arguments &#21644;&#22266;&#23450;&#30340;&#27979;&#35797;&#25968;&#25454;&#65292;&#35753;&#30495;&#23454; App &#21487;&#20197;&#38543;&#26102;&#36827;&#20837;&#30830;&#23450;&#30340; UI &#29366;&#24577;&#65292;&#20877;&#20351;&#29992; XCUITest &#33258;&#21160;&#23436;&#25104;&#19981;&#21516; locale &#19979;&#30340;&#25130;&#22270;&#65292;&#24182;&#23558;&#32467;&#26524;&#20132;&#32473; Remotion &#29983;&#25104;&#23459;&#20256;&#35270;&#39057;&#12290;&#25972;&#20010;&#27969;&#31243;&#24182;&#27809;&#26377;&#20026;&#20102;&#33829;&#38144;&#37325;&#26032;&#21046;&#20316;&#19968;&#22871; mock UI&#65292;&#32780;&#26159;&#22987;&#32456;&#20197;&#23454;&#38469;&#36816;&#34892;&#30340; SwiftUI &#30028;&#38754;&#20316;&#20026;&#32032;&#26448;&#26469;&#28304;&#12290;&#36825;&#20063;&#23637;&#31034;&#20102; testability &#22312;&#27979;&#35797;&#20043;&#22806;&#30340;&#21478;&#19968;&#23618;&#20215;&#20540;&#65306;&#24403;&#24212;&#29992;&#33021;&#22815;&#31283;&#23450;&#12289;&#20934;&#30830;&#22320;&#37325;&#29616;&#26576;&#20010;&#29366;&#24577;&#26102;&#65292;&#21516;&#19968;&#22871;&#33021;&#21147;&#20063;&#21487;&#20197;&#26381;&#21153;&#20110;&#35843;&#35797;&#12289;&#28436;&#31034;&#12289;&#26412;&#22320;&#21270;&#20197;&#21450;&#33829;&#38144;&#20869;&#23481;&#30340;&#33258;&#21160;&#21270;&#29983;&#20135;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-05"><span>AI &#26102;&#20195;&#65292;&#36719;&#20214;&#24037;&#31243;&#22522;&#26412;&#21151;&#27604;&#20197;&#24448;&#20219;&#20309;&#26102;&#20505;&#37117;&#26356;&#37325;&#35201; (Software Engineering fundamentals matter more than ever)</span></a></strong></h3><p><span>&#24403; Coding Agent &#24050;&#32463;&#33021;&#22815;&#24555;&#36895;&#29983;&#25104;&#20195;&#30721;&#12289;&#23436;&#25104;&#27979;&#35797;&#65292;&#29978;&#33267;&#29420;&#31435;&#23454;&#29616;&#30456;&#24403;&#22797;&#26434;&#30340;&#21151;&#33021;&#21518;&#65292;&#8220;&#33021;&#19981;&#33021;&#20570;&#20986;&#26469;&#8221;&#27491;&#22312;&#36880;&#28176;&#25104;&#20026;&#36719;&#20214;&#24320;&#21457;&#20013;&#26356;&#23481;&#26131;&#35299;&#20915;&#30340;&#38382;&#39064;&#12290;</span><a href="https://x.com/heckj"><span>Joseph Heck</span></a><span> &#35748;&#20026;&#65292;&#30495;&#27491;&#22256;&#38590;&#30340;&#37096;&#20998;&#20381;&#28982;&#27809;&#26377;&#28040;&#22833;&#65306;&#22914;&#20309;&#35774;&#35745;&#28165;&#26224;&#30340;&#36793;&#30028;&#19982;&#25277;&#35937;&#65292;&#22914;&#20309;&#35753;&#36719;&#20214;&#20855;&#22791;&#21487;&#35843;&#35797;&#24615;&#12289;&#21487;&#32500;&#25252;&#24615;&#21644;&#21487;&#32452;&#21512;&#24615;&#65292;&#20197;&#21450;&#22914;&#20309;&#22312;&#21508;&#31181;&#32422;&#26463;&#20043;&#38388;&#20570;&#20986;&#21512;&#29702;&#30340;&#21462;&#33293;&#12290;AI &#21487;&#20197;&#26174;&#33879;&#38477;&#20302;&#23454;&#29616;&#25104;&#26412;&#65292;&#21364;&#26080;&#27861;&#26367;&#20195;&#36825;&#20123;&#24314;&#31435;&#22312;&#32463;&#39564;&#12289;&#21028;&#26029;&#21644;&#38271;&#26399;&#35270;&#35282;&#20043;&#19978;&#30340;&#36719;&#20214;&#24037;&#31243;&#33021;&#21147;&#12290;&#26576;&#31181;&#24847;&#20041;&#19978;&#65292;&#24403;&#8220;&#20889;&#20986;&#33021;&#24037;&#20316;&#30340;&#20195;&#30721;&#8221;&#36234;&#26469;&#36234;&#23481;&#26131;&#65292;Software Engineering fundamentals &#21453;&#32780;&#21464;&#24471;&#26356;&#21152;&#37325;&#35201;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0149-06"><span>&#20026;&#20160;&#20040;&#35828;&#22312; AI &#26102;&#20195;&#65292;&#8220;&#23450;&#20041;&#38382;&#39064;&#8221;&#27604;&#8220;&#20889;&#20986;&#20195;&#30721;&#8221;&#26356;&#37325;&#35201;&#65311;(Why Soft Skills Matter More Than Technical Skills in the Age of AI)</span></a></strong></h3><p><span>&#22914;&#26524;&#19978;&#19968;&#31687;&#35752;&#35770;&#30340;&#26159; AI &#26102;&#20195;&#8220;&#24590;&#26679;&#25226;&#36719;&#20214;&#20570;&#22909;&#8221;&#65292;</span><a href="https://twitter.com/azamsharp"><span>Mohammad Azam</span></a><span> &#21017;&#25226;&#38382;&#39064;&#21521;&#21069;&#25512;&#36827;&#20102;&#19968;&#27493;&#65306;&#25105;&#20204;&#39318;&#20808;&#38656;&#35201;&#21028;&#26029;&#8220;&#24212;&#35813;&#20570;&#20160;&#20040;&#8221;&#12290;&#24403; AI &#19981;&#26029;&#38477;&#20302;&#20195;&#30721;&#23454;&#29616;&#30340;&#25104;&#26412;&#65292;&#29702;&#35299;&#19994;&#21153;&#12289;&#28548;&#28165;&#38656;&#27714;&#12289;&#25552;&#20986;&#27491;&#30830;&#30340;&#38382;&#39064;&#12289;&#27807;&#36890;&#21327;&#20316;&#20197;&#21450;&#35780;&#20272;&#21462;&#33293;&#30340;&#37325;&#35201;&#24615;&#21453;&#32780;&#26356;&#21152;&#31361;&#20986;&#12290;AI &#21487;&#20197;&#22312;&#20960;&#31186;&#38047;&#20869;&#32473;&#20986;&#21313;&#31181;&#23454;&#29616;&#26041;&#26696;&#65292;&#21364;&#19981;&#30693;&#36947;&#20844;&#21496;&#30340;&#26576;&#26465;&#19994;&#21153;&#35268;&#21017;&#20026;&#20309;&#23384;&#22312;&#65292;&#20063;&#26080;&#27861;&#26367;&#24320;&#21457;&#32773;&#25215;&#25285;&#26368;&#32456;&#20132;&#20184;&#30340;&#36131;&#20219;&#12290;&#25216;&#26415;&#33021;&#21147;&#24182;&#27809;&#26377;&#22240;&#27492;&#22833;&#21435;&#20215;&#20540;&#8212;&#8212;&#23427;&#20173;&#28982;&#26159;&#21028;&#26029; AI &#29983;&#25104;&#32467;&#26524;&#26159;&#21542;&#21512;&#29702;&#30340;&#22522;&#30784;&#65307;&#21482;&#26159;&#26410;&#26469;&#26356;&#21152;&#31232;&#32570;&#30340;&#65292;&#25110;&#35768;&#19981;&#20877;&#26159;&#8220;&#33021;&#22815;&#20889;&#20986;&#22810;&#23569;&#20195;&#30721;&#8221;&#65292;&#32780;&#26159;&#29702;&#35299;&#38382;&#39064;&#12289;&#20570;&#20986;&#21028;&#26029;&#65292;&#24182;&#26368;&#32456;&#35299;&#20915;&#27491;&#30830;&#38382;&#39064;&#30340;&#33021;&#21147;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-07"><span>GlyphKit&#65306;&#22312; SwiftUI &#20013;&#29992;&#30690;&#37327;&#36718;&#24275;&#31934;&#20934;&#25511;&#21046;&#23383;&#24418;&#25490;&#29256;</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#26174;&#31034;&#19968;&#20010;&#23383;&#31526;&#24456;&#31616;&#21333;&#65292;&#20294;&#35201;&#35753;&#23383;&#24418;&#31934;&#30830;&#22320;&#21344;&#25454;&#25351;&#23450;&#21306;&#22495;&#65292;&#21364;&#24182;&#19981;&#23481;&#26131;&#12290;Text &#30340;&#39318;&#35201;&#30446;&#26631;&#26159;&#25991;&#26412;&#25490;&#29256;&#65292;&#22522;&#32447;&#12289;&#23383;&#20307;&#24230;&#37327;&#20197;&#21450; Dynamic Type &#37117;&#21487;&#33021;&#21442;&#19982;&#26368;&#32456;&#24067;&#23616;&#12290;</span></p><p><span>GlyphKit &#36873;&#25321;&#25226;&#23383;&#24418;&#24403;&#20316;&#22270;&#24418;&#22788;&#29702;&#65306;&#36890;&#36807; Core Text &#25552;&#21462;&#21333;&#20010;&#23383;&#31526;&#30340;&#30690;&#37327;&#36718;&#24275;&#65288;CGPath&#65289;&#65292;&#20877;&#20351;&#29992; SwiftUI Canvas &#32472;&#21046;&#65292;&#20174;&#32780;&#33719;&#24471;&#26356;&#30452;&#25509;&#30340;&#23610;&#23544;&#19982;&#20301;&#32622;&#25511;&#21046;&#12290;GlyphKit &#24182;&#38750; Text &#30340;&#26367;&#20195;&#21697;&#12290;&#23427;&#26356;&#36866;&#21512;&#21333;&#20010;&#12289;&#35013;&#39280;&#24615;&#23383;&#24418;&#65307;&#22797;&#26434;&#23383;&#32032;&#12289;&#36830;&#23383;&#21450;&#38656;&#35201;&#25991;&#23383;&#36741;&#21161;&#21151;&#33021;&#30340;&#20869;&#23481;&#65292;&#20173;&#24212;&#20132;&#32473;&#23436;&#25972;&#30340;&#25991;&#26412;&#25490;&#29256;&#31995;&#32479;&#12290;</span></p><h2><strong><span>&#27714;&#36132;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0149-08"><span>[&#28145;&#22323; / &#19978;&#28023; / &#21271;&#20140;] &#25238;&#38899;&#30740;&#21457; - &#23458;&#25143;&#31471;&#28210;&#26579;&#24341;&#25806;&#30740;&#21457;&#24037;&#31243;&#24072;&#65288;iOS / &#36328;&#31471;&#28210;&#26579;&#65289;</span></a></strong></h3><h4><strong><span>&#22242;&#38431;&#20171;&#32461;</span></strong></h4><p><span>&#22242;&#38431;&#20171;&#32461;&#65306;&#25238;&#38899;&#30740;&#21457;&#37096;&#38376;&#36127;&#36131;&#22810;&#27454;&#22823;&#22411;&#20135;&#21697;&#30340;&#30740;&#21457;&#65292;&#21253;&#25324;&#20294;&#19981;&#38480;&#20110;&#25238;&#38899;&#12289;&#35199;&#29916;&#35270;&#39057;&#12289;&#27773;&#27700;&#38899;&#20048;&#12290; &#21152;&#20837;&#25105;&#20204;&#65292;&#20320;&#23558;&#26377;&#26426;&#20250;&#21442;&#19982;&#20159;&#32423;&#29992;&#25143;&#22330;&#26223;&#30340;&#24320;&#21457;&#19982;&#26550;&#26500;&#24037;&#20316;&#65292;&#20351;&#29992;&#21069;&#27839;&#30340;&#25216;&#26415;&#21161;&#21147;&#19994;&#21153;&#19968;&#36215;&#19981;&#26029;&#25104;&#38271;&#12290;</span></p><h4><strong><span>&#23703;&#20301;&#25551;&#36848;</span></strong></h4><ol><li><p><span>&#36127;&#36131;&#23458;&#25143;&#31471;&#36328;&#31471;&#28210;&#26579;&#22522;&#30784;&#26694;&#26550;&#30340;&#21151;&#33021;&#36845;&#20195;&#19982;&#24615;&#33021;&#20248;&#21270;&#65292;&#25345;&#32493;&#25552;&#21319;&#22797;&#26434;&#30028;&#38754;&#30340;&#27969;&#30021;&#24230;&#19982;&#31283;&#23450;&#24615;&#65307;</span></p></li><li><p><span>&#21442;&#19982;&#22768;&#26126;&#24335; UI &#26694;&#26550;&#22312; iOS &#19978;&#30340;&#33021;&#21147;&#24314;&#35774;&#65292;&#21253;&#25324;&#26680;&#24515;&#28210;&#26579;&#33021;&#21147;&#12289;&#31995;&#32479;&#29305;&#24615;&#36866;&#37197;&#19982;&#37197;&#22871;&#30740;&#21457;&#35774;&#26045;&#65307;</span></p></li><li><p><span>&#28145;&#20837;&#28210;&#26579;&#38142;&#36335;&#24320;&#23637;&#24615;&#33021;&#20998;&#26512;&#19982;&#35843;&#20248;&#65292;&#23450;&#20301;&#24182;&#35299;&#20915;&#21345;&#39039;&#12289;&#25481;&#24103;&#12289;&#20869;&#23384;&#19982;&#21551;&#21160;&#31561;&#20851;&#38190;&#38382;&#39064;&#65307;</span></p></li><li><p><span>&#21442;&#19982;&#28210;&#26579;&#24615;&#33021;&#30417;&#25511;&#20307;&#31995;&#24314;&#35774;&#65292;&#32467;&#21512;&#30417;&#25511;&#25968;&#25454;&#25512;&#21160;&#38382;&#39064;&#30340;&#33258;&#21160;&#21270;&#20998;&#26512;&#12289;&#24402;&#22240;&#19982;&#27835;&#29702;&#65307;</span></p></li><li><p><span>&#27785;&#28096;&#36890;&#29992;&#20248;&#21270;&#26041;&#26696;&#19982;&#25216;&#26415;&#20307;&#31995;&#65292;&#23545;&#22806;&#36827;&#34892;&#25216;&#26415;&#36755;&#20986;&#65292;&#25552;&#21319;&#20844;&#21496;&#23458;&#25143;&#31471;&#25972;&#20307;&#30740;&#21457;&#25928;&#29575;&#19982;&#25216;&#26415;&#24433;&#21709;&#21147;&#12290;</span></p></li></ol><h4><strong><span>&#23703;&#20301;&#35201;&#27714;</span></strong></h4><ol><li><p><span>&#26412;&#31185;&#21450;&#20197;&#19978;&#23398;&#21382;&#65292;&#35745;&#31639;&#26426;&#21450;&#30456;&#20851;&#19987;&#19994;&#65307;</span></p></li><li><p><span>3&#24180;&#20197;&#19978; iOS/Mac &#23458;&#25143;&#31471;&#24320;&#21457;&#32463;&#39564;&#65292;&#29087;&#24713; Apple SDK&#65292;&#29087;&#32451;&#25484;&#25569; Swift/C++&#65307;</span></p></li><li><p><span>&#29087;&#24713; SwiftUI/Compose &#31561;&#22768;&#26126;&#24335;UI&#26694;&#26550;&#30340;&#28210;&#26579;&#26426;&#21046;&#65292;&#25110;&#26377;&#36328;&#31471;UI&#26694;&#26550;&#30340;&#24320;&#21457;&#12289;&#33853;&#22320;&#32463;&#39564;&#65307;</span></p></li><li><p><span>&#20855;&#22791;&#25166;&#23454;&#30340;&#24615;&#33021;&#20248;&#21270;&#33021;&#21147;&#65292;&#29087;&#32451;&#20351;&#29992; Instruments&#12289;Time Profiler&#12289;Allocations&#12289;System Trace &#31561;&#24037;&#20855;&#36827;&#34892;&#20998;&#26512;&#19982;&#35843;&#20248;&#65307;</span></p></li><li><p><span>&#20855;&#26377;&#33391;&#22909;&#30340;&#20195;&#30721;&#39550;&#39533;&#33021;&#21147;&#19982;&#25216;&#26415;&#35774;&#35745;&#33021;&#21147;&#65292;&#33021;&#29420;&#31435;&#23436;&#25104;&#27169;&#22359;&#35774;&#35745;&#19982;&#22797;&#26434;&#38382;&#39064;&#25915;&#22362;&#65307;</span></p></li><li><p><span>&#33391;&#22909;&#30340;&#27807;&#36890;&#21327;&#20316;&#33021;&#21147;&#19982;&#26381;&#21153;&#24847;&#35782;&#65292;&#36131;&#20219;&#24515;&#24378;&#12289;&#33258;&#39537;&#21147;&#24378;&#12289;&#36861;&#27714;&#21331;&#36234;&#12290;</span></p></li></ol><h4><strong><span>&#32852;&#31995;&#26041;&#24335;</span></strong></h4><p><span>&#20869;&#25512;&#32852;&#31995;&#65306;&#37038;&#31665; </span><a href="mailto:yexulei.swift@bytedance.com"><span>yexulei.swift@bytedance.com</span></a></p><p><span>&#32852;&#31995;&#26102;&#35831;&#22791;&#27880;&#12300;&#23458;&#25143;&#31471;&#28210;&#26579;&#24341;&#25806; + &#22995;&#21517; + &#24037;&#20316;&#24180;&#38480;&#12301;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #148]]></title><description><![CDATA[Apple Intelligence Has Passed Chinese Government Review and Is Coming to China]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 10 Aug 2026 12:01:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!e-3Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e-3Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32428,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/210547203?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e-3Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!e-3Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5f52b0-b843-4429-84a5-b12b30682434_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong><span>Apple Intelligence Has Passed Chinese Government Review and Is Coming to China</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-148/">Read on web &#8594;</a></p><p><span>At WWDC 26, Apple unveiled a new Apple Intelligence architecture. Gemini was introduced on the cloud side, while Apple also confirmed that its third-generation Apple Foundation Models were built in collaboration with Google. For a while, this made me think that bringing Apple Intelligence to China might actually become even more difficult.</span></p><p><span>But things moved faster than expected. In July, Apple Intelligence appeared on the latest list of generative AI services registered with China&#8217;s Cyberspace Administration of China (CAC). Then, just two days ago, Apple confirmed that Alibaba&#8217;s Qwen would be involved in the Chinese version of Apple Intelligence, and the integration briefly appeared in Apple&#8217;s official documentation. Although the document was temporarily taken down the day after going live on August 8, its detailed setup instructions and privacy descriptions had already revealed a fairly complete picture of how the integration would work. This suggests that the official launch of Apple Intelligence in China is now entering its final countdown.</span></p><p><span>In addition to Alibaba&#8217;s Qwen, the registration information also revealed that Baidu will participate deeply as a partner in the AI search and visual search capabilities of the Chinese version of Apple Intelligence. In other words, Apple can not only adjust the underlying models and service providers by region, but also rely on more than one partner within the same market.</span></p><p><span>As countries and regions continue to strengthen their requirements around privacy, data, and AI services, regional differences are becoming almost unavoidable. China is becoming Apple&#8217;s first major example of a new approach: keeping the overall Apple Intelligence product experience and developer interfaces relatively consistent, while selecting different underlying models based on local regulations and ecosystems. This model is likely to appear in more markets over time and could become an important part of Apple Intelligence&#8217;s global expansion.</span></p><p><span>For developers using Apple Intelligence APIs, this is also good news. If Apple can continue to maintain consistency at the API layer, developers should theoretically not need to maintain completely different implementations for different markets. It would also allow apps that rely heavily on Apple Intelligence capabilities to reach a much broader audience.</span></p><p><span>Gemini and Qwen may not be the two most prominent names in the Agent scenarios I use day to day, but both perform quite well in areas such as world knowledge and language understanding. Given that Apple Intelligence is currently more focused on system-level assistance, and that these partners also bring mature model infrastructure and extensive cloud service experience, Apple&#8217;s choices seem quite reasonable.</span></p><p><span>Apple Intelligence has become one of Apple&#8217;s most important entry points into the AI era. Its current capabilities are still somewhat short of my personal expectations, but starting in 2026, it is at least beginning to reach substantially more users around the world. Rather than focusing only on how many tasks it can complete today, I am more interested in seeing how Apple will use WWDC 2027 to bring AI more deeply into its hardware, operating systems, and services ecosystem.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-147/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/controlling-orphans-in-swiftui-text/?utm_source=fatbobman%20weekly%20issue%20148&amp;utm_medium=web"><span>Controlling Orphans in SwiftUI Text: Uncovering the Undocumented avoidsOrphans</span></a></strong></h3><p><span>SwiftUI&#8217;s </span><code>Text</code><span> has a default behavior: when the last line of a paragraph contains only a single orphaned word or character, it automatically moves an entire word group from the previous line down to avoid leaving it alone. While this behavior is often helpful, it can also leave excessive whitespace on the preceding line, especially in narrow layouts or mixed Chinese&#8211;English text, disrupting the visual balance of the paragraph. UIKit allows developers to disable this behavior through </span><code>NSParagraphStyle</code><span>, but SwiftUI exposes no public API for doing so. This article uncovers an undocumented SwiftUI API that has existed for quite some time&#8212;</span><code>avoidsOrphans</code><span>&#8212;allowing developers to regain control over this behavior.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-01"><span>An Even Closer Look at Protocols and Global Actors</span></a></strong></h3><p><span>As Swift&#8217;s concurrency model continues to evolve, some engineering decisions that once felt obvious are beginning to change alongside the language itself. In this article, </span><a href="https://mastodon.social/@mattiem"><span>Matt Massicotte</span></a><span> goes beyond the familiar question of whether </span><code>@MainActor</code><span> belongs on a protocol or individual methods, using it as a starting point to explore API design in the era of Swift Concurrency. Rather than promoting a so-called &#8220;best practice,&#8221; Matt emphasizes a broader principle: isolation is a constraint, and constraints should arise from real requirements&#8212;not from habit.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-02"><span>Weekly Tuist News #1</span></a></strong></h3><p><span>As AI agents become increasingly integrated into the development workflow, engineering tools such as Tuist are becoming more important&#8212;even for independent developers.</span></p><p><span>Longtime Tuist community contributor </span><a href="https://www.linkedin.com/in/gamehelper/"><span>Lee YoungJun</span></a><span> has launched a new series, Weekly Tuist News, dedicated to tracking the Tuist ecosystem. Rather than simply summarizing release notes, the series combines community updates with the author&#8217;s hands-on experience. In its debut issue, he covers SwifterPM becoming the default dependency restoration method, new controls for target cache invalidation, and Tuist&#8217;s </span><code>auth.md</code><span> support for coding agents, along with practical observations from real-world usage.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-03"><span>Preview Multiple SwiftUI View States with #Preview(arguments:)</span></a></strong></h3><p><span>Most SwiftUI components have more than one meaningful state: empty, loading, error, permission-restricted, and so on. During development, we often end up maintaining multiple nearly identical </span><code>#Preview</code><span> declarations or placing every state into a single </span><code>VStack</code><span>. Xcode 27&#8217;s new </span><code>#Preview(arguments:)</code><span> API is designed specifically for this scenario, generating multiple independent previews from a collection of state data while allowing each one to be inspected individually in the Canvas.</span></p><p><span>In the article, </span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> also shares his approach to organizing previews: </span><code>arguments</code><span> should describe business states, not environments. Even as the API evolves, this separation between application state and runtime environment remains a valuable design principle.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-04"><span>Concentric Buttons with OS 27&#8217;s SwiftUI APIs</span></a></strong></h3><p><span>WWDC26 introduced </span><code>GeometryProxy.concentricCornerRadii</code><span>, allowing SwiftUI developers to access a container&#8217;s concentric corner radius information. However, </span><code>ButtonBorderShape</code><span> remains a closed type, making it impossible to create truly custom button border shapes directly. </span><a href="https://twitter.com/_al_we"><span>Alexander Wei&#223;</span></a><span> demonstrates how to leverage this new API together with </span><code>onGeometryChange</code><span>, a custom </span><code>ViewModifier</code><span>, and method overloading to build a concentric button solution that feels almost indistinguishable from a native SwiftUI API.</span></p><blockquote><p><span>For new APIs such as </span><code>GeometryProxy.concentricCornerRadii</code><span>, it usually takes only a few seconds to understand what they do. The real challenge comes when using them in production, where implementation details and framework limitations quickly surface. Rather than serving as an API introduction, this article explores those practical considerations and the scenarios where the API can be effectively applied.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-05"><span>Swift, AI, and the future of software development</span></a></strong></h3><p><span>AI has become an indispensable part of many developers&#8217; workflows, but beyond improving productivity, it is also quietly changing the relationship between developers and their code. In this article, </span><a href="https://x.com/tiborbodecs"><span>Tibor B&#246;decs</span></a><span> candidly reflects on his own experience over the past year: embracing AI for its efficiency while missing the satisfaction of writing code and deeply understanding problems; believing that AI will continue to reshape software development while hoping it remains a tool that augments human thinking rather than replacing it.</span></p><blockquote><p><span>Over the past months, I&#8217;ve found myself struggling with many of the same questions as Tibor B&#246;decs. While AI has taken away some of the joy and created a subtle sense of distance between myself, the code, and the products I build, I&#8217;ve also been working relentlessly to gain greater control over it&#8212;to make it an extension of my own thinking, rather than allowing myself to become an extension of it.</span></p></blockquote><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-06"><span>Gitwyn: A Git Client Designed Around the Xcode Workflow</span></a></strong></h3><p><span>Although Xcode&#8217;s built-in Git support has improved significantly over the past few releases, it still falls short in both usability and functionality for many everyday workflows. Developed by </span><a href="https://www.linkedin.com/in/karthikk9828/"><span>Karthik K</span></a><span>, Gitwyn is a native Git client designed around the Xcode workflow. Press &#8984;&#8679;E in any Xcode project to review changes, organize staged files, generate commit messages, and push code&#8212;all without leaving Xcode or switching to another Git tool.</span></p><p><span>One of Gitwyn&#8217;s standout features is its ability to generate commit messages locally using on-device Apple Intelligence based on staged changes. No network connection is required, and your source code never leaves your Mac. More importantly, it streamlines the entire flow of reviewing diffs, organizing commits, generating descriptions, and pushing changes, keeping Git operations within the Xcode development context.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-07"><span>VersionedDocC: Bringing Version Management to Swift-DocC</span></a></strong></h3><p><span>For years, every WWDC I would immediately open Apple&#8217;s developer documentation and use the &#8220;API Changes&#8221; feature to compare different Xcode and SDK releases, tracking newly introduced, modified, and deprecated APIs. Unfortunately, this incredibly useful capability disappeared after the documentation website redesign in 2025. Although the old comparison URLs still exist, they no longer present complete API changes.</span></p><p><span>Developed by </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span>, VersionedDocC brings this capability back to DocC. It adds a release orchestration layer on top of the existing Swift toolchain, generating stable URLs for different versions, providing a version selector, displaying public API differences between adjacent releases based on symbol graphs, and avoiding repeated builds of historical documentation through immutable caching. The project also includes a SwiftPM plugin, GitHub Action, and GitHub Pages workflow, with support for multi-platform symbol graphs, external modules, and standalone DocC catalogs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-08"><span>Swift Subprocess 1.0</span></a></strong></h3><p><span>After a year of iteration, Swift&#8217;s official </span><code>swift-subprocess</code><span> project released version 1.0 this week. It is a cross-platform subprocess library built on Swift Concurrency, providing a unified way to launch commands, supply input, stream output, and manage process termination and cancellation across macOS, Linux, Windows, Android, and BSD.</span></p><p><span>It is particularly well suited for Swift CLIs, build systems, server applications, developer tools, and macOS automation. Note that version 1.0 requires Swift 6.2 and is not intended for regular iOS applications. It also deliberately leaves higher-level features such as sandboxing, command authorization, and pseudo-terminals (PTYs) to other layers.</span></p><p><code>swift-subprocess</code><span> also fills an important missing piece for building native AI agents in Swift: reliably executing external tools, continuously receiving their output, and properly managing subprocess lifecycles. The model decides </span><em><span>what</span></em><span> to do, while Subprocess provides a more controllable, observable, and Swifty way to execute those decisions.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-148?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>Apple Intelligence &#24050;&#36890;&#36807;&#20013;&#22269;&#25919;&#24220;&#23457;&#26680;&#65292;&#21363;&#23558;&#22312;&#20013;&#22269;&#25552;&#20379;&#26381;&#21153;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-148/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#22312; WWDC 26 &#19978;&#65292;&#33529;&#26524;&#20844;&#24067;&#20102;&#26032;&#30340; Apple Intelligence &#26550;&#26500;&#65292;&#19981;&#20165;&#22312;&#20113;&#31471;&#24341;&#20837; Gemini&#65292;&#31532;&#19977;&#20195; Apple Foundation Models &#20063;&#30830;&#35748;&#30001;&#33529;&#26524;&#19982; Google &#21512;&#20316;&#26500;&#24314;&#12290;&#36825;&#19968;&#24230;&#35753;&#25105;&#20197;&#20026;&#65292;Apple Intelligence &#36827;&#20837;&#20013;&#22269;&#24066;&#22330;&#30340;&#38590;&#24230;&#21453;&#32780;&#36827;&#19968;&#27493;&#22686;&#21152;&#20102;&#12290;</span></p><p><span>&#20294;&#20107;&#24773;&#30340;&#21457;&#23637;&#27604;&#39044;&#24819;&#20013;&#26356;&#24555;&#12290;7 &#26376;&#65292;Apple Intelligence &#24050;&#32463;&#20986;&#29616;&#22312;&#20013;&#22269;&#22269;&#23478;&#20114;&#32852;&#32593;&#20449;&#24687;&#21150;&#20844;&#23460;&#65288;CAC&#65289;&#20844;&#24067;&#30340;&#26368;&#26032;&#19968;&#25209;&#29983;&#25104;&#24335; AI &#26381;&#21153;&#22791;&#26696;&#21517;&#21333;&#20013;&#12290;&#32780;&#23601;&#22312;&#20004;&#22825;&#21069;&#65292;&#33529;&#26524;&#21448;&#30830;&#35748;&#38463;&#37324;&#24052;&#24052; Qwen &#23558;&#21442;&#19982;&#20013;&#22269;&#29256; Apple Intelligence&#65292;&#24182;&#19968;&#24230;&#20986;&#29616;&#22312;&#33529;&#26524;&#30340;&#23448;&#26041;&#25991;&#26723;&#20013;&#12290;&#34429;&#28982;&#35813;&#25991;&#26723;&#22312; 8 &#26376; 8 &#26085;&#30701;&#26242;&#19978;&#32447;&#21518;&#20110;&#27425;&#26085;&#34987;&#26242;&#26102;&#25764;&#22238;&#65292;&#20294;&#20854;&#20013;&#35814;&#32454;&#30340;&#25805;&#20316;&#25351;&#24341;&#21644;&#38544;&#31169;&#35828;&#26126;&#65292;&#24050;&#32463;&#21521;&#22806;&#30028;&#25581;&#31034;&#20102;&#30456;&#24403;&#23436;&#25972;&#30340;&#38598;&#25104;&#26041;&#24335;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;Apple Intelligence &#22312;&#20013;&#22269;&#27491;&#24335;&#25552;&#20379;&#26381;&#21153;&#24050;&#32463;&#36827;&#20837;&#20498;&#35745;&#26102;&#12290;</span></p><p><span>&#38500;&#20102;&#38463;&#37324;&#24052;&#24052;&#30340; Qwen&#65292;&#22791;&#26696;&#20449;&#24687;&#36824;&#25259;&#38706;&#65292;&#30334;&#24230;&#20063;&#23558;&#20316;&#20026;&#21512;&#20316;&#20249;&#20276;&#28145;&#24230;&#21442;&#19982;&#20013;&#22269;&#29256; Apple Intelligence &#30340; AI &#25628;&#32034;&#19982;&#35270;&#35273;&#25628;&#32034;&#12290;&#36825;&#24847;&#21619;&#30528;&#65292;&#33529;&#26524;&#19981;&#20165;&#21487;&#20197;&#26681;&#25454;&#22320;&#21306;&#35843;&#25972;&#24213;&#23618;&#27169;&#22411;&#21644;&#26381;&#21153;&#25552;&#20379;&#21830;&#65292;&#32780;&#19988;&#36825;&#26679;&#30340;&#21512;&#20316;&#20851;&#31995;&#20063;&#24182;&#38750;&#21482;&#33021;&#30001;&#19968;&#23478;&#21378;&#21830;&#25215;&#25285;&#12290;</span></p><p><span>&#38543;&#30528;&#21508;&#20010;&#22269;&#23478;&#21644;&#22320;&#21306;&#23545;&#38544;&#31169;&#12289;&#25968;&#25454;&#20197;&#21450; AI &#26381;&#21153;&#30417;&#31649;&#35201;&#27714;&#30340;&#19981;&#26029;&#21152;&#24378;&#65292;&#21306;&#22495;&#21270;&#24046;&#24322;&#20960;&#20046;&#24050;&#32463;&#19981;&#21487;&#36991;&#20813;&#12290;&#33529;&#26524;&#27491;&#22312;&#20013;&#22269;&#29575;&#20808;&#23454;&#36341;&#19968;&#31181;&#26032;&#30340;&#26041;&#24335;&#65306;&#22312;&#20445;&#25345; Apple Intelligence &#25972;&#20307;&#20135;&#21697;&#20307;&#39564;&#21644;&#24320;&#21457;&#25509;&#21475;&#30456;&#23545;&#32479;&#19968;&#30340;&#21516;&#26102;&#65292;&#26681;&#25454;&#19981;&#21516;&#22320;&#21306;&#30340;&#27861;&#35268;&#19982;&#29983;&#24577;&#36873;&#25321;&#19981;&#21516;&#30340;&#24213;&#23618;&#27169;&#22411;&#12290;&#26410;&#26469;&#65292;&#36825;&#31181;&#27169;&#24335;&#24456;&#21487;&#33021;&#36824;&#20250;&#20986;&#29616;&#22312;&#26356;&#22810;&#24066;&#22330;&#65292;&#24182;&#25104;&#20026; Apple Intelligence &#20840;&#29699;&#21270;&#36807;&#31243;&#20013;&#30456;&#24403;&#37325;&#35201;&#30340;&#19968;&#37096;&#20998;&#12290;</span></p><p><span>&#23545;&#20110;&#20351;&#29992; Apple Intelligence API &#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#21516;&#26679;&#26159;&#19968;&#20010;&#22909;&#28040;&#24687;&#12290;&#22914;&#26524;&#33529;&#26524;&#33021;&#22815;&#32487;&#32493;&#32500;&#25345; API &#23618;&#30340;&#19968;&#33268;&#24615;&#65292;&#24320;&#21457;&#32773;&#29702;&#35770;&#19978;&#26080;&#38656;&#20026;&#20102;&#19981;&#21516;&#24066;&#22330;&#32500;&#25252;&#23436;&#20840;&#19981;&#21516;&#30340;&#23454;&#29616;&#26041;&#26696;&#65292;&#20063;&#24847;&#21619;&#30528;&#37027;&#20123;&#20197; Apple Intelligence &#33021;&#21147;&#20026;&#37325;&#35201;&#29305;&#33394;&#30340;&#24212;&#29992;&#65292;&#23558;&#26377;&#26426;&#20250;&#35302;&#36798;&#26356;&#24191;&#27867;&#30340;&#29992;&#25143;&#12290;</span></p><p><span>Gemini &#21644; Qwen &#25110;&#35768;&#24182;&#19981;&#26159;&#25105;&#26085;&#24120; Agent &#20351;&#29992;&#22330;&#26223;&#20013;&#26368;&#32768;&#30524;&#30340;&#20004;&#20010;&#21517;&#23383;&#65292;&#20294;&#23427;&#20204;&#22312;&#19990;&#30028;&#30693;&#35782;&#12289;&#35821;&#35328;&#29702;&#35299;&#31561;&#26041;&#38754;&#37117;&#26377;&#30456;&#24403;&#19981;&#38169;&#30340;&#34920;&#29616;&#12290;&#32771;&#34385;&#21040; Apple Intelligence &#24403;&#21069;&#26356;&#20559;&#21521;&#31995;&#32479;&#32423;&#36741;&#21161;&#33021;&#21147;&#65292;&#32780;&#36825;&#20123;&#21512;&#20316;&#20249;&#20276;&#21448;&#25317;&#26377;&#25104;&#29087;&#30340;&#27169;&#22411;&#22522;&#30784;&#35774;&#26045;&#21644;&#20113;&#26381;&#21153;&#32463;&#39564;&#65292;&#33529;&#26524;&#36825;&#26679;&#30340;&#36873;&#25321;&#20854;&#23454;&#30456;&#24403;&#21512;&#29702;&#12290;</span></p><p><span>Apple Intelligence &#24050;&#32463;&#25104;&#20026;&#33529;&#26524;&#22312; AI &#26102;&#20195;&#26368;&#37325;&#35201;&#30340;&#20837;&#21475;&#20043;&#19968;&#12290;&#23427;&#30446;&#21069;&#30340;&#33021;&#21147;&#36317;&#31163;&#25105;&#30340;&#20010;&#20154;&#26399;&#24453;&#20173;&#26377;&#19968;&#20123;&#36317;&#31163;&#65292;&#20294;&#33267;&#23569;&#20174; 2026 &#24180;&#24320;&#22987;&#65292;&#23427;&#27491;&#22312;&#30495;&#27491;&#35206;&#30422;&#20840;&#29699;&#26356;&#22810;&#29992;&#25143;&#12290;&#30456;&#27604;&#20110;&#20170;&#22825;&#23427;&#31350;&#31455;&#33021;&#23436;&#25104;&#22810;&#23569;&#20219;&#21153;&#65292;&#25105;&#26356;&#26399;&#24453; WWDC 2027 &#19978;&#65292;&#33529;&#26524;&#20250;&#22914;&#20309;&#36827;&#19968;&#27493;&#35753; AI &#28145;&#20837;&#34701;&#20837;&#33258;&#24049;&#30340;&#30828;&#20214;&#12289;&#31995;&#32479;&#19982;&#26381;&#21153;&#29983;&#24577;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-146/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/controlling-orphans-in-swiftui-text/?utm_source=fatbobman%20weekly%20issue%20148&amp;utm_medium=web"><span>&#22312; SwiftUI Text &#20013;&#25511;&#21046;&#23396;&#34892;&#65306;&#25366;&#25496;&#26410;&#20844;&#24320;&#30340; avoidsOrphans</span></a></strong></h3><p><span>SwiftUI &#30340; </span><code>Text</code><span> &#26377;&#19968;&#39033;&#40664;&#35748;&#34892;&#20026;&#65306;&#24403;&#27573;&#33853;&#26411;&#34892;&#21482;&#21097;&#19968;&#20010;&#23396;&#35789;&#25110;&#23396;&#23383;&#26102;&#65292;&#23427;&#20250;&#20027;&#21160;&#25226;&#19978;&#19968;&#34892;&#30340;&#23436;&#25972;&#35789;&#32452;&#19968;&#24182;&#25512;&#21040;&#26411;&#34892;&#65292;&#36991;&#20813;&#8220;&#33853;&#21333;&#8221;&#12290;&#36825;&#20221;&#20307;&#36148;&#22810;&#25968;&#26102;&#20505;&#26159;&#23545;&#30340;&#65292;&#20294;&#20195;&#20215;&#26159;&#19978;&#19968;&#34892;&#21487;&#33021;&#30041;&#19979;&#19968;&#22823;&#29255;&#31354;&#30333;&#8212;&#8212;&#22312;&#31364;&#23481;&#22120;&#25110;&#20013;&#33521;&#28151;&#25490;&#30340;&#22330;&#26223;&#20013;&#65292;&#21453;&#32780;&#30772;&#22351;&#20102;&#27573;&#33853;&#30340;&#22343;&#34913;&#12290;&#40635;&#28902;&#22312;&#20110;&#65292;UIKit &#20801;&#35768;&#24320;&#21457;&#32773;&#36890;&#36807; </span><code>NSParagraphStyle</code><span> &#20851;&#25481;&#36825;&#39033;&#31574;&#30053;&#65292;SwiftUI &#21364;&#27809;&#26377;&#25552;&#20379;&#20219;&#20309;&#20844;&#24320;&#25509;&#21475;&#12290;&#26412;&#25991;&#23558;&#25366;&#25496; SwiftUI &#20013;&#19968;&#20010;&#26089;&#24050;&#23384;&#22312;&#12289;&#21364;&#22987;&#32456;&#26410;&#26366;&#20844;&#24320;&#30340; API &#8212;&#8212; </span><code>avoidsOrphans</code><span>&#65292;&#35753;&#24320;&#21457;&#32773;&#37325;&#26032;&#25343;&#22238;&#36825;&#39033;&#25511;&#21046;&#26435;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-01"><span>&#20877;&#35848;&#21327;&#35758;&#19982;&#20840;&#23616; Actor &#30340;&#35774;&#35745;&#26435;&#34913; (An Even Closer Look at Protocols and Global Actors)</span></a></strong></h3><p><span>&#38543;&#30528; Swift &#24182;&#21457;&#27169;&#22411;&#19981;&#26029;&#28436;&#36827;&#65292;&#19968;&#20123;&#36807;&#21435;&#34987;&#35270;&#20026;&#29702;&#25152;&#24403;&#28982;&#30340;&#24037;&#31243;&#21462;&#33293;&#65292;&#20063;&#24320;&#22987;&#22240;&#35821;&#35328;&#33021;&#21147;&#30340;&#22686;&#24378;&#32780;&#21457;&#29983;&#21464;&#21270;&#12290;&#22312;&#26412;&#25991;&#20013;&#65292;&#8288;</span><a href="https://mastodon.social/@mattiem"><span>Matt Massicotte</span></a><span> &#24182;&#27809;&#26377;&#20572;&#30041;&#22312;&#35752;&#35770;&#8220;</span><code>@MainActor</code><span> &#24212;&#35813;&#25918;&#22312; protocol &#19978;&#36824;&#26159;&#26041;&#27861;&#19978;&#8221;&#65292;&#32780;&#26159;&#20511;&#27492;&#36827;&#19968;&#27493;&#25506;&#35752;&#20102; Swift &#24182;&#21457;&#26102;&#20195;&#30340; API &#35774;&#35745;&#24605;&#36335;&#12290;&#30456;&#27604;&#32473;&#20986;&#19968;&#31181;&#25152;&#35859;&#30340;&#8220;&#26368;&#20339;&#23454;&#36341;&#8221;&#65292;Matt &#26356;&#24378;&#35843;&#19968;&#31181;&#35774;&#35745;&#24605;&#36335;&#65306;&#38548;&#31163;&#26159;&#19968;&#31181;&#32422;&#26463;&#65292;&#24212;&#24403;&#28304;&#20110;&#30495;&#23454;&#38656;&#27714;&#65292;&#32780;&#19981;&#26159;&#27839;&#34989;&#26082;&#26377;&#20064;&#24815;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-02"><span>Tuist &#27599;&#21608;&#21160;&#24577;&#31532;&#19968;&#26399; (Weekly Tuist News #1)</span></a></strong></h3><p><span>&#38543;&#30528; AI Agent &#36234;&#26469;&#36234;&#28145;&#20837;&#24320;&#21457;&#27969;&#31243;&#65292;Tuist &#36825;&#31867;&#24037;&#31243;&#31649;&#29702;&#24037;&#20855;&#30340;&#37325;&#35201;&#24615;&#20063;&#22312;&#19981;&#26029;&#25552;&#21319;&#65292;&#23545;&#20110;&#29420;&#31435;&#24320;&#21457;&#32773;&#32780;&#35328;&#21516;&#26679;&#22914;&#27492;&#12290;</span></p><p><span>&#20316;&#20026;&#38271;&#26399;&#27963;&#36291;&#20110; Tuist &#31038;&#21306;&#30340;&#24320;&#21457;&#32773;&#65292;&#8288;</span><a href="https://www.linkedin.com/in/gamehelper/"><span>Lee YoungJun</span></a><span> &#25512;&#20986;&#20102;&#19968;&#20010;&#19987;&#38376;&#36861;&#36394; Tuist &#29983;&#24577;&#30340;&#26032;&#31995;&#21015; Weekly Tuist News&#12290;&#19982;&#21333;&#32431;&#27719;&#24635; release notes &#19981;&#21516;&#65292;&#36825;&#20010;&#31995;&#21015;&#36824;&#20250;&#32467;&#21512;&#31038;&#21306;&#21160;&#24577;&#20197;&#21450;&#20316;&#32773;&#22312;&#23454;&#38469;&#39033;&#30446;&#20013;&#30340;&#20351;&#29992;&#20307;&#39564;&#12290;&#22312;&#21019;&#21002;&#21495;&#20013;&#65292;&#20182;&#20171;&#32461;&#20102; SwifterPM &#25104;&#20026;&#40664;&#35748;&#20381;&#36182;&#24674;&#22797;&#26041;&#24335;&#12289;Target &#32531;&#23384;&#22833;&#25928;&#26465;&#20214;&#30340;&#26032;&#25511;&#21046;&#33021;&#21147;&#65292;&#20197;&#21450; Tuist &#38754;&#21521; Coding Agent &#30340; </span><code>auth.md</code><span> &#25903;&#25345;&#65292;&#24182;&#32467;&#21512;&#23454;&#38469;&#20351;&#29992;&#20998;&#20139;&#20102;&#33258;&#24049;&#30340;&#39564;&#35777;&#36807;&#31243;&#19982;&#35266;&#23519;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-03"><span>&#20351;&#29992; #Preview(arguments:) &#36731;&#26494;&#39044;&#35272; SwiftUI &#35270;&#22270;&#30340;&#22810;&#29366;&#24577;</span></a></strong></h3><p><span>&#22823;&#22810;&#25968; SwiftUI &#32452;&#20214;&#37117;&#19981;&#21482;&#26377;&#19968;&#31181;&#29366;&#24577;&#65306;&#31354;&#25968;&#25454;&#12289;&#21152;&#36733;&#20013;&#12289;&#38169;&#35823;&#12289;&#26435;&#38480;&#21463;&#38480;&#31561;&#12290;&#24320;&#21457;&#36807;&#31243;&#20013;&#65292;&#25105;&#20204;&#36890;&#24120;&#20250;&#32500;&#25252;&#19968;&#32452;&#37325;&#22797;&#30340; </span><code>#Preview</code><span>&#65292;&#25110;&#23558;&#25152;&#26377;&#29366;&#24577;&#25918;&#36827;&#19968;&#20010; </span><code>VStack</code><span> &#20013;&#32479;&#19968;&#23637;&#31034;&#12290;Xcode 27 &#26032;&#22686;&#30340; </span><code>#Preview(arguments:)</code><span> &#27491;&#26159;&#20026;&#36825;&#19968;&#22330;&#26223;&#32780;&#35774;&#35745;&#65292;&#23427;&#33021;&#22815;&#26681;&#25454;&#19968;&#32452;&#29366;&#24577;&#25968;&#25454;&#33258;&#21160;&#29983;&#25104;&#22810;&#20010;&#29420;&#31435;&#30340; Preview&#65292;&#24182;&#25903;&#25345;&#22312; Canvas &#20013;&#21333;&#29420;&#26597;&#30475;&#27599;&#19968;&#31181;&#29366;&#24577;&#12290;</span></p><p><span>&#8288;</span><a href="https://x.com/iosartem"><span>Artem Novichkov</span></a><span> &#22312;&#25991;&#20013;&#20063;&#20998;&#20139;&#20102;&#20182;&#32452;&#32455; Preview &#30340;&#24605;&#36335;&#65306;</span><code>arguments</code><span> &#24212;&#35813;&#25551;&#36848;&#19994;&#21153;&#29366;&#24577;&#65288;State&#65289;&#65292;&#32780;&#19981;&#26159;&#29615;&#22659;&#65288;Environment&#65289;&#12290;&#21363;&#20351;&#26410;&#26469; API &#32487;&#32493;&#28436;&#36827;&#65292;&#36825;&#31181;&#23558;&#19994;&#21153;&#29366;&#24577;&#19982;&#36816;&#34892;&#29615;&#22659;&#20998;&#31163;&#30340;&#35774;&#35745;&#29702;&#24565;&#20381;&#28982;&#20855;&#26377;&#38271;&#26399;&#21442;&#32771;&#20215;&#20540;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-04"><span>&#29992; iOS 27 &#26032; API &#23454;&#29616; SwiftUI &#21516;&#24515;&#22278;&#35282;&#25353;&#38062; (Concentric Buttons with OS 27&#8217;s SwiftUI APIs)</span></a></strong></h3><p><span>WWDC 26 &#20013;&#65292;&#33529;&#26524;&#32473; SwiftUI &#26032;&#22686;&#20102; </span><code>GeometryProxy.concentricCornerRadii</code><span>&#65292;&#35753;&#24320;&#21457;&#32773;&#33021;&#22815;&#33719;&#21462;&#23481;&#22120;&#30340;&#21516;&#24515;&#22278;&#35282;&#20449;&#24687;&#12290;&#19981;&#36807;&#65292;</span><code>ButtonBorderShape</code><span> &#20173;&#28982;&#26159;&#19968;&#20010;&#23553;&#38381;&#31867;&#22411;&#65292;&#26080;&#27861;&#30452;&#25509;&#23454;&#29616;&#30495;&#27491;&#30340;&#33258;&#23450;&#20041;&#25353;&#38062;&#36793;&#26694;&#12290;&#8288;</span><a href="https://twitter.com/_al_we"><span>Alexander Wei&#223;</span></a><span> &#21033;&#29992;&#36825;&#19968;&#26032; API&#65292;&#32467;&#21512; </span><code>onGeometryChange</code><span>&#12289;&#33258;&#23450;&#20041; </span><code>ViewModifier</code><span> &#19982;&#26041;&#27861;&#37325;&#36733;&#65292;&#23454;&#29616;&#20102;&#19968;&#22871;&#20351;&#29992;&#26041;&#24335;&#20960;&#20046;&#19982;&#31995;&#32479; API &#26080;&#24322;&#30340;&#21516;&#24515;&#25353;&#38062;&#26041;&#26696;&#12290;</span></p><blockquote><p><span>&#23545;&#20110; </span><code>GeometryProxy.concentricCornerRadii</code><span> &#36825;&#31867;&#26032;&#22686; API&#65292;&#25105;&#20204;&#24448;&#24448;&#21482;&#38656;&#20960;&#31186;&#38047;&#23601;&#33021;&#30693;&#36947;&#23427;&#30340;&#20316;&#29992;&#65307;&#20294;&#30495;&#27491;&#24212;&#29992;&#21040;&#39033;&#30446;&#20013;&#26102;&#65292;&#25165;&#20250;&#21457;&#29616;&#36824;&#26377;&#19981;&#23569;&#23454;&#29616;&#32454;&#33410;&#21644;&#26694;&#26550;&#38480;&#21046;&#38656;&#35201;&#32771;&#34385;&#12290;&#19982;&#20854;&#35828;&#36825;&#26159;&#19968;&#31687; API &#20171;&#32461;&#65292;&#19981;&#22914;&#35828; Alexander &#20998;&#20139;&#20102;&#23427;&#22312;&#23454;&#38469;&#20351;&#29992;&#20013;&#30340;&#27880;&#24847;&#20107;&#39033;&#65292;&#20197;&#21450;&#20540;&#24471;&#23581;&#35797;&#30340;&#24212;&#29992;&#22330;&#26223;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-05"><span>Swift&#12289;AI &#19982;&#36719;&#20214;&#24320;&#21457;&#30340;&#26410;&#26469;&#23637;&#26395; (Swift, AI, and the future of software development)</span></a></strong></h3><p><span>AI &#24050;&#32463;&#25104;&#20026;&#35768;&#22810;&#24320;&#21457;&#32773;&#24037;&#20316;&#27969;&#20013;&#19981;&#21487;&#25110;&#32570;&#30340;&#19968;&#37096;&#20998;&#65292;&#20294;&#23427;&#22312;&#25552;&#21319;&#25928;&#29575;&#30340;&#21516;&#26102;&#65292;&#20063;&#24708;&#28982;&#25913;&#21464;&#30528;&#24320;&#21457;&#32773;&#19982;&#20195;&#30721;&#20043;&#38388;&#30340;&#20851;&#31995;&#12290;&#8288;</span><a href="https://x.com/tiborbodecs"><span>Tibor B&#246;decs</span></a><span> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#30495;&#35802;&#20998;&#20139;&#20102;&#33258;&#24049;&#36825;&#19968;&#24180;&#26469;&#30340;&#22256;&#24785;&#65306;&#19968;&#26041;&#38754;&#20139;&#21463; AI &#24102;&#26469;&#30340;&#39640;&#25928;&#29575;&#65292;&#21478;&#19968;&#26041;&#38754;&#21448;&#24576;&#24565;&#20146;&#25163;&#20889;&#20195;&#30721;&#12289;&#28145;&#20837;&#29702;&#35299;&#38382;&#39064;&#30340;&#36807;&#31243;&#65307;&#26082;&#30456;&#20449; AI &#20250;&#25345;&#32493;&#25913;&#21464;&#36719;&#20214;&#24320;&#21457;&#65292;&#20063;&#24076;&#26395;&#23427;&#22987;&#32456;&#21482;&#26159;&#24110;&#21161;&#24320;&#21457;&#32773;&#24605;&#32771;&#19982;&#21019;&#36896;&#30340;&#24037;&#20855;&#65292;&#32780;&#19981;&#26159;&#21462;&#20195;&#24605;&#32771;&#26412;&#36523;&#12290;</span></p><blockquote><p><span>&#22312;&#36807;&#21435;&#19968;&#27573;&#26102;&#38388;&#20013;&#65292;AI &#32473;&#25105;&#24102;&#26469;&#30340;&#22256;&#24785;&#19982; Tibor B&#246;decs &#24456;&#30456;&#20284;&#12290;&#23613;&#31649;&#23427;&#35753;&#25105;&#22833;&#21435;&#20102;&#19968;&#20123;&#20048;&#36259;&#65292;&#23545;&#20195;&#30721;&#12289;&#23545;&#20135;&#21697;&#20135;&#29983;&#20102;&#26576;&#31181;&#30095;&#31163;&#24863;&#65292;&#20294;&#25105;&#20063;&#19968;&#30452;&#19981;&#25032;&#22320;&#23581;&#35797;&#23545; AI &#24314;&#31435;&#26356;&#24378;&#30340;&#25484;&#25511;&#21147;&#65292;&#35753;&#23427;&#26356;&#22909;&#22320;&#20026;&#25105;&#25152;&#29992;&#65292;&#25104;&#20026;&#25105;&#30340;&#22806;&#33041;&#65292;&#32780;&#19981;&#26159;&#35753;&#25105;&#27814;&#20026;&#23427;&#30340;&#36741;&#21161;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0148-06"><span>Gitwyn&#65306;&#22260;&#32469; Xcode &#24037;&#20316;&#27969;&#35774;&#35745;&#30340; Git &#23458;&#25143;&#31471;</span></a></strong></h3><p><span>&#23613;&#31649;&#36817;&#20960;&#20010;&#29256;&#26412;&#20013; Xcode &#30340; Git &#21151;&#33021;&#24050;&#32463;&#26377;&#20102;&#26126;&#26174;&#25913;&#21892;&#65292;&#20294;&#26080;&#35770;&#26159;&#20351;&#29992;&#20307;&#39564;&#36824;&#26159;&#21151;&#33021;&#23436;&#25972;&#24615;&#65292;&#20173;&#38590;&#20197;&#28385;&#36275;&#37096;&#20998;&#24320;&#21457;&#32773;&#30340;&#22312;&#19981;&#21516;&#22330;&#26223;&#19979;&#30340;&#38656;&#27714;&#12290;&#30001; &#8288;</span><a href="https://www.linkedin.com/in/karthikk9828/"><span>Karthik K</span></a><span> &#24320;&#21457;&#30340; Gitwyn&#65292;&#26159;&#19968;&#27454;&#22260;&#32469; Xcode &#24037;&#20316;&#27969;&#35774;&#35745;&#30340;&#21407;&#29983; Git &#23458;&#25143;&#31471;&#12290;&#22312;&#20219;&#24847; Xcode &#39033;&#30446;&#20013;&#25353;&#19979; &#8984;&#8679;E&#65292;&#21363;&#21487;&#26597;&#30475;&#25913;&#21160;&#12289;&#25972;&#29702;&#26242;&#23384;&#20869;&#23481;&#12289;&#29983;&#25104;&#25552;&#20132;&#20449;&#24687;&#24182;&#25512;&#36865;&#20195;&#30721;&#65292;&#20840;&#31243;&#26080;&#38656;&#20999;&#25442;&#21040;&#32456;&#31471;&#25110;&#20854;&#20182; Git &#24037;&#20855;&#12290;</span></p><p><span>Gitwyn &#30340;&#19968;&#39033;&#29305;&#33394;&#21151;&#33021;&#26159;&#21033;&#29992;&#35774;&#22791;&#31471; Apple Intelligence&#65292;&#26681;&#25454;&#24050;&#26242;&#23384;&#30340;&#20195;&#30721;&#33258;&#21160;&#29983;&#25104;&#25552;&#20132;&#20449;&#24687;&#12290;&#26080;&#38656;&#32852;&#32593;&#65292;&#20063;&#19981;&#20250;&#19978;&#20256;&#28304;&#30721;&#12290;&#30456;&#27604;&#21333;&#32431;&#20943;&#23569;&#19968;&#27425;&#36755;&#20837;&#65292;&#23427;&#26356;&#24076;&#26395;&#23558;&#26597;&#30475;&#24046;&#24322;&#12289;&#32452;&#32455;&#25552;&#20132;&#12289;&#29983;&#25104;&#35828;&#26126;&#21644;&#25512;&#36865;&#20195;&#30721;&#25972;&#21512;&#20026;&#19968;&#27573;&#36830;&#32493;&#30340;&#24320;&#21457;&#27969;&#31243;&#65292;&#35753; Git &#25805;&#20316;&#23613;&#21487;&#33021;&#30041;&#22312; Xcode &#30340;&#24037;&#20316;&#19978;&#19979;&#25991;&#20013;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-07"><span>VersionedDocC&#65306;&#20026; Swift-DocC &#34917;&#19978;&#29256;&#26412;&#31649;&#29702;</span></a></strong></h3><p><span>&#36807;&#21435;&#20960;&#24180;&#65292;&#27599;&#36898; WWDC &#21484;&#24320;&#65292;&#25105;&#36890;&#24120;&#37117;&#20250;&#31532;&#19968;&#26102;&#38388;&#25171;&#24320;&#33529;&#26524;&#24320;&#21457;&#32773;&#25991;&#26723;&#65292;&#36890;&#36807;&#8220;API &#21464;&#21270;&#65288;API Changes&#65289;&#8221;&#21151;&#33021;&#27604;&#36739;&#19981;&#21516; Xcode &#19982; SDK &#29256;&#26412;&#65292;&#26597;&#30475; API &#30340;&#26032;&#22686;&#12289;&#20462;&#25913;&#19982;&#24323;&#29992;&#12290;&#36951;&#25022;&#30340;&#26159;&#65292;&#36825;&#39033;&#39047;&#20026;&#23454;&#29992;&#30340;&#21151;&#33021;&#22312; 2025 &#24180;&#30340;&#25991;&#26723;&#32593;&#31449;&#25913;&#29256;&#21518;&#28040;&#22833;&#20102;&#12290;&#21407;&#26377;&#30340;&#24046;&#24322;&#26597;&#35810;&#22320;&#22336;&#34429;&#28982;&#20173;&#21487;&#35775;&#38382;&#65292;&#21364;&#24050;&#26080;&#27861;&#21576;&#29616;&#23436;&#25972;&#30340; API &#21464;&#21270;&#12290;</span></p><p><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#24320;&#21457;&#30340; VersionedDocC&#65292;&#24688;&#22909;&#20026; DocC &#34917;&#19978;&#20102;&#36825;&#19968;&#33021;&#21147;&#12290;&#23427;&#22312;&#21407;&#26377; Swift &#24037;&#20855;&#38142;&#20043;&#19978;&#22686;&#21152;&#20102;&#19968;&#23618;&#21457;&#24067;&#32534;&#25490;&#65306;&#20026;&#19981;&#21516;&#29256;&#26412;&#29983;&#25104;&#31283;&#23450;&#22320;&#22336;&#65292;&#25552;&#20379;&#29256;&#26412;&#36873;&#25321;&#22120;&#65292;&#20381;&#25454;&#31526;&#21495;&#22270;&#23637;&#31034;&#30456;&#37051;&#29256;&#26412;&#30340;&#20844;&#24320; API &#21464;&#21270;&#65292;&#24182;&#36890;&#36807;&#19981;&#21487;&#21464;&#32531;&#23384;&#36991;&#20813;&#21453;&#22797;&#26500;&#24314;&#21382;&#21490;&#25991;&#26723;&#12290;&#39033;&#30446;&#21516;&#26102;&#25552;&#20379; SwiftPM &#25554;&#20214;&#12289;GitHub Action &#21644; GitHub Pages &#24037;&#20316;&#27969;&#65292;&#20063;&#25903;&#25345;&#22810;&#24179;&#21488;&#31526;&#21495;&#22270;&#12289;&#22806;&#37096;&#27169;&#22359;&#21450;&#29420;&#31435; DocC &#30446;&#24405;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0148-08"><span>Swift Subprocess 1.0</span></a></strong></h3><p><span>&#21382;&#32463;&#19968;&#24180;&#36845;&#20195;&#65292;Swift &#23448;&#26041;&#39033;&#30446; swift-subprocess &#26412;&#21608;&#21457;&#24067; 1.0 &#27491;&#24335;&#29256;&#12290;&#23427;&#26159;&#19968;&#22871;&#22522;&#20110; Swift Concurrency &#30340;&#36328;&#24179;&#21488;&#23376;&#36827;&#31243;&#24211;&#65292;&#21487;&#20197;&#22312; macOS&#12289;Linux&#12289;Windows&#12289;Android &#19982; BSD &#31995;&#32479;&#19978;&#65292;&#20197;&#32479;&#19968;&#26041;&#24335;&#21551;&#21160;&#21629;&#20196;&#12289;&#25552;&#20379;&#36755;&#20837;&#12289;&#27969;&#24335;&#35835;&#21462;&#36755;&#20986;&#65292;&#24182;&#31649;&#29702;&#36827;&#31243;&#30340;&#36864;&#20986;&#19982;&#21462;&#28040;&#12290;</span></p><p><span>&#23427;&#23588;&#20854;&#36866;&#21512; Swift CLI&#12289;&#26500;&#24314;&#24037;&#20855;&#12289;&#26381;&#21153;&#22120;&#31243;&#24207;&#12289;&#24320;&#21457;&#32773;&#24037;&#20855;&#19982; macOS &#33258;&#21160;&#21270;&#12290;&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;1.0 &#35201;&#27714; Swift 6.2&#65292;&#19981;&#38754;&#21521;&#26222;&#36890; iOS App&#65292;&#20063;&#26410;&#25552;&#20379;&#27801;&#31665;&#12289;&#21629;&#20196;&#25480;&#26435;&#25110;&#20266;&#32456;&#31471;&#65288;PTY&#65289;&#31561;&#26356;&#39640;&#23618;&#33021;&#21147;&#12290;</span></p><p><span>swift-subprocess &#20063;&#34917;&#19978;&#20102; Swift &#26500;&#24314;&#26412;&#22320; Agent &#25152;&#38656;&#30340;&#19968;&#22359;&#37325;&#35201;&#25340;&#22270;&#65306;&#21487;&#38752;&#25191;&#34892;&#24037;&#20855;&#12289;&#25345;&#32493;&#25509;&#25910;&#36816;&#34892;&#32467;&#26524;&#65292;&#24182;&#22949;&#21892;&#31649;&#29702;&#23376;&#36827;&#31243;&#29983;&#21629;&#21608;&#26399;&#12290;&#27169;&#22411;&#20915;&#23450;&#8220;&#20570;&#20160;&#20040;&#8221;&#65292;Subprocess &#21017;&#35753;&#8220;&#22914;&#20309;&#25191;&#34892;&#8221;&#21464;&#24471;&#26356;&#21487;&#25511;&#12289;&#26356;&#21487;&#35266;&#27979;&#65292;&#20063;&#26356;&#31526;&#21512; Swift &#30340;&#35821;&#35328;&#33539;&#24335;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #147]]></title><description><![CDATA[Hot Tea or Iced Coffee]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 03 Aug 2026 12:02:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YzuJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YzuJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 424w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 848w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1272w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp" width="1400" height="799" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:799,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:142272,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/209575455?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YzuJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 424w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 848w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1272w, https://substackcdn.com/image/fetch/$s_!YzuJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6a6d481-56b8-4eb1-a5f7-cdf7f0dd1d25_1400x799.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@alexmeier19?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Alex Meier</a><span> on </span><a href="https://unsplash.com/photos/a-glass-of-iced-tea-next-to-a-jar-of-iced-tea-EbXSMYVOF-I?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Hot Tea or Iced Coffee</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-147/">Read on web &#8594;</a></p><p><span>Recently, the temperatures in my city have been breaking historical records. Since the end of July, we&#8217;ve been stuck in a stretch of scorching weather lasting more than ten days, with temperatures consistently above 30&#176;C. While that may not sound particularly extreme on its own, paired with humidity exceeding 80%, it leaves behind a lingering sense of heat that never quite goes away&#8212;even after spending the entire day in an air-conditioned room set to 25&#176;C.</span></p><p><span>I&#8217;ve found myself turning to tea and coffee to improve how I feel. Interestingly, only a cup of hot tea gives me the satisfying sensation of heat escaping with perspiration, while only an iced coffee brings an immediate, refreshing coolness. I suspect this isn&#8217;t simply a matter of physics. More likely, it&#8217;s a psychological association shaped by years of habit.</span></p><p><span>There&#8217;s an old Chinese saying: &#8220;A calm mind brings a cool body.&#8221; I can&#8217;t claim to have reached that level of serenity. For now, I still rely on these simple drinks to help me find a bit of balance between warmth and coolness.</span></p><p><span>Hopefully, this hot and humid summer will return to normal sooner rather than later.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-146/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/liquid-glass-a-field-guide-to-uikit-compatibility-pitfalls/?utm_source=fatbobman%20weekly%20issue%20147&amp;utm_medium=web"><span>Liquid Glass: A Field Guide to UIKit Compatibility Pitfalls</span></a></strong></h3><p><span>While Liquid Glass introduces a fresh interaction experience, it also makes UIKit compatibility significantly more complex. The same UI can behave very differently across iOS 18, iOS 26, and iOS 27, while different API combinations and implementation approaches may introduce their own compatibility pitfalls. Drawing from real-world project experience, </span><a href="https://x.com/Megabits_Studio"><span>Megabits</span></a><span> summarizes common issues involving Sheets, Navigation, Popovers, Toolbars, and other UIKit components, while also explaining lower-level behaviors such as </span><code>UIBarButtonItem</code><span>, </span><code>CABackdropLayer</code><span>, and the Scroll Edge Effect, complete with practical solutions and runnable demos.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-01"><span>The Map, Drawn Twice</span></a></strong></h3><p><span>Apple&#8217;s UI rendering stack spans Core Graphics, Core Text, Core Image, Core Animation, and SwiftUI. Although developers work with these frameworks regularly, many never fully understand the distinct responsibility of each layer. In the inaugural issue of Apple UI Insider, </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> presents a conceptual map that traces the journey from Swift code to the final pixels on screen.</span></p><p><span>Mihaela adopts a fascinating validation approach: every illustration is rendered twice from the exact same scene description&#8212;once by a custom clean-room rendering engine, and once by Apple&#8217;s Core Graphics&#8212;before being compared pixel by pixel. Although nearly half of the pixels differ, the average pixel difference is only around 0.1%, making the two images visually almost indistinguishable. This methodology of understanding system behavior through independent implementations, reproducible experiments, and quantitative measurements is arguably even more compelling than the article itself, and makes the rest of the series especially worth looking forward to.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-02"><span>Finally found a use case for .fixedSize</span></a></strong></h3><p><code>.fixedSize</code><span> is one of SwiftUI&#8217;s most overlooked modifiers. Many developers associate it only with niche use cases such as preventing text wrapping. Starting from a common layout requirement&#8212;making every card inside a horizontal </span><code>ScrollView</code><span> match the height of the tallest one&#8212;</span><a href="https://www.linkedin.com/in/engomarelsayed"><span>Omar Elsayed</span></a><span> demonstrates how </span><code>.fixedSize</code><span> provides an elegant solution.</span></p><blockquote><p><span>Perhaps </span><code>.fixedSize</code><span> has never become widely adopted because its name is rather abstract. What exactly is being &#8220;fixed&#8221;? And what does &#8220;size&#8221; actually refer to? If you&#8217;d like to better understand why it changes layout behavior, you may find my previous series, </span><a href="https://fatbobman.com/en/posts/layout-dimensions-1/"><span>SwiftUI Layout: The Mystery of Size</span></a><span>, helpful. It recreates </span><code>fixedSize</code><span> from scratch and breaks down the layout negotiation mechanism behind it.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-03"><span>Two Interesting Explorations of LazyVStack&#8217;s Layout Mechanism</span></a></strong></h3><p><span>On the Apple Developer Forums, </span><a href="https://developer.apple.com/forums/profile/alextar04"><span>alextar04</span></a><span> published two in-depth analyses of </span><code>LazyVStack</code><span>. One investigates blank screens and truncated cells during fast scrolling, while the other examines why </span><code>GeometryReader</code><span> reports multiple different sizes when used inside a </span><code>LazyVStack</code><span> (</span><a href="https://developer.apple.com/forums/thread/839688"><span>Thread 2</span></a><span>). Beyond providing minimal reproducible examples, the author combines insights from the WWDC 26 Lazy Stack session, SwiftUI logging, and experimental observations to reconstruct how SwiftUICore&#8212;including symbol resolution and </span><code>CA::Transaction</code><span> validation&#8212;might estimate sizes and validate layouts, using these hypotheses to explain the observed behavior.</span></p><blockquote><p><span>These two posts also highlight the design differences between </span><code>List</code><span> and </span><code>LazyVStack</code><span> from another perspective. The author suggests that, in order to support lazy layout, </span><code>LazyVStack</code><span> relies on size estimation under certain circumstances, which naturally leads to behavior different from </span><code>List</code><span>. This further illustrates why neither container is universally better&#8212;their strengths simply apply to </span><a href="https://fatbobman.com/en/posts/list-or-lazyvstack/"><span>different scenarios</span></a><span>.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-08"><span>Swift on Windows: A Year of Refinement</span></a></strong></h3><p><span>A year ago, Swift on Windows had already proven itself capable of supporting real production applications. But being &#8220;functional&#8221; is not the same as being predictable. Over the past year, </span><a href="https://x.com/browsercompany"><span>The Browser Company</span></a><span>, together with Apple and the Swift community, has focused on strengthening the platform&#8217;s foundations: rebuilding the runtime build system with modern CMake, introducing the Experimental Swift SDK, formalizing both static and dynamic linking models, and improving runtime selection and distribution across multi-toolchain environments.</span></p><p><span>What truly advances the maturity of a cross-platform ecosystem is often not a headline-grabbing feature, but the engineering details that are easy to overlook: whether build configurations are reproducible and auditable, whether runtimes can be bound deterministically, whether tools can be distributed independently, and whether CI and developer environments behave consistently. This article offers an excellent overview of how Swift on Windows has evolved over the past year&#8212;not through flashy new capabilities, but through continuous refinement of its engineering foundations.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-04"><span>Memo Property: Reusing More Stateful Business Logic for SwiftUI Views</span></a></strong></h3><p><span>In </span><a href="https://github.com/vanvoorden/TaskProperty"><span>TaskProperty</span></a><span>, </span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> demonstrated how custom </span><code>DynamicProperty</code><span> types can extract stateful business logic from SwiftUI views while remaining aligned with the view lifecycle. Building on that idea, this article leverages Swift&#8217;s latest Parameter Packs (Variadic Generics) to implement a React-like </span><code>useMemo</code><span> mechanism for SwiftUI: filtering, sorting, and other expensive computations are recomputed only when explicitly declared dependencies change, while cached results are reused for unrelated view updates.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-05"><span>One Model Object, Multiple Editing Flows: The Missing Layer Between Model and UI</span></a></strong></h3><p><span>Since the introduction of Observation, many developers have assumed that Combine is gradually becoming less relevant in SwiftUI. In this article, </span><a href="https://www.linkedin.com/in/sergey-tristan/"><span>Sergey Tristan</span></a><span> presents a different perspective. When multiple independent editing flows share the same model object, with each flow interested in only part of its state, Observation excels at efficiently detecting changes, while Combine is better suited for composing, transforming, and continuously synchronizing data. Rather than replacing one another, the two complement each other.</span></p><p><span>The article introduces a Projection layer between the model and the UI that transforms one or more continuously changing data sources into reactive representations tailored for different consumers. Whether or not you adopt this architecture, it raises an interesting question: as applications evolve to include increasingly independent yet interconnected editing flows, do we need an abstraction beyond DTOs, ViewModels, and Observation to organize these continuously evolving data flows?</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0147-06"><span>Apple External Display Support Lookup</span></a></strong></h3><p><span>External display support across Apple devices can be surprisingly complicated. Capabilities vary by chip generation, hardware model, and even operating system version. Created by </span><a href="https://www.linkedin.com/in/parishkhan/"><span>Parish Khan</span></a><span>, RetinaDesk provides a convenient online lookup tool that lets you quickly check how many external displays a Mac, iPad, or iPhone supports, along with maximum resolution, refresh rate, extended display support, mirroring capabilities, and more.</span></p><p><span>For developers working with multi-display setups, Stage Manager, or external display features, this is a handy reference that makes it much easier to verify device capabilities without digging through Apple&#8217;s technical specifications.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-07"><span>Agent Island</span></a></strong></h3><p><span>Agent Island is an open-source local monitoring tool created by </span><a href="https://x.com/tngzhy658431902"><span>Tristan Tang</span></a><span>. It continuously monitors the local session files generated by Claude Code and Codex, determines their current state in real time, and displays intuitive status updates and notifications through a Dynamic Island-style menu bar interface, so you no longer need to keep watching your terminal. It can also automatically execute predefined follow-up actions once your AI model usage window resets, helping long-running tasks resume seamlessly.</span></p><p><span>The project follows a local-first design, requiring no cloud services and uploading no conversation data. It also provides token usage statistics, quota reset countdowns, and weekly/monthly usage reports.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-147?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#28909;&#33590;&#36824;&#26159;&#20912;&#21654;&#21857;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-147/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#25105;&#25152;&#22312;&#30340;&#22478;&#24066;&#65292;&#27668;&#28201;&#19981;&#26029;&#21047;&#26032;&#21382;&#21490;&#32426;&#24405;&#12290;&#20174; 7 &#26376;&#26411;&#24320;&#22987;&#65292;&#20415;&#38519;&#20837;&#20102;&#25345;&#32493;&#21313;&#22825;&#20197;&#19978;&#12289;&#36229;&#36807; 30 &#25668;&#27663;&#24230;&#30340;&#39640;&#28201;&#37239;&#26257;&#12290;&#23613;&#31649;&#20174;&#32477;&#23545;&#25968;&#20540;&#19978;&#30475;&#24182;&#19981;&#31639;&#24778;&#20154;&#65292;&#20294;&#37197;&#19978;&#36229;&#36807; 80% &#30340;&#28287;&#24230;&#65292;&#21363;&#20415;&#20840;&#22825;&#24453;&#22312; 25 &#24230;&#30340;&#31354;&#35843;&#25151;&#37324;&#65292;&#20307;&#20869;&#20381;&#28982;&#33021;&#25874;&#20986;&#19968;&#32929;&#25381;&#20043;&#19981;&#21435;&#30340;&#29157;&#28909;&#12290;</span></p><p><span>&#25105;&#20250;&#36890;&#36807;&#21917;&#33590;&#12289;&#21917;&#21654;&#21857;&#26469;&#25913;&#21892;&#8220;&#20307;&#24863;&#8221;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#21807;&#26377;&#28909;&#33590;&#33021;&#24102;&#32473;&#25105;&#19968;&#31181;&#28909;&#37327;&#38543;&#27735;&#27700;&#37322;&#25918;&#30340;&#36890;&#36879;&#24863;&#65292;&#32780;&#20063;&#21807;&#26377;&#20912;&#21654;&#21857;&#33021;&#24102;&#26469;&#29255;&#21051;&#30452;&#25130;&#20102;&#24403;&#30340;&#28165;&#20937;&#12290;&#25105;&#24819;&#65292;&#36825;&#26410;&#24517;&#26159;&#39278;&#21697;&#26412;&#36523;&#30340;&#29289;&#29702;&#29305;&#24615;&#20351;&#28982;&#65292;&#25110;&#35768;&#26356;&#22810;&#26159;&#38271;&#26399;&#39278;&#39135;&#20064;&#24815;&#22312;&#24515;&#20013;&#30041;&#19979;&#30340;&#24515;&#29702;&#26263;&#31034;&#12290;</span></p><p><span>&#20013;&#22269;&#26377;&#21477;&#32769;&#35805;&#21483;&#8220;&#24515;&#38745;&#33258;&#28982;&#20937;&#8221;&#12290;&#25105;&#33258;&#35748;&#36824;&#27809;&#36798;&#21040;&#36825;&#33324;&#36229;&#33073;&#30340;&#24515;&#22659;&#65292;&#29616;&#38454;&#27573;&#20173;&#20813;&#19981;&#20102;&#20511;&#21161;&#36825;&#20123;&#26479;&#20013;&#29289;&#65292;&#22312;&#20919;&#28909;&#20043;&#38388;&#23547;&#24471;&#19968;&#28857;&#24179;&#34913;&#12290;</span></p><p><span>&#20294;&#24895;&#36825;&#20010;&#38391;&#28909;&#30340;&#22799;&#22825;&#65292;&#33021;&#26089;&#28857;&#22797;&#24402;&#24120;&#24577;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-146/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/liquid-glass-a-field-guide-to-uikit-compatibility-pitfalls/?utm_source=fatbobman%20weekly%20issue%20147&amp;utm_medium=web"><span>Liquid Glass&#65306;UIKit &#36866;&#37197;&#36393;&#22353;&#23454;&#24405;</span></a></strong></h3><p><span>Liquid Glass &#22312;&#24102;&#26469;&#20840;&#26032;&#20132;&#20114;&#20307;&#39564;&#30340;&#21516;&#26102;&#65292;&#20063;&#35753; UIKit &#30340;&#20860;&#23481;&#24615;&#21464;&#24471;&#26356;&#21152;&#22797;&#26434;&#12290;&#21516;&#19968;&#22871; UI&#65292;&#22312; iOS 18&#12289;iOS 26 &#19982; iOS 27 &#19978;&#21487;&#33021;&#34920;&#29616;&#20986;&#25130;&#28982;&#19981;&#21516;&#30340;&#34892;&#20026;&#65307;&#19981;&#21516;&#30340; API &#32452;&#21512;&#19982;&#23454;&#29616;&#26041;&#24335;&#65292;&#20063;&#21487;&#33021;&#35302;&#21457;&#21508;&#24335;&#21508;&#26679;&#30340;&#20860;&#23481;&#24615;&#38382;&#39064;&#12290;</span><a href="https://x.com/Megabits_mzq"><span>Megabits</span></a><span> &#32467;&#21512;&#30495;&#23454;&#39033;&#30446;&#32463;&#39564;&#65292;&#24635;&#32467;&#20102; UIKit &#19979; Sheet&#12289;Navigation&#12289;Popover&#12289;Toolbar &#31561;&#22810;&#20010;&#20856;&#22411;&#22330;&#26223;&#20013;&#30340;&#36866;&#37197;&#38519;&#38449;&#65292;&#24182;&#20998;&#26512;&#20102; </span><code>UIBarButtonItem</code><span>&#12289;</span><code>CABackdropLayer</code><span>&#12289;Scroll Edge Effect &#31561;&#24213;&#23618;&#34892;&#20026;&#65292;&#32473;&#20986;&#20102;&#23545;&#24212;&#30340;&#35299;&#20915;&#26041;&#26696;&#19982;&#21487;&#36816;&#34892; Demo&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-01"><span>&#20004;&#24230;&#32472;&#21046;&#30340;&#20687;&#32032;&#28210;&#26579;&#22320;&#22270; (The Map, Drawn Twice)</span></a></strong></h3><p><span>Apple &#30340; UI &#28210;&#26579;&#20307;&#31995;&#28041;&#21450; Core Graphics&#12289;Core Text&#12289;Core Image&#12289;Core Animation &#19982; SwiftUI &#31561;&#22810;&#20010;&#23618;&#27425;&#65292;&#24320;&#21457;&#32773;&#34429;&#28982;&#32463;&#24120;&#20351;&#29992;&#36825;&#20123;&#26694;&#26550;&#65292;&#21364;&#26410;&#24517;&#30495;&#27491;&#29702;&#35299;&#23427;&#20204;&#21508;&#33258;&#25215;&#25285;&#30340;&#32844;&#36131;&#12290;&#22312; Apple UI Insider &#30340;&#21019;&#21002;&#21495;&#20013;&#65292;</span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#32472;&#21046;&#20102;&#19968;&#24352;&#20174; Swift &#20195;&#30721;&#21040;&#26368;&#32456;&#20687;&#32032;&#30340;&#32844;&#36131;&#22320;&#22270;&#12290;</span></p><p><span>Mihaela &#37319;&#29992;&#20102;&#19968;&#31181;&#24456;&#26377;&#24847;&#24605;&#30340;&#39564;&#35777;&#26041;&#24335;&#65306;&#27599;&#19968;&#24352;&#25554;&#22270;&#37117;&#30001;&#21516;&#19968;&#20221;&#22330;&#26223;&#25551;&#36848;&#29983;&#25104;&#20004;&#27425;&#65292;&#19968;&#27425;&#20132;&#32473;&#33258;&#24049;&#23454;&#29616;&#30340; clean-room &#28210;&#26579;&#24341;&#25806;&#65292;&#21478;&#19968;&#27425;&#20132;&#32473; Apple &#30340; Core Graphics&#65292;&#20877;&#36880;&#20687;&#32032;&#27604;&#36739;&#20004;&#32773;&#30340;&#36755;&#20986;&#12290;&#23613;&#31649;&#32422;&#26377;&#19968;&#21322;&#20687;&#32032;&#23384;&#22312;&#24046;&#24322;&#65292;&#20294;&#24179;&#22343;&#20687;&#32032;&#24046;&#24322;&#20165;&#32422;&#20026; 0.1%&#65292;&#35270;&#35273;&#25928;&#26524;&#20960;&#20046;&#23436;&#20840;&#19968;&#33268;&#12290;&#36825;&#31181;&#36890;&#36807;&#29420;&#31435;&#23454;&#29616;&#12289;&#21487;&#22797;&#29616;&#23454;&#39564;&#21644;&#37327;&#21270;&#32467;&#26524;&#26469;&#30740;&#31350;&#31995;&#32479;&#34892;&#20026;&#30340;&#26041;&#27861;&#65292;&#27604;&#25991;&#31456;&#26412;&#36523;&#20171;&#32461;&#30340;&#20869;&#23481;&#26356;&#20540;&#24471;&#20851;&#27880;&#65292;&#20063;&#35753;&#20154;&#26356;&#21152;&#26399;&#24453;&#36825;&#19968;&#31995;&#21015;&#21518;&#32493;&#30340;&#30740;&#31350;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-02"><span>&#32456;&#20110;&#20026; .fixedSize &#25214;&#21040;&#20102;&#21512;&#36866;&#22330;&#26223; (Finally found a use case for .fixedSize)</span></a></strong></h3><p><code>.fixedSize</code><span> &#26159; SwiftUI &#20013;&#19968;&#20010;&#32463;&#24120;&#34987;&#24573;&#35270;&#30340; modifier&#65292;&#19981;&#23569;&#24320;&#21457;&#32773;&#23545;&#23427;&#30340;&#21360;&#35937;&#20173;&#20572;&#30041;&#22312;&#36991;&#20813;&#25991;&#26412;&#25240;&#34892;&#31561;&#23569;&#25968;&#22330;&#26223;&#12290;&#8288;</span><a href="https://www.linkedin.com/in/engomarelsayed"><span>Omar Elsayed</span></a><span> &#20174;&#19968;&#20010;&#24456;&#24120;&#35265;&#30340;&#38656;&#27714;&#20986;&#21457;&#65306;&#22914;&#20309;&#35753;&#27178;&#21521; </span><code>ScrollView</code><span> &#20013;&#25152;&#26377;&#21345;&#29255;&#37117;&#19982;&#26368;&#39640;&#30340;&#37027;&#19968;&#39033;&#20445;&#25345;&#30456;&#21516;&#39640;&#24230;&#65292;&#20998;&#20139;&#20102;&#33258;&#24049;&#20511;&#21161; </span><code>.fixedSize</code><span> &#25214;&#21040;&#35299;&#20915;&#26041;&#26696;&#30340;&#36807;&#31243;&#12290;</span></p><blockquote><p><span>&#25110;&#35768; </span><code>.fixedSize</code><span> &#19968;&#30452;&#27809;&#26377;&#24471;&#21040;&#24191;&#27867;&#20351;&#29992;&#65292;&#19982;&#23427;&#30053;&#26174;&#25277;&#35937;&#30340;&#21629;&#21517;&#20063;&#26377;&#19968;&#23450;&#20851;&#31995;&#12290;&#31350;&#31455;&#22266;&#23450;&#30340;&#26159;&#20160;&#20040;&#65311;&#23545;&#24212;&#30340; size &#21448;&#26159;&#20160;&#20040;&#65311;&#22914;&#26524;&#24819;&#28145;&#20837;&#29702;&#35299;&#23427;&#20026;&#20309;&#33021;&#22815;&#25913;&#21464;&#24067;&#23616;&#32467;&#26524;&#65292;&#21487;&#20197;&#21442;&#38405;&#25105;&#20043;&#21069;&#20889;&#30340;&#12298;&#8288;</span><a href="https://fatbobman.com/zh/posts/layout-dimensions-1/"><span>SwiftUI &#24067;&#23616;&#65306;&#23610;&#23544;</span></a><span>&#12299;&#31995;&#21015;&#65292;&#20854;&#20013;&#36890;&#36807;&#23454;&#29616; </span><code>fixedSize</code><span> &#30340;&#22797;&#21046;&#21697;&#65292;&#25286;&#35299;&#20102;&#23427;&#22312; SwiftUI &#24067;&#23616;&#21327;&#21830;&#20013;&#30340;&#24037;&#20316;&#26426;&#21046;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-03"><span>&#20851;&#20110; LazyVStack &#24067;&#23616;&#26426;&#21046;&#30340;&#20004;&#27425;&#26377;&#36259;&#25506;&#32034;</span></a></strong></h3><p><span>&#22312; Apple Developer Forums &#19978;&#65292;&#8288;</span><a href="https://developer.apple.com/forums/profile/alextar04"><span>alextar04</span></a><span> &#36830;&#32493;&#21457;&#24067;&#20102;&#20004;&#31687;&#20851;&#20110; </span><code>LazyVStack</code><span> &#30340;&#20998;&#26512;&#24086;&#12290;&#20004;&#31687;&#24086;&#23376;&#20998;&#21035;&#22260;&#32469;&#24555;&#36895;&#28378;&#21160;&#26102;&#21487;&#33021;&#20986;&#29616;&#30340;&#31354;&#30333;&#21306;&#22495;&#19982; Cell &#25130;&#26029;&#65292;&#20197;&#21450; </span><code>GeometryReader</code><span> &#22312; </span><code>LazyVStack</code><span> &#20013;&#33719;&#21462;&#21040;&#30340;&#23610;&#23544;&#20026;&#20309;&#20250;&#22810;&#27425;&#21464;&#21270;&#23637;&#24320;&#65288;&#8288;</span><a href="https://developer.apple.com/forums/thread/839688"><span>&#24086;&#23376; 2</span></a><span>&#65289;&#12290;&#20316;&#32773;&#19981;&#20165;&#25552;&#20379;&#20102;&#26368;&#23567;&#22797;&#29616;&#24037;&#31243;&#65292;&#36824;&#32467;&#21512; WWDC 26 &#20851;&#20110; Lazy Stack &#30340;&#20171;&#32461;&#12289;SwiftUI &#26085;&#24535;&#20197;&#21450;&#23454;&#39564;&#32467;&#26524;&#65292;&#23581;&#35797;&#36824;&#21407; SwiftUICore &#24213;&#23618;&#65288;&#22914;&#31526;&#21495;&#35745;&#31639;&#19982; CA::Transaction &#25552;&#20132;&#39564;&#35777;&#65289;&#22312;&#20272;&#31639;&#23610;&#23544;&#12289;&#26657;&#39564;&#24067;&#23616;&#26102;&#21487;&#33021;&#37319;&#29992;&#30340;&#24037;&#20316;&#26041;&#24335;&#65292;&#24182;&#25454;&#27492;&#35299;&#37322;&#36825;&#20123;&#29616;&#35937;&#20135;&#29983;&#30340;&#21407;&#22240;&#12290;</span></p><blockquote><p><span>&#36825;&#20004;&#31687;&#24086;&#23376;&#20063;&#20174;&#21478;&#19968;&#20010;&#35282;&#24230;&#23637;&#29616;&#20102; </span><code>List</code><span> &#19982; </span><code>LazyVStack</code><span> &#22312;&#35774;&#35745;&#29702;&#24565;&#19978;&#30340;&#24046;&#24322;&#12290;&#20316;&#32773;&#25512;&#27979;&#65292;</span><code>LazyVStack</code><span> &#20026;&#20102;&#23454;&#29616;&#25042;&#24067;&#23616;&#65292;&#20250;&#22312;&#37096;&#20998;&#22330;&#26223;&#19979;&#20381;&#36182;&#23610;&#23544;&#20272;&#31639;&#31561;&#26426;&#21046;&#65292;&#22240;&#27492;&#19982; </span><code>List</code><span> &#21576;&#29616;&#20986;&#19981;&#21516;&#30340;&#34892;&#20026;&#12290;&#36825;&#20063;&#35828;&#26126;&#20102;&#20026;&#20160;&#20040;&#20004;&#32773;&#24182;&#19981;&#23384;&#22312;&#32477;&#23545;&#30340;&#20248;&#21155;&#65292;&#32780;&#26159;&#8288;</span><a href="https://fatbobman.com/zh/posts/list-or-lazyvstack/"><span>&#21508;&#33258;&#36866;&#29992;&#20110;&#19981;&#21516;&#30340;&#22330;&#26223;</span></a><span>&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-08"><span>Swift on Windows&#65306;&#19968;&#24180;&#30340;&#25171;&#30952;&#19982;&#23436;&#21892; (Swift on Windows: A year of refinement)</span></a></strong></h3><p><span>Swift on Windows &#22312;&#19968;&#24180;&#21069;&#24050;&#32463;&#33021;&#22815;&#25903;&#25745;&#30495;&#23454;&#30340;&#29983;&#20135;&#24212;&#29992;&#65292;&#20294;&#8220;&#21487;&#20197;&#36816;&#34892;&#8221;&#24182;&#19981;&#31561;&#20110;&#8220;&#36275;&#22815;&#21487;&#39044;&#27979;&#8221;&#12290;&#8288;</span><a href="https://x.com/browsercompany"><span>The Browser Company</span></a><span> &#19982; Apple &#21450; Swift &#31038;&#21306;&#23558;&#37325;&#28857;&#25918;&#22312;&#20102;&#22522;&#30784;&#35774;&#26045;&#30340;&#25171;&#30952;&#19978;&#65306;&#20351;&#29992;&#29616;&#20195; CMake &#37325;&#26500; Runtime &#26500;&#24314;&#31995;&#32479;&#65292;&#25512;&#20986; Experimental Swift SDK&#65292;&#26126;&#30830;&#38745;&#24577;&#19982;&#21160;&#24577;&#38142;&#25509;&#27169;&#22411;&#65292;&#24182;&#25913;&#21892;&#22810;&#24037;&#20855;&#38142;&#29615;&#22659;&#20013;&#30340; Runtime &#36873;&#25321;&#19982;&#20998;&#21457;&#38382;&#39064;&#12290;</span></p><p><span>&#30495;&#27491;&#25512;&#21160;&#36328;&#24179;&#21488;&#25104;&#29087;&#24230;&#25552;&#21319;&#30340;&#65292;&#24448;&#24448;&#19981;&#26159;&#26576;&#20010;&#24341;&#20154;&#27880;&#30446;&#30340;&#26032;&#29305;&#24615;&#65292;&#32780;&#26159;&#36825;&#20123;&#23481;&#26131;&#34987;&#24573;&#35270;&#30340;&#24037;&#31243;&#32454;&#33410;&#65306;&#26500;&#24314;&#37197;&#32622;&#26159;&#21542;&#21487;&#23457;&#35745;&#12289;Runtime &#33021;&#21542;&#31934;&#30830;&#32465;&#23450;&#12289;&#24037;&#20855;&#26159;&#21542;&#21487;&#20197;&#29420;&#31435;&#20998;&#21457;&#65292;&#20197;&#21450; CI &#19982;&#24320;&#21457;&#29615;&#22659;&#33021;&#21542;&#22987;&#32456;&#20445;&#25345;&#19968;&#33268;&#12290;&#36825;&#31687;&#25991;&#31456;&#24456;&#22909;&#22320;&#23637;&#31034;&#20102; Swift &#22312; Windows &#24179;&#21488;&#36807;&#21435;&#19968;&#24180;&#26368;&#37325;&#35201;&#30340;&#36827;&#27493;&#65292;&#26356;&#22810;&#26469;&#33258;&#24037;&#31243;&#33021;&#21147;&#30340;&#25345;&#32493;&#25171;&#30952;&#65292;&#32780;&#38750;&#21151;&#33021;&#19978;&#30340;&#25193;&#24352;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-04"><span>MemoProperty&#65306;&#22312; SwiftUI &#20013;&#22797;&#29992;&#26377;&#29366;&#24577;&#19994;&#21153;&#36923;&#36753; (Memo Property: Reusing More Stateful Business Logic for SwiftUI Views)</span></a></strong></h3><p><span>&#22312; </span><a href="https://github.com/vanvoorden/TaskProperty"><span>TaskProperty</span></a><span> &#20013;&#65292;</span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> &#23637;&#31034;&#20102;&#22914;&#20309;&#20511;&#21161;&#33258;&#23450;&#20041; </span><code>DynamicProperty</code><span>&#65292;&#23558;&#24102;&#26377;&#29983;&#21629;&#21608;&#26399;&#21644;&#29366;&#24577;&#30340;&#19994;&#21153;&#36923;&#36753;&#20174; View &#20013;&#25277;&#31163;&#20986;&#26469;&#12290;&#26412;&#25991;&#27839;&#30528;&#30456;&#21516;&#30340;&#24605;&#36335;&#32487;&#32493;&#21521;&#21069;&#65292;&#32467;&#21512; Swift &#26368;&#26032;&#30340;&#21442;&#25968;&#21253;&#65288;Parameter Packs / Variadic Generics&#65289;&#31561;&#21069;&#27839;&#35821;&#27861;&#65292;&#23581;&#35797;&#22312; SwiftUI &#20013;&#23454;&#29616;&#19968;&#20010;&#31867;&#20284; React </span><code>useMemo</code><span> &#30340;&#26426;&#21046;&#65306;&#21482;&#26377;&#24403;&#26174;&#24335;&#22768;&#26126;&#30340;&#20381;&#36182;&#21457;&#29983;&#21464;&#21270;&#26102;&#65292;&#25165;&#37325;&#26032;&#25191;&#34892;&#36807;&#28388;&#12289;&#25490;&#24207;&#31561;&#35745;&#31639;&#65292;&#21542;&#21017;&#30452;&#25509;&#22797;&#29992;&#27492;&#21069;&#32531;&#23384;&#30340;&#32467;&#26524;&#65292;&#36991;&#20813; View &#22240;&#26080;&#20851;&#29366;&#24577;&#21464;&#21270;&#32780;&#37325;&#22797;&#23436;&#25104;&#26114;&#36149;&#24037;&#20316;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-05"><span>&#22810;&#27969;&#32534;&#36753;&#19979;&#30340;&#29366;&#24577;&#21516;&#27493;&#65306;&#26500;&#24314;&#27169;&#22411;&#19982; UI &#20043;&#38388;&#32570;&#22833;&#30340;&#8220;&#25237;&#24433;&#23618;&#8221; (One Model Object, Multiple Editing Flows: The Missing Layer Between Model and UI)</span></a></strong></h3><p><span>Observation &#20986;&#29616;&#20043;&#21518;&#65292;&#19981;&#23569;&#24320;&#21457;&#32773;&#24320;&#22987;&#35748;&#20026; Combine &#22312; SwiftUI &#20013;&#24050;&#32463;&#36880;&#28176;&#22833;&#21435;&#20215;&#20540;&#12290;</span><a href="https://www.linkedin.com/in/sergey-tristan/"><span>Sergey Tristan</span></a><span> &#30340;&#36825;&#31687;&#25991;&#31456;&#21017;&#25552;&#20379;&#20102;&#19968;&#20010;&#19981;&#21516;&#30340;&#35270;&#35282;&#65306;&#24403;&#21516;&#19968;&#20010;&#27169;&#22411;&#23545;&#35937;&#38656;&#35201;&#34987;&#22810;&#20010;&#29420;&#31435;&#30340;&#32534;&#36753;&#27969;&#31243;&#20849;&#20139;&#65292;&#24182;&#19988;&#27599;&#20010;&#27969;&#31243;&#21482;&#20851;&#24515;&#20854;&#20013;&#19968;&#37096;&#20998;&#29366;&#24577;&#26102;&#65292;Observation &#36127;&#36131;&#39640;&#25928;&#22320;&#24863;&#30693;&#21464;&#21270;&#65292;&#32780; Combine &#26356;&#36866;&#21512;&#25215;&#25285;&#25968;&#25454;&#32452;&#21512;&#12289;&#36716;&#25442;&#19982;&#25345;&#32493;&#21516;&#27493;&#30340;&#32844;&#36131;&#65292;&#20004;&#32773;&#24182;&#38750;&#26367;&#20195;&#20851;&#31995;&#65292;&#32780;&#26159;&#21487;&#20197;&#21508;&#21496;&#20854;&#32844;&#12290;</span></p><p><span>&#25991;&#31456;&#25552;&#20986;&#20102;&#19968;&#20010;&#20301;&#20110; Model &#19982; UI &#20043;&#38388;&#30340; Projection &#27010;&#24565;&#65292;&#23558;&#19968;&#20010;&#25110;&#22810;&#20010;&#25345;&#32493;&#21464;&#21270;&#30340;&#25968;&#25454;&#28304;&#36716;&#25442;&#20026;&#19981;&#21516;&#28040;&#36153;&#32773;&#25152;&#38656;&#30340;&#21709;&#24212;&#24335;&#34920;&#31034;&#12290;&#26080;&#35770;&#26159;&#21542;&#35748;&#21516;&#36825;&#31181;&#26550;&#26500;&#65292;&#23427;&#37117;&#25552;&#20986;&#20102;&#19968;&#20010;&#20540;&#24471;&#24605;&#32771;&#30340;&#38382;&#39064;&#65306;&#24403;&#24212;&#29992;&#24320;&#22987;&#25317;&#26377;&#36234;&#26469;&#36234;&#22810;&#29420;&#31435;&#21364;&#21448;&#30456;&#20114;&#20851;&#32852;&#30340;&#32534;&#36753;&#27969;&#31243;&#26102;&#65292;&#26159;&#21542;&#38656;&#35201;&#19968;&#31181;&#19981;&#21516;&#20110; DTO&#12289;ViewModel &#25110; Observation &#30340;&#25277;&#35937;&#26469;&#32452;&#32455;&#36825;&#20123;&#25345;&#32493;&#28436;&#21270;&#30340;&#25968;&#25454;&#27969;&#65311;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0147-06"><span>Apple &#22806;&#25509;&#26174;&#31034;&#22120;&#25903;&#25345;&#26597;&#35810;</span></a></strong></h3><p><span>&#33529;&#26524;&#35774;&#22791;&#23545;&#22806;&#25509;&#26174;&#31034;&#22120;&#30340;&#25903;&#25345;&#19968;&#30452;&#27604;&#36739;&#22797;&#26434;&#65292;&#19981;&#21516;&#33455;&#29255;&#12289;&#19981;&#21516;&#26426;&#22411;&#65292;&#29978;&#33267;&#19981;&#21516;&#31995;&#32479;&#29256;&#26412;&#20043;&#38388;&#37117;&#23384;&#22312;&#26126;&#26174;&#24046;&#24322;&#12290;&#30001; </span><a href="https://www.linkedin.com/in/parishkhan/"><span>Parish Khan</span></a><span> &#21019;&#24314;&#30340; RetinaDesk &#25552;&#20379;&#20102;&#19968;&#20010;&#22312;&#32447;&#26597;&#35810;&#24037;&#20855;&#65292;&#21487;&#20197;&#24555;&#36895;&#20102;&#35299; Mac&#12289;iPad&#12289;iPhone &#31561;&#35774;&#22791;&#25903;&#25345;&#30340;&#22806;&#25509;&#26174;&#31034;&#22120;&#25968;&#37327;&#12289;&#26368;&#39640;&#20998;&#36776;&#29575;&#12289;&#21047;&#26032;&#29575;&#65292;&#20197;&#21450;&#26159;&#21542;&#25903;&#25345;&#25193;&#23637;&#26174;&#31034;&#12289;&#38236;&#20687;&#27169;&#24335;&#31561;&#20449;&#24687;&#12290;</span></p><p><span>&#23545;&#20110;&#38656;&#35201;&#27979;&#35797;&#22810;&#23631;&#26174;&#31034;&#12289;Stage Manager &#25110;&#22806;&#25509;&#26174;&#31034;&#22120;&#30456;&#20851;&#21151;&#33021;&#30340;&#24320;&#21457;&#32773;&#65292;&#36825;&#20063;&#26159;&#19968;&#20010;&#24456;&#26041;&#20415;&#30340;&#21442;&#32771;&#24037;&#20855;&#65292;&#33021;&#22815;&#24555;&#36895;&#30830;&#35748;&#19981;&#21516;&#35774;&#22791;&#32452;&#21512;&#30340;&#33021;&#21147;&#36793;&#30028;&#65292;&#32780;&#26080;&#38656;&#36880;&#19968;&#26597;&#38405; Apple &#23448;&#26041;&#25216;&#26415;&#35268;&#26684;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0147-07"><span>Agent Island</span></a></strong></h3><p><span>Agent Island &#26159;&#19968;&#20010;&#30001; &#8288;</span><a href="https://x.com/tngzhy658431902"><span>Tristan Tang</span></a><span> &#24320;&#21457;&#30340;&#24320;&#28304;&#26412;&#22320;&#29366;&#24577;&#30417;&#35270;&#24037;&#20855;&#65292;&#23427;&#20250;&#25345;&#32493;&#35835;&#21462; Claude Code &#19982; Codex &#22312;&#26412;&#22320;&#29983;&#25104;&#30340;&#20250;&#35805;&#35760;&#24405;&#65292;&#23454;&#26102;&#21028;&#26029;&#24403;&#21069;&#29366;&#24577;&#65292;&#24182;&#36890;&#36807;&#33756;&#21333;&#26639;&#20013;&#30340;&#8220;&#28789;&#21160;&#23707;&#8221;&#26679;&#24335;&#32452;&#20214;&#25552;&#20379;&#30452;&#35266;&#30340;&#29366;&#24577;&#26174;&#31034;&#19982;&#25552;&#37266;&#65292;&#35753;&#24320;&#21457;&#32773;&#26080;&#38656;&#19968;&#30452;&#30447;&#30528;&#32456;&#31471;&#12290;&#23427;&#36824;&#25903;&#25345;&#22312; AI &#27169;&#22411;&#39069;&#24230;&#31383;&#21475;&#37325;&#32622;&#21518;&#33258;&#21160;&#25191;&#34892;&#39044;&#35774;&#30340;&#21518;&#32493;&#25805;&#20316;&#65292;&#24110;&#21161;&#38271;&#26102;&#38388;&#36816;&#34892;&#30340;&#20219;&#21153;&#26356;&#39034;&#30021;&#22320;&#34900;&#25509;&#19979;&#21435;&#12290;</span></p><p><span>&#39033;&#30446;&#37319;&#29992; Local-first &#35774;&#35745;&#65292;&#19981;&#20381;&#36182;&#20113;&#31471;&#26381;&#21153;&#65292;&#19981;&#19978;&#20256;&#20219;&#20309;&#20250;&#35805;&#20869;&#23481;&#65292;&#21516;&#26102;&#25552;&#20379; Token &#20351;&#29992;&#32479;&#35745;&#12289;&#39069;&#24230;&#37325;&#32622;&#20498;&#35745;&#26102;&#12289;&#21608;/&#26376;&#25253;&#21578;&#31561;&#21151;&#33021;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #146]]></title><description><![CDATA[It's Not That the Models Are Slower&#8212;The Tasks Have Become Bigger]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 27 Jul 2026 12:04:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bnF_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bnF_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bnF_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 424w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 848w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1272w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp" width="1456" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:209726,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/208633411?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bnF_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 424w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 848w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1272w, https://substackcdn.com/image/fetch/$s_!bnF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e95f65d-811e-42f7-89d8-cf9bd876ceff_1920x950.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@wouterdepraetere?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Wouter De Praetere</a><span> on </span><a href="https://unsplash.com/photos/a-close-up-of-a-snail-on-a-table-ELfMdIihkTg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>It&#8217;s Not That the Models Are Slower&#8212;The Tasks Have Become Bigger</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-146/">Read on web &#8594;</a></p><p><span>Lately, even tasks that I consider relatively simple often take AI several minutes&#8212;or sometimes even tens of minutes&#8212;to complete. It gave me the impression that as models become more capable, they somehow have to become slower.</span></p><p><span>In reality, the main reason lies with me. Although today&#8217;s AI agents let us choose different models and reasoning levels, it&#8217;s much easier&#8212;and often more reliable&#8212;to simply hand even straightforward tasks to the most capable models. At the same time, modern agents no longer limit themselves to the small change you explicitly requested. They proactively expand their search, analyze whether the modification could affect other parts of the project, and try to identify potential issues before they happen. The models may be more powerful than ever, but they&#8217;re also taking on substantially more work for every task.</span></p><p><span>There&#8217;s another factor as well. As my trust in these models has grown, so has the scope of the tasks I assign to them. What used to be &#8220;refactor a function&#8221; or &#8220;improve a screen&#8221; has gradually become &#8220;implement a feature,&#8221; &#8220;build a module,&#8221; or even &#8220;create an entire product.&#8221; Without realizing it, I&#8217;ve started treating AI agents as genuine collaborators. The pace at which model performance improves simply hasn&#8217;t kept up with the way we now use them.</span></p><p><span>In other words, developers are no longer pursuing only &#8220;writing code faster.&#8221; Increasingly, we&#8217;re using AI to </span><strong><span>write better code, even if it takes longer</span></strong><span>.</span></p><p><span>The shift from question-answering to task delivery has happened in just a single year. As we grow accustomed to waking up and reviewing completed work, the real bottleneck is quietly moving elsewhere. We used to ask whether a model was capable of completing a task. Today, the more important questions are how to define a clear, verifiable objective, and how to reduce the cost of achieving it. AI is becoming more like a teammate, and the ability to organize and decompose work effectively is becoming the next competitive advantage.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-145/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-01"><span>Bluetooth without the delegate dance</span></a></strong></h3><p><span>Delegates remain a challenge many developers continue to face years after the introduction of Swift Concurrency. Not only do they often lead to cumbersome code organization, but under Swift 6&#8217;s strict concurrency checking they also become increasingly difficult to integrate naturally with modern concurrent code. </span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> leverages Swift 6.2&#8217;s Custom Executor to bind CoreBluetooth&#8217;s callback queue directly to an Actor&#8217;s execution context, allowing delegate callbacks to run naturally within Actor isolation without additional locks, thread hopping, or synchronization logic.</span></p><blockquote><p><span>Custom Executor allows an Actor&#8217;s tasks to run on a designated executor, making it a powerful tool for bridging traditional callback-based APIs with Swift Concurrency. If you&#8217;re facing similar migration or abstraction challenges, this implementation is well worth studying. I also explored this topic in depth using Core Data as an example in </span><a href="https://fatbobman.com/en/posts/core-data-reform-achieving-elegant-concurrency-operations-like-swiftdata/"><span>this article</span></a><span>, explaining how to bind traditional serial queues to Actor executors for seamless integration with Swift Concurrency.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-02"><span>Working with Xcode on CI</span></a></strong></h3><p><span>As more developers adopt self-hosted macOS runners or cloud-based CI, reliably managing Xcode, Simulator Runtimes, and code-signing environments has become an essential part of engineering infrastructure. </span><a href="https://mastodon.social/@rodionovd"><span>Dmitry Rodionov</span></a><span> shares a collection of practical techniques for using the Xcode CLI in CI, including managing multiple Xcode installations with </span><code>DEVELOPER_DIR</code><span> instead of </span><code>xcode-select</code><span>, automating the installation and cleanup of Simulator Runtimes and Metal Toolchains, and reducing unnecessary recompilation during branch switching with Compilation Caching.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-03"><span>Squeeze every last bit of value out of GitHub Actions</span></a></strong></h3><p><span>Optimizing GitHub Actions doesn&#8217;t necessarily mean more aggressive caching, more complex workflows, or additional conditional logic. Instead, this article advocates a more valuable principle: every CI run should match the actual risk introduced by a change. Starting from the investigation of an apparently ordinary flaky test, </span><a href="https://x.com/rbbtsn0w"><span>Snow</span></a><span> discusses how deterministic tests eliminate unnecessary reruns, how portable checks can be moved to Linux while leaving Xcode-dependent validation to macOS, and how Build, Test, or Build for Testing can be selected dynamically based on change risk to avoid wasting expensive runner time.</span></p><blockquote><p><span>I particularly agree with one of the article&#8217;s core ideas: the goal of CI is not to &#8220;run more,&#8221; but to &#8220;answer the right questions.&#8221; Every expensive macOS build should validate a risk that a cheaper runner cannot, and every failure should provide actionable information that helps move the project forward.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-04"><span>Building adaptive non-modal panels in SwiftUI</span></a></strong></h3><p><span>Starting with WWDC26, iPhone-only apps running through iPhone Mirroring on a Mac or on an iPad enter a resizable environment. This means relying solely on </span><code>horizontalSizeClass</code><span> for layout decisions is becoming increasingly unreliable. </span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> demonstrates how to build an adaptive non-modal panel by recording scene size and safe-area insets at the root using </span><code>onGeometryChange</code><span>, then choosing between bottom and side presentations based on the actual available width. One particularly useful technique is preserving the resolved layout cache during dragging, preventing adaptive content from changing size due to repeated measurements.</span></p><blockquote><p><span>If your app is iPhone-only but still has users running it on iPad or macOS, layout adaptation deserves much more attention going forward. As discussed in </span><a href="https://fatbobman.com/en/posts/from-size-class-to-available-space/"><span>From Size Class to Available Space</span></a><span>, the era of resizable canvases no longer guarantees developers absolute control over interface layouts, instead giving users much greater control over how apps are presented.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-05"><span>SwiftUI @ContentBuilder - Faster Type Checking in Xcode 27</span></a></strong></h3><p><span>Xcode 27 introduces the new </span><code>@ContentBuilder</code><span>. Although it is currently just a type alias for </span><code>ViewBuilder</code><span>, Apple has begun recommending this new name in its latest SwiftUI APIs. </span><a href="https://x.com/sagarunagar_"><span>Sagar Unagar</span></a><span> explains the change and notes that, for most applications, there is no need to immediately replace every </span><code>@ViewBuilder</code><span> with </span><code>@ContentBuilder</code><span>, as existing code already benefits from the compiler improvements introduced in Xcode 27.</span></p><blockquote><p><span>I haven&#8217;t written much SwiftUI code recently, so I haven&#8217;t yet experienced firsthand whether this change significantly improves compilation performance. That said, in previous projects I often noticed Xcode struggling with type inference and code completion whenever different builder content was mixed inside a </span><code>ViewBuilder</code><span>, especially with APIs like Table and Charts. If Xcode 27 truly improves these scenarios, then this change represents much more than just a new builder name.</span></p></blockquote><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-06"><span>tswift: A Lightweight Swift Runtime Built with Rust</span></a></strong></h3><p><span>Without relying on the Swift toolchain, LLVM, code generation, or any C dependencies, tswift can parse, semantically analyze, and execute Swift source code. Developed by </span><a href="https://github.com/siuying"><span>Francis Chong</span></a><span>, tswift implements the Swift frontend entirely in Rust, handling lexical, syntactic, and semantic analysis before interpreting Swift language semantics and standard library behavior through a tree-walking runtime.</span></p><p><span>Beyond the language runtime itself, the project is also exploring framework support. SwiftUI already has a basic rendering pipeline, while Charts currently implements 58 of 60 range-related members, can render Web SVG output, and can bridge to Apple&#8217;s native Charts framework on iOS.</span></p><blockquote><p><span>Whether it&#8217;s the C-based </span><a href="https://miniswift.run/"><span>miniSwift</span></a><span>, the recent signs of the Swift compiler&#8217;s </span><a href="https://fatbobman.com/en/weekly/issue-142/"><span>self-hosting progress</span></a><span>, or the Rust-based tswift runtime, they all demonstrate that the Swift ecosystem is evolving toward a more open and diverse implementation landscape. As more implementation paths emerge, Swift&#8217;s cross-platform potential continues to grow beyond what many expected.</span></p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-146?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#19981;&#26159;&#27169;&#22411;&#21464;&#24930;&#20102;&#65292;&#26159;&#20219;&#21153;&#21464;&#22823;&#20102;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-146/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;&#21363;&#20415;&#26159;&#19968;&#20123;&#25105;&#35748;&#20026;&#24182;&#19981;&#31639;&#22797;&#26434;&#30340;&#24037;&#20316;&#65292;AI &#20132;&#20184;&#32467;&#26524;&#20063;&#24120;&#24120;&#38656;&#35201;&#20960;&#20998;&#38047;&#65292;&#29978;&#33267;&#20960;&#21313;&#20998;&#38047;&#12290;&#36825;&#35753;&#25105;&#20135;&#29983;&#20102;&#19968;&#31181;&#38169;&#35273;&#65306;&#38590;&#36947;&#38543;&#30528;&#27169;&#22411;&#33021;&#21147;&#19981;&#26029;&#22686;&#24378;&#65292;&#36895;&#24230;&#21482;&#33021;&#36234;&#26469;&#36234;&#24930;&#65311;</span></p><p><span>&#20854;&#23454;&#65292;&#30495;&#27491;&#30340;&#21407;&#22240;&#26356;&#22810;&#26469;&#33258;&#20110;&#25105;&#33258;&#24049;&#12290;&#34429;&#28982; Agent &#25552;&#20379;&#20102;&#27169;&#22411;&#21644;&#24605;&#32771;&#24378;&#24230;&#30340;&#35843;&#25972;&#36873;&#39033;&#65292;&#20294;&#20026;&#20102;&#30465;&#20107;&#65292;&#20063;&#20026;&#20102;&#36861;&#27714;&#26356;&#39640;&#30340;&#25104;&#21151;&#29575;&#65292;&#25105;&#36234;&#26469;&#36234;&#20064;&#24815;&#25226;&#19968;&#20123;&#21407;&#26412;&#24182;&#19981;&#22797;&#26434;&#30340;&#20219;&#21153;&#30452;&#25509;&#20132;&#32473;&#39640;&#32423;&#27169;&#22411;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#22914;&#20170;&#30340; Agent &#20063;&#19981;&#20250;&#20687;&#36807;&#21435;&#37027;&#26679;&#21482;&#20851;&#27880;&#20320;&#35201;&#27714;&#20462;&#25913;&#30340;&#37027;&#19968;&#23567;&#22359;&#20195;&#30721;&#65292;&#32780;&#26159;&#20250;&#20027;&#21160;&#25193;&#22823;&#25628;&#32034;&#33539;&#22260;&#65292;&#20998;&#26512;&#25913;&#21160;&#26159;&#21542;&#20250;&#24433;&#21709;&#25972;&#20010;&#39033;&#30446;&#65292;&#24182;&#23581;&#35797;&#25552;&#21069;&#21457;&#29616;&#28508;&#22312;&#38382;&#39064;&#12290;&#27169;&#22411;&#34429;&#28982;&#26356;&#24378;&#20102;&#65292;&#20294;&#23436;&#25104;&#19968;&#27425;&#20219;&#21153;&#25152;&#25215;&#25285;&#30340;&#24037;&#20316;&#20063;&#26126;&#26174;&#26356;&#22810;&#20102;&#12290;</span></p><p><span>&#38500;&#27492;&#20043;&#22806;&#65292;&#38543;&#30528;&#25105;&#23545;&#27169;&#22411;&#33021;&#21147;&#30340;&#20449;&#20219;&#19981;&#26029;&#25552;&#39640;&#65292;&#20132;&#32473;&#23427;&#30340;&#20219;&#21153;&#31890;&#24230;&#20063;&#21457;&#29983;&#20102;&#21464;&#21270;&#12290;&#20174;&#26368;&#21021;&#20462;&#25913;&#19968;&#20010;&#20989;&#25968;&#12289;&#20248;&#21270;&#19968;&#20010;&#39029;&#38754;&#65292;&#21040;&#23454;&#29616;&#19968;&#20010;&#21151;&#33021;&#12289;&#23436;&#25104;&#19968;&#20010;&#27169;&#22359;&#65292;&#29978;&#33267;&#30452;&#25509;&#24320;&#21457;&#19968;&#20010;&#20135;&#21697;&#65292;&#25105;&#24050;&#32463;&#19981;&#30693;&#19981;&#35273;&#25226; Agent &#24403;&#25104;&#20102;&#19968;&#20301;&#30495;&#27491;&#30340;&#21327;&#20316;&#32773;&#12290;&#27169;&#22411;&#36895;&#24230;&#30340;&#25552;&#21319;&#65292;&#24050;&#32463;&#36319;&#19981;&#19978;&#20351;&#29992;&#26041;&#24335;&#21464;&#21270;&#30340;&#36895;&#24230;&#12290;</span></p><p><span>&#25442;&#21477;&#35805;&#35828;&#65292;&#24320;&#21457;&#32773;&#36861;&#27714;&#30340;&#24050;&#32463;&#19981;&#20877;&#21482;&#26159;&#8220;&#26356;&#24555;&#22320;&#20889;&#20195;&#30721;&#8221;&#65292;&#32780;&#26159;&#20511;&#21161; AI&#8220;&#26356;&#24930;&#22320;&#20889;&#20986;&#26356;&#22909;&#30340;&#20195;&#30721;&#8221;&#12290;</span></p><p><span>&#20174;&#38382;&#31572;&#24335;&#65292;&#21040;&#20132;&#20184;&#24335;&#65292;&#21482;&#29992;&#20102;&#30701;&#30701;&#19968;&#24180;&#26102;&#38388;&#12290;&#24403;&#25105;&#20204;&#24320;&#22987;&#20064;&#24815;&#19968;&#35273;&#37266;&#26469;&#25509;&#25910;&#25104;&#26524;&#26102;&#65292;&#30495;&#27491;&#30340;&#29942;&#39048;&#20063;&#24708;&#28982;&#21457;&#29983;&#20102;&#21464;&#21270;&#12290;&#36807;&#21435;&#65292;&#25105;&#20204;&#20851;&#24515;&#30340;&#26159;&#27169;&#22411;&#33021;&#19981;&#33021;&#23436;&#25104;&#20219;&#21153;&#65307;&#29616;&#22312;&#65292;&#26356;&#37325;&#35201;&#30340;&#38382;&#39064;&#21464;&#25104;&#20102;&#22914;&#20309;&#23450;&#20041;&#19968;&#20010;&#28165;&#26224;&#12289;&#21487;&#39564;&#35777;&#30340;&#30446;&#26631;&#65292;&#20197;&#21450;&#22914;&#20309;&#38477;&#20302;&#23454;&#29616;&#30446;&#26631;&#30340;&#25104;&#26412;&#12290;&#27169;&#22411;&#36234;&#26469;&#36234;&#20687;&#22242;&#38431;&#25104;&#21592;&#65292;&#32780;&#39640;&#36136;&#37327;&#22320;&#32452;&#32455;&#21644;&#25286;&#35299;&#24037;&#20316;&#65292;&#20063;&#27491;&#22312;&#25104;&#20026;&#26032;&#30340;&#25928;&#29575;&#31454;&#20105;&#21147;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-145/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-01"><span>&#29992;&#29616;&#20195;&#24182;&#21457;&#25216;&#26415;&#24320;&#21457;&#34013;&#29273;&#24212;&#29992; (Bluetooth without the delegate dance)</span></a></strong></h3><p><span>Delegate &#20173;&#26159;&#24456;&#22810;&#24320;&#21457;&#32773;&#22312; Swift Concurrency &#24050;&#32463;&#25512;&#20986;&#25968;&#24180;&#21518;&#19981;&#24471;&#19981;&#38754;&#23545;&#30340;&#38382;&#39064;&#65306;&#19981;&#20165;&#20195;&#30721;&#32452;&#32455;&#32321;&#29712;&#65292;&#22312; Swift 6 &#30340;&#20005;&#26684;&#24182;&#21457;&#26816;&#26597;&#19979;&#65292;&#20063;&#36234;&#26469;&#36234;&#38590;&#19982;&#29616;&#20195;&#24182;&#21457;&#20195;&#30721;&#33258;&#28982;&#21327;&#20316;&#12290;&#8288;</span><a href="https://linkedin.com/in/kyle-browning-eng-manager"><span>Kyle Browning</span></a><span> &#21033;&#29992; Swift 6.2 &#30340; Custom Executor&#65292;&#23558; CoreBluetooth &#30340;&#22238;&#35843;&#38431;&#21015;&#19982; Actor &#30340;&#25191;&#34892;&#19978;&#19979;&#25991;&#32465;&#23450;&#65292;&#20351; Delegate &#22238;&#35843;&#22825;&#28982;&#36816;&#34892;&#22312; Actor &#38548;&#31163;&#29615;&#22659;&#20013;&#65292;&#26080;&#38656;&#39069;&#22806;&#30340;&#38145;&#12289;&#32447;&#31243;&#20999;&#25442;&#25110;&#21516;&#27493;&#36923;&#36753;&#12290;</span></p><blockquote><p><span>Custom Executor &#21487;&#20197;&#35753; Actor &#20013;&#30340;&#20219;&#21153;&#36816;&#34892;&#22312;&#25351;&#23450;&#30340;&#25191;&#34892;&#22120;&#19978;&#65292;&#26159;&#36830;&#25509;&#20256;&#32479;&#22238;&#35843; API &#19982; Swift Concurrency &#30340;&#19968;&#39033;&#37325;&#35201;&#33021;&#21147;&#12290;&#22914;&#26524;&#20320;&#20063;&#38754;&#20020;&#31867;&#20284;&#30340;&#36801;&#31227;&#25110;&#23553;&#35013;&#38382;&#39064;&#65292;&#19981;&#22952;&#21442;&#32771;&#20316;&#32773;&#30340;&#23454;&#29616;&#24605;&#36335;&#12290;&#25105;&#20063;&#26366;&#22312;&#8288;</span><a href="https://fatbobman.com/zh/posts/core-data-reform-achieving-elegant-concurrency-operations-like-swiftdata/"><span>&#36825;&#31687;&#25991;&#31456;</span></a><span>&#20013;&#65292;&#20197; Core Data &#20026;&#20363;&#65292;&#35814;&#32454;&#20171;&#32461;&#20102;&#22914;&#20309;&#21033;&#29992; Custom Executor &#23558;&#20256;&#32479;&#20018;&#34892;&#38431;&#21015;&#19982; Actor &#25191;&#34892;&#22120;&#32465;&#23450;&#65292;&#23454;&#29616;&#19982; Swift Concurrency &#30340;&#33258;&#28982;&#34701;&#21512;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-02"><span>CI &#29615;&#22659;&#19979;&#30340; Xcode &#31649;&#29702;&#23454;&#36341; (Working with Xcode on CI)</span></a></strong></h3><p><span>&#38543;&#30528;&#36234;&#26469;&#36234;&#22810;&#24320;&#21457;&#32773;&#37319;&#29992;&#33258;&#24314; macOS Runner &#25110;&#20113;&#31471; CI&#65292;&#31283;&#23450;&#22320;&#31649;&#29702; Xcode&#12289;Simulator Runtime &#19982;&#31614;&#21517;&#29615;&#22659;&#65292;&#24050;&#25104;&#20026;&#24037;&#31243;&#32500;&#25252;&#30340;&#37325;&#35201;&#32452;&#25104;&#37096;&#20998;&#12290;</span><a href="https://mastodon.social/@rodionovd"><span>Dmitry Rodionov</span></a><span> &#22260;&#32469; Xcode CLI &#22312; CI &#20013;&#30340;&#20351;&#29992;&#65292;&#24635;&#32467;&#20102;&#19981;&#23569;&#20010;&#20154;&#24515;&#24471;&#65292;&#20363;&#22914;&#20351;&#29992; </span><code>DEVELOPER_DIR</code><span> &#26367;&#20195; </span><code>xcode-select</code><span> &#31649;&#29702;&#22810;&#29256;&#26412; Xcode&#12289;&#33258;&#21160;&#23433;&#35013;&#19982;&#28165;&#29702; Simulator Runtime &#21644; Metal Toolchain&#65292;&#20197;&#21450;&#21033;&#29992; Compilation Caching &#20943;&#23569;&#20998;&#25903;&#20999;&#25442;&#24102;&#26469;&#30340;&#37325;&#22797;&#32534;&#35793;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-03"><span>&#27048;&#24178; GitHub Actions &#30340;&#26368;&#21518;&#19968;&#28857;&#20215;&#20540;</span></a></strong></h3><p><span>GitHub Actions &#30340;&#20248;&#21270;&#65292;&#26410;&#24517;&#24847;&#21619;&#30528;&#26356;&#28608;&#36827;&#30340;&#32531;&#23384;&#12289;&#26356;&#22797;&#26434;&#30340; Workflow&#65292;&#25110;&#26356;&#22810;&#30340;&#26465;&#20214;&#21028;&#26029;&#12290;&#36825;&#31687;&#25991;&#31456;&#25552;&#20986;&#20102;&#19968;&#20010;&#20540;&#24471;&#20511;&#37492;&#30340;&#24605;&#36335;&#65306;&#35753;&#27599;&#19968;&#27425; CI &#25191;&#34892;&#37117;&#19982;&#23454;&#38469;&#39118;&#38505;&#30456;&#21305;&#37197;&#12290;</span><a href="https://x.com/rbbtsn0w"><span>Snow</span></a><span> &#20174;&#19968;&#27425;&#30475;&#20284;&#26222;&#36890;&#30340; Flaky Test &#25490;&#26597;&#24320;&#22987;&#65292;&#36880;&#27493;&#35752;&#35770;&#20102;&#22914;&#20309;&#29992;&#30830;&#23450;&#24615;&#27979;&#35797;&#28040;&#38500;&#26080;&#24847;&#20041;&#30340;&#37325;&#36305;&#12289;&#23558;&#21487;&#31227;&#26893;&#30340;&#26816;&#26597;&#36801;&#31227;&#21040; Linux&#12289;&#20165;&#25226;&#30495;&#27491;&#20381;&#36182; Xcode &#30340;&#39564;&#35777;&#30041;&#32473; macOS&#65292;&#20197;&#21450;&#26681;&#25454;&#21464;&#26356;&#39118;&#38505;&#21160;&#24577;&#36873;&#25321; Build&#12289;Test &#25110; Build for Testing&#65292;&#36991;&#20813;&#26114;&#36149;&#30340; Runner &#25191;&#34892;&#19981;&#24517;&#35201;&#30340;&#24037;&#20316;&#12290;</span></p><blockquote><p><span>&#25105;&#24456;&#35748;&#21516;&#25991;&#20013;&#30340;&#19968;&#20010;&#35266;&#28857;&#65306;CI &#30340;&#30446;&#26631;&#19981;&#26159;&#8220;&#36305;&#24471;&#26356;&#22810;&#8221;&#65292;&#32780;&#26159;&#8220;&#22238;&#31572;&#27491;&#30830;&#30340;&#38382;&#39064;&#8221;&#12290;&#27599;&#19968;&#27425;&#26114;&#36149;&#30340; macOS &#26500;&#24314;&#65292;&#37117;&#24212;&#35813;&#39564;&#35777;&#19968;&#20010;&#26356;&#20415;&#23452;&#30340; Runner &#26080;&#27861;&#39564;&#35777;&#30340;&#39118;&#38505;&#65307;&#27599;&#19968;&#27425;&#22833;&#36133;&#65292;&#20063;&#37117;&#24212;&#35813;&#25552;&#20379;&#36275;&#20197;&#25512;&#21160;&#20462;&#22797;&#30340;&#20449;&#24687;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-04"><span>&#22312; SwiftUI &#20013;&#26500;&#24314;&#33258;&#36866;&#24212;&#38750;&#27169;&#24577;&#38754;&#26495; (Building adaptive non-modal panels in SwiftUI)</span></a></strong></h3><p><span>&#20174; WWDC 26 &#24320;&#22987;&#65292;iPhone-only &#24212;&#29992;&#22312;&#36890;&#36807; iPhone Mirroring &#26174;&#31034;&#21040; Mac&#65292;&#25110;&#22312; iPad &#19978;&#36816;&#34892;&#26102;&#65292;&#23558;&#36827;&#20837;&#21487;&#21464;&#23610;&#23544;&#29615;&#22659;&#12290;&#36825;&#24847;&#21619;&#30528;&#20165;&#20381;&#36182; </span><code>horizontalSizeClass</code><span> &#21028;&#26029;&#24067;&#23616;&#24418;&#24577;&#24050;&#32463;&#36234;&#26469;&#36234;&#19981;&#21487;&#38752;&#12290;&#8288;</span><a href="https://x.com/hishnash"><span>Matthaus Woolard</span></a><span> &#20171;&#32461;&#20102;&#22914;&#20309;&#26500;&#24314;&#19968;&#20010;&#33258;&#36866;&#24212;&#30340;&#38750;&#27169;&#24577; Panel&#65306;&#36890;&#36807; </span><code>onGeometryChange</code><span> &#22312;&#22330;&#26223;&#26681;&#37096;&#35760;&#24405;&#31383;&#21475;&#23610;&#23544;&#19982; Safe Area&#65292;&#26681;&#25454;&#30495;&#23454;&#21487;&#29992;&#23485;&#24230;&#20915;&#23450;&#38754;&#26495;&#26174;&#31034;&#22312;&#24213;&#37096;&#36824;&#26159;&#20391;&#36793;&#12290;&#20854;&#20013;&#65292;&#22312;&#25302;&#21160;&#26399;&#38388;&#20445;&#30041;&#24050;&#32463;&#35299;&#26512;&#30340;&#24067;&#23616;&#32531;&#23384;&#65292;&#36991;&#20813;&#33258;&#36866;&#24212;&#20869;&#23481;&#22240;&#37325;&#22797;&#27979;&#37327;&#32780;&#20986;&#29616;&#23610;&#23544;&#36339;&#21464;&#65292;&#26159;&#19968;&#20010;&#30456;&#24403;&#23454;&#29992;&#30340;&#25216;&#24039;&#12290;</span></p><blockquote><p><span>&#22914;&#26524;&#20320;&#30340;&#24212;&#29992;&#26159; iPhone-only&#65292;&#24182;&#19988;&#20173;&#26377;&#29992;&#25143;&#20250;&#22312; iPad &#25110; macOS &#19978;&#20351;&#29992;&#23427;&#65292;&#37027;&#20040;&#20174;&#20170;&#24180;&#24320;&#22987;&#23601;&#38656;&#35201;&#29305;&#21035;&#20851;&#27880;&#24067;&#23616;&#30340;&#36866;&#37197;&#12290;&#8288;</span><a href="https://fatbobman.com/zh/posts/from-size-class-to-available-space/"><span>&#21487;&#21464;&#30011;&#24067;</span></a><span> &#20174;&#26576;&#31181;&#24847;&#20041;&#19978;&#26469;&#35828;&#65292;&#19981;&#20877;&#20445;&#35777;&#24320;&#21457;&#32773;&#23545;&#30028;&#38754;&#24067;&#23616;&#25317;&#26377;&#32477;&#23545;&#25511;&#21046;&#26435;&#65292;&#32780;&#26159;&#23558;&#26356;&#22810;&#30340;&#36873;&#25321;&#26435;&#20132;&#21040;&#20102;&#29992;&#25143;&#25163;&#20013;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0146-05"><span>SwiftUI @ContentBuilder&#65306;&#22823;&#24133;&#25552;&#21319; Xcode 27 &#32534;&#35793;&#25928;&#29575; (SwiftUI @ContentBuilder - Faster Type Checking in Xcode 27)</span></a></strong></h3><p><span>Xcode 27 &#24341;&#20837;&#20102;&#26032;&#30340; </span><code>@ContentBuilder</code><span>&#12290;&#34429;&#28982;&#23427;&#30446;&#21069;&#20173;&#21482;&#26159; </span><code>ViewBuilder</code><span> &#30340;&#31867;&#22411;&#21035;&#21517;&#65292;&#20294; Apple &#24050;&#24320;&#22987;&#22312;&#26032;&#30340; SwiftUI API &#20013;&#25512;&#33616;&#20351;&#29992;&#36825;&#19968;&#21517;&#31216;&#12290;</span><a href="https://x.com/sagarunagar_"><span>Sagar Unagar</span></a><span> &#20171;&#32461;&#20102;&#36825;&#19968;&#21464;&#21270;&#65292;&#21516;&#26102;&#25351;&#20986;&#65292;&#23545;&#22823;&#22810;&#25968;&#24212;&#29992;&#26469;&#35828;&#65292;&#24182;&#27809;&#26377;&#24517;&#35201;&#31435;&#21363;&#23558;&#25152;&#26377; </span><code>@ViewBuilder</code><span> &#26367;&#25442;&#25104; </span><code>@ContentBuilder</code><span>&#65292;&#24050;&#26377;&#20195;&#30721;&#22312; Xcode 27 &#19979;&#21516;&#26679;&#33021;&#22815;&#21463;&#30410;&#20110;&#32534;&#35793;&#22120;&#30340;&#25913;&#36827;&#12290;</span></p><blockquote><p><span>&#25105;&#26368;&#36817;&#24182;&#27809;&#26377;&#24590;&#20040;&#20889; SwiftUI &#20195;&#30721;&#65292;&#22240;&#27492;&#36824;&#27809;&#26377;&#20146;&#36523;&#20307;&#20250;&#21040;&#36825;&#20010;&#25913;&#21160;&#26159;&#21542;&#30495;&#27491;&#24102;&#26469;&#20102;&#32534;&#35793;&#25928;&#29575;&#19978;&#30340;&#25552;&#21319;&#12290;&#19981;&#36807;&#22312;&#20043;&#21069;&#30340;&#24320;&#21457;&#20013;&#65292;&#26080;&#35770;&#26159; Table &#36824;&#26159; Charts&#65292;&#24403;&#23558;&#19981;&#21516;&#30340; Builder &#20869;&#23481;&#28151;&#20889;&#21040; </span><code>ViewBuilder</code><span> &#20013;&#26102;&#65292;Xcode &#30340;&#31867;&#22411;&#25512;&#23548;&#21644;&#20195;&#30721;&#34917;&#20840;&#37117;&#20250;&#26126;&#26174;&#21464;&#24930;&#12290;&#22914;&#26524; Xcode 27 &#30830;&#23454;&#25913;&#21892;&#20102;&#36825;&#31867;&#22330;&#26223;&#65292;&#37027;&#20040;&#36825;&#27425;&#35843;&#25972;&#30340;&#24847;&#20041;&#23601;&#36828;&#19981;&#27490;&#19968;&#20010;&#26032;&#30340; Builder &#21517;&#31216;&#12290;</span></p></blockquote><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0146-06"><span>tswift: &#29992; Rust &#26500;&#24314;&#36731;&#37327; Swift &#36816;&#34892;&#26102;</span></a></strong></h3><p><span>&#26080;&#38656; Swift &#24037;&#20855;&#38142;&#12289;LLVM&#12289;&#20195;&#30721;&#29983;&#25104;&#25110; C &#20381;&#36182;&#65292;&#21363;&#21487;&#35299;&#26512;&#12289;&#35821;&#20041;&#20998;&#26512;&#24182;&#25191;&#34892; Swift &#28304;&#30721;&#12290;&#8288;</span><a href="https://github.com/siuying"><span>Francis Chong</span></a><span> &#24320;&#21457;&#30340; tswift &#20197;&#32431; Rust &#23454;&#29616;&#20102; Swift &#21069;&#31471;&#65292;&#23436;&#25104;&#35789;&#27861;&#12289;&#35821;&#27861;&#19982;&#35821;&#20041;&#20998;&#26512;&#65292;&#20877;&#36890;&#36807;&#26641;&#36941;&#21382;&#36816;&#34892;&#26102;&#23454;&#29616; Swift &#30340;&#35821;&#35328;&#35821;&#20041;&#19982;&#26631;&#20934;&#24211;&#34892;&#20026;&#12290;</span></p><p><span>&#38500;&#35821;&#35328;&#36816;&#34892;&#26102;&#22806;&#65292;&#39033;&#30446;&#20063;&#22312;&#25506;&#32034;&#26694;&#26550;&#23618;&#38754;&#30340;&#25903;&#25345;&#65306;SwiftUI &#24050;&#20855;&#22791;&#22522;&#30784;&#28210;&#26579;&#33021;&#21147;&#65292;Charts &#25903;&#25345;&#35206;&#30422; 58/60 &#20010;&#33539;&#22260;&#25104;&#21592;&#65292;&#21487;&#36755;&#20986; Web SVG&#65292;&#24182;&#21487;&#19979;&#27785;&#21040; iOS &#21407;&#29983; Charts&#12290;</span></p><blockquote><p><span>&#26080;&#35770;&#26159; C &#32534;&#20889;&#30340; </span><a href="https://miniswift.run/"><span>miniSwift</span></a><span>&#12289;Swift &#32534;&#35793;&#22120;&#36817;&#26399;&#23637;&#29616;&#20986;&#30340;&#8288;</span><a href="https://fatbobman.com/zh/weekly/issue-142/"><span>&#33258;&#20030;&#36857;&#35937;</span></a><span>&#65292;&#36824;&#26159;&#20197; Rust &#26500;&#24314;&#30340; tswift&#65292;&#37117;&#23637;&#29616;&#20986; Swift &#29983;&#24577;&#27491;&#26397;&#30528;&#26356;&#21152;&#24320;&#25918;&#12289;&#22810;&#20803;&#30340;&#23454;&#29616;&#26041;&#21521;&#21457;&#23637;&#12290;&#36234;&#26469;&#36234;&#20016;&#23500;&#30340;&#23454;&#29616;&#36335;&#24452;&#65292;&#20063;&#35753; Swift &#30340;&#36328;&#24179;&#21488;&#28508;&#21147;&#21576;&#29616;&#20986;&#36229;&#20986;&#39044;&#26399;&#30340;&#21487;&#33021;&#24615;&#12290;</span></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #145]]></title><description><![CDATA[When Inspiration Outruns the Results]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 20 Jul 2026 12:01:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kcn6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kcn6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kcn6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 424w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 848w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1272w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp" width="1400" height="705" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:705,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:67124,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/207725710?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kcn6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 424w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 848w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1272w, https://substackcdn.com/image/fetch/$s_!kcn6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05acb873-ef6b-4f0e-857b-d29a6206ffc2_1400x705.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@skyestudios?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Skye Studios</a><span> on </span><a href="https://unsplash.com/photos/low-angle-photography-of-drop-lights-NDLLFxTELrU?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Inspiration Outruns the Results</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-145/">Read on web &#8594;</a></p><p><span>Over the past few months, I&#8217;ve been refining my own AI-assisted workflow. Real progress has been made, but for long-running tasks, I&#8217;ve consistently lacked any quantifiable benchmark data. Thanks to competition among AI model providers, OpenAI recently lifted its 5-hour usage cap &#8212; which finally let me test my ideas without interruption, and compare the results and performance of different approaches head to head. Last week I burned through 6 or 7 accumulated limit resets across my two Pro accounts, and genuinely got a taste of &#8220;token freedom.&#8221;</span></p><p><span>Since each test run typically takes at least several dozen minutes, I found myself flooded with ideas while waiting and observing &#8212; new optimizations and tweaks kept popping into my head. This produced a strange phenomenon: while the old version was still running its test, the new version&#8217;s code was already written. My iteration speed had completely outpaced my test results. Some of those changes did turn out to work well, but once I calmed down, I had to face an uncomfortable truth &#8212; many of my &#8220;brilliant ideas&#8221; were really just assumptions I hadn&#8217;t thought through carefully.</span></p><p><span>At the time, caught in the false &#8220;flow state&#8221; that vibe coding produces, I didn&#8217;t notice this at all. It wasn&#8217;t until the test results showed a clear regression that I slammed on the brakes and actually stopped to reflect.</span></p><p><span>AI genuinely shortens the time it takes to validate an idea &#8212; but that convenience makes it easy to fall into a blind spot, skipping the deep thinking and logical groundwork that should happen before you start coding. Cheap, exhaustive testing shouldn&#8217;t become a substitute for real thought. Looking back, the intuition and experience we&#8217;ve built up are often far more efficient than AI&#8217;s blind trial-and-error at ruling out or refining ideas that were never going to work.</span></p><p><span>AI is an extraordinarily powerful tool &#8212; but where it should really earn its keep is in assisting execution, not replacing thinking.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-144/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-01"><span>Geometry, Compositing and Drawing Groups in SwiftUI</span></a></strong></h3><p><span>SwiftUI has three similarly-named modifiers with very different jobs &#8212; </span><code>geometryGroup()</code><span>, </span><code>compositingGroup()</code><span>, and </span><code>drawingGroup()</code><span>. They&#8217;re not only easy to confuse; most people don&#8217;t fully grasp the subtlety of what each one actually does.</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> breaks them down through three concrete scenarios: </span><code>geometryGroup()</code><span> lifts the interpolation up a level, fixing the problem of child views lacking a consistent transition state during animation; </span><code>compositingGroup()</code><span> establishes a compositing boundary for the graphical effects applied above it (like opacity or blend modes), so they treat multiple sublayers as a single unit rather than acting on each layer separately; </span><code>drawingGroup()</code><span> rasterizes multiple layers into a single offscreen image, trading space for performance &#8212; at the cost of having to regenerate that image every time the content changes.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-02"><span>One TaskGroup, Two Live Streams: a Swift 6 LLM Benchmark</span></a></strong></h3><p><span>By pulling all mutable run-state into a single </span><code>actor</code><span>, </span><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> safely merges two independent async streams &#8212; model inference and system telemetry &#8212; into one ordered event stream.</span></p><p><span>Token counts, time-to-first-token latency, sample records, and all other run-time state live only inside the actor. Inside </span><code>execute</code><span>, a single </span><code>withThrowingTaskGroup</code><span> runs two things at once: a child task consumes the telemetry stream, sampling every 500ms and emitting </span><code>RunEvent</code><span>s; a parent task runs the inference loop sequentially, where every </span><code>await</code><span> is a suspension point &#8212; the child task only gets a chance to run when the parent yields. The whole actor exposes just one </span><code>AsyncThrowingStream</code><span> to the outside. Because every access goes through actor isolation, the interleaving never conflicts &#8212; zero data races isn&#8217;t a matter of discipline, it&#8217;s something the compiler proves outright.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-03"><span>Syncing SwiftData with a Custom Backend Using HistoryObserver</span></a></strong></h3><p><span>Years ago, Apple gave SwiftData a history mechanism similar to Core Data&#8217;s Persistent History Tracking, letting developers track data-change events made to the same database from different sources in real time. But without a simple entry point that fit SwiftData&#8217;s design philosophy, the feature never saw much adoption. At WWDC 2026, Apple introduced </span><code>HistoryObserver</code><span> for SwiftData, making both triggering and incremental reads dramatically simpler. </span><a href="https://x.com/azamsharp"><span>Mohammad Azam</span></a><span> shows how this plays out in a real project, building a complete custom one-way sync pipeline with </span><code>HistoryObserver</code><span>.</span></p><p><span>The article walks through a simple room-measurement app: using </span><code>withContinuousObservation</code><span> to watch a change counter and trigger sync, using a persisted </span><code>lastToken</code><span> as a bookmark for incremental reads, and using </span><code>isDeleted</code><span> soft deletes paired with </span><code>author</code><span> tags to avoid the recursive self-triggering that hard deletes would otherwise cause. Mohammad works through each of the pitfalls you&#8217;ll hit building a sync engine, one by one, with a complete runnable example on GitHub.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-04"><span>Public Asset Symbol Constants in Swift Packages</span></a></strong></h3><p><span>Xcode auto-generates typed asset constants from </span><code>.xcassets</code><span> catalogs &#8212; things like </span><code>Color(.skyBlue)</code><span> / </span><code>Image(.logo)</code><span> &#8212; but these constants are always </span><code>internal</code><span>, so other Swift packages can&#8217;t use them. Xcode offers no public option, and there&#8217;s no way to turn this generation off from </span><code>Package.swift</code><span> either.</span></p><p><a href="https://mastodon.social/@ralfebert"><span>Ralf Ebert</span></a><span> puts any assets meant for cross-package sharing into a </span><code>Public/</code><span> subfolder inside </span><code>.xcassets</code><span>, then uses a Ruby script to scan every </span><code>**/*.xcassets/Public/</code><span> and generate a </span><code>&lt;PackageName&gt;+Generated.swift</code><span> with a nested enum, re-exporting the internal symbols as </span><code>public</code><span> &#8212; so other libraries can simply call </span><code>Image(.AppCommons.logo)</code><span>.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-06"><span>Previews and MCP</span></a></strong></h3><p><span>Xcode 27 exposes 47 tools through its MCP interface, and </span><code>RenderPreview</code><span> is the one responsible for rendering and screenshotting a SwiftUI Preview. But calling it requires the app to establish an STDIO connection via </span><code>xcrun mcpbridge</code><span>, which means the app can&#8217;t be sandboxed &#8212; a direct conflict with Mac App Store requirements.</span></p><p><a href="https://www.linkedin.com/in/amy-delves-41968418b/"><span>Amy Delves</span></a><span>&#8216;s solution is to introduce a separate, unsandboxed XPC service dedicated to talking to Xcode&#8217;s MCP, while the main app stays sandboxed; the two communicate over XPC. The rendered result is read by the helper service and shipped back inline, sidestepping the fact that the main sandboxed app can&#8217;t reach file paths outside the sandbox.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-07"><span>I Found a Workaround for an App Store Connect Bug</span></a></strong></h3><p><span>Plenty of developers have run into this App Store Connect bug: pages keep redirecting back to </span><code>/login</code><span> even while you&#8217;re already logged in. After </span><a href="https://lapcatsoftware.com/articles/2026/7/6.html"><span>getting nowhere with Apple</span></a><span>, </span><a href="https://mastodon.social/@lapcatsoftware"><span>Jeff Johnson</span></a><span> compared the HTTP cookies of two requests in Chrome and tracked down the root cause: a session cookie named </span><code>dc</code><span> (</span><code>dc=st</code><span>) &#8212; on first login, that cookie hasn&#8217;t been set yet, so the server responds with a 302 redirect to the login page. The fix was to manually turn it into a permanent cookie expiring a year out. The whole diagnosis took under an hour.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-05"><span>What&#8217;s an Icon in 2026?</span></a></strong></h3><p><span>At WWDC 2025, Apple recommended using Icon Composer to build icons, with the rationale that icons should move from static images toward &#8220;more expressive,&#8221; multi-layered artworks. As a result, an icon no longer has one fixed appearance &#8212; it only takes on a particular form once &#8220;observed&#8221; on a specific device under specific settings. Take Apple&#8217;s Phone app icon as an example: the classic green background with a white handset now splits into several separate versions across dark mode, glass mode, and various tint colors.</span></p><p><a href="https://mastodon.social/@jimniels"><span>Jim Nielsen</span></a><span> argues that an icon&#8217;s value has always rested on being simple, consistent, and memorable. The further you push toward &#8220;expressiveness&#8221; by stacking on variants, the more you dilute the icon&#8217;s core job &#8212; instant recognition.</span></p><h2><strong><span>Tool</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-08"><span>ImmersiveMap: Building a Native Immersive Map with SwiftUI and Metal</span></a></strong></h3><p><span>ImmersiveMap is a native map rendering engine for Apple platforms built by </span><a href="https://x.com/BobkinArtem"><span>Artem Bobkin</span></a><span>, implemented in Swift and Metal, and exposed through </span><code>ImmersiveMapView</code><span> as a declarative interface that fits naturally into SwiftUI conventions.</span></p><p><span>The project&#8217;s standout capability is a continuous transition between a spherical globe and a flat map. Beyond that, it covers vector tile (Vector Tile Source) parsing, label layout, 3D buildings, starfield and day/night effects, map styling, camera fly-to animations, and live markers that support clustering and dynamic movement. Developers can run it out of the box with the built-in tiles, or plug in Mapbox or a custom MVT (Mapbox Vector Tile) data source.</span></p><p><span>ImmersiveMap is a thorough demonstration of how to wrap a complex Metal rendering system behind a clean SwiftUI API. For developers who want to understand how a map engine, SwiftUI, and low-level graphics rendering work together, it&#8217;s a genuinely worthwhile open-source project to study.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-145?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403;&#28789;&#24863;&#36305;&#22312;&#20102;&#32467;&#26524;&#21069;&#38754;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-145/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#36807;&#21435;&#20960;&#20010;&#26376;&#65292;&#25105;&#19968;&#30452;&#22312;&#20248;&#21270;&#33258;&#24049;&#30340; AI &#24037;&#20316;&#27969;&#12290;&#23613;&#31649;&#39047;&#26377;&#36827;&#23637;&#65292;&#20294;&#22312;&#38271;&#20219;&#21153;&#20013;&#65292;&#22987;&#32456;&#32570;&#20047;&#19968;&#20123;&#21487;&#20197;&#37327;&#21270;&#30340; benchmark &#25968;&#25454;&#12290;&#24471;&#30410;&#20110; AI &#27169;&#22411;&#20844;&#21496;&#20043;&#38388;&#30340;&#31454;&#20105;&#65292;&#19981;&#20037;&#21069; OpenAI &#35299;&#38500;&#20102; 5 &#23567;&#26102;&#30340;&#39069;&#24230;&#38480;&#21046;&#65292;&#36825;&#35753;&#25105;&#32456;&#20110;&#33021;&#22815;&#19981;&#38388;&#26029;&#22320;&#27979;&#35797;&#33258;&#24049;&#30340;&#19968;&#20123;&#24819;&#27861;&#65292;&#24182;&#27604;&#36739;&#19981;&#21516;&#26041;&#26696;&#22312;&#25928;&#26524;&#19982;&#24615;&#33021;&#19978;&#30340;&#24046;&#24322;&#12290;&#19978;&#21608;&#65292;&#25105;&#25226;&#20004;&#20010; Pro &#36134;&#25143;&#25874;&#19979;&#30340; 6&#12289;7 &#27425;&#39069;&#24230;&#37117;&#29992;&#25481;&#20102;&#65292;&#30528;&#23454;&#20307;&#39564;&#20102;&#19968;&#25226;&#8220;Token &#33258;&#30001;&#8221;&#30340;&#24863;&#35273;&#12290;</span></p><p><span>&#30001;&#20110;&#27599;&#19968;&#20010;&#27979;&#35797;&#36890;&#24120;&#37117;&#38656;&#35201;&#36305;&#19978;&#33267;&#23569;&#20960;&#21313;&#20998;&#38047;&#65292;&#22312;&#31561;&#24453;&#12289;&#35266;&#27979;&#30340;&#36807;&#31243;&#20013;&#65292;&#25105;&#32463;&#24120;&#20250;&#28789;&#24863;&#28044;&#21160;&#65292;&#33041;&#23376;&#37324;&#19981;&#26029;&#20882;&#20986;&#21508;&#31181;&#20248;&#21270;&#21644;&#35843;&#25972;&#26041;&#26696;&#12290;&#36825;&#23601;&#20135;&#29983;&#20102;&#19968;&#20010;&#22855;&#24618;&#30340;&#29616;&#35937;&#65306;&#26087;&#29256;&#26412;&#30340;&#27979;&#35797;&#36824;&#22312;&#36816;&#34892;&#26102;&#65292;&#26032;&#29256;&#26412;&#30340;&#20195;&#30721;&#24050;&#32463;&#20889;&#23436;&#20102;&#12290;&#36845;&#20195;&#36895;&#24230;&#24443;&#24213;&#36305;&#22312;&#20102;&#27979;&#35797;&#32467;&#26524;&#21069;&#38754;&#12290;&#23613;&#31649;&#20854;&#20013;&#30830;&#23454;&#26377;&#19968;&#20123;&#25913;&#21160;&#39047;&#35265;&#25104;&#25928;&#65292;&#20294;&#20919;&#38745;&#21518;&#20063;&#19981;&#24471;&#19981;&#38754;&#23545;&#19968;&#20010;&#27531;&#37239;&#30340;&#20107;&#23454;&#8212;&#8212;&#35768;&#22810;&#33258;&#20197;&#20026;&#26159;&#30340;&#8220;&#28789;&#24863;&#8221;&#20854;&#23454;&#21482;&#26159;&#24819;&#24403;&#28982;&#65292;&#24182;&#27809;&#26377;&#32463;&#36807;&#23457;&#24910;&#30340;&#24605;&#32771;&#12290;</span></p><p><span>&#28982;&#32780;&#65292;&#22312;&#37027;&#31181;&#30001;&#8220;Vibe Coding&#8221;&#20135;&#29983;&#30340;&#34394;&#20551;&#8220;&#24515;&#27969;&#8221;&#29366;&#24577;&#19979;&#65292;&#24403;&#26102;&#30340;&#25105;&#24182;&#27809;&#26377;&#24847;&#35782;&#21040;&#36825;&#19968;&#28857;&#12290;&#30452;&#21040;&#27979;&#35797;&#32467;&#26524;&#20986;&#29616;&#26126;&#26174;&#30340;&#21155;&#21270;&#65292;&#25105;&#25165;&#29467;&#22320;&#36393;&#19979;&#21049;&#36710;&#65292;&#24320;&#22987;&#35748;&#30495;&#21453;&#24605;&#12290;</span></p><p><span>AI &#30340;&#30830;&#26497;&#22823;&#22320;&#32553;&#30701;&#20102;&#25105;&#20204;&#39564;&#35777;&#19968;&#20010; Idea &#30340;&#26102;&#38388;&#65292;&#20294;&#36825;&#31181;&#20415;&#21033;&#20063;&#23481;&#26131;&#35753;&#20154;&#38519;&#20837;&#30450;&#21306;&#65292;&#24573;&#30053;&#20102;&#22312;&#21160;&#25163;&#21069;&#23545;&#26500;&#24819;&#36827;&#34892;&#28145;&#20837;&#24605;&#32771;&#19982;&#36923;&#36753;&#26803;&#29702;&#30340;&#36807;&#31243;&#12290;&#19981;&#33021;&#35753;&#20302;&#25104;&#26412;&#30340;&#8220;&#31351;&#20030;&#27979;&#35797;&#8221;&#21462;&#20195;&#30495;&#27491;&#30340;&#24605;&#32771;&#12290;&#22238;&#36807;&#22836;&#26469;&#30475;&#65292;&#25105;&#20204;&#31215;&#32047;&#30340;&#30452;&#35273;&#19982;&#32463;&#39564;&#65292;&#22312;&#21542;&#20915;&#25110;&#35843;&#25972;&#37027;&#20123;&#19981;&#20999;&#23454;&#38469;&#30340;&#26500;&#24819;&#26102;&#65292;&#25928;&#29575;&#24448;&#24448;&#36828;&#39640;&#20110; AI &#30340;&#30450;&#30446;&#35797;&#38169;&#12290;</span></p><p><span>AI &#26159;&#19968;&#20010;&#26497;&#20854;&#24378;&#22823;&#30340;&#24037;&#20855;&#65292;&#20294;&#23427;&#26368;&#35813;&#21457;&#25381;&#20316;&#29992;&#30340;&#22320;&#26041;&#26159;&#36741;&#21161;&#25191;&#34892;&#65292;&#32780;&#38750;&#20195;&#26367;&#24605;&#32771;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-144/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-01"><span>&#21400;&#28165; SwiftUI &#20013;&#30340;&#19977;&#22823;&#35270;&#22270;&#32452;&#20462;&#39280;&#31526; (Geometry, compositing and drawing groups in SwiftUI)</span></a></strong></h3><p><span>SwiftUI &#20013;&#19977;&#20010;&#21517;&#23383;&#30456;&#36817;&#21364;&#32844;&#36131;&#36837;&#24322;&#30340;&#20462;&#39280;&#31526;&#8212;&#8212;</span><code>geometryGroup()</code><span>&#12289;</span><code>compositingGroup()</code><span>&#12289;</span><code>drawingGroup()</code><span>&#65292;&#23427;&#20204;&#19981;&#20165;&#23481;&#26131;&#34987;&#28151;&#28102;&#65292;&#32780;&#19988;&#24456;&#22810;&#20154;&#20063;&#19981;&#30693;&#36947;&#23427;&#20204;&#30340;&#31934;&#22937;&#20316;&#29992;&#12290;</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span> &#29992;&#19977;&#20010;&#20855;&#20307;&#22330;&#26223;&#36880;&#19968;&#25286;&#35299;&#65306;</span><code>geometryGroup()</code><span> &#36890;&#36807;&#23558;&#25554;&#20540;&#26426;&#21046;&#19978;&#25552;&#65292;&#35299;&#20915;&#23376;&#35270;&#22270;&#21160;&#30011;&#32570;&#23569;&#19968;&#33268;&#36807;&#28193;&#29366;&#24577;&#30340;&#38382;&#39064;&#65307;</span><code>compositingGroup()</code><span> &#20026;&#20854;&#19978;&#23618;&#30340;&#22270;&#24418;&#25928;&#26524;&#65288;&#22914; opacity&#12289;blend mode&#65289;&#21010;&#23450;&#21512;&#25104;&#36793;&#30028;&#65292;&#20351;&#20854;&#25226;&#22810;&#20010;&#23376;&#23618;&#32423;&#24403;&#20316;&#19968;&#20010;&#25972;&#20307;&#22788;&#29702;&#65292;&#32780;&#38750;&#36880;&#23618;&#20998;&#21035;&#20316;&#29992;&#65307;</span><code>drawingGroup()</code><span> &#21017;&#26159;&#25226;&#22810;&#20010;&#23618;&#32423;&#26629;&#26684;&#21270;&#65288;rasterize&#65289;&#20026;&#19968;&#24352;&#31163;&#23631;&#22270;&#20687;&#65288;offscreen image&#65289;&#65292;&#20197;&#31354;&#38388;&#25442;&#24615;&#33021;&#65292;&#20195;&#20215;&#26159;&#27599;&#27425;&#20869;&#23481;&#21464;&#21270;&#37117;&#35201;&#37325;&#26032;&#29983;&#25104;&#36825;&#24352;&#22270;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-02"><span>&#29992; Swift 6 &#24182;&#21457;&#26426;&#21046;&#21512;&#24182; LLM &#19982;&#36965;&#27979;&#21452;&#25968;&#25454;&#27969; (One TaskGroup, Two Live Streams: a Swift 6 LLM Benchmark)</span></a></strong></h3><p><a href="https://linkedin.com/in/wesmatlock"><span>Wesley Matlock</span></a><span> &#36890;&#36807;&#23558;&#25152;&#26377;&#21487;&#21464;&#36816;&#34892;&#29366;&#24577;&#25910;&#36827;&#19968;&#20010; </span><code>actor</code><span>&#65292;&#20174;&#32780;&#23558;&#27169;&#22411;&#25512;&#29702;&#19982;&#31995;&#32479;&#36965;&#27979;&#20004;&#26465;&#29420;&#31435;&#30340;&#24322;&#27493;&#27969;&#65292;&#23433;&#20840;&#21512;&#24182;&#20026;&#19968;&#20010;&#26377;&#24207;&#20107;&#20214;&#27969;&#12290;</span></p><p><span>token &#35745;&#25968;&#12289;&#39318; token &#24310;&#36831;&#12289;&#37319;&#26679;&#35760;&#24405;&#31561;&#25152;&#26377;&#36816;&#34892;&#26102;&#29366;&#24577;&#21482;&#23384;&#22312;&#20110; actor &#20869;&#37096;&#12290;&#22312; </span><code>execute</code><span> &#20013;&#65292;&#19968;&#20010; </span><code>withThrowingTaskGroup</code><span> &#21516;&#26102;&#36305;&#20004;&#26465;&#36923;&#36753;&#8212;&#8212;&#23376;&#20219;&#21153;&#65288;child task&#65289;&#28040;&#36153;&#36965;&#27979;&#27969;&#65288;telemetry stream&#65289;&#65292;&#25353; 500ms &#33410;&#22863;&#37319;&#26679;&#24182;&#29983;&#25104; </span><code>RunEvent</code><span>&#65307;&#29238;&#20219;&#21153;&#65288;parent task&#65289;&#21017;&#39034;&#24207;&#25191;&#34892;&#25512;&#29702;&#24490;&#29615;&#65292;&#27599;&#27425; </span><code>await</code><span> &#37117;&#26159;&#19968;&#20010;&#25346;&#36215;&#28857;&#65288;suspension point&#65289;&#65292;&#29238;&#20219;&#21153;&#35753;&#20986;&#26102;&#23376;&#20219;&#21153;&#25165;&#26377;&#26426;&#20250;&#36816;&#34892;&#65292;&#25972;&#20010; actor &#23545;&#22806;&#21482;&#26292;&#38706;&#19968;&#20010; </span><code>AsyncThrowingStream</code><span>&#12290;&#22240;&#20026;&#25152;&#26377;&#35775;&#38382;&#37117;&#32463;&#36807; actor &#38548;&#31163;&#65292;&#20132;&#26367;&#25191;&#34892;&#27704;&#19981;&#20914;&#31361;&#8212;&#8212;&#38646;&#31454;&#20105;&#19981;&#26159;&#38752;&#33258;&#35273;&#65292;&#26159;&#32534;&#35793;&#22120;&#30452;&#25509;&#35777;&#26126;&#30340;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-03"><span>&#21033;&#29992; HistoryObserver &#26500;&#24314; SwiftData &#33258;&#23450;&#20041;&#21516;&#27493; (Syncing SwiftData with a Custom Backend Using HistoryObserver)</span></a></strong></h3><p><span>&#20960;&#24180;&#21069;&#65292;&#33529;&#26524;&#20415;&#32473; SwiftData &#25552;&#20379;&#20102; SwiftData History &#26426;&#21046;&#65292;&#35813;&#26426;&#21046;&#19982; Core Data &#30340; Persistent History Tracking &#31867;&#20284;&#65292;&#35753;&#24320;&#21457;&#32773;&#23454;&#26102;&#25484;&#25569;&#26469;&#33258;&#19981;&#21516;&#28304;&#23545;&#21516;&#19968;&#20010;&#25968;&#25454;&#24211;&#36896;&#25104;&#30340;&#25968;&#25454;&#21464;&#26356;&#20107;&#20214;&#65292;&#20294;&#30001;&#20110;&#32570;&#23569;&#19968;&#20010;&#19982; SwiftData &#35774;&#35745;&#29702;&#24565;&#36148;&#36817;&#30340;&#31616;&#21333;&#20837;&#21475;&#65292;&#35813;&#21151;&#33021;&#30340;&#21033;&#29992;&#29575;&#24182;&#19981;&#39640;&#12290;&#22312; WWDC 2026 &#19978;&#65292;&#33529;&#26524;&#20026; SwiftData &#24341;&#20837; </span><code>HistoryObserver</code><span>&#65292;&#35753;&#35302;&#21457;&#12289;&#22686;&#37327;&#35835;&#21462;&#21464;&#24471;&#38750;&#24120;&#31616;&#21333;&#12290;</span><a href="https://x.com/azamsharp"><span>Mohammad Azam</span></a><span> &#23637;&#31034;&#20102;&#35813;&#33021;&#21147;&#22312;&#30495;&#23454;&#39033;&#30446;&#20013;&#30340;&#24212;&#29992;&#65292;&#36890;&#36807; </span><code>HistoryObserver</code><span> &#25645;&#20986;&#23436;&#25972;&#30340;&#33258;&#23450;&#20041;&#21333;&#21521;&#21516;&#27493;&#31649;&#32447;&#12290;</span></p><p><span>&#25991;&#31456;&#22260;&#32469;&#19968;&#20010;&#25151;&#38388;&#27979;&#37327;&#23567;&#24212;&#29992;&#23637;&#24320;&#65306;&#29992; </span><code>withContinuousObservation</code><span> &#30417;&#21548;&#21464;&#26356;&#35745;&#25968;&#35302;&#21457;&#21516;&#27493;&#65292;&#29992;&#25345;&#20037;&#21270;&#30340; </span><code>lastToken</code><span> &#20570;&#20070;&#31614;&#23454;&#29616;&#22686;&#37327;&#35835;&#21462;&#65292;&#20877;&#29992; </span><code>isDeleted</code><span> &#36719;&#21024;&#38500;&#37197;&#21512; </span><code>author</code><span> &#26631;&#31614;&#36991;&#20813;&#30828;&#21024;&#38500;&#24341;&#21457;&#30340;&#36882;&#24402;&#33258;&#35302;&#21457;&#12290;Mohammad &#23545;&#25171;&#36896;&#21516;&#27493;&#24341;&#25806;&#26102;&#20250;&#36393;&#30340;&#22353;&#65292;&#36880;&#19968;&#32473;&#20986;&#35299;&#27861;&#65292;&#24182;&#38468;&#24102;&#23436;&#25972;&#21487;&#36305;&#30340; GitHub &#31034;&#20363;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-04"><span>&#22312; Swift &#27169;&#22359;&#21253;&#20013;&#20849;&#20139;&#20844;&#24320;&#30340;&#36164;&#28304;&#31526;&#21495;&#24120;&#37327; (Public asset symbol constants in Swift packages)</span></a></strong></h3><p><span>Xcode &#20250;&#20174; </span><code>.xcassets</code><span> &#33258;&#21160;&#29983;&#25104;&#31867;&#22411;&#21270;&#30340;&#36164;&#28304;&#24120;&#37327;&#65292;&#27604;&#22914; </span><code>Color(.skyBlue)</code><span> / </span><code>Image(.logo)</code><span>&#65292;&#20294;&#36825;&#20123;&#24120;&#37327;&#26159; </span><code>internal</code><span> &#30340;&#65292;&#26080;&#27861;&#20379;&#20854;&#20182; Swift &#21253;&#20351;&#29992;&#65292;Xcode &#26082;&#19981;&#25552;&#20379; public &#36873;&#39033;&#65292;&#20063;&#26080;&#27861;&#22312; </span><code>Package.swift</code><span> &#37324;&#20851;&#38381;&#36825;&#22871;&#29983;&#25104;&#26426;&#21046;&#12290;</span></p><p><a href="https://mastodon.social/@ralfebert"><span>Ralf Ebert</span></a><span> &#25226;&#35201;&#36328;&#21253;&#20849;&#20139;&#30340;&#36164;&#28304;&#25918;&#36827; </span><code>.xcassets</code><span> &#20869;&#30340; </span><code>Public/</code><span> &#23376;&#30446;&#24405;&#65292;&#20877;&#29992;&#19968;&#20010; Ruby &#33050;&#26412;&#25195;&#25551;&#25152;&#26377; </span><code>**/*.xcassets/Public/</code><span>&#65292;&#25353;&#21253;&#21517;&#29983;&#25104;&#19968;&#20010;&#23884;&#22871; enum &#30340; </span><code>&lt;PackageName&gt;+Generated.swift</code><span>&#65292;&#25226;&#20869;&#37096;&#31526;&#21495;&#37325;&#26032;&#23548;&#20986;&#20026; </span><code>public</code><span>&#8212;&#8212;&#20174;&#32780;&#21487;&#20197;&#22312;&#20854;&#20182;&#24211;&#20013;&#36890;&#36807; </span><code>Image(.AppCommons.logo)</code><span> &#30340;&#26041;&#24335;&#26469;&#35843;&#29992;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-06"><span>&#31361;&#30772; Xcode &#39044;&#35272;&#19982; MCP &#30340;&#27801;&#30418;&#38480;&#21046; (Previews and MCP)</span></a></strong></h3><p><span>Xcode 27 &#25552;&#20379;&#30340; MCP &#25509;&#21475;&#19968;&#20849;&#26292;&#38706;&#20102; 47 &#20010;&#24037;&#20855;&#65292;&#20854;&#20013; </span><code>RenderPreview</code><span> &#36127;&#36131;&#23545; Preview &#36827;&#34892;&#28210;&#26579;&#19982;&#25130;&#22270;&#12290;&#20294;&#35843;&#29992;&#23427;&#30340;&#24212;&#29992;&#24517;&#39035;&#36890;&#36807; </span><code>xcrun mcpbridge</code><span> &#24314;&#31435; STDIO &#36830;&#25509;&#65292;&#36825;&#35201;&#27714;&#24212;&#29992;&#19981;&#33021;&#34987;&#27801;&#30418;&#21270;&#65288;sandboxed&#65289;&#8212;&#8212;&#30452;&#25509;&#19982;&#19978;&#26550; Mac App Store &#30340;&#35268;&#21017;&#20914;&#31361;&#12290;</span></p><p><a href="https://www.linkedin.com/in/amy-delves-41968418b/"><span>Amy Delves</span></a><span> &#30340;&#35299;&#27861;&#26159;&#24341;&#20837;&#19968;&#20010;&#29420;&#31435;&#30340;&#12289;&#26410;&#27801;&#30418;&#21270;&#30340; XPC &#26381;&#21153;&#19987;&#38376;&#19982; Xcode MCP &#23545;&#35805;&#65292;&#20027; App &#26412;&#36523;&#20173;&#20445;&#25345;&#27801;&#30418;&#21270;&#65292;&#20004;&#32773;&#36890;&#36807; XPC &#36890;&#20449;&#65307;&#28210;&#26579;&#32467;&#26524;&#30001; helper &#26381;&#21153;&#35835;&#21462;&#21518;&#20869;&#32852;&#20256;&#22238;&#65292;&#20174;&#32780;&#32469;&#24320;&#20027; App &#26080;&#27861;&#35775;&#38382;&#27801;&#30418;&#22806;&#25991;&#20214;&#36335;&#24452;&#30340;&#38480;&#21046;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-07"><span>&#25105;&#25214;&#21040;&#20102;&#35299;&#20915; App Store Connect &#30331;&#24405; Bug &#30340; workaround (I found a workaround for an App Store Connect bug)</span></a></strong></h3><p><span>&#19981;&#23569;&#24320;&#21457;&#32773;&#37117;&#36935;&#21040;&#36807; App Store Connect &#30340;&#19968;&#20010; Bug&#65306;&#22312;&#24050;&#30331;&#24405;&#29366;&#24577;&#19979;&#39029;&#38754;&#20173;&#20250;&#36339;&#36716;&#22238; </span><code>/login</code><span>&#12290;</span><a href="https://mastodon.social/@lapcatsoftware"><span>Jeff Johnson</span></a><span> &#22312;&#19982; Apple </span><a href="https://lapcatsoftware.com/articles/2026/7/6.html"><span>&#27807;&#36890;&#26080;&#26524;</span></a><span>&#21518;&#65292;&#29992; Chrome &#23545;&#27604;&#20004;&#27425;&#35831;&#27714;&#30340; HTTP Cookie&#65292;&#25214;&#21040;&#20102;&#38382;&#39064;&#26681;&#28304;&#65306;&#19968;&#20010;&#21517;&#20026; </span><code>dc</code><span> &#30340; session cookie&#65288;</span><code>dc=st</code><span>&#65289;&#8212;&#8212;&#39318;&#27425;&#30331;&#24405;&#26102;&#35813; cookie &#23578;&#26410;&#20889;&#20837;&#65292;&#26381;&#21153;&#31471;&#22240;&#27492;&#36820;&#22238; 302 &#36339;&#36716;&#21040;&#30331;&#24405;&#39029;&#12290;&#35299;&#20915;&#21150;&#27861;&#26159;&#25226;&#23427;&#25163;&#21160;&#25913;&#25104;&#19968;&#24180;&#21518;&#36807;&#26399;&#30340;&#27704;&#20037; cookie&#65292;&#25972;&#20010;&#35786;&#26029;&#36807;&#31243;&#19981;&#21040;&#19968;&#23567;&#26102;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0145-05"><span>&#22914;&#20309;&#23450;&#20041; 2026 &#24180;&#30340; App &#22270;&#26631;&#65311; (What&#8217;s an Icon in 2026?)</span></a></strong></h3><p><span>Apple &#22312; WWDC 2025 &#19978;&#25512;&#33616;&#29992; Icon Composer &#21046;&#20316;&#22270;&#26631;&#65292;&#29702;&#30001;&#26159;&#35753;&#22270;&#26631;&#20174;&#38745;&#24577;&#22270;&#20687;&#36208;&#21521;&#8220;&#26356;&#20855;&#34920;&#29616;&#21147;&#8221;&#30340;&#22810;&#23618;&#20316;&#21697;&#8212;&#8212;&#22270;&#26631;&#30001;&#27492;&#19981;&#20877;&#26377;&#21807;&#19968;&#30830;&#23450;&#30340;&#26679;&#23376;&#65292;&#21482;&#26377;&#22312;&#20855;&#20307;&#35774;&#22791;&#12289;&#20855;&#20307;&#35774;&#32622;&#19979;&#34987;&#8220;&#35266;&#27979;&#8221;&#26102;&#25165;&#20250;&#21576;&#29616;&#20986;&#26576;&#19968;&#31181;&#24418;&#24577;&#12290;&#20197; Apple &#30005;&#35805; App &#22270;&#26631;&#20026;&#20363;&#65306;&#32511;&#24213;&#30333;&#35805;&#31570;&#30340;&#32463;&#20856;&#24418;&#35937;&#65292;&#22914;&#20170;&#35201;&#20998;&#35010;&#25104;&#28145;&#33394;&#27169;&#24335;&#12289;&#29627;&#29827;&#27169;&#24335;&#12289;&#22810;&#31181;&#30528;&#33394;&#30340;&#22909;&#20960;&#20010;&#29256;&#26412;&#12290;</span></p><p><a href="https://mastodon.social/@jimniels"><span>Jim Nielsen</span></a><span> &#35748;&#20026;&#22270;&#26631;&#30340;&#20215;&#20540;&#26412;&#23601;&#24314;&#31435;&#22312;&#8220;&#31616;&#21333;&#12289;&#19968;&#33268;&#12289;&#26131;&#35760;&#8221;&#20043;&#19978;&#65292;&#36234;&#24448;&#8220;&#23500;&#26377;&#34920;&#29616;&#21147;&#8221;&#30340;&#26041;&#21521;&#22534;&#21472;&#21464;&#20307;&#65292;&#36234;&#26159;&#22312;&#31232;&#37322;&#22270;&#26631;&#26412;&#35813;&#25215;&#25285;&#30340;&#21363;&#26102;&#36776;&#35782;&#21151;&#33021;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0145-08"><span>ImmersiveMap&#65306;&#29992; SwiftUI &#19982; Metal &#26500;&#24314;&#21407;&#29983;&#27785;&#28024;&#24335;&#22320;&#22270;</span></a></strong></h3><p><span>ImmersiveMap &#26159; </span><a href="https://x.com/BobkinArtem"><span>Artem Bobkin</span></a><span> &#24320;&#21457;&#30340;&#19968;&#27454;&#38754;&#21521; Apple &#24179;&#21488;&#30340;&#21407;&#29983;&#22320;&#22270;&#28210;&#26579;&#24341;&#25806;&#65292;&#29992; Swift &#19982; Metal &#23454;&#29616;&#65292;&#24182;&#36890;&#36807; </span><code>ImmersiveMapView</code><span> &#25552;&#20379;&#31526;&#21512; SwiftUI &#20351;&#29992;&#20064;&#24815;&#30340;&#22768;&#26126;&#24335;&#25509;&#21475;&#12290;</span></p><p><span>&#39033;&#30446;&#26368;&#32768;&#30524;&#30340;&#33021;&#21147;&#65292;&#26159;&#29699;&#24418;&#22320;&#29699;&#19982;&#24179;&#38754;&#22320;&#22270;&#20043;&#38388;&#30340;&#36830;&#32493;&#36807;&#28193;&#12290;&#27492;&#22806;&#65292;&#23427;&#36824;&#28085;&#30422;&#30690;&#37327;&#29926;&#29255;&#65288;Vector Tile Source&#65289;&#35299;&#26512;&#12289;&#26631;&#31614;&#24067;&#23616;&#12289;3D &#24314;&#31569;&#12289;&#26143;&#31354;&#19982;&#26172;&#22812;&#25928;&#26524;&#12289;&#22320;&#22270;&#26679;&#24335;&#12289;&#30456;&#26426;&#39134;&#34892;&#21160;&#30011;&#65292;&#20197;&#21450;&#25903;&#25345;&#32858;&#21512;&#19982;&#21160;&#24577;&#31227;&#21160;&#30340;&#23454;&#26102;&#26631;&#35760;&#12290;&#24320;&#21457;&#32773;&#26082;&#21487;&#20197;&#30452;&#25509;&#20351;&#29992;&#20869;&#32622;&#29926;&#29255;&#36816;&#34892;&#65292;&#20063;&#21487;&#20197;&#25509;&#20837; Mapbox &#25110;&#33258;&#23450;&#20041;&#30340; MVT&#65288;Mapbox Vector Tile&#65289;&#25968;&#25454;&#28304;&#12290;</span></p><p><span>ImmersiveMap &#23436;&#25972;&#23637;&#31034;&#20102;&#22914;&#20309;&#25226;&#22797;&#26434;&#30340; Metal &#28210;&#26579;&#31995;&#32479;&#23553;&#35013;&#22312;&#31616;&#27905;&#30340; SwiftUI API &#20043;&#19979;&#12290;&#23545;&#20110;&#24819;&#29702;&#35299;&#22320;&#22270;&#24341;&#25806;&#12289;SwiftUI &#19982;&#24213;&#23618;&#22270;&#24418;&#28210;&#26579;&#22914;&#20309;&#21327;&#21516;&#24037;&#20316;&#30340;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;&#36825;&#26159;&#19968;&#20221;&#39047;&#20855;&#21442;&#32771;&#20215;&#20540;&#30340;&#24320;&#28304;&#39033;&#30446;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #144]]></title><description><![CDATA[When Every Data Write Comes at a New Price]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 13 Jul 2026 12:04:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NmMs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NmMs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NmMs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154602,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/206785933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NmMs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!NmMs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9d77e4-ec9d-42f0-90d1-221e81deee3c_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@liam_1?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Liam Briese</a><span> on </span><a href="https://unsplash.com/photos/macro-shot-photo-of-a-computer-ram-lYxQ5F9xBDM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Every Data Write Comes at a New Price</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-144/">Read on web &#8594;</a></p><p><span>Recently, OpenAI&#8217;s Codex was found to have a logging issue: the program kept writing large volumes of logs to a local database, causing the files to grow continuously and generating far more disk writes than normal. Bugs like this are hardly new. A few years ago, most people would probably have deleted the files, restarted the app, and waited for the next release to fix it.</span></p><p><span>This time, however, the reaction was noticeably different. Instead of asking how much disk space remained, more people began wondering how much data had already been written to their SSDs, whether it might affect flash endurance, and how much more they would have to pay for the same amount of memory and storage when replacing their devices in the future.</span></p><p><span>The Codex bug may not be any more serious than other runaway logging incidents in the past. What has changed is that </span><strong><span>every pointless write suddenly seems to come at a price again.</span></strong></p><p><span>As demand for AI compute continues to surge, memory manufacturers are increasingly prioritizing higher-margin, higher-demand products such as HBM, server memory, and enterprise SSDs. Consumer memory and SSDs are therefore receiving a smaller share of production capacity, while their prices continue to rise.</span></p><p><span>Memory and flash have always been cyclical industries, so price increases and declines are nothing unusual. What makes the current situation unsettling is that it no longer appears to be merely another inventory cycle. It is accompanied by a longer-term shift of industry resources toward AI infrastructure.</span></p><p><span>Even if prices eventually fall, consumers may not quickly return to the old assumption that large amounts of storage are practically free.</span></p><p><span>As storage stops feeling inexhaustible, developers may also need to reconsider their attitude toward resources.</span></p><p><span>When I first encountered computers, a common Apple II configuration had only 48 KB of memory. To make use of the additional 16 KB provided by an expansion card, developers had to arrange addresses, code, and data with great care, finding ways to make every byte count.</span></p><p><span>A game spanning tens of gigabytes today inevitably offers graphics, sound, world scale, and interactive complexity that would have been unimaginable in the Famicom/NES era. Yet its enormous size does not guarantee that it will be more enjoyable than a game measured in only tens of kilobytes.</span></p><p><span>This is not to say that modern software should not grow larger. What is worth examining is how, over many years, developers have grown accustomed to storage capacities increasing naturally and networks becoming ever faster. As long as there is still room for logs, caches, and temporary data, few people stop to ask why they exist or when they will be deleted.</span></p><p><span>Expensive SSDs will not automatically produce better software, nor will memory shortages suddenly make developers smarter. But once hardware can no longer be assumed to grow without limit, engineering questions that have long been overlooked begin to resurface.</span></p><p><span>I do not miss the days when developers had to struggle within a few dozen kilobytes.</span></p><p><span>What is worth recovering is not the scarcity itself, but an engineering habit that once felt natural and has gradually faded away:</span></p><p><strong><span>knowing why every byte arrives&#8212;and when it will leave.</span></strong></p><p><a href="https://fatbobman.com/en/weekly/issue-143/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-01"><span>Swift Task lifetime when an iOS device is locked</span></a></strong></h3><p><span>This Q&amp;A comes from the Apple Developer Forums. The original poster found that a Swift Task making several sequential REST requests would sometimes complete normally after the device was locked, sometimes pause, and occasionally time out. DTS engineer Quinn &#8220;The Eskimo!&#8221; explains that Swift Concurrency runs entirely within the app process. Once iOS suspends that process, the worker threads executing the Task also stop, and the Task itself receives no additional background execution privileges.</span></p><p><span>This behavior can be especially confusing when networking is involved. If the app is suspended while a URLSession request is in progress, the request may fail because the connection becomes defunct. When the process resumes, developers may see a timeout or networking error rather than the Task continuing from where it paused and completing successfully. Quinn outlines four possible approaches: delay process suspension, stop in-flight requests before the app becomes eligible for suspension, allow requests to fail and implement retry and error recovery, or use a URLSession background session.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-02"><span>anyAppleOS in Swift 6.4</span></a></strong></h3><p><span>In the past, declaring availability for an API shared across Apple platforms required developers to list each platform and its corresponding OS version separately. Because version numbers differed across platforms for many years, these declarations were not only verbose but also prone to omissions and versioning mistakes. With Apple&#8217;s platforms adopting aligned major version numbers starting at 26, Swift 6.4 introduces </span><code>anyAppleOS</code><span>, allowing developers to describe APIs and code targeting Apple operating systems more concisely in </span><code>@available</code><span>, </span><code>#available</code><span>, and </span><code>#if os(...)</code><span>.</span></p><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; introduces the new syntax and explains how it differs from platform-specific availability, </span><code>canImport</code><span>, and the platform declarations in </span><code>Package.swift</code><span>. He also shows how more specific availability rules can be combined with </span><code>anyAppleOS</code><span> when support arrives later on certain platforms or is unavailable altogether.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-03"><span>The Anatomy of a Reusable SwiftUI View</span></a></strong></h3><p><span>More developers are trying to make the APIs of their reusable SwiftUI views feel as close as possible to Apple&#8217;s own designs, but there is often no clear methodology for putting that goal into practice. </span><a href="https://x.com/_al_we"><span>Alexander Wei&#223;</span></a><span>&#8288; shares his approach: first determine whether a component is semantic, describing a functional concept, or prescriptive, carrying a clearly defined visual form. From there, define its semantics, valid states, data flow, and interaction behavior. Components should also follow SwiftUI&#8217;s state-management conventions, use immutable values, Binding, and State appropriately, and treat accessibility, environment values, and stable view identity as part of the design rather than focusing only on the shape of the call site.</span></p><p><span>Using Card, Tag, and Rating as examples, the article demonstrates concrete implementations involving initializers, custom View Styles, and environment values. The central idea is not simply to imitate the appearance of Apple&#8217;s APIs, but to make custom components genuinely fit into the SwiftUI ecosystem through their composition model, state flow, interaction behavior, accessibility support, and environmental adaptation.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-04"><span>The hidden cost of unstable SwiftUI environment defaults</span></a></strong></h3><p><span>The </span><code>@Entry</code><span> macro makes custom environment values easier to declare, but directly using a reference-type instance as the default, such as </span><code>@Entry var logger = AppLogger()</code><span>, can cause unnecessary view updates. Whenever SwiftUI cannot find an injected value higher in the hierarchy and falls back to the default, it may create a new </span><code>AppLogger</code><span>. Although these objects behave identically, they are not the same instance, so SwiftUI may treat the environment value as changed and re-evaluate views that read it. Starting with Xcode 27, the compiler warns about this pattern, making a previously subtle issue easier to catch.</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>&#8288; uses </span><code>_printChanges()</code><span> to demonstrate the issue directly and offers two solutions: keep the default instance in stable external storage, or declare the environment value as Optional and inject it explicitly at the app entry point.</span></p><p><span>I also analyzed this issue in </span><a href="https://fatbobman.com/en/posts/swiftui-environment-concepts-and-practice/#repeated-instance-creation-with-the-entry-macro"><span>SwiftUI Environment: Concepts and Practice</span></a><span>&#8288;. The root cause lies in how the </span><code>@Entry</code><span> macro generates the default environment value, allowing the default expression to be evaluated repeatedly whenever fallback access occurs.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-05"><span>Make Vertical Parallax for ScrollView in SwiftUI</span></a></strong></h3><p><span>Early 2D games created rich visual depth at very little cost by moving different image layers at different speeds. In SwiftUI, however, the difficult part of implementing scroll-based parallax is usually not calculating the offset, but continuously obtaining each view&#8217;s position within a </span><code>ScrollView</code><span>. In the past, this often required a combination of </span><code>GeometryReader</code><span>, custom coordinate spaces, and state propagation, resulting in more code and potentially causing unnecessary view updates when handled poorly.</span></p><p><span>The introduction of </span><code>visualEffect</code><span> has greatly reduced the complexity of building these effects. </span><a href="https://x.com/Codelaby"><span>codelaby</span></a><span>&#8288; demonstrates how to read a view&#8217;s geometry directly inside </span><code>visualEffect</code><span> and apply an </span><code>offset</code><span> based on its scroll position, without maintaining additional state or changing the view&#8217;s original layout.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-06"><span>swift-span-algorithms: Adding Algorithmic Capabilities to Span</span></a></strong></h3><p><span>When working with contiguous memory, Swift developers traditionally had two main choices. Types such as </span><code>Array</code><span> and </span><code>ContiguousArray</code><span> own their storage and are safe and convenient, but may involve copying, reference counting, or additional allocation. Pointer types such as </span><code>UnsafeBufferPointer</code><span> offer low overhead and greater control, but require developers to ensure that the underlying memory remains valid and that every access stays within bounds.</span></p><p><span>Introduced in Swift 6.2, </span><code>Span&lt;Element&gt;</code><span> fills the gap between these approaches. It is a non-owning view over contiguous memory: it does not retain the underlying storage, but relies on compiler-enforced lifetime tracking and bounds checks to provide safe access. In Swift 6.2, however, Span does not yet offer the same breadth of algorithms available to Collection and Sequence.</span></p><p><a href="https://www.linkedin.com/in/david-retegan-72b298261/"><span>David Retegan</span></a><span>&#8288; created swift-span-algorithms to fill that gap. The library adds searching, comparison, trimming, chunking, sliding windows, splitting, cursor-based operations, and other utilities for Span, RawSpan, MutableSpan, and InlineArray. It is designed around zero hidden allocations and constant additional space, extending Span&#8217;s algorithmic capabilities while continuing to respect its lifetime constraints.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-144?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403;&#27599;&#19968;&#27425;&#20889;&#20837;&#37117;&#26377;&#20102;&#26032;&#20215;&#26684;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-144/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#26368;&#36817;&#65292;OpenAI &#30340; Codex &#34987;&#21457;&#29616;&#23384;&#22312;&#19968;&#20010;&#26085;&#24535;&#20889;&#20837;&#38382;&#39064;&#65306;&#31243;&#24207;&#20250;&#25345;&#32493;&#21521;&#26412;&#22320;&#25968;&#25454;&#24211;&#20889;&#20837;&#22823;&#37327;&#26085;&#24535;&#65292;&#23548;&#33268;&#25991;&#20214;&#19981;&#26029;&#33192;&#32960;&#65292;&#24182;&#20135;&#29983;&#36828;&#36229;&#27491;&#24120;&#27700;&#24179;&#30340;&#30913;&#30424;&#20889;&#20837;&#12290;&#31867;&#20284;&#30340; Bug &#36807;&#21435;&#24182;&#19981;&#23569;&#35265;&#12290;&#25918;&#22312;&#20960;&#24180;&#21069;&#65292;&#20154;&#20204;&#22823;&#27010;&#21482;&#26159;&#21024;&#38500;&#25991;&#20214;&#12289;&#37325;&#21551;&#24212;&#29992;&#65292;&#28982;&#21518;&#31561;&#24453;&#19979;&#19968;&#20010;&#29256;&#26412;&#20462;&#22797;&#12290;</span></p><p><span>&#20294;&#36825;&#19968;&#27425;&#65292;&#22823;&#23478;&#30340;&#21453;&#24212;&#26126;&#26174;&#19981;&#21516;&#12290;&#27604;&#36215;&#8220;&#36824;&#21097;&#22810;&#23569;&#30913;&#30424;&#31354;&#38388;&#8221;&#65292;&#26356;&#22810;&#20154;&#24320;&#22987;&#20851;&#24515; SSD &#24050;&#32463;&#32047;&#35745;&#20889;&#20837;&#20102;&#22810;&#23569;&#25968;&#25454;&#65292;&#20250;&#19981;&#20250;&#24433;&#21709;&#38378;&#23384;&#23551;&#21629;&#65292;&#20197;&#21450;&#26410;&#26469;&#26356;&#25442;&#35774;&#22791;&#26102;&#65292;&#38656;&#35201;&#20026;&#21516;&#26679;&#23481;&#37327;&#30340;&#20869;&#23384;&#21644;&#23384;&#20648;&#22810;&#20184;&#22810;&#23569;&#38065;&#12290;</span></p><p><span>Codex &#30340; Bug &#26410;&#24517;&#27604;&#36807;&#21435;&#37027;&#20123;&#22833;&#25511;&#30340;&#26085;&#24535;&#31243;&#24207;&#26356;&#21152;&#20005;&#37325;&#12290;&#30495;&#27491;&#21457;&#29983;&#21464;&#21270;&#30340;&#26159;&#65306;</span><strong><span>&#27599;&#19968;&#27425;&#26080;&#24847;&#20041;&#30340;&#20889;&#20837;&#65292;&#20284;&#20046;&#37117;&#37325;&#26032;&#26377;&#20102;&#20215;&#26684;&#12290;</span></strong></p><p><span>&#38543;&#30528; AI &#31639;&#21147;&#38656;&#27714;&#36805;&#36895;&#22686;&#38271;&#65292;&#23384;&#20648;&#22120;&#21378;&#21830;&#36234;&#26469;&#36234;&#20542;&#21521;&#20110;&#20248;&#20808;&#20445;&#38556; HBM&#12289;&#26381;&#21153;&#22120;&#20869;&#23384;&#21644;&#20225;&#19994;&#32423; SSD &#31561;&#21033;&#28070;&#26356;&#39640;&#12289;&#38656;&#27714;&#26356;&#26106;&#30427;&#30340;&#20135;&#21697;&#12290;&#28040;&#36153;&#32423;&#20869;&#23384;&#21644; SSD &#33021;&#22815;&#20998;&#37197;&#21040;&#30340;&#20135;&#33021;&#22240;&#27492;&#21463;&#21040;&#25380;&#21387;&#65292;&#20215;&#26684;&#20063;&#19981;&#26029;&#36208;&#39640;&#12290;</span></p><p><span>&#20869;&#23384;&#21644;&#38378;&#23384;&#26412;&#26469;&#23601;&#26159;&#20856;&#22411;&#30340;&#21608;&#26399;&#24615;&#34892;&#19994;&#65292;&#20215;&#26684;&#19978;&#28072;&#21644;&#19979;&#36300;&#24182;&#19981;&#32597;&#35265;&#12290;&#20294;&#36825;&#19968;&#36718;&#21464;&#21270;&#20196;&#20154;&#19981;&#23433;&#30340;&#22320;&#26041;&#65292;&#22312;&#20110;&#23427;&#20284;&#20046;&#19981;&#20877;&#21482;&#26159;&#19968;&#27425;&#31616;&#21333;&#30340;&#24211;&#23384;&#21608;&#26399;&#65292;&#32780;&#26159;&#20276;&#38543;&#30528;&#20135;&#19994;&#36164;&#28304;&#21521; AI &#22522;&#30784;&#35774;&#26045;&#38271;&#26399;&#20542;&#26012;&#12290;</span></p><p><span>&#21363;&#20351;&#20215;&#26684;&#26368;&#32456;&#20173;&#20250;&#22238;&#33853;&#65292;&#28040;&#36153;&#32773;&#24656;&#24597;&#20063;&#24456;&#38590;&#36805;&#36895;&#22238;&#21040;&#36807;&#21435;&#37027;&#31181;&#8220;&#22823;&#23481;&#37327;&#36817;&#20046;&#20813;&#36153;&#8221;&#30340;&#24515;&#29702;&#39044;&#26399;&#12290;</span></p><p><span>&#24403;&#23384;&#20648;&#19981;&#20877;&#26174;&#24471;&#21462;&#20043;&#19981;&#23613;&#26102;&#65292;&#24320;&#21457;&#32773;&#25110;&#35768;&#20063;&#24212;&#35813;&#36716;&#21464;&#23545;&#36164;&#28304;&#26102;&#30340;&#24577;&#24230;&#12290;</span></p><p><span>&#22312;&#25105;&#26368;&#24320;&#22987;&#25509;&#35302;&#30005;&#33041;&#26102;&#65292;Apple II &#24120;&#35265;&#30340;&#20869;&#23384;&#37197;&#32622;&#21482;&#26377; 48 KB&#12290;&#20026;&#20102;&#20351;&#29992;&#25193;&#23637;&#21345;&#39069;&#22806;&#25552;&#20379;&#30340; 16 KB &#31354;&#38388;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#20180;&#32454;&#23433;&#25490;&#22320;&#22336;&#12289;&#20195;&#30721;&#21644;&#25968;&#25454;&#65292;&#24819;&#26041;&#35774;&#27861;&#25226;&#27599;&#19968;&#20010;&#23383;&#33410;&#37117;&#21033;&#29992;&#36215;&#26469;&#12290;</span></p><p><span>&#20170;&#22825;&#19968;&#20010;&#25968;&#21313; GB &#30340;&#28216;&#25103;&#65292;&#24517;&#28982;&#25317;&#26377; FC &#26102;&#20195;&#26080;&#27861;&#24819;&#35937;&#30340;&#30011;&#38754;&#12289;&#22768;&#38899;&#12289;&#19990;&#30028;&#35268;&#27169;&#21644;&#20132;&#20114;&#22797;&#26434;&#24230;&#12290;&#28982;&#32780;&#65292;&#24040;&#22823;&#30340;&#23481;&#37327;&#24182;&#19981;&#33021;&#20445;&#35777;&#23427;&#24102;&#26469;&#30340;&#20048;&#36259;&#19968;&#23450;&#36229;&#36807;&#19968;&#20010;&#21482;&#26377;&#20960;&#21313; KB &#30340;&#28216;&#25103;&#12290;</span></p><p><span>&#36825;&#24182;&#19981;&#26159;&#35828;&#29616;&#20195;&#36719;&#20214;&#19981;&#24212;&#35813;&#21464;&#22823;&#12290;&#30495;&#27491;&#20540;&#24471;&#24605;&#32771;&#30340;&#26159;&#65292;&#22312;&#36807;&#21435;&#24456;&#22810;&#24180;&#20013;&#65292;&#24320;&#21457;&#32773;&#24050;&#32463;&#20064;&#24815;&#20102;&#23384;&#20648;&#23481;&#37327;&#20250;&#33258;&#28982;&#22686;&#38271;&#12289;&#32593;&#32476;&#20250;&#19981;&#26029;&#21464;&#24555;&#12290;&#26085;&#24535;&#12289;&#32531;&#23384;&#21644;&#20020;&#26102;&#25968;&#25454;&#21482;&#35201;&#26242;&#26102;&#36824;&#25918;&#24471;&#19979;&#65292;&#23601;&#24456;&#23569;&#26377;&#20154;&#36861;&#38382;&#23427;&#20204;&#20026;&#20160;&#20040;&#23384;&#22312;&#65292;&#21448;&#23558;&#22312;&#20160;&#20040;&#26102;&#20505;&#34987;&#21024;&#38500;&#12290;</span></p><p><span>&#26114;&#36149;&#30340; SSD &#19981;&#20250;&#33258;&#21160;&#21019;&#36896;&#20248;&#31168;&#30340;&#36719;&#20214;&#65292;&#20869;&#23384;&#30701;&#32570;&#20063;&#19981;&#20250;&#35753;&#24320;&#21457;&#32773;&#31361;&#28982;&#21464;&#24471;&#26356;&#21152;&#32874;&#26126;&#12290;&#20294;&#24403;&#30828;&#20214;&#19981;&#20877;&#34987;&#40664;&#35748;&#20250;&#26080;&#38480;&#22686;&#38271;&#26102;&#65292;&#37027;&#20123;&#26366;&#32463;&#34987;&#24573;&#35270;&#30340;&#24037;&#31243;&#38382;&#39064;&#20415;&#20250;&#37325;&#26032;&#28014;&#20986;&#27700;&#38754;&#12290;</span></p><p><span>&#25105;&#24182;&#19981;&#24576;&#24565;&#37027;&#20010;&#38656;&#35201;&#22312;&#20960;&#21313; KB &#20013;&#21453;&#22797;&#33150;&#25386;&#30340;&#26102;&#20195;&#12290;</span></p><p><span>&#30495;&#27491;&#20540;&#24471;&#37325;&#26032;&#25342;&#36215;&#30340;&#65292;&#24182;&#19981;&#26159;&#36164;&#28304;&#21294;&#20047;&#65292;&#32780;&#26159;&#37027;&#31181;&#26366;&#32463;&#21313;&#20998;&#33258;&#28982;&#12289;&#21518;&#26469;&#21364;&#36880;&#28176;&#28040;&#22833;&#30340;&#24037;&#31243;&#20064;&#24815;&#65306;</span></p><p><strong><span>&#30693;&#36947;&#27599;&#19968;&#20010;&#23383;&#33410;&#20026;&#20160;&#20040;&#21040;&#26469;&#65292;&#20063;&#30693;&#36947;&#23427;&#23558;&#22312;&#20160;&#20040;&#26102;&#20505;&#31163;&#24320;&#12290;</span></strong></p><p><a href="https://fatbobman.com/zh/weekly/issue-143/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-01"><span>iOS &#35774;&#22791;&#38145;&#23450;&#21518;&#65292;Swift Task &#33021;&#36816;&#34892;&#22810;&#20037;&#65311;(Swift Task lifetime when an iOS device is locked)</span></a></strong></h3><p><span>&#36825;&#26159;&#19968;&#31687;&#26469;&#33258; Apple Developer Forums &#30340;&#38382;&#31572;&#12290;&#25552;&#38382;&#32773;&#21457;&#29616;&#65292;&#19968;&#20010;&#20250;&#20018;&#34892;&#25191;&#34892;&#22810;&#20010; REST &#35831;&#27714;&#30340; Swift Task&#65292;&#22312;&#35774;&#22791;&#38145;&#23450;&#21518;&#26377;&#26102;&#33021;&#22815;&#27491;&#24120;&#23436;&#25104;&#65292;&#26377;&#26102;&#20250;&#26242;&#20572;&#65292;&#29978;&#33267;&#20986;&#29616;&#36229;&#26102;&#12290;DTS &#24037;&#31243;&#24072; Quinn &#8220;The Eskimo!&#8221; &#35299;&#37322;&#36947;&#65292;Swift Concurrency &#23436;&#20840;&#36816;&#34892;&#22312;&#24212;&#29992;&#36827;&#31243;&#20013;&#65307;&#19968;&#26086; iOS &#25346;&#36215;&#36827;&#31243;&#65292;&#25191;&#34892; Task &#30340;&#24037;&#20316;&#32447;&#31243;&#20063;&#20250;&#20572;&#27490;&#65292;Task &#26412;&#36523;&#24182;&#19981;&#20250;&#33719;&#24471;&#39069;&#22806;&#30340;&#21518;&#21488;&#36816;&#34892;&#33021;&#21147;&#12290;</span></p><p><span>&#36825;&#31181;&#26426;&#21046;&#22312;&#32593;&#32476;&#35831;&#27714;&#20013;&#23588;&#20854;&#23481;&#26131;&#36896;&#25104;&#22256;&#24785;&#12290;&#24212;&#29992;&#34987;&#25346;&#36215;&#26102;&#65292;&#27491;&#22312;&#36827;&#34892;&#30340; URLSession &#35831;&#27714;&#21487;&#33021;&#22240;&#36830;&#25509;&#22833;&#25928;&#32780;&#22833;&#36133;&#65307;&#36827;&#31243;&#24674;&#22797;&#21518;&#65292;&#24320;&#21457;&#32773;&#30475;&#21040;&#30340;&#21487;&#33021;&#26159;&#35831;&#27714;&#36229;&#26102;&#25110;&#32593;&#32476;&#38169;&#35823;&#65292;&#32780;&#19981;&#26159; Task &#20174;&#26242;&#20572;&#22788;&#32487;&#32493;&#24182;&#39034;&#21033;&#23436;&#25104;&#12290;Quinn &#32473;&#20986;&#20102;&#22235;&#31181;&#22788;&#29702;&#26041;&#21521;&#65306;&#35774;&#27861;&#24310;&#32531;&#36827;&#31243;&#25346;&#36215;&#12289;&#22312;&#24212;&#29992;&#21363;&#23558;&#34987;&#25346;&#36215;&#26102;&#20572;&#27490;&#35831;&#27714;&#12289;&#20801;&#35768;&#35831;&#27714;&#22833;&#36133;&#24182;&#20570;&#22909;&#37325;&#35797;&#19982;&#38169;&#35823;&#24674;&#22797;&#65292;&#25110;&#32773;&#20351;&#29992; URLSession &#30340;&#21518;&#21488;&#20250;&#35805;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-02"><span>Swift 6.4 &#20013;&#30340; anyAppleOS (anyAppleOS in Swift 6.4)</span></a></strong></h3><p><span>&#36807;&#21435;&#65292;&#20026;&#36328; Apple &#24179;&#21488;&#20849;&#20139;&#30340; API &#22768;&#26126;&#21487;&#29992;&#24615;&#26102;&#65292;&#24320;&#21457;&#32773;&#38656;&#35201;&#20998;&#21035;&#21015;&#20986;&#21508;&#20010;&#24179;&#21488;&#21450;&#20854;&#23545;&#24212;&#30340;&#31995;&#32479;&#29256;&#26412;&#12290;&#30001;&#20110;&#19981;&#21516;&#24179;&#21488;&#30340;&#29256;&#26412;&#21495;&#38271;&#26399;&#19981;&#19968;&#33268;&#65292;&#36825;&#31867;&#22768;&#26126;&#19981;&#20165;&#20887;&#38271;&#65292;&#20063;&#23481;&#26131;&#20986;&#29616;&#36951;&#28431;&#25110;&#29256;&#26412;&#22635;&#20889;&#38169;&#35823;&#12290;&#38543;&#30528; Apple &#21508;&#24179;&#21488;&#20174; 26 &#24320;&#22987;&#32479;&#19968;&#29256;&#26412;&#21495;&#65292;Swift 6.4 &#24341;&#20837;&#20102; </span><code>anyAppleOS</code><span>&#65292;&#20801;&#35768;&#24320;&#21457;&#32773;&#22312; </span><code>@available</code><span>&#12289;</span><code>#available</code><span> &#21644; </span><code>#if os(...)</code><span> &#20013;&#65292;&#20197;&#26356;&#31616;&#27905;&#30340;&#26041;&#24335;&#25551;&#36848;&#36866;&#29992;&#20110; Apple &#25805;&#20316;&#31995;&#32479;&#30340; API &#19982;&#20195;&#30721;&#12290;</span></p><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; &#20171;&#32461;&#20102;&#36825;&#19968;&#26032;&#35821;&#27861;&#65292;&#24182;&#26803;&#29702;&#20102;&#23427;&#19982;&#24179;&#21488;&#19987;&#23646;&#21487;&#29992;&#24615;&#12289;</span><code>canImport</code><span> &#20197;&#21450; </span><code>Package.swift</code><span> &#24179;&#21488;&#22768;&#26126;&#20043;&#38388;&#30340;&#21306;&#21035;&#65292;&#21516;&#26102;&#35828;&#26126;&#20102;&#22914;&#20309;&#32467;&#21512;&#26356;&#20855;&#20307;&#30340;&#21487;&#29992;&#24615;&#35268;&#21017;&#65292;&#22788;&#29702;&#37096;&#20998;&#24179;&#21488;&#24310;&#21518;&#25903;&#25345;&#25110;&#23436;&#20840;&#19981;&#21487;&#29992;&#30340;&#24773;&#20917;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-03"><span>&#21487;&#22797;&#29992; SwiftUI &#35270;&#22270;&#30340;&#35774;&#35745;&#21078;&#26512; (The Anatomy of a Reusable SwiftUI View)</span></a></strong></h3><p><span>&#36234;&#26469;&#36234;&#22810;&#30340;&#24320;&#21457;&#32773;&#22312;&#26500;&#24314;&#21487;&#22797;&#29992; SwiftUI &#35270;&#22270;&#26102;&#65292;&#37117;&#24076;&#26395;&#20854; API &#23613;&#21487;&#33021;&#36148;&#36817; Apple &#23448;&#26041;&#30340;&#35774;&#35745;&#26041;&#24335;&#65292;&#20294;&#20855;&#20307;&#22914;&#20309;&#33853;&#22320;&#65292;&#24448;&#24448;&#32570;&#23569;&#19968;&#22871;&#28165;&#26224;&#30340;&#26041;&#27861;&#12290;</span><a href="https://x.com/_al_we"><span>Alexander Wei&#223;</span></a><span>&#8288; &#32473;&#20986;&#20102;&#33258;&#24049;&#30340;&#35774;&#35745;&#24605;&#36335;&#65306;&#39318;&#20808;&#21028;&#26029;&#32452;&#20214;&#23646;&#20110;&#25551;&#36848;&#21151;&#33021;&#27010;&#24565;&#30340;&#35821;&#20041;&#22411;&#32452;&#20214;&#65292;&#36824;&#26159;&#20855;&#26377;&#26126;&#30830;&#35270;&#35273;&#24418;&#24577;&#30340;&#35268;&#23450;&#22411;&#32452;&#20214;&#65292;&#20877;&#26803;&#29702;&#20854;&#35821;&#20041;&#12289;&#21512;&#27861;&#29366;&#24577;&#12289;&#25968;&#25454;&#27969;&#19982;&#20132;&#20114;&#34892;&#20026;&#12290;&#21516;&#26102;&#65292;&#32452;&#20214;&#36824;&#24212;&#36981;&#24490; SwiftUI &#30340;&#29366;&#24577;&#31649;&#29702;&#26041;&#24335;&#65292;&#27491;&#30830;&#20351;&#29992;&#19981;&#21487;&#21464;&#20540;&#12289;Binding &#19982; State&#65292;&#24182;&#23558;&#26080;&#38556;&#30861;&#25903;&#25345;&#12289;&#29615;&#22659;&#20540;&#21644;&#35270;&#22270;&#36523;&#20221;&#31283;&#23450;&#24615;&#32435;&#20837;&#35774;&#35745;&#65292;&#32780;&#19981;&#21482;&#26159;&#20851;&#27880; API &#30340;&#35843;&#29992;&#24418;&#24335;&#12290;</span></p><p><span>&#25991;&#31456;&#36890;&#36807; Card&#12289;Tag &#21644; Rating &#19977;&#20010;&#31034;&#20363;&#23637;&#31034;&#20102;&#21021;&#22987;&#21270;&#26041;&#27861;&#12289;&#33258;&#23450;&#20041; View Style &#21644;&#29615;&#22659;&#20540;&#31561;&#20855;&#20307;&#23454;&#29616;&#12290;&#36825;&#22871;&#26041;&#27861;&#30340;&#26680;&#24515;&#24182;&#38750;&#31616;&#21333;&#27169;&#20223; Apple API &#30340;&#22806;&#24418;&#65292;&#32780;&#26159;&#35753;&#33258;&#23450;&#20041;&#32452;&#20214;&#22312;&#32452;&#21512;&#26041;&#24335;&#12289;&#29366;&#24577;&#27969;&#36716;&#12289;&#20132;&#20114;&#34892;&#20026;&#12289;&#26080;&#38556;&#30861;&#25903;&#25345;&#21644;&#29615;&#22659;&#36866;&#37197;&#31561;&#26041;&#38754;&#30495;&#27491;&#34701;&#20837; SwiftUI &#20307;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-04"><span>SwiftUI &#29615;&#22659;&#40664;&#35748;&#20540;&#19981;&#31283;&#23450;&#30340;&#38544;&#24615;&#25104;&#26412; (The hidden cost of unstable SwiftUI environment defaults)</span></a></strong></h3><p><code>@Entry</code><span> &#23439;&#35753;&#33258;&#23450;&#20041;&#29615;&#22659;&#20540;&#30340;&#22768;&#26126;&#26356;&#21152;&#20415;&#25463;&#65292;&#20294;&#22914;&#26524;&#30452;&#25509;&#23558;&#24341;&#29992;&#31867;&#22411;&#23454;&#20363;&#20316;&#20026;&#40664;&#35748;&#20540;&#65292;&#20363;&#22914; </span><code>@Entry var logger = AppLogger()</code><span>&#65292;&#23601;&#21487;&#33021;&#24102;&#26469;&#19981;&#24517;&#35201;&#30340;&#35270;&#22270;&#26356;&#26032;&#12290;&#27599;&#24403; SwiftUI &#27809;&#26377;&#25214;&#21040;&#19978;&#23618;&#27880;&#20837;&#30340;&#20540;&#32780;&#22238;&#36864;&#21040;&#40664;&#35748;&#20540;&#26102;&#65292;&#37117;&#21487;&#33021;&#37325;&#26032;&#21019;&#24314;&#19968;&#20010; </span><code>AppLogger</code><span>&#12290;&#36825;&#20123;&#23545;&#35937;&#34429;&#28982;&#21151;&#33021;&#30456;&#21516;&#65292;&#21364;&#19981;&#26159;&#21516;&#19968;&#20010;&#23454;&#20363;&#65292;&#22240;&#27492; SwiftUI &#20250;&#35748;&#20026;&#29615;&#22659;&#20540;&#21457;&#29983;&#20102;&#21464;&#21270;&#65292;&#36827;&#32780;&#37325;&#26032;&#35745;&#31639;&#35835;&#21462;&#23427;&#30340;&#35270;&#22270;&#12290;Xcode 27 &#24320;&#22987;&#20250;&#38024;&#23545;&#36825;&#31181;&#20889;&#27861;&#21457;&#20986;&#35686;&#21578;&#65292;&#35753;&#36825;&#20010;&#36807;&#21435;&#19981;&#26131;&#23519;&#35273;&#30340;&#38382;&#39064;&#26356;&#26089;&#26292;&#38706;&#20986;&#26469;&#12290;</span></p><p><a href="https://x.com/natpanferova"><span>Natalia Panferova</span></a><span>&#8288; &#20351;&#29992; </span><code>_printChanges()</code><span> &#30452;&#35266;&#23637;&#31034;&#20102;&#36825;&#19968;&#38382;&#39064;&#65292;&#24182;&#32473;&#20986;&#20004;&#31181;&#35299;&#20915;&#26041;&#24335;&#65306;&#23558;&#40664;&#35748;&#23454;&#20363;&#20445;&#23384;&#22312;&#31283;&#23450;&#30340;&#22806;&#37096;&#23384;&#20648;&#20013;&#65292;&#25110;&#32773;&#23558;&#29615;&#22659;&#20540;&#22768;&#26126;&#20026; Optional&#65292;&#20877;&#30001;&#24212;&#29992;&#20837;&#21475;&#26174;&#24335;&#27880;&#20837;&#12290;</span></p><blockquote><p><span>&#25105;&#22312;&#12298;</span><a href="https://fatbobman.com/zh/posts/swiftui-environment-concepts-and-practice/#entry-%E5%AE%8F%E7%9A%84%E5%AE%9E%E4%BE%8B%E9%87%8D%E5%A4%8D%E5%88%9B%E5%BB%BA%E9%97%AE%E9%A2%98"><span>SwiftUI Environment&#65306;&#29702;&#24565;&#19982;&#23454;&#36341;</span></a><span>&#12299;&#20013;&#20063;&#20998;&#26512;&#36807;&#36825;&#19968;&#38382;&#39064;&#12290;&#20854;&#26681;&#28304;&#22312;&#20110; </span><code>@Entry</code><span> &#23439;&#29983;&#25104;&#40664;&#35748;&#29615;&#22659;&#20540;&#30340;&#26041;&#24335;&#65292;&#20351;&#40664;&#35748;&#34920;&#36798;&#24335;&#21487;&#33021;&#22312;&#22238;&#36864;&#35775;&#38382;&#26102;&#34987;&#37325;&#22797;&#27714;&#20540;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0144-05"><span>&#20351;&#29992; visualEffect &#20026; SwiftUI ScrollView &#21019;&#24314;&#32437;&#21521;&#35270;&#24046;&#25928;&#26524; (Make Vertical Parallax for ScrollView in SwiftUI)</span></a></strong></h3><p><span>&#26089;&#26399;&#30340;&#20108;&#32500;&#28216;&#25103;&#36890;&#36807;&#35753;&#19981;&#21516;&#22270;&#23618;&#20197;&#19981;&#21516;&#36895;&#24230;&#31227;&#21160;&#65292;&#29992;&#24456;&#20302;&#30340;&#25104;&#26412;&#20415;&#33829;&#36896;&#20986;&#20102;&#23500;&#26377;&#23618;&#27425;&#24863;&#30340;&#35270;&#35273;&#25928;&#26524;&#12290;&#20294;&#22312; SwiftUI &#20013;&#23454;&#29616;&#28378;&#21160;&#35270;&#24046;&#65292;&#30495;&#27491;&#40635;&#28902;&#30340;&#36890;&#24120;&#19981;&#26159;&#35745;&#31639;&#20559;&#31227;&#37327;&#65292;&#32780;&#26159;&#25345;&#32493;&#33719;&#21462;&#27599;&#20010;&#35270;&#22270;&#22312; </span><code>ScrollView</code><span> &#20013;&#30340;&#20301;&#32622;&#12290;&#36807;&#21435;&#65292;&#36825;&#31867;&#25928;&#26524;&#24448;&#24448;&#38656;&#35201;&#32467;&#21512; </span><code>GeometryReader</code><span>&#12289;&#33258;&#23450;&#20041;&#22352;&#26631;&#31354;&#38388;&#21644;&#29366;&#24577;&#20256;&#36882;&#26469;&#23436;&#25104;&#65292;&#19981;&#20165;&#20195;&#30721;&#37327;&#36739;&#22823;&#65292;&#22788;&#29702;&#19981;&#24403;&#36824;&#21487;&#33021;&#24341;&#21457;&#39069;&#22806;&#30340;&#35270;&#22270;&#26356;&#26032;&#12290;</span></p><p><code>visualEffect</code><span> &#30340;&#24341;&#20837;&#22823;&#24133;&#38477;&#20302;&#20102;&#36825;&#31867;&#25928;&#26524;&#30340;&#23454;&#29616;&#38590;&#24230;&#12290;</span><a href="https://x.com/Codelaby"><span>codelaby</span></a><span>&#8288; &#23637;&#31034;&#20102;&#22914;&#20309;&#30452;&#25509;&#22312; </span><code>visualEffect</code><span> &#20013;&#35835;&#21462;&#35270;&#22270;&#30340;&#20960;&#20309;&#20449;&#24687;&#65292;&#24182;&#26681;&#25454;&#28378;&#21160;&#20301;&#32622;&#24212;&#29992; </span><code>offset</code><span>&#65292;&#26080;&#39035;&#39069;&#22806;&#32500;&#25252;&#29366;&#24577;&#65292;&#20063;&#19981;&#20250;&#25913;&#21464;&#35270;&#22270;&#21407;&#26377;&#30340;&#24067;&#23616;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0144-06"><span>swift-span-algorithms: &#32473; Span &#34917;&#19978;&#31639;&#27861;&#33021;&#21147;</span></a></strong></h3><p><span>&#22312;&#22788;&#29702;&#36830;&#32493;&#20869;&#23384;&#26102;&#65292;Swift &#36807;&#21435;&#20027;&#35201;&#26377;&#20004;&#31867;&#36873;&#25321;&#65306;&#20351;&#29992; </span><code>Array</code><span>&#12289;</span><code>ContiguousArray</code><span> &#31561;&#25317;&#26377;&#23384;&#20648;&#30340;&#23481;&#22120;&#65292;&#23433;&#20840;&#26131;&#29992;&#65292;&#20294;&#21487;&#33021;&#20276;&#38543;&#22797;&#21046;&#12289;&#24341;&#29992;&#35745;&#25968;&#25110;&#39069;&#22806;&#20998;&#37197;&#65307;&#20351;&#29992; </span><code>UnsafeBufferPointer</code><span> &#31561;&#25351;&#38024;&#31867;&#22411;&#65292;&#25104;&#26412;&#20302;&#12289;&#25511;&#21046;&#21147;&#24378;&#65292;&#21364;&#38656;&#35201;&#24320;&#21457;&#32773;&#33258;&#34892;&#20445;&#35777;&#20869;&#23384;&#20173;&#28982;&#26377;&#25928;&#65292;&#24182;&#36991;&#20813;&#36234;&#30028;&#35775;&#38382;&#12290;</span></p><p><span>Swift 6.2 &#26032;&#22686;&#30340; </span><code>Span&lt;Element&gt;</code><span> &#22635;&#34917;&#20102;&#20004;&#32773;&#20043;&#38388;&#30340;&#31354;&#30333;&#12290;&#23427;&#26159;&#19968;&#27573;&#36830;&#32493;&#20869;&#23384;&#30340;&#38750;&#25317;&#26377;&#35270;&#22270;&#65306;&#19981;&#25345;&#26377;&#24213;&#23618;&#23384;&#20648;&#65292;&#21364;&#33021;&#20511;&#21161;&#32534;&#35793;&#22120;&#36861;&#36394;&#29983;&#21629;&#21608;&#26399;&#65292;&#24182;&#36890;&#36807;&#36793;&#30028;&#26816;&#26597;&#25552;&#20379;&#23433;&#20840;&#35775;&#38382;&#12290;&#19981;&#36807;&#65292;&#22312; Swift 6.2 &#20013;&#65292;Span &#23578;&#26410;&#25317;&#26377; Collection&#12289;Sequence &#37027;&#33324;&#23436;&#25972;&#30340;&#31639;&#27861;&#33021;&#21147;&#12290;</span></p><p><a href="https://www.linkedin.com/in/david-retegan-72b298261/"><span>David Retegan</span></a><span> &#24320;&#21457;&#30340; swift-span-algorithms &#27491;&#26159;&#23545;&#36825;&#19968;&#32570;&#21475;&#30340;&#34917;&#20805;&#12290;&#23427;&#20026; Span&#12289;RawSpan&#12289;MutableSpan &#21644; InlineArray &#25552;&#20379;&#26597;&#25214;&#12289;&#27604;&#36739;&#12289;&#20462;&#21098;&#12289;&#20998;&#22359;&#12289;&#28369;&#21160;&#31383;&#21475;&#12289;&#20999;&#20998;&#21450;&#28216;&#26631;&#65288;Cursor&#65289;&#31561;&#25805;&#20316;&#12290;&#25972;&#20010;&#24211;&#38646;&#20197;&#26080;&#38544;&#34255;&#20998;&#37197;&#21644;&#24120;&#25968;&#32423;&#39069;&#22806;&#31354;&#38388;&#20026;&#35774;&#35745;&#30446;&#26631;&#65292;&#22312;&#25193;&#23637;&#31639;&#27861;&#33021;&#21147;&#30340;&#21516;&#26102;&#65292;&#20173;&#28982;&#36981;&#23432; Span &#30340;&#29983;&#21629;&#21608;&#26399;&#32422;&#26463;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #143]]></title><description><![CDATA[When Linux Becomes "Air": Containers, Agents, and a "Desktop War" That No Longer Matters]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 06 Jul 2026 12:03:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GmsY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GmsY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GmsY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:216564,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/205433093?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GmsY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!GmsY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17d3ccb8-d519-4896-ba3a-67222b1abefd_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@tri_gemini?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Sammy Xu</a><span> on </span><a href="https://unsplash.com/photos/a-tabby-cat-peeking-out-from-under-papers-63rXs30iJ9s?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>When Linux Becomes &#8220;Air&#8221;: Containers, Agents, and a &#8220;Desktop War&#8221; That No Longer Matters</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-143/">Read on web &#8594;</a></p><p><span>A week ago, Microsoft released the public preview of native Windows 11 container support that requires no Docker. Combined with Apple&#8217;s recent 1.0 release of its container manager (Apple Container), both major desktop operating systems have now deeply integrated Linux containers as first-class citizens of the system.</span></p><p><span>This has sparked an interesting debate. Some see it as Linux&#8217;s ultimate victory: it never truly won the desktop market, yet it is now everywhere. Others ask the opposite question: when both Windows and macOS can run Linux containers smoothly and with little overhead, is this really a victory for Linux &#8212; or the beginning of its complete &#8220;commoditization&#8221; and &#8220;invisibility&#8221;?</span></p><p><span>These two views may seem contradictory, but they both point to the same fact: the role of Linux is changing.</span></p><p><span>In the past, when we talked about an operating system, we were usually talking about a complete platform &#8212; one with its own desktop, applications, development model, user habits, and ecosystem boundaries. Windows is a platform, macOS is a platform, and Linux distributions are, of course, platforms too. Around these platforms, people debated market share, user experience, compatibility, and that &#8220;Year of the Linux Desktop&#8221; joke that has been recycled for decades.</span></p><p><span>But containers have changed the structure of the question.</span></p><p><span>In modern software development, Linux increasingly appears not as &#8220;the operating system you are using,&#8221; but as &#8220;the default runtime environment.&#8221; Developers rarely say &#8220;I deployed to Linux.&#8221; They are far more likely to say &#8220;I deployed to Kubernetes,&#8221; &#8220;I&#8217;m running on the cloud,&#8221; or &#8220;I used a container image.&#8221;</span></p><p><span>This shift will become even more pronounced in the age of AI agents. As agents evolve from simple chat assistants into tools that actually execute tasks, what they need is no longer just a conversational interface, but a lightweight, instantly bootable, fully isolated, and easily disposable execution environment. Containers are a natural fit for this role. And as more and more tasks are carried out through agents, the interface where humans interact directly with the operating system is quietly losing weight &#8212; the outcome of the decades-long &#8220;desktop war&#8221; matters less and less.</span></p><p><span>Linux, then, is outgrowing its identity as a &#8220;platform.&#8221; It never won the desktop market share battle, yet it has made its way into the foundation of nearly every modern computing system. It never convinced everyone to switch to Linux, yet it has compelled every platform to support the way Linux runs.</span></p><p><span>The highest form of victory is not having everyone chant your name, but having everyone depend on you &#8212; while barely remembering you&#8217;re there. This is a victory where silence speaks louder than words.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-142/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/debugging-notes-on-two-swiftui-animation-bugs/?utm_source=fatbobman%20weekly%20issue%20143&amp;utm_medium=web"><span>Debugging Notes on Two SwiftUI Animation Bugs</span></a></strong></h3><p><span>Easy-to-use animation has always been one of SwiftUI&#8217;s defining features. But the nature of a declarative framework is a double-edged sword: once an animation misbehaves, tracking down the cause is often trickier than in an imperative framework. This post records two SwiftUI animation bugs I ran into over the past two weeks&#8212;less a set of solutions than an account of the hunt itself, shared in the hope that the thought process proves useful the next time you face something similar.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-01"><span>Task Property: Reusing Stateful Business Logic for SwiftUI Views</span></a></strong></h3><p><span>When encapsulating stateful business logic in SwiftUI, what comes to mind first? Putting it in the view? Writing a modifier? </span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> offers a less common but distinctly SwiftUI-flavored perspective: using </span><code>DynamicProperty</code><span> to extract stateful business logic out of the view, encapsulating it as reusable dynamic properties and letting views return to a purer declarative expression.</span></p><p><span>The </span><code>TaskProperty</code><span> in the project is merely a helper primitive for managing the lifecycle of asynchronous </span><code>Task</code><span>s within custom dynamic properties. It is practical, but not what the README really wants to emphasize. Starting from the question of &#8220;how to reuse stateful business logic,&#8221; the author gradually demonstrates that </span><code>DynamicProperty</code><span> is not just the mechanism behind </span><code>@State</code><span>, </span><code>@Binding</code><span>, and </span><code>@Environment</code><span>&#8212;it can also serve as a way to organize and reuse stateful business logic.</span></p><blockquote><p><span>Articles about custom </span><code>DynamicProperty</code><span> are rare, and what distinguishes this one is that it does not stop at API instruction. Instead, it brings the question back to the organization of business logic itself: is there shareable stateful logic mixed into your Views? Could that logic be extracted into custom dynamic properties that sit closer to the SwiftUI lifecycle?</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-02"><span>Why My SwiftUI Map Bounced in Heading-Follow Mode?</span></a></strong></h3><p><a href="https://x.com/emrdgrmnci"><span>Emre Degirmenci</span></a><span> ran into a classic SwiftUI + MapKit boundary problem in a TCA-based map application: in heading-follow mode, the map kept jittering, the camera jumped, and the tracking state even exited unexpectedly. Interestingly, the same Map component worked fine in another app built with MVVM, which shifted the question from &#8220;an implementation mistake&#8221; to &#8220;whether the state synchronization model is sound.&#8221;</span></p><p><span>The root cause is that MapKit generates high-frequency camera updates in heading-follow mode, while the original implementation wrote those updates back to the TCA Store through two-way binding, creating a loop of &#8220;MapKit drives &#8594; state updates &#8594; state drives MapKit again&#8221; that broke the system&#8217;s own continuous animation logic. The fix was to leave camera changes under MapKit&#8217;s own control and intervene explicitly only when necessary, thereby avoiding conflicts between state and system-driven behavior.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-03"><span>SwiftUI 3D is Flat</span></a></strong></h3><p><span>In UIKit / AppKit, Core Animation&#8217;s </span><code>CATransformLayer</code><span> provides a genuinely shared 3D space with depth sorting, so many developers naturally assume that SwiftUI&#8217;s </span><code>rotation3DEffect</code><span> and </span><code>projectionEffect</code><span> are built on a similar 3D scene. But </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> shows through an experiment that SwiftUI has no unified 3D space or depth-buffering mechanism. After 3D transformations, multiple views remain &#8220;independent 2D projections,&#8221; which leads to typical occlusion errors&#8212;for example, a back face covering a front face.</span></p><p><span>This behavior is not a defect; it looks more like a deliberate design choice in SwiftUI: constraining 3D capabilities to the projection level of individual views rather than introducing a full 3D scene and hierarchy system.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-04"><span>Introducing the Safari MCP server for web developers</span></a></strong></h3><p><span>In today&#8217;s AI coding agent ecosystem, browser automation has long been dominated by the Chrome / Chromium stack as the de facto standard (Playwright, Puppeteer, CDP, etc.), with Safari mostly serving as a compatibility-verification environment.</span></p><p><span>The Safari MCP server (Safari Technology Preview 247) aims to change that: it exposes Safari&#8217;s browser session capabilities to agents, giving them direct access to the DOM, network requests, console logs, screenshots, and page state, so that debugging and analysis can happen in Safari&#8217;s real runtime environment. This moves Safari into the main path of the agent toolchain, rather than relying on indirect inference from Chromium or cross-browser switching for verification.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-05"><span>noUI()</span></a></strong></h3><p><span>As AI agent tools work their way deeper into development and content-production workflows, the role of UI is being reexamined. Starting from a DOS-style command interface, </span><a href="https://x.com/jordanmorgan10"><span>Jordan Morgan</span></a><span> poses a question worth pondering: when more and more operations can be performed directly by agents through natural language, does UI still need to exist in the form of an &#8220;explicit interface&#8221;?</span></p><blockquote><p><span>The part of the article that fascinated me most is the interactive terminal interface the author built with JavaScript and CSS. This design is not merely an example or a demo&#8212;it embeds the article&#8217;s argument itself into an operable UI, drawing readers into the discussion of UI&#8217;s changing form precisely through the act of &#8220;using an interface.&#8221; Here, UI is not just a vehicle of expression; it becomes part of the argument.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-06"><span>What does Activity Monitor measure?</span></a></strong></h3><p><span>Since AI agents entered everyday development workflows, many developers have had a similar experience: the Mac&#8217;s fans spin up more often and memory pressure rises noticeably, yet the CPU / Energy figures shown in Activity Monitor often fail to match that intuition.</span></p><p><span>Through controlled experiments with </span><code>powermetrics</code><span> and a variety of real workloads, </span><a href="https://x.com/howardnoakley"><span>Howard Oakley</span></a><span> shows that the CPU % in Activity Monitor is closer to a simple sum of each CPU core&#8217;s active residency than to a &#8220;utilization percentage&#8221; in the traditional sense; GPU % is likewise only an approximation of active residency; and Energy Impact mainly reflects a CPU-level power estimate&#8212;it neither includes the GPU nor captures how energy consumption changes over time particularly well.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-07"><span>Quiver: Learning Linear Algebra and Classical Machine Learning with Swift</span></a></strong></h3><p><a href="https://www.linkedin.com/in/waynebishop/"><span>Wayne Bishop</span></a><span> has long maintained </span><a href="https://waynewbishop.github.io/swift-algorithms/"><span>Swift Algorithms &amp; Data Structures</span></a><span>, an e-book on algorithms and data structures for Swift developers. In its latest fifth edition, the book has extended beyond traditional algorithms and data structures into vectors, matrices, and similarity computation; Quiver pushes that path further into numerical computing, statistics, and classical machine learning.</span></p><p><span>Quiver is a pure Swift, zero-dependency library for linear algebra, statistics, and classical machine learning. It directly extends the Swift standard library&#8217;s </span><code>Array</code><span>, emphasizing value semantics, </span><code>Codable</code><span>, </span><code>Sendable</code><span>, and lightweight on-device execution on Apple platforms. Its goal is not to replace the Python numerical ecosystem, but to give Swift developers an entry point for understanding linear algebra, training small models, and bringing the results back into an App&#8212;all in a familiar language. In the later chapters of Swift Algorithms &amp; Data Structures, Wayne uses Quiver as the companion tool for the math and machine-learning fundamentals.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-08"><span>SwipeCell v3: A Native SwiftUI Swipe Menu</span></a></strong></h3><p><span>At WWDC 2026, SwiftUI&#8217;s new </span><code>swipeActionsContainer()</code><span> finally let swipe menus step outside of </span><code>List</code><span>, serving </span><code>ScrollView</code><span>, lazy stacks, and more custom containers. Unfortunately, this capability currently requires system versions corresponding to </span><code>anyAppleOS 27</code><span>.</span></p><p><span>SwipeCell was the first third-party library I wrote six years ago, when I had just entered Swift development. The old versions were naive, but they also accompanied me through the changes in SwiftUI&#8217;s swipe interactions over the years. I recently gave it a complete rewrite and released v3: the new API is more SwiftUI-idiomatic, the configuration is more complete, the interaction feel has been re-polished, and macOS support has been added.</span></p><p><span>SwipeCell v3 is currently published on the </span><code>v3-beta</code><span> branch and remains in beta. You are welcome to try it out and report any issues you encounter.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-143?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>&#24403; Linux &#25104;&#20026;&#8220;&#31354;&#27668;&#8221;&#65306;&#23481;&#22120;&#12289;Agent &#19982;&#19981;&#20877;&#37325;&#35201;&#30340;&#8220;&#26700;&#38754;&#20043;&#20105;&#8221;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-143/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19968;&#21608;&#21069;&#65292;&#24494;&#36719;&#25512;&#20986;&#20102;&#26080;&#38656; Docker &#30340; Windows 11 &#21407;&#29983;&#23481;&#22120;&#25903;&#25345;&#30340;&#20844;&#24320;&#39044;&#35272;&#65307;&#20877;&#32467;&#21512;&#33529;&#26524;&#19981;&#20037;&#21069;&#21457;&#24067;&#30340;&#23481;&#22120;&#31649;&#29702;&#22120;&#65288;container&#65289;1.0 &#27491;&#24335;&#29256;&#65292;&#19968;&#26102;&#38388;&#65292;&#20004;&#22823;&#20027;&#27969;&#26700;&#38754;&#25805;&#20316;&#31995;&#32479;&#37117;&#23558; Linux &#23481;&#22120;&#28145;&#24230;&#38598;&#25104;&#20026;&#20102;&#31995;&#32479;&#30340;&#19968;&#31561;&#20844;&#27665;&#12290;</span></p><p><span>&#36825;&#20214;&#20107;&#24341;&#21457;&#20102;&#19968;&#22330;&#26377;&#36259;&#30340;&#35752;&#35770;&#12290;&#26377;&#20154;&#35748;&#20026;&#65292;&#36825;&#26159; Linux &#30340;&#26368;&#32456;&#32988;&#21033;&#65306;&#34429;&#28982;&#23427;&#22987;&#32456;&#27809;&#33021;&#30495;&#27491;&#36194;&#19979;&#26700;&#38754;&#24066;&#22330;&#65292;&#20294;&#23427;&#24050;&#32463;&#26080;&#22788;&#19981;&#22312;&#65307;&#20063;&#26377;&#20154;&#25552;&#20986;&#21453;&#38382;&#65306;&#24403; Windows &#21644; macOS &#37117;&#33021;&#30456;&#23545;&#39034;&#30021;&#12289;&#36731;&#37327;&#22320;&#36816;&#34892; Linux &#23481;&#22120;&#26102;&#65292;&#36825;&#31350;&#31455;&#26159; Linux &#30340;&#32988;&#21033;&#65292;&#36824;&#26159;&#23427;&#34987;&#24443;&#24213;&#8220;&#24037;&#20855;&#21270;&#8221;&#21644;&#8220;&#38544;&#24418;&#21270;&#8221;&#30340;&#24320;&#22987;&#65311;</span></p><p><span>&#36825;&#20004;&#31181;&#35828;&#27861;&#30475;&#20284;&#30456;&#21453;&#65292;&#20854;&#23454;&#37117;&#35302;&#30896;&#21040;&#20102;&#21516;&#19968;&#20010;&#20107;&#23454;&#65306;Linux &#30340;&#35282;&#33394;&#27491;&#22312;&#21457;&#29983;&#21464;&#21270;&#12290;</span></p><p><span>&#36807;&#21435;&#65292;&#25105;&#20204;&#35848;&#35770;&#25805;&#20316;&#31995;&#32479;&#26102;&#65292;&#36890;&#24120;&#26159;&#22312;&#35848;&#35770;&#19968;&#20010;&#23436;&#25972;&#30340;&#24179;&#21488;&#12290;&#23427;&#26377;&#33258;&#24049;&#30340;&#26700;&#38754;&#12289;&#24212;&#29992;&#12289;&#24320;&#21457;&#27169;&#22411;&#12289;&#29992;&#25143;&#20064;&#24815;&#21644;&#29983;&#24577;&#36793;&#30028;&#12290;Windows &#26159;&#19968;&#20010;&#24179;&#21488;&#65292;macOS &#26159;&#19968;&#20010;&#24179;&#21488;&#65292;Linux &#21457;&#34892;&#29256;&#24403;&#28982;&#20063;&#26159;&#19968;&#20010;&#24179;&#21488;&#12290;&#22260;&#32469;&#36825;&#20123;&#24179;&#21488;&#65292;&#20154;&#20204;&#35752;&#35770;&#20221;&#39069;&#12289;&#20307;&#39564;&#12289;&#20860;&#23481;&#24615;&#65292;&#20197;&#21450;&#37027;&#20010;&#24050;&#32463;&#34987;&#21453;&#22797;&#35843;&#20355;&#20102;&#20960;&#21313;&#24180;&#30340;&#8220;Linux &#26700;&#38754;&#20803;&#24180;&#8221;&#12290;</span></p><p><span>&#20294;&#23481;&#22120;&#25913;&#21464;&#20102;&#36825;&#20010;&#38382;&#39064;&#30340;&#32467;&#26500;&#12290;</span></p><p><span>&#22312;&#29616;&#20195;&#36719;&#20214;&#24320;&#21457;&#20013;&#65292;Linux &#36234;&#26469;&#36234;&#23569;&#20197;&#8220;&#20320;&#27491;&#22312;&#20351;&#29992;&#30340;&#25805;&#20316;&#31995;&#32479;&#8221;&#30340;&#24418;&#24335;&#20986;&#29616;&#65292;&#32780;&#26159;&#20197;&#8220;&#40664;&#35748;&#36816;&#34892;&#29615;&#22659;&#8221;&#30340;&#24418;&#24335;&#23384;&#22312;&#12290;&#24320;&#21457;&#32773;&#19981;&#19968;&#23450;&#20250;&#35828;&#8220;&#25105;&#37096;&#32626;&#21040;&#20102; Linux&#8221;&#65292;&#20182;&#20204;&#26356;&#21487;&#33021;&#35828;&#8220;&#25105;&#37096;&#32626;&#21040;&#20102; Kubernetes&#8221;&#12289;&#8220;&#25105;&#36305;&#22312;&#20113;&#19978;&#8221;&#12289;&#8220;&#25105;&#29992;&#20102;&#19968;&#20010;&#23481;&#22120;&#38236;&#20687;&#8221;&#12290;</span></p><p><span>&#36825;&#31181;&#21464;&#21270;&#22312; AI Agent &#26102;&#20195;&#20250;&#26356;&#21152;&#26126;&#26174;&#12290;&#38543;&#30528; Agent &#20174;&#31616;&#21333;&#30340;&#32842;&#22825;&#21161;&#25163;&#36716;&#21521;&#33021;&#22815;&#30495;&#27491;&#25191;&#34892;&#20219;&#21153;&#30340;&#24037;&#20855;&#65292;&#23427;&#20204;&#38656;&#35201;&#30340;&#19981;&#20877;&#21482;&#26159;&#19968;&#20010;&#23545;&#35805;&#30028;&#38754;&#65292;&#32780;&#26159;&#19968;&#20010;&#36731;&#37327;&#12289;&#31186;&#32423;&#21551;&#21160;&#12289;&#23436;&#20840;&#38548;&#31163;&#19988;&#26131;&#20110;&#38144;&#27585;&#30340;&#25191;&#34892;&#29615;&#22659;&#12290;&#23481;&#22120;&#22825;&#28982;&#36866;&#21512;&#25215;&#25285;&#36825;&#31181;&#35282;&#33394;&#12290;&#32780;&#24403;&#36234;&#26469;&#36234;&#22810;&#30340;&#20219;&#21153;&#32463;&#30001; Agent &#23436;&#25104;&#65292;&#20154;&#19982;&#25805;&#20316;&#31995;&#32479;&#30452;&#25509;&#20132;&#20114;&#30340;&#30028;&#38754;&#65292;&#20854;&#26435;&#37325;&#20063;&#22312;&#24708;&#28982;&#19979;&#38477;&#8212;&#8212;&#37027;&#22330;&#25345;&#32493;&#20102;&#25968;&#21313;&#24180;&#30340;&#8220;&#26700;&#38754;&#20043;&#20105;&#8221;&#65292;&#32988;&#36127;&#24050;&#32463;&#24840;&#21457;&#19981;&#37325;&#35201;&#20102;&#12290;</span></p><p><span>&#25152;&#20197;&#65292;Linux &#27491;&#22312;&#36229;&#36234;&#8220;&#24179;&#21488;&#8221;&#36825;&#20010;&#36523;&#20221;&#12290;&#23427;&#27809;&#26377;&#25104;&#20026;&#26700;&#38754;&#25805;&#20316;&#31995;&#32479;&#20221;&#39069;&#30340;&#36194;&#23478;&#65292;&#21364;&#36827;&#20837;&#20102;&#20960;&#20046;&#25152;&#26377;&#29616;&#20195;&#35745;&#31639;&#20307;&#31995;&#30340;&#24213;&#23618;&#12290;&#23427;&#27809;&#26377;&#35753;&#25152;&#26377;&#20154;&#37117;&#25913;&#29992; Linux&#65292;&#21364;&#35753;&#25152;&#26377;&#24179;&#21488;&#37117;&#19981;&#24471;&#19981;&#25903;&#25345; Linux &#30340;&#36816;&#34892;&#26041;&#24335;&#12290;</span></p><p><span>&#19981;&#26159;&#35753;&#25152;&#26377;&#20154;&#37117;&#39640;&#21898;&#20320;&#30340;&#21517;&#23383;&#65292;&#32780;&#26159;&#35753;&#25152;&#26377;&#20154;&#37117;&#31163;&#19981;&#24320;&#20320;&#65292;&#21364;&#21448;&#24819;&#19981;&#36215;&#20320;&#12290;&#36825;&#31181;&#32988;&#21033;&#26080;&#22768;&#32988;&#26377;&#22768;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-142/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/debugging-notes-on-two-swiftui-animation-bugs/?utm_source=fatbobman%20weekly%20issue%20143&amp;utm_medium=web"><span>&#20004;&#20010; SwiftUI &#21160;&#30011; Bug &#25490;&#26597;&#23567;&#35760;</span></a></strong></h3><p><span>&#26131;&#29992;&#30340;&#21160;&#30011;&#19968;&#30452;&#26159; SwiftUI &#30340;&#20027;&#35201;&#29305;&#33394;&#20043;&#19968;&#12290;&#20294;&#22768;&#26126;&#24335;&#26694;&#26550;&#30340;&#29305;&#24615;&#26159;&#19968;&#25226;&#21452;&#20995;&#21073;&#65306;&#21160;&#30011;&#19968;&#26086;&#20986;&#29616;&#24322;&#24120;&#65292;&#25490;&#26597;&#24448;&#24448;&#27604;&#21629;&#20196;&#24335;&#26694;&#26550;&#26356;&#26840;&#25163;&#12290;&#26412;&#25991;&#35760;&#24405;&#20102;&#36807;&#21435;&#20004;&#21608;&#37324;&#65292;&#25105;&#22312;&#24320;&#21457;&#20013;&#36935;&#21040;&#30340;&#20004;&#20010;&#19982; SwiftUI &#21160;&#30011;&#26377;&#20851;&#30340; Bug&#12290;&#19982;&#20854;&#35828;&#26159;&#35299;&#20915;&#26041;&#26696;&#65292;&#19981;&#22914;&#35828;&#26159;&#19968;&#27573;&#25490;&#26597;&#30340;&#24515;&#36335;&#8212;&#8212;&#24076;&#26395;&#33021;&#20026;&#20320;&#38754;&#23545;&#31867;&#20284;&#38382;&#39064;&#26102;&#24320;&#38420;&#19968;&#28857;&#24605;&#36335;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-01"><span>&#21033;&#29992;&#23646;&#24615;&#26426;&#21046;&#37325;&#26500;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753; (Task Property: Reusing Stateful Business Logic for SwiftUI Views)</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#23553;&#35013;&#24102;&#29366;&#24577;&#30340;&#19994;&#21153;&#36923;&#36753;&#65292;&#20320;&#31532;&#19968;&#26102;&#38388;&#20250;&#24819;&#21040;&#20160;&#20040;&#26041;&#24335;&#65311;&#25918;&#36827;&#35270;&#22270;&#65311;&#20889;&#25104; modifier&#65311;</span><a href="https://www.linkedin.com/in/vanvoorden/"><span>Rick Van Voorden</span></a><span> &#25552;&#20379;&#20102;&#19968;&#20010;&#19981;&#22826;&#24120;&#35265;&#20294;&#24456;&#26377; SwiftUI &#21619;&#36947;&#30340;&#35270;&#35282;&#65306;&#21033;&#29992; </span><code>DynamicProperty</code><span> &#23558;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753;&#20174; View &#20013;&#25277;&#31163;&#20986;&#26469;&#65292;&#23553;&#35013;&#20026;&#21487;&#22797;&#29992;&#30340;&#21160;&#24577;&#23646;&#24615;&#65292;&#35753; View &#22238;&#24402;&#26356;&#32431;&#31929;&#30340;&#22768;&#26126;&#24335;&#34920;&#36798;&#12290;</span></p><p><span>&#39033;&#30446;&#20013;&#30340; </span><code>TaskProperty</code><span> &#21482;&#26159;&#19968;&#20010;&#36741;&#21161;&#21407;&#35821;&#65292;&#29992;&#20110;&#22312;&#33258;&#23450;&#20041;&#21160;&#24577;&#23646;&#24615;&#20013;&#31649;&#29702;&#24322;&#27493; </span><code>Task</code><span> &#30340;&#29983;&#21629;&#21608;&#26399;&#12290;&#23427;&#24456;&#23454;&#29992;&#65292;&#20294;&#24182;&#19981;&#26159;&#36825;&#31687; README &#30495;&#27491;&#24819;&#24378;&#35843;&#30340;&#37325;&#28857;&#12290;&#20316;&#32773;&#20174;&#8220;&#22914;&#20309;&#22797;&#29992; Stateful Business Logic&#8221;&#36825;&#20010;&#38382;&#39064;&#20986;&#21457;&#65292;&#36880;&#27493;&#23637;&#31034;&#20102; </span><code>DynamicProperty</code><span> &#19981;&#21482;&#26159; </span><code>@State</code><span>&#12289;</span><code>@Binding</code><span>&#12289;</span><code>@Environment</code><span> &#32972;&#21518;&#30340;&#26426;&#21046;&#65292;&#20063;&#21487;&#20197;&#25104;&#20026;&#32452;&#32455;&#21644;&#22797;&#29992;&#29366;&#24577;&#21270;&#19994;&#21153;&#36923;&#36753;&#30340;&#19968;&#31181;&#26041;&#24335;&#12290;</span></p><blockquote><p><span>&#20851;&#20110;&#33258;&#23450;&#20041; </span><code>DynamicProperty</code><span> &#30340;&#25991;&#31456;&#24182;&#19981;&#22810;&#65292;&#32780;&#26412;&#25991;&#30340;&#29305;&#28857;&#22312;&#20110;&#65292;&#23427;&#27809;&#26377;&#20572;&#30041;&#22312; API &#20351;&#29992;&#25945;&#23398;&#19978;&#65292;&#32780;&#26159;&#25226;&#38382;&#39064;&#25918;&#22238;&#19994;&#21153;&#36923;&#36753;&#32452;&#32455;&#26412;&#36523;&#65306;&#20320;&#30340; View &#20013;&#26159;&#21542;&#28151;&#20837;&#20102;&#21487;&#20849;&#20139;&#30340;&#29366;&#24577;&#36923;&#36753;&#65311;&#36825;&#20123;&#36923;&#36753;&#26159;&#21542;&#21487;&#20197;&#34987;&#25277;&#21462;&#20026;&#26356;&#36148;&#36817; SwiftUI &#29983;&#21629;&#21608;&#26399;&#30340;&#33258;&#23450;&#20041;&#21160;&#24577;&#23646;&#24615;&#65311;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-02"><span>SwiftUI &#22320;&#22270;&#22312;&#33322;&#21521;&#36319;&#38543;&#27169;&#24335;&#19979;&#20026;&#20309;&#20250;&#25238;&#21160;&#65311;(Why My SwiftUI Map Bounced in Heading-Follow Mode?)</span></a></strong></h3><p><a href="https://x.com/emrdgrmnci"><span>Emre Degirmenci</span></a><span> &#22312;&#19968;&#20010;&#22522;&#20110; TCA &#30340;&#22320;&#22270;&#24212;&#29992;&#20013;&#36935;&#21040;&#20102;&#19968;&#20010;&#20856;&#22411;&#30340; SwiftUI + MapKit &#36793;&#30028;&#38382;&#39064;&#65306;&#22312; heading-follow &#27169;&#24335;&#19979;&#65292;&#22320;&#22270;&#20986;&#29616;&#25345;&#32493;&#25238;&#21160;&#12289;&#30456;&#26426;&#36339;&#21160;&#65292;&#29978;&#33267;&#23450;&#20301;&#29366;&#24577;&#24322;&#24120;&#36864;&#20986;&#12290;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#21516;&#26679;&#30340; Map &#32452;&#20214;&#22312;&#21478;&#19968;&#20010; MVVM &#26550;&#26500;&#30340;&#24212;&#29992;&#20013;&#21364;&#27809;&#26377;&#38382;&#39064;&#65292;&#36825;&#20351;&#24471;&#38382;&#39064;&#20174;&#8220;&#23454;&#29616;&#38169;&#35823;&#8221;&#36716;&#21521;&#20102;&#8220;&#29366;&#24577;&#21516;&#27493;&#27169;&#22411;&#26159;&#21542;&#21512;&#29702;&#8221;&#12290;</span></p><p><span>&#26680;&#24515;&#21407;&#22240;&#22312;&#20110; MapKit &#22312; heading-follow &#27169;&#24335;&#19979;&#20250;&#20135;&#29983;&#39640;&#39057;&#30456;&#26426;&#26356;&#26032;&#65292;&#32780;&#21407;&#23454;&#29616;&#36890;&#36807;&#21452;&#21521;&#32465;&#23450;&#23558;&#26356;&#26032;&#25968;&#25454;&#22238;&#20889;&#21040; TCA Store&#65292;&#36896;&#25104;&#20102;&#8220;MapKit &#39537;&#21160; &#8594; &#29366;&#24577;&#26356;&#26032; &#8594; &#20877;&#39537;&#21160; MapKit&#8221;&#30340;&#22238;&#36335;&#65292;&#30772;&#22351;&#20102;&#31995;&#32479;&#33258;&#36523;&#30340;&#36830;&#32493;&#21160;&#30011;&#36923;&#36753;&#12290;&#20462;&#22797;&#26041;&#24335;&#20026;&#35753;&#30456;&#26426;&#21464;&#21270;&#20445;&#25345;&#30001; MapKit &#33258;&#36523;&#25511;&#21046;&#65292;&#21482;&#22312;&#38656;&#35201;&#26102;&#36827;&#34892;&#26174;&#24335;&#24178;&#39044;&#65292;&#20174;&#32780;&#36991;&#20813;&#29366;&#24577;&#19982;&#31995;&#32479;&#39537;&#21160;&#20043;&#38388;&#30340;&#20914;&#31361;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-03"><span>SwiftUI 3D is Flat</span></a></strong></h3><p><span>&#22312; UIKit / AppKit &#20013;&#65292;Core Animation &#30340; </span><code>CATransformLayer</code><span> &#25552;&#20379;&#20102;&#30495;&#27491;&#30340;&#20849;&#20139; 3D &#31354;&#38388;&#19982;&#28145;&#24230;&#25490;&#24207;&#33021;&#21147;&#65292;&#22240;&#27492;&#19981;&#23569;&#24320;&#21457;&#32773;&#20250;&#33258;&#28982;&#22320;&#35748;&#20026; SwiftUI &#30340; </span><code>rotation3DEffect</code><span>&#12289;</span><code>projectionEffect</code><span> &#20063;&#24314;&#31435;&#22312;&#31867;&#20284;&#30340; 3D &#22330;&#26223;&#20043;&#19978;&#12290;&#20294; </span><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#36890;&#36807;&#19968;&#20010;&#23454;&#39564;&#25351;&#20986;&#65306;SwiftUI &#24182;&#19981;&#23384;&#22312;&#32479;&#19968;&#30340; 3D &#31354;&#38388;&#25110;&#28145;&#24230;&#32531;&#20914;&#26426;&#21046;&#12290;&#22810;&#20010;&#35270;&#22270;&#22312; 3D &#21464;&#25442;&#21518;&#30340;&#32467;&#26524;&#20173;&#28982;&#26159;&#8220;&#21508;&#33258;&#29420;&#31435;&#30340; 2D &#25237;&#24433;&#8221;&#65292;&#22240;&#27492;&#20250;&#20986;&#29616;&#20856;&#22411;&#30340;&#36974;&#25377;&#38169;&#35823;&#65292;&#20363;&#22914;&#8220;&#32972;&#38754;&#35206;&#30422;&#27491;&#38754;&#8221;&#12290;</span></p><p><span>&#36825;&#31181;&#34892;&#20026;&#24182;&#38750;&#32570;&#38519;&#65292;&#32780;&#26356;&#20687;&#26159; SwiftUI &#26377;&#24847;&#30340;&#35774;&#35745;&#36873;&#25321;&#65306;&#23558; 3D &#33021;&#21147;&#38480;&#21046;&#22312;&#21333;&#20010; view &#30340;&#25237;&#24433;&#23618;&#38754;&#65292;&#32780;&#19981;&#26159;&#24341;&#20837;&#23436;&#25972;&#30340; 3D &#22330;&#26223;&#19982;&#23618;&#32423;&#20307;&#31995;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-04"><span>Safari &#25512;&#20986;&#38754;&#21521; Web &#24320;&#21457;&#32773;&#30340; MCP (Introducing the Safari MCP server for web developers)</span></a></strong></h3><p><span>&#22312;&#24403;&#21069; AI coding agent &#29983;&#24577;&#20013;&#65292;&#27983;&#35272;&#22120;&#33258;&#21160;&#21270;&#38271;&#26399;&#20197; Chrome / Chromium &#20307;&#31995;&#20026;&#20107;&#23454;&#26631;&#20934;&#65288;Playwright&#12289;Puppeteer&#12289;CDP &#31561;&#65289;&#65292;Safari &#36890;&#24120;&#26356;&#22810;&#20316;&#20026;&#20860;&#23481;&#24615;&#39564;&#35777;&#29615;&#22659;&#12290;</span></p><p><span>Safari MCP server&#65288;Safari Technology Preview 247&#65289;&#35797;&#22270;&#25913;&#21464;&#36825;&#19968;&#28857;&#65306;&#23427;&#23558; Safari &#27983;&#35272;&#22120;&#20250;&#35805;&#33021;&#21147;&#26292;&#38706;&#32473; agent&#65292;&#20351;&#20854;&#21487;&#20197;&#30452;&#25509;&#35775;&#38382; DOM&#12289;&#32593;&#32476;&#35831;&#27714;&#12289;&#25511;&#21046;&#21488;&#26085;&#24535;&#12289;&#25130;&#22270;&#20197;&#21450;&#39029;&#38754;&#29366;&#24577;&#65292;&#20174;&#32780;&#22312; Safari &#30340;&#30495;&#23454;&#36816;&#34892;&#29615;&#22659;&#20013;&#23436;&#25104;&#35843;&#35797;&#19982;&#20998;&#26512;&#12290;&#36825;&#20351; Safari &#24320;&#22987;&#36827;&#20837; agent toolchain &#30340;&#20027;&#36335;&#24452;&#65292;&#32780;&#19981;&#20877;&#21482;&#26159;&#20381;&#36182; Chromium &#30340;&#38388;&#25509;&#25512;&#26029;&#25110;&#36328;&#27983;&#35272;&#22120;&#20999;&#25442;&#39564;&#35777;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-05"><span>AI &#26102;&#20195;&#19979;&#30340;&#8220;&#26080; UI&#8221;&#36235;&#21183;&#24605;&#32771; noUI()</span></a></strong></h3><p><span>&#22312;&#24403;&#21069; AI agent &#24037;&#20855;&#36880;&#28176;&#28145;&#20837;&#24320;&#21457;&#19982;&#20869;&#23481;&#29983;&#20135;&#27969;&#31243;&#30340;&#32972;&#26223;&#19979;&#65292;UI &#30340;&#35282;&#33394;&#27491;&#22312;&#34987;&#37325;&#26032;&#23457;&#35270;&#12290;</span><a href="https://x.com/jordanmorgan10"><span>Jordan Morgan</span></a><span>&#8288; &#20174; DOS &#39118;&#26684;&#30340;&#21629;&#20196;&#30028;&#38754;&#20999;&#20837;&#65292;&#25552;&#20986;&#19968;&#20010;&#20540;&#24471;&#24605;&#32771;&#30340;&#38382;&#39064;&#65306;&#24403;&#36234;&#26469;&#36234;&#22810;&#30340;&#25805;&#20316;&#21487;&#20197;&#30452;&#25509;&#30001; agent &#36890;&#36807;&#33258;&#28982;&#35821;&#35328;&#23436;&#25104;&#26102;&#65292;UI &#26159;&#21542;&#20173;&#28982;&#38656;&#35201;&#20197;&#8220;&#26174;&#24335;&#30028;&#38754;&#8221;&#30340;&#24418;&#24335;&#23384;&#22312;&#65311;</span></p><blockquote><p><span>&#25991;&#31456;&#20013;&#26368;&#21560;&#24341;&#25105;&#30340;&#37096;&#20998;&#65292;&#26159;&#20316;&#32773;&#22522;&#20110; JavaScript &#19982; CSS &#26500;&#24314;&#20102;&#19968;&#20010;&#21487;&#20132;&#20114;&#30340;&#32456;&#31471;&#30028;&#38754;&#12290;&#36825;&#20010;&#35774;&#35745;&#24182;&#19981;&#20165;&#20165;&#29992;&#20110;&#31034;&#20363;&#25110;&#28436;&#31034;&#65292;&#32780;&#26159;&#23558;&#25991;&#31456;&#30340;&#35770;&#36848;&#26412;&#36523;&#23884;&#20837;&#21040;&#19968;&#20010;&#21487;&#25805;&#20316;&#30340; UI &#20013;&#65292;&#20351;&#35835;&#32773;&#22312;&#8220;&#20351;&#29992;&#30028;&#38754;&#8221;&#30340;&#36807;&#31243;&#20013;&#36827;&#20837;&#23545; UI &#24418;&#24577;&#21464;&#21270;&#30340;&#35752;&#35770;&#20043;&#20013;&#12290;UI &#22312;&#36825;&#37324;&#19981;&#21482;&#26159;&#34920;&#36798;&#36733;&#20307;&#65292;&#20063;&#25104;&#20026;&#35770;&#35777;&#30340;&#19968;&#37096;&#20998;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-06"><span>&#37325;&#26032;&#35748;&#35782; Mac &#27963;&#21160;&#30417;&#35270;&#22120;&#30340;&#21508;&#39033;&#24615;&#33021;&#25351;&#26631; (What does Activity Monitor measure?)</span></a></strong></h3><p><span>&#22312; AI agent &#36880;&#28176;&#36827;&#20837;&#26085;&#24120;&#24320;&#21457;&#27969;&#31243;&#20043;&#21518;&#65292;&#24456;&#22810;&#24320;&#21457;&#32773;&#37117;&#20250;&#26377;&#31867;&#20284;&#30340;&#20307;&#39564;&#65306;Mac &#39118;&#25159;&#26356;&#39057;&#32321;&#21551;&#21160;&#12289;&#20869;&#23384;&#21387;&#21147;&#26126;&#26174;&#19978;&#21319;&#65292;&#20294; Activity Monitor &#20013;&#26174;&#31034;&#30340; CPU / Energy &#25968;&#20540;&#21364;&#24448;&#24448;&#19982;&#30452;&#35266;&#24863;&#21463;&#24182;&#19981;&#19968;&#33268;&#12290;</span></p><p><a href="https://x.com/howardnoakley"><span>Howard Oakley</span></a><span> &#36890;&#36807; powermetrics &#19982;&#22810;&#31181;&#30495;&#23454;&#36127;&#36733;&#23545;&#29031;&#23454;&#39564;&#25351;&#20986;&#65292;Activity Monitor &#20013;&#30340; CPU % &#26356;&#25509;&#36817;&#21508; CPU core active residency &#30340;&#31616;&#21333;&#21472;&#21152;&#65292;&#32780;&#38750;&#20256;&#32479;&#24847;&#20041;&#19978;&#30340;&#8220;&#21033;&#29992;&#29575;&#30334;&#20998;&#27604;&#8221;&#65307;GPU % &#21516;&#26679;&#21482;&#26159; active residency &#30340;&#36817;&#20284;&#34920;&#36798;&#65307;&#32780; Energy Impact &#21017;&#20027;&#35201;&#21453;&#26144; CPU &#23618;&#38754;&#30340;&#21151;&#32791;&#20272;&#31639;&#65292;&#26082;&#19981;&#21253;&#21547; GPU&#65292;&#20063;&#27809;&#26377;&#24456;&#22909;&#22320;&#21051;&#30011;&#26102;&#38388;&#32500;&#24230;&#19978;&#30340;&#33021;&#32791;&#21464;&#21270;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-07"><span>Quiver&#65306;&#29992; Swift &#23398;&#32447;&#24615;&#20195;&#25968;&#19982;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;</span></a></strong></h3><p><a href="https://www.linkedin.com/in/waynebishop/"><span>Wayne Bishop</span></a><span> &#38271;&#26399;&#32500;&#25252;&#30340;&#12298;</span><a href="https://waynewbishop.github.io/swift-algorithms/"><span>Swift Algorithms &amp; Data Structures</span></a><span>&#12299;&#26159;&#19968;&#37096;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#31639;&#27861;&#19982;&#25968;&#25454;&#32467;&#26500;&#30005;&#23376;&#20070;&#12290;&#22312;&#26368;&#26032;&#30340;&#31532;&#20116;&#29256;&#20013;&#65292;&#36825;&#26412;&#20070;&#24050;&#32463;&#20174;&#20256;&#32479;&#31639;&#27861;&#12289;&#25968;&#25454;&#32467;&#26500;&#24310;&#20280;&#21040;&#21521;&#37327;&#12289;&#30697;&#38453;&#21644;&#30456;&#20284;&#24230;&#35745;&#31639;&#65307;&#32780; Quiver &#21017;&#25226;&#36825;&#26465;&#36335;&#24452;&#32487;&#32493;&#25512;&#36827;&#21040;&#25968;&#20540;&#35745;&#31639;&#12289;&#32479;&#35745;&#21644;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;&#12290;</span></p><p><span>Quiver &#26159;&#19968;&#20010;&#32431; Swift&#12289;&#38646;&#20381;&#36182;&#30340;&#32447;&#24615;&#20195;&#25968;&#12289;&#32479;&#35745;&#19982;&#32463;&#20856;&#26426;&#22120;&#23398;&#20064;&#24211;&#12290;&#23427;&#30452;&#25509;&#25193;&#23637; Swift &#26631;&#20934;&#24211;&#30340; </span><code>Array</code><span>&#65292;&#24378;&#35843;&#20540;&#35821;&#20041;&#12289;</span><code>Codable</code><span>&#12289;</span><code>Sendable</code><span>&#65292;&#20197;&#21450;&#22312; Apple &#24179;&#21488;&#19978;&#30340;&#36731;&#37327;&#31471;&#20391;&#36816;&#34892;&#12290;&#23427;&#30340;&#30446;&#26631;&#19981;&#26159;&#26367;&#20195; Python &#25968;&#20540;&#29983;&#24577;&#65292;&#32780;&#26159;&#20026; Swift &#24320;&#21457;&#32773;&#25552;&#20379;&#19968;&#20010;&#29992;&#29087;&#24713;&#35821;&#35328;&#29702;&#35299;&#32447;&#24615;&#20195;&#25968;&#12289;&#35757;&#32451;&#23567;&#22411;&#27169;&#22411;&#65292;&#24182;&#23558;&#32467;&#26524;&#24102;&#22238; App &#30340;&#20837;&#21475;&#12290;Wayne &#22312;&#12298;Swift Algorithms &amp; Data Structures&#12299;&#21518;&#32493;&#31456;&#33410;&#20013;&#65292;&#20063;&#27491;&#26159;&#20197; Quiver &#20316;&#20026;&#25968;&#23398;&#19982;&#26426;&#22120;&#23398;&#20064;&#22522;&#30784;&#20869;&#23481;&#30340;&#37197;&#22871;&#24037;&#20855;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0143-08"><span>SwipeCell v3&#65306;SwiftUI &#21407;&#29983;&#30340;&#20391;&#28369;&#33756;&#21333;</span></a></strong></h3><p><span>WWDC 2026 &#19978;&#65292;SwiftUI &#36890;&#36807;&#26032;&#30340; </span><code>swipeActionsContainer()</code><span> &#32456;&#20110;&#35753;&#20391;&#28369;&#33756;&#21333;&#36208;&#20986;&#20102; </span><code>List</code><span>&#65292;&#21487;&#20197;&#26381;&#21153;&#20110; </span><code>ScrollView</code><span>&#12289;&#25042;&#21152;&#36733;&#26632;&#20197;&#21450;&#26356;&#22810;&#33258;&#23450;&#20041;&#23481;&#22120;&#12290;&#20294;&#36951;&#25022;&#30340;&#26159;&#65292;&#36825;&#39033;&#33021;&#21147;&#30446;&#21069;&#38656;&#35201; </span><code>anyAppleOS 27</code><span> &#23545;&#24212;&#30340;&#31995;&#32479;&#29256;&#26412;&#25165;&#33021;&#20351;&#29992;&#12290;</span></p><p><span>SwipeCell &#26159;&#25105;&#20845;&#24180;&#21069;&#21018;&#36827;&#20837; Swift &#24320;&#21457;&#26102;&#20889;&#19979;&#30340;&#31532;&#19968;&#20010;&#31532;&#19977;&#26041;&#24211;&#12290;&#26087;&#29256;&#26412;&#24456;&#31258;&#23273;&#65292;&#20294;&#20063;&#38506;&#25105;&#35265;&#35777;&#20102; SwiftUI &#20391;&#28369;&#20132;&#20114;&#36825;&#20123;&#24180;&#30340;&#21464;&#21270;&#12290;&#26368;&#36817;&#25105;&#23545;&#23427;&#20570;&#20102;&#24443;&#24213;&#30340;&#37325;&#20889;&#65292;&#25512;&#20986;&#20102; v3 &#29256;&#26412;&#65306;&#26032;&#30340; API &#26356; SwiftUI &#21270;&#65292;&#37197;&#32622;&#26356;&#23436;&#25972;&#65292;&#20132;&#20114;&#25163;&#24863;&#20063;&#37325;&#26032;&#25171;&#30952;&#65292;&#24182;&#21152;&#20837;&#20102; macOS &#25903;&#25345;&#12290;</span></p><p><span>&#30446;&#21069; SwipeCell v3 &#21457;&#24067;&#22312; </span><code>v3-beta</code><span> &#20998;&#25903;&#65292;&#20173;&#22788;&#20110; beta &#38454;&#27573;&#65292;&#27426;&#36814;&#35797;&#29992;&#65292;&#20063;&#27426;&#36814;&#21453;&#39304;&#20351;&#29992;&#20013;&#30340;&#38382;&#39064;&#12290;</span></p><h2><strong><span>&#27714;&#36132;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0143-09"><span>&#36164;&#28145; iOS / Swift &#24037;&#31243;&#24072;</span></a></strong></h3><p><strong><span>Speak</span></strong><span>&#65306;YC &#23413;&#21270;&#12289;OpenAI &#22810;&#36718;&#25237;&#36164;&#30340; AI &#35821;&#35328;&#23398;&#20064;&#29420;&#35282;&#20861;&#12290;</span></p><p><span>&#24037;&#20316;&#22320;&#65306;&#19978;&#28023;&#12290;</span></p><p><span>&#19968;&#23478;&#22312;&#28023;&#22806;&#22810;&#20010;&#24066;&#22330;&#38271;&#26399;&#39564;&#35777;&#12289;&#21830;&#19994;&#21270;&#25104;&#29087;&#30340; AI-native &#35821;&#35328;&#23398;&#20064;&#20844;&#21496;&#65292;&#27491;&#22312;&#20174; 0 -&gt; 1 &#32452;&#24314;&#20013;&#22269;&#26680;&#24515;&#24037;&#31243;&#22242;&#38431;&#12290;&#22242;&#38431;&#23567;&#32780;&#32654;&#12289;&#19981;&#20869;&#21367;&#65292;&#37325;&#24230;&#20351;&#29992; AI(Cursor / Claude Code &#31561;)&#65292;&#30475;&#37325;&#24037;&#31243; owner &#24847;&#35782;&#21644; agentic engineering &#24037;&#20316;&#26041;&#24335;&#12290;</span></p><p><span>&#20316;&#20026;&#20013;&#22269;&#22242;&#38431;&#30340;&#26089;&#26399;&#26680;&#24515; iOS&#65292;&#20320;&#23558;&#20840;&#31243;&#21442;&#19982;&#25216;&#26415;&#36873;&#22411;,&#25645;&#24314;&#22269;&#20869; iOS &#23436;&#25972;&#22522;&#24314;&#12289;&#23545;&#25509;&#26412;&#22303;&#25903;&#20184; / &#30331;&#24405; / &#21512;&#35268; SDK&#12289;&#20248;&#21270; AI &#35821;&#38899;&#23454;&#26102;&#20132;&#20114;&#20307;&#39564;,&#24182;&#19982;&#20840;&#29699;&#22242;&#38431;&#33521;&#25991;&#21327;&#20316;&#12290;</span></p><p><span>&#26399;&#24453;&#20320;&#20855;&#22791;:</span></p><ul><li><p><span>5 &#24180;&#20197;&#19978; iOS &#21407;&#29983;(Swift)&#24320;&#21457;&#32463;&#39564;,&#26377;&#19978;&#32447;&#30340;&#28040;&#36153;&#32423;&#20135;&#21697;</span></p></li><li><p><span>&#25166;&#23454;&#30340;&#21407;&#29983; iOS &#28145;&#24230;(&#24615;&#33021;&#12289;&#31283;&#23450;&#24615;&#12289;&#26550;&#26500;&#12289;&#24369;&#32593;&#20248;&#21270;&#31561;)</span></p></li><li><p><span>AI-native &#24037;&#20316;&#27969;(&#26085;&#24120;&#29992; Cursor / Claude / Copilot &#31561;)</span></p></li><li><p><span>&#20070;&#38754;&#33521;&#25991;&#32988;&#20219; PR / Slack / &#25991;&#26723;,&#21475;&#35821; B1+&#12289;&#33021;&#28165;&#26224;&#34920;&#36798;&#25216;&#26415;&#24819;&#27861;</span></p></li><li><p><span>&#26377;&#22269;&#20869; App Store &#19978;&#26550; / &#26412;&#22303; SDK &#32463;&#39564;&#32773;&#20248;&#20808;;&#38899;&#35270;&#39057; / RTC / &#35821;&#38899;&#26041;&#21521;&#21152;&#20998;</span></p></li></ul><p><span>&#128073; </span><a href="https://usespeak.notion.site/speak-ios-founding-engineer-sh"><span>&#35814;&#32454;&#21442;&#35265;</span></a></p><p><span>&#26377;&#24847;&#21521;&#32773;&#27426;&#36814;&#25237;&#36882;&#33521;&#25991;&#31616;&#21382;&#33267; </span><a href="mailto:a.suen@usespeak.com"><span>a.suen@usespeak.com</span></a></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #142]]></title><description><![CDATA[SPI Joins Apple, and Swift Moves Toward Self-Hosting]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 29 Jun 2026 12:03:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Lh7P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Lh7P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 424w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 848w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1272w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp" width="1400" height="782" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:782,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:109432,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/204052037?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Lh7P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 424w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 848w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1272w, https://substackcdn.com/image/fetch/$s_!Lh7P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89eefa6b-3b86-48ff-b142-70ff38d8c5f1_1400x782.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@alanaprilio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Alan Aprilio</a><span> on </span><a href="https://unsplash.com/photos/hands-connecting-colorful-puzzle-pieces-together-EwVWnl4Z4Wo?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>SPI Joins Apple, and Swift Moves Toward Self-Hosting</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-142/">Read on web &#8594;</a></p><p><span>A few days ago, Swift Package Index (SPI) announced that it had joined Apple. The two sides will work together to build a comprehensive package registry for Swift developers. At the same time, SPI&#8217;s existing capabilities, including package discovery, compatibility checking, and documentation hosting, will continue to be provided, and package authors will not need to adjust their current publishing workflows in the short term.</span></p><p><span>This also adds a new footnote to the observation I made in </span><a href="https://fatbobman.com/en/weekly/issue-135/"><span>#135</span></a><span>&#8288; that &#8220;SwiftPM has only just reached its second chapter&#8221;: the retreat of CocoaPods merely pushed SPM into the default position, while SPI joining Apple truly opens the next act of Swift package ecosystem infrastructure.</span></p><p><span>If SwiftPM answered the question of &#8220;whether packages can be conveniently depended on,&#8221; and SPI answered &#8220;whether packages can be found and evaluated,&#8221; then joining Apple moves the conversation further toward &#8220;whether packages can be published, identified, and distributed in a trustworthy way.&#8221; Looking at the medium term, three points are especially worth watching:</span></p><ul><li><p><span>SPI will evolve from a third-party indexing service into an important entry point for the official package registry;</span></p></li><li><p><span>The Swift package ecosystem may gradually reduce its implicit dependence on GitHub as a source of hosting, distribution, and identity;</span></p></li><li><p><span>Xcode may establish closer integration with SPI&#8217;s search, compatibility checking, and documentation capabilities.</span></p></li></ul><p><span>Another exciting development for Swift developers last week was Erik Eckstein&#8217;s announcement on the Swift forums that the Swift project will drop the requirement that the compiler &#8220;</span><a href="https://forums.swift.org/t/dropping-the-requirement-for-c-only-bootstrapping/87739/3"><span>must be buildable using only a C++ host toolchain</span></a><span>&#8288;.&#8221; In other words, starting from the </span><code>main</code><span> branch, building the Swift compiler will require an existing Swift toolchain. This also means that mandatory compiler paths that previously had to remain implemented in C++ can now gradually be written in Swift. The officially mentioned scope includes core components such as the Parser, AST, Type Checker, and mandatory SIL passes.</span></p><p><span>This does not mean that the Swift compiler has already been completely rewritten in Swift, nor does it mean that the C++ parser will disappear immediately. More precisely, this is an important threshold for the Swift compiler as it moves toward bootstrapping and self-hosting: Swift is no longer limited to peripheral tools, optional features, or individual optimization passes, but can now enter the compiler&#8217;s core paths.</span></p><p><span>Bootstrapping itself does not simply prove the strength or weakness of a language, but it does represent a form of engineering maturity: whether the language, compiler, standard library, package manager, and cross-platform build system are strong enough to support their own continued evolution. For a language that hopes to expand its influence beyond Apple platforms, this step carries both symbolic significance and practical value.</span></p><p><span>Looking at SPI joining Apple alongside the Swift compiler moving toward self-hosting, it becomes clear that they point to the same thing: Swift is filling in its ecosystem infrastructure. The former concerns package discovery, identity, signing, and trusted distribution, while the latter improves the maintainability and evolution capacity of the language toolchain itself. Whether Swift can truly break out depends not only on how much influence Apple has over it, but on whether Apple and the Swift community can continue to show an open and enterprising attitude, and whether they can make the toolchain, package ecosystem, and cross-platform experience complete enough. On these two developments, I am willing to remain optimistic.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-141/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-01"><span>Bring Swift to The APPLE II</span></a></strong></h3><p><span>The Apple II was one of Apple&#8217;s most important early products and continues to influence many developers today. Many people once used BASIC or Apple Pascal on it, but what would it feel like to write Swift on this machine? </span><a href="https://x.com/yeokm1"><span>Yeo Kheng Meng</span></a><span>&#8288; created SwiftII, a Swift-like mini development environment that allows an old machine with a 1 MHz 6502 CPU and around 64 KB of memory to write and run Swift-like programs.</span></p><p><span>What makes the article fascinating is not only &#8220;getting a Swift-like language running on the Apple II,&#8221; but also the many engineering trade-offs imposed by hardware limitations: limited memory space, conflicts between the language card and ProDOS, keyboard and display differences across Apple II models, and why the project ultimately had to be distributed as multiple disk images. The author also candidly shares the process of AI-assisted development. Even with the help of Claude Code and Codex, key architectural trade-offs, scope control, and hardware testing strategies still had to be handled by the author. This article offers both retro-computing engineering details and the compromises involved in bringing modern language design into an extremely constrained environment.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-02"><span>Building an over-the-air update system for native Swift with WebAssembly, from scratch</span></a></strong></h3><p><span>Building an OTA update mechanism for native Swift iOS apps is a controversial but valuable direction. In this article, </span><a href="https://www.linkedin.com/in/jackasolomon/"><span>Jack Solomon</span></a><span>&#8288; demonstrates a WebAssembly-based approach: compile Swift functions into WASM, load and execute them inside an iOS app through WasmKit, and then download new WASM modules from a server, allowing the app to change its runtime behavior without rebuilding or replacing the signed binary.</span></p><p><span>The article breaks down the Swift-to-WASM toolchain, WASI, </span><code>@_cdecl</code><span> exports, reactor modules, passing parameters through linear memory, and why hot-updating SwiftUI views requires dynamic replacement and a serializable view description tree. Jack also packaged this approach into a Swift SDK: </span><a href="https://github.com/patch-release/patch-swift"><span>patch-swift</span></a><span>&#8288;.</span></p><blockquote><p><span>It should be noted that this type of solution touches the boundaries of App Store Review rules around downloading and executing code, so actual usage still requires careful evaluation of the scenario and compliance risks.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-03"><span>SwiftUI Is One Graph</span></a></strong></h3><p><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span>&#8288; published two long articles about SwiftUI&#8217;s underlying mechanisms over the past week, and they are worth reading together. The first, SwiftUI Is One Graph, starts from observed behavior and Apple patents to explain that SwiftUI is not simply doing View Tree diffing, but is more like a demand-driven attribute graph: View structs themselves are disposable descriptions, while what truly persists is the attribute graph and the state, dependencies, layout, and animation propagation within it.</span></p><p><span>The second article, &#8220;</span><a href="https://l.fatbobman.com/w0142-04"><span>The SwiftUI Oracle: Measuring a Clean Room Against the Real Thing</span></a><span>,&#8221; goes further by showing how to validate this understanding. The author implements a clean-room engine called PureView that does not depend on SwiftUI, then treats real SwiftUI as an oracle and uses differential testing of layout, animation, pixel rendering, and more to validate the model.</span></p><blockquote><p><span>Mihaela&#8217;s workflow is highly inspiring for AI agents. Agents do not need to rely solely on language models to guess whether SwiftUI behavior is correct; they can generate or modify an implementation, run tests, and let real SwiftUI provide comparable results. This kind of &#8220;unit test&#8221;-like feedback loop can turn the understanding of a black-box framework into engineering signals that can be continuously verified and iterated on.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-05"><span>SwiftUI: Intercept-able Picker / Menu / Context Menu</span></a></strong></h3><p><span>In many scenarios, developers want to perform some synchronous operation before components such as </span><code>Menu</code><span>, </span><code>Picker</code><span>, or </span><code>contextMenu</code><span> are presented, such as recording how many times a menu is opened, updating state, or temporarily deciding whether presentation should be allowed. SwiftUI, however, does not provide a corresponding callback. In this article, </span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span> shares an implementation approach: bridge to a native View that hosts SwiftUI content, execute </span><code>menuWillOpen</code><span> when the corresponding gesture is triggered, and then decide whether to actively present the menu using AppKit APIs such as </span><code>NSMenu.popUpContextMenu</code><span>.</span></p><blockquote><p><span>This article once again highlights a practical issue with SwiftUI: many seemingly simple interaction controls, once they go beyond what the system modifiers expose, still require understanding the underlying AppKit / UIKit layer to truly solve.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-06"><span>_UIPortalView: From Live Mirroring to Liquid Glass-Style Effects</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; shared an interesting private UIKit component, </span><code>_UIPortalView</code><span>. Backed by </span><code>CAPortalLayer</code><span>, it can project the rendered result of a </span><code>sourceView</code><span> to another location on the screen in real time, without duplicating the View hierarchy or repeatedly generating snapshots. Compared with static snapshots, Portal is more like a &#8220;live window&#8221; at the compositing layer: the source view remains the single source of state, while changes to text, animations, layout, or subviews can be reflected synchronously elsewhere.</span></p><p><span>The article also connects </span><code>_UIPortalView</code><span> with Liquid Glass-style effects: through </span><code>matchesPosition</code><span>, clipping, offsets, and 3D transforms, it can achieve real-time mirroring, reflections, lenses, shared backgrounds, edge distortion, and other effects.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-07"><span>Taking control of toolbar items in SwiftUI</span></a></strong></h3><p><span>The new SwiftUI Toolbar APIs introduced at WWDC 26 strike a better balance between system adaptivity and explicit developer control. In this article, </span><a href="https://x.com/mecid"><span>Majid Jabrayilov</span></a><span>&#8288; introduces several new control capabilities: using </span><code>visibilityPriority</code><span> to specify the display priority of toolbar items, explicitly creating collapsed menus with </span><code>ToolbarOverflowMenu</code><span>, pinning important actions to the trailing edge of the top bar with </span><code>.topBarPinnedTrailing</code><span>, and using </span><code>toolbarMinimizeBehavior</code><span> to control how the navigation bar, tab bar, bottom bar, and others minimize during scrolling.</span></p><p><span>The same set of toolbar items may be presented differently on iOS, iPadOS, and macOS. The value of the new APIs is that they do not undermine the original cross-platform adaptive nature of SwiftUI Toolbar, while still allowing developers to express more clearly which actions should be shown first, which actions can be intentionally placed into overflow, and how toolbars should respond to scrolling.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-08"><span>iOS-Simulator-Camera-Extend: Adding a &#8220;Truly Usable Camera&#8221; to iOS Simulator</span></a></strong></h3><p><span>iOS Simulator has long lacked real camera capabilities. Features involving QR code scanning, OCR, faces, video calls, or </span><code>AVCaptureSession</code><span> often require a physical device or mocked logic. Developed by </span><a href="https://x.com/GSYTech_CarGuo"><span>Shuyu Guo</span></a><span>, iOS-Simulator-Camera-Extend recreates the core idea of SimCam: through a macOS-side frame source, </span><code>DYLD_INSERT_LIBRARIES</code><span> hooks inside Simulator, and AVFoundation swizzling, the app under test can access the Mac camera, desktop, images, videos, and QR code feeds in the simulator without code changes or a different bundle id.</span></p><p><span>Even more interestingly, it also provides another path based on a CMIO System Extension, allowing macOS apps such as QuickTime, FaceTime, Zoom, and OBS to see a SimCam Virtual Camera. In other words, the same frame source can be fed both to an app running inside iOS Simulator and used as a macOS virtual camera, making it very useful for debugging, demonstrations, and automated testing of camera-related features.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-142?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>SPI &#21152;&#20837; Apple&#65292;Swift &#36808;&#21521;&#33258;&#20030;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-142/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#20960;&#22825;&#21069;&#65292;Swift Package Index&#65288;SPI&#65289;&#23459;&#24067;&#24050;&#21152;&#20837; Apple&#12290;&#21452;&#26041;&#23558;&#20849;&#21516;&#24314;&#35774;&#19968;&#20010;&#38754;&#21521; Swift &#24320;&#21457;&#32773;&#30340;&#32508;&#21512; package registry&#65307;&#19982;&#27492;&#21516;&#26102;&#65292;SPI &#29616;&#26377;&#30340;&#21253;&#21457;&#29616;&#12289;&#20860;&#23481;&#24615;&#26816;&#26597;&#12289;&#25991;&#26723;&#25176;&#31649;&#31561;&#33021;&#21147;&#20173;&#20250;&#32487;&#32493;&#25552;&#20379;&#65292;&#21253;&#20316;&#32773;&#22312;&#30701;&#26399;&#20869;&#20063;&#26080;&#38656;&#35843;&#25972;&#29616;&#26377;&#30340;&#21457;&#24067;&#27969;&#31243;&#12290;</span></p><p><span>&#36825;&#20063;&#35753; </span><a href="https://fatbobman.com/zh/weekly/issue-135/"><span>#135</span></a><span>&#8288; &#20013;&#8220;SwiftPM &#25165;&#21018;&#21040;&#31532;&#20108;&#31456;&#8221;&#30340;&#21028;&#26029;&#24471;&#21040;&#20102;&#26032;&#30340;&#27880;&#33050;&#65306;CocoaPods &#30340;&#36864;&#22330;&#21482;&#26159;&#25226; SPM &#25512;&#19978;&#20102;&#40664;&#35748;&#20301;&#32622;&#65292;&#32780; SPI &#21152;&#20837; Apple&#65292;&#25165;&#30495;&#27491;&#25581;&#24320;&#20102; Swift &#21253;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#24314;&#35774;&#30340;&#19979;&#19968;&#24149;&#12290;</span></p><p><span>&#22914;&#26524;&#35828; SwiftPM &#35299;&#20915;&#30340;&#26159;&#8220;&#33021;&#19981;&#33021;&#26041;&#20415;&#22320;&#20381;&#36182;&#21253;&#8221;&#65292;SPI &#35299;&#20915;&#30340;&#26159;&#8220;&#33021;&#19981;&#33021;&#25214;&#21040;&#24182;&#35780;&#20272;&#21253;&#8221;&#65292;&#37027;&#20040;&#36825;&#27425;&#21152;&#20837; Apple &#21017;&#25226;&#38382;&#39064;&#36827;&#19968;&#27493;&#25512;&#36827;&#21040;&#20102;&#8220;&#33021;&#19981;&#33021;&#21487;&#20449;&#22320;&#21457;&#24067;&#12289;&#35782;&#21035;&#21644;&#20998;&#21457;&#21253;&#8221;&#12290;&#20174;&#20013;&#26399;&#26469;&#30475;&#65292;&#26377;&#19977;&#28857;&#23588;&#20854;&#20540;&#24471;&#35266;&#23519;&#65306;</span></p><ul><li><p><span>SPI &#23558;&#20174;&#31532;&#19977;&#26041;&#32034;&#24341;&#26381;&#21153;&#65292;&#28436;&#36827;&#20026;&#23448;&#26041; package registry &#30340;&#37325;&#35201;&#20837;&#21475;&#65307;</span></p></li><li><p><span>Swift &#21253;&#29983;&#24577;&#21487;&#33021;&#36880;&#27493;&#38477;&#20302;&#23545; GitHub &#20316;&#20026;&#25176;&#31649;&#12289;&#20998;&#21457;&#19982;&#36523;&#20221;&#26469;&#28304;&#30340;&#38544;&#24615;&#20381;&#36182;&#65307;</span></p></li><li><p><span>Xcode &#26377;&#26426;&#20250;&#19982; SPI &#30340;&#25628;&#32034;&#12289;&#20860;&#23481;&#24615;&#26816;&#26597;&#21644;&#25991;&#26723;&#33021;&#21147;&#24314;&#31435;&#26356;&#32039;&#23494;&#30340;&#38598;&#25104;&#12290;</span></p></li></ul><p><span>&#19978;&#21608;&#65292;&#21478;&#19968;&#20214;&#35753; Swift &#24320;&#21457;&#32773;&#25391;&#22859;&#30340;&#20107;&#24773;&#26159;&#65292;Erik Eckstein &#22312; Swift &#35770;&#22363;&#19978;&#23459;&#24067;&#65292;Swift &#39033;&#30446;&#23558;&#21462;&#28040;&#8220;</span><a href="https://forums.swift.org/t/dropping-the-requirement-for-c-only-bootstrapping/"><span>&#24517;&#39035;&#33021;&#22815;&#20165;&#20351;&#29992; C++ &#23487;&#20027;&#24037;&#20855;&#38142;&#26500;&#24314;&#32534;&#35793;&#22120;</span></a><span>&#8221;&#30340;&#35201;&#27714;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#20174; </span><code>main</code><span> &#20998;&#25903;&#24320;&#22987;&#65292;&#26500;&#24314; Swift &#32534;&#35793;&#22120;&#23558;&#38656;&#35201;&#24050;&#26377;&#30340; Swift &#24037;&#20855;&#38142;&#21442;&#19982;&#65307;&#36825;&#20063;&#20351;&#24471;&#32534;&#35793;&#22120;&#20013;&#37027;&#20123;&#36807;&#21435;&#24517;&#39035;&#20445;&#25345; C++ &#23454;&#29616;&#30340;&#24378;&#21046;&#36335;&#24452;&#65292;&#29616;&#22312;&#21487;&#20197;&#36880;&#27493;&#29992; Swift &#32534;&#20889;&#12290;&#23448;&#26041;&#25552;&#21040;&#30340;&#33539;&#22260;&#21253;&#25324; Parser&#12289;AST&#12289;Type Checker&#65292;&#20197;&#21450; mandatory SIL passes &#31561;&#26680;&#24515;&#37096;&#20998;&#12290;</span></p><p><span>&#36825;&#24182;&#19981;&#24847;&#21619;&#30528; Swift &#32534;&#35793;&#22120;&#24050;&#32463;&#23436;&#20840;&#29992; Swift &#37325;&#20889;&#65292;&#20063;&#19981;&#24847;&#21619;&#30528; C++ parser &#20250;&#39532;&#19978;&#28040;&#22833;&#12290;&#26356;&#20934;&#30830;&#22320;&#35828;&#65292;&#36825;&#26159; Swift &#32534;&#35793;&#22120;&#36808;&#21521;&#33258;&#20030;&#21644;&#33258;&#25176;&#31649;&#30340;&#37325;&#35201;&#38376;&#27099;&#65306;Swift &#19981;&#20877;&#21482;&#26159;&#29992;&#20110;&#22806;&#22260;&#24037;&#20855;&#12289;&#21487;&#36873;&#21151;&#33021;&#25110;&#20010;&#21035;&#20248;&#21270; pass&#65292;&#32780;&#26159;&#21487;&#20197;&#36827;&#20837;&#32534;&#35793;&#22120;&#30340;&#26680;&#24515;&#36335;&#24452;&#12290;</span></p><p><span>&#33258;&#20030;&#26412;&#36523;&#24182;&#19981;&#33021;&#31616;&#21333;&#35777;&#26126;&#19968;&#38376;&#35821;&#35328;&#33021;&#21147;&#30340;&#39640;&#20302;&#65292;&#20294;&#23427;&#20195;&#34920;&#20102;&#19968;&#31181;&#24037;&#31243;&#25104;&#29087;&#24230;&#65306;&#35821;&#35328;&#12289;&#32534;&#35793;&#22120;&#12289;&#26631;&#20934;&#24211;&#12289;&#21253;&#31649;&#29702;&#22120;&#21644;&#36328;&#24179;&#21488;&#26500;&#24314;&#31995;&#32479;&#65292;&#26159;&#21542;&#24050;&#32463;&#24378;&#22823;&#21040;&#36275;&#20197;&#25903;&#25745;&#33258;&#36523;&#30340;&#25345;&#32493;&#28436;&#36827;&#12290;&#23545;&#20110;&#19968;&#20010;&#24076;&#26395;&#22312; Apple &#24179;&#21488;&#20043;&#22806;&#32487;&#32493;&#25193;&#23637;&#24433;&#21709;&#21147;&#30340;&#35821;&#35328;&#26469;&#35828;&#65292;&#36825;&#19968;&#27493;&#30340;&#35937;&#24449;&#24847;&#20041;&#21644;&#23454;&#38469;&#20215;&#20540;&#37117;&#19981;&#23567;&#12290;</span></p><p><span>&#25226; SPI &#21152;&#20837; Apple &#19982; Swift &#32534;&#35793;&#22120;&#36808;&#21521;&#33258;&#25176;&#31649;&#25918;&#22312;&#19968;&#36215;&#30475;&#65292;&#20250;&#21457;&#29616;&#23427;&#20204;&#25351;&#21521;&#30340;&#26159;&#21516;&#19968;&#20214;&#20107;&#65306;Swift &#27491;&#22312;&#34917;&#40784;&#29983;&#24577;&#22522;&#30784;&#35774;&#26045;&#12290;&#21069;&#32773;&#20851;&#20046;&#21253;&#30340;&#21457;&#29616;&#12289;&#36523;&#20221;&#12289;&#31614;&#21517;&#21644;&#21487;&#20449;&#20998;&#21457;&#65292;&#21518;&#32773;&#21017;&#25552;&#21319;&#20102;&#35821;&#35328;&#24037;&#20855;&#38142;&#33258;&#36523;&#30340;&#21487;&#32500;&#25252;&#24615;&#19982;&#28436;&#36827;&#33021;&#21147;&#12290;Swift &#33021;&#21542;&#30495;&#27491;&#30772;&#22280;&#65292;&#20851;&#38190;&#24182;&#19981;&#21482;&#22312;&#20110; Apple &#22312;&#20854;&#20013;&#25317;&#26377;&#22810;&#22823;&#30340;&#24433;&#21709;&#21147;&#65292;&#32780;&#22312;&#20110; Apple &#19982; Swift &#31038;&#21306;&#26159;&#21542;&#33021;&#25345;&#32493;&#23637;&#29616;&#24320;&#25918;&#12289;&#36827;&#21462;&#30340;&#24577;&#24230;&#65292;&#24182;&#25226;&#24037;&#20855;&#38142;&#12289;&#21253;&#29983;&#24577;&#21644;&#36328;&#24179;&#21488;&#20307;&#39564;&#25171;&#30952;&#21040;&#36275;&#22815;&#23436;&#25972;&#12290;&#23601;&#36825;&#20004;&#20214;&#20107;&#32780;&#35328;&#65292;&#25105;&#24895;&#24847;&#20445;&#25345;&#20048;&#35266;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-141/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-01"><span>&#22312; Apple II &#19978;&#36305; Swift (Bring Swift to The APPLE II)</span></a></strong></h3><p><span>Apple II &#26159;&#33529;&#26524;&#26089;&#26399;&#26368;&#37325;&#35201;&#30340;&#20135;&#21697;&#20043;&#19968;&#65292;&#33267;&#20170;&#20173;&#24433;&#21709;&#30528;&#35768;&#22810;&#24320;&#21457;&#32773;&#12290;&#24456;&#22810;&#20154;&#37117;&#26366;&#22312;&#23427;&#19978;&#38754;&#20351;&#29992; BASIC &#25110; Apple Pascal&#65292;&#20294;&#22914;&#26524;&#22312;&#36825;&#21488;&#26426;&#22120;&#19978;&#20889; Swift&#65292;&#21448;&#20250;&#26159;&#20160;&#20040;&#20307;&#39564;&#65311;</span><a href="https://x.com/yeokm1"><span>Yeo Kheng Meng</span></a><span>&#8288; &#23454;&#29616;&#20102;&#19968;&#20010; Swift &#39118;&#26684;&#30340;&#36855;&#20320;&#24320;&#21457;&#29615;&#22659; SwiftII&#65292;&#35753;&#19968;&#21488;&#25645;&#36733; 1 MHz 6502 CPU&#12289;64 KB &#32423;&#21035;&#20869;&#23384;&#30340;&#32769;&#26426;&#22120;&#20063;&#33021;&#32534;&#20889;&#21644;&#36816;&#34892;&#31867;&#20284; Swift &#30340;&#31243;&#24207;&#12290;</span></p><p><span>&#25991;&#31456;&#31934;&#24425;&#30340;&#22320;&#26041;&#19981;&#21482;&#26159;&#8220;&#35753; Apple II &#36305;&#19978;&#31867; Swift &#35821;&#35328;&#8221;&#65292;&#36824;&#21253;&#25324;&#22823;&#37327;&#22260;&#32469;&#30828;&#20214;&#38480;&#21046;&#30340;&#24037;&#31243;&#21462;&#33293;&#65306;&#26377;&#38480;&#30340;&#20869;&#23384;&#31354;&#38388;&#12289;&#35821;&#35328;&#21345;&#21644; ProDOS &#30340;&#20914;&#31361;&#12289;&#19981;&#21516; Apple II &#26426;&#22411;&#30340;&#38190;&#30424;&#19982;&#26174;&#31034;&#24046;&#24322;&#65292;&#20197;&#21450;&#20026;&#20160;&#20040;&#26368;&#32456;&#35201;&#25286;&#25104;&#22810;&#24352;&#30913;&#30424;&#38236;&#20687;&#21457;&#24067;&#12290;&#20316;&#32773;&#20063;&#22374;&#35802;&#20998;&#20139;&#20102; AI &#36741;&#21161;&#24320;&#21457;&#30340;&#36807;&#31243;&#12290;&#21363;&#20415;&#26377; Claude Code &#21644; Codex &#30340;&#24110;&#21161;&#65292;&#20851;&#38190;&#30340;&#26550;&#26500;&#21462;&#33293;&#12289;&#33539;&#22260;&#25511;&#21046;&#21644;&#30828;&#20214;&#27979;&#35797;&#31574;&#30053;&#20173;&#28982;&#38656;&#35201;&#20316;&#32773;&#33258;&#24049;&#25226;&#20851;&#12290;&#26412;&#25991;&#26082;&#26377;&#22797;&#21476;&#35745;&#31639;&#26426;&#30340;&#24037;&#31243;&#32454;&#33410;&#65292;&#20063;&#26377;&#29616;&#20195;&#35821;&#35328;&#35774;&#35745;&#22312;&#26497;&#23567;&#29615;&#22659;&#20013;&#30340;&#21462;&#33293;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-02"><span>&#22522;&#20110; WebAssembly &#23454;&#29616; Swift App &#28909;&#26356;&#26032; (Building an over-the-air update system for native Swift with WebAssembly, from scratch)</span></a></strong></h3><p><span>&#20026;&#21407;&#29983; Swift iOS App &#26500;&#24314; OTA &#26356;&#26032;&#26426;&#21046;&#65292;&#26159;&#19968;&#20010;&#26377;&#20105;&#35758;&#20294;&#20063;&#24456;&#26377;&#20215;&#20540;&#30340;&#26041;&#21521;&#12290;</span><a href="https://www.linkedin.com/in/jackasolomon/"><span>Jack Solomon</span></a><span>&#8288; &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#23637;&#31034;&#20102;&#22522;&#20110; WebAssembly &#30340;&#23454;&#29616;&#24605;&#36335;&#65306;&#23558; Swift &#20989;&#25968;&#32534;&#35793;&#25104; WASM&#65292;&#20877;&#36890;&#36807; WasmKit &#22312; iOS App &#20869;&#21152;&#36733;&#25191;&#34892;&#65292;&#38543;&#21518;&#20174;&#26381;&#21153;&#22120;&#19979;&#36733;&#26032;&#30340; WASM &#27169;&#22359;&#65292;&#35753; App &#22312;&#19981;&#37325;&#26032;&#26500;&#24314;&#12289;&#19981;&#26367;&#25442;&#24050;&#31614;&#21517;&#20108;&#36827;&#21046;&#30340;&#24773;&#20917;&#19979;&#25913;&#21464;&#36816;&#34892;&#32467;&#26524;&#12290;</span></p><p><span>&#25991;&#31456;&#25286;&#35299;&#20102; Swift to WASM &#30340;&#24037;&#20855;&#38142;&#12289;WASI&#12289;</span><code>@_cdecl</code><span> &#23548;&#20986;&#12289;reactor module&#12289;&#32447;&#24615;&#20869;&#23384;&#20256;&#21442;&#65292;&#20197;&#21450; SwiftUI &#35270;&#22270;&#28909;&#26356;&#26032;&#20026;&#20160;&#20040;&#38656;&#35201; dynamic replacement &#21644;&#21487;&#24207;&#21015;&#21270;&#30340;&#35270;&#22270;&#25551;&#36848;&#26641;&#12290;Jack &#20063;&#23558;&#36825;&#22871;&#24605;&#36335;&#21253;&#35013;&#25104;&#20102; Swift SDK&#65306;</span><a href="https://github.com/patch-release/patch-swift"><span>patch-swift</span></a><span>&#8288;&#12290;</span></p><blockquote><p><span>&#38656;&#35201;&#27880;&#24847;&#30340;&#26159;&#65292;&#36825;&#31867;&#26041;&#26696;&#35302;&#21450; App Store &#23457;&#26680;&#35268;&#21017;&#20013;&#20851;&#20110;&#19979;&#36733;&#21644;&#25191;&#34892;&#20195;&#30721;&#30340;&#36793;&#30028;&#65292;&#23454;&#38469;&#20351;&#29992;&#26102;&#20173;&#38656;&#35201;&#35880;&#24910;&#35780;&#20272;&#22330;&#26223;&#21644;&#21512;&#35268;&#39118;&#38505;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-03"><span>&#29702;&#35299; SwiftUI &#30340;&#24213;&#23618;&#26680;&#24515;&#65306;&#23646;&#24615;&#22270; (SwiftUI Is One Graph)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/mihaelamj"><span>Mihaela Mihaljevi&#263; Jaki&#263;</span></a><span> &#22312;&#36807;&#21435;&#19968;&#21608;&#36830;&#32493;&#21457;&#34920;&#20102;&#20004;&#31687;&#20851;&#20110; SwiftUI &#24213;&#23618;&#26426;&#21046;&#30340;&#38271;&#25991;&#65292;&#20540;&#24471;&#25918;&#22312;&#19968;&#36215;&#38405;&#35835;&#12290;&#31532;&#19968;&#31687; SwiftUI Is One Graph &#20174;&#23454;&#38469;&#34892;&#20026;&#21644; Apple &#19987;&#21033;&#20986;&#21457;&#65292;&#35299;&#37322; SwiftUI &#24182;&#19981;&#26159;&#31616;&#21333;&#30340; View Tree diff&#65292;&#32780;&#26356;&#20687;&#26159;&#19968;&#20010; demand-driven attribute graph&#65306;View struct &#26412;&#36523;&#21482;&#26159;&#21487;&#20002;&#24323;&#30340;&#25551;&#36848;&#65292;&#30495;&#27491;&#25345;&#32493;&#23384;&#22312;&#30340;&#26159;&#23646;&#24615;&#22270;&#65292;&#20197;&#21450;&#20854;&#20013;&#30340;&#29366;&#24577;&#12289;&#20381;&#36182;&#12289;&#24067;&#23616;&#21644;&#21160;&#30011;&#20256;&#25773;&#12290;</span></p><p><span>&#31532;&#20108;&#31687; &#12298;</span><a href="https://l.fatbobman.com/w0142-04"><span>The SwiftUI Oracle: Measuring a Clean Room Against the Real Thing</span></a><span>&#12299;&#21017;&#36827;&#19968;&#27493;&#23637;&#31034;&#20102;&#22914;&#20309;&#39564;&#35777;&#36825;&#31181;&#29702;&#35299;&#12290;&#20316;&#32773;&#23454;&#29616;&#20102;&#19968;&#20010;&#19981;&#20381;&#36182; SwiftUI &#30340; clean-room &#24341;&#25806; PureView&#65292;&#20877;&#25226;&#30495;&#23454; SwiftUI &#24403;&#20316; oracle&#65292;&#36890;&#36807;&#24067;&#23616;&#12289;&#21160;&#30011;&#12289;&#20687;&#32032;&#28210;&#26579;&#31561; differential testing &#21435;&#39564;&#35777;&#33258;&#24049;&#30340;&#27169;&#22411;&#12290;</span></p><blockquote><p><span>Mihaela &#30340;&#24037;&#20316;&#27969;&#23545; AI agent &#24456;&#26377;&#21551;&#21457;&#12290;Agent &#19981;&#38656;&#35201;&#21482;&#38752;&#35821;&#35328;&#27169;&#22411;&#21435;&#29468; SwiftUI &#34892;&#20026;&#26159;&#21542;&#27491;&#30830;&#65292;&#32780;&#26159;&#21487;&#20197;&#29983;&#25104;&#25110;&#20462;&#25913;&#23454;&#29616;&#65292;&#28982;&#21518;&#36816;&#34892;&#27979;&#35797;&#65292;&#35753;&#30495;&#23454; SwiftUI &#32473;&#20986;&#21487;&#27604;&#36739;&#30340;&#32467;&#26524;&#12290;&#36825;&#31181;&#31867;&#20284;&#8220;&#21333;&#20803;&#27979;&#35797;&#8221;&#30340;&#21453;&#39304;&#38381;&#29615;&#65292;&#33021;&#25226;&#23545;&#40657;&#30418;&#26694;&#26550;&#30340;&#29702;&#35299;&#21464;&#25104;&#21487;&#20197;&#25345;&#32493;&#39564;&#35777;&#21644;&#36845;&#20195;&#30340;&#24037;&#31243;&#20449;&#21495;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-05"><span>&#22312; SwiftUI &#20013;&#23454;&#29616;&#21487;&#25318;&#25130;&#22238;&#35843;&#30340;&#33756;&#21333;&#19982;&#36873;&#25321;&#22120; (SwiftUI: Intercept-able Picker / Menu / Context Menu)</span></a></strong></h3><p><span>&#24456;&#22810;&#22330;&#26223;&#19979;&#65292;&#24320;&#21457;&#32773;&#37117;&#24076;&#26395;&#33021;&#22312; </span><code>Menu</code><span>&#12289;</span><code>Picker</code><span>&#12289;</span><code>contextMenu</code><span> &#31561;&#32452;&#20214;&#24377;&#20986;&#21069;&#25191;&#34892;&#19968;&#20123;&#21516;&#27493;&#25805;&#20316;&#65292;&#27604;&#22914;&#32479;&#35745;&#25171;&#24320;&#27425;&#25968;&#12289;&#26356;&#26032;&#29366;&#24577;&#65292;&#25110;&#32773;&#20020;&#26102;&#20915;&#23450;&#26159;&#21542;&#20801;&#35768;&#23637;&#31034;&#12290;&#20294; SwiftUI &#24182;&#27809;&#26377;&#25552;&#20379;&#23545;&#24212;&#30340;&#22238;&#35843;&#12290;</span><a href="https://x.com/itsuki68391179"><span>Itsuki</span></a><span>&#8288; &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#20998;&#20139;&#20102;&#33258;&#24049;&#30340;&#23454;&#29616;&#24605;&#36335;&#65306;&#36890;&#36807;&#26725;&#25509;&#19968;&#20010;&#25215;&#36733; SwiftUI &#20869;&#23481;&#30340;&#21407;&#29983; View&#65292;&#22312;&#23545;&#24212;&#25163;&#21183;&#35302;&#21457;&#26102;&#20808;&#25191;&#34892; </span><code>menuWillOpen</code><span>&#65292;&#20877;&#20915;&#23450;&#26159;&#21542;&#20351;&#29992; </span><code>NSMenu.popUpContextMenu</code><span> &#31561; AppKit API &#20027;&#21160;&#23637;&#31034;&#33756;&#21333;&#12290;</span></p><blockquote><p><span>&#26412;&#25991;&#20877;&#27425;&#20307;&#29616;&#20102; SwiftUI &#30340;&#19968;&#20010;&#29616;&#23454;&#38382;&#39064;&#65306;&#24456;&#22810;&#30475;&#20284;&#31616;&#21333;&#30340;&#20132;&#20114;&#25511;&#21046;&#65292;&#19968;&#26086;&#36229;&#20986;&#31995;&#32479; modifier &#26292;&#38706;&#30340;&#33021;&#21147;&#65292;&#20173;&#28982;&#38656;&#35201;&#29702;&#35299;&#24213;&#23618; AppKit / UIKit &#25165;&#33021;&#30495;&#27491;&#35299;&#20915;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-06"><span>&#35299;&#26512; UIPortalView&#65306;&#20174;&#35270;&#22270;&#23454;&#26102;&#25237;&#24433;&#21040;&#27969;&#20307;&#29627;&#29827;&#29305;&#25928; (_UIPortalView: From Live Mirroring to Liquid Glass-Style Effects)</span></a></strong></h3><p><a href="https://www.linkedin.com/in/artem-mirzabekian/"><span>Artem Mirzabekian</span></a><span>&#8288; &#20998;&#20139;&#20102; UIKit &#20013;&#19968;&#20010;&#26377;&#36259;&#30340;&#31169;&#26377;&#32452;&#20214; </span><code>_UIPortalView</code><span>&#12290;&#23427;&#30001; </span><code>CAPortalLayer</code><span> &#25903;&#25345;&#65292;&#21487;&#20197;&#25226;&#26576;&#20010; </span><code>sourceView</code><span> &#30340;&#28210;&#26579;&#32467;&#26524;&#23454;&#26102;&#25237;&#23556;&#21040;&#23631;&#24149;&#19978;&#30340;&#21478;&#19968;&#20010;&#20301;&#32622;&#65292;&#32780;&#19981;&#38656;&#35201;&#22797;&#21046;&#19968;&#20221; View &#23618;&#32423;&#65292;&#20063;&#19981;&#38656;&#35201;&#21453;&#22797;&#29983;&#25104; snapshot&#12290;&#30456;&#27604;&#38745;&#24577;&#24555;&#29031;&#65292;Portal &#26356;&#20687;&#26159;&#21512;&#25104;&#23618;&#19978;&#30340;&#8220;&#23454;&#26102;&#31383;&#21475;&#8221;&#65306;&#28304;&#35270;&#22270;&#20173;&#28982;&#26159;&#21807;&#19968;&#29366;&#24577;&#26469;&#28304;&#65292;&#32780;&#25991;&#26412;&#12289;&#21160;&#30011;&#12289;&#24067;&#23616;&#25110;&#23376;&#35270;&#22270;&#21464;&#21270;&#37117;&#21487;&#20197;&#21516;&#27493;&#21453;&#26144;&#21040;&#21478;&#19968;&#22788;&#26174;&#31034;&#12290;</span></p><p><span>&#25991;&#31456;&#36824;&#25226; </span><code>_UIPortalView</code><span> &#21644; Liquid Glass &#25928;&#26524;&#32852;&#31995;&#36215;&#26469;&#65306;&#36890;&#36807; </span><code>matchesPosition</code><span>&#12289;&#35009;&#21098;&#12289;&#20559;&#31227;&#21644; 3D transform&#65292;&#21487;&#20197;&#23454;&#29616;&#23454;&#26102;&#38236;&#20687;&#12289;&#21453;&#23556;&#12289;&#38236;&#22836;&#12289;&#20849;&#20139;&#32972;&#26223;&#21644;&#36793;&#32536;&#25197;&#26354;&#31561;&#25928;&#26524;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0142-07"><span>&#25484;&#25511; SwiftUI &#24037;&#20855;&#26639;&#26032; API (Taking control of toolbar items in SwiftUI)</span></a></strong></h3><p><span>WWDC 26 &#24102;&#26469;&#30340;&#26032; SwiftUI Toolbar API&#65292;&#35753;&#31995;&#32479;&#33258;&#36866;&#24212;&#21644;&#24320;&#21457;&#32773;&#26174;&#24335;&#25511;&#21046;&#20043;&#38388;&#21462;&#24471;&#20102;&#26356;&#22909;&#30340;&#24179;&#34913;&#12290;</span><a href="https://x.com/mecid"><span>Majid Jabrayilov</span></a><span> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#20171;&#32461;&#20102;&#20960;&#39033;&#26032;&#30340;&#25511;&#21046;&#33021;&#21147;&#65306;&#36890;&#36807; </span><code>visibilityPriority</code><span> &#25351;&#23450; toolbar item &#30340;&#26174;&#31034;&#20248;&#20808;&#32423;&#65292;&#29992; </span><code>ToolbarOverflowMenu</code><span> &#26126;&#30830;&#21019;&#24314;&#25240;&#21472;&#33756;&#21333;&#65292;&#20511;&#21161; </span><code>.topBarPinnedTrailing</code><span> &#23558;&#37325;&#35201;&#25805;&#20316;&#22266;&#23450;&#22312;&#39030;&#37096;&#26639;&#23614;&#37096;&#65292;&#20197;&#21450;&#20351;&#29992; </span><code>toolbarMinimizeBehavior</code><span> &#25511;&#21046;&#23548;&#33322;&#26639;&#12289;&#26631;&#31614;&#26639;&#12289;&#24213;&#37096;&#26639;&#31561;&#22312;&#28378;&#21160;&#26102;&#30340;&#26368;&#23567;&#21270;&#34892;&#20026;&#12290;</span></p><p><span>&#21516;&#19968;&#32452; toolbar items &#22312; iOS&#12289;iPadOS &#21644; macOS &#19978;&#21487;&#33021;&#20250;&#26377;&#19981;&#21516;&#30340;&#23637;&#31034;&#26041;&#24335;&#12290;&#26032; API &#30340;&#20215;&#20540;&#22312;&#20110;&#65292;&#23427;&#20204;&#27809;&#26377;&#30772;&#22351; SwiftUI Toolbar &#21407;&#26412;&#30340;&#36328;&#24179;&#21488;&#33258;&#36866;&#24212;&#33021;&#21147;&#65292;&#21364;&#35753;&#24320;&#21457;&#32773;&#21487;&#20197;&#26356;&#26126;&#30830;&#22320;&#34920;&#36798;&#21738;&#20123;&#25805;&#20316;&#24212;&#35813;&#20248;&#20808;&#26174;&#31034;&#12289;&#21738;&#20123;&#25805;&#20316;&#21487;&#20197;&#20027;&#21160;&#25918;&#36827; overflow&#65292;&#20197;&#21450;&#24037;&#20855;&#26639;&#24212;&#35813;&#22914;&#20309;&#21709;&#24212;&#28378;&#21160;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0142-08"><span>iOS-Simulator-Camera-Extend&#65306;&#32473; iOS Simulator &#34917;&#19978;&#8220;&#30495;&#23454;&#21487;&#29992;&#30340;&#30456;&#26426;&#8221;</span></a></strong></h3><p><span>iOS Simulator &#19968;&#30452;&#27809;&#26377;&#30495;&#27491;&#30340;&#30456;&#26426;&#33021;&#21147;&#65292;&#28041;&#21450;&#25195;&#30721;&#12289;OCR&#12289;&#20154;&#33080;&#12289;&#35270;&#39057;&#36890;&#35805;&#12289;</span><code>AVCaptureSession</code><span> &#30340;&#21151;&#33021;&#65292;&#24448;&#24448;&#21482;&#33021;&#19978;&#30495;&#26426;&#25110;&#20889;&#27169;&#25311;&#36923;&#36753;&#12290;&#30001; </span><a href="https://x.com/GSYTech_CarGuo"><span>Shuyu Guo</span></a><span>&#8288; &#24320;&#21457;&#30340; iOS-Simulator-Camera-Extend &#22797;&#21051;&#20102; SimCam &#30340;&#26680;&#24515;&#24605;&#36335;&#65292;&#36890;&#36807; macOS &#31471;&#24103;&#28304;&#12289;Simulator &#20869; </span><code>DYLD_INSERT_LIBRARIES</code><span> hook &#19982; AVFoundation swizzle&#65292;&#35753;&#34987;&#27979; App &#26080;&#38656;&#25913;&#20195;&#30721;&#12289;&#26080;&#38656;&#25442; bundle id&#65292;&#23601;&#33021;&#22312;&#27169;&#25311;&#22120;&#37324;&#25343;&#21040; Mac &#25668;&#20687;&#22836;&#12289;&#26700;&#38754;&#12289;&#22270;&#29255;&#12289;&#35270;&#39057;&#21644;&#20108;&#32500;&#30721;&#30011;&#38754;&#12290;</span></p><p><span>&#26356;&#26377;&#24847;&#24605;&#30340;&#26159;&#65292;&#23427;&#36824;&#25552;&#20379;&#20102;&#21478;&#19968;&#26465; CMIO System Extension &#38142;&#36335;&#65292;&#35753; QuickTime&#12289;FaceTime&#12289;Zoom&#12289;OBS &#31561; macOS &#24212;&#29992;&#20063;&#33021;&#30475;&#21040;&#19968;&#21488; SimCam Virtual Camera&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;&#21516;&#19968;&#20221;&#24103;&#28304;&#26082;&#21487;&#20197;&#21890;&#32473; iOS Simulator &#37324;&#30340; App&#65292;&#20063;&#21487;&#20197;&#20316;&#20026; macOS &#34394;&#25311;&#25668;&#20687;&#22836;&#20351;&#29992;&#65292;&#23545;&#30456;&#26426;&#30456;&#20851;&#21151;&#33021;&#30340;&#35843;&#35797;&#12289;&#28436;&#31034;&#21644;&#33258;&#21160;&#21270;&#27979;&#35797;&#37117;&#24456;&#23454;&#29992;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #141]]></title><description><![CDATA[Is Anyone Else Excited by Swift&#8217;s Progress as a Language?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 22 Jun 2026 12:02:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1E-5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1E-5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1E-5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp" width="1400" height="933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:933,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:205812,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/203025332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1E-5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 424w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 848w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1272w, https://substackcdn.com/image/fetch/$s_!1E-5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cf57250-fac7-451d-bed6-475adf571a3c_1400x933.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><span>Photo by </span><a href="https://unsplash.com/@guillealvarez?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Guille &#193;lvarez</a><span> on </span><a href="https://unsplash.com/photos/people-jumping-on-shore-front-of-golden-hour-IcI3FizU9Cw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong><span>Is Anyone Else Excited by Swift&#8217;s Progress as a Language?</span></strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-141/">Read on web &#8594;</a></p><p><span>Last week, a Reddit post titled &#8220;</span><a href="https://www.reddit.com/r/swift/comments/1u5skay/is_anyone_else_excited_by_swift_progress_as_the/"><span>Is anyone else excited by Swift progress as the language?</span></a><span>&#8288;&#8221; sparked a lively discussion. At WWDC 2026, Apple made it clear that Swift is now being used in key WebKit components, the QUIC networking stack, font rendering, drivers, and firmware&#8212;and, as the original poster claimed, it has started making its way into the core operating system kernel beginning with the 27 releases. The original poster saw this as Apple finally delivering on the promise it made in 2014 when it introduced Swift as a &#8220;high-level systems programming language.&#8221; The discussion soon expanded beyond whether that promise had been fulfilled to topics such as cross-platform support, language governance, the tooling experience, and whether Swift is becoming too large and ambitious.</span></p><p><span>Despite its remaining shortcomings, I still appreciate the progress Swift has made over the years. This week&#8217;s recommendations happen to offer several different perspectives on that progress: Swift 6.4 continues to fill in practical gaps in the concurrency model; KernelKit reveals the infrastructure Apple is laying for Swift in the kernel; and SwiftOS demonstrates Embedded Swift taking on an entire operating system and real-world service workloads. Swift&#8217;s progress is no longer measured only by the number of language features it has gained, but also by the growing range of work it can handle&#8212;and many of those use cases are no longer merely experimental.</span></p><p><span>Personally, since Swift 6, I have tried to adopt new language features wherever possible. For new projects, I have already raised the minimum required Swift compiler version to 6.2, and as my understanding deepens, I may raise it further. Some features involving concurrency, ownership, and isolation can feel awkward at first. Once their design goals become clear, however, they often turn out not to increase cognitive load, but to reduce it: correctness that once depended on conventions, comments, and developer experience can now be expressed as constraints the compiler is able to verify. The result is code that is easier to reason about, clearer in intent, and able to prevent many safety issues before it ever runs.</span></p><p><span>In the age of AI, a language&#8217;s ergonomic advantages may no longer determine adoption as decisively as they once did. As the cost of generating code falls, the real differentiators are more likely to be the ecosystem, tooling, available deployment targets, and whether the compiler can provide consistently reliable feedback. But that does not make language design less important&#8212;it simply changes how its value appears. As AI participates in writing more of our code, strong type systems, explicit ownership semantics, and strict concurrency checking become machine-verifiable guardrails. AI can produce code faster; the language and compiler help us determine which of that code deserves to be trusted.</span></p><p><span>Swift has always occupied a somewhat contradictory position. The Apple ecosystem gives it a large, stable field of application, yet it has also caused the language to be seen for years as something that &#8220;belongs only to Apple.&#8221; That ecosystem is both the hardest boundary for Swift to cross as it expands outward and the solid foundation that ensures continued investment, steady evolution, and protection from fading into irrelevance. Today, developments such as the official Android SDK, the WebAssembly SDK, and the Windows Working Group suggest that this boundary is gradually moving outward. Of course, tooling, package ecosystems, and the overall developer experience on non-Apple platforms still have a long way to go.</span></p><p><span>Does Swift still make me feel excited? Perhaps not exactly. But I genuinely enjoy where the language is today. Compared with the grand vision of a decade ago, I prefer the current pace: turning those promises into engineering reality, one step at a time.</span></p><p><a href="https://fatbobman.com/en/weekly/issue-140/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong><span>Original</span></strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/from-size-class-to-available-space/?utm_source=fatbobman%20weekly%20issue%20141&amp;utm_medium=web"><span>From Size Class to Available Space: Is horizontalSizeClass Still Reliable?</span></a></strong></h3><p><span>Starting with WWDC 26, iPhone apps mirrored to a Mac through iPhone Mirroring will support freely resizable windows. At the same time, iPhone-only apps running on iPad will also enter a variable-size environment. The impact of this update goes far beyond simply allowing iPhone apps to resize. It is changing how many developers have long understood the layout system. Traits that were once commonly used as the basis for layout decisions, such as </span><code>horizontalSizeClass</code><span>, are no longer suitable as the primary indicator of window width. So, is this change a sudden shift in direction, or the inevitable result of Apple&#8217;s years-long evolution of its layout system? This article explores that question.</span></p><h2><strong><span>Recent Recommendations</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-01"><span>Swift 6.4: What&#8217;s New in Concurrency</span></a></strong></h3><p><span>In this article, </span><a href="https://x.com/twannl"><span>Antoine van der Lee</span></a><span>&#8288; reviews a series of improvements Swift 6.4 brings to concurrency, including support for asynchronous cleanup in </span><code>defer</code><span>, cancellation shields that ensure critical cleanup or rollback operations can finish, warnings for ignored throwing </span><code>Task</code><span> instances, and typed error support for </span><code>Task</code><span>. In addition, </span><code>Result</code><span> can now directly wrap asynchronous throwing operations, while </span><code>~Sendable</code><span> and the </span><code>weak let</code><span> introduced in Swift 6.3 make the modeling of </span><code>Sendable</code><span> types more precise.</span></p><p><span>Compared with the more sweeping changes made to the concurrency model before Swift 6.2, these additions introduce relatively little new cognitive overhead. Instead, they refine the existing model and address practical engineering concerns involving cleanup, cancellation, error handling, and type modeling.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-02"><span>Apple Internals: Swift in the Kernel</span></a></strong></h3><p><span>Swift has now been around for more than a decade. As the creator of the language, has Apple begun using it to develop operating system kernels? Josh Maine of </span><a href="https://x.com/calif_io"><span>Calif</span></a><span> analyzed the macOS 27 and iOS 27 kernelcaches, along with the Xcode 27 Beta toolchain, and discovered that Apple has added an internal SDK called KernelKit, separate Mach-O platform identifiers for different operating systems, and an Embedded Swift runtime statically linked into a macOS kernel extension.</span></p><p><span>However, this does not mean that XNU is being rewritten in Swift. At present, Swift appears only at the kernel-extension layer. The runtime included in macOS is not yet referenced by any other component, while iOS has so far completed only the platform and toolchain groundwork. The infrastructure looks more like Apple laying down the toolchain, runtime, and linking environment before introducing actual Swift kernel components. In any case, it brings us one step closer to seeing real kernel components written in Swift.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-03"><span>Touch to Pixels: UI Pipeline Internals on iOS</span></a></strong></h3><p><span>What exactly happens inside the system after you tap an iOS interface but before the pixels on the screen change? Starting with a single touch event, </span><a href="https://x.com/jacobtechtavern"><span>Jacob Bartlett</span></a><span>&#8288; follows the entire journey through the touchscreen hardware, XNU, IOKit, backboardd, the app&#8217;s Run Loop, UIKit, and Core Animation. He traces how the event reaches our code, and how the resulting UI update passes through the Render Server, GPU, and frame buffer before finally becoming pixels on the display. Understanding this complete journey from Touch to Pixels not only gives us a clearer mental model of the iOS UI system, but also helps when diagnosing common performance issues such as main-thread blocking, stuttering animations, and dropped frames.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-04"><span>Dynamic Text in SwiftUI</span></a></strong></h3><p><span>Imagine an app with a global preference that determines whether every screen displays a user&#8217;s full name or nickname. The most direct approach is to add a conditional check everywhere a username appears, but the entire preference breaks down as soon as one new feature forgets to handle it. </span><a href="https://mastodon.social/@DLX"><span>Robb B&#246;hnke</span></a><span> solves this by using a BCP 47 private-use subtag to encode the preference into </span><code>Locale</code><span>, then reading it through a custom </span><code>FormatStyle</code><span> when </span><code>Text</code><span> is actually rendered. This approach works around SwiftUI&#8217;s lack of a dynamic </span><code>Text</code><span> initializer and turns logic that could easily be forgotten at individual call sites into application-wide default behavior.</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-05"><span>SwiftUI SensoryFeedback Cache Key Pitfall: Do Not Store Continuous Values</span></a></strong></h3><p><span>Can dynamically adjusting haptic feedback intensity with a Slider in SwiftUI really cause memory usage to grow rapidly? It sounds surprising, but the issue genuinely exists from iOS 17 through iOS 26. </span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> discovered that the internal implementation in these versions included continuous values such as </span><code>intensity</code><span> in the feedback generator&#8217;s cache key. Every tiny change in intensity could therefore correspond to a new </span><code>UIImpactFeedbackGenerator</code><span> instance, causing the cache to grow continuously.</span></p><p><span>Kyle filed an FB late last year and was notified this June that the issue had been fixed. Rather than patching the problem by introducing a cache-specific key, iOS 27 redraws the model boundary: it completely separates the &#8220;stable identity&#8221; represented by </span><code>FeedbackType</code><span> from the per-play dynamic parameters stored in the new </span><code>Payload</code><span>. The public API remains unchanged, but the cache behavior is corrected at the data-model level.</span></p><blockquote><p><span>What makes this fix worth studying is not merely that it resolves the memory-growth issue, but that it demonstrates an important principle of API design: stable information describing an object&#8217;s identity should not be mixed with dynamic parameters that affect only a single operation. It also reminds us that simply conforming to </span><code>Hashable</code><span> does not make a type inherently suitable for use as a cache key. Rather than repeatedly excluding exceptional fields at the point of use, drawing clear semantic boundaries in the data model is usually the more reliable design.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-06"><span>Architecting a Conversion Engine in Swift</span></a></strong></h3><p><span>When an application needs to convert among formats such as Markdown, HTML, rich text, and PDF, how can it prevent conversion logic from growing quadratically as more formats are added? </span><a href="https://bsky.app/profile/arthurvansiclen.com"><span>Arthur Van Siclen</span></a><span> explains the solution he developed for Minimal: introduce an Intermediate Representation, or IR, so that each format only needs its own Parser and Renderer. With six formats, this reduces the number of conversion relationships from 30 to 12.</span></p><p><span>Its treatment of lossy conversion is particularly worth learning from. Different formats do not have equivalent expressive capabilities, so Minimal uses </span><code>Concession</code><span> to explicitly record formatting that was downgraded, content that was dropped, or data that was truncated during conversion, rather than pretending that every conversion can be lossless.</span></p><h2><strong><span>Tools</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-07"><span>SwiftOS: Building a Real Operating System with Embedded Swift</span></a></strong></h3><p><span>SwiftOS is a 64-bit ARM operating system written almost entirely from scratch in Embedded Swift. Its author, </span><a href="https://www.linkedin.com/in/andrey-sapunov/"><span>Andrey Sapunov</span></a><span>, began with a straightforward idea: rather than learning operating-system concepts only from books, why not build one and truly understand how kernels, memory, processes, and devices work together? His choice of Swift was not merely a matter of language preference. He wanted to preserve predictable code generation and low-level control while using Swift&#8217;s type system, ownership model, and modern engineering tools to make systems code safer and easier to express.</span></p><p><span>SwiftOS follows a distinctly modern systems architecture: AArch64, MMU-based process address-space isolation, a custom syscall ABI, a capability-oriented authorization model, static linking, a signed read-only base image, and a native Swift userland. It already includes an in-kernel TCP/IP stack, can run nginx and Node.js, and is deployed on a real Hetzner Cloud ARM instance&#8212;the project&#8217;s website is hosted by SwiftOS itself.</span></p><blockquote><p><span>We may still need more time before Swift is widely used within Apple&#8217;s operating system kernels. But SwiftOS proves at least one thing: Embedded Swift is no longer limited to firmware and bare-metal examples. It is capable of supporting an operating system with process isolation, user-space programs, a network stack, and real service workloads.</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-08"><span>Loupe: Giving AI Agents Runtime Evidence for Native Apple UIs</span></a></strong></h3><p><span>Loupe, created by </span><a href="https://www.linkedin.com/in/won-heo-5a0497135/"><span>Won Heo</span></a><span>, is a runtime diagnostics and E2E verification tool for Apple platforms. It is particularly useful when AI coding agents such as Codex and Claude Code participate in native UI development. Loupe does not replace xcodebuild, XCTest, or other tools responsible for building and testing an application. Instead, by injecting or linking a runtime into a debug build, it adds a runtime UI evidence layer on top of them. From the app that is actually running, it can collect UIKit and AppKit view structures, accessibility information, screenshots, logs, URLSession network activity, and state such as Defaults and Feature Flags, then expose querying and auditing capabilities through its CLI.</span></p><p><span>An agent can begin with a compact observation of the UI, inspect specific nodes in greater detail as needed, perform simulator-visible actions such as </span><code>tap</code><span>, </span><code>swipe</code><span>, </span><code>drag</code><span>, and </span><code>type</code><span>, and record before-and-after snapshots, diffs, and traces. It can also make probe-like runtime changes to selected UIKit properties and constraints, quickly verify whether an adjustment works, and then return to the source code to implement the actual fix. This turns questions such as &#8220;Does it look right?&#8221;, &#8220;Does the interaction work?&#8221;, and &#8220;Has the layout drifted?&#8221; from screenshot-driven guesswork into a reviewable and reproducible chain of evidence.</span></p><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-141?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong><span>Swift &#36824;&#35753;&#20320; Excited &#21527;&#65311;</span></strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-141/">&#32593;&#39029;&#29256;</a></strong></p><p><span>&#19978;&#21608;&#65292;Reddit &#19978;&#19968;&#31687;&#39064;&#20026;&#12298;</span><a href="https://www.reddit.com/r/swift/comments/1u5skay/is_anyone_else_excited_by_swift_progress_as_the/"><span>Is anyone else excited by Swift progress as the language?</span></a><span>&#12299;&#30340;&#24086;&#23376;&#24341;&#21457;&#20102;&#19981;&#23569;&#35752;&#35770;&#12290;WWDC 2026 &#19978;&#65292;Apple &#26126;&#30830;&#34920;&#31034;&#65292;Swift &#24050;&#34987;&#29992;&#20110; WebKit &#20851;&#38190;&#32452;&#20214;&#12289;QUIC &#32593;&#32476;&#26632;&#12289;&#23383;&#20307;&#28210;&#26579;&#12289;&#39537;&#21160;&#19982;&#22266;&#20214;&#12290;&#21457;&#24086;&#32773;&#25454;&#27492;&#35748;&#20026;&#65292;Swift &#27491;&#22312;&#21521;&#26680;&#24515;&#25805;&#20316;&#31995;&#32479;&#20869;&#26680;&#36808;&#36827;&#65292;&#24182;&#23558;&#36825;&#19968;&#24149;&#35270;&#20026; 2014 &#24180;&#8221;&#39640;&#32423;&#31995;&#32479;&#32534;&#31243;&#35821;&#35328;&#8221;&#25215;&#35834;&#30340;&#20817;&#29616;&#12290;&#35780;&#35770;&#21306;&#30340;&#35752;&#35770;&#21017;&#24456;&#24555;&#20174;&#8220;&#26159;&#21542;&#20817;&#29616;&#20102;&#25215;&#35834;&#8221;&#65292;&#24310;&#20280;&#21040;&#36328;&#24179;&#21488;&#25903;&#25345;&#12289;&#35821;&#35328;&#27835;&#29702;&#12289;&#24037;&#20855;&#38142;&#20307;&#39564;&#65292;&#20197;&#21450; Swift &#26159;&#21542;&#27491;&#22312;&#21464;&#24471;&#36807;&#20110;&#24222;&#22823;&#31561;&#35805;&#39064;&#12290;</span></p><p><span>&#23613;&#31649;&#38382;&#39064;&#20381;&#28982;&#19981;&#23569;&#65292;&#25105;&#20173;&#28982;&#24456;&#27427;&#36175; Swift &#36825;&#20123;&#24180;&#30340;&#36827;&#23637;&#12290;&#26412;&#26399;&#25512;&#33616;&#30340;&#20869;&#23481;&#20063;&#24688;&#22909;&#25552;&#20379;&#20102;&#20960;&#20010;&#19981;&#21516;&#30340;&#35266;&#23519;&#20999;&#38754;&#65306;Swift 6.4 &#32487;&#32493;&#34917;&#40784;&#24182;&#21457;&#27169;&#22411;&#20013;&#30340;&#24037;&#31243;&#32454;&#33410;&#65292;KernelKit &#23637;&#31034;&#20102; Apple &#20026;&#20869;&#26680; Swift &#38138;&#35774;&#30340;&#22522;&#30784;&#35774;&#26045;&#65292;SwiftOS &#21017;&#35753; Embedded Swift &#25215;&#25285;&#36215;&#19968;&#20010;&#23436;&#25972;&#25805;&#20316;&#31995;&#32479;&#19982;&#30495;&#23454;&#26381;&#21153;&#36127;&#36733;&#12290;Swift &#30340;&#36827;&#27493;&#24050;&#19981;&#21482;&#20307;&#29616;&#20026;&#35821;&#35328;&#29305;&#24615;&#36234;&#26469;&#36234;&#22810;&#65292;&#26356;&#20307;&#29616;&#22312;&#23427;&#33021;&#22815;&#32988;&#20219;&#30340;&#24037;&#20316;&#31181;&#31867;&#19981;&#26029;&#22686;&#21152;&#65292;&#32780;&#19988;&#20854;&#20013;&#19981;&#23569;&#24050;&#32463;&#36208;&#20986;&#20102;&#23454;&#39564;&#38454;&#27573;&#12290;</span></p><p><span>&#23601;&#25105;&#20010;&#20154;&#32780;&#35328;&#65292;&#20174; Swift 6 &#24320;&#22987;&#65292;&#25105;&#20960;&#20046;&#37117;&#22312;&#23613;&#21487;&#33021;&#22320;&#20351;&#29992;&#26032;&#30340;&#35821;&#35328;&#33021;&#21147;&#12290;&#22312;&#26032;&#39033;&#30446;&#20013;&#65292;&#25105;&#24050;&#32463;&#23558; Swift &#32534;&#35793;&#22120;&#30340;&#26368;&#20302;&#29256;&#26412;&#35201;&#27714;&#35774;&#32622;&#20026; 6.2&#65307;&#38543;&#30528;&#29702;&#35299;&#19981;&#26029;&#28145;&#20837;&#65292;&#26410;&#26469;&#21487;&#33021;&#36824;&#20250;&#32487;&#32493;&#25552;&#39640;&#12290;&#19968;&#20123;&#28041;&#21450;&#24182;&#21457;&#12289;&#25152;&#26377;&#26435;&#21644;&#38548;&#31163;&#30340;&#29305;&#24615;&#65292;&#21021;&#30475;&#26102;&#30830;&#23454;&#26377;&#20123;&#25303;&#21475;&#65292;&#20294;&#30495;&#27491;&#29702;&#35299;&#20854;&#35774;&#35745;&#30446;&#26631;&#21518;&#24448;&#24448;&#20250;&#21457;&#29616;&#65306;&#23427;&#20204;&#19981;&#26159;&#22312;&#22686;&#21152;&#24515;&#26234;&#36127;&#25285;&#65292;&#32780;&#26159;&#22312;&#25226;&#36807;&#21435;&#20381;&#36182;&#32422;&#23450;&#12289;&#27880;&#37322;&#21644;&#32463;&#39564;&#32500;&#25345;&#30340;&#27491;&#30830;&#24615;&#65292;&#36716;&#21464;&#20026;&#32534;&#35793;&#22120;&#21487;&#20197;&#26816;&#26597;&#30340;&#32422;&#26463;&#12290;&#20195;&#30721;&#22240;&#27492;&#26356;&#23481;&#26131;&#25512;&#29702;&#65292;&#24847;&#22270;&#20063;&#26356;&#21152;&#28165;&#26970;&#65292;&#35768;&#22810;&#23433;&#20840;&#38382;&#39064;&#21017;&#22312;&#36816;&#34892;&#20043;&#21069;&#23601;&#34987;&#25377;&#20102;&#19979;&#26469;&#12290;</span></p><p><span>&#22312; AI &#26102;&#20195;&#65292;&#19968;&#38376;&#35821;&#35328;&#30340;&#20154;&#20307;&#24037;&#23398;&#20248;&#21183;&#65292;&#25110;&#35768;&#19981;&#20877;&#20687;&#36807;&#21435;&#37027;&#26679;&#21333;&#29420;&#20915;&#23450;&#24320;&#21457;&#32773;&#26159;&#21542;&#24895;&#24847;&#37319;&#29992;&#23427;&#8212;&#8212;&#29983;&#25104;&#20195;&#30721;&#30340;&#25104;&#26412;&#19979;&#38477;&#21518;&#65292;&#30495;&#27491;&#25289;&#24320;&#24046;&#36317;&#30340;&#26356;&#21487;&#33021;&#26159;&#29983;&#24577;&#12289;&#24037;&#20855;&#38142;&#12289;&#21487;&#37096;&#32626;&#30340;&#24179;&#21488;&#65292;&#20197;&#21450;&#32534;&#35793;&#22120;&#33021;&#21542;&#25345;&#32493;&#25552;&#20379;&#21487;&#38752;&#21453;&#39304;&#12290;&#20294;&#35821;&#35328;&#35774;&#35745;&#30340;&#37325;&#35201;&#24615;&#24182;&#26410;&#22240;&#27492;&#20943;&#24369;&#65292;&#21453;&#32780;&#25442;&#20102;&#19968;&#31181;&#26041;&#24335;&#20307;&#29616;&#65306;&#24403;&#36234;&#26469;&#36234;&#22810;&#20195;&#30721;&#30001; AI &#21442;&#19982;&#29983;&#25104;&#26102;&#65292;&#24378;&#31867;&#22411;&#31995;&#32479;&#12289;&#26126;&#30830;&#30340;&#25152;&#26377;&#26435;&#35821;&#20041;&#21644;&#20005;&#26684;&#30340;&#24182;&#21457;&#26816;&#26597;&#65292;&#37117;&#20250;&#25104;&#20026;&#21487;&#26426;&#22120;&#39564;&#35777;&#30340;&#25252;&#26639;&#12290;AI &#21487;&#20197;&#26356;&#24555;&#22320;&#20135;&#29983;&#20195;&#30721;&#65292;&#32780;&#35821;&#35328;&#21644;&#32534;&#35793;&#22120;&#36127;&#36131;&#21578;&#35785;&#25105;&#20204;&#65292;&#21738;&#20123;&#20195;&#30721;&#20540;&#24471;&#20449;&#20219;&#12290;</span></p><p><span>Swift &#30340;&#22788;&#22659;&#20063;&#22987;&#32456;&#24102;&#30528;&#19968;&#31181;&#30683;&#30462;&#12290;Apple &#29983;&#24577;&#20026;&#23427;&#25552;&#20379;&#20102;&#31283;&#23450;&#19988;&#24222;&#22823;&#30340;&#24212;&#29992;&#22330;&#26223;&#65292;&#21364;&#20063;&#38271;&#26399;&#35753;&#22806;&#30028;&#23558;&#20854;&#35270;&#20026;&#19968;&#38376;&#8220;&#21482;&#23646;&#20110; Apple&#8221;&#30340;&#35821;&#35328;&#12290;&#36825;&#20010;&#29983;&#24577;&#26082;&#26159; Swift &#21521;&#22806;&#25193;&#24352;&#26102;&#26368;&#38590;&#36328;&#36234;&#30340;&#36793;&#30028;&#65292;&#20063;&#26159;&#23427;&#33021;&#22815;&#24471;&#21040;&#38271;&#26399;&#25237;&#20837;&#12289;&#31283;&#27493;&#28436;&#36827;&#65292;&#19981;&#33267;&#20110;&#36731;&#26131;&#34987;&#26102;&#20195;&#28120;&#27760;&#30340;&#22362;&#23454;&#21518;&#30462;&#12290;&#22914;&#20170;&#65292;&#23448;&#26041; Android SDK&#12289;WebAssembly SDK &#21644; Windows &#24037;&#20316;&#32452;&#31561;&#36827;&#23637;&#34920;&#26126;&#65292;&#36825;&#26465;&#36793;&#30028;&#27491;&#22312;&#36880;&#28176;&#21521;&#22806;&#31227;&#21160;&#65307;&#24403;&#28982;&#65292;&#38750; Apple &#24179;&#21488;&#19978;&#30340;&#24037;&#20855;&#38142;&#12289;&#21253;&#29983;&#24577;&#21644;&#24320;&#21457;&#20307;&#39564;&#20173;&#26377;&#24456;&#38271;&#30340;&#36335;&#35201;&#36208;&#12290;</span></p><p><span>&#35201;&#35828; Swift &#29616;&#22312;&#26159;&#21542;&#20173;&#35753;&#25105;&#24863;&#21040; Excited&#65292;&#20498;&#20063;&#26410;&#24517;&#65307;&#20294;&#25105;&#30830;&#23454;&#24456; Enjoy &#23427;&#24403;&#21069;&#30340;&#29366;&#24577;&#12290;&#30456;&#27604;&#21313;&#24180;&#21069;&#30340;&#23439;&#22823;&#24895;&#26223;&#65292;&#25105;&#26356;&#21916;&#27426;&#20170;&#22825;&#36825;&#31181;&#25226;&#25215;&#35834;&#19968;&#28857;&#28857;&#21464;&#25104;&#24037;&#31243;&#29616;&#23454;&#30340;&#33410;&#22863;&#12290;</span></p><p><a href="https://fatbobman.com/zh/weekly/issue-140/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong><span>&#21407;&#21019;</span></strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/from-size-class-to-available-space/?utm_source=fatbobman%20weekly%20issue%20141&amp;utm_medium=web"><span>&#20174; Size Class &#21040;&#21487;&#29992;&#31354;&#38388;&#65292;horizontalSizeClass &#36824;&#21487;&#38752;&#21527;&#65311;</span></a></strong></h3><p><span>&#20174; WWDC 26 &#24320;&#22987;&#65292;iPhone &#24212;&#29992;&#22312; iPhone Mirroring &#21040; Mac &#26102;&#65292;&#20854;&#31383;&#21475;&#23610;&#23544;&#23558;&#25903;&#25345;&#33258;&#30001;&#35843;&#25972;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;iPhone-only &#24212;&#29992;&#22312; iPad &#19978;&#36816;&#34892;&#26102;&#65292;&#20063;&#20250;&#36827;&#20837;&#21487;&#21464;&#23610;&#23544;&#29615;&#22659;&#12290;&#36825;&#27425;&#26356;&#26032;&#24102;&#26469;&#30340;&#24433;&#21709;&#36828;&#19981;&#27490;&#8220;iPhone &#24212;&#29992;&#21487;&#20197;&#35843;&#25972;&#23610;&#23544;&#8221;&#36825;&#20040;&#31616;&#21333;&#12290;&#23427;&#27491;&#22312;&#25913;&#21464;&#35768;&#22810;&#24320;&#21457;&#32773;&#38271;&#26399;&#20197;&#26469;&#23545;&#24067;&#23616;&#31995;&#32479;&#30340;&#29702;&#35299;&#12290;&#19968;&#20123;&#36807;&#21435;&#24120;&#34987;&#29992;&#20316;&#24067;&#23616;&#20381;&#25454;&#30340; trait&#65292;&#20363;&#22914; </span><code>horizontalSizeClass</code><span> &#24050;&#19981;&#20877;&#36866;&#21512;&#20316;&#20026;&#31383;&#21475;&#23485;&#24230;&#30340;&#20027;&#35201;&#21028;&#26029;&#20381;&#25454;&#12290;&#37027;&#20040;&#65292;&#36825;&#31181;&#21464;&#21270;&#31350;&#31455;&#26159;&#19968;&#27425;&#31361;&#28982;&#20986;&#29616;&#30340;&#36716;&#21521;&#65292;&#36824;&#26159; Apple &#22810;&#24180;&#24067;&#23616;&#19979;&#30340;&#24517;&#28982;&#28436;&#36827;&#65311;&#26412;&#25991;&#23558;&#23545;&#27492;&#36827;&#34892;&#25506;&#35752;&#12290;</span></p><h2><strong><span>&#36817;&#26399;&#25512;&#33616;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-01"><span>Swift 6.4 &#24182;&#21457;&#26032;&#29305;&#24615; (Swift 6.4: What&#8217;s New in Concurrency)</span></a></strong></h3><p><a href="https://x.com/twannl"><span>Antoine van der Lee</span></a><span> &#22312;&#26412;&#25991;&#20013;&#26803;&#29702;&#20102; Swift 6.4 &#20026;&#24182;&#21457;&#32534;&#31243;&#24102;&#26469;&#30340;&#19968;&#31995;&#21015;&#25913;&#36827;&#65292;&#21253;&#25324;&#25903;&#25345;&#22312; defer &#20013;&#25191;&#34892;&#24322;&#27493;&#28165;&#29702;&#12289;&#36890;&#36807;&#21462;&#28040;&#23631;&#34109;&#30830;&#20445;&#20851;&#38190;&#30340;&#28165;&#29702;&#25110;&#22238;&#28378;&#25805;&#20316;&#24471;&#20197;&#23436;&#25104;&#12289;&#20026;&#34987;&#24573;&#30053;&#30340;&#21487;&#25243;&#38169; Task &#22686;&#21152;&#35686;&#21578;&#65292;&#20197;&#21450;&#20026; Task &#24341;&#20837;&#31867;&#22411;&#21270;&#38169;&#35823;&#25903;&#25345;&#12290;&#27492;&#22806;&#65292;Result &#29616;&#22312;&#21487;&#20197;&#30452;&#25509;&#23553;&#35013;&#24322;&#27493;&#21487;&#25243;&#20986;&#25805;&#20316;&#65292;~Sendable &#21644; Swift 6.3 &#24341;&#20837;&#30340; weak let &#20063;&#35753; Sendable &#31867;&#22411;&#30340;&#34920;&#36798;&#26356;&#21152;&#20934;&#30830;&#12290;</span></p><p><span>&#30456;&#36739;&#20110; Swift 6.2 &#20043;&#21069;&#23545;&#24182;&#21457;&#27169;&#22411;&#36739;&#20026;&#22823;&#20992;&#38420;&#26023;&#30340;&#35843;&#25972;&#65292;&#36825;&#20123;&#21464;&#21270;&#19981;&#20250;&#24102;&#26469;&#22826;&#22810;&#26032;&#30340;&#24515;&#26234;&#36127;&#25285;&#65292;&#26356;&#22810;&#26159;&#22312;&#29616;&#26377;&#27169;&#22411;&#20043;&#19978;&#34917;&#40784;&#32454;&#33410;&#65292;&#35299;&#20915;&#23454;&#38469;&#24037;&#31243;&#20013;&#28165;&#29702;&#12289;&#21462;&#28040;&#12289;&#38169;&#35823;&#22788;&#29702;&#21644;&#31867;&#22411;&#24314;&#27169;&#31561;&#26041;&#38754;&#30340;&#38382;&#39064;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-02"><span>&#25506;&#32034;&#33529;&#26524;&#31995;&#32479;&#20869;&#26680;&#20013;&#30340; Swift (Apple Internals: Swift in the Kernel)</span></a></strong></h3><p><span>Swift &#24050;&#32463;&#35806;&#29983;&#21313;&#20313;&#24180;&#12290;&#20316;&#20026;&#36825;&#38376;&#35821;&#35328;&#30340;&#21019;&#36896;&#32773;&#65292;&#33529;&#26524;&#26159;&#21542;&#24050;&#32463;&#24320;&#22987;&#23558;&#23427;&#29992;&#20110;&#25805;&#20316;&#31995;&#32479;&#20869;&#26680;&#30340;&#24320;&#21457;&#65311;&#26469;&#33258; </span><a href="https://x.com/calif_io"><span>Calif</span></a><span> &#30340; Josh Maine &#36890;&#36807;&#20998;&#26512; macOS 27&#12289;iOS 27 &#30340; kernelcache &#19982; Xcode 27 Beta &#24037;&#20855;&#38142;&#21457;&#29616;&#65292;Apple &#26032;&#22686;&#20102;&#21517;&#20026; KernelKit &#30340;&#20869;&#37096; SDK&#12289;&#23545;&#24212;&#19981;&#21516;&#31995;&#32479;&#30340; Mach-O &#24179;&#21488;&#26631;&#35782;&#65292;&#20197;&#21450;&#19968;&#22871;&#38745;&#24577;&#38142;&#25509;&#22312; macOS &#20869;&#26680;&#25193;&#23637;&#20013;&#30340; Embedded Swift &#36816;&#34892;&#26102;&#12290;</span></p><p><span>&#19981;&#36807;&#65292;&#36825;&#24182;&#19981;&#24847;&#21619;&#30528; XNU &#27491;&#22312;&#34987; Swift &#37325;&#20889;&#12290;&#30446;&#21069;&#65292;Swift &#21482;&#20986;&#29616;&#22312;&#20869;&#26680;&#25193;&#23637;&#23618;&#65307;macOS &#20013;&#30340;&#36816;&#34892;&#26102;&#23578;&#26410;&#34987;&#20854;&#20182;&#32452;&#20214;&#23454;&#38469;&#35843;&#29992;&#65292;&#32780; iOS &#29616;&#38454;&#27573;&#20063;&#21482;&#26159;&#23436;&#25104;&#20102;&#24179;&#21488;&#21644;&#24037;&#20855;&#38142;&#23618;&#38754;&#30340;&#20934;&#22791;&#12290;&#25972;&#22871;&#22522;&#30784;&#35774;&#26045;&#26356;&#20687;&#26159; Apple &#22312;&#27491;&#24335;&#24341;&#20837; Swift &#20869;&#26680;&#32452;&#20214;&#20043;&#21069;&#65292;&#20808;&#34892;&#38138;&#35774;&#24037;&#20855;&#38142;&#12289;&#36816;&#34892;&#26102;&#19982;&#38142;&#25509;&#29615;&#22659;&#12290;&#26080;&#35770;&#22914;&#20309;&#65292;&#36825;&#24847;&#21619;&#30528;&#36317;&#31163;&#30495;&#27491;&#20351;&#29992; Swift &#32534;&#20889;&#20869;&#26680;&#32452;&#20214;&#21448;&#36817;&#20102;&#19968;&#27493;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-03"><span>&#20174;&#35302;&#25720;&#21040;&#20687;&#32032;&#65306;iOS &#28210;&#26579;&#31649;&#32447;&#24213;&#23618;&#25506;&#31192; (Touch to Pixels: UI Pipeline Internals on iOS)</span></a></strong></h3><p><span>&#24403;&#25163;&#25351;&#28857;&#20987; iOS &#30028;&#38754;&#21518;&#65292;&#21040;&#23631;&#24149;&#19978;&#30340;&#20687;&#32032;&#21457;&#29983;&#21464;&#21270;&#20043;&#21069;&#65292;&#31995;&#32479;&#20869;&#37096;&#31350;&#31455;&#32463;&#21382;&#20102;&#20160;&#20040;&#65311;</span><a href="https://x.com/jacobtechtavern"><span>Jacob Bartlett</span></a><span>&#8288; &#20174;&#19968;&#27425;&#35302;&#25720;&#20107;&#20214;&#20986;&#21457;&#65292;&#27839;&#30528;&#35302;&#25720;&#23631;&#30828;&#20214;&#12289;XNU&#12289;IOKit&#12289;backboardd&#12289;&#24212;&#29992; Run Loop&#12289;UIKit &#19982; Core Animation&#65292;&#19968;&#36335;&#36861;&#36394;&#20107;&#20214;&#22914;&#20309;&#25269;&#36798;&#25105;&#20204;&#30340;&#20195;&#30721;&#65292;&#20197;&#21450;&#30028;&#38754;&#26356;&#26032;&#22914;&#20309;&#32463;&#36807; Render Server&#12289;GPU &#21644;&#24103;&#32531;&#20914;&#21306;&#65292;&#26368;&#32456;&#36716;&#21270;&#20026;&#23631;&#24149;&#19978;&#30340;&#20687;&#32032;&#12290;&#20102;&#35299;&#36825;&#26465;&#20174; Touch &#21040; Pixels &#30340;&#23436;&#25972;&#38142;&#36335;&#65292;&#19981;&#20165;&#33021;&#24110;&#21161;&#25105;&#20204;&#24314;&#31435;&#23545; iOS UI &#31995;&#32479;&#30340;&#25972;&#20307;&#35748;&#35782;&#65292;&#20063;&#26377;&#21161;&#20110;&#20998;&#26512;&#20027;&#32447;&#31243;&#38459;&#22622;&#12289;&#21160;&#30011;&#21345;&#39039;&#21644;&#25481;&#24103;&#31561;&#24120;&#35265;&#30340;&#30028;&#38754;&#24615;&#33021;&#38382;&#39064;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-04"><span>SwiftUI &#21160;&#24577;&#25991;&#26412;&#28210;&#26579; (Dynamic Text in SwiftUI)</span></a></strong></h3><p><span>&#35774;&#24819;&#19968;&#20010;&#22330;&#26223;&#65306;&#24212;&#29992;&#37324;&#26377;&#19968;&#20010;&#20840;&#23616;&#24320;&#20851;&#65292;&#20915;&#23450;&#25152;&#26377;&#30028;&#38754;&#26174;&#31034;&#29992;&#25143;&#30340;&#20840;&#21517;&#36824;&#26159;&#26165;&#31216;&#12290;&#26368;&#30452;&#25509;&#30340;&#20570;&#27861;&#65292;&#26159;&#22312;&#27599;&#19968;&#22788;&#26174;&#31034;&#29992;&#25143;&#21517;&#30340;&#22320;&#26041;&#37117;&#21152;&#19978;&#21028;&#26029;&#65292;&#20294;&#21482;&#35201;&#26377;&#19968;&#20010;&#26032;&#21151;&#33021;&#24536;&#35760;&#22788;&#29702;&#65292;&#36825;&#20010;&#24320;&#20851;&#23601;&#20250;&#22833;&#25928;&#12290;</span><a href="https://mastodon.social/@DLX"><span>Robb B&#246;hnke</span></a><span> &#30340;&#35299;&#27861;&#26159;&#20511;&#29992; BCP 47 &#30340;&#31169;&#26377;&#23376;&#26631;&#31614;&#65292;&#23558;&#36825;&#39033;&#20559;&#22909;&#32534;&#30721;&#36827; </span><code>Locale</code><span>&#65292;&#20877;&#36890;&#36807;&#33258;&#23450;&#20041; </span><code>FormatStyle</code><span>&#65292;&#22312; </span><code>Text</code><span> &#30495;&#27491;&#28210;&#26579;&#26102;&#35835;&#21462;&#24182;&#36873;&#25321;&#23545;&#24212;&#30340;&#21517;&#31216;&#12290;&#36825;&#31181;&#20570;&#27861;&#32469;&#36807;&#20102; SwiftUI &#32570;&#23569;&#21160;&#24577; </span><code>Text</code><span> &#21021;&#22987;&#21270; API &#30340;&#38480;&#21046;&#65292;&#20063;&#25226;&#23481;&#26131;&#36951;&#28431;&#30340;&#35843;&#29992;&#31471;&#36923;&#36753;&#21464;&#25104;&#20102;&#24212;&#29992;&#33539;&#22260;&#20869;&#30340;&#40664;&#35748;&#34892;&#20026;&#12290;</span></p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-05"><span>SwiftUI SensoryFeedback Cache Key &#32463;&#39564;&#25945;&#35757;&#65306;&#19981;&#35201;&#23384;&#20648;&#36830;&#32493;&#20540;</span></a></strong></h3><p><span>&#22312; SwiftUI &#20013;&#29992; Slider &#21160;&#24577;&#35843;&#25972;&#35302;&#35273;&#21453;&#39304;&#24378;&#24230;&#65292;&#31455;&#28982;&#21487;&#33021;&#23548;&#33268;&#20869;&#23384;&#24555;&#36895;&#22686;&#38271;&#65311;&#21548;&#36215;&#26469;&#19981;&#21487;&#24605;&#35758;&#65292;&#20294;&#36825;&#20010;&#38382;&#39064;&#30830;&#23454;&#23384;&#22312;&#20110; iOS 17 &#33267; iOS 26 &#20013;&#12290;</span><a href="https://x.com/KyleSwifter"><span>Kyle Ye</span></a><span> &#21457;&#29616;&#65292;&#36825;&#20123;&#29256;&#26412;&#30340;&#20869;&#37096;&#23454;&#29616;&#23558; </span><code>intensity</code><span> &#36825;&#26679;&#30340;&#36830;&#32493;&#20540;&#32435;&#20837;&#20102;&#21453;&#39304;&#29983;&#25104;&#22120;&#30340;&#32531;&#23384;&#38190;&#12290;&#24378;&#24230;&#20540;&#30340;&#27599;&#19968;&#27425;&#32454;&#24494;&#21464;&#21270;&#65292;&#37117;&#21487;&#33021;&#23545;&#24212;&#19968;&#20010;&#26032;&#30340; </span><code>UIImpactFeedbackGenerator</code><span> &#23454;&#20363;&#65292;&#26368;&#32456;&#23548;&#33268;&#32531;&#23384;&#19981;&#26029;&#33192;&#32960;&#12290;</span></p><p><span>Kyle &#22312;&#21435;&#24180;&#24180;&#24213;&#25552;&#20132;&#20102; FB&#65292;&#24182;&#20110;&#20170;&#24180; 6 &#26376;&#25910;&#21040;&#38382;&#39064;&#24050;&#20462;&#22797;&#30340;&#36890;&#30693;&#12290;iOS 27 &#30340;&#35299;&#20915;&#26041;&#26696;&#24182;&#19981;&#26159;&#22686;&#21152;&#19968;&#20010;&#32531;&#23384;&#19987;&#29992; Key &#26469;&#25171;&#34917;&#19969;&#65292;&#32780;&#26159;&#37325;&#26032;&#21010;&#20998;&#27169;&#22411;&#36793;&#30028;&#65306;&#23558;&#20195;&#34920;&#8220;&#31283;&#23450;&#36523;&#20221;&#8221;&#30340; </span><code>FeedbackType</code><span>&#65292;&#19982;&#27599;&#27425;&#25773;&#25918;&#20351;&#29992;&#30340;&#21160;&#24577;&#21442;&#25968; </span><code>Payload</code><span> &#24443;&#24213;&#25286;&#24320;&#12290;&#20844;&#24320; API &#20445;&#25345;&#19981;&#21464;&#65292;&#32531;&#23384;&#36923;&#36753;&#21364;&#20174;&#25968;&#25454;&#27169;&#22411;&#23618;&#38754;&#24471;&#21040;&#20102;&#20462;&#27491;&#12290;</span></p><blockquote><p><span>&#36825;&#27425;&#20462;&#22797;&#20540;&#24471;&#20851;&#27880;&#30340;&#22320;&#26041;&#65292;&#19981;&#21482;&#26159;&#35299;&#20915;&#20102;&#20869;&#23384;&#22686;&#38271;&#38382;&#39064;&#65292;&#26356;&#20307;&#29616;&#20102; API &#35774;&#35745;&#20013;&#30340;&#19968;&#20010;&#37325;&#35201;&#21407;&#21017;&#65306;&#25551;&#36848;&#8220;&#23545;&#35937;&#36523;&#20221;&#8221;&#30340;&#31283;&#23450;&#20449;&#24687;&#65292;&#19981;&#24212;&#19982;&#21482;&#24433;&#21709;&#21333;&#27425;&#25805;&#20316;&#30340;&#21160;&#24577;&#21442;&#25968;&#28151;&#22312;&#19968;&#36215;&#12290;&#23427;&#20063;&#25552;&#37266;&#25105;&#20204;&#65292;&#19968;&#20010;&#31867;&#22411;&#21363;&#20351;&#28385;&#36275; </span><code>Hashable</code><span>&#65292;&#20063;&#19981;&#20195;&#34920;&#23427;&#22825;&#28982;&#36866;&#21512;&#20316;&#20026;&#32531;&#23384;&#38190;&#12290;&#30456;&#27604;&#22312;&#20351;&#29992;&#22788;&#19981;&#26029;&#25490;&#38500;&#29305;&#27530;&#23383;&#27573;&#65292;&#20174;&#25968;&#25454;&#27169;&#22411;&#23618;&#38754;&#21010;&#28165;&#35821;&#20041;&#36793;&#30028;&#65292;&#36890;&#24120;&#26159;&#26356;&#21487;&#38752;&#30340;&#35774;&#35745;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-06"><span>Swift &#26500;&#24314;&#25991;&#26723;&#36716;&#25442;&#24341;&#25806;&#30340;&#26550;&#26500;&#35774;&#35745; (Architecting a Conversion Engine in Swift)</span></a></strong></h3><p><span>&#24403;&#24212;&#29992;&#38656;&#35201;&#22312; Markdown&#12289;HTML&#12289;&#23500;&#25991;&#26412;&#12289;PDF &#31561;&#22810;&#31181;&#26684;&#24335;&#20043;&#38388;&#20114;&#30456;&#36716;&#25442;&#26102;&#65292;&#22914;&#20309;&#36991;&#20813;&#36716;&#25442;&#36923;&#36753;&#38543;&#30528;&#26684;&#24335;&#25968;&#37327;&#21576;&#24179;&#26041;&#32423;&#22686;&#38271;&#65311;</span><a href="https://bsky.app/profile/arthurvansiclen.com"><span>Arthur Van Siclen</span></a><span>&#8288; &#20171;&#32461;&#20102;&#20182;&#22312; Minimal &#20013;&#30340;&#35299;&#20915;&#26041;&#26696;&#65306;&#35774;&#35745;&#19968;&#22871;&#20013;&#38388;&#34920;&#31034; IR&#65292;&#35753;&#27599;&#31181;&#26684;&#24335;&#21482;&#38656;&#20998;&#21035;&#23454;&#29616; Parser &#21644; Renderer&#65292;&#20174;&#32780;&#23558;&#20845;&#31181;&#26684;&#24335;&#20043;&#38388;&#30340; 30 &#26465;&#36716;&#25442;&#20851;&#31995;&#20943;&#23569;&#20026; 12 &#26465;&#12290;</span></p><p><span>&#20854;&#20013;&#65292;&#23545;&#8220;&#26377;&#25439;&#36716;&#25442;&#8221;&#30340;&#22788;&#29702;&#23588;&#20854;&#20540;&#24471;&#20511;&#37492;&#12290;&#19981;&#21516;&#26684;&#24335;&#30340;&#34920;&#36798;&#33021;&#21147;&#24182;&#19981;&#23545;&#31561;&#65292;Minimal &#36890;&#36807; </span><code>Concession</code><span> &#26174;&#24335;&#35760;&#24405;&#36716;&#25442;&#36807;&#31243;&#20013;&#21457;&#29983;&#30340;&#26684;&#24335;&#38477;&#32423;&#12289;&#20869;&#23481;&#20002;&#24323;&#25110;&#25130;&#26029;&#65292;&#32780;&#19981;&#26159;&#20551;&#35774;&#25152;&#26377;&#26684;&#24335;&#20043;&#38388;&#37117;&#33021;&#26080;&#25439;&#36716;&#25442;&#12290;</span></p><h2><strong><span>&#24037;&#20855;</span></strong></h2><h3><strong><a href="https://l.fatbobman.com/w0141-07"><span>SwiftOS&#65306;&#29992; Embedded Swift &#20889;&#19968;&#20010;&#30495;&#27491;&#30340;&#25805;&#20316;&#31995;&#32479;</span></a></strong></h3><p><span>SwiftOS &#26159;&#19968;&#20010;&#20960;&#20046;&#23436;&#20840;&#20351;&#29992; Embedded Swift &#20174;&#38646;&#32534;&#20889;&#30340; 64 &#20301; ARM &#25805;&#20316;&#31995;&#32479;&#12290;&#20316;&#32773; </span><a href="https://www.linkedin.com/in/andrey-sapunov/"><span>Andrey Sapunov</span></a><span>&#8288; &#30340;&#20986;&#21457;&#28857;&#24456;&#26420;&#32032;&#65306;&#19982;&#20854;&#21482;&#20174;&#20070;&#26412;&#19978;&#29702;&#35299;&#25805;&#20316;&#31995;&#32479;&#65292;&#19981;&#22914;&#20146;&#25163;&#23454;&#29616;&#19968;&#20010;&#65292;&#30495;&#27491;&#24324;&#28165;&#20869;&#26680;&#12289;&#20869;&#23384;&#12289;&#36827;&#31243;&#19982;&#35774;&#22791;&#22914;&#20309;&#21327;&#20316;&#12290;&#36873;&#25321; Swift &#20063;&#19981;&#21482;&#26159;&#20986;&#20110;&#35821;&#35328;&#20559;&#22909;&#65292;&#32780;&#26159;&#24076;&#26395;&#22312;&#20445;&#25345;&#20195;&#30721;&#29983;&#25104;&#21487;&#39044;&#27979;&#21644;&#24213;&#23618;&#25511;&#21046;&#33021;&#21147;&#30340;&#21516;&#26102;&#65292;&#20511;&#21161; Swift &#30340;&#31867;&#22411;&#31995;&#32479;&#12289;&#25152;&#26377;&#26435;&#27169;&#22411;&#21644;&#29616;&#20195;&#24037;&#31243;&#24037;&#20855;&#65292;&#35753;&#31995;&#32479;&#20195;&#30721;&#26356;&#23433;&#20840;&#12289;&#26356;&#23481;&#26131;&#34920;&#36798;&#12290;</span></p><p><span>SwiftOS &#36873;&#25321;&#20102;&#19968;&#26465;&#39047;&#20026;&#29616;&#20195;&#30340;&#31995;&#32479;&#36335;&#32447;&#65306;AArch64&#12289;&#22522;&#20110; MMU &#30340;&#36827;&#31243;&#22320;&#22336;&#31354;&#38388;&#38548;&#31163;&#12289;&#33258;&#23450;&#20041; syscall ABI&#12289;&#33021;&#21147;&#23548;&#21521;&#30340;&#25480;&#26435;&#27169;&#22411;&#12289;&#38745;&#24577;&#38142;&#25509;&#12289;&#31614;&#21517;&#21482;&#35835;&#22522;&#30784;&#38236;&#20687;&#65292;&#20197;&#21450;&#21407;&#29983; Swift userland&#12290;&#23427;&#24050;&#32463;&#23454;&#29616;&#20102;&#20869;&#26680;&#24577; TCP/IP &#26632;&#65292;&#33021;&#22815;&#36816;&#34892; nginx &#21644; Node.js&#65292;&#24182;&#36816;&#34892;&#22312;&#30495;&#23454;&#30340; Hetzner Cloud ARM &#23454;&#20363;&#19978;&#8212;&#8212;&#39033;&#30446;&#23448;&#32593;&#23601;&#26159;&#30001; SwiftOS &#33258;&#24049;&#25176;&#31649;&#30340;&#12290;</span></p><blockquote><p><span>&#25110;&#35768;&#65292;&#25105;&#20204;&#36824;&#38656;&#35201;&#26356;&#22810;&#26102;&#38388;&#65292;&#25165;&#33021;&#30475;&#21040; Swift &#34987;&#22823;&#35268;&#27169;&#29992;&#20110;&#33529;&#26524;&#30340;&#31995;&#32479;&#20869;&#26680;&#12290;&#20294; SwiftOS &#33267;&#23569;&#35777;&#26126;&#20102;&#19968;&#20214;&#20107;&#65306;Embedded Swift &#24050;&#32463;&#19981;&#21482;&#33021;&#22815;&#32534;&#20889;&#22266;&#20214;&#21644;&#35064;&#26426;&#31034;&#20363;&#65292;&#23427;&#20063;&#36275;&#20197;&#25903;&#25745;&#19968;&#20010;&#25317;&#26377;&#36827;&#31243;&#38548;&#31163;&#12289;&#29992;&#25143;&#24577;&#31243;&#24207;&#12289;&#32593;&#32476;&#26632;&#21644;&#30495;&#23454;&#26381;&#21153;&#36127;&#36733;&#30340;&#25805;&#20316;&#31995;&#32479;&#12290;</span></p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0141-08"><span>Loupe&#65306;&#20026; AI Agent &#34917;&#19978; Apple &#21407;&#29983; UI &#30340;&#36816;&#34892;&#26102;&#35777;&#25454;</span></a></strong></h3><p><span>Loupe &#26159;&#30001; </span><a href="https://www.linkedin.com/in/won-heo-5a0497135/"><span>Won Heo</span></a><span>&#8288; &#21457;&#36215;&#30340; Apple &#24179;&#21488;&#36816;&#34892;&#26102;&#35786;&#26029;&#19982; E2E &#39564;&#35777;&#24037;&#20855;&#65292;&#23588;&#20854;&#36866;&#21512; Codex&#12289;Claude Code &#36825;&#31867; AI Coding Agent &#21442;&#19982;&#21407;&#29983;&#30028;&#38754;&#24320;&#21457;&#26102;&#20351;&#29992;&#12290;&#23427;&#24182;&#19981;&#26367;&#20195; xcodebuild&#12289;XCTest &#25110;&#20854;&#20182;&#36127;&#36131;&#26500;&#24314;&#21644;&#27979;&#35797;&#30340;&#24037;&#20855;&#65292;&#32780;&#26159;&#36890;&#36807;&#21521;&#35843;&#35797;&#20013;&#30340; App &#27880;&#20837;&#25110;&#38142;&#25509;&#36816;&#34892;&#26102;&#65292;&#34917;&#19978;&#20854;&#21518;&#30340; UI &#35777;&#25454;&#23618;&#65306;&#20174;&#30495;&#27491;&#36816;&#34892;&#30340; App &#20013;&#37319;&#38598; UIKit/AppKit &#35270;&#22270;&#32467;&#26500;&#12289;&#21487;&#35775;&#38382;&#24615;&#20449;&#24687;&#12289;&#25130;&#22270;&#12289;&#26085;&#24535;&#12289;URLSession &#32593;&#32476;&#27963;&#21160;&#65292;&#20197;&#21450; Defaults&#12289;Feature Flags &#31561;&#29366;&#24577;&#65292;&#20877;&#36890;&#36807; CLI &#25552;&#20379;&#26597;&#35810;&#19982;&#23457;&#35745;&#33021;&#21147;</span></p><p><span>Agent &#21487;&#20197;&#20808;&#33719;&#21462;&#32039;&#20945;&#30340; UI &#35266;&#23519;&#32467;&#26524;&#65292;&#20877;&#25353;&#38656;&#28145;&#20837;&#26816;&#26597;&#20855;&#20307;&#33410;&#28857;&#65292;&#25191;&#34892; tap&#12289;swipe&#12289;drag&#12289;type &#31561;&#27169;&#25311;&#22120;&#21487;&#35265;&#25805;&#20316;&#65292;&#24182;&#35760;&#24405;&#25805;&#20316;&#21069;&#21518;&#30340;&#24555;&#29031;&#12289;&#24046;&#24322;&#19982; trace&#65307;&#23427;&#36824;&#21487;&#20197;&#23545;&#37096;&#20998; UIKit &#23646;&#24615;&#21644;&#32422;&#26463;&#36827;&#34892;&#36816;&#34892;&#26102;&#25506;&#38024;&#24335;&#20462;&#25913;&#65292;&#24555;&#36895;&#39564;&#35777;&#35843;&#25972;&#26159;&#21542;&#26377;&#25928;&#65292;&#20877;&#22238;&#21040;&#28304;&#30721;&#23436;&#25104;&#30495;&#27491;&#30340;&#20462;&#27491;&#12290;&#36825;&#35753;&#8220;&#30475;&#36215;&#26469;&#23545;&#19981;&#23545;&#12289;&#28857;&#36215;&#26469;&#36890;&#19981;&#36890;&#12289;&#24067;&#23616;&#26377;&#27809;&#26377;&#28418;&#31227;&#8221;&#19981;&#20877;&#21482;&#20381;&#36182;&#25130;&#22270;&#19982;&#29468;&#27979;&#65292;&#32780;&#26159;&#25104;&#20026;&#19968;&#26465;&#33021;&#22815;&#22797;&#26597;&#21644;&#30041;&#30165;&#30340;&#35777;&#25454;&#38142;&#12290;</span></p>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #140]]></title><description><![CDATA[WWDC 26: AI Watched It for You &#8212; Now What?]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 15 Jun 2026 12:03:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XG78!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XG78!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XG78!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!XG78!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:87014,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/202066210?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XG78!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 424w, https://substackcdn.com/image/fetch/$s_!XG78!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 848w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1272w, https://substackcdn.com/image/fetch/$s_!XG78!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238159c7-c0e2-4de6-83d4-e9df3f48d8ac_1400x788.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@zachmmalin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Zach M</a> on <a href="https://unsplash.com/photos/artificial-intelligence-concept-within-a-human-head-7F9PhBM1gFM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>WWDC 26: AI Watched It for You &#8212; Now What?</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-140/">Read on web &#8594;</a></p><p>With the rise of AI Agent workflows, many developers this year have started letting AI handle the summarizing and highlight-picking, absorbing WWDC announcements at a much faster pace. Apple has been accommodating too &#8212; releasing all Sessions, transcripts, and sample code at once, making it even easier for AI to process everything.</p><p>For me personally, what used to be a manual ritual of extracting <code>interface</code> files and comparing old and new APIs has become a single instruction in an Agent workflow. From a pure efficiency standpoint, that&#8217;s a real, tangible gain.</p><p>But information distilled at speed can&#8217;t always capture the nuance and precision that Apple engineers embed in a Session. Many Sessions are still worth sitting down with &#8212; carefully, even repeatedly.</p><p>AI accelerates how fast you acquire information. It doesn&#8217;t deepen how well you understand it. Information flowing into an AI&#8217;s context window is not the same as knowledge taking root in your own mind.</p><p>Your viewing habits can evolve with the times. Your standards for yourself shouldn&#8217;t.</p><p><a href="https://fatbobman.com/en/weekly/issue-139/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>WWDC 2026</strong></h2><h3><strong>Roundups</strong></h3><ul><li><p><strong>WWDC 26 Group Lab Q&amp;A</strong> by <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a></p><p>At this year&#8217;s Group Labs, Apple engineers answered questions from developers live on stage. Anton has compiled summaries from the <a href="https://antongubarenko.substack.com/p/wwdc26-swift-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-for-beginners-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI for Beginners</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI Advanced</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-power-and-performance-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Performance</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-visionos-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">VisionOS</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-coding-intelligence-machine?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">AI</a>, <a href="https://antongubarenko.substack.com/p/wwdc26-icon-composer-for-beginners?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Icon Composer</a>, and <a href="https://antongubarenko.substack.com/p/wwdc26-camera-and-photo-technologies?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Camera and Photo</a> Labs.</p></li><li><p><a href="https://www.massicotte.org/blog/wwdc26-unanswered-qa/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">(Some) Unanswered Swift Group Questions</a> by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a></p><p>Time limits and voting mechanics meant not every question at the Swift Group Lab got answered. Matt picked out a selection of those that didn&#8217;t make it and offered his own take &#8212; covering Swift 6 migration, Approachable Concurrency, default MainActor isolation, <code>@preconcurrency</code>, Sendable / ~Sendable, and unstructured tasks.</p></li><li><p><a href="https://onmyway133.com/posts/whats-new-in-swift-6.4-at-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s new in Swift 6.4 at WWDC26</a> by <a href="https://x.com/onmyway133">Khoa Pham</a></p><p>A walkthrough of the Swift 6.4 changes that make code more concise and expressive.</p></li><li><p><a href="https://wadetregaskis.com/whats-coming-in-swift-6-4/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s Coming in Swift 6.4</a> by <a href="https://mastodon.social/@everything@wadetregaskis.com">Wade Tregaskis</a></p><p>Wade rounds up the Swift Evolution proposals marked as implemented in Swift 6.4, spanning concurrency, ownership, the standard library, accessors, package management, and compiler diagnostics.</p></li><li><p><a href="https://azamsharp.com/2026/06/12/whats-new-in-swiftdata.html?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s New in SwiftData for iOS 27</a> by <a href="https://x.com/azamsharp">Mohammad Azam</a></p><p>SwiftData may not have received a headline-grabbing overhaul this year, but the new enum predicates, sectioned queries, composite predicates, <code>.codable</code> attribute, and <code>ResultsObserver</code> all address real pain points and meaningfully round out the developer experience.</p></li><li><p><a href="https://swiftwithmajid.com/2026/06/08/what-is-new-in-swiftui-after-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What is new in SwiftUI after WWDC26</a> by <a href="https://x.com/mecid">Majid Jabrayilov</a></p><p>Majid surveys the SwiftUI additions from WWDC26 &#8212; many of them long-requested by the community. The one disappointment: with the exception of <code>@State</code>, most new APIs don&#8217;t offer backward compatibility.</p></li><li><p><a href="https://www.swiftjectivec.com/ios-27-notable-uikit-additions/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS 27: Notable UIKit Additions</a> by <a href="https://x.com/jordanmorgan10">Jordan Morgan</a></p><p>SwiftUI keeps moving forward, but Apple hasn&#8217;t let up on UIKit either. This year&#8217;s UIKit API updates focus mainly on adapting to new system capabilities and aligning with what&#8217;s new in SwiftUI.</p></li></ul><h3><strong>Documentation</strong></h3><ul><li><p><a href="https://wwdc.ai/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC.ai</a> by <a href="https://x.com/Superwall">Superwall</a></p><p>A site designed to help developers and AI agents quickly get up to speed on Apple&#8217;s developer updates. It offers Session summaries, an Ask AI interface, and a <a href="https://github.com/superwall/skills">Skill</a> for direct use in code assistants.</p></li><li><p><a href="https://github.com/0Itsuki0/iOS-MacOS_AppleBetaDocRetriever?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS/MacOS: Apple Beta Doc Retriever</a> by <a href="https://x.com/itsuki68391179">Itsuki</a></p><p>An open-source iOS/macOS app that lets developers browse Beta-tagged documentation and APIs, making it easy to spot what&#8217;s changed between OS versions.</p></li><li><p><a href="https://wwdc-quick-look.swiftgg.team/articles/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC Quick Look</a> by <a href="https://swift.swiftgg.team/">SwiftGG</a></p><p>A comprehensive archive of every Session from WWDC 2020 to today, with linked Sessions, video timestamps, and key code snippets. Also ships a <a href="https://github.com/SwiftGGTeam/wwdc-quick-look">Skill</a> for use with AI tools.</p></li><li><p><a href="https://askwwdc.com/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Ask WWDC</a> by <a href="https://x.com/matthew_spear">Matt Spear</a></p><p>A natural-language Q&amp;A search tool for WWDC content. Ask a question, get a concise answer along with the relevant Sessions.</p></li></ul><h3><strong>New Features</strong></h3><ul><li><p><a href="https://livsycode.com/swiftui/swiftuis-state-is-now-a-macro/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s @State is now a macro</a> by <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a></p><p><code>@State</code> was originally designed with value types in mind. Once the Observation framework arrived in iOS 17, a gap became apparent: <code>@State</code> lacked the lazy initialization behavior that <code>@StateObject</code> provided for reference types. WWDC26 finally closes that gap. What&#8217;s particularly worth noting is that Apple didn&#8217;t touch the property wrapper implementation &#8212; instead, they introduced a same-named macro to handle the change. This approach may offer a useful blueprint for managing future compatibility challenges.</p></li><li><p><a href="https://swiftuisnippets.wordpress.com/2026/06/10/wwdc26-the-evolution-of-presentation-transitions-in-swiftui/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC26: The Evolution of Presentation Transitions in SwiftUI</a> by <a href="https://x.com/Codelaby">codelaby</a></p><p>SwiftUI gains a <code>crossFade</code> transition for <code>sheet</code> and <code>fullScreenCover</code> in WWDC26. The downside: custom presentation transitions are still not on the table.</p></li><li><p><a href="https://nilcoalescing.com/blog/CustomScrollLayoutsWithSwipeActionsInSwiftUIOnIOS27/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Custom scroll layouts with swipe actions in SwiftUI on iOS 27</a> by <a href="https://x.com/natpanferova">Natalia Panferova</a></p><p>Starting in iOS 27, <code>swipeActions</code> is no longer exclusive to <code>List</code>. The new <code>swipeActionsContainer()</code> modifier brings swipe action support to <code>LazyVStack</code>, <code>LazyVGrid</code>, and custom <code>Layout</code> types inside a <code>ScrollView</code>. The new <code>onPresentationChanged</code> callback also fires when a row&#8217;s swipe actions expand or collapse &#8212; handy for tracking the active item, syncing state, or triggering additional logic.</p></li><li><p><a href="https://artemnovichkov.com/blog/using-claude-with-apple-foundation-models?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Claude with Apple Foundation Models</a> by <a href="https://x.com/iosartem">Artem Novichkov</a></p><p>WWDC26 brings a significant expansion to the Foundation Models framework: beyond Apple&#8217;s on-device model, <code>LanguageModelSession</code> can now connect to server-side models conforming to the <code>LanguageModel</code> protocol. This article demonstrates how to integrate Claude via Anthropic&#8217;s <code>ClaudeForFoundationModels</code> package.</p></li><li><p><a href="https://www.sagarunagar.com/blog/swiftui-prominent-tab-is-not-a-floating-action-button/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s New .prominent Tab in iOS 27 Is Not a Floating Action Button</a> by <a href="https://x.com/sagarunagar_">Sagar Unagar</a></p><p>iOS 27 introduces <code>Tab(role: .prominent)</code>, which gives a tab stronger visual emphasis in the system tab bar. Sagar&#8217;s reminder: this is meant to highlight the most important navigation destination in your app &#8212; not to replace a Floating Action Button, a navigation bar &#8220;+&#8221; button, or an action that opens a sheet.</p></li></ul><h3><strong>Issues &amp; Solutions</strong></h3><ul><li><p><a href="https://www.donnywals.com/installing-simulator-runtimes-from-the-command-line/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Installing simulator runtimes from the command line</a> by <a href="https://x.com/donnywals">Donny Wals</a></p><p>If you&#8217;ve installed Xcode 27 and the iOS Simulator Runtime won&#8217;t download through the Xcode UI, <code>xcodebuild</code> from the command line is your workaround.</p></li><li><p><a href="https://www.avanderlee.com/ai-development/using-xcode-27s-agent-skills-in-claude-codex-and-cursor/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Xcode 27&#8217;s Agent Skills in Claude, Codex, and Cursor</a> by <a href="https://x.com/twannl">Antoine v.d. SwiftLee</a></p><p>Xcode 27 ships with a set of official Apple-provided Agent Skills covering SwiftUI, UIKit, testing, and more. They can also be exported for use in Claude, Codex, Cursor, and other tools.</p></li></ul><h2><strong>Recent Recommendations</strong></h2><ul><li><p><a href="https://www.swift.org/blog/migrating-truetype-hinting-to-swift/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift at Apple: Migrating the TrueType Hinting Interpreter</a> by <a href="https://mastodon.social/@numist@xoxo.zone">Scott Perry</a></p><p>Apple&#8217;s team shares their experience rewriting the TrueType hinting interpreter from C to memory-safe Swift: the new implementation is pixel-identical to the original while running 13% faster on average. The article goes deep on noncopyable types, Span, and projection types as tools for system-level performance work.</p></li></ul><blockquote><p>The TrueType hinting interpreter is the bytecode engine embedded in TrueType fonts. It reads hinting instructions and adjusts glyph control points accordingly, helping text render more crisply at specific sizes and on lower-resolution pixel grids.</p></blockquote><ul><li><p><a href="https://deliveryhero.jobs/blog/scaling-ios-application-development-with-tuist/?utm_medium=LinkedIn&amp;utm_source=Employee_Advocacy_Program?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Scaling iOS application development with Tuist</a> by <a href="https://www.linkedin.com/in/mikeamike/">Michael Gerasymenko</a> and <a href="https://www.linkedin.com/in/dubeyashu/">Ashutosh Dubey</a></p><p>The Delivery Hero Logistics team shares how they used Tuist to scale a large iOS codebase &#8212; keeping their Xcode and Swift Package Manager workflow intact while adding Swift-defined project structure, explicit dependency graphs, binary caching, and selective testing. The result: local clean build time dropped from 2.5 minutes to 0.5 minutes, with CI builds and unit test runs cut by 2.5x.</p></li></ul><blockquote><p>The real point of the article isn&#8217;t &#8220;Tuist makes builds faster.&#8221; It&#8217;s about how Tuist helps teams make large iOS projects more maintainable.</p></blockquote><ul><li><p><a href="https://alejandromp.com/development/blog/keeping-up-with-swift-forums-using-codex?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Keeping Up With Swift Forums Using Codex</a> by <a href="https://x.com/alexito4">Alejandro Martinez</a></p><p>Alejandro walks through building a personal workflow that automatically tracks Swift Forums activity every day using Codex Automations and a Swift CLI: the CLI handles forum data and state sync, while Codex takes care of understanding context, generating summaries, and driving further exploration. A practical example of &#8220;AI-driven, programs as tools&#8221; automation design.</p></li><li><p><a href="https://github.com/apple/container?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Container 1.0</a></p><p>Apple officially released Container 1.0 a few days ago. As an OCI container solution built for Apple silicon, it offers stronger isolation, faster startup, and a more native macOS experience compared to Docker. That said, the ecosystem is still young, and tooling continues to mature.</p></li></ul><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-140?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>WWDC 26&#65306;AI &#24110;&#20320;&#30475;&#23436;&#20102;&#65292;&#28982;&#21518;&#21602;&#65311;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-140/">&#32593;&#39029;&#29256;</a></strong></p><p>&#38543;&#30528; AI Agent &#24037;&#20316;&#27969;&#30340;&#26222;&#21450;&#65292;&#20170;&#24180;&#19981;&#23569;&#24320;&#21457;&#32773;&#24320;&#22987;&#35753; AI &#20195;&#21171;&#27719;&#24635;&#12289;&#31579;&#36873;&#37325;&#28857;&#65292;&#20197;&#26356;&#24555;&#30340;&#33410;&#22863;&#28040;&#21270; WWDC &#19978;&#25512;&#20986;&#30340;&#26032;&#33021;&#21147;&#12290;&#33529;&#26524;&#20063;&#24456;&#37197;&#21512;&#8212;&#8212;&#19968;&#27425;&#24615;&#25918;&#20986;&#20840;&#37096; Session&#12289;&#25991;&#23383;&#31295;&#19982;&#31034;&#20363;&#20195;&#30721;&#65292;&#36827;&#19968;&#27493;&#38477;&#20302;&#20102; AI &#22788;&#29702;&#36825;&#20123;&#20869;&#23481;&#30340;&#38376;&#27099;&#12290;</p><p>&#23545;&#25105;&#20010;&#20154;&#32780;&#35328;&#65292;&#24448;&#24180;&#25163;&#21160;&#25552;&#21462; <code>interface</code> &#12289;&#36880;&#19968;&#27604;&#23545;&#26032;&#26087; API &#30340;&#25805;&#20316;&#65292;&#22914;&#20170;&#24050;&#21464;&#25104; Agent &#24037;&#20316;&#27969;&#37324;&#30340;&#19968;&#26465;&#25351;&#20196;&#12290;&#20174;&#25928;&#29575;&#35282;&#24230;&#26469;&#35828;&#65292;&#36825;&#26159;&#23454;&#23454;&#22312;&#22312;&#30340;&#36827;&#27493;&#12290;</p><p>&#20294;&#24555;&#36895;&#25552;&#28860;&#20986;&#30340;&#20449;&#24687;&#65292;&#24448;&#24448;&#26080;&#27861;&#31934;&#20934;&#12289;&#23436;&#25972;&#22320;&#36824;&#21407;&#33529;&#26524;&#24037;&#31243;&#24072;&#22312; Session &#20013;&#20256;&#36882;&#30340;&#20851;&#38190;&#32454;&#33410;&#12290;&#24456;&#22810; Session &#20173;&#20540;&#24471;&#38745;&#19979;&#24515;&#26469;&#65292;&#20180;&#32454;&#29978;&#33267;&#21453;&#22797;&#35266;&#30475;&#12290;</p><p>AI &#25552;&#21319;&#30340;&#26159;&#33719;&#21462;&#36164;&#35759;&#30340;&#36895;&#24230;&#65292;&#32780;&#38750;&#29702;&#35299;&#30340;&#28145;&#24230;&#12290;&#36164;&#35759;&#36827;&#20102; AI &#30340;&#19978;&#19979;&#25991;&#65292;&#19981;&#31561;&#20110;&#30693;&#35782;&#36827;&#20102;&#25105;&#20204;&#33258;&#24049;&#30340;&#33041;&#23376;&#12290;</p><p>&#35266;&#30475;&#20064;&#24815;&#21487;&#20197;&#19982;&#26102;&#20465;&#36827;&#65292;&#20294;&#23545;&#33258;&#24049;&#30340;&#35201;&#27714;&#65292;&#19981;&#35813;&#36319;&#30528;&#19968;&#36215;&#25171;&#25240;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-139/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>WWDC 2026</strong></h2><h3><strong>&#27719;&#24635;</strong></h3><ul><li><p><strong>WWDC 26 Group Lab Q&amp;A</strong> by <a href="https://x.com/AntonGubarenko">Anton Gubarenko</a></p><p>&#20170;&#24180;&#30340; Group Lab &#20013;&#65292;&#26469;&#33258; Apple &#30340;&#19987;&#23478;&#22260;&#32469;&#24320;&#21457;&#32773;&#25552;&#20986;&#30340;&#21508;&#31867;&#38382;&#39064;&#36827;&#34892;&#20102;&#29616;&#22330;&#35299;&#31572;&#12290;Anton &#20998;&#21035;&#27719;&#24635;&#20102; <a href="https://antongubarenko.substack.com/p/wwdc26-swift-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-for-beginners-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI &#21021;&#23398;&#32773;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-swiftui-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI &#36827;&#38454;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-power-and-performance-group?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">&#24615;&#33021;</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-visionos-group-lab-q-and-a?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">VisionOS</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-coding-intelligence-machine?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">AI</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-icon-composer-for-beginners?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Icon Composer</a>&#12289;<a href="https://antongubarenko.substack.com/p/wwdc26-camera-and-photo-technologies?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Camera and Photo</a> &#31561;&#20027;&#39064; Lab &#30340;&#38382;&#31572;&#20869;&#23481;&#12290;</p></li><li><p><a href="https://www.massicotte.org/blog/wwdc26-unanswered-qa/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">(Some) Unanswered Swift Group Questions</a> by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a></p><p>&#30001;&#20110;&#26102;&#38388;&#21644;&#25237;&#31080;&#26426;&#21046;&#38480;&#21046;&#65292;Swift Group Lab &#20013;&#24182;&#38750;&#27599;&#20010;&#38382;&#39064;&#37117;&#33021;&#34987;&#29616;&#22330;&#22238;&#31572;&#12290;Matt &#36873;&#21462;&#20102;&#19968;&#20123;&#26410;&#33719;&#22238;&#31572;&#30340;&#38382;&#39064;&#24182;&#32473;&#20986;&#20010;&#20154;&#35299;&#35835;&#65292;&#20869;&#23481;&#20027;&#35201;&#38598;&#20013;&#22312; Swift 6 &#36801;&#31227;&#12289;Approachable Concurrency&#12289;&#40664;&#35748; MainActor &#38548;&#31163;&#12289;<code>@preconcurrency</code>&#12289;Sendable / ~Sendable&#65292;&#20197;&#21450;&#38750;&#32467;&#26500;&#21270;&#20219;&#21153;&#31561;&#26041;&#21521;&#12290;</p></li><li><p><a href="https://onmyway133.com/posts/whats-new-in-swift-6.4-at-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s new in Swift 6.4 at WWDC26</a> by <a href="https://x.com/onmyway133">Khoa Pham</a></p><p>&#36825;&#31687;&#25991;&#31456;&#26803;&#29702;&#20102; Swift 6.4 &#20013;&#35753;&#20195;&#30721;&#26356;&#31616;&#27905;&#12289;&#26356;&#20855;&#34920;&#29616;&#21147;&#30340;&#19968;&#31995;&#21015;&#21464;&#21270;&#12290;</p></li><li><p><a href="https://wadetregaskis.com/whats-coming-in-swift-6-4/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s Coming in Swift 6.4</a> by <a href="https://mastodon.social/@everything@wadetregaskis.com">Wade Tregaskis</a></p><p>&#36825;&#31687;&#25991;&#31456;&#25972;&#29702;&#20102; Swift 6.4 &#20013;&#24050;&#26631;&#35760;&#20026; implemented &#30340; Swift Evolution &#25552;&#26696;&#65292;&#35206;&#30422;&#24182;&#21457;&#12289;&#25152;&#26377;&#26435;&#12289;&#26631;&#20934;&#24211;&#12289;&#35775;&#38382;&#22120;&#12289;&#21253;&#31649;&#29702;&#21644;&#32534;&#35793;&#22120;&#35786;&#26029;&#31561;&#22810;&#20010;&#26041;&#21521;&#12290;</p></li><li><p><a href="https://azamsharp.com/2026/06/12/whats-new-in-swiftdata.html?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What&#8217;s New in SwiftData for iOS 27</a> by <a href="https://x.com/azamsharp">Mohammad Azam</a></p><p>&#23613;&#31649; SwiftData &#20170;&#24180;&#30475;&#36215;&#26469;&#27809;&#26377;&#29305;&#21035;&#24040;&#22823;&#30340;&#26356;&#26032;&#65292;&#20294;&#26032;&#22686;&#30340;&#26522;&#20030;&#35859;&#35789;&#12289;&#20998;&#27573;&#26597;&#35810;&#12289;&#22797;&#21512;&#35859;&#35789;&#12289;<code>.codable</code> &#23646;&#24615;&#21644; <code>ResultsObserver</code> &#37117;&#38754;&#21521;&#20855;&#20307;&#30171;&#28857;&#65292;&#36827;&#19968;&#27493;&#34917;&#40784;&#20102; SwiftData &#30340;&#20351;&#29992;&#20307;&#39564;&#12290;</p></li><li><p><a href="https://swiftwithmajid.com/2026/06/08/what-is-new-in-swiftui-after-wwdc26/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">What is new in SwiftUI after WWDC26</a> by <a href="https://x.com/mecid">Majid Jabrayilov</a></p><p>Majid &#23545;&#20170;&#24180; WWDC26 &#19978; SwiftUI &#30456;&#20851;&#26032;&#21151;&#33021;&#20570;&#20102;&#26803;&#29702;&#65292;&#20854;&#20013;&#19981;&#23569;&#37117;&#26159;&#24320;&#21457;&#32773;&#38271;&#26399;&#26399;&#24453;&#30340;&#33021;&#21147;&#12290;&#30053;&#26174;&#36951;&#25022;&#30340;&#26159;&#65292;&#38500;&#20102; <code>@State</code> &#22806;&#65292;&#22823;&#22810;&#25968;&#26032; API &#24182;&#26410;&#25552;&#20379;&#21521;&#21069;&#20860;&#23481;&#25903;&#25345;&#12290;</p></li><li><p><a href="https://www.swiftjectivec.com/ios-27-notable-uikit-additions/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS 27: Notable UIKit Additions</a> by <a href="https://x.com/jordanmorgan10">Jordan Morgan</a></p><p>SwiftUI &#32487;&#32493;&#21457;&#23637;&#65292;&#20294; Apple &#24182;&#27809;&#26377;&#25918;&#24930;&#23545; UIKit &#30340;&#32500;&#25252;&#12290;&#20170;&#24180;&#30340; UIKit API &#26356;&#26032;&#26356;&#22810;&#22260;&#32469;&#31995;&#32479;&#26032;&#29305;&#24615;&#36866;&#37197;&#65292;&#20197;&#21450;&#19982; SwiftUI &#30340;&#26032;&#33021;&#21147;&#23545;&#40784;&#23637;&#24320;&#12290;</p></li></ul><h3><strong>&#25991;&#26723;</strong></h3><ul><li><p><a href="https://wwdc.ai/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC.ai</a> by <a href="https://x.com/Superwall">Superwall</a></p><p>&#19968;&#20010;&#24110;&#21161;&#24320;&#21457;&#32773;&#25110; AI &#20195;&#29702;&#24555;&#36895;&#20102;&#35299; Apple &#24320;&#21457;&#32773;&#26356;&#26032;&#30340;&#32593;&#31449;&#65292;&#25552;&#20379; Session &#25688;&#35201;&#12289;Ask AI &#33021;&#21147;&#65292;&#24182;&#25552;&#20379; <a href="https://github.com/superwall/skills">Skill</a>&#8288; &#26041;&#20415;&#22312;&#20195;&#30721;&#21161;&#25163;&#20013;&#30452;&#25509;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://github.com/0Itsuki0/iOS-MacOS_AppleBetaDocRetriever?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">iOS/MacOS: Apple Beta Doc Retriever</a> by <a href="https://x.com/itsuki68391179">Itsuki</a></p><p>&#19968;&#27454; iOS/macOS &#24320;&#28304;&#24212;&#29992;&#65292;&#21487;&#24110;&#21161;&#24320;&#21457;&#32773;&#26597;&#30475;&#24102;&#26377; Beta &#26631;&#27880;&#30340;&#25991;&#26723;&#21644; API&#65292;&#24555;&#36895;&#20102;&#35299;&#26032;&#26087;&#31995;&#32479;&#29256;&#26412;&#38388;&#30340;&#24046;&#24322;&#12290;</p></li><li><p><a href="https://wwdc-quick-look.swiftgg.team/articles/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC Quick Look</a> by <a href="https://swift.swiftgg.team/">SwiftGG</a></p><p>&#27719;&#24635;&#20102;&#33258; WWDC 2020 &#33267;&#20170;&#30340;&#25152;&#26377; Session &#20869;&#23481;&#65292;&#21253;&#21547;&#20851;&#32852; Session&#12289;&#35270;&#39057;&#36339;&#36716;&#21644;&#20851;&#38190;&#20195;&#30721;&#29255;&#27573;&#65292;&#20063;&#25552;&#20379;&#20102; <a href="https://github.com/SwiftGGTeam/wwdc-quick-look">Skill</a>&#8288; &#26041;&#20415; AI &#24037;&#20855;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://askwwdc.com/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Ask WWDC</a> by <a href="https://x.com/matthew_spear">Matt Spear</a></p><p>&#19968;&#20010;&#38754;&#21521; WWDC &#20869;&#23481;&#30340;&#38382;&#31572;&#25628;&#32034;&#24037;&#20855;&#65292;&#21487;&#20197;&#26681;&#25454;&#33258;&#28982;&#35821;&#35328;&#38382;&#39064;&#24555;&#36895;&#23450;&#20301;&#30456;&#20851; Session&#65292;&#24182;&#25972;&#29702;&#20986;&#31616;&#30701;&#31572;&#26696;&#21644;&#37325;&#28857;&#20869;&#23481;&#12290;</p></li></ul><h3><strong>&#26032;&#21151;&#33021;</strong></h3><ul><li><p><a href="https://livsycode.com/swiftui/swiftuis-state-is-now-a-macro/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s @State is now a macro</a> by <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a></p><p><code>@State</code> &#22312; SwiftUI &#26089;&#26399;&#20027;&#35201;&#38754;&#21521;&#20540;&#31867;&#22411;&#65292;&#20294;&#38543;&#30528; Observation &#26694;&#26550;&#22312; iOS 17 &#24341;&#20837;&#65292;<code>@State</code> &#19981;&#20855;&#22791;&#31867;&#20284; <code>@StateObject</code> &#30340;&#23454;&#20363;&#25042;&#21152;&#36733;&#33021;&#21147;&#36825;&#19968;&#38382;&#39064;&#36880;&#28176;&#26174;&#29616;&#12290;WWDC26 &#32456;&#20110;&#34917;&#19978;&#20102;&#36825;&#22359;&#30701;&#26495;&#12290;&#23588;&#20854;&#20540;&#24471;&#20851;&#27880;&#30340;&#26159;&#65292;Apple &#24182;&#27809;&#26377;&#30452;&#25509;&#35843;&#25972;&#23646;&#24615;&#21253;&#35013;&#22120;&#30340;&#23454;&#29616;&#65292;&#32780;&#26159;&#36890;&#36807;&#21516;&#21517;&#23439;&#26469;&#23436;&#25104;&#25913;&#36896;&#65292;&#36825;&#25110;&#35768;&#20063;&#25552;&#20379;&#20102;&#19968;&#31181;&#26410;&#26469;&#22788;&#29702;&#20860;&#23481;&#24615;&#38382;&#39064;&#30340;&#26032;&#24605;&#36335;&#12290;</p></li><li><p><a href="https://swiftuisnippets.wordpress.com/2026/06/10/wwdc26-the-evolution-of-presentation-transitions-in-swiftui/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">WWDC26: The Evolution of Presentation Transitions in SwiftUI</a> by <a href="https://x.com/Codelaby">codelaby</a></p><p>WWDC26 &#20013;&#65292;SwiftUI &#20026; <code>sheet</code> / <code>fullScreenCover</code> &#26032;&#22686;&#20102; <code>crossFade</code> &#36716;&#22330;&#25928;&#26524;&#12290;&#36951;&#25022;&#30340;&#26159;&#65292;&#30446;&#21069;&#20173;&#26410;&#25552;&#20379;&#33258;&#23450;&#20041;&#36716;&#22330;&#33021;&#21147;&#12290;</p></li><li><p><a href="https://nilcoalescing.com/blog/CustomScrollLayoutsWithSwipeActionsInSwiftUIOnIOS27/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Custom scroll layouts with swipe actions in SwiftUI on iOS 27</a> by <a href="https://x.com/natpanferova">Natalia Panferova</a></p><p>&#20174; iOS 27 &#24320;&#22987;&#65292;<code>swipeActions</code> &#19981;&#20877;&#26159; <code>List</code> &#30340;&#19987;&#23646;&#33021;&#21147;&#12290;&#26032;&#22686;&#30340; <code>swipeActionsContainer()</code> &#21487;&#20197;&#35753; <code>ScrollView</code> &#20013;&#30340; <code>LazyVStack</code>&#12289;<code>LazyVGrid</code> &#25110;&#33258;&#23450;&#20041; <code>Layout</code> &#25903;&#25345;&#28369;&#21160;&#25805;&#20316;&#65307;&#26032;&#30340; <code>onPresentationChanged</code> &#22238;&#35843;&#20063;&#21487;&#20197;&#22312;&#26576;&#19968;&#34892;&#30340;&#28369;&#21160;&#25805;&#20316;&#23637;&#24320;&#25110;&#25910;&#36215;&#26102;&#35302;&#21457;&#65292;&#20415;&#20110;&#35760;&#24405;&#24403;&#21069;&#27963;&#36291;&#39033;&#12289;&#32852;&#21160;&#29366;&#24577;&#25110;&#25191;&#34892;&#39069;&#22806;&#36923;&#36753;&#12290;</p></li><li><p><a href="https://artemnovichkov.com/blog/using-claude-with-apple-foundation-models?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Claude with Apple Foundation Models</a> by <a href="https://x.com/iosartem">Artem Novichkov</a></p><p>Foundation Models framework &#22312; WWDC26 &#19978;&#33719;&#24471;&#20102;&#19968;&#20010;&#37325;&#35201;&#25193;&#23637;&#65306;&#38500;&#20102; Apple &#30340;&#31471;&#20391;&#27169;&#22411;&#65292;<code>LanguageModelSession</code> &#29616;&#22312;&#20063;&#21487;&#20197;&#25509;&#20837;&#31526;&#21512; <code>LanguageModel</code> &#21327;&#35758;&#30340;&#26381;&#21153;&#31471;&#22823;&#27169;&#22411;&#12290;&#25991;&#31456;&#23637;&#31034;&#20102;&#22914;&#20309;&#20351;&#29992; Anthropic &#30340; <code>ClaudeForFoundationModels</code> &#23558; Claude &#25509;&#20837; Apple Foundation Models&#12290;</p></li><li><p><a href="https://www.sagarunagar.com/blog/swiftui-prominent-tab-is-not-a-floating-action-button/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">SwiftUI&#8217;s New .prominent Tab in iOS 27 Is Not a Floating Action Button</a> by <a href="https://x.com/sagarunagar_">Sagar Unagar</a></p><p>iOS 27 &#20013;&#65292;SwiftUI &#26032;&#22686;&#30340; <code>Tab(role: .prominent)</code> &#21487;&#20197;&#35753;&#26576;&#20010; tab &#22312;&#31995;&#32479; tab bar &#20013;&#33719;&#24471;&#26356;&#24378;&#30340;&#35270;&#35273;&#24378;&#35843;&#12290;Sagar &#25552;&#37266;&#65292;&#36825;&#39033;&#33021;&#21147;&#24212;&#35813;&#29992;&#20110;&#31361;&#20986;&#24212;&#29992;&#20013;&#26368;&#37325;&#35201;&#30340;&#23548;&#33322;&#30446;&#30340;&#22320;&#65292;&#32780;&#19981;&#26159;&#26367;&#20195; Floating Action Button&#12289;&#23548;&#33322;&#26639; &#8220;+&#8221; &#25353;&#38062;&#25110;&#24377;&#20986; sheet &#30340;&#25805;&#20316;&#20837;&#21475;&#12290;</p></li></ul><h3><strong>&#38382;&#39064;&#19982;&#35299;&#20915;</strong></h3><ul><li><p><a href="https://www.donnywals.com/installing-simulator-runtimes-from-the-command-line/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Installing simulator runtimes from the command line</a> by <a href="https://x.com/donnywals">Donny Wals</a></p><p>&#22914;&#26524;&#24320;&#21457;&#32773;&#22312;&#23433;&#35013; Xcode 27 &#21518;&#36935;&#21040; iOS Simulator Runtime &#26080;&#27861;&#36890;&#36807; Xcode UI &#27491;&#24120;&#19979;&#36733;&#30340;&#38382;&#39064;&#65292;&#21487;&#20197;&#25913;&#29992; <code>xcodebuild</code> &#20174;&#21629;&#20196;&#34892;&#23433;&#35013;&#36816;&#34892;&#26102;&#12290;</p></li><li><p><a href="https://www.avanderlee.com/ai-development/using-xcode-27s-agent-skills-in-claude-codex-and-cursor/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Using Xcode 27&#8217;s Agent Skills in Claude, Codex, and Cursor</a> by <a href="https://x.com/twannl">Antoine v.d. SwiftLee</a></p><p>Xcode 27 &#20869;&#32622;&#20102;&#19968;&#32452; Apple &#23448;&#26041;&#25552;&#20379;&#30340; Agent Skills&#65292;&#28085;&#30422; SwiftUI&#12289;UIKit&#12289;&#27979;&#35797;&#31561;&#22330;&#26223;&#65292;&#24182;&#25552;&#20379;&#20102;&#23548;&#20986;&#33021;&#21147;&#65292;&#26041;&#20415;&#22312; Claude&#12289;Codex&#12289;Cursor &#31561;&#24037;&#20855;&#20013;&#20351;&#29992;&#12290;</p></li><li><p><a href="https://github.com/SkyBlue997/enableMacosAI?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">EnableMacosAI</a> by <a href="https://github.com/SkyBlue997">&#28023;&#31354;&#33980;</a></p><p>&#19968;&#20010;&#29992;&#20110;&#22312;&#20013;&#22269;&#38144;&#21806;&#30340; macOS &#35774;&#22791;&#19978;&#21551;&#29992;&#23436;&#25972; Apple Intelligence &#30340;&#24037;&#20855;&#12290;</p></li></ul><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><ul><li><p><a href="https://www.swift.org/blog/migrating-truetype-hinting-to-swift/?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Swift at Apple: Migrating the TrueType Hinting Interpreter</a> by <a href="https://mastodon.social/@numist@xoxo.zone">Scott Perry</a></p><p>Apple &#23433;&#20840;&#22242;&#38431;&#20998;&#20139;&#20102;&#23558; TrueType hinting interpreter &#20174; C &#36801;&#31227;&#21040; Swift &#30340;&#32463;&#39564;&#65306;&#22312;&#20445;&#25345;&#20687;&#32032;&#32423;&#19968;&#33268;&#30340;&#21069;&#25552;&#19979;&#65292;&#26032;&#30340;&#20869;&#23384;&#23433;&#20840; Swift &#23454;&#29616;&#24179;&#22343;&#27604;&#21407; C &#23454;&#29616;&#24555; 13%&#65292;&#25991;&#31456;&#20063;&#28145;&#20837;&#20171;&#32461;&#20102;&#38750;&#21487;&#22797;&#21046;&#31867;&#22411;&#12289;Span&#12289;projection type &#31561;&#22312;&#31995;&#32479;&#32423;&#24615;&#33021;&#20248;&#21270;&#20013;&#30340;&#23454;&#36341;&#12290;</p></li></ul><blockquote><p>TrueType hinting interpreter &#26159; TrueType &#23383;&#20307;&#28210;&#26579;&#31995;&#32479;&#20013;&#30340;&#25552;&#31034;&#25351;&#20196;&#35299;&#37322;&#22120;&#65292;&#23427;&#20250;&#35835;&#21462;&#23383;&#20307;&#20013;&#30340; hinting &#23383;&#33410;&#30721;&#65292;&#24182;&#26681;&#25454;&#36825;&#20123;&#25351;&#20196;&#35843;&#25972;&#23383;&#24418;&#25511;&#21046;&#28857;&#65292;&#35753;&#25991;&#23383;&#22312;&#29305;&#23450;&#23383;&#21495;&#21644;&#23631;&#24149;&#20687;&#32032;&#32593;&#26684;&#19978;&#26174;&#31034;&#24471;&#26356;&#28165;&#26224;&#12290;</p></blockquote><ul><li><p><a href="https://deliveryhero.jobs/blog/scaling-ios-application-development-with-tuist/?utm_medium=LinkedIn&amp;utm_source=Employee_Advocacy_Program?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Scaling iOS application development with Tuist</a> by <a href="https://www.linkedin.com/in/mikeamike/">Michael Gerasymenko</a> and <a href="https://www.linkedin.com/in/dubeyashu/">Ashutosh Dubey</a></p><p>Delivery Hero Logistics &#22242;&#38431;&#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Tuist &#25193;&#23637;&#22823;&#22411; iOS &#24037;&#31243;&#65306;&#22312;&#20445;&#30041; Xcode &#21644; Swift Package Manager &#24037;&#20316;&#27969;&#30340;&#21516;&#26102;&#65292;&#36890;&#36807; Swift &#20195;&#30721;&#23450;&#20041;&#39033;&#30446;&#32467;&#26500;&#12289;&#26174;&#24335;&#20381;&#36182;&#22270;&#12289;&#20108;&#36827;&#21046;&#32531;&#23384;&#21644;&#36873;&#25321;&#24615;&#27979;&#35797;&#65292;&#23558;&#26412;&#22320; clean build &#20174; 2.5 &#20998;&#38047;&#38477;&#21040; 0.5 &#20998;&#38047;&#65292;&#24182;&#35753; CI &#26500;&#24314;&#21644;&#21333;&#27979;&#32791;&#26102;&#32553;&#30701; 2.5 &#20493;&#12290;</p></li></ul><blockquote><p>&#25991;&#31456;&#30340;&#37325;&#28857;&#19981;&#21482;&#26159;&#8220;Tuist &#21487;&#20197;&#21152;&#24555;&#26500;&#24314;&#8221;&#65292;&#32780;&#26159;&#23637;&#31034;&#20102;&#23427;&#22914;&#20309;&#24110;&#21161;&#22242;&#38431;&#25226;&#22823;&#22411; iOS &#24037;&#31243;&#21464;&#24471;&#26356;&#21487;&#32500;&#25252;&#12290;</p></blockquote><ul><li><p><a href="https://alejandromp.com/development/blog/keeping-up-with-swift-forums-using-codex?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Keeping Up With Swift Forums Using Codex</a> by <a href="https://x.com/alexito4">Alejandro Martinez</a></p><p>Alejandro &#20998;&#20139;&#20102;&#22914;&#20309;&#29992; Codex Automations &#21644; Swift CLI &#26500;&#24314;&#19968;&#20010;&#27599;&#22825;&#33258;&#21160;&#36319;&#36827; Swift Forums &#30340;&#20010;&#20154;&#24037;&#20316;&#27969;&#65306;&#30001; CLI &#22788;&#29702;&#35770;&#22363;&#25968;&#25454;&#21644;&#29366;&#24577;&#21516;&#27493;&#65292;Codex &#36127;&#36131;&#29702;&#35299;&#19978;&#19979;&#25991;&#12289;&#29983;&#25104;&#25688;&#35201;&#21644;&#25512;&#36827;&#21518;&#32493;&#25506;&#32034;&#65292;&#23637;&#31034;&#20102;&#19968;&#31181;&#8220;AI &#39537;&#21160;&#12289;&#31243;&#24207;&#20316;&#20026;&#24037;&#20855;&#8221;&#30340;&#23454;&#29992;&#33258;&#21160;&#21270;&#35774;&#35745;&#12290;</p></li><li><p><a href="https://github.com/apple/container?utm_source=fatbobman%20weekly%20issue%20140&amp;utm_medium=web">Container 1.0</a></p><p>Apple &#20960;&#22825;&#21069;&#27491;&#24335;&#21457;&#24067;&#20102; Container 1.0&#12290;&#20316;&#20026;&#38754;&#21521; Apple silicon &#30340; OCI &#23481;&#22120;&#26041;&#26696;&#65292;&#23427;&#30456;&#27604; Docker &#22312;&#38548;&#31163;&#12289;&#21551;&#21160;&#36895;&#24230;&#21644; macOS &#21407;&#29983;&#20307;&#39564;&#19978;&#26356;&#26377;&#20248;&#21183;&#12290;&#24403;&#28982;&#65292;&#30001;&#20110;&#29983;&#24577;&#20173;&#26032;&#65292;&#30456;&#20851;&#21151;&#33021;&#21644;&#24037;&#20855;&#38142;&#36824;&#22312;&#25345;&#32493;&#23436;&#21892;&#20013;&#12290;</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #139]]></title><description><![CDATA[First Impressions of WWDC 2026: In Line with Expectations, but More Pragmatic]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Tue, 09 Jun 2026 12:03:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!chp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!chp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!chp5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 424w, https://substackcdn.com/image/fetch/$s_!chp5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 848w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg" width="1400" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77180,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/201238663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!chp5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 424w, https://substackcdn.com/image/fetch/$s_!chp5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 848w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!chp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27d73e23-5035-4e07-91b6-be2edb4ada2d_1400x788.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>First Impressions of WWDC 2026: In Line with Expectations, but More Pragmatic</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-139/">Read on web &#8594;</a></p><p>Like many developers, I cared more this year about improvements in stability and efficiency, and I also deliberately lowered my expectations for &#8220;surprising new features.&#8221; With that mindset, after quickly going through several topics from the first day of WWDC 2026 that I personally care about, my initial impression of this year&#8217;s event is: it was in line with expectations, and quite pragmatic.</p><p><strong>AI</strong></p><p>Although Foundation Models was introduced last year, the capabilities it offered at the time were still not compelling enough for many developers. This year&#8217;s changes are clearly more practical: the APIs have been further integrated; image input is now supported; developers can choose between on-device models, Private Cloud Compute, or third-party server models depending on the task; and eligible developers can use Apple Foundation Models running on Private Cloud Compute for free. At the same time, the system is also gaining stronger view awareness, better understanding of app context, and the ability to bring users back into apps through App Intents.</p><p>These improvements significantly increase the practicality and appeal of Foundation Models. It is no longer merely a framework that is &#8220;worth trying&#8221;; it is beginning to have the foundation needed to enter real product workflows. Unsurprisingly, more developers will likely be willing to experiment with this system this year and gradually incorporate it as one of the core capabilities of their apps.</p><p><strong>SwiftUI</strong></p><p>For me, the biggest change in SwiftUI comes from its comprehensive support for document-based apps. It not only adds a large number of new APIs, but also shifts the mental model toward &#8220;observable document objects + asynchronous snapshots + dedicated readers / writers.&#8221; This is clearly better suited to complex document apps, and it also aligns more closely with the overall evolution of modern Swift around Observation and Concurrency.</p><p>The sessions also mentioned that SwiftUI continues to optimize layout- and container-related implementations, bringing noticeable performance improvements in some scenarios. This is an improvement developers have urgently needed. However, SwiftUI still does not provide the ability to create custom Lazy containers, which remains a clear disappointment. <code>reorderable</code> and <code>swipeActions</code> are no longer limited to specific containers. This is not merely an expansion of their applicable scope; it also reflects further integration of the underlying interaction logic. Perhaps the benefits of this integration will become more apparent in next year&#8217;s APIs.</p><p><code>@State</code> now supports lazy initialization, text selection on iOS has been enhanced, and <code>alert</code> / <code>confirmationDialog</code> now provide <code>Binding&lt;T?&gt;</code> support. These are all welcome improvements, though they do feel like they arrived a little late. <code>AnyNavigationTransition</code> appears in the interface, but there is still no public support for custom transitions. For now, developers can only choose between the system-provided zoom and crossFade transitions.</p><p>The new DataDetection framework gives <code>Text</code> better content recognition capabilities; toolbars also gain more control. These changes also show Apple&#8217;s continued emphasis on using SwiftUI to build macOS apps. Overall, SwiftUI this year does not rely on a single standout API to create surprise. Instead, through a set of additions and integrations, it moves closer to the everyday needs of complex apps.</p><p><strong>SwiftData</strong></p><p>Compared with <code>@Query</code> gaining support for section fetches, and <code>ResultsObserver</code> enabling observation of query result changes outside views, I am more interested in <code>@Attribute(.codable)</code>. It provides a clearer storage intent and gives developers a way to avoid falling into the black box of composition.</p><p>Of course, <code>@Attribute(.codable)</code> is not a silver bullet. It is more like a clearly defined escape hatch SwiftData provides for opaque Codable types: suitable for storing external types that you cannot model yourself, but still genuinely need to persist. The cost is that this content cannot participate in SwiftData&#8217;s predicate, sort, or migration awareness. Precisely for this reason, its value lies not in being &#8220;more powerful,&#8221; but in being &#8220;more explicit.&#8221;</p><p>However, SwiftData still does not provide cloud syncing for public / shared data, nor have I seen a clearer signal of performance improvements. These issues will continue to limit its adoption. For many developers, SwiftData this year feels more like it is filling key gaps rather than making a leap significant enough to fundamentally change confidence in it.</p><p><strong>Xcode</strong></p><p>Over the past six months, my development workflow has basically been Codex App / Claude App + Xcode, with Xcode appearing significantly less often than the former two. After briefly trying Xcode 27, I expect Xcode&#8217;s presence in my workflow to increase noticeably. I am especially looking forward to the changes Xcode&#8217;s built-in AI workflows may bring in areas such as fine-tuning UI, improving performance, and validating previews.</p><p>Device Hub is undoubtedly a major surprise. It integrates simulators, physical device management, system state testing, and dynamic size adjustment into a new workflow. Its impact on day-to-day development experience may be more direct than that of many individual APIs. That said, iPhone apps now also support dynamic size adjustment, which will bring new challenges for developers, especially in terms of data and state organization. Adapting to different sizes is not something that can be solved merely by relying on dynamic layout containers. In many scenarios, large and small sizes correspond to very different navigation logic.</p><div><hr></div><p>This year, I probably won&#8217;t rush to write articles about the new SwiftUI and SwiftData APIs. Instead of introducing new interfaces one by one, I would rather spend some time systematically digesting these changes and sorting out the implicit logic behind them: how Apple is reorganizing the relationship between SwiftUI, SwiftData, Foundation Models, and Xcode&#8217;s AI workflow &#8212; and how these changes will ultimately affect the way we build apps.</p><p><a href="https://fatbobman.com/en/weekly/issue-138/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/core-data-observation-freer-mental-model/?utm_source=fatbobman%20weekly%20issue%20139&amp;utm_medium=web">Core Data + Observation: From Property-Level Reactivity to a Freer Mental Model</a></strong></h3><p>The introduction of the Observation framework refined SwiftUI&#8217;s state-driven updates from object-level observation to property-level observation, significantly reducing many unnecessary refreshes caused by coarse-grained observation. More importantly, it makes the declarative logic of state management feel natural again: a view only needs to read the properties it truly depends on, and the framework can establish the corresponding reactive relationships from there. To bring the conveniences of modern Swift features to Core Data, a long-standing persistence framework, I recently explored and implemented Observation support in <a href="https://fatbobman.com/zh/posts/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/">Core Data Evolution</a> (CDE), giving <code>NSManagedObject</code> precise property-level observation capabilities. This article discusses the motivation behind this feature, how to use it, the implementation approach, engineering challenges, and some of the trade-offs made during development.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-01">Bringing Goodnotes to the Web with Swift and WebAssembly</a></strong></h3><p>As a well-known note-taking app in the Apple ecosystem, Goodnotes did not choose to completely rewrite its product when moving to the Web. Instead, it brought years of accumulated Swift code into the browser environment through WebAssembly. In this article, <a href="https://x.com/kateinoigakukun">Yuta Saito</a> explains how Goodnotes maintains the same ink rendering, document synchronization, CRDT-based conflict resolution, search indexing, and interaction experience on the Web as in the native app. The Swift codebase for Goodnotes Web is about 2.2 million lines of code, of which 1.47 million lines are shared code; the final generated WebAssembly binary is about 50 MB, compressed to around 12 MB with Brotli. The significance of this article is not merely that it shows Swift can run on the Web, but that it presents how a real, large-scale Swift application can use WebAssembly to extend core capabilities originally deeply rooted in Apple platforms to more platforms.</p><blockquote><p>Yuta&#8217;s iOS Conf 2026 talk, <a href="https://www.youtube.com/watch?v=ysD4_qqd-po">Swift at Scale: Where Performance Really Comes From</a>, is also worth watching. Compared with the official article&#8217;s overview of the overall Goodnotes Web architecture, this talk focuses more on a real Swift performance case: the Goodnotes team found that an <code>Update</code> value type used to aggregate partial UI updates had grown to about 6 KB as features accumulated, and it contained many non-trivial members. Even though most updates only used one or two fields, the hot path still paid the cost of copying and reference counting. The team eventually refactored the data structure through a hot-cold split, keeping frequently accessed fields in the main struct while moving infrequent updates into separate storage. This reduced the type size from about 6 KB to around 300 bytes and brought about a 42% improvement in CPU time.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-02">Announcing the Networking Workgroup</a></strong></h3><p>Swift&#8217;s networking APIs are not lacking in choices; rather, there are too many choices with overlapping responsibilities. From <code>URLSession</code> and <code>Network.framework</code> on Apple platforms, to SwiftNIO and AsyncHTTPClient in the server-side ecosystem, and further down to lower-level HTTP representation types, developers often have to deal with inconsistent models and migration costs across different platforms and abstraction layers. More importantly, many of these APIs appeared before modern Swift capabilities such as async/await, structured concurrency, actors, and <code>Sendable</code> had matured, making it difficult for them to naturally reflect Swift&#8217;s current strengths in concurrency, safety, and cross-platform development. These issues are discussed more systematically in <a href="https://github.com/swiftlang/swift-evolution/blob/main/visions/networking.md">A Vision for Networking in Swift</a>, while the <a href="https://github.com/apple/swift-http-api-proposal">Swift HTTP API Proposal</a> can be seen as an early exploration in this direction.</p><p>The official establishment of the Networking Workgroup sends an important signal: the Swift ecosystem is beginning to treat networking as cross-platform infrastructure that requires long-term governance, rather than simply allowing individual frameworks and packages to evolve independently within their own domains. The goal of the workgroup is not to simply replace existing solutions, but to promote clearer layering, more consistent types, better interoperability, and stronger observability, so that Swift can have a more unified, modern, and sustainable networking foundation across Apple platforms, server-side development, CLI tools, WebAssembly, Android, Windows, and even Embedded Swift.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-03">WWDC 2026 Wish Lists</a></strong></h3><p><a href="https://x.com/mjtsai">Michael Tsai</a> collected wish lists from several Apple developers ahead of WWDC 2026. Similar to the expectations I shared in <a href="https://fatbobman.com/zh/weekly/issue-138/">the previous issue of the weekly newsletter</a>, most developers are calling for a Snow Leopard-style quality-focused release: rethinking the usability of Liquid Glass on the Mac, reducing instability at the system and framework levels, and fixing long-standing issues that affect daily development, such as iCloud sync, Spotlight, System Settings, error messages, SwiftUI, Xcode, Simulator, indexing, and previews. Many developers also hope that this year will not introduce another wave of &#8220;busywork&#8221; caused by adapting to new designs, new frameworks, or new review requirements, but instead give the existing platforms more time for refinement.</p><p>Another clear theme is how Apple&#8217;s developer tools should evolve in the age of AI agents. Several authors mention that they hope Apple will provide more official Agent Skills, MCP support, CLI tools, and automation interfaces, allowing AI to more reliably read documentation, operate Xcode, manage App Store Connect, modify project settings, run builds, control Simulator, and even understand UI hierarchies in a more structured way, rather than relying on screenshots or fragile Accessibility information.</p><blockquote><p>Adapting to the AI era and improving system stability are indeed becoming shared expectations among more Apple developers. By the time you read this issue, WWDC 2026 has already begun. After reading these wish lists and then watching this year&#8217;s announcements, I wonder whether everyone has found the answers they were hoping for.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-04">Apple-like</a></strong></h3><p>Around WWDC 2026, discussions about Apple&#8217;s future direction have become noticeably more frequent. Many people expect Apple to &#8220;return to its roots&#8221; or rediscover its former state, but in this article, <a href="https://mastodon.social/@_Davidsmith">David Smith</a> chooses a more constructive question: what does it mean to be Apple-like? As a long-time Apple platform developer, he summarizes this quality into several directions: The Best, and then Better; Excellence for Everyone; and Beneficial and Brilliant. In other words, continuously pursuing high quality, and not spending down user expectations even after getting ahead; making excellent experiences available to as many people as possible through pricing, accessibility, and design; and avoiding manipulative ways of chasing short-term metrics, instead solving users&#8217; problems in ways that are genuinely beneficial and delightful.</p><blockquote><p>When we expect Apple to improve system stability, developer tools, and platform experience, this article also reminds us that independent developers and app teams can examine their own products through similar standards.</p></blockquote><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-05">MarkdownPDF: A Markdown-to-PDF Engine Written Entirely in Swift</a></strong></h3><p>MarkdownPDF is an open-source Markdown-to-PDF engine written entirely in Swift by <a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263;</a>. It does not depend on platform or system capabilities such as PDFKit, CoreGraphics, WebKit, Chromium, LaTeX, or C-based PDF/Markdown libraries. Markdown parsing, layout, and PDF serialization are all implemented in Swift. Precisely because its core is pure and its dependencies are restrained, the project has strong cross-platform potential. It can target WebAssembly/WASI and generate PDFs from Markdown locally in the browser. The <a href="https://pdf.aleahim.com/">Playground</a> provided by the author demonstrates this capability.</p><blockquote><p>Goodnotes shows the engineering practice of migrating a large Swift application to the Web, while MarkdownPDF offers another perspective: when the core logic is pure enough and the dependencies are restrained enough, Swift tools themselves can also adapt naturally to the WebAssembly runtime environment. Swift&#8217;s move toward the Web is evolving from a proof of concept into an increasingly concrete engineering choice.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-06">AdaEngine: A Swift-first Open Source Game Engine</a></strong></h3><p>AdaEngine is an open-source Swift-first game engine and application framework created by <a href="https://x.com/SpectralDragon_">Vladislav Prusakov</a>, which recently released its first public milestone, 0.1.0. The project is designed for cross-platform development. Apple platforms are currently the most mature, while support for Windows, Linux, Android, and WebAssembly/WebGPU is also being developed.</p><p>With a data-driven ECS at its core, AdaEngine combines Swift macros, a plugin-based architecture, SwiftUI-like AdaUI, asset hot reloading, a scene system, 2D physics, audio, input, and Metal / WebGPU rendering backends. It aims to let Swift serve not only Apple platform app development, but also games, interactive tools, and creative software.</p><blockquote><p>Vladislav gives a more complete introduction to the project in <a href="https://adaengine.org/articles/introducing-adaengine-0-1-0">Introducing AdaEngine 0.1.0</a>.</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-139?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>WWDC 2026 &#21021;&#21360;&#35937;&#65306;&#31526;&#21512;&#39044;&#26399;&#65292;&#20294;&#26356;&#21153;&#23454;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-139/">&#32593;&#39029;&#29256;</a></strong></p><p>&#21644;&#24456;&#22810;&#24320;&#21457;&#32773;&#19968;&#26679;&#65292;&#25105;&#20170;&#24180;&#26356;&#30475;&#37325;&#31283;&#23450;&#24615;&#19982;&#25928;&#29575;&#26041;&#38754;&#30340;&#25913;&#21892;&#65292;&#20063;&#20027;&#21160;&#38477;&#20302;&#20102;&#23545;&#8220;&#24778;&#21916;&#22411;&#26032;&#21151;&#33021;&#8221;&#30340;&#26399;&#24453;&#12290;&#24102;&#30528;&#36825;&#26679;&#30340;&#39044;&#26399;&#65292;&#24555;&#36895;&#27983;&#35272;&#20102; WWDC 2026 &#31532;&#19968;&#22825;&#20013;&#20960;&#20010;&#25105;&#27604;&#36739;&#20851;&#24515;&#30340;&#20027;&#39064;&#21518;&#65292;&#26412;&#23626;&#27963;&#21160;&#32473;&#25105;&#30340;&#21021;&#27493;&#21360;&#35937;&#26159;&#65306;&#31526;&#21512;&#39044;&#26399;&#65292;&#32780;&#19988;&#30456;&#24403;&#21153;&#23454;&#12290;</p><p><strong>AI</strong></p><p>&#23613;&#31649; Foundation Models &#22312;&#21435;&#24180;&#24050;&#32463;&#25512;&#20986;&#65292;&#20294;&#24403;&#26102;&#25552;&#20379;&#30340;&#33021;&#21147;&#65292;&#23545;&#24456;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#20173;&#19981;&#36275;&#20197;&#26500;&#25104;&#36275;&#22815;&#24378;&#30340;&#21560;&#24341;&#21147;&#12290;&#20170;&#24180;&#30340;&#21464;&#21270;&#21017;&#26126;&#26174;&#26356;&#21153;&#23454;&#65306;API &#36827;&#19968;&#27493;&#25972;&#21512;&#65292;&#25903;&#25345;&#22270;&#20687;&#36755;&#20837;&#65292;&#21487;&#20197;&#26681;&#25454;&#20219;&#21153;&#36873;&#25321;&#35774;&#22791;&#31471;&#27169;&#22411;&#12289;&#31169;&#26377;&#20113;&#35745;&#31639;&#25110;&#31532;&#19977;&#26041;&#26381;&#21153;&#22120;&#27169;&#22411;&#65307;&#28385;&#36275;&#26465;&#20214;&#30340;&#24320;&#21457;&#32773;&#36824;&#21487;&#20197;&#20813;&#36153;&#20351;&#29992;&#36816;&#34892;&#22312;&#31169;&#26377;&#20113;&#35745;&#31639;&#19978;&#30340; Apple &#22522;&#30784;&#27169;&#22411;&#12290;&#19982;&#27492;&#21516;&#26102;&#65292;&#31995;&#32479;&#20063;&#24320;&#22987;&#20855;&#22791;&#26356;&#24378;&#30340;&#35270;&#22270;&#24863;&#30693;&#12289;App &#19978;&#19979;&#25991;&#29702;&#35299;&#65292;&#20197;&#21450;&#36890;&#36807; App Intents &#23558;&#29992;&#25143;&#37325;&#26032;&#24102;&#22238;&#24212;&#29992;&#30340;&#33021;&#21147;&#12290;</p><p>&#36825;&#20123;&#25913;&#36827;&#22823;&#24133;&#25552;&#21319;&#20102; Foundation Models &#30340;&#23454;&#29992;&#24615;&#21644;&#21560;&#24341;&#21147;&#12290;&#23427;&#19981;&#20877;&#21482;&#26159;&#19968;&#20010;&#8220;&#21487;&#20197;&#35797;&#35797;&#8221;&#30340;&#26694;&#26550;&#65292;&#32780;&#26159;&#24320;&#22987;&#20855;&#22791;&#36827;&#20837;&#30495;&#23454;&#20135;&#21697;&#27969;&#31243;&#30340;&#22522;&#30784;&#12290;&#19981;&#20986;&#24847;&#22806;&#65292;&#20170;&#24180;&#20250;&#26377;&#26356;&#22810;&#24320;&#21457;&#32773;&#24895;&#24847;&#23581;&#35797;&#36825;&#22871;&#31995;&#32479;&#65292;&#24182;&#36880;&#27493;&#23558;&#20854;&#32435;&#20837;&#24212;&#29992;&#30340;&#26680;&#24515;&#33021;&#21147;&#20043;&#19968;&#12290;</p><p><strong>SwiftUI</strong></p><p>&#23545;&#25105;&#26469;&#35828;&#65292;SwiftUI &#26368;&#22823;&#30340;&#21464;&#21270;&#26469;&#33258;&#23545;&#25991;&#26723;&#31867;&#24212;&#29992;&#30340;&#20840;&#38754;&#25903;&#25345;&#12290;&#23427;&#19981;&#20165;&#22686;&#21152;&#20102;&#22823;&#37327;&#26032; API&#65292;&#20063;&#23558;&#24515;&#26234;&#27169;&#22411;&#35843;&#25972;&#20026;&#8220;&#21487;&#35266;&#23519;&#25991;&#26723;&#23545;&#35937; + &#24322;&#27493;&#24555;&#29031; + &#19987;&#29992; reader / writer&#8221;&#12290;&#36825;&#26174;&#28982;&#26356;&#36866;&#21512;&#22797;&#26434;&#25991;&#26723; App&#65292;&#20063;&#26356;&#31526;&#21512;&#29616;&#20195; Swift &#22312; Observation &#21644; Concurrency &#26041;&#21521;&#19978;&#30340;&#25972;&#20307;&#28436;&#36827;&#12290;</p><p>Session &#20013;&#20063;&#25552;&#21040;&#65292;SwiftUI &#22312;&#24067;&#23616;&#19982;&#23481;&#22120;&#30456;&#20851;&#23454;&#29616;&#19978;&#32487;&#32493;&#20248;&#21270;&#65292;&#37096;&#20998;&#22330;&#26223;&#19979;&#30340;&#24615;&#33021;&#20250;&#26377;&#26126;&#26174;&#25552;&#21319;&#12290;&#36825;&#26159;&#24320;&#21457;&#32773;&#36843;&#20999;&#38656;&#35201;&#30340;&#25913;&#36827;&#12290;&#19981;&#36807;&#65292;SwiftUI &#20173;&#26410;&#25552;&#20379;&#33258;&#23450;&#20041; Lazy &#23481;&#22120;&#30340;&#33021;&#21147;&#65292;&#36825;&#26080;&#30097;&#26159;&#19968;&#20010;&#36951;&#25022;&#12290;<code>reorderable</code> &#21644; <code>swipeActions</code> &#19981;&#20877;&#23616;&#38480;&#20110;&#29305;&#23450;&#23481;&#22120;&#65292;&#36825;&#19981;&#21482;&#26159;&#36866;&#29992;&#33539;&#22260;&#30340;&#25193;&#22823;&#65292;&#20063;&#20307;&#29616;&#20102;&#24213;&#23618;&#20132;&#20114;&#36923;&#36753;&#30340;&#36827;&#19968;&#27493;&#25972;&#21512;&#12290;&#25110;&#35768;&#36825;&#20123;&#25972;&#21512;&#24102;&#26469;&#30340;&#25910;&#30410;&#65292;&#20250;&#22312;&#26126;&#24180;&#30340; API &#20013;&#21576;&#29616;&#24471;&#26356;&#21152;&#26126;&#26174;&#12290;</p><p><code>@State</code> &#25903;&#25345;&#24816;&#24615;&#21021;&#22987;&#21270;&#65292;iOS &#19978;&#30340; text selection &#24471;&#21040;&#22686;&#24378;&#65292;<code>alert</code> / <code>confirmationDialog</code> &#25552;&#20379;&#20102; <code>Binding&lt;T?&gt;</code> &#25903;&#25345;&#65292;&#36825;&#20123;&#37117;&#24456;&#22909;&#65292;&#21482;&#26159;&#24863;&#35273;&#26469;&#24471;&#31245;&#26202;&#20102;&#19968;&#20123;&#12290;interface &#20013;&#20986;&#29616;&#20102; <code>AnyNavigationTransition</code>&#65292;&#20294;&#30446;&#21069;&#20173;&#27809;&#26377;&#24320;&#25918;&#33258;&#23450;&#20041; transition &#30340;&#33021;&#21147;&#65292;&#21482;&#33021;&#22312;&#31995;&#32479;&#39044;&#35774;&#30340; zoom &#21644; crossFade &#20013;&#20999;&#25442;&#12290;</p><p>&#26032;&#30340; DataDetection &#26694;&#26550;&#20026; <code>Text</code> &#25552;&#20379;&#20102;&#26356;&#22909;&#30340;&#20869;&#23481;&#35782;&#21035;&#33021;&#21147;&#65307;toolbar &#33719;&#24471;&#20102;&#26356;&#22810;&#25511;&#21046;&#21147;&#65292;&#20063;&#33021;&#30475;&#20986; Apple &#23545;&#20351;&#29992; SwiftUI &#24320;&#21457; macOS &#24212;&#29992;&#30340;&#37325;&#35270;&#12290;&#25972;&#20307;&#26469;&#30475;&#65292;&#20170;&#24180;&#30340; SwiftUI &#24182;&#19981;&#26159;&#38752;&#26576;&#20010;&#21333;&#28857; API &#24102;&#26469;&#24778;&#21916;&#65292;&#32780;&#26159;&#36890;&#36807;&#19968;&#32452;&#34917;&#40784;&#21644;&#25972;&#21512;&#65292;&#35753;&#23427;&#26356;&#25509;&#36817;&#22797;&#26434; App &#30340;&#26085;&#24120;&#38656;&#27714;&#12290;</p><p><strong>SwiftData</strong></p><p>&#30456;&#36739;&#20110; <code>@Query</code> &#25903;&#25345; section fetch&#65292;&#20197;&#21450; <code>ResultsObserver</code> &#25552;&#20379;&#35270;&#22270;&#22806;&#35266;&#23519;&#26597;&#35810;&#32467;&#26524;&#21464;&#21270;&#30340;&#33021;&#21147;&#65292;&#25105;&#26356;&#30475;&#37325; <code>@Attribute(.codable)</code>&#12290;&#23427;&#25552;&#20379;&#20102;&#26356;&#26126;&#30830;&#30340;&#23384;&#20648;&#24847;&#22270;&#65292;&#20063;&#32473;&#20102;&#24320;&#21457;&#32773;&#19968;&#20010;&#36991;&#20813;&#38519;&#20837; composition &#40657;&#30418;&#30340;&#28192;&#36947;&#12290;</p><p>&#24403;&#28982;&#65292;<code>@Attribute(.codable)</code> &#24182;&#19981;&#26159;&#38134;&#24377;&#12290;&#23427;&#26356;&#20687;&#26159; SwiftData &#20026;&#19981;&#36879;&#26126; Codable &#31867;&#22411;&#25552;&#20379;&#30340;&#26126;&#30830;&#20986;&#21475;&#65306;&#36866;&#21512;&#23384;&#20648;&#20320;&#26080;&#27861;&#24314;&#27169;&#12289;&#20294;&#21448;&#30830;&#23454;&#38656;&#35201;&#25345;&#20037;&#21270;&#30340;&#22806;&#37096;&#31867;&#22411;&#65307;&#20195;&#20215;&#21017;&#26159;&#36825;&#37096;&#20998;&#20869;&#23481;&#26080;&#27861;&#21442;&#19982; SwiftData &#30340; predicate&#12289;sort &#21644; migration &#24863;&#30693;&#12290;&#27491;&#22240;&#22914;&#27492;&#65292;&#23427;&#30340;&#20215;&#20540;&#19981;&#22312;&#20110;&#8220;&#26356;&#24378;&#8221;&#65292;&#32780;&#22312;&#20110;&#8220;&#26356;&#26126;&#30830;&#8221;&#12290;</p><p>&#19981;&#36807;&#65292;SwiftData &#20173;&#27809;&#26377;&#25552;&#20379; public / shared &#25968;&#25454;&#30340;&#20113;&#31471;&#21516;&#27493;&#33021;&#21147;&#65292;&#20063;&#27809;&#26377;&#30475;&#21040;&#26356;&#26126;&#30830;&#30340;&#24615;&#33021;&#25913;&#21892;&#20449;&#21495;&#12290;&#36825;&#20123;&#38382;&#39064;&#20173;&#20250;&#38480;&#21046;&#23427;&#30340;&#37319;&#32435;&#29575;&#12290;&#23545;&#35768;&#22810;&#24320;&#21457;&#32773;&#26469;&#35828;&#65292;SwiftData &#20170;&#24180;&#26356;&#20687;&#26159;&#22312;&#34917;&#40784;&#20851;&#38190;&#32570;&#21475;&#65292;&#32780;&#19981;&#26159;&#23436;&#25104;&#19968;&#27425;&#36275;&#20197;&#25913;&#21464;&#20449;&#24515;&#30340;&#36291;&#36801;&#12290;</p><p><strong>Xcode</strong></p><p>&#36807;&#21435;&#21322;&#24180;&#20013;&#65292;&#25105;&#30340;&#24320;&#21457;&#27169;&#24335;&#22522;&#26412;&#26159; Codex App / Claude App + Xcode&#65292;&#20854;&#20013; Xcode &#30340;&#20986;&#22330;&#26102;&#38388;&#26126;&#26174;&#23569;&#20110;&#21069;&#20004;&#32773;&#12290;&#22312;&#31616;&#21333;&#20351;&#29992; Xcode 27 &#21518;&#65292;&#25105;&#39044;&#35745;&#25509;&#19979;&#26469;&#23427;&#30340;&#20986;&#22330;&#26102;&#38388;&#20250;&#26126;&#26174;&#22686;&#21152;&#12290;&#25105;&#23588;&#20854;&#26399;&#24453;&#22312; UI &#31934;&#32454;&#35843;&#25972;&#12289;&#24615;&#33021;&#25913;&#21892;&#12289;&#39044;&#35272;&#39564;&#35777;&#31561;&#26041;&#38754;&#65292;Xcode &#20869;&#32622; AI &#27969;&#31243;&#33021;&#24102;&#26469;&#30340;&#21464;&#21270;&#12290;</p><p>Device Hub &#26080;&#30097;&#26159;&#19968;&#20010;&#24040;&#22823;&#24778;&#21916;&#12290;&#23427;&#23558;&#27169;&#25311;&#22120;&#12289;&#23454;&#20307;&#35774;&#22791;&#31649;&#29702;&#12289;&#31995;&#32479;&#29366;&#24577;&#27979;&#35797;&#21644;&#21160;&#24577;&#23610;&#23544;&#35843;&#25972;&#25972;&#21512;&#21040;&#19968;&#20010;&#26032;&#30340;&#24037;&#20316;&#27969;&#20013;&#65292;&#36825;&#23545;&#26085;&#24120;&#24320;&#21457;&#20307;&#39564;&#30340;&#24433;&#21709;&#21487;&#33021;&#27604;&#24456;&#22810;&#21333;&#20010; API &#26356;&#30452;&#25509;&#12290;&#19981;&#36807;&#65292;iPhone &#24212;&#29992;&#20063;&#24320;&#22987;&#25903;&#25345;&#21160;&#24577;&#23610;&#23544;&#35843;&#25972;&#65292;&#36825;&#20250;&#32473;&#24320;&#21457;&#32773;&#24102;&#26469;&#26032;&#30340;&#25361;&#25112;&#65292;&#23588;&#20854;&#26159;&#22312;&#25968;&#25454;&#21644;&#29366;&#24577;&#32452;&#32455;&#23618;&#38754;&#12290;&#38024;&#23545;&#19981;&#21516;&#23610;&#23544;&#30340;&#36866;&#37197;&#65292;&#24182;&#19981;&#26159;&#21482;&#38752;&#21160;&#24577;&#24067;&#23616;&#23481;&#22120;&#23601;&#33021;&#35299;&#20915;&#30340;&#12290;&#24456;&#22810;&#22330;&#26223;&#19979;&#65292;&#22823;&#23610;&#23544;&#21644;&#23567;&#23610;&#23544;&#23545;&#24212;&#30340;&#23548;&#33322;&#36923;&#36753;&#20250;&#26377;&#24456;&#22823;&#24046;&#24322;&#12290;</p><div><hr></div><p>&#20170;&#24180;&#25105;&#24212;&#35813;&#19981;&#20250;&#31532;&#19968;&#26102;&#38388;&#22260;&#32469; SwiftUI&#12289;SwiftData &#30340;&#26032; API &#20889;&#25991;&#31456;&#12290;&#30456;&#27604;&#36880;&#26465;&#20171;&#32461;&#26032;&#22686;&#25509;&#21475;&#65292;&#25105;&#26356;&#24819;&#33457;&#19968;&#20123;&#26102;&#38388;&#31995;&#32479;&#28040;&#21270;&#36825;&#20123;&#21464;&#21270;&#65292;&#26803;&#29702;&#23427;&#20204;&#32972;&#21518;&#30340;&#38544;&#21547;&#36923;&#36753;&#65306;Apple &#27491;&#22312;&#24590;&#26679;&#37325;&#26032;&#32452;&#32455; SwiftUI&#12289;SwiftData&#12289;Foundation Models &#19982; Xcode AI &#24037;&#20316;&#27969;&#20043;&#38388;&#30340;&#20851;&#31995;&#65292;&#20197;&#21450;&#36825;&#20123;&#21464;&#21270;&#26368;&#32456;&#20250;&#22914;&#20309;&#24433;&#21709;&#25105;&#20204;&#26500;&#24314; App &#30340;&#26041;&#24335;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-138/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/core-data-observation-freer-mental-model/?utm_source=fatbobman%20weekly%20issue%20139&amp;utm_medium=web">Core Data + Observation&#65306;&#20174;&#23646;&#24615;&#32423;&#21709;&#24212;&#21040;&#24515;&#26234;&#35299;&#25918;</a></strong></h3><p>Observation &#26694;&#26550;&#30340;&#25512;&#20986;&#65292;&#35753; SwiftUI &#30340;&#29366;&#24577;&#21709;&#24212;&#20174;&#23545;&#35937;&#32423;&#36827;&#19968;&#27493;&#32454;&#21270;&#21040;&#23646;&#24615;&#32423;&#65292;&#26174;&#33879;&#32531;&#35299;&#20102;&#35768;&#22810;&#30001;&#31895;&#31890;&#24230;&#35266;&#23519;&#24102;&#26469;&#30340;&#26080;&#25928;&#21047;&#26032;&#38382;&#39064;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#23427;&#35753;&#29366;&#24577;&#31649;&#29702;&#30340;&#22768;&#26126;&#24335;&#36923;&#36753;&#37325;&#26032;&#21464;&#24471;&#33258;&#28982;&#65306;&#35270;&#22270;&#21482;&#38656;&#35201;&#35835;&#21462;&#33258;&#24049;&#30495;&#27491;&#20381;&#36182;&#30340;&#23646;&#24615;&#65292;&#26694;&#26550;&#20415;&#33021;&#25454;&#27492;&#24314;&#31435;&#21709;&#24212;&#20851;&#31995;&#12290;&#20026;&#20102;&#35753; Core Data &#36825;&#20010;&#32769;&#29260;&#25345;&#20037;&#21270;&#26694;&#26550;&#20063;&#33021;&#20139;&#21463;&#21040;&#29616;&#20195; Swift &#29305;&#24615;&#30340;&#20415;&#21033;&#65292;&#25105;&#36817;&#26399;&#22312; <a href="https://fatbobman.com/zh/posts/cde-an-attempt-to-make-core-data-feel-more-like-modern-swift/">Core Data Evolution</a>&#65288;CDE&#65289;&#20013;&#25506;&#32034;&#24182;&#23454;&#29616;&#20102;&#23545; Observation &#30340;&#25903;&#25345;&#65292;&#36171;&#20104; <code>NSManagedObject</code> &#23646;&#24615;&#32423;&#30340;&#31934;&#30830;&#35266;&#23519;&#33021;&#21147;&#12290;&#26412;&#25991;&#23558;&#22260;&#32469;&#36825;&#19968;&#33021;&#21147;&#30340;&#21160;&#22240;&#12289;&#20351;&#29992;&#26041;&#24335;&#12289;&#23454;&#29616;&#24605;&#36335;&#12289;&#24037;&#31243;&#25361;&#25112;&#20197;&#21450;&#24320;&#21457;&#36807;&#31243;&#20013;&#30340;&#19968;&#20123;&#21462;&#33293;&#23637;&#24320;&#35752;&#35770;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-01">&#29992; Swift &#21644; WebAssembly &#25226; Goodnotes &#24102;&#21040; Web (Bringing Goodnotes to the web with Swift and WebAssembly)</a></strong></h3><p>&#20316;&#20026;&#33529;&#26524;&#29983;&#24577;&#20013;&#33879;&#21517;&#30340;&#31508;&#35760;&#24212;&#29992;&#65292;Goodnotes &#22312;&#36208;&#21521; Web &#24179;&#21488;&#26102;&#65292;&#24182;&#27809;&#26377;&#36873;&#25321;&#23436;&#20840;&#37325;&#20889;&#65292;&#32780;&#26159;&#25226;&#22810;&#24180;&#31215;&#32047;&#30340; Swift &#20195;&#30721;&#36890;&#36807; WebAssembly &#24102;&#21040;&#27983;&#35272;&#22120;&#29615;&#22659;&#37324;&#12290;<a href="https://x.com/kateinoigakukun">Yuta Saito</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#20102; Goodnotes &#22914;&#20309;&#22312; Web &#31471;&#20445;&#25345;&#19982;&#21407;&#29983; App &#19968;&#33268;&#30340;&#22696;&#36857;&#28210;&#26579;&#12289;&#25991;&#26723;&#21516;&#27493;&#12289;CRDT &#20914;&#31361;&#22788;&#29702;&#12289;&#25628;&#32034;&#32034;&#24341;&#19982;&#20132;&#20114;&#20307;&#39564;&#12290;Goodnotes Web &#30340; Swift &#20195;&#30721;&#35268;&#27169;&#32422; 220 &#19975;&#34892;&#65292;&#20854;&#20013; 147 &#19975;&#34892;&#26159;&#20849;&#20139;&#20195;&#30721;&#65307;&#26368;&#32456;&#29983;&#25104;&#30340; WebAssembly &#20108;&#36827;&#21046;&#32422; 50 MB&#65292;&#32463; Brotli &#21387;&#32553;&#21518;&#32422; 12 MB&#12290;&#36825;&#31687;&#25991;&#31456;&#30340;&#24847;&#20041;&#19981;&#21482;&#26159;&#23637;&#31034; Swift &#21487;&#20197;&#36816;&#34892;&#22312; Web &#19978;&#65292;&#32780;&#26159;&#21576;&#29616;&#20102;&#19968;&#20010;&#30495;&#23454;&#30340;&#22823;&#22411; Swift &#24212;&#29992;&#22914;&#20309;&#20511;&#21161; WebAssembly&#65292;&#25226;&#21407;&#26412;&#28145;&#26893;&#20110;&#33529;&#26524;&#24179;&#21488;&#30340;&#26680;&#24515;&#33021;&#21147;&#24310;&#23637;&#21040;&#26356;&#22810;&#24179;&#21488;&#12290;</p><blockquote><p>Yuta &#22312; iOS Conf 2026 &#30340;&#28436;&#35762; <a href="https://www.youtube.com/watch?v=ysD4_qqd-po">Swift at Scale: Where Performance Really Comes From</a> &#20063;&#24456;&#20540;&#24471;&#35266;&#30475;&#12290;&#30456;&#27604;&#23448;&#26041;&#25991;&#31456;&#23545; Goodnotes Web &#25972;&#20307;&#26550;&#26500;&#30340;&#20171;&#32461;&#65292;&#36825;&#22330;&#28436;&#35762;&#26356;&#32858;&#28966;&#19968;&#20010;&#30495;&#23454;&#30340; Swift &#24615;&#33021;&#26696;&#20363;&#65306;Goodnotes &#22242;&#38431;&#21457;&#29616;&#65292;&#19968;&#20010;&#29992;&#20110;&#32858;&#21512; UI &#23616;&#37096;&#26356;&#26032;&#30340; Update &#20540;&#31867;&#22411;&#38543;&#30528;&#21151;&#33021;&#22686;&#38271;&#33192;&#32960;&#21040;&#32422; 6 KB&#65292;&#24182;&#21253;&#21547;&#22823;&#37327; non-trivial &#25104;&#21592;&#12290;&#21363;&#20351;&#22823;&#22810;&#25968;&#26356;&#26032;&#21482;&#20351;&#29992;&#19968;&#20004;&#20010;&#23383;&#27573;&#65292;&#28909;&#36335;&#24452;&#20013;&#20173;&#35201;&#20026;&#22797;&#21046;&#21644;&#24341;&#29992;&#35745;&#25968;&#25104;&#26412;&#20184;&#36153;&#12290;&#22242;&#38431;&#26368;&#32456;&#36890;&#36807; hot-cold split &#37325;&#26500;&#25968;&#25454;&#32467;&#26500;&#65292;&#23558;&#39640;&#39057;&#23383;&#27573;&#20445;&#30041;&#22312;&#20027;&#32467;&#26500;&#20307;&#20013;&#65292;&#25226;&#20302;&#39057;&#26356;&#26032;&#31227;&#20837;&#21333;&#29420;&#23384;&#20648;&#65292;&#20351;&#31867;&#22411;&#22823;&#23567;&#20174;&#32422; 6 KB &#38477;&#21040;&#32422; 300 bytes&#65292;&#24182;&#24102;&#26469;&#32422; 42% &#30340; CPU &#26102;&#38388;&#25913;&#21892;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-02">Swift &#23448;&#26041;&#25104;&#31435;&#32593;&#32476;&#24037;&#20316;&#32452; (Announcing the Networking Workgroup)</a></strong></h3><p>Swift &#29616;&#22312;&#30340;&#32593;&#32476; API &#24182;&#19981;&#26159;&#32570;&#23569;&#36873;&#25321;&#65292;&#32780;&#26159;&#36873;&#25321;&#36807;&#22810;&#19988;&#23384;&#22312;&#37325;&#21472;&#65306;&#20174; Apple &#24179;&#21488;&#19978;&#30340; URLSession&#12289;Network.framework&#65292;&#21040;&#26381;&#21153;&#31471;&#29983;&#24577;&#20013;&#30340; SwiftNIO&#12289;AsyncHTTPClient&#65292;&#20877;&#21040;&#26356;&#24213;&#23618;&#30340; HTTP &#34920;&#31034;&#31867;&#22411;&#65292;&#24320;&#21457;&#32773;&#22312;&#19981;&#21516;&#24179;&#21488;&#12289;&#19981;&#21516;&#25277;&#35937;&#23618;&#20043;&#38388;&#24448;&#24448;&#38656;&#35201;&#38754;&#23545;&#19981;&#19968;&#33268;&#30340;&#27169;&#22411;&#21644;&#36801;&#31227;&#25104;&#26412;&#12290;&#26356;&#37325;&#35201;&#30340;&#26159;&#65292;&#24456;&#22810; API &#20986;&#29616;&#20110; async/await&#12289;structured concurrency&#12289;actors&#12289;Sendable &#31561;&#29616;&#20195; Swift &#33021;&#21147;&#25104;&#29087;&#20043;&#21069;&#65292;&#22240;&#27492;&#24456;&#38590;&#33258;&#28982;&#22320;&#20307;&#29616;&#20170;&#22825; Swift &#22312;&#24182;&#21457;&#12289;&#23433;&#20840;&#24615;&#21644;&#36328;&#24179;&#21488;&#26041;&#38754;&#30340;&#35821;&#35328;&#20248;&#21183;&#12290;&#36825;&#20123;&#38382;&#39064;&#22312; <a href="https://github.com/swiftlang/swift-evolution/blob/main/visions/networking.md">A Vision for Networking in Swift</a> &#20013;&#26377;&#26356;&#31995;&#32479;&#30340;&#38416;&#36848;&#65292;&#32780; <a href="https://github.com/apple/swift-http-api-proposal">Swift HTTP API Proposal</a> &#21017;&#21487;&#20197;&#30475;&#20316;&#26159;&#23545;&#36825;&#19968;&#26041;&#21521;&#30340;&#26089;&#26399;&#25506;&#32034;&#12290;</p><p>&#26412;&#27425; Swift &#23448;&#26041;&#25104;&#31435; Networking Workgroup&#65292;&#37322;&#25918;&#20102;&#19968;&#20010;&#24456;&#37325;&#35201;&#30340;&#20449;&#21495;&#65306;Swift &#29983;&#24577;&#24320;&#22987;&#25226;&#32593;&#32476;&#33021;&#21147;&#20316;&#20026;&#19968;&#39033;&#38656;&#35201;&#38271;&#26399;&#27835;&#29702;&#30340;&#36328;&#24179;&#21488;&#22522;&#30784;&#35774;&#26045;&#26469;&#25512;&#36827;&#65292;&#32780;&#19981;&#21482;&#26159;&#35753;&#21508;&#20010;&#26694;&#26550;&#21644;&#21253;&#22312;&#21508;&#33258;&#22330;&#26223;&#20013;&#29420;&#31435;&#28436;&#36827;&#12290;&#24037;&#20316;&#32452;&#30340;&#30446;&#26631;&#19981;&#26159;&#31616;&#21333;&#26367;&#20195;&#29616;&#26377;&#26041;&#26696;&#65292;&#32780;&#26159;&#25512;&#21160;&#26356;&#28165;&#26224;&#30340;&#20998;&#23618;&#12289;&#26356;&#19968;&#33268;&#30340;&#31867;&#22411;&#12289;&#26356;&#22909;&#30340;&#20114;&#25805;&#20316;&#24615;&#21644;&#21487;&#35266;&#27979;&#24615;&#65292;&#35753; Swift &#22312; Apple &#24179;&#21488;&#12289;&#26381;&#21153;&#31471;&#12289;CLI&#12289;WebAssembly&#12289;Android&#12289;Windows &#20035;&#33267; Embedded Swift &#31561;&#22330;&#26223;&#20013;&#65292;&#37117;&#33021;&#25317;&#26377;&#26356;&#32479;&#19968;&#12289;&#29616;&#20195;&#19988;&#21487;&#25345;&#32493;&#30340;&#32593;&#32476;&#22522;&#30784;&#35774;&#26045;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-03">WWDC 26 &#24895;&#26395;&#21333;&#27719;&#24635; (WWDC 2026 Wish Lists)</a></strong></h3><p><a href="https://x.com/mjtsai">Michael Tsai</a> &#27719;&#24635;&#20102;&#22810;&#20301; Apple &#24320;&#21457;&#32773;&#22312; WWDC 2026 &#21069;&#30340;&#24895;&#26395;&#28165;&#21333;&#12290;&#21644;&#25105;&#22312; <a href="https://fatbobman.com/zh/weekly/issue-138/">&#19978;&#19968;&#26399;&#21608;&#25253;</a> &#20013;&#30340;&#26399;&#35768;&#31867;&#20284;&#65292;&#22823;&#22810;&#24320;&#21457;&#32773;&#22312;&#21628;&#21505;&#19968;&#27425;&#20559;&#21521; Snow Leopard &#24335;&#30340;&#36136;&#37327;&#20462;&#22797;&#65306;&#37325;&#26032;&#23457;&#35270; Liquid Glass &#22312; Mac &#19978;&#30340;&#21487;&#29992;&#24615;&#65292;&#20943;&#23569;&#31995;&#32479;&#21644;&#26694;&#26550;&#23618;&#38754;&#30340;&#19981;&#31283;&#23450;&#65292;&#20462;&#22797; iCloud &#21516;&#27493;&#12289;Spotlight&#12289;&#31995;&#32479;&#35774;&#32622;&#12289;&#38169;&#35823;&#25552;&#31034;&#12289;SwiftUI&#12289;Xcode&#12289;Simulator&#12289;&#32034;&#24341;&#21644;&#39044;&#35272;&#31561;&#38271;&#26399;&#24433;&#21709;&#26085;&#24120;&#24320;&#21457;&#20307;&#39564;&#30340;&#38382;&#39064;&#12290;&#20063;&#26377;&#19981;&#23569;&#24320;&#21457;&#32773;&#24076;&#26395;&#20170;&#24180;&#19981;&#35201;&#20877;&#24341;&#20837;&#22823;&#37327;&#20026;&#20102;&#36866;&#37197;&#26032;&#35774;&#35745;&#12289;&#26032;&#26694;&#26550;&#25110;&#26032;&#23457;&#26680;&#35201;&#27714;&#32780;&#20135;&#29983;&#30340;&#8220;&#24537;&#30860;&#24037;&#20316;&#8221;&#65292;&#32780;&#26159;&#32473;&#29616;&#26377;&#24179;&#21488;&#26356;&#22810;&#25171;&#30952;&#26102;&#38388;&#12290;</p><p>&#21478;&#19968;&#20010;&#26126;&#26174;&#20027;&#39064;&#26159; AI Agent &#26102;&#20195;&#19979;&#30340; Apple &#24320;&#21457;&#24037;&#20855;&#24212;&#35813;&#22914;&#20309;&#28436;&#36827;&#12290;&#22810;&#20301;&#20316;&#32773;&#37117;&#25552;&#21040;&#65292;&#24076;&#26395; Apple &#25552;&#20379;&#26356;&#23448;&#26041;&#30340; Agent Skills&#12289;MCP&#12289;CLI &#21644;&#21487;&#33258;&#21160;&#21270;&#25509;&#21475;&#65292;&#35753; AI &#33021;&#26356;&#21487;&#38752;&#22320;&#35835;&#21462;&#25991;&#26723;&#12289;&#25805;&#20316; Xcode&#12289;&#31649;&#29702; App Store Connect&#12289;&#20462;&#25913;&#39033;&#30446;&#37197;&#32622;&#12289;&#36816;&#34892;&#26500;&#24314;&#12289;&#25511;&#21046; Simulator&#65292;&#29978;&#33267;&#20197;&#26356;&#32467;&#26500;&#21270;&#30340;&#26041;&#24335;&#29702;&#35299; UI &#23618;&#32423;&#65292;&#32780;&#19981;&#26159;&#20381;&#36182;&#25130;&#22270;&#25110;&#33030;&#24369;&#30340; Accessibility &#20449;&#24687;&#12290;</p><blockquote><p>&#19982; AI &#26102;&#20195;&#30340;&#36866;&#37197;&#21644;&#31995;&#32479;&#31283;&#23450;&#24615;&#65292;&#30830;&#23454;&#27491;&#22312;&#25104;&#20026;&#26356;&#22810; Apple &#24320;&#21457;&#32773;&#30340;&#20849;&#21516;&#26399;&#24453;&#12290;&#30475;&#21040;&#26412;&#26399;&#21608;&#25253;&#26102;&#65292;WWDC 2026 &#24050;&#32463;&#24320;&#24149;&#65292;&#19981;&#30693;&#36947;&#35835;&#23436;&#36825;&#20123;&#24895;&#26395;&#20877;&#30475;&#20170;&#24180;&#30340;&#21457;&#24067;&#20250;&#65292;&#22823;&#23478;&#26159;&#21542;&#25214;&#21040;&#20102;&#24515;&#20013;&#26399;&#24453;&#30340;&#31572;&#26696;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-04">Apple-like</a></strong></h3><p>&#22312; WWDC 2026 &#21069;&#21518;&#65292;&#22260;&#32469; Apple &#26410;&#26469;&#26041;&#21521;&#30340;&#35752;&#35770;&#26126;&#26174;&#22686;&#22810;&#12290;&#24456;&#22810;&#20154;&#26399;&#24453; Apple &#8220;&#22238;&#21040;&#26681;&#26412;&#8221;&#25110;&#37325;&#26032;&#25214;&#22238;&#36807;&#21435;&#30340;&#29366;&#24577;&#65292;&#20294; <a href="https://mastodon.social/@_Davidsmith">David Smith</a> &#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#36873;&#25321;&#20102;&#19968;&#20010;&#26356;&#26377;&#24314;&#35774;&#24615;&#30340;&#38382;&#39064;&#65306;&#20160;&#20040;&#25165;&#26159; Apple-like&#65311;&#20316;&#20026;&#19968;&#21517;&#38271;&#26399;&#30340; Apple &#24179;&#21488;&#24320;&#21457;&#32773;&#65292;&#20182;&#23558;&#36825;&#31181;&#27668;&#36136;&#24635;&#32467;&#20026;&#20960;&#20010;&#26041;&#21521;&#65306;The Best, and then Better&#65292;Excellence for Everyone&#65292;&#20197;&#21450; Beneficial and Brilliant&#12290;&#20063;&#23601;&#26159;&#25345;&#32493;&#36861;&#27714;&#39640;&#36136;&#37327;&#65292;&#21363;&#20351;&#24050;&#32463;&#39046;&#20808;&#20063;&#19981;&#33021;&#28040;&#32791;&#29992;&#25143;&#26399;&#24453;&#65307;&#22312;&#20215;&#26684;&#12289;&#21487;&#35775;&#38382;&#24615;&#21644;&#35774;&#35745;&#19978;&#35753;&#20248;&#31168;&#20307;&#39564;&#23613;&#21487;&#33021;&#26381;&#21153;&#26356;&#22810;&#20154;&#65307;&#24182;&#19988;&#36991;&#20813;&#29992;&#25805;&#32437;&#24615;&#30340;&#26041;&#24335;&#36861;&#36880;&#30701;&#26399;&#25351;&#26631;&#65292;&#32780;&#26159;&#29992;&#30495;&#27491;&#26377;&#30410;&#12289;&#20196;&#20154;&#24778;&#21916;&#30340;&#26041;&#24335;&#35299;&#20915;&#29992;&#25143;&#30340;&#38382;&#39064;&#12290;</p><blockquote><p>&#24403;&#25105;&#20204;&#26399;&#24453; Apple &#25913;&#21892;&#31995;&#32479;&#31283;&#23450;&#24615;&#12289;&#24320;&#21457;&#24037;&#20855;&#21644;&#24179;&#21488;&#20307;&#39564;&#26102;&#65292;&#36825;&#31687;&#25991;&#31456;&#20063;&#25552;&#37266;&#25105;&#20204;&#65292;&#29420;&#31435;&#24320;&#21457;&#32773;&#21644;&#24212;&#29992;&#22242;&#38431;&#21516;&#26679;&#21487;&#20197;&#29992;&#31867;&#20284;&#30340;&#26631;&#20934;&#23457;&#35270;&#33258;&#24049;&#30340;&#20135;&#21697;&#12290;</p></blockquote><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0139-05">MarkdownPDF&#65306;&#32431; Swift &#32534;&#20889;&#30340; Markdown &#36716; PDF &#24341;&#25806;</a></strong></h3><p>MarkdownPDF &#26159; <a href="https://www.linkedin.com/in/mihaelamj">Mihaela Mihaljevi&#263;</a> &#24320;&#28304;&#30340;&#32431; Swift Markdown &#36716; PDF &#24341;&#25806;&#12290;&#23427;&#19981;&#20381;&#36182; PDFKit&#12289;CoreGraphics&#12289;WebKit&#12289;Chromium&#12289;LaTeX&#12289;C PDF/Markdown &#24211;&#31561;&#24179;&#21488;&#25110;&#31995;&#32479;&#33021;&#21147;&#65292;Markdown &#35299;&#26512;&#12289;&#25490;&#29256;&#19982; PDF &#24207;&#21015;&#21270;&#37117;&#22312; Swift &#20869;&#23436;&#25104;&#12290;&#27491;&#22240;&#20026;&#26680;&#24515;&#36275;&#22815;&#32431;&#20928;&#12289;&#20381;&#36182;&#36275;&#22815;&#20811;&#21046;&#65292;&#39033;&#30446;&#20855;&#22791;&#33391;&#22909;&#30340;&#36328;&#24179;&#21488;&#28508;&#21147;&#65292;&#21487;&#20197;&#36866;&#37197;&#21040; WebAssembly/WASI &#36816;&#34892;&#30446;&#26631;&#65292;&#24182;&#22312;&#27983;&#35272;&#22120;&#26412;&#22320;&#23436;&#25104; Markdown &#21040; PDF &#30340;&#29983;&#25104;&#12290;&#20316;&#32773;&#25552;&#20379;&#30340; <a href="https://pdf.aleahim.com/">Playground</a> &#27491;&#26159;&#36825;&#19968;&#33021;&#21147;&#30340;&#28436;&#31034;&#12290;</p><blockquote><p>Goodnotes &#23637;&#31034;&#30340;&#26159;&#22823;&#22411; Swift &#24212;&#29992;&#36801;&#31227;&#21040; Web &#30340;&#24037;&#31243;&#23454;&#36341;&#65292;MarkdownPDF &#21017;&#25552;&#20379;&#20102;&#21478;&#19968;&#20010;&#35282;&#24230;&#65306;&#24403;&#26680;&#24515;&#36923;&#36753;&#36275;&#22815;&#32431;&#20928;&#12289;&#20381;&#36182;&#36275;&#22815;&#20811;&#21046;&#26102;&#65292;Swift &#24037;&#20855;&#26412;&#36523;&#20063;&#21487;&#20197;&#33258;&#28982;&#36866;&#37197;&#21040; WebAssembly &#36816;&#34892;&#29615;&#22659;&#12290;Swift &#36208;&#21521; Web&#65292;&#27491;&#22312;&#20174;&#27010;&#24565;&#39564;&#35777;&#21464;&#25104;&#36234;&#26469;&#36234;&#20855;&#20307;&#30340;&#24037;&#31243;&#36873;&#25321;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0139-06">AdaEngine&#65306;Swift-first &#24320;&#28304;&#28216;&#25103;&#24341;&#25806;</a></strong></h3><p>AdaEngine &#26159; <a href="https://x.com/SpectralDragon_">Vladislav Prusakov</a> &#25512;&#20986;&#30340;&#24320;&#28304; Swift-first &#28216;&#25103;&#24341;&#25806;&#19982;&#24212;&#29992;&#26694;&#26550;&#65292;&#36817;&#26399;&#21457;&#24067;&#20102;&#31532;&#19968;&#20010;&#20844;&#24320;&#37324;&#31243;&#30865; 0.1.0&#12290;&#39033;&#30446;&#38754;&#21521;&#36328;&#24179;&#21488;&#32780;&#35774;&#35745;&#65292;&#30446;&#21069; Apple &#24179;&#21488;&#26368;&#25104;&#29087;&#65292;&#24182;&#27491;&#22312;&#25512;&#36827; Windows&#12289;Linux&#12289;Android &#19982; WebAssembly/WebGPU &#31561;&#24179;&#21488;&#25903;&#25345;&#12290;</p><p>&#23427;&#20197; data-driven ECS &#20026;&#26680;&#24515;&#65292;&#32467;&#21512; Swift &#23439;&#12289;&#25554;&#20214;&#21270;&#26550;&#26500;&#12289;&#31867; SwiftUI &#30340; AdaUI&#12289;&#36164;&#20135;&#28909;&#37325;&#36733;&#12289;&#22330;&#26223;&#31995;&#32479;&#12289;2D &#29289;&#29702;&#12289;&#38899;&#39057;&#12289;&#36755;&#20837;&#65292;&#20197;&#21450; Metal / WebGPU &#28210;&#26579;&#21518;&#31471;&#31561;&#33021;&#21147;&#65292;&#35797;&#22270;&#35753; Swift &#19981;&#21482;&#26381;&#21153;&#20110; Apple &#24179;&#21488;&#24212;&#29992;&#65292;&#20063;&#33021;&#36827;&#20837;&#28216;&#25103;&#12289;&#20114;&#21160;&#24037;&#20855;&#19982;&#21019;&#24847;&#36719;&#20214;&#24320;&#21457;&#22330;&#26223;&#12290;</p><blockquote><p>Vladislav &#22312; <a href="https://adaengine.org/articles/introducing-adaengine-0-1-0">Introducing AdaEngine 0.1.0</a> &#19968;&#25991;&#20013;&#23545;&#39033;&#30446;&#20570;&#20102;&#26356;&#23436;&#25972;&#30340;&#20171;&#32461;&#12290;</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Fatbobman's Swift Weekly #138]]></title><description><![CDATA[Stability > New Features]]></description><link>https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138</link><guid isPermaLink="false">https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138</guid><dc:creator><![CDATA[Fatbobman(东坡肘子)]]></dc:creator><pubDate>Mon, 01 Jun 2026 12:04:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!eZJ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eZJ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 424w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 848w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1272w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp" width="1456" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112960,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://weekly.fatbobman.com/i/200084313?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eZJ4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 424w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 848w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1272w, https://substackcdn.com/image/fetch/$s_!eZJ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44043495-65d0-488d-b189-566c095d8b3a_1919x1045.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@scottkelley?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Scott Kelley</a> on <a href="https://unsplash.com/photos/silhouette-of-stones-on-beach-during-sunset-ie0Hk-btBvw?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure></div><h2><strong>Stability &gt; New Features</strong></h2><p><a href="https://fatbobman.com/en/weekly/issue-138/">Read on web &#8594;</a></p><p>Whether it is SwiftUI or SwiftData, these foundational frameworks, into which Apple poured so much hope, promised a bright future when they were first introduced. However, their actual trajectory seems to have diverged from the original blueprint. The deeper I dive into these frameworks, the more I marvel at their elegant architectural design&#8212;yet I also find myself speechless at their underwhelming implementation. Watching the halo around these designs gradually fade, I cannot help but feel a sense of wistfulness.</p><p>Rumor has it that in the upcoming operating systems to be released this year (including iOS 27 and macOS 27), Apple will adopt a refinement strategy similar to the Mac OS X Snow Leopard era. This means prioritizing system stability, performance optimization, clearing legacy code, and squashing bugs over introducing disruptive visual redesigns or a flurry of new low-level features. If this indeed turns out to be the case, it would be deeply reassuring. Looking back at <a href="https://fatbobman.com/en/weekly/issue-006/">Issue #006</a> of the weekly newsletter published more than two years ago, rumors also circulated back then that Apple would focus on fixing existing defects and improving performance. Yet, judging by the actual user experience over the past two years, that goal seems to have fallen short.</p><p>With WWDC 26 less than ten days away, rather than more flashy new features, what I look forward to most this year is Apple delivering a grounded, more stable experience for both developers and consumers.</p><p><a href="https://fatbobman.com/en/weekly/issue-137/">Previous Issue</a>&#65372;<a href="https://fatbobman.com/en/weekly/">Newsletter Archive</a></p><div><hr></div><h2>&#128226; <strong><a href="https://fatbobman.com/en/sponsorship/">Sponsor Fatbobman&#8217;s Swift Weekly</a></strong></h2><p>Promote your product to Swift &amp; iOS developers across:</p><p>- Blog: <strong>50,000</strong>+ monthly visitors<br>- Newsletter: <strong>4,000</strong>+ subscribers, <strong>53</strong>% open rate </p><p>Perfect for developer tools, courses, and services.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://fatbobman.com/en/sponsorship/&quot;,&quot;text&quot;:&quot;&#128226; View Sponsorship Options&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://fatbobman.com/en/sponsorship/"><span>&#128226; View Sponsorship Options</span></a></p><p>Enjoyed this issue? <strong><a href="https://buymeacoffee.com/fatbobman">Buy me a coffee </a></strong><a href="https://buymeacoffee.com/fatbobman">&#9749;&#65039;</a></p><div><hr></div><h2><strong>Original</strong></h2><h3><strong><a href="https://fatbobman.com/en/posts/taming-row-height-and-spacing-jumps/?utm_source=fatbobman%20weekly%20issue%20138&amp;utm_medium=web">Taming Row Height and Spacing Jumps in SwiftUI List with a Custom Layout</a></strong></h3><p>In SwiftUI, adding animation to view state changes often takes very little code, but <code>List</code> does not always produce the kind of smooth transition we expect. This is especially noticeable when the height of content inside a row changes dynamically&#8212;for example, when a subtitle goes from empty to non-empty, or when updated text changes its line count. In these cases, the system&#8217;s default layout process can easily cause the row height to jump abruptly, leading to visible flickering, clipping, or sudden spacing changes. Starting from this common issue, this article gradually breaks down why dynamic row-height animations fail in <code>List</code>, and builds a solution entirely based on native SwiftUI capabilities through custom <code>Layout</code>, <code>Animatable</code>, <code>LayoutValueKey</code>, and state decoupling.</p><p>This is not an article primarily aimed at providing a ready-to-use component. Rather than focusing only on the final code, I hope to use this problem to outline a way of investigating SwiftUI layout issues: first understand why the framework &#8220;does not behave as expected,&#8221; then reorganize state, measurement, and layout along the grain of its mechanisms, so that the animation happens at the correct level.</p><h2><strong>Recent Recommendations</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-01">Stateless Actors</a></strong></h3><p>Actors are usually understood as tools for protecting mutable state, so an actor with no stored properties&#8212;a seemingly stateless actor&#8212;naturally raises the question: does it have any reason to exist? This article explores that question through examples such as <code>NetworkClient</code>, custom global actors, custom executors, and file-system access. It shows that stateless actors are not necessarily unreasonable, but they may introduce extra costs such as serialization, protocol-adaptation difficulties, and type-system propagation. The key question is what problem they are actually solving.</p><p>The most important point in the article is the &#8220;first rule of actors&#8221; proposed by <a href="https://mastodon.social/@mattiem">Matt Massicotte</a>: just like with any synchronization primitive, before using an actor, you should be able to clearly explain why it is necessary. A stateless actor is not necessarily wrong, but it may indicate that we are using an actor to solve a problem that does not actually require one. Only when it clearly takes on responsibilities such as isolation, serialization, executor adaptation, or protection of external state does it become a reasonable design.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-02">Building a Custom Data Store in SwiftData</a></strong></h3><p>Many developers tend to think of SwiftData as Apple&#8217;s high-level wrapper around SQLite, but that underestimates its potential as a framework for object-graph management and persistence coordination. Whether we are talking about SwiftData or Core Data, their more important capability is not merely reading and writing a database for us, but keeping model objects, queries, context management, and the underlying storage clearly separated. As long as the underlying storage can exchange data in the way the framework expects, the data source does not have to be SQLite.</p><p><a href="https://x.com/azamsharp">Mohammad Azam</a> demonstrates this by implementing a JSON-file-based custom data store. The article shows that what SwiftData exchanges with the underlying store is not the live object marked with <code>@Model</code>, but a converted snapshot. Once you understand this, the responsibility boundaries of <code>DataStoreConfiguration</code>, <code>DataStore</code>, <code>DefaultSnapshot</code>, <code>PersistentIdentifier</code>, and <code>fetch</code> / <code>save</code> become much clearer: SwiftData is responsible for model objects, observation, change tracking, and SwiftUI integration, while the custom store is only responsible for reading and writing snapshots.</p><blockquote><p>In <a href="https://fatbobman.com/en/weekly/issue-127/#datastorekit">Weekly Issue #127</a>, I recommended <a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a>, a more engineering-oriented custom DataStore project. It does not simply replace SwiftData&#8217;s backend with JSON or file storage; instead, it attempts to reimplement a SwiftData-aware SQLite storage layer based on custom DataStore, with extensive work around predicate translation, inheritance, caching, persistent history, and background prefetching. Developers who want to explore this direction further can use it as an advanced reference.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-03">Task Names in Swift Concurrency</a></strong></h3><p>GCD has queue labels, but tasks in Swift Concurrency long lacked a similar diagnostic identifier. With SE-0469 implemented in Swift 6.2, APIs such as <code>Task</code>, <code>Task.detached</code>, and task group <code>addTask</code> now support a <code>name</code> parameter. Developers can assign short, readable names to concurrent tasks, making it easier to locate specific execution units in LLDB, Instruments, and logs.</p><p><a href="https://x.com/iosartem">Artem Novichkov</a> walks through the usage and limitations of task names, and reminds developers that a task name should be treated as diagnostic information, not as part of program logic. It is useful for debugging, performance analysis, and log investigation, but it should not carry business state.</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-04">UniqueBox, Ref, and MutableRef in Swift 6.4</a></strong></h3><p>Swift 6.4 continues the language&#8217;s evolution around ownership, borrow, noncopyable types, lifetime dependency, <code>Span</code>, and <code>MutableSpan</code>. Through the three types <code>UniqueBox</code>, <code>Ref</code>, and <code>MutableRef</code>, <a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> introduces Swift&#8217;s new expressive capabilities around storage location, ownership, and access lifetime. Their significance is not that ordinary business code should immediately start using these low-level building blocks, but that Swift is gradually elevating relationships that previously depended on class boxes, <code>UnsafePointer</code>, or compiler-internal reasoning into language models that can be written into API shapes and checked by the type system.</p><p>Specifically, <code>UniqueBox</code> expresses that &#8220;a value lives on the heap and is owned by a single owner,&#8221; while <code>Ref</code> and <code>MutableRef</code> correspond to shared reading and exclusive mutation within a given lifetime. In other words, these types do not merely add a convenient API for a specific business scenario; they provide a more precise low-level vocabulary for describing &#8220;where a value lives, who owns it, and who can access it.&#8221;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-05">Clarification on Current CloudKit CKAsset File Size Limits</a></strong></h3><p>There has long been a confusing claim in the community around the file-size limit of <code>CKAsset</code>: some documentation has mentioned a 50 MB limit, but that mostly applies to CloudKit Web Services rather than <code>CKAsset</code> uploads through the native CloudKit framework on Apple platforms. This time, an Apple Frameworks Engineer gave a very clear answer on the developer forums: a single <code>CKAsset</code> supports up to 50 GB, assuming the user has enough remaining iCloud storage. Apps therefore need to correctly handle <code>CKError.quotaExceeded</code>.</p><blockquote><p>I am introducing this Q&amp;A in the weekly not just because it clarifies a number, but because it draws an important boundary: the fact that <code>CKAsset</code> supports large files does not mean large-file syncing is a simple or automatically reliable engineering problem. The follow-up discussion also mentions that large file transfers often need to consider background execution when an app is suspended or terminated, and can use long-lived CloudKit operations or schedule uploads through <code>BGProcessingTask</code> in <code>BackgroundTasks</code>. In other words, 50 GB answers the question &#8220;does CloudKit allow it?&#8221;; background transfer, failure recovery, quota handling, and user experience still need to be designed carefully by the app.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-06">Providing Useful Debugging Information for Agents</a></strong></h3><p>As AI agents become increasingly involved in compiling, testing, and diagnosing Swift projects, a very practical problem has become more prominent: the output of <code>xcodebuild</code> is simply too long. If the complete log is handed directly to an agent, it not only consumes a large number of tokens, but also risks burying the useful information in noise. The <a href="https://github.com/ldomaradzki/xcsift">Xcsift</a> tool introduced by <a href="https://www.linkedin.com/in/gamehelper/">Lee young-jun</a> in this article is designed precisely for this scenario. Unlike <code>xcpretty</code>, which is mainly aimed at human readability, Xcsift organizes <code>xcodebuild</code> / SwiftPM output into structured results that are more suitable for LLM consumption, including compile errors, warnings, test failures, coverage, and build timing.</p><blockquote><p>One easily overlooked detail in AI-assisted development workflows is that we should not let agents &#8220;read everything and decide what matters by themselves.&#8221; Instead, we should try to perform filtering and structuring at the tool layer first. Xcsift is a practical solution built on top of existing <code>xcodebuild</code> output, while the Tuist team previously discussed structured build data beyond build logs in <a href="https://l.fatbobman.com/w0113-09">Teaching AI to Read Xcode Builds</a>. Viewed together, they show two levels of build diagnosis in agentic coding: first reduce noise, then improve semantics.</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-07">The MiniSwift Story</a></strong></h3><p>I previously recommended <a href="https://miniswift.run/">MiniSwift</a> in the weekly. At that time, the most fascinating part was that <a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> had implemented a Swift compiler frontend and WASM backend from scratch in C, without relying on LLVM, Clang, or Apple&#8217;s official toolchain. In this article, the author fills in the story behind the project: it did not begin as a &#8220;show-off compiler project,&#8221; but from a very specific question&#8212;could one get a more stable SwiftUI preview on canvas, free from the instability of WebView or Xcode Preview?</p><p>The reason MiniSwift is worth recommending again is that it has clearly taken a big step from an early compiler prototype toward its original goal. It no longer merely compiles Swift code to WASM; through a custom UIIR, canvas renderer, and diff engine, it can now <strong>render SwiftUI code directly into an interactive preview in the browser</strong>. Judging from the official demo, <code>@State</code>, basic layout, buttons, text, and some modifiers can already provide immediate feedback in the browser similar to SwiftUI Preview. In other words, the previously mentioned idea of a &#8220;SwiftUI browser preview that does not crash&#8221; is turning from a concept into a tool that can be experienced directly.</p><h2><strong>Tools</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-08">MistKit: Letting Server-Side Swift Access CloudKit</a></strong></h3><p>Developed by <a href="https://x.com/leogdion">Leo G Dion</a>, MistKit has a clear goal: to wrap Apple&#8217;s CloudKit Web Services REST API in a modern Swift interface, allowing server-side Swift, command-line tools, and environments such as Linux and Windows&#8212;where the native CloudKit framework is unavailable&#8212;to access the same CloudKit containers. It is not meant to replace the CloudKit framework on Apple platforms, but to fill the gap in scenarios where the native framework cannot be used directly.</p><p>The project builds its lower-level client on top of swift-openapi-generator, while providing higher-level capabilities such as async/await, type-safe CloudKit operations, structured errors, record querying and CRUD, record / zone changes, asset upload, and user-identity-related functionality. For authentication, it supports API Token, Web Auth Token, and Server-to-Server. Server-to-Server is mainly for the public database, while operations involving user context in private or shared databases require Web Auth Token. This makes it suitable for background tasks, CLIs, content catalogs, public database management, and data bridging between the web and Apple devices.</p><blockquote><p>CloudKit is often seen as a &#8220;client-side service,&#8221; but MistKit makes it more natural for servers to participate in the CloudKit ecosystem. For example, a scheduled job could maintain a software version catalog, RSS aggregation content, or app asset packages in the public database; or, after user authorization, a backend could process data in a user&#8217;s private database. For apps already relying on CloudKit, it provides a path for extending data-processing capabilities beyond Apple platforms.</p></blockquote><div><hr></div><p>Thanks for reading Fatbobman&#8217;s Swift Weekly! This post is public so feel free to share it.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://weekly.fatbobman.com/p/fatbobmans-swift-weekly-138?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>&#31283;&#23450; &gt; &#26032;&#21151;&#33021;</strong></h2><p><strong><a href="https://fatbobman.com/zh/weekly/issue-138/">&#32593;&#39029;&#29256;</a></strong></p><p>&#26080;&#35770;&#26159; SwiftUI &#36824;&#26159; SwiftData&#65292;&#36825;&#20123;&#33529;&#26524;&#23492;&#20104;&#21402;&#26395;&#30340;&#22522;&#30784;&#26694;&#26550;&#65292;&#22312;&#25512;&#20986;&#26102;&#37117;&#25551;&#32472;&#20102;&#20805;&#28385;&#20809;&#26126;&#30340;&#26410;&#26469;&#65292;&#20294;&#23454;&#38469;&#36208;&#21183;&#20284;&#20046;&#37117;&#21644;&#26368;&#21021;&#30340;&#35774;&#23450;&#19981;&#22826;&#19968;&#26679;&#12290;&#24403;&#25105;&#36234;&#28145;&#20837;&#20102;&#35299;&#36825;&#20123;&#26694;&#26550;&#65292;&#23601;&#36234;&#23545;&#23427;&#20204;&#31934;&#22937;&#30340;&#26550;&#26500;&#35774;&#35745;&#25152;&#25240;&#26381;&#65292;&#21516;&#26102;&#20063;&#23545;&#37027;&#20123;&#19981;&#23613;&#22914;&#20154;&#24847;&#30340;&#23454;&#29616;&#24863;&#21040;&#26080;&#35821;&#12290;&#30524;&#30475;&#30528;&#36825;&#20123;&#35774;&#35745;&#30340;&#20809;&#29615;&#36880;&#28176;&#35114;&#21435;&#65292;&#24515;&#20013;&#19981;&#20813;&#21775;&#22040;&#12290;</p><p>&#20256;&#38395;&#33529;&#26524;&#22312;&#20170;&#24180;&#21363;&#23558;&#21457;&#24067;&#30340;&#20840;&#26032;&#25805;&#20316;&#31995;&#32479;&#65288;&#21253;&#25324; iOS 27 &#21644; macOS 27&#65289;&#20013;&#65292;&#23558;&#37319;&#21462;&#31867;&#20284;&#20110;&#24403;&#24180; Mac OS X Snow Leopard &#26102;&#20195;&#30340;&#35843;&#25972;&#31574;&#30053;&#8212;&#8212;&#23558;&#37325;&#24515;&#25918;&#22312;&#31995;&#32479;&#31283;&#23450;&#24615;&#12289;&#24615;&#33021;&#20248;&#21270;&#12289;&#28165;&#29702;&#32769;&#26087;&#20195;&#30721;&#21644;&#20462;&#22797; Bug &#19978;&#65292;&#32780;&#19981;&#26159;&#24341;&#20837;&#39072;&#35206;&#24615;&#30340;&#35270;&#35273;&#35774;&#35745;&#25110;&#32321;&#22810;&#30340;&#24213;&#23618;&#26032;&#21151;&#33021;&#12290;&#22914;&#26524;&#30495;&#33021;&#22914;&#27492;&#65292;&#37027;&#23454;&#22312;&#26159;&#20196;&#20154;&#27427;&#24944;&#12290;&#22238;&#30475;&#20004;&#24180;&#22810;&#21069;&#30340; <a href="https://fatbobman.com/zh/weekly/issue-006/">&#31532;&#20845;&#26399;&#21608;&#25253;</a>&#65292;&#24403;&#26102;&#20063;&#20256;&#20986;&#36807;&#33529;&#26524;&#35201;&#38598;&#20013;&#20462;&#22797;&#24444;&#26102;&#23384;&#22312;&#30340;&#32570;&#38519;&#24182;&#25552;&#39640;&#36719;&#20214;&#24615;&#33021;&#65292;&#20294;&#33267;&#23569;&#20174;&#36807;&#21435;&#20004;&#24180;&#30340;&#23454;&#38469;&#20351;&#29992;&#20307;&#39564;&#26469;&#30475;&#65292;&#36825;&#20010;&#30446;&#26631;&#20284;&#20046;&#26410;&#33021;&#36798;&#25104;&#12290;</p><p>&#36317;&#31163; WWDC 26 &#24050;&#32463;&#19981;&#36275;&#21313;&#22825;&#20102;&#12290;&#30456;&#36739;&#20110;&#26356;&#22810;&#12289;&#26356;&#28843;&#30340;&#26032;&#21151;&#33021;&#65292;&#25105;&#20170;&#24180;&#26356;&#26399;&#24453;&#33529;&#26524;&#33021;&#32473;&#24320;&#21457;&#32773;&#21644;&#28040;&#36153;&#32773;&#24102;&#26469;&#19968;&#27425;&#33050;&#36367;&#23454;&#22320;&#12289;&#26356;&#21152;&#31283;&#23450;&#30340;&#20307;&#39564;&#12290;</p><p><a href="https://fatbobman.com/zh/weekly/issue-137/">&#21069;&#19968;&#26399;&#20869;&#23481;</a>&#65372;<a href="https://fatbobman.com/zh/weekly/">&#20840;&#37096;&#21608;&#25253;&#21015;&#34920;</a></p><div class="pullquote"><p>&#22914;&#26524;&#24744;&#21457;&#29616;&#36825;&#20221;&#21608;&#25253;&#25110;&#25105;&#30340;&#21338;&#23458;&#23545;&#24744;&#26377;&#25152;&#24110;&#21161;&#65292;&#21487;&#20197;&#32771;&#34385;&#36890;&#36807; <strong> <a href="https://www.buymeacoffee.com/fatbobman">Buy Me a Coffee</a></strong> &#25903;&#25345;&#25105;&#30340;&#21019;&#20316;&#12290;</p></div><h2><strong>&#21407;&#21019;</strong></h2><h3><strong><a href="https://fatbobman.com/zh/posts/taming-row-height-and-spacing-jumps/?utm_source=fatbobman%20weekly%20issue%20138&amp;utm_medium=web">&#29992;&#33258;&#23450;&#20041; Layout &#21270;&#35299; SwiftUI List &#30340;&#34892;&#39640;&#19982;&#38388;&#36317;&#36339;&#21464;</a></strong></h3><p>&#22312; SwiftUI &#20013;&#65292;&#20026;&#35270;&#22270;&#29366;&#24577;&#21464;&#21270;&#28155;&#21152;&#21160;&#30011;&#24448;&#24448;&#21482;&#38656;&#35201;&#24456;&#23569;&#30340;&#20195;&#30721;&#65292;&#20294; <code>List</code> &#24182;&#19981;&#24635;&#33021;&#32473;&#20986;&#31526;&#21512;&#39044;&#26399;&#30340;&#36807;&#28193;&#25928;&#26524;&#12290;&#23588;&#20854;&#24403; row &#20869;&#37096;&#30340;&#20869;&#23481;&#39640;&#24230;&#21457;&#29983;&#21464;&#21270;&#26102;&#65292;&#20363;&#22914;&#21103;&#26631;&#39064;&#20174;&#26080;&#21040;&#26377;&#12289;&#25991;&#26412;&#34892;&#25968;&#22240;&#25968;&#25454;&#26356;&#26032;&#32780;&#25913;&#21464;&#65292;&#31995;&#32479;&#40664;&#35748;&#30340;&#24067;&#23616;&#36807;&#31243;&#24456;&#23481;&#26131;&#35753;&#34892;&#39640;&#30452;&#25509;&#30828;&#20999;&#65292;&#36827;&#32780;&#24102;&#26469;&#38378;&#28865;&#12289;&#35009;&#21098;&#25110; spacing &#31361;&#21464;&#12290;&#26412;&#25991;&#20174;&#36825;&#19968;&#24120;&#35265;&#38382;&#39064;&#20986;&#21457;&#65292;&#36880;&#27493;&#25286;&#35299; <code>List</code> &#21160;&#24577;&#34892;&#39640;&#21160;&#30011;&#22833;&#25928;&#30340;&#21407;&#22240;&#65292;&#24182;&#36890;&#36807;&#33258;&#23450;&#20041; <code>Layout</code>&#12289;<code>Animatable</code>&#12289;<code>LayoutValueKey</code> &#19982;&#29366;&#24577;&#35299;&#32806;&#65292;&#26500;&#24314;&#20986;&#19968;&#22871;&#23436;&#20840;&#22522;&#20110; SwiftUI &#21407;&#29983;&#33021;&#21147;&#30340;&#35299;&#20915;&#26041;&#26696;&#12290;</p><p>&#36825;&#24182;&#19981;&#26159;&#19968;&#31687;&#20197;&#25552;&#20379;&#24320;&#31665;&#21363;&#29992;&#32452;&#20214;&#20026;&#20027;&#35201;&#30446;&#26631;&#30340;&#25991;&#31456;&#12290;&#30456;&#27604;&#26368;&#32456;&#20195;&#30721;&#65292;&#25105;&#26356;&#24076;&#26395;&#20511;&#36825;&#20010;&#38382;&#39064;&#26803;&#29702;&#19968;&#26465; SwiftUI &#24067;&#23616;&#38382;&#39064;&#30340;&#25506;&#26597;&#36335;&#24452;&#65306;&#20808;&#29702;&#35299;&#26694;&#26550;&#20026;&#20160;&#20040;&#8220;&#19981;&#25353;&#39044;&#26399;&#24037;&#20316;&#8221;&#65292;&#20877;&#39034;&#30528;&#23427;&#30340;&#26426;&#21046;&#37325;&#26032;&#32452;&#32455;&#29366;&#24577;&#12289;&#27979;&#37327;&#19982;&#24067;&#23616;&#65292;&#35753;&#21160;&#30011;&#30495;&#27491;&#21457;&#29983;&#22312;&#27491;&#30830;&#30340;&#23618;&#32423;&#19978;&#12290;</p><h2><strong>&#36817;&#26399;&#25512;&#33616;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-01">&#26080;&#29366;&#24577; actor (Stateless Actors)</a></strong></h3><p>Actor &#36890;&#24120;&#34987;&#29702;&#35299;&#20026;&#8220;&#29992;&#26469;&#20445;&#25252;&#21487;&#21464;&#29366;&#24577;&#8221;&#30340;&#24037;&#20855;&#65292;&#22240;&#27492;&#19968;&#20010;&#27809;&#26377;&#23384;&#20648;&#23646;&#24615;&#12289;&#30475;&#20284;&#26080;&#29366;&#24577;&#30340; actor &#24456;&#23481;&#26131;&#35753;&#20154;&#30097;&#24785;&#65306;&#23427;&#21040;&#24213;&#26377;&#27809;&#26377;&#23384;&#22312;&#30340;&#24517;&#35201;&#65311;&#25991;&#31456;&#20197; <code>NetworkClient</code>&#12289;&#33258;&#23450;&#20041; global actor&#12289;custom executor &#19982;&#25991;&#20214;&#31995;&#32479;&#35775;&#38382;&#31561;&#22330;&#26223;&#20026;&#20363;&#65292;&#35828;&#26126;&#26080;&#29366;&#24577; actor &#24182;&#38750;&#19968;&#23450;&#19981;&#21512;&#29702;&#65292;&#20294;&#20063;&#21487;&#33021;&#24102;&#26469;&#20018;&#34892;&#21270;&#12289;&#21327;&#35758;&#36866;&#37197;&#21644;&#31867;&#22411;&#31995;&#32479;&#20256;&#25773;&#31561;&#39069;&#22806;&#25104;&#26412;&#65307;&#20851;&#38190;&#22312;&#20110;&#23427;&#31350;&#31455;&#26159;&#22312;&#35299;&#20915;&#20160;&#20040;&#38382;&#39064;&#12290;</p><p>&#36825;&#31687;&#25991;&#31456;&#26368;&#20540;&#24471;&#20851;&#27880;&#30340;&#28857;&#65292;&#26159; <a href="https://mastodon.social/@mattiem">Matt Massicotte</a> &#25552;&#20986;&#30340;&#8220;actor &#31532;&#19968;&#21407;&#21017;&#8221;&#65306;&#20687;&#20351;&#29992;&#20219;&#20309;&#21516;&#27493;&#21407;&#35821;&#19968;&#26679;&#65292;&#22312;&#20351;&#29992; actor &#20043;&#21069;&#65292;&#24212;&#35813;&#33021;&#28165;&#26970;&#35828;&#26126;&#23427;&#20026;&#20160;&#20040;&#24517;&#35201;&#12290;&#26080;&#29366;&#24577; actor &#24182;&#19981;&#19968;&#23450;&#26159;&#38169;&#35823;&#65292;&#20294;&#23427;&#24456;&#21487;&#33021;&#24847;&#21619;&#30528;&#25105;&#20204;&#27491;&#22312;&#29992; actor &#35299;&#20915;&#19968;&#20010;&#24182;&#19981;&#38656;&#35201; actor &#30340;&#38382;&#39064;&#65307;&#21482;&#26377;&#24403;&#23427;&#30830;&#23454;&#25215;&#25285;&#20102;&#38548;&#31163;&#12289;&#20018;&#34892;&#21270;&#12289;executor &#36866;&#37197;&#25110;&#22806;&#37096;&#29366;&#24577;&#20445;&#25252;&#31561;&#26126;&#30830;&#32844;&#36131;&#26102;&#65292;&#25165;&#26159;&#21512;&#29702;&#30340;&#35774;&#35745;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-02">&#20026; SwiftData &#26500;&#24314;&#33258;&#23450;&#20041;&#23384;&#20648;&#26684;&#24335; (Building a Custom Data Store in SwiftData)</a></strong></h3><p>&#24456;&#22810;&#24320;&#21457;&#32773;&#23481;&#26131;&#23558; SwiftData &#29702;&#35299;&#20026;&#33529;&#26524;&#23448;&#26041;&#23545; SQLite &#30340;&#39640;&#23618;&#23553;&#35013;&#65292;&#20294;&#36825;&#20854;&#23454;&#20302;&#20272;&#20102;&#23427;&#20316;&#20026;&#23545;&#35937;&#22270;&#31649;&#29702;&#19982;&#25345;&#20037;&#21270;&#21327;&#35843;&#26694;&#26550;&#30340;&#28508;&#21147;&#12290;&#26080;&#35770;&#26159; SwiftData &#36824;&#26159; Core Data&#65292;&#26356;&#37325;&#35201;&#30340;&#33021;&#21147;&#37117;&#19981;&#21482;&#26159;&#26367;&#25105;&#20204;&#35835;&#20889;&#25968;&#25454;&#24211;&#65292;&#32780;&#26159;&#35753;&#27169;&#22411;&#23545;&#35937;&#12289;&#26597;&#35810;&#12289;&#19978;&#19979;&#25991;&#31649;&#29702;&#19982;&#24213;&#23618;&#23384;&#20648;&#20043;&#38388;&#20445;&#25345;&#28165;&#26224;&#20998;&#24037;&#12290;&#21482;&#35201;&#24213;&#23618;&#23384;&#20648;&#33021;&#22815;&#25353;&#29031;&#26694;&#26550;&#35201;&#27714;&#23436;&#25104;&#25968;&#25454;&#20132;&#25442;&#65292;&#25968;&#25454;&#26469;&#28304;&#23601;&#19981;&#19968;&#23450;&#38750;&#24471;&#26159; SQLite&#12290;</p><p><a href="https://x.com/azamsharp">Mohammad Azam</a> &#36890;&#36807;&#23454;&#29616;&#19968;&#20010;&#22522;&#20110; JSON &#25991;&#20214;&#30340; custom data store&#65292;&#23637;&#31034;&#20102; SwiftData &#19982;&#24213;&#23618;&#23384;&#20648;&#20043;&#38388;&#30495;&#27491;&#20132;&#25442;&#30340;&#24182;&#19981;&#26159; <code>@Model</code> &#26631;&#35760;&#30340;&#23454;&#26102;&#23545;&#35937;&#65292;&#32780;&#26159;&#32463;&#36807;&#36716;&#25442;&#21518;&#30340; snapshot&#12290;&#29702;&#35299;&#36825;&#19968;&#28857;&#20043;&#21518;&#65292;<code>DataStoreConfiguration</code>&#12289;<code>DataStore</code>&#12289;<code>DefaultSnapshot</code>&#12289;<code>PersistentIdentifier</code> &#20197;&#21450; <code>fetch</code> / <code>save</code> &#30340;&#32844;&#36131;&#36793;&#30028;&#37117;&#20250;&#21464;&#24471;&#28165;&#26224;&#36215;&#26469;&#65306;SwiftData &#36127;&#36131;&#27169;&#22411;&#23545;&#35937;&#12289;&#35266;&#23519;&#12289;&#21464;&#26356;&#36861;&#36394;&#21644; SwiftUI &#38598;&#25104;&#65292;&#32780;&#33258;&#23450;&#20041; store &#21482;&#36127;&#36131;&#35835;&#21462;&#21644;&#20889;&#20837;&#24555;&#29031;&#12290;</p><blockquote><p>&#22312; <a href="https://fatbobman.com/zh/weekly/issue-127/#datastorekit">#127 &#26399;&#21608;&#25253;&#20013;</a>&#65292;&#25105;&#26366;&#25512;&#33616;&#36807;&#19968;&#20010;&#26356;&#24037;&#31243;&#21270;&#30340;&#33258;&#23450;&#20041; DataStore &#39033;&#30446; <a href="https://l.fatbobman.com/w0127-07">DataStoreKit</a>&#12290;&#23427;&#24182;&#19981;&#26159;&#31616;&#21333;&#22320;&#25226; SwiftData &#21518;&#31471;&#25442;&#25104; JSON &#25110;&#25991;&#20214;&#23384;&#20648;&#65292;&#32780;&#26159;&#23581;&#35797;&#22522;&#20110; custom DataStore &#37325;&#26032;&#23454;&#29616;&#19968;&#22871; SwiftData-aware &#30340; SQLite &#23384;&#20648;&#23618;&#65292;&#24182;&#22312; predicate &#32763;&#35793;&#12289;&#32487;&#25215;&#12289;&#32531;&#23384;&#12289;&#21382;&#21490;&#36861;&#36394;&#20197;&#21450;&#21518;&#21488;&#39044;&#21462;&#31561;&#26041;&#38754;&#20570;&#20102;&#22823;&#37327;&#25193;&#23637;&#12290;&#24819;&#22312;&#27492;&#26041;&#21521;&#36827;&#19968;&#27493;&#30740;&#31350;&#30340;&#24320;&#21457;&#32773;&#65292;&#21487;&#20197;&#23558;&#23427;&#20316;&#20026;&#36827;&#38454;&#21442;&#32771;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-03">&#32473; Swift &#24182;&#21457;&#20219;&#21153;&#21629;&#21517; (Task Names in Swift Concurrency)</a></strong></h3><p>GCD &#26377; queue label&#65292;Swift Concurrency &#30340; task &#21364;&#38271;&#26399;&#32570;&#23569;&#31867;&#20284;&#30340;&#35786;&#26029;&#26631;&#35782;&#12290;&#38543;&#30528; SE-0469 &#22312; Swift 6.2 &#20013;&#23454;&#29616;&#65292;Task&#12289;Task.detached&#12289;task group &#30340; addTask &#31561; API &#24320;&#22987;&#25903;&#25345; name &#21442;&#25968;&#65292;&#24320;&#21457;&#32773;&#21487;&#20197;&#20026;&#24182;&#21457;&#20219;&#21153;&#28155;&#21152;&#31616;&#30701;&#12289;&#21487;&#35835;&#30340;&#21517;&#31216;&#65292;&#20174;&#32780;&#22312; LLDB&#12289;Instruments &#21644;&#26085;&#24535;&#20013;&#26356;&#23481;&#26131;&#23450;&#20301;&#20855;&#20307;&#25191;&#34892;&#21333;&#20803;&#12290;</p><p><a href="https://x.com/iosartem">Artem Novichkov</a> &#26803;&#29702;&#20102; task name &#30340;&#29992;&#27861;&#19982;&#38480;&#21046;&#65292;&#24182;&#25552;&#37266;&#24320;&#21457;&#32773;&#65306;task name &#24212;&#21482;&#20316;&#20026;&#35786;&#26029;&#20449;&#24687;&#65292;&#32780;&#19981;&#26159;&#31243;&#24207;&#36923;&#36753;&#30340;&#19968;&#37096;&#20998;&#12290;&#23427;&#36866;&#21512;&#36741;&#21161;&#35843;&#35797;&#12289;&#24615;&#33021;&#20998;&#26512;&#21644;&#26085;&#24535;&#25490;&#26597;&#65292;&#20294;&#19981;&#24212;&#25215;&#36733;&#19994;&#21153;&#29366;&#24577;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-04">UniqueBox, Ref, and MutableRef in Swift 6.4</a>&#65532;</strong></h3><p>Swift 6.4 &#24310;&#32493;&#20102;&#36817;&#20960;&#24180;&#22260;&#32469; ownership&#12289;borrow&#12289;noncopyable type&#12289;lifetime dependency&#12289;<code>Span</code> &#19982; <code>MutableSpan</code> &#31561;&#26041;&#21521;&#30340;&#28436;&#36827;&#12290;<a href="https://www.linkedin.com/in/artem-mirzabekian/">Artem Mirzabekian</a> &#36890;&#36807; <code>UniqueBox</code>&#12289;<code>Ref</code> &#21644; <code>MutableRef</code> &#36825;&#19977;&#20010;&#31867;&#22411;&#65292;&#20171;&#32461;&#20102; Swift &#22312;&#23384;&#20648;&#20301;&#32622;&#12289;&#25152;&#26377;&#26435;&#19982;&#35775;&#38382;&#29983;&#21629;&#21608;&#26399;&#19978;&#30340;&#26032;&#34920;&#36798;&#33021;&#21147;&#12290;&#23427;&#20204;&#30340;&#24847;&#20041;&#24182;&#19981;&#26159;&#40723;&#21169;&#26222;&#36890;&#19994;&#21153;&#20195;&#30721;&#31435;&#21051;&#25913;&#29992;&#36825;&#20123;&#24213;&#23618;&#26500;&#20214;&#65292;&#32780;&#26159;&#23637;&#31034; Swift &#27491;&#22312;&#25226;&#36807;&#21435;&#20381;&#36182; class box&#12289;UnsafePointer &#25110;&#32534;&#35793;&#22120;&#20869;&#37096;&#25512;&#29702;&#30340;&#20851;&#31995;&#65292;&#36880;&#27493;&#25552;&#21319;&#20026;&#21487;&#20197;&#20889;&#36827; API &#24418;&#29366;&#12289;&#24182;&#30001;&#31867;&#22411;&#31995;&#32479;&#26816;&#26597;&#30340;&#35821;&#35328;&#27169;&#22411;&#12290;</p><p>&#20854;&#20013;&#65292;<code>UniqueBox</code> &#29992;&#26469;&#34920;&#36798;&#8220;&#19968;&#20010;&#20540;&#20301;&#20110;&#22534;&#19978;&#65292;&#24182;&#30001;&#21333;&#19968;&#25152;&#26377;&#32773;&#25345;&#26377;&#8221;&#65307;<code>Ref</code> &#21644; <code>MutableRef</code> &#21017;&#20998;&#21035;&#23545;&#24212;&#26576;&#27573;&#29983;&#21629;&#21608;&#26399;&#20869;&#30340;&#20849;&#20139;&#35835;&#21462;&#19982;&#29420;&#21344;&#20462;&#25913;&#12290;&#25442;&#21477;&#35805;&#35828;&#65292;&#36825;&#20123;&#31867;&#22411;&#34917;&#19978;&#30340;&#19981;&#26159;&#26576;&#20010;&#20855;&#20307;&#19994;&#21153;&#22330;&#26223;&#30340;&#20415;&#21033; API&#65292;&#32780;&#26159;&#19968;&#22871;&#26356;&#31934;&#30830;&#25551;&#36848;&#8220;&#20540;&#22312;&#21738;&#37324;&#12289;&#24402;&#35841;&#25152;&#26377;&#12289;&#35841;&#33021;&#35775;&#38382;&#8221;&#30340;&#24213;&#23618;&#35789;&#27719;&#12290;</p><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-05">&#20851;&#20110; CloudKit CKAsset &#24403;&#21069;&#25991;&#20214;&#22823;&#23567;&#38480;&#21046;&#30340;&#28548;&#28165; (Clarification on Current CloudKit CKAsset File Size Limits)</a>&#65532;</strong></h3><p>&#20851;&#20110; <code>CKAsset</code> &#30340;&#25991;&#20214;&#22823;&#23567;&#19978;&#38480;&#65292;&#31038;&#21306;&#37324;&#38271;&#26399;&#23384;&#22312;&#19968;&#20010;&#23481;&#26131;&#28151;&#28102;&#30340;&#35828;&#27861;&#65306;&#26377;&#20123;&#25991;&#26723;&#20013;&#25552;&#21040;&#36807; 50 MB &#38480;&#21046;&#65292;&#20294;&#37027;&#26356;&#22810;&#23545;&#24212; CloudKit Web Services&#65292;&#32780;&#19981;&#26159; Apple &#24179;&#21488;&#19978;&#36890;&#36807;&#21407;&#29983; CloudKit framework &#19978;&#20256;&#30340; <code>CKAsset</code>&#12290;&#36825;&#27425; Apple Frameworks Engineer &#22312;&#24320;&#21457;&#32773;&#35770;&#22363;&#20013;&#32473;&#20986;&#20102;&#19968;&#20010;&#38750;&#24120;&#26126;&#30830;&#30340;&#22238;&#31572;&#65306;&#21333;&#20010; <code>CKAsset</code> &#26368;&#39640;&#25903;&#25345; 50 GB&#65292;&#21069;&#25552;&#26159;&#29992;&#25143;&#20173;&#26377;&#36275;&#22815;&#30340; iCloud &#23384;&#20648;&#31354;&#38388;&#65292;&#22240;&#27492;&#24212;&#29992;&#38656;&#35201;&#27491;&#30830;&#22788;&#29702; <code>CKError.quotaExceeded</code>&#12290;</p><blockquote><p>&#20043;&#25152;&#20197;&#22312;&#21608;&#25253;&#20013;&#20171;&#32461;&#36825;&#20010;&#38382;&#31572;&#65292;&#24182;&#19981;&#21482;&#26159;&#22240;&#20026;&#23427;&#28548;&#28165;&#20102;&#19968;&#20010;&#25968;&#23383;&#65292;&#32780;&#26159;&#22240;&#20026;&#23427;&#21010;&#28165;&#20102;&#19968;&#20010;&#37325;&#35201;&#36793;&#30028;&#65306;<code>CKAsset</code> &#25903;&#25345;&#22823;&#25991;&#20214;&#65292;&#24182;&#19981;&#31561;&#20110;&#22823;&#25991;&#20214;&#21516;&#27493;&#23601;&#26159;&#31616;&#21333;&#21487;&#38752;&#30340;&#24037;&#31243;&#38382;&#39064;&#12290;&#21518;&#32493;&#35752;&#35770;&#20063;&#25552;&#21040;&#65292;&#22823;&#25991;&#20214;&#20256;&#36755;&#24448;&#24448;&#38656;&#35201;&#32771;&#34385;&#24212;&#29992;&#25346;&#36215;&#12289;&#32456;&#27490;&#21518;&#30340;&#21518;&#21488;&#25191;&#34892;&#33021;&#21147;&#65292;&#21487;&#20197;&#32467;&#21512; long-lived CloudKit operations&#65292;&#25110;&#36890;&#36807; <code>BackgroundTasks</code> &#20013;&#30340; <code>BGProcessingTask</code> &#26469;&#23433;&#25490;&#19978;&#20256;&#20219;&#21153;&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;50 GB &#22238;&#31572;&#30340;&#26159;&#8220;CloudKit &#26159;&#21542;&#20801;&#35768;&#8221;&#65292;&#32780;&#21518;&#21488;&#20256;&#36755;&#12289;&#22833;&#36133;&#24674;&#22797;&#12289;&#37197;&#39069;&#22788;&#29702;&#21644;&#29992;&#25143;&#20307;&#39564;&#65292;&#20173;&#28982;&#38656;&#35201;&#24212;&#29992;&#33258;&#24049;&#35748;&#30495;&#35774;&#35745;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-06">&#20026; Agent &#25552;&#20379;&#26377;&#25928;&#30340;&#35843;&#35797;&#20449;&#24687; (Don&#8217;t allow the agent reading whole output of Xcodebuild)</a></strong></h3><p>&#38543;&#30528; AI agent &#36234;&#26469;&#36234;&#22810;&#22320;&#21442;&#19982; Swift &#39033;&#30446;&#30340;&#32534;&#35793;&#12289;&#27979;&#35797;&#21644;&#38382;&#39064;&#23450;&#20301;&#65292;&#19968;&#20010;&#24456;&#29616;&#23454;&#30340;&#38382;&#39064;&#24320;&#22987;&#21464;&#24471;&#31361;&#20986;&#65306;<code>xcodebuild</code> &#30340;&#36755;&#20986;&#23454;&#22312;&#22826;&#38271;&#20102;&#12290;&#22914;&#26524;&#30452;&#25509;&#25226;&#23436;&#25972;&#26085;&#24535;&#20132;&#32473; agent&#65292;&#19981;&#20165;&#20250;&#28040;&#32791;&#22823;&#37327; token&#65292;&#20063;&#23481;&#26131;&#35753;&#30495;&#27491;&#26377;&#29992;&#30340;&#20449;&#24687;&#34987;&#28153;&#27809;&#22312;&#22122;&#22768;&#20013;&#12290;<a href="https://www.linkedin.com/in/gamehelper/">Lee young-jun</a> &#22312;&#26412;&#25991;&#20013;&#20171;&#32461;&#30340; <a href="https://github.com/ldomaradzki/xcsift">Xcsift</a> &#27491;&#26159;&#20026;&#36825;&#20010;&#22330;&#26223;&#35774;&#35745;&#30340;&#24037;&#20855;&#65306;&#23427;&#19981;&#20687; <code>xcpretty</code> &#37027;&#26679;&#20027;&#35201;&#38754;&#21521;&#20154;&#31867;&#38405;&#35835;&#65292;&#32780;&#26159;&#25226; <code>xcodebuild</code> / SwiftPM &#30340;&#36755;&#20986;&#25972;&#29702;&#25104;&#26356;&#36866;&#21512; LLM &#28040;&#36153;&#30340;&#32467;&#26500;&#21270;&#32467;&#26524;&#65292;&#20363;&#22914;&#32534;&#35793;&#38169;&#35823;&#12289;&#35686;&#21578;&#12289;&#27979;&#35797;&#22833;&#36133;&#12289;&#35206;&#30422;&#29575;&#21644;&#26500;&#24314;&#32791;&#26102;&#31561;&#12290;</p><blockquote><p>AI &#36741;&#21161;&#24320;&#21457;&#24037;&#20316;&#27969;&#20013;&#19968;&#20010;&#23481;&#26131;&#34987;&#24573;&#30053;&#30340;&#32454;&#33410;&#26159;&#65306;&#25105;&#20204;&#19981;&#24212;&#35813;&#35753; agent &#8220;&#35835;&#23436;&#25152;&#26377;&#20869;&#23481;&#20877;&#33258;&#24049;&#21028;&#26029;&#37325;&#28857;&#8221;&#65292;&#32780;&#24212;&#35813;&#23613;&#37327;&#22312;&#24037;&#20855;&#23618;&#20808;&#23436;&#25104;&#20449;&#24687;&#31579;&#36873;&#19982;&#32467;&#26500;&#21270;&#12290;Xcsift &#26159;&#19968;&#20010;&#22522;&#20110;&#29616;&#26377; <code>xcodebuild</code> &#36755;&#20986;&#30340;&#23454;&#29992;&#26041;&#26696;&#65292;&#32780; Tuist &#22242;&#38431;&#27492;&#21069;&#22312; <a href="https://l.fatbobman.com/w0113-09">Teaching AI to Read Xcode Builds</a> &#20013;&#21017;&#36827;&#19968;&#27493;&#35752;&#35770;&#20102;&#26500;&#24314;&#26085;&#24535;&#20043;&#22806;&#30340;&#32467;&#26500;&#21270; build data&#12290;&#20004;&#32773;&#25918;&#22312;&#19968;&#36215;&#30475;&#65292;&#27491;&#22909;&#20307;&#29616;&#20102; agentic coding &#22312;&#26500;&#24314;&#35786;&#26029;&#19978;&#30340;&#20004;&#20010;&#23618;&#27425;&#65306;&#20808;&#20943;&#23569;&#22122;&#22768;&#65292;&#20877;&#25552;&#21319;&#35821;&#20041;&#12290;</p></blockquote><div><hr></div><h3><strong><a href="https://l.fatbobman.com/w0138-07">The MiniSwift Story</a>&#65532;</strong></h3><p>&#25105;&#22312;&#20043;&#21069;&#30340;&#21608;&#25253;&#20013;&#26366;&#25512;&#33616;&#36807; <a href="https://miniswift.run/">MiniSwift</a>&#65292;&#24403;&#26102;&#26368;&#21560;&#24341;&#20154;&#30340;&#37096;&#20998;&#65292;&#26159; <a href="https://www.linkedin.com/in/ugur-toprakdeviren/">Ugur Toprakdeviren</a> &#22312;&#19981;&#20381;&#36182; LLVM&#12289;Clang &#25110; Apple &#23448;&#26041;&#24037;&#20855;&#38142;&#30340;&#24773;&#20917;&#19979;&#65292;&#29992; C &#20174;&#38646;&#23454;&#29616;&#20102; Swift &#32534;&#35793;&#22120;&#21069;&#31471;&#19982; WASM &#21518;&#31471;&#12290;&#32780;&#22312;&#36825;&#31687;&#25991;&#31456;&#20013;&#65292;&#20316;&#32773;&#34917;&#20840;&#20102;&#39033;&#30446;&#32972;&#21518;&#30340;&#26469;&#40857;&#21435;&#33033;&#65306;&#23427;&#26368;&#21021;&#24182;&#19981;&#26159;&#20026;&#20102;&#8220;&#28843;&#25216;&#24335;&#22320;&#20889;&#19968;&#20010;&#32534;&#35793;&#22120;&#8221;&#65292;&#32780;&#26159;&#28304;&#20110;&#19968;&#20010;&#24456;&#20855;&#20307;&#30340;&#38382;&#39064;&#8212;&#8212;&#33021;&#19981;&#33021;&#25670;&#33073; WebView &#25110; Xcode Preview &#30340;&#19981;&#31283;&#23450;&#65292;&#29992; canvas &#24471;&#21040;&#26356;&#31283;&#23450;&#30340; SwiftUI &#39044;&#35272;&#12290;</p><p>&#36825;&#27425;&#20540;&#24471;&#20877;&#27425;&#25512;&#33616;&#65292;&#26159;&#22240;&#20026; MiniSwift &#24050;&#32463;&#26126;&#26174;&#20174;&#26089;&#26399; compiler prototype &#21521;&#23427;&#26368;&#21021;&#30340;&#30446;&#26631;&#36808;&#36827;&#20102;&#19968;&#22823;&#27493;&#12290;&#29616;&#22312;&#23427;&#19981;&#21482;&#26159;&#25226; Swift &#20195;&#30721;&#32534;&#35793;&#21040; WASM&#65292;&#32780;&#26159;&#36827;&#19968;&#27493;&#36890;&#36807;&#33258;&#23450;&#20041; UIIR&#12289;canvas renderer &#21644; diff engine&#65292;<strong>&#25226; SwiftUI &#20195;&#30721;&#30452;&#25509;&#28210;&#26579;&#25104;&#27983;&#35272;&#22120;&#20013;&#30340;&#21487;&#20132;&#20114;&#39044;&#35272;</strong>&#65307;&#20174;&#23448;&#32593;&#23637;&#31034;&#26469;&#30475;&#65292;<code>@State</code>&#12289;&#22522;&#30784;&#24067;&#23616;&#12289;&#25353;&#38062;&#12289;&#25991;&#26412;&#21644;&#37096;&#20998;&#20462;&#39280;&#22120;&#24050;&#32463;&#21487;&#20197;&#22312;&#32593;&#39029;&#20013;&#24418;&#25104;&#31867;&#20284; SwiftUI Preview &#30340;&#21363;&#26102;&#21453;&#39304;&#12290;&#20063;&#23601;&#26159;&#35828;&#65292;&#20043;&#21069;&#25552;&#21040;&#30340;&#8220;&#19981;&#20250;&#23849;&#28291;&#30340; SwiftUI &#27983;&#35272;&#22120;&#39044;&#35272;&#8221;&#65292;&#27491;&#22312;&#20174;&#35774;&#24819;&#21464;&#25104;&#19968;&#20010;&#21487;&#20197;&#30452;&#25509;&#20307;&#39564;&#30340;&#24037;&#20855;&#12290;</p><h2><strong>&#24037;&#20855;</strong></h2><h3><strong><a href="https://l.fatbobman.com/w0138-08">MistKit&#65306;&#35753;&#26381;&#21153;&#31471; Swift &#35775;&#38382; CloudKit</a></strong></h3><p>&#30001; <a href="https://x.com/leogdion">Leo G Dion</a> &#24320;&#21457;&#30340; MistKit &#30446;&#26631;&#24456;&#26126;&#30830;&#65306;&#25226; Apple &#30340; CloudKit Web Services REST API &#23553;&#35013;&#25104;&#29616;&#20195; Swift &#25509;&#21475;&#65292;&#35753;&#26381;&#21153;&#31471; Swift&#12289;&#21629;&#20196;&#34892;&#24037;&#20855;&#65292;&#20197;&#21450; Linux&#12289;Windows &#31561;&#27809;&#26377;&#21407;&#29983; CloudKit framework &#30340;&#29615;&#22659;&#65292;&#20063;&#33021;&#35775;&#38382;&#21516;&#19968;&#22871; CloudKit &#23481;&#22120;&#12290;&#23427;&#24182;&#19981;&#26159;&#35201;&#26367;&#20195; Apple &#24179;&#21488;&#19978;&#30340; CloudKit framework&#65292;&#32780;&#26159;&#34917;&#36275;&#37027;&#20123;&#26080;&#27861;&#30452;&#25509;&#20351;&#29992;&#21407;&#29983;&#26694;&#26550;&#30340;&#22330;&#26223;&#12290;</p><p>&#39033;&#30446;&#22522;&#20110; swift-openapi-generator &#26500;&#24314;&#24213;&#23618;&#23458;&#25143;&#31471;&#65292;&#19978;&#23618;&#25552;&#20379; async/await&#12289;&#31867;&#22411;&#23433;&#20840;&#30340; CloudKit &#25805;&#20316;&#12289;&#32467;&#26500;&#21270;&#38169;&#35823;&#12289;record &#26597;&#35810;&#19982;&#22686;&#21024;&#25913;&#12289;record / zone changes&#12289;asset upload &#21644;&#29992;&#25143;&#36523;&#20221;&#30456;&#20851;&#33021;&#21147;&#12290;&#35748;&#35777;&#26041;&#38754;&#35206;&#30422; API Token&#12289;Web Auth Token &#19982; Server-to-Server&#65307;&#20854;&#20013; Server-to-Server &#20027;&#35201;&#29992;&#20110; public database&#65292;&#28041;&#21450; private &#25110; shared database &#30340;&#29992;&#25143;&#19978;&#19979;&#25991;&#25805;&#20316;&#21017;&#38656;&#35201; Web Auth Token&#12290;&#36825;&#20351;&#23427;&#36866;&#21512;&#21518;&#21488;&#20219;&#21153;&#12289;CLI&#12289;&#20869;&#23481;&#30446;&#24405;&#12289;&#20844;&#20849;&#25968;&#25454;&#24211;&#31649;&#29702;&#65292;&#20197;&#21450; Web &#19982; Apple &#35774;&#22791;&#20043;&#38388;&#30340;&#25968;&#25454;&#26725;&#25509;&#12290;</p><blockquote><p>CloudKit &#24120;&#34987;&#35270;&#20026;&#8220;&#23458;&#25143;&#31471;&#26381;&#21153;&#8221;&#65292;&#20294; MistKit &#35753;&#26381;&#21153;&#31471;&#21442;&#19982; CloudKit &#29983;&#24577;&#21464;&#24471;&#26356;&#33258;&#28982;&#12290;&#20363;&#22914;&#65292;&#29992;&#23450;&#26102;&#20219;&#21153;&#32500;&#25252; public database &#20013;&#30340;&#36719;&#20214;&#29256;&#26412;&#30446;&#24405;&#12289;RSS &#32858;&#21512;&#20869;&#23481;&#12289;&#24212;&#29992;&#32032;&#26448;&#21253;&#65307;&#25110;&#22312;&#29992;&#25143;&#25480;&#26435;&#21518;&#65292;&#35753;&#21518;&#31471;&#22788;&#29702; private database &#20013;&#30340;&#25968;&#25454;&#12290;&#23545;&#24050;&#32463;&#20381;&#36182; CloudKit &#30340;&#24212;&#29992;&#26469;&#35828;&#65292;&#23427;&#25552;&#20379;&#20102;&#19968;&#26465;&#22312; Apple &#24179;&#21488;&#20043;&#22806;&#25193;&#23637;&#25968;&#25454;&#22788;&#29702;&#33021;&#21147;&#30340;&#36335;&#24452;&#12290;</p></blockquote>]]></content:encoded></item></channel></rss>