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

推荐订阅源

U
Unit 42
N
News and Events Feed by Topic
S
Schneier on Security
G
GRAHAM CLULEY
Scott Helme
Scott Helme
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
CERT Recently Published Vulnerability Notes
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
T
The Blog of Author Tim Ferriss
Cisco Talos Blog
Cisco Talos Blog
P
Privacy & Cybersecurity Law Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
Blog — PlanetScale
Blog — PlanetScale
Project Zero
Project Zero
MyScale Blog
MyScale Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
The Last Watchdog
The Last Watchdog
Vercel News
Vercel News
The Cloudflare Blog
C
Check Point Blog
Help Net Security
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
腾讯CDC
NISL@THU
NISL@THU
S
Security @ Cisco Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
SegmentFault 最新的问题
MongoDB | Blog
MongoDB | Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
AWS News Blog
AWS News Blog
Cloudbric
Cloudbric
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Vulnerabilities – Threatpost
S
Secure Thoughts

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 The State of SwiftUI | 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 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
Surprises with Swift Extensions | Peter Steinberger
Peter Steinberger · 2016-03-24 · via Peter Steinberger

tl;dr: Swift extensions on Objective-C classes still need to be prefixed. You can use @objc(prefix_name) to keep the name pretty in Swift and expose a prefixed version for the ObjC runtime. PSPDFKit is a commerical framework that allows you to embed a PDF viewer/editor into your app. Today, we received a report for a very weird crash with a stack trace that contained only UIKit symbols, but was clearly triggered by a specific action in PSPDFKit (Toggling the note annotation view controller quickly).

We wrote back and forth via our support desk and the developer was very cooperative. However, he couldn’t manage to create an isolated example of this and we were unable to reproduce this on our end as well. That’s fine. This happens sometimes. Might be a very weird configuration that he didn’t replicate in the sample that triggers the bug, so in the end we requested and got the whole app to debug.

With that we were able to instantly reproduce the crash:

