Skip to content

Commit

Permalink
⭐️ Impl: Add UIViewController+Swizzling
Browse files Browse the repository at this point in the history
Summary: WIP - Initial impl. for `UIViewController+Swizzling`
  • Loading branch information
dominicstop committed Apr 12, 2023
1 parent c20627a commit 5967b6b
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
112 changes: 112 additions & 0 deletions ios/src_library/Helpers+Utilities/UIViewController+Swizzling.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//
// RNIModalSwizzledViewController.swift
// react-native-ios-modal
//
// Created by Dominic Go on 4/11/23.
//

import Foundation


extension UIViewController {

static var isSwizzled = false;

@objc fileprivate func _swizzled_present(
_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)? = nil
) {
#if DEBUG
print(
"Log - UIViewController+Swizzling"
+ " - UIViewController._swizzled_present invoked"
+ " - arg viewControllerToPresent: \(viewControllerToPresent)"
+ " - arg animated: \(flag)"
);
#endif

// call original impl.
self._swizzled_present(viewControllerToPresent, animated: flag) {
#if DEBUG
print(
"Log - UIViewController+Swizzling"
+ " - UIViewController._swizzled_present"
+ " - completion invoked"
);
#endif

completion?();
};
};

@objc fileprivate func _swizzled_dismiss(
animated flag: Bool,
completion: (() -> Void)? = nil
) {
#if DEBUG
print(
"Log - UIViewController+Swizzling"
+ " - UIViewController._swizzled_dismiss invoked"
+ " - arg animated: \(flag)"
+ " - self.presentedViewController: \(String(describing: presentedViewController))"
);
#endif

// call original impl.
self._swizzled_dismiss(animated: flag) {
#if DEBUG
print(
"Log - UIViewController+Swizzling"
+ " - UIViewController._swizzled_dismiss"
+ " - completion invoked"
);
#endif
completion?();
};
};

// TODO: Move to `RNIUtilities`
static func swizzleExchangeMethods(
defaultSelector: Selector,
newSelector: Selector,
forClass class: AnyClass
) {
let defaultInstace =
class_getInstanceMethod(`class`.self, defaultSelector);

let newInstance =
class_getInstanceMethod(`class`.self, newSelector);

guard let defaultInstance = defaultInstace,
let newInstance = newInstance
else { return };

method_exchangeImplementations(defaultInstance, newInstance);
};

internal static func swizzleMethods() {
guard RNIModalSwizzling.shouldEnableSwizzling else { return };

#if DEBUG
print(
"Log - UIViewController+Swizzling"
+ " - UIViewController.swizzleMethods invoked"
);
#endif

self.swizzleExchangeMethods(
defaultSelector: #selector(Self.present(_:animated:completion:)),
newSelector: #selector(Self._swizzled_present(_:animated:completion:)),
forClass: UIViewController.self
);

self.swizzleExchangeMethods(
defaultSelector: #selector(Self.dismiss(animated:completion:)),
newSelector: #selector(Self._swizzled_dismiss(animated:completion:)),
forClass: UIViewController.self
);

self.isSwizzled.toggle();
};
};
12 changes: 12 additions & 0 deletions ios/src_library/React Native/RNIModal/RNIModalSwizzling.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// RNIModalSwizzling.swift
// react-native-ios-modal
//
// Created by Dominic Go on 4/12/23.
//

import Foundation

public class RNIModalSwizzling {
static var shouldEnableSwizzling = true;
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class RNIModalViewManager: RCTViewManager {
override init() {
super.init();
RNIModalViewManager.sharedInstance = self;

if !UIViewController.isSwizzled {
UIViewController.swizzleMethods();
};
};

@objc override func constantsToExport() -> [AnyHashable : Any]! {
Expand Down

0 comments on commit 5967b6b

Please sign in to comment.