https://github.com/kealdishx/swiftloadhook
Use a hack way to achieve similar functions as Load() or initialize() in OC
https://github.com/kealdishx/swiftloadhook
hook initializer ios load swift
Last synced: 9 months ago
JSON representation
Use a hack way to achieve similar functions as Load() or initialize() in OC
- Host: GitHub
- URL: https://github.com/kealdishx/swiftloadhook
- Owner: kealdishx
- License: mit
- Created: 2018-07-15T07:49:52.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-07-28T02:14:43.000Z (over 7 years ago)
- Last Synced: 2025-03-31T06:12:41.841Z (12 months ago)
- Topics: hook, initializer, ios, load, swift
- Language: Swift
- Homepage:
- Size: 26.4 KB
- Stars: 21
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SwiftLoadHook [中文介绍](https://github.com/iiiCeBlink/SwiftLoadHook/blob/master/README_CN.md)
## Purpose
This lib uses a hack way to achieve similar functions as `Load()` or `initialize()`.
## Reason
Upon migrating a project to Swift 3.1, Xcode raises a warning:
> Method ‘initialize()’ defines Objective-C class method ‘initialize’, which is not guaranteed to be invoked by Swift and will be disallowed in future versions.
## Requirements
- iOS 8.0+
- swift 3.0+
## Usage
First, drop files under `Sources` folder to your project.
Then, your target class should conforms to `SelfAware` protocol, and implements the functions in `SelfAware` protocol.
Finally, write the code you want in `awake` function just like that in `Load()` or `Initialize()`.
## Example
This example is used to help you understand how to use, you can find the code in the files under `Example` folder. In this example, I want to swizzle the IMP of function `viewWillAppear()` in `UIViewController`.
First, `UIViewController` should conform to `SelfAware` protocol and implement functions of the protocol.
```swift
extension UIViewController: SelfAware {
static func awake() {
UIViewController.classInit()
}
static func classInit() {
swizzleMethod
}
}
```
Then, I should implement `swizzleMethod` function. while swizzling methods, we should use `dispatch_once` in `Load()` or `Initialize()` function. However, since swift 3.x, we cannot find `dispatch_once` in API. How can we handle this? We can use `static let instance` to handle with it.
```swift
@objc func swizzled_viewWillAppear(_ animated: Bool) {
swizzled_viewWillAppear(animated)
print("swizzled_viewWillAppear")
}
private static let swizzleMethod: Void = {
let originalSelector = #selector(viewWillAppear(_:))
let swizzledSelector = #selector(swizzled_viewWillAppear(_:))
swizzlingForClass(UIViewController.self, originalSelector: originalSelector, swizzledSelector: swizzledSelector)
}()
private static func swizzlingForClass(_ forClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) {
let originalMethod = class_getInstanceMethod(forClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
guard (originalMethod != nil && swizzledMethod != nil) else {
return
}
if class_addMethod(forClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) {
class_replaceMethod(forClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
```
## Thanks
@JORDAN SMITH
## Reference
[Handling the Deprecation of initialize()](http://jordansmith.io/handling-the-deprecation-of-initialize/)
## License
SwiftLoadHook is released under the MIT license. See LICENSE for details.