2016-03-24 22:27:18.793 TheApp[45769:6521650] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(
	0   CoreFoundation                      0x0000000108d95e65 __exceptionPreprocess + 165
	1   libobjc.A.dylib                     0x0000000109f68deb objc_exception_throw + 48
	2   CoreFoundation                      0x0000000108c5c8c5 -[__NSArrayM insertObject:atIndex:] + 901
	3   UIKit                               0x0000000104b8c300 -[UIViewController _addChildViewController:performHierarchyCheck:notifyWillMove:] + 541
	4   UIKit                               0x000000010534b0bf -[UIInputWindowController changeToInputViewSet:] + 473
	5   UIKit                               0x0000000105344080 -[UIInputWindowController moveFromPlacement:toPlacement:starting:completion:] + 369
	6   UIKit                               0x000000010534bf0c -[UIInputWindowController setInputViewSet:] + 983
	7   UIKit                               0x0000000105343d08 -[UIInputWindowController performOperations:withAnimationStyle:] + 50
	8   UIKit                               0x000000010504bb15 -[UIPeripheralHost(UIKitInternal) setInputViews:animationStyle:] + 1179
	9   UIKit                               0x000000011a68cb89 -[UIPeripheralHostAccessibility setInputViews:animationStyle:] + 39
	10  UIKit                               0x0000000104c0251d -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] + 81
	11  UIKit                               0x0000000104bff546 -[UIResponder becomeFirstResponder] + 617
	12  UIKit                               0x0000000104a96c59 -[UIView(Hierarchy) becomeFirstResponder] + 138
	13  UIKit                               0x0000000105396788 -[UITextView becomeFirstResponder] + 75
	14  UIKit                               0x0000000104a96c95 -[UIView(Hierarchy) deferredBecomeFirstResponder] + 49
	15  UIKit                               0x0000000104a96d36 -[UIView(Hierarchy) _promoteSelfOrDescendantToFirstResponderIfNecessary] + 133
	16  UIKit                               0x0000000104a9709f __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 208
	17  UIKit                               0x0000000104a96f69 -[UIView(Hierarchy) _postMovedFromSuperview:] + 544
	18  UIKit                               0x0000000104aa4d8f -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1967
	19  UIKit                               0x0000000104e68d81 -[UINavigationTransitionView transition:fromView:toView:] + 672
	20  UIKit                               0x0000000104bcdcf5 -[UINavigationController _startTransition:fromViewController:toViewController:] + 3291
	21  UIKit                               0x0000000104bce2f1 -[UINavigationController _startDeferredTransitionIfNeeded:] + 890
	22  UIKit                               0x0000000104bcf3af -[UINavigationController __viewWillLayoutSubviews] + 57
	23  UIKit                               0x0000000104d75ff7 -[UILayoutContainerView layoutSubviews] + 248
	24  UIKit                               0x000000011a68f158 -[UILayoutContainerViewAccessibility layoutSubviews] + 43
	25  UIKit                               0x0000000104aa84a3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
	26  QuartzCore                          0x000000010427359a -[CALayer layoutSublayers] + 146
	27  QuartzCore                          0x0000000104267e70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
	28  QuartzCore                          0x0000000104267cee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
	29  QuartzCore                          0x000000010425c475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
	30  QuartzCore                          0x0000000104289c0a _ZN2CA11Transaction6commitEv + 486
	31  UIKit                               0x0000000104a1cb47 _afterCACommitHandler + 174
	32  CoreFoundation                      0x0000000108cc1367 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
	33  CoreFoundation                      0x0000000108cc12d7 __CFRunLoopDoObservers + 391
	34  CoreFoundation                      0x0000000108cb6f2b __CFRunLoopRun + 1147
	35  CoreFoundation                      0x0000000108cb6828 CFRunLoopRunSpecific + 488
	36  GraphicsServices                    0x000000010b366ad2 GSEventRunModal + 161
	37  UIKit                               0x00000001049f1610 UIApplicationMain + 171
	38  TheApp                              0x0000000101e206e2 main + 114
	39  libdyld.dylib                       0x000000010aa7192d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Notice how this is all UIKit, but triggered by an action in our framework. So we started digging and reading lots and lots of UIKit disassembly to understand what’s happening under the hood. Everything seemed reasonable. Next step was to try and create a sample, so we could report a radar. Has to be UIKit’s fault - right? :)

Since previous attempts to build a sample app failed, I started the other way around, with moving all relevant code into the app delegate and slowly trimming down on classes, without touching any of the 3rd-party dependencies. A very slow and cumbersome process. Of course I scanned all the files for categories but apart from a few harmless looking extensions the app was all Swift - some very neat MVVM and reactive programming in there. Interestingly enough, things stopped crashing once I did that. Ha - so it really had to be something in the app that was causing the crash. I looked through all the files but everything looked innocent. Then I took a closer look at UIViewController+Containment.swift, and added a breakpoint there…

That was it. These seemingly innocent extensions were overriding private API. Apple’s private API detection is not super sophisticated and wasn’t triggered when the app was uploaded to the App Store. It’s also not a public symbol so there were no warnings, not even a log message. Unprefixed categories are always dangerous, especially on classes that you do not own, like UIViewController. In PSPDFKit, we use categories for shared code, but prefix any method with pspdf_ to be absolutely sure we do not hit any name clashes. It’s certainly not pretty, and prefixes in Swift look even more alien, yet as you can see in this bug hunt, they are definitely necessary.

The following case was especially evil because this category almost did the same thing as UIKit’s internal private method of the same name. I shared my findings on Twitter and got a few interesting comments. Swift itself already fixes this problem, however only for pure Swift classes. Since Swift 2.2 landed the new symbolic selector references, Joe Groff remarked that it’s thinkable that future versions default to a more agressive name mangling.