惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
T
Tenable Blog
T
Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
Webroot Blog
Webroot Blog
Spread Privacy
Spread Privacy
O
OpenAI News
The Last Watchdog
The Last Watchdog
P
Proofpoint News Feed
C
Check Point Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
月光博客
月光博客
S
Securelist
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
T
Troy Hunt's Blog
W
WeLiveSecurity
GbyAI
GbyAI
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
Cisco Blogs
H
Help Net Security
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 【当耐特】
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
小众软件
小众软件
N
News and Events Feed by Topic

Peter Steinberger

OpenClaw, OpenAI and the future | Peter Steinberger Shipping at Inference-Speed | Peter Steinberger The Signature Flicker | Peter Steinberger Just Talk To It - the no-bs Way of Agentic Engineering | Peter Steinberger Claude Code Anonymous | Peter Steinberger Live Coding Session: Building Arena | Peter Steinberger My Current AI Dev Workflow | Peter Steinberger Essential Reading for Agentic Engineers - August 2025 | Peter Steinberger Just One More Prompt | Peter Steinberger Poltergeist: The Ghost That Keeps Your Builds Fresh | Peter Steinberger Don't read this Startup Slop | Peter Steinberger Essential Reading for Agentic Engineers - July 2025 | Peter Steinberger Self-Hosting AI Models After Claude's Usage Limits | Peter Steinberger Logging Privacy Shenanigans | Peter Steinberger VibeTunnel's first AI-anniversary | Peter Steinberger Making AppleScript Work in macOS CLI Tools: The Undocumented Parts | Peter Steinberger Peekaboo 2.0 – Free the CLI from its MCP shackles | Peter Steinberger Command your Claude Code Army, Reloaded | Peter Steinberger Essential Reading for Agentic Engineers | Peter Steinberger Slot Machines for Programmers: How Peter Builds Apps 20x Faster with AI | Peter Steinberger My AI Workflow for Understanding Any Codebase | Peter Steinberger stats.store: Privacy-First Sparkle Analytics | Peter Steinberger Showing Settings from macOS Menu Bar Items: A 5-Hour Journey | Peter Steinberger VibeTunnel: Turn Any Browser into Your Mac's Terminal | Peter Steinberger Vibe Meter 2.0: Calculating Claude Code Usage with Token Counting | Peter Steinberger llm.codes: Make Apple Docs AI-Readable | Peter Steinberger Automatic Observation Tracking in UIKit and AppKit: The Feature Apple Forgot to Mention | Peter Steinberger Peekaboo MCP – lightning-fast macOS screenshots for AI agents | Peter Steinberger Migrating 700+ Tests to Swift Testing: A Real-World Experience | Peter Steinberger Commanding Your Claude Code Army | Peter Steinberger Code Signing and Notarization: Sparkle and Tears | Peter Steinberger Vibe Meter: Monitor Your AI Costs | Peter Steinberger Claude Code is My Computer | Peter Steinberger Stop Over-thinking AI Subscriptions | Peter Steinberger Introducing Demark: HTML in. MD out. Blink-fast. | Peter Steinberger The Future of Vibe Coding: Building with AI, Live and Unfiltered | Peter Steinberger MCP Best Practices | Peter Steinberger Finding My Spark Again | Peter Steinberger Top-Level Menu Visibility in SwiftUI for macOS | Peter Steinberger Fixing keyboardShortcut in SwiftUI | Peter Steinberger Supporting Both Tap and Long Press on a Button in SwiftUI | Peter Steinberger On Using Apple Silicon Mac Mini for Continuous Integration | Peter Steinberger Apple Silicon M1: A Developer's Perspective | Peter Steinberger Gardening Your Twitter: Curating Your Timeline | Peter Steinberger Gardening Your Twitter: Growing Your Followers | Peter Steinberger Forbidden Controls in Catalyst: Optimize Interface for Mac | Peter Steinberger Disabling Keyboard Avoidance in SwiftUI's UIHostingController | Peter Steinberger Logging in Swift | Peter Steinberger Building with Swift Trunk Development Snapshots | Peter Steinberger Calling Super at Runtime in Swift | Peter Steinberger zld — A Faster Version of Apple's Linker | Peter Steinberger How to Fix LLDB: Couldn't IRGen Expression | Peter Steinberger Updating macOS on a Hackintosh | Peter Steinberger InterposeKit — Elegant Swizzling in Swift | Peter Steinberger The Great Mac Catalyst Text Input Crash Hunt | Peter Steinberger Jailbreaking for iOS Developers | Peter Steinberger Network Kernel Core Dump | Peter Steinberger How to macOS Core Dump | Peter Steinberger Kernel Panics and Surprise boot-args | Peter Steinberger The LG UltraFine 5K, kernel_task, and Me | Peter Steinberger Let's Try This Again | Peter Steinberger How We Work at PSPDFKit | Peter Steinberger Swizzling in Swift | Peter Steinberger WWDC for First-Timers, 2019 Edition | Peter Steinberger Challenges of Adopting Drag and Drop | Peter Steinberger Marzipan: Porting iOS Apps to the Mac | Peter Steinberger How to Use Slack and Not Go Crazy | Peter Steinberger Hardcore Debugging - Heavy Weapons for Hard Bugs | Peter Steinberger Binary Frameworks in Swift | Peter Steinberger Even Swiftier Objective-C | Peter Steinberger The Case for Deprecating UITableView | Peter Steinberger Running tests with Clang Address Sanitizer | Peter Steinberger UI testing on iOS, without busy waiting | Peter Steinberger Hiring a distributed team | Peter Steinberger Writing Good Bug Reports | Peter Steinberger Real-time collaboration, Apple, and you | Peter Steinberger Converting Xcode Test Runs to JUnit, the Fast Way | Peter Steinberger Efficient iOS Version Checking | Peter Steinberger Investigating Thread Safety of UIImage | Peter Steinberger Swifty Objective-C | Peter Steinberger Running UI Tests on iOS With Ludicrous Speed | Peter Steinberger A Pragmatic Approach to Cross-Platform | Peter Steinberger Surprises with Swift Extensions | Peter Steinberger Using ccache for Fun and Profit | Peter Steinberger UITableViewController designated initializer woes | Peter Steinberger Researching ResearchKit | Peter Steinberger The curious case of rotation with multiple windows on iOS 8 | Peter Steinberger UIKit Debug Mode | Peter Steinberger Retrofitting containsString: on iOS 7 | Peter Steinberger A Story About Swizzling "the Right Way™" and Touch Forwarding | Peter Steinberger Hacking with Aspects | Peter Steinberger Fixing UITextView On iOS 7 | Peter Steinberger Fixing What Apple Doesn't | Peter Steinberger How To Inspect The View Hierarchy Of Third-Party Apps | Peter Steinberger Fixing UISearchDisplayController On iOS 7 | Peter Steinberger Smart Proxy Delegation | Peter Steinberger Adding Keyboard Shortcuts To UIAlertView | Peter Steinberger How To Center Content Within UIScrollView | Peter Steinberger UIAppearance for Custom Views | Peter Steinberger Hacking Block Support Into UIMenuItem | Peter Steinberger
The State of SwiftUI | Peter Steinberger
Peter Steinberger · 2020-09-13 · via Peter Steinberger

