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

推荐订阅源

博客园 - 三生石上(FineUI控件)
U
Unit 42
人人都是产品经理
人人都是产品经理
罗磊的独立博客
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
aimingoo的专栏
aimingoo的专栏
T
Tailwind CSS Blog
GbyAI
GbyAI
Blog — PlanetScale
Blog — PlanetScale
I
InfoQ
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
B
Blog RSS Feed
WordPress大学
WordPress大学
腾讯CDC
H
Help Net Security
博客园 - Franky
博客园 - 【当耐特】
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
B
Blog
Vercel News
Vercel News
博客园 - 司徒正美

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
UITableViewController designated initializer woes | Peter...
Peter Steinberger · 2015-04-15 · via Peter Steinberger

With Xcode 61, Apple added support for the NS_DESIGNATED_INITIALIZER flag, and also added this to various framework classes. This is likely a byproduct of Swift, where the initializer call order is much more strongly enforced. This goes as far as there’s a new convenience keyword to mark the separation of convenience vs designated initializers.

This is a good thing. It’s far too easy to break the initializer chain, even though Apple’s documentation on it is superb.

With iOS 8.3, Apple made a modification in UITableViewController that by now, every one using this class will have seen. initWithStyle: is now a designated initializer. And while throughout the beta period, this was the only designated one, the GM suddenly added both initWithNibName:bundle: and initWithCoder: to the list as well - making this class quite inconvenient to subclass.

Most of your subclasses will have their own designated initializer since they likely depend on some object at initialization time. If that’s the case, you generally want to prevent users from calling the wrong initializer, even if they are marked designated in the superclass.

A common idiom to do this is to declare them unavailable:

The above code belongs to the header and results in compile-time warnings. Since Objective-C is dynamic, this makes calling init harder, but does not prevent you from shooting yourself in the foot. To be complete, let’s also block this in the implementation:

Combining the two makes it really hard to create objects that are not correctly initialized. So of course I also tried to apply this pattern to UITableViewController… which results in an assert. Here’s the designated initializer chain I’d expect:

[PSPDFTableViewController initWithAnnotations:] -> [UITableViewController initWithStyle:] -> [UIViewController initWithNibName:bundle:] -> [NSObject init].

However, Apple didn’t really play by the rules in UITableViewController. It calls [super init] inside initWithStyle:. init is overridden in UIViewController to call initWithNibName:bundle: since this is the designated initializer per documentation, even though it’s not annotated with the NS_DESIGNATED_INITIALIZER decoration. This results in following call order:

[PSPDFTableViewController initWithAnnotations:] -> [UITableViewController initWithStyle:] -> [UIViewController init] -> [PSPDFTableViewController initWithNibName:bundle:] (which asserts!).

This is very unfortunate, and I assume it’s not easy to correct since there surely are apps out there who rely on this call order. We work around this by wrapping our implementation into a clang diagnostic block to ignore “-Wobjc-designated-initializers”, but it doesn’t prevent anyone from creating the controller with an invalid state. Maybe Apple fixes this conditionally in iOS 9. rdar://problem/20549233.

What other ways are there do deal with it? Did I miss something here?


1. To be correct, [Clang commit r196314](http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131202/094628.html) landed in Xcode 5.1, so technically this already had support for designated initializers by using the `objc_designated_initializer` attribute directly.