4.10 · The runtime up close: introspection, encodings, IMPs and exceptions
The Objective-C runtime is a small C API you can call from Swift. Using it to look at a class, call an implementation directly or build a class on the fly shows what message sending, KVO and mocking libraries really do.
Mental model. The runtime is a set of public tables: classes, methods, properties, type strings. Everything dynamic in Objective-C is a read or write to those tables.
Looking and calling
Listing members, reading type strings and calling an implementation without the message send.
- How do you inspect a class’s methods and properties at run time, and what does a Swift class show?
The runtime functions class_copyMethodList, class_copyPropertyList, class_copyIvarList and class_copyProtocolList return C arrays you free afterwards, and… - What is a method type encoding, and why does a wrong signature crash instead of failing to compile?
The runtime does not store parameter types, it stores a type-encoding string per method: the return type, the total frame size, then each argument with its… - What is an IMP, and how can you call one without sending a message?
An IMP is the raw C function pointer behind a method: id (*)(id self, SEL _cmd, ...). method_getImplementation returns it and class_getMethodImplementation or…
Building and breaking
Creating classes at run time, and the exception model that Swift cannot catch.
- How do you create or retarget a class at run time, and why does Swift sometimes ignore it?
The runtime builds classes in three steps. objc_allocateClassPair(super, name, 0) creates an unregistered subclass, class_addMethod (with a type encoding and… - Why can’t Swift catch an NSException, and how do you handle one thrown by Objective-C code?
Objective-C has two error systems. Recoverable failures use NSError **, which Swift imports as throws. NSException (@throw, @try/@catch) is for programmer…
More in Objective-C & interop
- 4.1 · Message send, selectors, forwarding, isa
- 4.2 · Categories, associated objects, load and initialize
- 4.3 · NSObject, class clusters, copying
- 4.4 · @objc, what does not bridge, and error bridging
- 4.5 · Nullability, lightweight generics, Swift-friendly names
- 4.6 · Method swizzling, and when it is a footgun
- 4.7 · Reading Objective-C, blocks, and manual reference counting
- 4.8 · Mixed-language projects, costs, and migrating a large app
- 4.9 · How Objective-C declarations arrive in Swift
- 4.11 · Key-value coding and observing
- 4.12 · What crosses the boundary: inference and concurrency