Apple released SwiftUI last year, and it’s been an exciting and wild ride. With iOS 14, a lot of the rough edges have been smoothed out — is SwiftUI finally ready for production?

Fruta Sample App

Let’s look at Apple’s Fruta example, a cross-platform feature-rich app that’s built completely in SwiftUI. It’s great that Apple is finally releasing a more complex application for this year’s cycle.

I took a look when Big Sur beta 1 came out, and it was pretty unpolished:

Since then, there have been many betas, and we’re nearing the end of the cycle, with the GM expected in October. So it’s time to look at Fruta again. And indeed, the SwiftUI team did a great job fixing the various issues: The toolbar is pretty reliable, the sidebar no longer jumps out, multiple windows works… however, views are still sometimes misaligned, and it’s still fairly easy to make it crash on both macOS (FB8682269) and iOS 14b8 (FB8682290).

SwiftUI AttributeGraph Crashes

Most SwiftUI crashes are a result of either a diffing issue in AttributeGraph, or a bug with one of the bindings to the platform controls (AppKit or UIKit). Whenever you see AG::Graph in the stack trace, that’s SwiftUI’s AttributeGraph (written in C++), which takes over representing the view hierarchy and diffing. Crashes there are usually in this form:

 Fruta[3607:1466511] [error] precondition failure: invalid size for indirect attribute: 25 vs 24

