SwiftMediator
Swift componentization decoupling, router, Mirror reflection, function calls, SceneDelegate decoupling, AppDelegate decoupling. Swift组件化解耦,router,Mirror反射,函数调用,SceneDelegate解耦,AppDelegate解耦
Install / Use
/learn @zjinhu/SwiftMediatorREADME

Tool for decoupling Swift routing and module communication.
Componentized routing middleware with target-action scheme.
Support creating objects using string class name reflection, and passing dictionary parameters via Mirror reflection to assign values, achieving decoupling through strings. Supports page navigation and function method execution.
Support OpenURL method for page navigation with parameter passing.
Enable cross-module service calls and page navigation without coupling. No registration, no protocol needed -- just the target VC's class name and module name.
AppDelegate and SceneDelegate decoupling tools: only need to leave hooks in the main project. See Demo for details.
|
|
|
| ---------------- | ---------------- |
| | |
Installation
CocoaPods
-
Add
pod 'SwiftMediator'to Podfile -
Run
pod installorpod update -
Import
import SwiftMediator
Swift Package Manager
Starting from Xcode 11, Swift Package Manager is integrated and very convenient. SwiftMediator also supports SPM integration.
Select File > Swift Packages > Add Package Dependency in Xcode's menu bar, then enter:
https://github.com/zjinhu/SwiftMediator to complete integration.
Manual Installation
Drag the SwiftMediator folder from the Sources directory into your project.
Usage
Native Push / Present
// Present a view controller
SwiftMediator.shared.present("TestVC", moduleName: "SwiftMediator", paramsDic: ["str":"123123", "titleName":"23452345", "num":13, "dic":["a":12, "b":"100"]])
// Push a view controller
SwiftMediator.shared.push("TestVC", moduleName: "SwiftMediator", paramsDic: ["str":"123123", "titleName":"23452345", "num":13, "dic":["a":12, "b":"100"]])
URL Routing
SwiftMediator.shared.openUrl("app://push/SwiftMediator/TestVC?str=123&titleName=456&num=111")
SwiftUI Navigation
// Push a SwiftUI View
SwiftMediator.shared.push(MySwiftUIView(), title: "My View")
API Reference
URL Routing
URL routing automatically distinguishes between Push, Present, and fullScreen modal presentations. Parameters are extracted from the URL's scheme, host, path, and query components.
-
scheme: APP marker for deeplink, can be any value for in-app routing
-
host:
push,present, orfullScreento distinguish navigation style -
path:
/modulename/vcnameto get component name and VC name -
query:
key=value&key=valueformat, automatically converted to dictionary
/// URL routing with automatic Push/Present/fullScreen detection
/// - Parameter urlString: URL format: scheme://push|present|fullScreen/moduleName/vcName?queryParams
public func openUrl(_ urlString: String?)
Push Navigation
/// Push by class name (auto-instantiates VC)
/// - Parameters:
/// - vcName: Target view controller class name
/// - moduleName: Component bundle name (defaults to main bundle if nil)
/// - fromVC: Source view controller (defaults to top VC if nil)
/// - paramsDic: Parameter dictionary for KVC assignment
/// - animated: Whether to show animation
public func push(_ vcName: String,
moduleName: String? = nil,
fromVC: UIViewController? = nil,
paramsDic: [String: Any]? = nil,
animated: Bool = true)
/// Push with pre-initialized VC
/// - Parameters:
/// - vc: Pre-initialized view controller
/// - fromVC: Source view controller (defaults to top VC if nil)
/// - animated: Whether to show animation
public func push(_ vc: UIViewController?,
fromVC: UIViewController? = nil,
animated: Bool = true)
Pop Navigation
/// Pop to previous page
public func pop(animated: Bool = true)
/// Pop to root page
public func popToRoot(animated: Bool = true)
/// Pop to specific view controller
public func popTo(_ vc: UIViewController) -> Bool
/// Pop to view controller at index
public func popTo(_ index: Int) -> Bool
/// Pop to view controller with matching navigation bar title
public func popTo(_ navigationBarTitle: String) -> Bool
Modal Presentation
/// Present by class name (auto-instantiates VC)
/// - Parameters:
/// - vcName: Target view controller class name
/// - moduleName: Component bundle name (defaults to main bundle if nil)
/// - paramsDic: Parameter dictionary for KVC assignment
/// - fromVC: Source view controller (defaults to top VC if nil)
/// - needNav: Whether to wrap in navigation controller
/// - modelStyle: Modal presentation style
/// - animated: Whether to show animation
public func present(_ vcName: String,
moduleName: String? = nil,
paramsDic: [String: Any]? = nil,
fromVC: UIViewController? = nil,
needNav: Bool = false,
modelStyle: UIModalPresentationStyle = .fullScreen,
animated: Bool = true)
/// Present with pre-initialized VC
public func present(_ vc: UIViewController?,
fromVC: UIViewController? = nil,
needNav: Bool = false,
modelStyle: UIModalPresentationStyle = .fullScreen,
animated: Bool = true)
/// Dismiss current page (auto-detects pop vs dismiss)
public func dismissVC(animated: Bool = true)
Get Top View Controller
/// Get current top-most UINavigationController
public static func currentNavigationController() -> UINavigationController?
/// Get current top-most UIViewController
public static func currentViewController() -> UIViewController?
Object Initialization
/// Initialize UIViewController via reflection with property assignment
/// - Parameters:
/// - vcName: View controller class name
/// - moduleName: Component bundle name (defaults to main bundle if nil)
/// - dic: Parameter dictionary (properties must be marked @objc for KVC)
/// - Returns: Initialized view controller, or nil if failed
@discardableResult
public func initVC(_ vcName: String,
moduleName: String? = nil,
dic: [String: Any]? = nil) -> UIViewController?
/// Initialize UIView via reflection with property assignment
@discardableResult
public func initView(_ viewName: String,
moduleName: String? = nil,
dic: [String: Any]? = nil) -> UIView?
/// Initialize NSObject subclass via reflection with property assignment
@discardableResult
public func initObjc(_ objcName: String,
moduleName: String? = nil,
dic: [String: Any]? = nil) -> NSObject?
Method Invocation
/// Invoke instance method dynamically
/// - Note: Method must be marked @objc, e.g., @objc func myMethod(_ param: Any)
/// - Parameters:
/// - objc: Initialized object instance
/// - selName: Method name
/// - param: First parameter
/// - otherParam: Second parameter
/// - Returns: Execution result, or nil if method not found
@discardableResult
public func callObjcMethod(objc: AnyObject,
selName: String,
param: Any? = nil,
otherParam: Any? = nil) -> Unmanaged<AnyObject>?
/// Invoke class method dynamically
/// - Note: Method must be marked @objc, e.g., @objc class func myMethod(_ param: Any)
/// - Parameters:
/// - className: Class name
/// - selName: Method name
/// - moduleName: Component bundle name
/// - param: First parameter
/// - otherParam: Second parameter
/// - Returns: Execution result, or nil if class or method not found
@discardableResult
public func callClassMethod(className: String,
selName: String,
moduleName: String? = nil,
param: Any? = nil,
otherParam: Any? = nil) -> Unmanaged<AnyObject>?
SwiftUI Integration
/// Push a SwiftUI View onto the navigation stack
/// - Parameters:
/// - view: SwiftUI View
/// - title: Navigation bar title
public func push<V: View>(_ view: V, title: String? = nil)
/// Pop to view controller with matching title
public func popToTitle(_ navigationBarTitle: String) -> Bool
/// Convert SwiftUI View to UIViewController (View extension)
public func getVC() -> UIViewController
URL Encoding Utilities
/// Encode string for safe URL usage
public func urlEncoded() -> String
/// Decode URL-encoded string back to original
public func urlDecoded() -> String
Get Module Namespace
/// Get the module namespace where the object resides
public func getModuleName() -> String
AppDelegateMediator Decoupling
Used for AppDelegate decoupling. Multiple hooks can be created for various third-party initializations.
Usage:
// Create one or more hooks
class AppDe: AppDelegateMediator {
var window: UIWindow?
init(_ win: UIWindow?) {
window = win
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
print("App launched")
return true
}
func applicationWillResignActive(_ application: UIApplication) {
print("App will resign active")
}
}
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// Initialize the
