Skip to content

Commit f39ab2b

Browse files
committed
Updated docs for methods on NSObject
1 parent fe60f73 commit f39ab2b

File tree

1 file changed

+74
-18
lines changed

1 file changed

+74
-18
lines changed

Sources/InterposeKit/NSObject+Interpose.swift

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,52 @@ import ObjectiveC
22

33
extension NSObject {
44

5+
/// Prepares a hook for the specified method on this object.
6+
///
7+
/// Builds a block-based hook for an instance method available to the Objective-C runtime,
8+
/// with access to the original implementation.
9+
///
10+
/// The hook is returned in a pending state and must be applied using `apply()` to take effect.
11+
/// It can then be reverted using `revert()`.
12+
///
13+
/// InterposeKit installs the hook by creating a dynamic subclass at runtime and assigning it
14+
/// to the object. This ensures the hook only affects this specific object and leaves all other
15+
/// instances unchanged.
16+
///
17+
/// - Parameters:
18+
/// - selector: The selector of the method to hook.
19+
/// - methodSignature: The expected type of the original Objective-C method, declared using
20+
/// `@convention(c)`. The function must take the receiving object and selector as its first
21+
/// two parameters, e.g. `(@convention(c) (Receiver, Selector, Parameter) -> ReturnValue).self`.
22+
/// - hookSignature: The expected type of the hook block, declared using `@convention(block)`.
23+
/// It must match the method signature, excluding the `Selector` parameter, e.g.
24+
/// `(@convention(block) (Receiver, Parameter) -> ReturnValue).self`.
25+
/// - build: A closure that receives a proxy to the hook and returns the hook block.
26+
///
27+
/// - Returns: The prepared hook instance in the pending state.
28+
///
29+
/// - Throws: An ``InterposeError`` if the hook could not be prepared.
30+
///
31+
/// ### Example
32+
///
33+
/// ```swift
34+
/// let object = MyClass()
35+
/// let hook = try object.prepareHook(
36+
/// for: #selector(MyClass.getValue),
37+
/// methodSignature: (@convention(c) (MyClass, Selector) -> Int).self,
38+
/// hookSignature: (@convention(block) (MyClass) -> Int).self
39+
/// ) { hook in
40+
/// return { `self` in
41+
/// print("Before")
42+
/// let result = hook.original(self, hook.selector)
43+
/// print("After")
44+
/// return result + 1
45+
/// }
46+
/// }
47+
///
48+
/// try hook.apply()
49+
/// try hook.revert()
50+
/// ```
551
public func prepareHook<MethodSignature, HookSignature>(
652
for selector: Selector,
753
methodSignature: MethodSignature.Type,
@@ -17,35 +63,45 @@ extension NSObject {
1763
)
1864
}
1965

20-
/// Installs a hook for the specified selector on this object instance.
66+
/// Applies a hook for the specified method on this object.
2167
///
22-
/// Replaces the implementation of an instance method with a block-based hook, while providing
23-
/// access to the original implementation through a proxy.
68+
/// Builds a block-based hook for an instance method available to the Objective-C runtime,
69+
/// with access to the original implementation.
2470
///
25-
/// To be hookable, the method must be exposed to the Objective-C runtime. When written
26-
/// in Swift, it must be marked `@objc dynamic`.
71+
/// The hook takes effect immediately and can later be reverted using `revert()`.
72+
///
73+
/// InterposeKit installs the hook by creating a dynamic subclass at runtime and assigning it
74+
/// to the object. This ensures the hook only affects this specific object and leaves all other
75+
/// instances unchanged.
2776
///
2877
/// - Parameters:
29-
/// - selector: The selector of the instance method to hook.
30-
/// - methodSignature: The expected C function type of the original method implementation.
31-
/// - hookSignature: The type of the hook block.
32-
/// - build: A hook builder closure that receives a proxy to the hook (enabling access
33-
/// to the original implementation) and returns the hook block.
78+
/// - selector: The selector of the method to hook.
79+
/// - methodSignature: The expected type of the original Objective-C method, declared using
80+
/// `@convention(c)`. The function must take the receiving object and selector as its first
81+
/// two parameters, e.g. `(@convention(c) (Receiver, Selector, Parameter) -> ReturnValue).self`.
82+
/// - hookSignature: The expected type of the hook block, declared using `@convention(block)`.
83+
/// It must match the method signature, excluding the `Selector` parameter, e.g.
84+
/// `(@convention(block) (Receiver, Parameter) -> ReturnValue).self`.
85+
/// - build: A closure that receives a proxy to the hook and returns the hook block.
3486
///
35-
/// - Returns: The installed hook, which can later be reverted by calling `try hook.revert()`.
87+
/// - Returns: The applied hook instance in the active state.
3688
///
37-
/// - Throws: An error if the hook could not be applied—for example, if the method
38-
/// does not exist or is not exposed to the Objective-C runtime.
89+
/// - Throws: An ``InterposeError`` if the hook could not be applied.
3990
///
4091
/// ### Example
92+
///
4193
/// ```swift
94+
/// let object = MyClass()
4295
/// let hook = try object.applyHook(
43-
/// for: #selector(MyClass.someMethod),
44-
/// methodSignature: (@convention(c) (NSObject, Selector, Int) -> Void).self,
45-
/// hookSignature: (@convention(block) (NSObject, Int) -> Void).self
96+
/// for: #selector(MyClass.getValue),
97+
/// methodSignature: (@convention(c) (MyClass, Selector) -> Int).self,
98+
/// hookSignature: (@convention(block) (MyClass) -> Int).self
4699
/// ) { hook in
47-
/// return { `self`, parameter in
48-
/// hook.original(self, hook.selector, parameter)
100+
/// return { `self` in
101+
/// print("Before")
102+
/// let result = hook.original(self, hook.selector)
103+
/// print("After")
104+
/// return result + 1
49105
/// }
50106
/// }
51107
///

0 commit comments

Comments
 (0)