Googling for this error reveals that there are a lot of similar problems. People sometimes do find workarounds via wrapping views into other views or changing the hierarchy. But mostly, we’re powerless, and this is something Apple needs to fix in its framework. Since SwiftUI ships as part of the OS, end users need to update their devices to get these fixes.

Platform-Binding Crashes

SwiftUI uses many components from AppKit and UIKit, which is a much better strategy than reinventing the wheel. These components are stateful and are synced with custom manager classes that perform the state diffing. These wrappers can cause issues, and as they’re written in Swift, there aren’t many possibilities to fix issues from the outside (unlike with swizzling in the earlier days).

Example: Removing a favorited item while it’s selected crashes in the AppKit binding that syncs the SwiftUI state with NSTableView (FB8684522).

2020-09-13 10:31:25.483965+0200 Fruta[79371:2051792] [General] Row 0 out of row range [0--1] for rowViewAtRow:createIfNeeded:
2020-09-13 10:31:25.498144+0200 Fruta[79371:2051792] [General] (
	0   CoreFoundation                      0x00007fff20cdb0df __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007fff20b3d469 objc_exception_throw + 48
	2   AppKit                              0x00007fff237a7905 -[NSTableRowData rowViewAtRow:createIfNeeded:] + 675
	3   AppKit                              0x00007fff23813008 -[NSTableView viewAtColumn:row:makeIfNecessary:] + 29
	4   SwiftUI                             0x00007fff49565fc7 $s7SwiftUI19ListCoreCoordinatorC17selectionBehavior5atRow2inAA012PlatformItemC0V0L0V09SelectionG0VSgSi_So11NSTableViewCtF + 39
	5   SwiftUI                             0x00007fff49566b36 $s7SwiftUI19ListCoreCoordinatorC18selectionDidChange2inySo11NSTableViewC_tF + 2662
	6   SwiftUI                             0x00007fff49187850 $s7SwiftUI26NSTableViewListCoordinatorC05tableD19SelectionIsChangingyy10Foundation12NotificationVFTm + 112
	7   SwiftUI                             0x00007fff49187912 $s7SwiftUI26NSTableViewListCoordinatorC05tableD19SelectionIsChangingyy10Foundation12NotificationVFToTm + 114
	8   CoreFoundation                      0x00007fff20c56a6c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
	9   CoreFoundation                      0x00007fff20cf23bb ___CFXRegistrationPost_block_invoke + 49
	10  CoreFoundation                      0x00007fff20cf232f _CFXRegistrationPost + 454
	11  CoreFoundation                      0x00007fff20c275ce _CFXNotificationPost + 723
	12  Foundation                          0x00007fff218ba5e2 -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
	13  AppKit                              0x00007fff237ae588 -[NSTableView _sendSelectionChangedNotificationForRows:columns:] + 219
	14  AppKit                              0x00007fff2373b739 -[NSTableRowData _updateVisibleViewsBasedOnUpdateItems] + 4503
	15  AppKit                              0x00007fff2373a453 -[NSTableRowData _updateVisibleViewsBasedOnUpdateItemsAnimated] + 224
	16  AppKit                              0x00007fff2371a2dc -[NSTableRowData _doWorkAfterEndUpdates] + 95
	17  AppKit                              0x00007fff2371a19d -[NSTableView _endUpdateWithTile:] + 119
	18  SwiftUI                             0x00007fff49186759 $s7SwiftUI26NSTableViewListCoordinatorC011updateTableD0_4from2toySo0cD0C_xxtF + 1145
	19  SwiftUI                             0x00007fff4956c010 $s7SwiftUI19ListCoreCoordinatorC29updateTableViewAndVisibleRows_4from2toySo07NSTableH0C_xxtFyyXEfU_ + 304
	20  SwiftUI                             0x00007fff4956ccf5 $s7SwiftUI19ListCoreCoordinatorC24withSelectionUpdateGuardyyyyXEF + 53
	21  SwiftUI                             0x00007fff4956b2ff $s7SwiftUI19ListCoreCoordinatorC29updateTableViewAndVisibleRows_4from2toySo07NSTableH0C_xxtF + 79

It’s likely there are more bugs waiting to be discovered, but I only spent a few hours with Fruta and on writing up this article.

Performance

On my 2.4 GHz 8-Core Intel Core i9 MacBook Pro, it takes longer than a second to update the main view when changing the selection. This feels sluggish, not to mention it’s significantly longer than even most websites — that load data via the network — need. Fruta has everything local. What’s so slow here? Let’s look at Instruments!

  • Of the 10 seconds captured, 30 percent of them are used for the various retain/release and malloc calls in Swift and Objective-C.
  • NSAttributedString shows up often in stack traces, which hints that text layout seems especially expensive.
  • The AttributeGraph SwiftUI layout engine seems to create a lot of throwaway objects. These might mostly be Swift structs, but they’re still expensive.
  • JPG decoding happens on the main thread, but it’s only responsible for less than 1 percent of the time spent here.
  • When checking Hide System Libraries, there’s basically no work done in Fruta’s business logic.
  • Sorting for Top Functions, we see that AppKit’s auto layout logic, combined with SwiftUI’s graph, is taking up a lot of time.
  • There seems to be a lot of unnecessary invalidation. For example, AppKitToolbarCoordinator adds a toolbar item, which triggers NSHostingView.preferencesDidChange(), causing everything to lay itself out once again, even though the toolbar size doesn’t change.

The good news is there seem to be a lot of potential future optimizations possible to make this fast. Alternatively, there’s always the possibility of dropping out of SwiftUI for performance critical parts.

This isn’t unique to Fruta. I’ve been taking a look at @Dimillian’s RedditOS app, which is built with SwiftUI on macOS. He stopped development because it’s so slow that it’s not shippable. I did some debugging with an earlier version of Big Sur where the app still somewhat worked:

The general pattern here points to AppKit: The interaction between SwiftUI views and AppKit views seems to be poor. It’s important to understand that SwiftUI itself is fast — for many use cases it’s even faster than using CALayer, as @cocoawithlove proved — and the UIKit port is by far faster and better than the AppKit port.

Update for iOS 14 GM

It’s still trivial to crash the SwiftUI C++ AttributeGraph in Apple’s Fruta example on iOS 14 GM.

Update for Big Sur b9

Apple seems to have fixed an issue and specifically mentioned the Fruta Sample app in the Big Sur Beta Release Notes. However, after testing, it’s still trivially to crash.

Update for Big Sur b10 and iOS 14.2b4

Apple got back to me, explaining that I should test this again:

They indeed fixed the easy-to-trigger bug (good job!) and it took me a minute to get it to crash again. To be fair, this is a different issue and seems related to Apple Pay. I also found another Attributed Graph crash.

iOS stabilized as well, however I found a race condition in the List Coordinator. Overall things are really improving fast, the team here is working hard.

Conclusion

If your target platform is iOS 14, you’re now good to go with hobby projects or individual screens in SwiftUI. I’m currently working on making our PDF SDK for iOS easier to use with SwiftUI, and we’ll replace the settings/about screen of PDF Viewer with a SwiftUI version.

I personally wouldn’t yet go all-in on SwiftUI for production apps, although the crash rate is likely manageable and Apple is actively improving things with every release. Remember that SwiftUI ships with the OS, not with your app, so any bug fixes will only help if your users update the OS.

Other ports are not so great. AppKit seems particularly troublesome, but I’ve also heard of big issues with tvOS. If you need to deploy your app to the Mac, use Catalyst, which is a much more stable binding and feels really good with Big Sur’s native mode, where content is no longer scaled.

If you’re curious about SwiftUI, please don’t let this dampen your enthusiasm. It’s extremely fun to write, it’s clearly the future at Apple, and all these issues will surely be resolved within a few years.