@@ -2,6 +2,52 @@ import ObjectiveC
22
33extension 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