├── .gitignore ├── .travis.yml ├── Example ├── Podfile ├── Tests │ ├── Info.plist │ └── Tests.swift ├── TheRouter.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── TheRouter-Example.xcscheme ├── TheRouter.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── TheRouter │ ├── AnyPrifxClassTestController.swift │ ├── AppConfigServices.swift │ ├── AppDelegate.swift │ ├── Base.lproj │ └── LaunchScreen.xib │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── LARouterPresentController.swift │ ├── Main.storyboard │ ├── TheRouterApi.swift │ ├── TheRouterBController.h │ ├── TheRouterBController.m │ ├── TheRouterBaseAViewController.h │ ├── TheRouterBaseAViewController.m │ ├── TheRouterBaseBViewController.h │ ├── TheRouterBaseBViewController.m │ ├── TheRouterBaseControllerSwift.swift │ ├── TheRouterBaseViewController.h │ ├── TheRouterBaseViewController.m │ ├── TheRouterController.swift │ ├── TheRouterControllerA.swift │ ├── TheRouterControllerC.swift │ ├── TheRouterControllerD.swift │ ├── TheRouterControllerE.swift │ ├── TheRouterMacroRegisterController.swift │ ├── TheRouterModel.swift │ ├── TheRouterTabBarController.h │ ├── TheRouterTabBarController.m │ ├── TheRouterWebController.swift │ ├── TheRouter_Example-Bridging-Header.h │ └── ViewController.swift ├── LICENSE ├── README.md ├── README_CN.md ├── TheRouter-ObjectiveCDemo ├── Podfile ├── Podfile.lock ├── Pods │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── Target Support Files │ │ ├── Pods-TheRouter-ObjectiveCDemo │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-Info.plist │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-acknowledgements.markdown │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-acknowledgements.plist │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-dummy.m │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-frameworks.sh │ │ │ ├── Pods-TheRouter-ObjectiveCDemo-umbrella.h │ │ │ ├── Pods-TheRouter-ObjectiveCDemo.debug.xcconfig │ │ │ ├── Pods-TheRouter-ObjectiveCDemo.modulemap │ │ │ └── Pods-TheRouter-ObjectiveCDemo.release.xcconfig │ │ ├── TheRouter │ │ │ ├── TheRouter-Info.plist │ │ │ ├── TheRouter-dummy.m │ │ │ ├── TheRouter-prefix.pch │ │ │ ├── TheRouter-umbrella.h │ │ │ ├── TheRouter.debug.xcconfig │ │ │ ├── TheRouter.modulemap │ │ │ └── TheRouter.release.xcconfig │ │ └── Toast │ │ │ ├── Toast-Info.plist │ │ │ ├── Toast-dummy.m │ │ │ ├── Toast-prefix.pch │ │ │ ├── Toast-umbrella.h │ │ │ ├── Toast.debug.xcconfig │ │ │ ├── Toast.modulemap │ │ │ └── Toast.release.xcconfig │ ├── TheRouter.xcodeproj │ │ └── project.pbxproj │ ├── TheRouter │ │ ├── LICENSE │ │ ├── README.md │ │ └── TheRouter │ │ │ └── Classes │ │ │ ├── Decode+Extension.swift │ │ │ ├── TheRouter+Convenience.swift │ │ │ ├── TheRouter+Generate.swift │ │ │ ├── TheRouter+Jump.swift │ │ │ ├── TheRouter+Service.swift │ │ │ ├── TheRouter.swift │ │ │ ├── TheRouterBuilder.swift │ │ │ ├── TheRouterDebugTool.swift │ │ │ ├── TheRouterExtension.swift │ │ │ ├── TheRouterInterceptor.swift │ │ │ ├── TheRouterManager.swift │ │ │ ├── TheRouterParser.swift │ │ │ ├── TheRouterPattern.swift │ │ │ ├── TheRouterRequest.swift │ │ │ ├── TheRouterServiceManager.swift │ │ │ ├── TheRouterServiceProtocol.swift │ │ │ └── TheRouterable.swift │ ├── Toast.xcodeproj │ │ └── project.pbxproj │ └── Toast │ │ ├── README.md │ │ ├── Toast-Framework │ │ └── Toast.h │ │ ├── Toast │ │ ├── UIView+Toast.h │ │ └── UIView+Toast.m │ │ └── license ├── TheRouter-ObjectiveCDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── TheRouter-ObjectiveCDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── TheRouter-ObjectiveCDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── OpenRouter │ ├── TheRouterApi.swift │ ├── TheRouterBridging.swift │ └── TheRouterWebController.swift │ ├── SceneDelegate.h │ ├── SceneDelegate.m │ ├── TheRouter-ObjectiveCDemo-Bridging-Header.h │ ├── TheRouterController.h │ ├── TheRouterController.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── TheRouter.podspec ├── TheRouter ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── Decode+Extension.swift │ ├── TheRouerBridge.swift │ ├── TheRouter+Convenience.swift │ ├── TheRouter+Generate.swift │ ├── TheRouter+Jump.swift │ ├── TheRouter+Service.swift │ ├── TheRouter.swift │ ├── TheRouterBuilder.swift │ ├── TheRouterDebugTool.swift │ ├── TheRouterDynamicParamsMapping.h │ ├── TheRouterDynamicParamsMapping.m │ ├── TheRouterExtension.swift │ ├── TheRouterInterceptor.swift │ ├── TheRouterManager.swift │ ├── TheRouterParser.swift │ ├── TheRouterPattern.swift │ ├── TheRouterRequest.swift │ ├── TheRouterServiceManager.swift │ ├── TheRouterServiceProtocol.swift │ ├── TheRouterable │ ├── .gitignore │ ├── Package.swift │ └── Sources │ │ └── TheRouter │ │ └── TheRouterable.swift │ └── TheRouterableProxy.h ├── TheRouterMacro ├── .editorconfig ├── .gitignore ├── .vscode │ └── launch.json ├── Package.resolved ├── Package.swift └── Sources │ ├── TheRouterMacro │ └── TheRouterMacro.swift │ ├── TheRouterMacroClient │ └── main.swift │ └── TheRouterMacroMacros │ └── TheRouterMacroMacro.swift ├── _Pods.xcodeproj └── assets ├── IMG_7130.JPG ├── ScreenRecording.gif ├── TheRouter.png ├── chat_group.JPG ├── fetchRouterRegisterClass.png ├── loadclass_cache.png ├── opt.png ├── project.png ├── registerList_save.png ├── services.png ├── services_register.png └── vc.png /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | 21 | PodPushFile 22 | specpush.rb 23 | 24 | # Bundler 25 | .bundle 26 | 27 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 28 | # Carthage/Checkouts 29 | 30 | Carthage/Build 31 | 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 35 | # 36 | # Note: if you ignore the Pods directory, make sure to uncomment 37 | # `pod install` in .travis.yml 38 | # 39 | Example/Pods/ 40 | Example/Podfile.lock 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/ 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/TheRouter.xcworkspace -scheme TheRouter-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | platform :ios, '12.0' 4 | 5 | inhibit_all_warnings! 6 | install! 'cocoapods', 7 | disable_input_output_paths: true, 8 | generate_multiple_pod_projects: true 9 | 10 | target 'TheRouter_Example' do 11 | pod 'TheRouter', :path => '../' 12 | pod 'SnapKit', '5.6.0' 13 | pod 'Toast', '4.0.0' 14 | pod 'JKSwiftExtension' 15 | target 'TheRouter_Tests' do 16 | inherit! :search_paths 17 | 18 | 19 | end 20 | end 21 | 22 | post_install do |installer| 23 | installer.generated_projects.each do |project| 24 | project.targets.each do |target| 25 | target.build_configurations.each do |config| 26 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' 27 | config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO' 28 | config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" 29 | config.build_settings['CODE_SIGN_IDENTITY'] = '' 30 | if config.name == 'Debug' 31 | config.build_settings['STRIP_INSTALLED_PRODUCT'] = 'NO' # strip Linked product 32 | else 33 | config.build_settings['STRIP_INSTALLED_PRODUCT'] = 'YES' 34 | end 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import TheRouter 3 | 4 | class Tests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | // Put teardown code here. This method is called after the invocation of each test method in the class. 13 | super.tearDown() 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | XCTAssert(true, "Pass") 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure() { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Example/TheRouter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/TheRouter.xcodeproj/xcshareddata/xcschemes/TheRouter-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 76 | 78 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Example/TheRouter.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/TheRouter.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/TheRouter.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Example/TheRouter/AnyPrifxClassTestController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyPrifxClassTestController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 11/10/2021. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import TheRouter 11 | 12 | class AnyPrifxClassTestController: TheRouterBaseControllerSwift, TheRouterable { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | self.view.backgroundColor = .cyan 17 | } 18 | 19 | public static var patternString: [String] { 20 | ["scheme://router/anyClass_prex_test"] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Example/TheRouter/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 11/10/2021. 6 | // Copyright (c) 2021 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TheRouter 11 | /// 服务路由 12 | public let serivceHost = "scheme://services?" 13 | 14 | /// web跳转路由 15 | public let webRouterUrl = "scheme://webview/home" 16 | 17 | @UIApplicationMain 18 | class AppDelegate: UIResponder, UIApplicationDelegate { 19 | 20 | var window: UIWindow? 21 | 22 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 23 | 24 | // 日志回调,可以监控线上路由运行情况 25 | TheRouter.logcat { url, logType, errorMsg in 26 | NSLog("TheRouter: logMsg- \(url) \(logType.rawValue) \(errorMsg)") 27 | } 28 | 29 | // 类似RDVTabBarControlle也没有继承UITabbarController,导航栈也不同,那么就需要自己实现各种跳转逻辑 30 | // TheRouter.customJumpAction { jumpType, instance in 31 | // 32 | // } 33 | 34 | // 路由懒加载注册, 35 | // - excludeCocoapods: 是否对Cocoapods生成的组件进行动态注册 36 | // - excludeCocoapods = true 不对Cocoapods生成的组件进行动态注册, false 对Cocoapods生成的组件也进行遍历动态注册 37 | // - useCache: 是否开启本地缓存功能 38 | TheRouterManager.loadRouterClass(excludeCocoapods: true, useCache: false) 39 | 40 | TheRouter.lazyRegisterRouterHandle { url, userInfo in 41 | TheRouterManager.injectRouterServiceConfig(webRouterUrl, serivceHost) 42 | /// - Parameters: 43 | /// - excludeCocoapods: 排除一些非业务注册类,这里一般会将 "com.apple", "org.cocoapods" 进行过滤,但是如果组件化形式的,创建的BundleIdentifier也是 44 | /// org.cocoapods,这里需要手动改下,否则组件内的类将不会被获取。 45 | /// - urlPath: 将要打开的路由path 46 | /// - userInfo: 路由传递的参数 47 | /// - forceCheckEnable: 是否支持强制校验,强制校验要求Api声明与对应的类必须实现TheRouterAble协议 48 | /// - forceCheckEnable 强制打开TheRouterApi定义的便捷类与实现TheRouterAble协议类是否相同,打开的话,debug环境会自动检测,避免线上出问题,建议打开 49 | return TheRouterManager.addGloableRouter(true, url, userInfo, forceCheckEnable: true) 50 | } 51 | 52 | // 动态注册服务 53 | TheRouterManager.registerServices(excludeCocoapods: true) 54 | 55 | return true 56 | } 57 | 58 | func applicationWillResignActive(_ application: UIApplication) { 59 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 60 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 61 | } 62 | 63 | func applicationDidEnterBackground(_ application: UIApplication) { 64 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 65 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 66 | } 67 | 68 | func applicationWillEnterForeground(_ application: UIApplication) { 69 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 70 | } 71 | 72 | func applicationDidBecomeActive(_ application: UIApplication) { 73 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 74 | } 75 | 76 | func applicationWillTerminate(_ application: UIApplication) { 77 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 78 | } 79 | 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Example/TheRouter/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/TheRouter/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/TheRouter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/TheRouter/LARouterPresentController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LARouterController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 11/10/2021. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import TheRouter 11 | import SnapKit 12 | 13 | class LARouterPresentController: UIViewController, TheRouterable { 14 | 15 | 16 | @objc public var name: String? 17 | 18 | @objc public var value: String? 19 | 20 | lazy var backBtn: UIButton = { 21 | let btn = UIButton(type: .custom) 22 | btn.setTitleColor(.white, for: .normal) 23 | btn.setTitle("返回", for: .normal) 24 | btn.addTarget(self, action: #selector(backButtonClick), for: .touchUpInside) 25 | return btn 26 | }() 27 | 28 | @objc 29 | func backButtonClick() { 30 | self.dismiss(animated: true) { 31 | 32 | } 33 | } 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | self.view.backgroundColor = .cyan 38 | self.view.addSubview(backBtn) 39 | 40 | backBtn.snp.makeConstraints { make in 41 | make.left.equalTo(self.view.snp.left).offset(40) 42 | make.top.equalTo(self.view.snp.top).offset(100) 43 | make.width.height.equalTo(48) 44 | } 45 | 46 | print("\(self.name) -- \(self.value)") 47 | } 48 | 49 | public static var patternString: [String] { 50 | ["scheme://router/class_prex_test"] 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterApi.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterApi.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import TheRouter 11 | 12 | /** 13 | TheRouterApi 主要作用是做模块间解耦合,多个模块相互调用,抽出统一的Api,进行跨模块调用 14 | */ 15 | 16 | public class TheRouterApi: NSObject, CustomRouterInfo { 17 | 18 | public static var patternString = "scheme://router/demo" 19 | public static var routerClass = "TheRouter_Example.TheRouterController" 20 | public var params: [String: Any] { return [:] } 21 | public var jumpType: LAJumpType = .push 22 | 23 | public override init() {} 24 | } 25 | 26 | public class TheRouterTabApi: NSObject, CustomRouterInfo { 27 | 28 | public static var patternString = "scheme://router/tabbar" 29 | public static var routerClass = "TheRouterTabBarController" 30 | public var params: [String: Any] { return [:] } 31 | public var jumpType: LAJumpType = .showTab 32 | 33 | public override init() {} 34 | } 35 | 36 | 37 | public class TheRouterAApi: NSObject, CustomRouterInfo { 38 | 39 | public static var patternString = "scheme://router/demo1" 40 | public static var routerClass = "TheRouter_Example.TheRouterControllerA" 41 | public var params: [String: Any] { return ["dynamic": "value is dynamic"] } 42 | public var jumpType: LAJumpType = .push 43 | 44 | public override init() {} 45 | } 46 | 47 | public class TheRouterBApi: NSObject, CustomRouterInfo { 48 | 49 | public static var patternString = "scheme://router/demo2" 50 | public static var routerClass = "TheRouterBController" 51 | public var params: [String: Any] { return [:] } 52 | public var jumpType: LAJumpType = .push 53 | 54 | public override init() {} 55 | } 56 | 57 | public class TheRouterBaseAApi: NSObject, CustomRouterInfo { 58 | 59 | public static var patternString = "scheme://router/baseA" 60 | public static var routerClass = "TheRouterBaseAViewController" 61 | public var params: [String: Any] { return [:] } 62 | public var jumpType: LAJumpType = .push 63 | 64 | public override init() {} 65 | } 66 | 67 | public class TheRouterBaseBApi: NSObject, CustomRouterInfo { 68 | 69 | public static var patternString = "scheme://router/baseB" 70 | public static var routerClass = "TheRouterBaseBViewController" 71 | public var params: [String: Any] { return [:] } 72 | public var jumpType: LAJumpType = .push 73 | 74 | public override init() {} 75 | } 76 | 77 | 78 | public class TheRouterCApi: NSObject, CustomRouterInfo { 79 | 80 | public static var patternString = "scheme://router/demo33" 81 | public static var routerClass = "TheRouter_Example.TheRouterControllerC" 82 | public var params: [String: Any] { return ["desc":"如果直接调用TheRouterCApi进行路由跳转,此时路由地址demo33是错误的,无法进行跳转,触发断言,仅当动态下发修复之后才能跳转,测试可以注释TheRouterManager.addRelocationHandle这行代码"] } 83 | public var jumpType: LAJumpType = .push 84 | 85 | public override init() {} 86 | } 87 | 88 | public class TheRouterC3Api: NSObject, CustomRouterInfo { 89 | 90 | public static var patternString = "scheme://router/demo3" 91 | public static var routerClass = "TheRouter_Example.TheRouterControllerC" 92 | public var params: [String: Any] { return ["desc":"如果直接调用TheRouterCApi进行路由跳转,此时路由地址demo33是错误的,无法进行跳转,触发断言,仅当动态下发修复之后才能跳转,测试可以注释TheRouterManager.addRelocationHandle这行代码"] } 93 | public var jumpType: LAJumpType = .push 94 | 95 | public override init() {} 96 | } 97 | 98 | public class TheRouterDApi: NSObject, CustomRouterInfo { 99 | 100 | public static var patternString = "scheme://router/demo4" 101 | public static var routerClass = "TheRouter_Example.TheRouterControllerD" 102 | public var params: [String: Any] { return [:] } 103 | public var jumpType: LAJumpType = .push 104 | 105 | public override init() {} 106 | } 107 | 108 | public class TheRouterWebApi: NSObject, CustomRouterInfo { 109 | 110 | public static var patternString = "scheme://webview/home" 111 | public static var routerClass = "TheRouter_Example.TheRouterWebController" 112 | public var params: [String: Any] { return [:] } 113 | public var jumpType: LAJumpType = .push 114 | 115 | public override init() {} 116 | } 117 | 118 | public class TheRouterEApi:NSObject, CustomRouterInfo { 119 | 120 | public static var patternString = "scheme://router/demo9" 121 | public static var routerClass = "TheRouter_Example.TheRouterControllerE" 122 | public var params: [String: Any] { return [:] } 123 | public var jumpType: LAJumpType = .push 124 | 125 | public override init() {} 126 | } 127 | 128 | public class TheRouterLAApi:NSObject, CustomRouterInfo { 129 | 130 | public static var patternString = "scheme://router/class_prex_test" 131 | public static var routerClass = "TheRouter_Example.LARouterPresentController" 132 | public var params: [String: Any] { return [:] } 133 | public var jumpType: LAJumpType = .modal 134 | 135 | public override init() {} 136 | } 137 | 138 | public class TheRouterAnyPrifxApi:NSObject, CustomRouterInfo { 139 | 140 | public static var patternString = "scheme://router/anyClass_prex_test" 141 | public static var routerClass = "TheRouter_Example.AnyPrifxClassTestController" 142 | public var params: [String: Any] { return [:] } 143 | public var jumpType: LAJumpType = .push 144 | 145 | public override init() {} 146 | } 147 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBController.h 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TheRouterBaseViewController.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TheRouterBController : TheRouterBaseViewController 14 | 15 | @property (nonatomic, copy) QRResultBlock resultBlock; 16 | 17 | @property (nonatomic, strong) UILabel *desLabel; 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBController.m 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBController.h" 10 | @import TheRouter; 11 | @interface TheRouterBController () 12 | 13 | @end 14 | 15 | @implementation TheRouterBController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.view.backgroundColor = [UIColor yellowColor]; 20 | [self.view addSubview:self.desLabel]; 21 | 22 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 23 | if (self.resultBlock) { 24 | self.resultBlock(@"跳转成功了", true); 25 | } 26 | }); 27 | // Do any additional setup after loading the view. 28 | } 29 | 30 | - (UILabel *)desLabel { 31 | if (!_desLabel) { 32 | _desLabel = [[UILabel alloc]initWithFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width -300)/2, ([UIScreen mainScreen].bounds.size.height -200)/2, 300, 200)]; 33 | _desLabel.font = [UIFont systemFontOfSize:12]; 34 | _desLabel.numberOfLines = 0; 35 | _desLabel.textAlignment = NSTextAlignmentCenter; 36 | _desLabel.textColor = [UIColor blackColor]; 37 | } 38 | return _desLabel; 39 | } 40 | 41 | // 实现协议中的类方法 42 | + (NSArray *)patternString { 43 | return @[@"scheme://router/demo2"]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseAViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseAViewController.h 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TheRouterBaseAViewController : TheRouterBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseAViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseAViewController.m 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBaseAViewController.h" 10 | 11 | @implementation TheRouterBaseAViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | self.view.backgroundColor = [UIColor cyanColor]; 16 | } 17 | 18 | #pragma mark - ------------TheRouterableProxy------------ 19 | /// 重写实现协议中的类方法 20 | + (NSArray*)patternString { 21 | return @[@"scheme://router/baseA"]; 22 | } 23 | @end 24 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseBViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseBViewController.h 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TheRouterBaseBViewController : TheRouterBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseBViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseBViewController.m 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBaseBViewController.h" 10 | #import 11 | 12 | NSString *const TheRouterTabBarSelecIndex = @"tabBarSelecIndex"; 13 | @implementation TheRouterBaseBViewController 14 | 15 | - (void)viewDidLoad { 16 | [super viewDidLoad]; 17 | self.view.backgroundColor = [UIColor brownColor]; 18 | 19 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 20 | 21 | [TheRouerBridge openURL:@"scheme://router/tabbar?jumpType=5" userInfo:@{TheRouterTabBarSelecIndex: @1} complateHandler:^(NSDictionary * queries, UIViewController * resultVC) { 22 | 23 | }]; 24 | }); 25 | } 26 | 27 | #pragma mark - ------------TheRouterableProxy------------ 28 | /// 重写实现协议中的类方法 29 | + (NSArray*)patternString { 30 | return @[@"scheme://router/baseB"]; 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseControllerSwift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseControllerSwift.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class TheRouterBaseControllerSwift: UIViewController { 12 | 13 | public override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.view.backgroundColor = .cyan 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseViewController.h 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | // 定义Block类型 16 | typedef void (^QRResultBlock)(NSString *qrResult, BOOL qrStatus); 17 | 18 | 19 | @interface TheRouterBaseViewController : UIViewController 20 | 21 | @property (strong, nonatomic) NSDictionary *params; //!< 参数 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterBaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBaseViewController.m 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2024/4/9. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterBaseViewController.h" 10 | @import TheRouter; 11 | 12 | @interface TheRouterBaseViewController() 13 | 14 | @end 15 | @implementation TheRouterBaseViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.view.backgroundColor = [UIColor yellowColor]; 20 | NSLog(@"---> params = %@", self.params); 21 | } 22 | 23 | // 实现协议中的类方法 24 | + (NSArray *)patternString { 25 | return @[]; 26 | } 27 | 28 | + (NSUInteger)priority { 29 | return TheRouterPriorityDefault; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterViewController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/3/8. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | public typealias QrScanResultCallBack = (_ qrResult: String, _ isSucess: Bool) -> Void 15 | 16 | class TheRouterController: TheRouterBaseControllerSwift { 17 | 18 | // 扫码完成回调 19 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 20 | 21 | @objc public var desc: String = "" 22 | 23 | private lazy var resultLabel: UILabel = { 24 | let lb = UILabel() 25 | lb.textColor = .black 26 | lb.font = UIFont.systemFont(ofSize: 15) 27 | lb.textAlignment = .center 28 | lb.numberOfLines = 0 29 | return lb 30 | }() 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | self.view.backgroundColor = .white 35 | self.view.addSubview(resultLabel) 36 | 37 | resultLabel.snp.makeConstraints { make in 38 | make.width.equalTo(300) 39 | make.height.equalTo(200) 40 | make.center.equalTo(self.view.center) 41 | } 42 | 43 | self.resultLabel.text = self.desc 44 | 45 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 46 | 47 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 48 | _resultCallBack(("扫码回调了", false)) 49 | } 50 | // Do any additional setup after loading the view, typically from a nib. 51 | } 52 | 53 | override func didReceiveMemoryWarning() { 54 | super.didReceiveMemoryWarning() 55 | // Dispose of any resources that can be recreated. 56 | } 57 | 58 | } 59 | 60 | extension TheRouterController: TheRouterable { 61 | 62 | static var patternString: [String] { 63 | ["scheme://router/demo"] 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterControllerA.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterControllerA.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | 15 | @objcMembers 16 | class TheRouterControllerA: UIViewController { 17 | 18 | // 扫码完成回调 19 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 20 | 21 | @objc var desc: String = "" 22 | 23 | private lazy var resultLabel: UILabel = { 24 | let lb = UILabel() 25 | lb.textColor = .black 26 | lb.font = UIFont.systemFont(ofSize: 15) 27 | lb.textAlignment = .center 28 | lb.numberOfLines = 0 29 | return lb 30 | }() 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | self.view.backgroundColor = .orange 35 | self.view.addSubview(resultLabel) 36 | 37 | resultLabel.snp.makeConstraints { make in 38 | make.width.equalTo(300) 39 | make.height.equalTo(200) 40 | make.center.equalTo(self.view.center) 41 | } 42 | 43 | self.resultLabel.text = self.desc 44 | 45 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 46 | 47 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 48 | _resultCallBack(["扫码回调了":"1"]) 49 | } 50 | // Do any additional setup after loading the view, typically from a nib. 51 | } 52 | 53 | override func didReceiveMemoryWarning() { 54 | super.didReceiveMemoryWarning() 55 | // Dispose of any resources that can be recreated. 56 | } 57 | 58 | } 59 | 60 | extension TheRouterControllerA: TheRouterable { 61 | 62 | static var patternString: [String] { 63 | ["scheme://router/demo1"] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterControllerC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterControllerC.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | class TheRouterControllerC: TheRouterBaseControllerSwift { 15 | 16 | // 扫码完成回调 17 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 18 | 19 | @objc public var desc: String = "" 20 | 21 | private lazy var resultLabel: UILabel = { 22 | let lb = UILabel() 23 | lb.textColor = .black 24 | lb.font = UIFont.systemFont(ofSize: 15) 25 | lb.textAlignment = .center 26 | lb.numberOfLines = 0 27 | return lb 28 | }() 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | self.view.backgroundColor = .green 33 | self.view.addSubview(resultLabel) 34 | 35 | resultLabel.snp.makeConstraints { make in 36 | make.width.equalTo(300) 37 | make.height.equalTo(200) 38 | make.center.equalTo(self.view.center) 39 | } 40 | 41 | self.resultLabel.text = self.desc 42 | 43 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 44 | 45 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 46 | _resultCallBack(("扫码回调了", false)) 47 | } 48 | // Do any additional setup after loading the view, typically from a nib. 49 | } 50 | 51 | override func didReceiveMemoryWarning() { 52 | super.didReceiveMemoryWarning() 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | } 57 | 58 | extension TheRouterControllerC: TheRouterable { 59 | 60 | static var patternString: [String] { 61 | ["scheme://router/demo3", 62 | "scheme://router/demo33"] 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterControllerD.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterControllerD.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | class TheRouterControllerD: TheRouterBaseControllerSwift { 15 | 16 | // 扫码完成回调 17 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 18 | 19 | @objc public var desc: String = "" 20 | 21 | private lazy var resultLabel: UILabel = { 22 | let lb = UILabel() 23 | lb.textColor = .black 24 | lb.font = UIFont.systemFont(ofSize: 15) 25 | lb.textAlignment = .center 26 | lb.numberOfLines = 0 27 | return lb 28 | }() 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | self.view.backgroundColor = .purple 33 | self.view.addSubview(resultLabel) 34 | 35 | resultLabel.snp.makeConstraints { make in 36 | make.width.equalTo(300) 37 | make.height.equalTo(200) 38 | make.center.equalTo(self.view.center) 39 | } 40 | 41 | self.resultLabel.text = self.desc 42 | 43 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 44 | 45 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 46 | _resultCallBack(("扫码回调了", false)) 47 | } 48 | // Do any additional setup after loading the view, typically from a nib. 49 | } 50 | 51 | override func didReceiveMemoryWarning() { 52 | super.didReceiveMemoryWarning() 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | } 57 | 58 | extension TheRouterControllerD: TheRouterable { 59 | 60 | static var patternString: [String] { 61 | ["scheme://router/demo4"] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterControllerE.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterControllerE.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/11/22. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | class TheRouterControllerE: TheRouterBaseControllerSwift { 15 | 16 | // 扫码完成回调 17 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 18 | 19 | @objc public var desc: String = "" 20 | 21 | public lazy var resultLabel: UILabel = { 22 | let lb = UILabel() 23 | lb.textColor = .black 24 | lb.font = UIFont.systemFont(ofSize: 15) 25 | lb.textAlignment = .center 26 | lb.numberOfLines = 0 27 | return lb 28 | }() 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | self.view.backgroundColor = .purple 33 | self.view.addSubview(resultLabel) 34 | 35 | resultLabel.snp.makeConstraints { make in 36 | make.width.equalTo(300) 37 | make.height.equalTo(200) 38 | make.center.equalTo(self.view.center) 39 | } 40 | 41 | self.resultLabel.text = self.desc 42 | 43 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 44 | 45 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 46 | _resultCallBack(("扫码回调了", false)) 47 | } 48 | // Do any additional setup after loading the view, typically from a nib. 49 | } 50 | 51 | override func didReceiveMemoryWarning() { 52 | super.didReceiveMemoryWarning() 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | } 57 | 58 | extension TheRouterControllerE: TheRouterable { 59 | 60 | static var patternString: [String] { 61 | ["scheme://router/demo9"] 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterMacroRegisterController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterMacroRegisterController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by Jarvis on 2025/1/3. 6 | // Copyright © 2025 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import TheRouter 12 | import SnapKit 13 | 14 | @RouterPage(["scheme://router/demo-macro"]) 15 | class TheRouterMacroRegisterController: TheRouterBaseControllerSwift { 16 | 17 | // 扫码完成回调 18 | @objc public var qrResultCallBack: TheRouerParamsClosureWrapper? 19 | 20 | @objc public var desc: String = "" 21 | 22 | private lazy var resultLabel: UILabel = { 23 | let lb = UILabel() 24 | lb.textColor = .black 25 | lb.font = UIFont.systemFont(ofSize: 15) 26 | lb.textAlignment = .center 27 | lb.numberOfLines = 0 28 | return lb 29 | }() 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | self.view.backgroundColor = .magenta 34 | self.view.addSubview(resultLabel) 35 | 36 | resultLabel.snp.makeConstraints { make in 37 | make.width.equalTo(300) 38 | make.height.equalTo(200) 39 | make.center.equalTo(self.view.center) 40 | } 41 | 42 | self.resultLabel.text = self.desc 43 | 44 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { 45 | 46 | guard let _resultCallBack = self.qrResultCallBack?.closure else { return } 47 | _resultCallBack(("扫码回调了", false)) 48 | } 49 | // Do any additional setup after loading the view, typically from a nib. 50 | } 51 | 52 | override func didReceiveMemoryWarning() { 53 | super.didReceiveMemoryWarning() 54 | // Dispose of any resources that can be recreated. 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterModel.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/3/8. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct TheRouterModel: Codable { 12 | var name: String? 13 | var age: Int? 14 | } 15 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterTabBarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterTabBarController.h 3 | // TheRouter_Example 4 | // 5 | // Created by 姚亚杰 on 2024/5/31. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TheRouterTabBarController : UITabBarController 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterTabBarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterTabBarController.m 3 | // TheRouter_Example 4 | // 5 | // Created by 姚亚杰 on 2024/5/31. 6 | // Copyright © 2024 CocoaPods. All rights reserved. 7 | // 8 | 9 | #import "TheRouterTabBarController.h" 10 | #import 11 | 12 | @interface TheRouterTabBarController () 13 | 14 | @end 15 | 16 | @implementation TheRouterTabBarController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view. 21 | } 22 | 23 | + (instancetype)sharedInstance { 24 | static TheRouterTabBarController *instance = nil; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | instance = [[TheRouterTabBarController alloc] init]; 28 | }); 29 | return instance; 30 | } 31 | 32 | - (instancetype)copyWithZone:(NSZone *)zone { 33 | return self; 34 | } 35 | 36 | - (instancetype)mutableCopyWithZone:(NSZone *)zone { 37 | return self; 38 | } 39 | 40 | + (NSArray *)patternString { 41 | return @[@"scheme://router/tabbar"]; 42 | } 43 | 44 | + (NSUInteger)priority { 45 | return TheRouterPriorityDefault; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouterWebController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterWebController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/8/21. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import WebKit 11 | import TheRouter 12 | 13 | class TheRouterWebController: TheRouterBaseControllerSwift { 14 | 15 | var webView: WKWebView? 16 | 17 | @objc var url: String = "" 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | self.navigationItem.title = "WKWebView" 22 | self.initWebView() 23 | self.loadWebView(baseURL: self.url) 24 | } 25 | 26 | private func initWebView() { 27 | let preferences = WKPreferences() 28 | let userContentController = WKUserContentController() 29 | 30 | let configuration = WKWebViewConfiguration() 31 | configuration.preferences = preferences 32 | configuration.userContentController = userContentController 33 | 34 | self.webView = WKWebView(frame: self.view.bounds, configuration: configuration) 35 | self.webView?.uiDelegate = self 36 | self.webView?.navigationDelegate = self 37 | self.view.addSubview(self.webView!) 38 | } 39 | 40 | private func loadWebView(baseURL: String?) { 41 | guard let baseURL = baseURL else { return } 42 | let url = URL(string: baseURL)! 43 | let request = URLRequest(url: url) 44 | self.webView?.load(request) 45 | } 46 | 47 | 48 | } 49 | 50 | 51 | extension TheRouterWebController: WKUIDelegate, WKNavigationDelegate { 52 | 53 | // 页面开始加载时调用 54 | func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { 55 | } 56 | // 当内容开始返回时调用 57 | func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { 58 | } 59 | // 页面加载完成之后调用 60 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 61 | } 62 | 63 | // 页面加载失败时调用 64 | func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { 65 | } 66 | 67 | // 接收到服务器跳转请求之后调用 68 | func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) { 69 | } 70 | } 71 | 72 | 73 | extension TheRouterWebController: WKScriptMessageHandler { 74 | 75 | func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { } 76 | 77 | } 78 | 79 | extension TheRouterWebController: TheRouterable { 80 | 81 | static var patternString: [String] { 82 | ["scheme://webview/home"] 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Example/TheRouter/TheRouter_Example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "TheRouterBController.h" 6 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | source 'https://github.com/CocoaPods/Specs.git' 3 | 4 | platform :ios, '11.0' 5 | 6 | inhibit_all_warnings! 7 | install! 'cocoapods', 8 | disable_input_output_paths: true, 9 | generate_multiple_pod_projects: true 10 | 11 | target 'TheRouter-ObjectiveCDemo' do 12 | # Comment the next line if you don't want to use dynamic frameworks 13 | pod 'TheRouter', '1.1.5' 14 | pod 'Toast', '4.0.0' 15 | end 16 | 17 | post_install do |installer| 18 | installer.generated_projects.each do |project| 19 | project.targets.each do |target| 20 | target.build_configurations.each do |config| 21 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' 22 | config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO' 23 | config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" 24 | config.build_settings['CODE_SIGN_IDENTITY'] = '' 25 | if config.name == 'Debug' 26 | config.build_settings['STRIP_INSTALLED_PRODUCT'] = 'NO' # strip Linked product 27 | else 28 | config.build_settings['STRIP_INSTALLED_PRODUCT'] = 'YES' 29 | end 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TheRouter (1.1.5) 3 | - Toast (4.0.0) 4 | 5 | DEPENDENCIES: 6 | - TheRouter (= 1.1.5) 7 | - Toast (= 4.0.0) 8 | 9 | SPEC REPOS: 10 | https://github.com/CocoaPods/Specs.git: 11 | - TheRouter 12 | - Toast 13 | 14 | SPEC CHECKSUMS: 15 | TheRouter: 00d0b05bd06b5cf6e7df1ef00f0ebc92ee9c954a 16 | Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 17 | 18 | PODFILE CHECKSUM: 5f94f01c46f6a0697f0571b2d52c4474f6af608b 19 | 20 | COCOAPODS: 1.13.0 21 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TheRouter (1.1.5) 3 | - Toast (4.0.0) 4 | 5 | DEPENDENCIES: 6 | - TheRouter (= 1.1.5) 7 | - Toast (= 4.0.0) 8 | 9 | SPEC REPOS: 10 | https://github.com/CocoaPods/Specs.git: 11 | - TheRouter 12 | - Toast 13 | 14 | SPEC CHECKSUMS: 15 | TheRouter: 00d0b05bd06b5cf6e7df1ef00f0ebc92ee9c954a 16 | Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 17 | 18 | PODFILE CHECKSUM: 5f94f01c46f6a0697f0571b2d52c4474f6af608b 19 | 20 | COCOAPODS: 1.13.0 21 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TheRouter_ObjectiveCDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TheRouter_ObjectiveCDemo 5 | @end 6 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_TheRouter_ObjectiveCDemoVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_TheRouter_ObjectiveCDemoVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | ENABLE_BITCODE = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter" "${PODS_CONFIGURATION_BUILD_DIR}/Toast" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter/TheRouter.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast/Toast.framework/Headers" 7 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 8 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 9 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter/TheRouter.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Toast/Toast.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Toast" 10 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "Foundation" -framework "QuartzCore" -framework "TheRouter" -framework "Toast" -framework "UIKit" 11 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 12 | PODS_BUILD_DIR = ${BUILD_DIR} 13 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 14 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 15 | PODS_ROOT = ${SRCROOT}/Pods 16 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_TheRouter_ObjectiveCDemo { 2 | umbrella header "Pods-TheRouter-ObjectiveCDemo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Pods-TheRouter-ObjectiveCDemo/Pods-TheRouter-ObjectiveCDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | ENABLE_BITCODE = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter" "${PODS_CONFIGURATION_BUILD_DIR}/Toast" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter/TheRouter.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast/Toast.framework/Headers" 7 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 8 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 9 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter/TheRouter.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Toast/Toast.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/TheRouter" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Toast" 10 | OTHER_LDFLAGS = $(inherited) -ObjC -framework "Foundation" -framework "QuartzCore" -framework "TheRouter" -framework "Toast" -framework "UIKit" 11 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 12 | PODS_BUILD_DIR = ${BUILD_DIR} 13 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 14 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 15 | PODS_ROOT = ${SRCROOT}/Pods 16 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 17 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 18 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.5 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_TheRouter : NSObject 3 | @end 4 | @implementation PodsDummy_TheRouter 5 | @end 6 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double TheRouterVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char TheRouterVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/TheRouter 3 | ENABLE_BITCODE = NO 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings 6 | OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/TheRouter 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter.modulemap: -------------------------------------------------------------------------------- 1 | framework module TheRouter { 2 | umbrella header "TheRouter-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/TheRouter/TheRouter.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/TheRouter 3 | ENABLE_BITCODE = NO 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings 6 | OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/TheRouter 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Toast : NSObject 3 | @end 4 | @implementation PodsDummy_Toast 5 | @end 6 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "UIView+Toast.h" 14 | #import "Toast.h" 15 | 16 | FOUNDATION_EXPORT double ToastVersionNumber; 17 | FOUNDATION_EXPORT const unsigned char ToastVersionString[]; 18 | 19 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Toast 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = $(inherited) -framework "QuartzCore" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Toast 10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 14 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast.modulemap: -------------------------------------------------------------------------------- 1 | framework module Toast { 2 | umbrella header "Toast-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Target Support Files/Toast/Toast.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Toast 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = $(inherited) -framework "QuartzCore" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Toast 10 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 14 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/Decode+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Decode+Extension.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/6/24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct JSONCodingKeys: CodingKey { 11 | var stringValue: String 12 | 13 | init(stringValue: String) { 14 | self.stringValue = stringValue 15 | } 16 | 17 | var intValue: Int? 18 | 19 | init?(intValue: Int) { 20 | self.init(stringValue: "\(intValue)") 21 | self.intValue = intValue 22 | } 23 | } 24 | 25 | extension KeyedDecodingContainer { 26 | 27 | func decode(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary { 28 | let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) 29 | return try container.decode(type) 30 | } 31 | 32 | func decodeIfPresent(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary? { 33 | guard contains(key) else { 34 | return nil 35 | } 36 | return try decode(type, forKey: key) 37 | } 38 | 39 | func decode(_ type: Array.Type, forKey key: K) throws -> Array { 40 | var container = try self.nestedUnkeyedContainer(forKey: key) 41 | return try container.decode(type) 42 | } 43 | 44 | func decodeIfPresent(_ type: Array.Type, forKey key: K) throws -> Array? { 45 | guard contains(key) else { 46 | return nil 47 | } 48 | return try decode(type, forKey: key) 49 | } 50 | 51 | func decode(_ type: Dictionary.Type) throws -> Dictionary { 52 | var dictionary = Dictionary() 53 | 54 | for key in allKeys { 55 | if let boolValue = try? decode(Bool.self, forKey: key) { 56 | dictionary[key.stringValue] = boolValue 57 | } else if let stringValue = try? decode(String.self, forKey: key) { 58 | dictionary[key.stringValue] = stringValue 59 | } else if let intValue = try? decode(Int.self, forKey: key) { 60 | dictionary[key.stringValue] = intValue 61 | } else if let doubleValue = try? decode(Double.self, forKey: key) { 62 | dictionary[key.stringValue] = doubleValue 63 | } else if let nestedDictionary = try? decode(Dictionary.self, forKey: key) { 64 | dictionary[key.stringValue] = nestedDictionary 65 | } else if let nestedArray = try? decode(Array.self, forKey: key) { 66 | dictionary[key.stringValue] = nestedArray 67 | } 68 | } 69 | return dictionary 70 | } 71 | } 72 | 73 | extension UnkeyedDecodingContainer { 74 | 75 | mutating func decode(_ type: Array.Type) throws -> Array { 76 | var array: [Any] = [] 77 | while isAtEnd == false { 78 | if let value = try? decode(Bool.self) { 79 | array.append(value) 80 | } else if let value = try? decode(Double.self) { 81 | array.append(value) 82 | } else if let value = try? decode(String.self) { 83 | array.append(value) 84 | } else if let nestedDictionary = try? decode(Dictionary.self) { 85 | array.append(nestedDictionary) 86 | } else if let nestedArray = try? decode(Array.self) { 87 | array.append(nestedArray) 88 | } 89 | } 90 | return array 91 | } 92 | 93 | mutating func decode(_ type: Dictionary.Type) throws -> Dictionary { 94 | 95 | let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self) 96 | return try nestedContainer.decode(type) 97 | } 98 | } 99 | 100 | extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys { 101 | mutating func encode(_ value: Dictionary) throws { 102 | try value.forEach({ (key, value) in 103 | let key = JSONCodingKeys(stringValue: key) 104 | switch value { 105 | case let value as Bool: 106 | try encode(value, forKey: key) 107 | case let value as Int: 108 | try encode(value, forKey: key) 109 | case let value as String: 110 | try encode(value, forKey: key) 111 | case let value as Double: 112 | try encode(value, forKey: key) 113 | case let value as Dictionary: 114 | try encode(value, forKey: key) 115 | case let value as Array: 116 | try encode(value, forKey: key) 117 | case Optional.none: 118 | try encodeNil(forKey: key) 119 | default: 120 | throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + [key], debugDescription: "Invalid JSON value")) 121 | } 122 | }) 123 | } 124 | } 125 | 126 | extension KeyedEncodingContainerProtocol { 127 | mutating func encode(_ value: Dictionary?, forKey key: Key) throws { 128 | if value != nil { 129 | var container = self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) 130 | try container.encode(value!) 131 | } 132 | } 133 | 134 | mutating func encode(_ value: Array?, forKey key: Key) throws { 135 | if value != nil { 136 | var container = self.nestedUnkeyedContainer(forKey: key) 137 | try container.encode(value!) 138 | } 139 | } 140 | } 141 | 142 | extension UnkeyedEncodingContainer { 143 | mutating func encode(_ value: Array) throws { 144 | try value.enumerated().forEach({ (index, value) in 145 | switch value { 146 | case let value as Bool: 147 | try encode(value) 148 | case let value as Int: 149 | try encode(value) 150 | case let value as String: 151 | try encode(value) 152 | case let value as Double: 153 | try encode(value) 154 | case let value as Dictionary: 155 | try encode(value) 156 | case let value as Array: 157 | try encode(value) 158 | case Optional.none: 159 | try encodeNil() 160 | default: 161 | let keys = JSONCodingKeys(intValue: index).map({ [$0] }) ?? [] 162 | throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + keys, debugDescription: "Invalid JSON value")) 163 | } 164 | }) 165 | } 166 | 167 | mutating func encode(_ value: Dictionary) throws { 168 | var nestedContainer = self.nestedContainer(keyedBy: JSONCodingKeys.self) 169 | try nestedContainer.encode(value) 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouter+Convenience.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Convenience.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import UIKit 9 | 10 | public extension TheRouter { 11 | 12 | /// addRouterItem with parasing the dictionary, the class which match the className need inherit the protocol of TheRouterable 13 | /// 14 | class func addRouterItem(_ routerItem: RouteItem) { 15 | addRouterItem(routerItem.path, classString: routerItem.className) 16 | } 17 | 18 | /// addRouterItem with parasing the dictionary, the class which match the className need inherit the protocol of TheRouterable 19 | /// 20 | /// - Parameter dictionary: [patternString: className] 21 | class func addRouterItem(_ dictionary: [String: String]) { 22 | dictionary.forEach { (key: String, value: String) in 23 | addRouterItem(key, classString: value) 24 | } 25 | } 26 | 27 | /// convienience addRouterItem with className 28 | /// 29 | /// - Parameters: 30 | /// - patternString: register urlstring 31 | /// - classString: the class which match the className need inherit the protocol of TheRouterable 32 | class func addRouterItem(_ patternString: String, priority: uint = 0, classString: String) { 33 | let clz: AnyClass? = classString.trimmingCharacters(in: CharacterSet.whitespaces).la_matchClass() 34 | if let routerable = clz as? TheRouterable.Type { 35 | self.addRouterItem(patternString.trimmingCharacters(in: CharacterSet.whitespaces), priority: priority, handle: routerable.registerAction) 36 | } else { 37 | shareInstance.logcat?(patternString, .logError, "\(classString) register router error, please implementation the TheRouterable Protocol") 38 | assert(clz as? TheRouterable.Type != nil, "register router error, please implementation the TheRouterable Protocol") 39 | } 40 | } 41 | 42 | /// addRouterItem 43 | /// 44 | /// - Parameters: 45 | /// - patternString: register urlstring 46 | /// - priority: match priority, sort by inverse order 47 | /// - handle: block of refister URL 48 | class func addRouterItem(_ patternString: String, priority: uint = 0, handle: @escaping TheRouterPattern.HandleBlock) { 49 | shareInstance.addRouterItem(patternString.trimmingCharacters(in: CharacterSet.whitespaces), priority: priority, handle: handle) 50 | } 51 | 52 | /// addRouterItem 53 | /// 54 | /// - Parameters: 55 | /// - whiteList: whiteList for intercept 56 | /// - priority: match priority, sort by inverse order 57 | /// - handle: block of interception 58 | class func addRouterInterceptor(_ whiteList: [String] = [String](), priority: uint = 0, handle: @escaping TheRouterInterceptor.InterceptorHandleBlock) { 59 | shareInstance.addRouterInterceptor(whiteList, priority: priority, handle: handle) 60 | } 61 | 62 | /// addFailedHandel 63 | class func globalOpenFailedHandler(_ handel: @escaping FailedHandleBlock) { 64 | shareInstance.globalOpenFailedHandler(handel) 65 | } 66 | 67 | /// LazyRegister 68 | class func lazyRegisterRouterHandle(_ handel: @escaping LazyRegisterHandleBlock) { 69 | shareInstance.lazyRegisterRouterHandle(handel) 70 | } 71 | 72 | /// addRouterItemLogHandle 73 | class func logcat(_ handle: @escaping RouterLogHandleBlock) { 74 | shareInstance.logcat(handle) 75 | } 76 | 77 | /// removeRouter by register urlstring 78 | /// 79 | /// - Parameter patternString: register urlstring 80 | class func removeRouter(_ patternString: String) { 81 | shareInstance.removeRouter(patternString.trimmingCharacters(in: CharacterSet.whitespaces)) 82 | } 83 | 84 | /// Check whether register for url 85 | /// 86 | /// - Parameter urlString: real request urlstring 87 | /// - Returns: whether register 88 | class func canOpenURL(_ urlString: String) -> Bool { 89 | return shareInstance.canOpenURL(urlString.trimmingCharacters(in: CharacterSet.whitespaces)) 90 | } 91 | 92 | /// request for url 93 | /// 94 | /// - Parameters: 95 | /// - urlString: real request urlstring 96 | /// - userInfo: custom userInfo, could contain Object 97 | /// - Returns: response for request, contain pattern and queries 98 | class func requestURL(_ urlString: String, userInfo: [String: Any] = [String: Any]()) -> RouteResponse { 99 | return shareInstance.requestURL(urlString.trimmingCharacters(in: CharacterSet.whitespaces), userInfo: userInfo) 100 | } 101 | 102 | // injectRouterServiceConfig 103 | class func injectRouterServiceConfig(_ webPath: String?, _ serviceHost: String) { 104 | return shareInstance.injectRouterServiceConfig(webPath, serviceHost) 105 | } 106 | 107 | /// Is the route loaded 108 | /// - Parameter loadStatus: router paths loadStatus 109 | class func routerLoadStatus(_ loadStatus: Bool) { 110 | return shareInstance.routerLoadStatus(loadStatus) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouter+Generate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Generate.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/11/29. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | // MARK: - Constants 12 | // 跳转类型Key 13 | public let LAJumpTypeKey = "jumpType" 14 | // 第一个参数Key 15 | public let TheRouterIvar1Key = "ivar1" 16 | // 第二个参数Key 17 | public let TheRouterIvar2Key = "ivar2" 18 | // 返回值类型Key 19 | public let TheRouterFunctionResultKey = "resultType" 20 | // 路由Path常量Key 21 | public let TheRouterPath = "path" 22 | // 路由class常量Key 23 | public let TheRouterClassName = "class" 24 | //路由priority常量Key 25 | public let TheRouterPriority = "priority" 26 | 27 | //路由优先级默认值 28 | public let TheRouterDefaultPriority: UInt = 1000 29 | 30 | public typealias ComplateHandler = (([String: Any]?, Any?) -> Void)? 31 | 32 | // constants 33 | public extension TheRouter { 34 | static let patternKey = "patternKey" 35 | static let requestURLKey = "requestURLKey" 36 | static let matchFailedKey = "matchFailedKey" 37 | static let urlKey = "url" 38 | static let userInfoKey = "userInfo" 39 | } 40 | 41 | // 跳转方式 42 | @objc public enum LAJumpType: Int { 43 | case modal 44 | case push 45 | case popToTaget 46 | case windowNavRoot 47 | case modalDismissBeforePush 48 | } 49 | 50 | public struct RouteItem { 51 | 52 | public var path: String = "" 53 | public var className: String = "" 54 | public var action: String = "" 55 | public var descriptions: String = "" 56 | public var params: [String: Any] = [:] 57 | 58 | public init(path: String, className: String, action: String = "", descriptions: String = "", params: [String: Any] = [:]) { 59 | self.path = path 60 | self.className = className 61 | self.action = action 62 | self.descriptions = descriptions 63 | self.params = params 64 | } 65 | } 66 | 67 | // 动态路由调用方法返回类型 68 | @objc public enum TheRouterFunctionResultType: Int { 69 | case voidType // 无返回值类型 70 | case valueType // 值类型 71 | case referenceType // 引用类型 72 | } 73 | 74 | /// 远端下发路由数据 75 | @objc public enum TheRouterReloadMapEnum: Int { 76 | case none 77 | case replace 78 | case add 79 | case delete 80 | case reset 81 | } 82 | 83 | // 日志类型 84 | @objc public enum TheRouterLogType: Int { 85 | case logNormal 86 | case logError 87 | } 88 | 89 | public extension URL { 90 | var urlParameters: [String: String]? { 91 | guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), 92 | let queryItems = components.queryItems else { return nil } 93 | return queryItems.reduce(into: [String: String]()) { (result, item) in 94 | result[item.name] = item.value 95 | } 96 | } 97 | } 98 | 99 | extension TheRouter { 100 | 101 | // MARK: - Convenience method 102 | public class func generate(_ patternString: String, params: [String: Any] = [String: Any](), jumpType: LAJumpType) -> (String, [String: Any]) { 103 | 104 | if let url = URL(string: patternString) { 105 | let orginParams = url.urlParameters ?? [String: Any]() 106 | var queries = params 107 | queries[LAJumpTypeKey] = "\(jumpType.rawValue)" 108 | 109 | for (key, value) in orginParams.reversed() { 110 | queries[key] = value 111 | } 112 | return (patternString, queries) 113 | } 114 | 115 | return ("", [String: Any]()) 116 | } 117 | 118 | } 119 | 120 | public protocol CustomRouterInfo { 121 | static var patternString: String { get } 122 | static var routerClass: String { get } 123 | var params: [String: Any] { get } 124 | var jumpType: LAJumpType { get } 125 | } 126 | 127 | extension CustomRouterInfo { 128 | public var requiredURL: (String, [String: Any]) { 129 | return TheRouter.generate(Self.patternString, params: self.params, jumpType: self.jumpType) 130 | } 131 | } 132 | 133 | public struct TheRouterInfo: Decodable { 134 | public init() {} 135 | 136 | public var targetPath: String? 137 | public var orginPath: String? 138 | public var routerType: Int = 0 // 1: 表示替换或者修复客户端代码path错误 2: 新增路由path 3:删除路由 4: 重置路由 139 | public var path: String? // 新的路由地址 140 | public var className: String? // 路由地址对应的界面 141 | public var params: [String: Any]? 142 | 143 | enum CodingKeys: String, CodingKey { 144 | case targetPath 145 | case orginPath 146 | case path 147 | case className 148 | case routerType 149 | case params 150 | } 151 | 152 | public init(from decoder: Decoder) throws { 153 | 154 | let container = try decoder.container(keyedBy: CodingKeys.self) 155 | targetPath = try container.decodeIfPresent(String.self, forKey: CodingKeys.targetPath) 156 | orginPath = try container.decodeIfPresent(String.self, forKey: CodingKeys.orginPath) 157 | routerType = try container.decode(Int.self, forKey: CodingKeys.routerType) 158 | path = try container.decodeIfPresent(String.self, forKey: CodingKeys.path) 159 | className = try container.decodeIfPresent(String.self, forKey: CodingKeys.className) 160 | params = try container.decodeIfPresent(Dictionary.self, forKey: CodingKeys.params) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouter+Service.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Service.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension TheRouter { 11 | // MARK: - Register With Service Name 12 | /// 通过服务名称(named)注册LAServiceCreator 13 | /// - Parameters: 14 | /// - named: 服务名称 15 | /// - creator: 服务构造者 16 | class func registerService(named: String, creator: @escaping LAServiceCreator) { 17 | TheRouterServiceManager.default.registerService(named: named, creator: creator) 18 | } 19 | 20 | /// 通过服务名称(named)注册一个服务实例 (存在缓存中) 21 | /// - Parameters: 22 | /// - named: 服务名称 23 | /// - instance: 服务实例 24 | class func registerService(named: String, instance: Any) { 25 | TheRouterServiceManager.default.registerService(named: named, instance: instance) 26 | } 27 | 28 | /// 通过服务名称(named)注册LAServiceCreator 29 | /// - Parameters: 30 | /// - named: 服务名称 31 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 32 | class func registerService(named: String, lazyCreator: @escaping @autoclosure LAServiceCreator) { 33 | TheRouterServiceManager.default.registerService(named: named, lazyCreator: lazyCreator) 34 | } 35 | 36 | // MARK: - Register With Service Type 37 | /// 通过服务接口注册LAServiceCreator 38 | /// - Parameters: 39 | /// - service: 服务接口 40 | /// - creator: 服务构造者 41 | class func registerService(_ service: Service.Type, creator: @escaping () -> Service) { 42 | TheRouterServiceManager.default.registerService(service, creator: creator) 43 | } 44 | 45 | /// 通过服务接口注册LAServiceCreator 46 | /// - Parameters: 47 | /// - service: 服务接口 48 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 49 | class func registerService(_ service: Service.Type, lazyCreator: @escaping @autoclosure () -> Service) { 50 | TheRouterServiceManager.default.registerService(service, lazyCreator: lazyCreator()) 51 | } 52 | 53 | /// 通过服务接口注册一个服务实例 (存在缓存中) 54 | /// - Parameters: 55 | /// - service: 服务接口 56 | /// - instance: 服务实例 57 | class func registerService(_ service: Service.Type, instance: Service) { 58 | TheRouterServiceManager.default.registerService(service, instance: instance) 59 | } 60 | } 61 | 62 | public extension TheRouter { 63 | 64 | /// 根据服务名称创建服务(如果缓存中已有服务实例,则不需要创建) 65 | /// - Parameters: 66 | /// - named: 服务名称 67 | /// - shouldCache: 是否需要缓存 68 | @discardableResult 69 | class func createService(named: String, shouldCache: Bool = true) -> Any? { 70 | return TheRouterServiceManager.default.createService(named: named) 71 | } 72 | 73 | /// 根据服务接口创建服务(如果缓存中已有服务实例,则不需要创建) 74 | /// - Parameters: 75 | /// - service: 服务接口 76 | /// - shouldCache: 是否需要缓存 77 | @discardableResult 78 | class func createService(_ service: Service.Type, shouldCache: Bool = true) -> Service? { 79 | return TheRouterServiceManager.default.createService(service) 80 | } 81 | 82 | /// 通过服务名称获取服务 83 | /// - Parameter named: 服务名称 84 | @discardableResult 85 | class func getService(named: String) -> Any? { 86 | return TheRouterServiceManager.default.getService(named: named) 87 | } 88 | 89 | /// 通过服务接口获取服务 90 | /// - Parameter service: 服务接口 91 | @discardableResult 92 | class func getService(_ service: Service.Type) -> Service? { 93 | return TheRouterServiceManager.default.getService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBuilder.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/3/9. 6 | // 7 | 8 | import Foundation 9 | 10 | public class TheRouterBuilder { 11 | 12 | public var buildResult: (String, [String: Any]) = ("", [:]) 13 | 14 | public init () {} 15 | } 16 | 17 | extension TheRouterBuilder { 18 | 19 | @discardableResult 20 | public class func build(_ path: String) -> TheRouterBuilder { 21 | let builder = TheRouterBuilder.init() 22 | builder.buildPaths(path: path) 23 | return builder 24 | } 25 | 26 | @discardableResult 27 | public func withInt(key: String, value: Int) -> Self { 28 | buildResult.1[key] = value 29 | return self 30 | } 31 | 32 | @discardableResult 33 | public func withString(key: String, value: String) -> Self { 34 | buildResult.1[key] = value 35 | return self 36 | } 37 | 38 | @discardableResult 39 | public func withBool(key: String, value: Bool) -> Self { 40 | buildResult.1[key] = value 41 | return self 42 | } 43 | 44 | @discardableResult 45 | public func withDouble(key: String, value: Double) -> Self { 46 | buildResult.1[key] = value 47 | return self 48 | } 49 | 50 | @discardableResult 51 | public func withFloat(key: String, value: Float) -> Self { 52 | buildResult.1[key] = value 53 | return self 54 | } 55 | 56 | @discardableResult 57 | public func withAny(key: String, value: Any) -> Self { 58 | buildResult.1[key] = value 59 | return self 60 | } 61 | 62 | func buildPaths(path: String) { 63 | buildResult.0 = path 64 | } 65 | 66 | @discardableResult 67 | public func buildService(_ protocolInstance: TheRouterServiceProtocol.Type, methodName: String) -> Self { 68 | let protocolName = String(describing: protocolInstance) 69 | buildResult.0 = "\(TheRouter.shareInstance.serviceHost)protocol=\(protocolName)&method=\(methodName)" 70 | return self 71 | } 72 | 73 | @discardableResult 74 | public func buildServicePath(_ protocolInstance: TheRouterServiceProtocol.Type, methodName: String) -> String { 75 | let protocolName = String(describing: protocolInstance) 76 | return "\(TheRouter.shareInstance.serviceHost)protocol=\(protocolName)&method=\(methodName)" 77 | } 78 | 79 | @discardableResult 80 | func buildService(path: String) -> Self { 81 | buildResult.0 = path 82 | return self 83 | } 84 | 85 | @discardableResult 86 | public func buildDictionary(param: [String: Any]) -> Self { 87 | buildResult.1.merge(dic: param) 88 | return self 89 | } 90 | 91 | @discardableResult 92 | public func fetchService() -> Any? { 93 | let result = TheRouter.generate(buildResult.0, params: buildResult.1, jumpType: .push) 94 | TheRouter.shareInstance.logcat?(buildResult.0, .logNormal, "") 95 | return TheRouter.openURL(result) 96 | } 97 | 98 | public func navigation(_ handler: ComplateHandler = nil) { 99 | TheRouter.openURL(buildResult, complateHandler: handler) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterDebugTool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterDebugTool.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/11/22. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | public class TheRouterDebugTool { 12 | /// 检测 是否 被追踪 13 | @inline(__always) 14 | public static func checkTracing() -> Bool { 15 | let mib = UnsafeMutablePointer.allocate(capacity: 4) 16 | mib[0] = CTL_KERN//内核查看 17 | mib[1] = KERN_PROC//进程查看 18 | mib[2] = KERN_PROC_PID//进程ID 19 | mib[3] = getpid()//获取pid 20 | var size: Int = MemoryLayout.size 21 | var info: kinfo_proc? = nil 22 | /* 函数的返回值若为0时,证明没有错误,其他数字为错误码。 arg1 传入一个数组,该数组中的第一个元素指定本请求定向到内核的哪个子系统。第二个及其后元素依次细化指定该系统的某个部分。 arg2 数组中的元素数目 arg3 一个结构体,指向一个供内核存放该值的缓冲区,存放进程查询结果 arg4 缓冲区的大小 arg5/arg6 为了设置某个新值,arg5参数指向一个大小为arg6参数值的缓冲区。如果不准备指定一个新值,那么arg5应为一个空指针,arg6因为0. */ 23 | sysctl(mib, 4, &info, &size, nil, 0) 24 | //info.kp_proc.p_flag中存放的是标志位(二进制),在proc.h文件中有p_flag的宏定义,通过&运算可知对应标志位的值是否为0。(若结果值为0则对应标志位为0)。其中P_TRACED为正在跟踪调试过程。 25 | if (info.unsafelyUnwrapped.kp_proc.p_flag & P_TRACED) > 0 { 26 | //监听到被调试 27 | return true 28 | } 29 | return false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LACommonExtension.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension String { 11 | 12 | func containsSubString(substring: String) -> Bool { 13 | return range(of: substring) != nil 14 | } 15 | 16 | func la_dropFirst(_ count: Int) -> String { 17 | let start = self.index(startIndex, offsetBy: 0) 18 | let end = self.index(start, offsetBy: count) 19 | let results = self[start...end] 20 | return String(results) 21 | } 22 | 23 | func la_dropLast(_ count: Int) -> String { 24 | let start = self.index(endIndex, offsetBy: 0) 25 | let end = self.index(endIndex, offsetBy: -count) 26 | let results = self[start...end] 27 | return String(results) 28 | } 29 | 30 | func la_matchClass() -> AnyClass? { 31 | 32 | if let cls: AnyClass = NSClassFromString(self) { 33 | return cls 34 | } 35 | return nil 36 | } 37 | } 38 | 39 | // MARK:- 一、基本的扩展 40 | public extension Dictionary { 41 | 42 | // MARK: 1.1、检查字典里面是否有某个 key 43 | /// 检查字典里面是否有某个 key 44 | func has(_ key: Key) -> Bool { 45 | return index(forKey: key) != nil 46 | } 47 | 48 | // MARK: 1.2、字典的key或者value组成的数组 49 | /// 字典的key或者value组成的数组 50 | /// - Parameter map: map 51 | /// - Returns: 数组 52 | func toArray(_ map: (Key, Value) -> V) -> [V] { 53 | return self.map(map) 54 | } 55 | 56 | // MARK: 1.3、JSON字符串 -> 字典 57 | /// JsonString转为字典 58 | /// - Parameter json: JSON字符串 59 | /// - Returns: 字典 60 | static func jsonToDictionary(json: String) -> Dictionary? { 61 | if let data = (try? JSONSerialization.jsonObject( 62 | with: json.data(using: String.Encoding.utf8, 63 | allowLossyConversion: true)!, 64 | options: JSONSerialization.ReadingOptions.mutableContainers)) as? Dictionary { 65 | return data 66 | } else { 67 | return nil 68 | } 69 | } 70 | 71 | // MARK: 1.4、字典 -> JSON字符串 72 | /// 字典转换为JSONString 73 | func toJSON() -> String? { 74 | if let jsonData = try? JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions()) { 75 | let jsonStr = String(data: jsonData, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) 76 | return String(jsonStr ?? "") 77 | } 78 | return nil 79 | } 80 | 81 | // MARK: 1.5、字典里面所有的 key 82 | /// 字典里面所有的key 83 | /// - Returns: key 数组 84 | func allKeys() -> [Key] { 85 | /* 86 | shuffled:不会改变原数组,返回一个新的随机化的数组。 可以用于let 数组 87 | */ 88 | return self.keys.shuffled() 89 | } 90 | 91 | // MARK: 1.6、字典里面所有的 value 92 | /// 字典里面所有的value 93 | /// - Returns: value 数组 94 | func allValues() -> [Value] { 95 | return self.values.shuffled() 96 | } 97 | 98 | /// MARK: 1.7、用于字典的合并 99 | mutating func merge(dic:Dictionary) { 100 | self.merge(dic) { (parama1, parama2) -> Value in 101 | return parama1 102 | } 103 | } 104 | 105 | mutating func la_combine(_ dict: Dictionary) { 106 | var tem = self 107 | dict.forEach({ (key, value) in 108 | if let existValue = tem[key] { 109 | // combine same name query 110 | if let arrValue = existValue as? [Value] { 111 | tem[key] = (arrValue + [value]) as? Value 112 | } else { 113 | tem[key] = ([existValue, value]) as? Value 114 | } 115 | } else { 116 | tem[key] = value 117 | } 118 | }) 119 | self = tem 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterInterceptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterInterceptor.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import UIKit 9 | 10 | public class TheRouterInterceptor: NSObject { 11 | 12 | public typealias InterceptorHandleBlock = ([String: Any]) -> Bool 13 | 14 | var priority: uint 15 | var whiteList: [String] 16 | var handle: InterceptorHandleBlock 17 | 18 | init(_ whiteList: [String], 19 | priority: uint, 20 | handle: @escaping InterceptorHandleBlock) { 21 | 22 | self.whiteList = whiteList 23 | self.priority = priority 24 | self.handle = handle 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterParser.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol TheRouterParser { 11 | 12 | typealias ParserResult = (paths: [String], queries: [String: Any]) 13 | // 不做百分号转义 14 | static func parser(_ url: URL) -> ParserResult 15 | static func parserSheme(_ url: URL) -> String 16 | static func parserPaths(_ url: URL) -> [String] 17 | static func parserQuerys(_ url: URL) -> [String: Any] 18 | // 做百分号转义 19 | static func parser(_ urlString: String) -> ParserResult 20 | static func parserSheme(_ urlString: String) -> String 21 | static func parserPaths(_ urlString: String) -> [String] 22 | static func parserQuerys(_ urlString: String) -> [String: Any] 23 | } 24 | 25 | extension TheRouterParser { 26 | 27 | static func parser(_ url: URL) -> ParserResult { 28 | let paths = parserPaths(url) 29 | let query = parserQuerys(url) 30 | return (paths, query) 31 | } 32 | 33 | static func parserSheme(_ url: URL) -> String { 34 | return url.scheme ?? "" 35 | } 36 | 37 | static func parserPaths(_ url: URL) -> [String] { 38 | guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { 39 | return [String]() 40 | } 41 | let paths = la_parserPath(components) 42 | return paths 43 | } 44 | 45 | static func parserQuerys(_ url: URL) -> [String: Any] { 46 | guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { 47 | return [String: Any]() 48 | } 49 | let query = la_parserQuery(components) 50 | return (query as [String: Any]) 51 | } 52 | 53 | static func parser(_ urlString: String) -> ParserResult { 54 | let paths = parserPaths(urlString) 55 | let queries = parserQuerys(urlString) 56 | return (paths, queries) 57 | } 58 | 59 | static func parserSheme(_ urlString: String) -> String { 60 | if let url = canOpenURLString(urlString) { 61 | return url.scheme ?? "" 62 | } 63 | return "" 64 | } 65 | 66 | static func parserPaths(_ urlString: String) -> [String] { 67 | var paths = [String]() 68 | 69 | urlString.components(separatedBy: "#").forEach { componentString in 70 | if let url = canOpenURLString(componentString) { 71 | let result = parserPaths(url) 72 | paths += result 73 | } 74 | } 75 | return paths 76 | } 77 | 78 | static func parserQuerys(_ urlString: String) -> [String: Any] { 79 | var queries = [String: Any]() 80 | 81 | urlString.components(separatedBy: "#").forEach { componentString in 82 | if let url = canOpenURLString(componentString) { 83 | let result = parserQuerys(url) 84 | queries.la_combine(result) 85 | } 86 | } 87 | return queries 88 | } 89 | 90 | /// 解析Path (paths include the host) 91 | private static func la_parserPath(_ components: URLComponents) -> [String] { 92 | 93 | var paths = [String]() 94 | 95 | // check host 96 | if let host = components.host, host.count > 0 { 97 | paths.append(host) 98 | } 99 | 100 | // check path 101 | let path = components.path 102 | if path.count > 0 { 103 | let pathComponents = path.components(separatedBy: "/").filter { $0.count > 0} 104 | paths += pathComponents 105 | } 106 | 107 | return paths 108 | } 109 | 110 | /// 解析Query 111 | private static func la_parserQuery(_ components: URLComponents) -> [String: Any] { 112 | 113 | guard let items = components.queryItems, 114 | items.count > 0 else { 115 | return [:] 116 | } 117 | 118 | var queries = [String: Any]() 119 | items.forEach { (item) in 120 | if let value = item.value { 121 | queries[item.name] = value 122 | } else { 123 | } 124 | } 125 | 126 | return queries 127 | } 128 | 129 | /// 检查URL 130 | public static func canOpenURLString(_ urlString: String) -> URL? { 131 | 132 | let urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) 133 | guard let encodeString = urlString, encodeString.count > 0 else { 134 | return nil 135 | } 136 | 137 | guard let url = URL.init(string: encodeString) else { 138 | return nil 139 | } 140 | 141 | return url 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterPattern.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterPattern.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | public class TheRouterPattern: TheRouterParser { 11 | 12 | public typealias HandleBlock = ([String: Any]) -> Any? 13 | public static let PatternPlaceHolder = "~LA~" 14 | 15 | public var patternString: String 16 | public var sheme: String 17 | public var patternPaths: [String] 18 | public var priority: uint 19 | public var handle: HandleBlock 20 | public var matchString: String 21 | public var paramsMatchDict: [String: Int] 22 | 23 | public init(_ string: String, 24 | priority: uint = 0, 25 | handle: @escaping HandleBlock) { 26 | 27 | self.patternString = string 28 | self.priority = priority 29 | self.handle = handle 30 | self.sheme = TheRouterPattern.parserSheme(string) 31 | self.patternPaths = TheRouterPattern.parserPaths(string) 32 | self.paramsMatchDict = [String: Int]() 33 | 34 | var matchPaths = [String]() 35 | for i in 0.. Any 10 | 11 | public final class TheRouterServiceManager { 12 | 13 | public static let `default` = TheRouterServiceManager() 14 | 15 | public init() {} 16 | 17 | /// Service 同步 18 | private let serviceQueue = DispatchQueue(label: "scheme.TheRouterServiceManager.queue") 19 | /// Service构建者 20 | public var creatorsMap: [String: LAServiceCreator] = [:] 21 | /// service缓存 22 | public var servicesCache: [String: Any] = [:] 23 | } 24 | 25 | 26 | // MARK: - Service Register & Unregister 27 | public extension TheRouterServiceManager { 28 | class func serviceName(of value: T) -> String { 29 | return String(describing: value) 30 | } 31 | 32 | // MARK: - Register With Service Name 33 | /// 通过服务名称(named)注册LAServiceCreator 34 | /// - Parameters: 35 | /// - named: 服务名称 36 | /// - creator: 服务构造者 37 | func registerService(named: String, creator: @escaping LAServiceCreator) { 38 | serviceQueue.async { 39 | self.creatorsMap[named] = creator 40 | } 41 | } 42 | 43 | /// 通过服务名称(named)注册一个服务实例 (存在缓存中) 44 | /// - Parameters: 45 | /// - named: 服务名称 46 | /// - instance: 服务实例 47 | func registerService(named: String, instance: Any) { 48 | serviceQueue.async { 49 | self.servicesCache[named] = instance 50 | } 51 | } 52 | 53 | /// 通过服务名称(named)注册LAServiceCreator 54 | /// - Parameters: 55 | /// - named: 服务名称 56 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 57 | func registerService(named: String, lazyCreator: @escaping @autoclosure LAServiceCreator) { 58 | registerService(named: named, creator: lazyCreator) 59 | } 60 | 61 | // MARK: - Register With Service Type 62 | /// 通过服务接口注册LAServiceCreator 63 | /// - Parameters: 64 | /// - service: 服务接口 65 | /// - creator: 服务构造者 66 | func registerService(_ service: Service.Type, creator: @escaping () -> Service) { 67 | registerService(named: TheRouterServiceManager.serviceName(of: service), creator: creator) 68 | } 69 | 70 | /// 通过服务接口注册LAServiceCreator 71 | /// - Parameters: 72 | /// - service: 服务接口 73 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 74 | func registerService(_ service: Service.Type, lazyCreator: @escaping @autoclosure () -> Service) { 75 | registerService(named: TheRouterServiceManager.serviceName(of: service), creator: lazyCreator) 76 | } 77 | 78 | /// 通过服务接口注册一个服务实例 (存在缓存中) 79 | /// - Parameters: 80 | /// - service: 服务接口 81 | /// - instance: 服务实例 82 | func registerService(_ service: Service.Type, instance: Service) { 83 | registerService(named: TheRouterServiceManager.serviceName(of: service), instance: instance) 84 | } 85 | 86 | // MARK: - Unregister Service 87 | 88 | /// 通过服务名称取消注册服务 89 | /// - Parameter named: 服务名称 90 | @discardableResult 91 | func unregisterService(named: String) -> Any? { 92 | return serviceQueue.sync { 93 | self.creatorsMap.removeValue(forKey: named) 94 | return self.servicesCache.removeValue(forKey: named) 95 | } 96 | } 97 | 98 | /// 通过服务接口取消注册服务 99 | /// - Parameter service: 服务接口 100 | @discardableResult 101 | func unregisterService(_ service: Service) -> Service? { 102 | return unregisterService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 103 | } 104 | } 105 | 106 | // MARK: - Register Batch Services 107 | public extension TheRouterServiceManager { 108 | typealias BatchServiceMap = [String: LAServiceCreator] 109 | typealias ServiceEntry = BatchServiceMap.Element 110 | func registerService(_ services: BatchServiceMap) { 111 | serviceQueue.async { 112 | self.creatorsMap.merge(services, uniquingKeysWith: { _, v2 in v2 }) 113 | } 114 | } 115 | 116 | func registerService(entryLiteral entries: ServiceEntry ...) { 117 | return registerService(BatchServiceMap(entries, uniquingKeysWith: {_, v2 in v2})) 118 | } 119 | } 120 | 121 | // MARK: - Service Create 122 | public extension TheRouterServiceManager { 123 | /// 根据服务名称创建服务(如果缓存中已有服务实例,则不需要创建) 124 | /// - Parameters: 125 | /// - named: 服务名称 126 | /// - shouldCache: 是否需要缓存 127 | func createService(named: String, shouldCache: Bool = true) -> Any? { 128 | // 检查是否有缓存 129 | if let service = serviceQueue.sync(execute: { servicesCache[named] }) { 130 | return service 131 | } 132 | // 检查是否有构造者 133 | guard let creator = serviceQueue.sync(execute: { creatorsMap[named] }) else { 134 | return nil 135 | } 136 | 137 | let service = creator() 138 | if shouldCache { 139 | self.serviceQueue.async { 140 | self.servicesCache[named] = service 141 | } 142 | } 143 | return service 144 | } 145 | 146 | /// 根据服务接口创建服务(如果缓存中已有服务实例,则不需要创建) 147 | /// - Parameters: 148 | /// - service: 服务接口 149 | /// - shouldCache: 是否需要缓存 150 | func createService(_ service: Service.Type, shouldCache: Bool = true) -> Service? { 151 | return createService(named: TheRouterServiceManager.serviceName(of: service), shouldCache: shouldCache) as? Service 152 | } 153 | } 154 | 155 | // MARK: - Service Fetch 156 | public extension TheRouterServiceManager { 157 | /// 通过服务名称获取服务 158 | /// - Parameter named: 服务名称 159 | func getService(named: String) -> Any? { 160 | return self.createService(named: named) 161 | } 162 | 163 | /// 通过服务接口获取服务 164 | /// - Parameter service: 服务接口 165 | func getService(_ service: Service.Type) -> Service? { 166 | return getService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 167 | } 168 | } 169 | 170 | 171 | // MARK: - Service Clean Cache 172 | public extension TheRouterServiceManager { 173 | func cleanAllServiceCache() { 174 | serviceQueue.async { 175 | self.servicesCache.removeAll() 176 | } 177 | } 178 | 179 | @discardableResult 180 | func cleanServiceCache(named: String) -> Any? { 181 | return serviceQueue.sync { 182 | return self.servicesCache.removeValue(forKey: named) 183 | } 184 | } 185 | 186 | @discardableResult 187 | func cleanServiceCache(by service: Service.Type) -> Service? { 188 | return cleanServiceCache(named: TheRouterServiceManager.serviceName(of: service)) as? Service 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterServiceProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterServiceProtocol.swift 3 | // 4 | // Created by mars.yao on 2021/9/1. 5 | // 6 | 7 | import Foundation 8 | 9 | @objc 10 | public protocol TheRouterServiceProtocol: NSObjectProtocol { 11 | init() 12 | 13 | static var seriverName: String { get } 14 | } 15 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/TheRouter/TheRouter/Classes/TheRouterable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterable.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import UIKit 9 | 10 | 11 | public protocol TheRouterable { 12 | 13 | static var patternString: [String] { get } 14 | 15 | static func registerAction(info: [String: Any]) -> Any 16 | 17 | static var priority: UInt { get } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Toast/README.md: -------------------------------------------------------------------------------- 1 | Toast for iOS 2 | ============= 3 | 4 | [![Build Status](https://travis-ci.org/scalessec/Toast.svg?branch=3.0)](https://travis-ci.org/scalessec/Toast) 5 | [![CocoaPods Version](https://img.shields.io/cocoapods/v/Toast.svg)](http://cocoadocs.org/docsets/Toast) 6 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 7 | 8 | Toast is an Objective-C category that adds toast notifications to the `UIView` object class. It is intended to be simple, lightweight, and easy to use. Most 9 | toast notifications can be triggered with a single line of code. 10 | 11 | **Using Swift? A native swift port of this library is now available: [Toast-Swift](https://github.com/scalessec/Toast-Swift "Toast-Swift")** 12 | 13 | Screenshots 14 | --------- 15 | ![Toast Screenshots](toast_screenshots.jpg) 16 | 17 | 18 | Basic Examples 19 | --------- 20 | ```objc 21 | // basic usage 22 | [self.view makeToast:@"This is a piece of toast."]; 23 | 24 | // toast with a specific duration and position 25 | [self.view makeToast:@"This is a piece of toast with a specific duration and position." 26 | duration:3.0 27 | position:CSToastPositionTop]; 28 | 29 | // toast with all possible options 30 | [self.view makeToast:@"This is a piece of toast with a title & image" 31 | duration:3.0 32 | position:[NSValue valueWithCGPoint:CGPointMake(110, 110)] 33 | title:@"Toast Title" 34 | image:[UIImage imageNamed:@"toast.png"] 35 | style:nil 36 | completion:^(BOOL didTap) { 37 | if (didTap) { 38 | NSLog(@"completion from tap"); 39 | } else { 40 | NSLog(@"completion without tap"); 41 | } 42 | }]; 43 | 44 | // display toast with an activity spinner 45 | [self.view makeToastActivity:CSToastPositionCenter]; 46 | 47 | // display any view as toast 48 | [self.view showToast:myView]; 49 | ``` 50 | 51 | But wait, there's more! 52 | --------- 53 | ```objc 54 | // create a new style 55 | CSToastStyle *style = [[CSToastStyle alloc] initWithDefaultStyle]; 56 | 57 | // this is just one of many style options 58 | style.messageColor = [UIColor orangeColor]; 59 | 60 | // present the toast with the new style 61 | [self.view makeToast:@"This is a piece of toast." 62 | duration:3.0 63 | position:CSToastPositionBottom 64 | style:style]; 65 | 66 | // or perhaps you want to use this style for all toasts going forward? 67 | // just set the shared style and there's no need to provide the style again 68 | [CSToastManager setSharedStyle:style]; 69 | 70 | // toggle "tap to dismiss" functionality 71 | [CSToastManager setTapToDismissEnabled:YES]; 72 | 73 | // toggle queueing behavior 74 | [CSToastManager setQueueEnabled:YES]; 75 | 76 | // immediately hides all toast views in self.view 77 | [self.view hideAllToasts]; 78 | ``` 79 | 80 | See the demo project for more examples. 81 | 82 | Setup Instructions 83 | ------------------ 84 | 85 | [CocoaPods](http://cocoapods.org) 86 | ------------------ 87 | 88 | Install with CocoaPods by adding the following to your `Podfile`: 89 | ```ruby 90 | pod 'Toast', '~> 4.0.0' 91 | ``` 92 | 93 | [Carthage](https://github.com/Carthage/Carthage) 94 | ------------------ 95 | 96 | Install with Carthage by adding the following to your `Cartfile`: 97 | ```ogdl 98 | github "scalessec/Toast" ~> 4.0.0 99 | ``` 100 | Run `carthage update` to build the framework and link against `Toast.framework`. Then, `#import `. 101 | 102 | Manually 103 | -------- 104 | 105 | 1. Add `UIView+Toast.h` & `UIView+Toast.m` to your project. 106 | 2. `#import "UIView+Toast.h"` 107 | 3. Grab yourself a cold 🍺. 108 | 109 | MIT License 110 | ----------- 111 | Copyright (c) 2011-2017 Charles Scalesse. 112 | 113 | Permission is hereby granted, free of charge, to any person obtaining a 114 | copy of this software and associated documentation files (the 115 | "Software"), to deal in the Software without restriction, including 116 | without limitation the rights to use, copy, modify, merge, publish, 117 | distribute, sublicense, and/or sell copies of the Software, and to 118 | permit persons to whom the Software is furnished to do so, subject to 119 | the following conditions: 120 | 121 | The above copyright notice and this permission notice shall be included 122 | in all copies or substantial portions of the Software. 123 | 124 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 125 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 126 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 127 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 128 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 129 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 130 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 131 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Toast/Toast-Framework/Toast.h: -------------------------------------------------------------------------------- 1 | // 2 | // Toast.h 3 | // Toast 4 | // 5 | // Created by Charles Scalesse on 11/3/16. 6 | // 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Toast. 12 | FOUNDATION_EXPORT double ToastVersionNumber; 13 | 14 | //! Project version string for Toast. 15 | FOUNDATION_EXPORT const unsigned char ToastVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | #import 19 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/Pods/Toast/license: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2017 Charles Scalesse. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import "AppDelegate.h" 9 | #import "TheRouter_ObjectiveCDemo-Swift.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | [TheRouterService initTheRouter]; 21 | return YES; 22 | } 23 | 24 | #pragma mark - UISceneSession lifecycle 25 | 26 | 27 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { 28 | // Called when a new scene session is being created. 29 | // Use this method to select a configuration to create the new scene with. 30 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 31 | } 32 | 33 | 34 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { 35 | // Called when the user discards a scene session. 36 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 37 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/OpenRouter/TheRouterApi.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterApi.swift 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | import Foundation 9 | import TheRouter 10 | 11 | /** 12 | TheRouterApi 主要作用是做模块间解耦合,多个模块相互调用,抽出统一的Api,进行跨模块调用,为了保证线上稳定性,建议开启强制检查,会自动检测是否写错或者漏写,触发断言 13 | */ 14 | 15 | @objc public class TheRouterApi: NSObject, CustomRouterInfo { 16 | 17 | @objc public static var patternString = "scheme://router/objcDemo" 18 | public static var routerClass = "TheRouter_ObjectiveCDemo.TheRouterControllerSwift" 19 | public var params: [String: Any] { return [:] } 20 | public var jumpType: LAJumpType = .push 21 | 22 | // 这里没办法,OC不支持元组,只能拆开 23 | @objc public func generateParams() -> [String: Any] { 24 | return TheRouter.generate(Self.patternString, params: self.params, jumpType: self.jumpType).1 25 | } 26 | public override init() {} 27 | } 28 | 29 | public class TheRouterWebApi: NSObject, CustomRouterInfo { 30 | 31 | public static var patternString = "scheme://webview/home" 32 | public static var routerClass = "TheRouter_ObjectiveCDemo.TheRouterWebController" 33 | public var params: [String: Any] { return [:] } 34 | public var jumpType: LAJumpType = .push 35 | 36 | public override init() {} 37 | } 38 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/OpenRouter/TheRouterBridging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBridging.swift 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | import Foundation 9 | import TheRouter 10 | 11 | /// 服务路由 12 | public let serivceHost = "scheme://services?" 13 | 14 | /// web跳转路由 15 | public let webRouterUrl = "scheme://webview/home" 16 | 17 | @objc public class TheRouterService: NSObject { 18 | 19 | public typealias TheRouterComplateHandler = ((NSDictionary?, NSObject?) -> Void)? 20 | 21 | @objc public static func initTheRouter() { 22 | // 日志回调,可以监控线上路由运行情况 23 | TheRouter.logcat { url, logType, errorMsg in 24 | NSLog("TheRouter: logMsg- \(url) \(logType.rawValue) \(errorMsg)") 25 | } 26 | 27 | // 路由懒加载注册, 28 | // - excludeCocoapods: 是否对Cocoapods生成的组件进行动态注册 29 | // - excludeCocoapods = true 不对Cocoapods生成的组件进行动态注册, false 对Cocoapods生成的组件也进行遍历动态注册 30 | // - useCache: 是否开启本地缓存功能 31 | TheRouterManager.loadRouterClass(excludeCocoapods: true, useCache: true) 32 | 33 | TheRouter.lazyRegisterRouterHandle { url, userInfo in 34 | TheRouterManager.injectRouterServiceConfig(webRouterUrl, serivceHost) 35 | /// - Parameters: 36 | /// - excludeCocoapods: 排除一些非业务注册类,这里一般会将 "com.apple", "org.cocoapods" 进行过滤,但是如果组件化形式的,创建的BundleIdentifier也是 37 | /// org.cocoapods,这里需要手动改下,否则组件内的类将不会被获取。 38 | /// - urlPath: 将要打开的路由path 39 | /// - userInfo: 路由传递的参数 40 | /// - forceCheckEnable: 是否支持强制校验,强制校验要求Api声明与对应的类必须实现TheRouterAble协议 41 | /// - forceCheckEnable 强制打开TheRouterApi定义的便捷类与实现TheRouterAble协议类是否相同,打开的话,debug环境会自动检测,避免线上出问题,建议打开 42 | return TheRouterManager.addGloableRouter(true, url, userInfo, forceCheckEnable: true) 43 | } 44 | 45 | // 动态注册服务 46 | TheRouterManager.registerServices(excludeCocoapods: true) 47 | } 48 | 49 | @discardableResult 50 | @objc public static func openURL(_ urlString: String, 51 | _ userInfo: [String: Any] = [String: Any](), 52 | _ complateHandler: TheRouterComplateHandler = nil) -> Any? { 53 | TheRouter.openURL(urlString, userInfo: userInfo, complateHandler: { (dict, obj) in 54 | // 将结果转换为Objective-C兼容的类型 55 | complateHandler?(dict as NSDictionary?, obj as? NSObject) 56 | }) 57 | } 58 | 59 | @discardableResult 60 | @objc public static func openWebURL(_ urlString: String, 61 | _ userInfo: [String: Any] = [String: Any]()) -> Any? { 62 | return TheRouter.openURL((urlString, userInfo)) 63 | } 64 | 65 | } 66 | 67 | // 假设需要跳转的类是TheRouterController, 那么在此处实现 68 | public class TheRouterControllerSwift: TheRouterController, TheRouterable { 69 | 70 | public static var patternString: [String] { 71 | ["scheme://router/objcDemo"] 72 | } 73 | 74 | public static func registerAction(info: [String : Any]) -> Any { 75 | let vc = TheRouterController() 76 | // 参数记得自己赋值 77 | return vc 78 | } 79 | 80 | public static var priority: UInt { 81 | TheRouterDefaultPriority 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/OpenRouter/TheRouterWebController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterWebController.swift 3 | // TheRouter_Example 4 | // 5 | // Created by mars.yao on 2023/8/21. 6 | // Copyright © 2023 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import WebKit 11 | import TheRouter 12 | 13 | class TheRouterWebController: UIViewController { 14 | 15 | var webView: WKWebView? 16 | 17 | var baseUrl: String = "" 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | self.navigationItem.title = "WKWebView" 22 | self.initWebView() 23 | self.loadWebView(baseURL: self.baseUrl) 24 | } 25 | 26 | private func initWebView() { 27 | let preferences = WKPreferences() 28 | let userContentController = WKUserContentController() 29 | 30 | let configuration = WKWebViewConfiguration() 31 | configuration.preferences = preferences 32 | configuration.userContentController = userContentController 33 | 34 | self.webView = WKWebView(frame: self.view.bounds, configuration: configuration) 35 | self.webView?.uiDelegate = self 36 | self.webView?.navigationDelegate = self 37 | self.view.addSubview(self.webView!) 38 | } 39 | 40 | private func loadWebView(baseURL: String?) { 41 | guard let baseURL = baseURL else { return } 42 | let url = URL(string: baseURL)! 43 | let request = URLRequest(url: url) 44 | self.webView?.load(request) 45 | } 46 | 47 | 48 | } 49 | 50 | 51 | extension TheRouterWebController: WKUIDelegate, WKNavigationDelegate { 52 | 53 | // 页面开始加载时调用 54 | func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { 55 | } 56 | // 当内容开始返回时调用 57 | func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { 58 | } 59 | // 页面加载完成之后调用 60 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 61 | } 62 | 63 | // 页面加载失败时调用 64 | func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { 65 | } 66 | 67 | // 接收到服务器跳转请求之后调用 68 | func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) { 69 | } 70 | } 71 | 72 | 73 | extension TheRouterWebController: WKScriptMessageHandler { 74 | 75 | func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { } 76 | 77 | } 78 | 79 | extension TheRouterWebController: TheRouterable { 80 | 81 | static var patternString: [String] { 82 | ["scheme://webview/home"] 83 | } 84 | 85 | static func registerAction(info: [String : Any]) -> Any { 86 | let webVC = TheRouterWebController() 87 | webVC.baseUrl = info["url"] as? String ?? "" 88 | return webVC 89 | } 90 | 91 | static var priority: UInt { 92 | TheRouterDefaultPriority 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import 9 | 10 | @interface SceneDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow * window; 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.m 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import "SceneDelegate.h" 9 | 10 | @interface SceneDelegate () 11 | 12 | @end 13 | 14 | @implementation SceneDelegate 15 | 16 | 17 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | } 22 | 23 | 24 | - (void)sceneDidDisconnect:(UIScene *)scene { 25 | // Called as the scene is being released by the system. 26 | // This occurs shortly after the scene enters the background, or when its session is discarded. 27 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 28 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 29 | } 30 | 31 | 32 | - (void)sceneDidBecomeActive:(UIScene *)scene { 33 | // Called when the scene has moved from an inactive state to an active state. 34 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 35 | } 36 | 37 | 38 | - (void)sceneWillResignActive:(UIScene *)scene { 39 | // Called when the scene will move from an active state to an inactive state. 40 | // This may occur due to temporary interruptions (ex. an incoming phone call). 41 | } 42 | 43 | 44 | - (void)sceneWillEnterForeground:(UIScene *)scene { 45 | // Called as the scene transitions from the background to the foreground. 46 | // Use this method to undo the changes made on entering the background. 47 | } 48 | 49 | 50 | - (void)sceneDidEnterBackground:(UIScene *)scene { 51 | // Called as the scene transitions from the foreground to the background. 52 | // Use this method to save data, release shared resources, and store enough scene-specific state information 53 | // to restore the scene back to its current state. 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "TheRouterController.h" 6 | 7 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/TheRouterController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterController.h 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface TheRouterController : UIViewController 13 | 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/TheRouterController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterController.m 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import "TheRouterController.h" 9 | 10 | @interface TheRouterController () 11 | 12 | @end 13 | 14 | @implementation TheRouterController 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | self.view.backgroundColor = [UIColor orangeColor]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import 9 | 10 | @interface ViewController : UIViewController 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import "ViewController.h" 9 | #import "TheRouter_ObjectiveCDemo-Swift.h" 10 | 11 | @interface ViewController () 12 | - (IBAction)push:(id)sender; 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | // Do any additional setup after loading the view. 22 | } 23 | 24 | 25 | - (IBAction)push:(id)sender { 26 | 27 | [TheRouterService openURL:TheRouterApi.patternString :[[[TheRouterApi alloc] init] generateParams] :^(NSDictionary * _Nullable params, NSObject * _Nullable classInstance) { 28 | 29 | }]; 30 | // 下方为H5跳转Demo 31 | // [TheRouterService openWebURL:@"https://therouter.cn/" :@{}]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /TheRouter-ObjectiveCDemo/TheRouter-ObjectiveCDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TheRouter-ObjectiveCDemo 4 | // 5 | // Created by mars.yao on 2024/1/25. 6 | // 7 | 8 | #import 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | NSString * appDelegateClassName; 13 | @autoreleasepool { 14 | // Setup code that might create autoreleased objects goes here. 15 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 16 | } 17 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 18 | } 19 | -------------------------------------------------------------------------------- /TheRouter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint TheRouter.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'TheRouter' 11 | s.version = '1.1.8' 12 | s.summary = 'TheRouter一个用于模块间解耦和通信,基于Swift协议进行动态懒加载注册路由与打开路由的工具。同时支持通过Service-Protocol寻找对应的模块,并用 protocol进行依赖注入和模块通信。' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | TODO: Add long description of the pod here. 22 | DESC 23 | 24 | s.homepage = 'https://github.com/HuolalaTech/therouter-ios' 25 | s.license = { :type => 'MIT', :file => 'LICENSE' } 26 | s.author = { 'mars' => 'mars.yao' } 27 | s.source = { :git => 'https://github.com/HuolalaTech/hll-wp-therouter-ios.git', :tag => s.version.to_s } 28 | s.source_files = 'TheRouter/Classes/**/*', 'TheRouter/Classes/TheRouter/Sources/TheRouter/*' 29 | s.exclude_files = 'TheRouter/Classes/TheRouterable/Package.swift' 30 | s.frameworks = 'UIKit', 'Foundation' 31 | s.ios.deployment_target = '11.0' 32 | # swift 支持的版本 33 | s.swift_version = '5.0' 34 | s.static_framework = true 35 | s.xcconfig = {"ENABLE_BITCODE" => "NO"} 36 | s.pod_target_xcconfig = { 37 | 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D DEBUG' 38 | } 39 | 40 | s.subspec 'TheRouterMacro' do |macro| 41 | macro.source_files = 'TheRouterMacro/Sources/TheRouterMacro/*' 42 | macro.preserve_paths = 'TheRouterMacro/Package.swift', 'TheRouterMacro/Sources/**/*' 43 | 44 | product_folder = "${PODS_BUILD_DIR}/Products/TheRouterMacroMacros" 45 | 46 | script = <<-SCRIPT.squish 47 | env -i PATH="$PATH" "$SHELL" -l -c 48 | "swift build -c release --product TheRouterMacroMacros 49 | --package-path \\"$PODS_TARGET_SRCROOT/TheRouterMacro\\" 50 | --scratch-path \\"#{product_folder}\\"" 51 | SCRIPT 52 | 53 | macro.script_phase = { 54 | :name => 'Build TheRouterMacroMacros macro plugin', 55 | :script => script, 56 | :input_files => Dir.glob("{TheRouterMacro/Package.swift,TheRouterMacro/Sources/**/*}").map { 57 | |path| "$(PODS_TARGET_SRCROOT)/#{path}" 58 | }, 59 | :output_files => ["#{product_folder}/release/TheRouterMacroMacros"], 60 | :execution_position => :before_compile 61 | } 62 | 63 | macro.user_target_xcconfig = { 64 | 'OTHER_SWIFT_FLAGS' => <<-FLAGS.squish 65 | -Xfrontend -load-plugin-executable 66 | -Xfrontend #{product_folder}/release/TheRouterMacroMacros#TheRouterMacroMacros 67 | FLAGS 68 | } 69 | end 70 | end 71 | 72 | -------------------------------------------------------------------------------- /TheRouter/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/TheRouter/Assets/.gitkeep -------------------------------------------------------------------------------- /TheRouter/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/TheRouter/Classes/.gitkeep -------------------------------------------------------------------------------- /TheRouter/Classes/Decode+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Decode+Extension.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/6/24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct JSONCodingKeys: CodingKey { 11 | var stringValue: String 12 | 13 | init(stringValue: String) { 14 | self.stringValue = stringValue 15 | } 16 | 17 | var intValue: Int? 18 | 19 | init?(intValue: Int) { 20 | self.init(stringValue: "\(intValue)") 21 | self.intValue = intValue 22 | } 23 | } 24 | 25 | extension KeyedDecodingContainer { 26 | 27 | func decode(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary { 28 | let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) 29 | return try container.decode(type) 30 | } 31 | 32 | func decodeIfPresent(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary? { 33 | guard contains(key) else { 34 | return nil 35 | } 36 | return try decode(type, forKey: key) 37 | } 38 | 39 | func decode(_ type: Array.Type, forKey key: K) throws -> Array { 40 | var container = try self.nestedUnkeyedContainer(forKey: key) 41 | return try container.decode(type) 42 | } 43 | 44 | func decodeIfPresent(_ type: Array.Type, forKey key: K) throws -> Array? { 45 | guard contains(key) else { 46 | return nil 47 | } 48 | return try decode(type, forKey: key) 49 | } 50 | 51 | func decode(_ type: Dictionary.Type) throws -> Dictionary { 52 | var dictionary = Dictionary() 53 | 54 | for key in allKeys { 55 | if let boolValue = try? decode(Bool.self, forKey: key) { 56 | dictionary[key.stringValue] = boolValue 57 | } else if let stringValue = try? decode(String.self, forKey: key) { 58 | dictionary[key.stringValue] = stringValue 59 | } else if let intValue = try? decode(Int.self, forKey: key) { 60 | dictionary[key.stringValue] = intValue 61 | } else if let doubleValue = try? decode(Double.self, forKey: key) { 62 | dictionary[key.stringValue] = doubleValue 63 | } else if let nestedDictionary = try? decode(Dictionary.self, forKey: key) { 64 | dictionary[key.stringValue] = nestedDictionary 65 | } else if let nestedArray = try? decode(Array.self, forKey: key) { 66 | dictionary[key.stringValue] = nestedArray 67 | } 68 | } 69 | return dictionary 70 | } 71 | } 72 | 73 | extension UnkeyedDecodingContainer { 74 | 75 | mutating func decode(_ type: Array.Type) throws -> Array { 76 | var array: [Any] = [] 77 | while isAtEnd == false { 78 | if let value = try? decode(Bool.self) { 79 | array.append(value) 80 | } else if let value = try? decode(Double.self) { 81 | array.append(value) 82 | } else if let value = try? decode(String.self) { 83 | array.append(value) 84 | } else if let nestedDictionary = try? decode(Dictionary.self) { 85 | array.append(nestedDictionary) 86 | } else if let nestedArray = try? decode(Array.self) { 87 | array.append(nestedArray) 88 | } 89 | } 90 | return array 91 | } 92 | 93 | mutating func decode(_ type: Dictionary.Type) throws -> Dictionary { 94 | 95 | let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self) 96 | return try nestedContainer.decode(type) 97 | } 98 | } 99 | 100 | extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys { 101 | mutating func encode(_ value: Dictionary) throws { 102 | try value.forEach({ (key, value) in 103 | let key = JSONCodingKeys(stringValue: key) 104 | switch value { 105 | case let value as Bool: 106 | try encode(value, forKey: key) 107 | case let value as Int: 108 | try encode(value, forKey: key) 109 | case let value as String: 110 | try encode(value, forKey: key) 111 | case let value as Double: 112 | try encode(value, forKey: key) 113 | case let value as Dictionary: 114 | try encode(value, forKey: key) 115 | case let value as Array: 116 | try encode(value, forKey: key) 117 | case Optional.none: 118 | try encodeNil(forKey: key) 119 | default: 120 | throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + [key], debugDescription: "Invalid JSON value")) 121 | } 122 | }) 123 | } 124 | } 125 | 126 | extension KeyedEncodingContainerProtocol { 127 | mutating func encode(_ value: Dictionary?, forKey key: Key) throws { 128 | if value != nil { 129 | var container = self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) 130 | try container.encode(value!) 131 | } 132 | } 133 | 134 | mutating func encode(_ value: Array?, forKey key: Key) throws { 135 | if value != nil { 136 | var container = self.nestedUnkeyedContainer(forKey: key) 137 | try container.encode(value!) 138 | } 139 | } 140 | } 141 | 142 | extension UnkeyedEncodingContainer { 143 | mutating func encode(_ value: Array) throws { 144 | try value.enumerated().forEach({ (index, value) in 145 | switch value { 146 | case let value as Bool: 147 | try encode(value) 148 | case let value as Int: 149 | try encode(value) 150 | case let value as String: 151 | try encode(value) 152 | case let value as Double: 153 | try encode(value) 154 | case let value as Dictionary: 155 | try encode(value) 156 | case let value as Array: 157 | try encode(value) 158 | case Optional.none: 159 | try encodeNil() 160 | default: 161 | let keys = JSONCodingKeys(intValue: index).map({ [$0] }) ?? [] 162 | throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + keys, debugDescription: "Invalid JSON value")) 163 | } 164 | }) 165 | } 166 | 167 | mutating func encode(_ value: Dictionary) throws { 168 | var nestedContainer = self.nestedContainer(keyedBy: JSONCodingKeys.self) 169 | try nestedContainer.encode(value) 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouerBridge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouerBridge.swift 3 | // HPPush 4 | // 5 | // Created by mars.yao on 2024/5/14. 6 | // 7 | 8 | import Foundation 9 | 10 | @objcMembers 11 | public class TheRouerBridge: NSObject { 12 | 13 | public class func canOpenUrl(_ urlString: String) -> Bool { 14 | return TheRouter.canOpenURL(urlString) 15 | } 16 | 17 | // 方法1:根据URL字符串打开 18 | @discardableResult 19 | public class func openURL(_ urlString: String, userInfo: [String: Any] = [String: Any](), complateHandler: ComplateHandler = nil) -> Any? { 20 | return TheRouter.openURL(urlString, userInfo: userInfo, complateHandler: complateHandler) 21 | } 22 | 23 | 24 | // 方法2:根据URL元组打开 25 | @discardableResult 26 | public class func openURL(_ uriTuple: (String, [String: Any]), complateHandler: ComplateHandler = nil) -> Any? { 27 | return TheRouter.openURL(uriTuple, complateHandler: complateHandler) 28 | } 29 | 30 | // 方法3:根据URL元组打开WebURL 31 | @discardableResult 32 | public class func openWebURL(_ uriTuple: (String, [String: Any])) -> Any? { 33 | return TheRouter.openURL(uriTuple) 34 | } 35 | 36 | // 方法4:根据URL字符串打开WebURL 37 | @discardableResult 38 | public class func openWebURL(_ urlString: String, userInfo: [String: Any] = [String: Any]()) -> Any? { 39 | return TheRouter.openURL((urlString, userInfo)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouter+Convenience.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Convenience.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import UIKit 9 | 10 | public extension TheRouter { 11 | 12 | /// addRouterItem with parasing the dictionary, the class which match the className need inherit the protocol of TheRouterable 13 | /// 14 | class func addRouterItem(_ routerItem: RouteItem) { 15 | addRouterItem(routerItem.path, classString: routerItem.className) 16 | } 17 | 18 | /// addRouterItem with parasing the dictionary, the class which match the className need inherit the protocol of TheRouterable 19 | /// 20 | /// - Parameter dictionary: [patternString: className] 21 | class func addRouterItem(_ dictionary: [String: String]) { 22 | dictionary.forEach { (key: String, value: String) in 23 | addRouterItem(key, classString: value) 24 | } 25 | } 26 | 27 | /// convienience addRouterItem with className 28 | /// 29 | /// - Parameters: 30 | /// - patternString: register urlstring 31 | /// - classString: the class which match the className need inherit the protocol of TheRouterable 32 | class func addRouterItem(patternString: String, priority: uint = 0, classString: String) { 33 | 34 | let clz: AnyClass? = classString.trimmingCharacters(in: CharacterSet.whitespaces).la_matchClass() 35 | if let _ = clz as? TheRouterable.Type { 36 | self.addRouterItem(patternString.trimmingCharacters(in: CharacterSet.whitespaces), classString: classString, priority: priority) 37 | } else { 38 | if let currentCls = clz, currentCls.self.conforms(to: TheRouterableProxy.self) { 39 | self.addRouterItem(patternString.trimmingCharacters(in: CharacterSet.whitespaces), classString: classString, priority: priority) 40 | } else { 41 | shareInstance.logcat?(patternString, .logError, "\(classString) register router error, please implementation the TheRouterable Protocol") 42 | assert(clz as? TheRouterable.Type != nil, "register router error, please implementation the TheRouterable Protocol") 43 | } 44 | } 45 | } 46 | 47 | /// addRouterItem 48 | /// 49 | /// - Parameters: 50 | /// - patternString: register urlstring 51 | /// - priority: match priority, sort by inverse order 52 | /// - handle: block of refister URL 53 | class func addRouterItem(_ patternString: String, classString: String, priority: uint = 0) { 54 | shareInstance.addRouterItem(patternString.trimmingCharacters(in: CharacterSet.whitespaces), classString: classString, priority: priority) 55 | } 56 | 57 | /// addRouterItem 58 | /// 59 | /// - Parameters: 60 | /// - whiteList: whiteList for intercept 61 | /// - priority: match priority, sort by inverse order 62 | /// - handle: block of interception 63 | class func addRouterInterceptor(_ whiteList: [String] = [String](), priority: uint = 0, handle: @escaping TheRouterInterceptor.InterceptorHandleBlock) { 64 | shareInstance.addRouterInterceptor(whiteList, priority: priority, handle: handle) 65 | } 66 | 67 | /// addFailedHandel 68 | class func globalOpenFailedHandler(_ handel: @escaping FailedHandleBlock) { 69 | shareInstance.globalOpenFailedHandler(handel) 70 | } 71 | 72 | /// LazyRegister 73 | class func lazyRegisterRouterHandle(_ handel: @escaping LazyRegisterHandleBlock) { 74 | shareInstance.lazyRegisterRouterHandle(handel) 75 | } 76 | 77 | /// addRouterItemLogHandle 78 | class func logcat(_ handle: @escaping RouterLogHandleBlock) { 79 | shareInstance.logcat(handle) 80 | } 81 | 82 | /// addRouterItemLogHandle 83 | class func customJumpAction(_ handle: @escaping CustomJumpActionClouse) { 84 | shareInstance.customJumpAction(handle) 85 | } 86 | 87 | /// removeRouter by register urlstring 88 | /// 89 | /// - Parameter patternString: register urlstring 90 | class func removeRouter(_ patternString: String) { 91 | shareInstance.removeRouter(patternString.trimmingCharacters(in: CharacterSet.whitespaces)) 92 | } 93 | 94 | /// Check whether register for url 95 | /// 96 | /// - Parameter urlString: real request urlstring 97 | /// - Returns: whether register 98 | class func canOpenURL(_ urlString: String) -> Bool { 99 | return shareInstance.canOpenURL(urlString.trimmingCharacters(in: CharacterSet.whitespaces)) 100 | } 101 | 102 | /// request for url 103 | /// 104 | /// - Parameters: 105 | /// - urlString: real request urlstring 106 | /// - userInfo: custom userInfo, could contain Object 107 | /// - Returns: response for request, contain pattern and queries 108 | class func requestURL(_ urlString: String, userInfo: [String: Any] = [String: Any]()) -> RouteResponse { 109 | return shareInstance.requestURL(urlString.trimmingCharacters(in: CharacterSet.whitespaces), userInfo: userInfo) 110 | } 111 | 112 | // injectRouterServiceConfig 113 | class func injectRouterServiceConfig(_ webPath: String?, _ serviceHost: String) { 114 | return shareInstance.injectRouterServiceConfig(webPath, serviceHost) 115 | } 116 | 117 | /// Is the route loaded 118 | /// - Parameter loadStatus: router paths loadStatus 119 | class func routerLoadStatus(_ loadStatus: Bool) { 120 | return shareInstance.routerLoadStatus(loadStatus) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouter+Generate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Generate.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/11/29. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | // MARK: - Constants 12 | // 跳转类型Key 13 | public let LAJumpTypeKey = "jumpType" 14 | // 第一个参数Key 15 | public let TheRouterIvar1Key = "ivar1" 16 | // 第二个参数Key 17 | public let TheRouterIvar2Key = "ivar2" 18 | // 返回值类型Key 19 | public let TheRouterFunctionResultKey = "resultType" 20 | // 路由Path常量Key 21 | public let TheRouterPath = "path" 22 | // 路由class常量Key 23 | public let TheRouterClassName = "class" 24 | //路由priority常量Key 25 | public let TheRouterPriority = "priority" 26 | // tabBar选中参数 tabBarSelecIndex 27 | public let TheRouterTabBarSelecIndex = "tabBarSelecIndex" 28 | 29 | 30 | //路由优先级默认值 31 | public let TheRouterDefaultPriority: UInt = 1000 32 | 33 | public typealias ComplateHandler = (([String: Any]?, Any?) -> Void)? 34 | 35 | // constants 36 | public extension TheRouter { 37 | static let patternKey = "patternKey" 38 | static let requestURLKey = "requestURLKey" 39 | static let matchFailedKey = "matchFailedKey" 40 | static let urlKey = "url" 41 | static let userInfoKey = "userInfo" 42 | } 43 | 44 | // 跳转方式 45 | @objc public enum LAJumpType: Int { 46 | case modal 47 | case push 48 | case popToTaget 49 | case windowNavRoot 50 | case modalDismissBeforePush 51 | case showTab 52 | } 53 | 54 | public struct RouteItem { 55 | 56 | public var path: String = "" 57 | public var className: String = "" 58 | public var action: String = "" 59 | public var descriptions: String = "" 60 | public var params: [String: Any] = [:] 61 | 62 | public init(path: String, className: String, action: String = "", descriptions: String = "", params: [String: Any] = [:]) { 63 | self.path = path 64 | self.className = className 65 | self.action = action 66 | self.descriptions = descriptions 67 | self.params = params 68 | } 69 | } 70 | 71 | // 动态路由调用方法返回类型 72 | @objc public enum TheRouterFunctionResultType: Int { 73 | case voidType // 无返回值类型 74 | case valueType // 值类型 75 | case referenceType // 引用类型 76 | } 77 | 78 | /// 远端下发路由数据 79 | @objc public enum TheRouterReloadMapEnum: Int { 80 | case none 81 | case replace 82 | case add 83 | case delete 84 | case reset 85 | } 86 | 87 | // 日志类型 88 | @objc public enum TheRouterLogType: Int { 89 | case logNormal 90 | case logError 91 | } 92 | 93 | public extension URL { 94 | var urlParameters: [String: String]? { 95 | guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), 96 | let queryItems = components.queryItems else { return nil } 97 | return queryItems.reduce(into: [String: String]()) { (result, item) in 98 | result[item.name] = item.value 99 | } 100 | } 101 | } 102 | 103 | extension TheRouter { 104 | 105 | // MARK: - Convenience method 106 | public class func generate(_ patternString: String, params: [String: Any] = [String: Any](), jumpType: LAJumpType) -> (String, [String: Any]) { 107 | 108 | if let url = URL(string: patternString) { 109 | let orginParams = url.urlParameters ?? [String: Any]() 110 | var queries = params 111 | queries[LAJumpTypeKey] = "\(jumpType.rawValue)" 112 | 113 | for (key, value) in orginParams.reversed() { 114 | queries[key] = value 115 | } 116 | return (patternString, queries) 117 | } 118 | 119 | return ("", [String: Any]()) 120 | } 121 | 122 | } 123 | 124 | public protocol CustomRouterInfo { 125 | static var patternString: String { get } 126 | static var routerClass: String { get } 127 | var params: [String: Any] { get } 128 | var jumpType: LAJumpType { get } 129 | } 130 | 131 | extension CustomRouterInfo { 132 | public var requiredURL: (String, [String: Any]) { 133 | return TheRouter.generate(Self.patternString, params: self.params, jumpType: self.jumpType) 134 | } 135 | } 136 | 137 | public struct TheRouterInfo: Decodable { 138 | public init() {} 139 | 140 | public var targetPath: String? 141 | public var orginPath: String? 142 | public var routerType: Int = 0 // 1: 表示替换或者修复客户端代码path错误 2: 新增路由path 3:删除路由 4: 重置路由 143 | public var path: String? // 新的路由地址 144 | public var className: String? // 路由地址对应的界面 145 | public var params: [String: Any]? 146 | 147 | enum CodingKeys: String, CodingKey { 148 | case targetPath 149 | case orginPath 150 | case path 151 | case className 152 | case routerType 153 | case params 154 | } 155 | 156 | public init(from decoder: Decoder) throws { 157 | 158 | let container = try decoder.container(keyedBy: CodingKeys.self) 159 | targetPath = try container.decodeIfPresent(String.self, forKey: CodingKeys.targetPath) 160 | orginPath = try container.decodeIfPresent(String.self, forKey: CodingKeys.orginPath) 161 | routerType = try container.decode(Int.self, forKey: CodingKeys.routerType) 162 | path = try container.decodeIfPresent(String.self, forKey: CodingKeys.path) 163 | className = try container.decodeIfPresent(String.self, forKey: CodingKeys.className) 164 | params = try container.decodeIfPresent(Dictionary.self, forKey: CodingKeys.params) 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouter+Service.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouter+Service.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension TheRouter { 11 | // MARK: - Register With Service Name 12 | /// 通过服务名称(named)注册LAServiceCreator 13 | /// - Parameters: 14 | /// - named: 服务名称 15 | /// - creator: 服务构造者 16 | class func registerService(named: String, creator: @escaping LAServiceCreator) { 17 | TheRouterServiceManager.default.registerService(named: named, creator: creator) 18 | } 19 | 20 | /// 通过服务名称(named)注册一个服务实例 (存在缓存中) 21 | /// - Parameters: 22 | /// - named: 服务名称 23 | /// - instance: 服务实例 24 | class func registerService(named: String, instance: Any) { 25 | TheRouterServiceManager.default.registerService(named: named, instance: instance) 26 | } 27 | 28 | /// 通过服务名称(named)注册LAServiceCreator 29 | /// - Parameters: 30 | /// - named: 服务名称 31 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 32 | class func registerService(named: String, lazyCreator: @escaping @autoclosure LAServiceCreator) { 33 | TheRouterServiceManager.default.registerService(named: named, lazyCreator: lazyCreator) 34 | } 35 | 36 | // MARK: - Register With Service Type 37 | /// 通过服务接口注册LAServiceCreator 38 | /// - Parameters: 39 | /// - service: 服务接口 40 | /// - creator: 服务构造者 41 | class func registerService(_ service: Service.Type, creator: @escaping () -> Service) { 42 | TheRouterServiceManager.default.registerService(service, creator: creator) 43 | } 44 | 45 | /// 通过服务接口注册LAServiceCreator 46 | /// - Parameters: 47 | /// - service: 服务接口 48 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 49 | class func registerService(_ service: Service.Type, lazyCreator: @escaping @autoclosure () -> Service) { 50 | TheRouterServiceManager.default.registerService(service, lazyCreator: lazyCreator()) 51 | } 52 | 53 | /// 通过服务接口注册一个服务实例 (存在缓存中) 54 | /// - Parameters: 55 | /// - service: 服务接口 56 | /// - instance: 服务实例 57 | class func registerService(_ service: Service.Type, instance: Service) { 58 | TheRouterServiceManager.default.registerService(service, instance: instance) 59 | } 60 | } 61 | 62 | public extension TheRouter { 63 | 64 | /// 根据服务名称创建服务(如果缓存中已有服务实例,则不需要创建) 65 | /// - Parameters: 66 | /// - named: 服务名称 67 | /// - shouldCache: 是否需要缓存 68 | @discardableResult 69 | class func createService(named: String, shouldCache: Bool = true) -> Any? { 70 | return TheRouterServiceManager.default.createService(named: named) 71 | } 72 | 73 | /// 根据服务接口创建服务(如果缓存中已有服务实例,则不需要创建) 74 | /// - Parameters: 75 | /// - service: 服务接口 76 | /// - shouldCache: 是否需要缓存 77 | @discardableResult 78 | class func createService(_ service: Service.Type, shouldCache: Bool = true) -> Service? { 79 | return TheRouterServiceManager.default.createService(service) 80 | } 81 | 82 | /// 通过服务名称获取服务 83 | /// - Parameter named: 服务名称 84 | @discardableResult 85 | class func getService(named: String) -> Any? { 86 | return TheRouterServiceManager.default.getService(named: named) 87 | } 88 | 89 | /// 通过服务接口获取服务 90 | /// - Parameter service: 服务接口 91 | @discardableResult 92 | class func getService(_ service: Service.Type) -> Service? { 93 | return TheRouterServiceManager.default.getService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterBuilder.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/3/9. 6 | // 7 | 8 | import Foundation 9 | 10 | public class TheRouterBuilder { 11 | 12 | public var buildResult: (String, [String: Any]) = ("", [:]) 13 | 14 | public init () {} 15 | } 16 | 17 | extension TheRouterBuilder { 18 | 19 | @discardableResult 20 | public class func build(_ path: String) -> TheRouterBuilder { 21 | let builder = TheRouterBuilder.init() 22 | builder.buildPaths(path: path) 23 | return builder 24 | } 25 | 26 | @discardableResult 27 | public func withInt(key: String, value: Int) -> Self { 28 | buildResult.1[key] = value 29 | return self 30 | } 31 | 32 | @discardableResult 33 | public func withString(key: String, value: String) -> Self { 34 | buildResult.1[key] = value 35 | return self 36 | } 37 | 38 | @discardableResult 39 | public func withBool(key: String, value: Bool) -> Self { 40 | buildResult.1[key] = value 41 | return self 42 | } 43 | 44 | @discardableResult 45 | public func withDouble(key: String, value: Double) -> Self { 46 | buildResult.1[key] = value 47 | return self 48 | } 49 | 50 | @discardableResult 51 | public func withFloat(key: String, value: Float) -> Self { 52 | buildResult.1[key] = value 53 | return self 54 | } 55 | 56 | @discardableResult 57 | public func withAny(key: String, value: Any) -> Self { 58 | buildResult.1[key] = value 59 | return self 60 | } 61 | 62 | func buildPaths(path: String) { 63 | buildResult.0 = path 64 | } 65 | 66 | @discardableResult 67 | public func buildService(_ protocolInstance: TheRouterServiceProtocol.Type, methodName: String) -> Self { 68 | let protocolName = String(describing: protocolInstance) 69 | buildResult.0 = "\(TheRouter.shareInstance.serviceHost)protocol=\(protocolName)&method=\(methodName)" 70 | return self 71 | } 72 | 73 | @discardableResult 74 | public func buildServicePath(_ protocolInstance: TheRouterServiceProtocol.Type, methodName: String) -> String { 75 | let protocolName = String(describing: protocolInstance) 76 | return "\(TheRouter.shareInstance.serviceHost)protocol=\(protocolName)&method=\(methodName)" 77 | } 78 | 79 | @discardableResult 80 | func buildService(path: String) -> Self { 81 | buildResult.0 = path 82 | return self 83 | } 84 | 85 | @discardableResult 86 | public func buildDictionary(param: [String: Any]) -> Self { 87 | buildResult.1.merge(dic: param) 88 | return self 89 | } 90 | 91 | @discardableResult 92 | public func fetchService() -> Any? { 93 | let result = TheRouter.generate(buildResult.0, params: buildResult.1, jumpType: .push) 94 | TheRouter.shareInstance.logcat?(buildResult.0, .logNormal, "") 95 | return TheRouter.openURL(result) 96 | } 97 | 98 | public func navigation(_ handler: ComplateHandler = nil) { 99 | TheRouter.openURL(buildResult, complateHandler: handler) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterDebugTool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterDebugTool.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/11/22. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | public class TheRouterDebugTool { 12 | /// 检测 是否 被追踪 13 | @inline(__always) 14 | public static func checkTracing() -> Bool { 15 | let mib = UnsafeMutablePointer.allocate(capacity: 4) 16 | mib[0] = CTL_KERN//内核查看 17 | mib[1] = KERN_PROC//进程查看 18 | mib[2] = KERN_PROC_PID//进程ID 19 | mib[3] = getpid()//获取pid 20 | var size: Int = MemoryLayout.size 21 | var info: kinfo_proc? = nil 22 | /* 函数的返回值若为0时,证明没有错误,其他数字为错误码。 arg1 传入一个数组,该数组中的第一个元素指定本请求定向到内核的哪个子系统。第二个及其后元素依次细化指定该系统的某个部分。 arg2 数组中的元素数目 arg3 一个结构体,指向一个供内核存放该值的缓冲区,存放进程查询结果 arg4 缓冲区的大小 arg5/arg6 为了设置某个新值,arg5参数指向一个大小为arg6参数值的缓冲区。如果不准备指定一个新值,那么arg5应为一个空指针,arg6因为0. */ 23 | sysctl(mib, 4, &info, &size, nil, 0) 24 | //info.kp_proc.p_flag中存放的是标志位(二进制),在proc.h文件中有p_flag的宏定义,通过&运算可知对应标志位的值是否为0。(若结果值为0则对应标志位为0)。其中P_TRACED为正在跟踪调试过程。 25 | if (info.unsafelyUnwrapped.kp_proc.p_flag & P_TRACED) > 0 { 26 | //监听到被调试 27 | return true 28 | } 29 | return false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterDynamicParamsMapping.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterDynamicParamsMapping.h 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2023/7/27. 6 | // 7 | 8 | #import 9 | 10 | typedef struct ReturnStruct{ 11 | __unsafe_unretained id instanceObject; 12 | __unsafe_unretained id returnValue; 13 | }ReturnStruct; 14 | 15 | @interface TheRouterDynamicParamsMapping : NSObject 16 | 17 | @property (nonatomic, strong) NSArray *filterKey; 18 | 19 | + (instancetype)router; 20 | 21 | /** 22 | 初始化 类。可直接通过NSClassFromString 获取。在这里为保持陆游的美观。才写上 23 | 24 | @param className 类字符串名字 25 | @return 返回类对象 26 | */ 27 | - (Class)routerClassName:(NSString*)className; 28 | 29 | /** 30 | 初始化 类对象。获取类的初始化对象。 31 | 32 | @param className 类名 33 | @return 返回ReturnStruct结构体 包含实例对象 和 返回值。 类的初始化实例 34 | */ 35 | - (id)routerGetInstanceWithClassName:(NSString*)className; 36 | @end 37 | 38 | 39 | @interface NSObject (TheRouterClass) 40 | 41 | /** 42 | 实例子对象 给属性 赋值 43 | @param propertyParameter 属性字典组合。 key为属性的字符串。 value为属性需要赋予的值 44 | @return 返回 45 | */ 46 | - (ReturnStruct)setPropertyParameter:(NSDictionary*)propertyParameter; 47 | 48 | 49 | /** 50 | 执行实例子方法 51 | 52 | @param selectString 方法名 53 | @param methodParaments 方法参数 --- 指针参数 对应参数 以指针类型传入 54 | @return 返回值 55 | */ 56 | - (ReturnStruct)instanceMethodSelect:(NSString*)selectString parameter:(void *)methodParaments, ... NS_REQUIRES_NIL_TERMINATION; 57 | 58 | /** 59 | 执行类方法 60 | 61 | @param selectString 方法名 62 | @param methodParaments 方法参数 --- 指针参数 对应参数 以指针类型传入 63 | @return 返回值 64 | */ 65 | + (ReturnStruct)classMethodSelect:(NSString*)selectString parameter:(void *)methodParaments, ... NS_REQUIRES_NIL_TERMINATION; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LACommonExtension.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension String { 11 | 12 | func containsSubString(substring: String) -> Bool { 13 | return range(of: substring) != nil 14 | } 15 | 16 | func la_dropFirst(_ count: Int) -> String { 17 | let start = self.index(startIndex, offsetBy: 0) 18 | let end = self.index(start, offsetBy: count) 19 | let results = self[start...end] 20 | return String(results) 21 | } 22 | 23 | func la_dropLast(_ count: Int) -> String { 24 | let start = self.index(endIndex, offsetBy: 0) 25 | let end = self.index(endIndex, offsetBy: -count) 26 | let results = self[start...end] 27 | return String(results) 28 | } 29 | 30 | func la_matchClass() -> AnyClass? { 31 | 32 | if let cls: AnyClass = NSClassFromString(self) { 33 | return cls 34 | } 35 | return nil 36 | } 37 | } 38 | 39 | // MARK:- 一、基本的扩展 40 | public extension Dictionary { 41 | 42 | // MARK: 1.1、检查字典里面是否有某个 key 43 | /// 检查字典里面是否有某个 key 44 | func has(_ key: Key) -> Bool { 45 | return index(forKey: key) != nil 46 | } 47 | 48 | // MARK: 1.2、字典的key或者value组成的数组 49 | /// 字典的key或者value组成的数组 50 | /// - Parameter map: map 51 | /// - Returns: 数组 52 | func toArray(_ map: (Key, Value) -> V) -> [V] { 53 | return self.map(map) 54 | } 55 | 56 | // MARK: 1.3、JSON字符串 -> 字典 57 | /// JsonString转为字典 58 | /// - Parameter json: JSON字符串 59 | /// - Returns: 字典 60 | static func jsonToDictionary(json: String) -> Dictionary? { 61 | if let data = (try? JSONSerialization.jsonObject( 62 | with: json.data(using: String.Encoding.utf8, 63 | allowLossyConversion: true)!, 64 | options: JSONSerialization.ReadingOptions.mutableContainers)) as? Dictionary { 65 | return data 66 | } else { 67 | return nil 68 | } 69 | } 70 | 71 | // MARK: 1.4、字典 -> JSON字符串 72 | /// 字典转换为JSONString 73 | func toJSON() -> String? { 74 | if let jsonData = try? JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions()) { 75 | let jsonStr = String(data: jsonData, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) 76 | return String(jsonStr ?? "") 77 | } 78 | return nil 79 | } 80 | 81 | // MARK: 1.5、字典里面所有的 key 82 | /// 字典里面所有的key 83 | /// - Returns: key 数组 84 | func allKeys() -> [Key] { 85 | /* 86 | shuffled:不会改变原数组,返回一个新的随机化的数组。 可以用于let 数组 87 | */ 88 | return self.keys.shuffled() 89 | } 90 | 91 | // MARK: 1.6、字典里面所有的 value 92 | /// 字典里面所有的value 93 | /// - Returns: value 数组 94 | func allValues() -> [Value] { 95 | return self.values.shuffled() 96 | } 97 | 98 | /// MARK: 1.7、用于字典的合并 99 | mutating func merge(dic:Dictionary) { 100 | self.merge(dic) { (parama1, parama2) -> Value in 101 | return parama1 102 | } 103 | } 104 | 105 | mutating func la_combine(_ dict: Dictionary) { 106 | var tem = self 107 | dict.forEach({ (key, value) in 108 | if let existValue = tem[key] { 109 | // combine same name query 110 | if let arrValue = existValue as? [Value] { 111 | tem[key] = (arrValue + [value]) as? Value 112 | } else { 113 | tem[key] = ([existValue, value]) as? Value 114 | } 115 | } else { 116 | tem[key] = value 117 | } 118 | }) 119 | self = tem 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterInterceptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterInterceptor.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import UIKit 9 | 10 | public class TheRouterInterceptor: NSObject { 11 | 12 | public typealias InterceptorHandleBlock = ([String: Any]) -> Bool 13 | 14 | var priority: uint 15 | var whiteList: [String] 16 | var handle: InterceptorHandleBlock 17 | 18 | init(_ whiteList: [String], 19 | priority: uint, 20 | handle: @escaping InterceptorHandleBlock) { 21 | 22 | self.whiteList = whiteList 23 | self.priority = priority 24 | self.handle = handle 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterParser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterParser.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol TheRouterParser { 11 | 12 | typealias ParserResult = (paths: [String], queries: [String: Any]) 13 | // 不做百分号转义 14 | static func parser(_ url: URL) -> ParserResult 15 | static func parserSheme(_ url: URL) -> String 16 | static func parserPaths(_ url: URL) -> [String] 17 | static func parserQuerys(_ url: URL) -> [String: Any] 18 | // 做百分号转义 19 | static func parser(_ urlString: String) -> ParserResult 20 | static func parserSheme(_ urlString: String) -> String 21 | static func parserPaths(_ urlString: String) -> [String] 22 | static func parserQuerys(_ urlString: String) -> [String: Any] 23 | } 24 | 25 | extension TheRouterParser { 26 | 27 | static func parser(_ url: URL) -> ParserResult { 28 | let paths = parserPaths(url) 29 | let query = parserQuerys(url) 30 | return (paths, query) 31 | } 32 | 33 | static func parserSheme(_ url: URL) -> String { 34 | return url.scheme ?? "" 35 | } 36 | 37 | static func parserPaths(_ url: URL) -> [String] { 38 | guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { 39 | return [String]() 40 | } 41 | let paths = la_parserPath(components) 42 | return paths 43 | } 44 | 45 | static func parserQuerys(_ url: URL) -> [String: Any] { 46 | guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { 47 | return [String: Any]() 48 | } 49 | let query = la_parserQuery(components) 50 | return (query as [String: Any]) 51 | } 52 | 53 | static func parser(_ urlString: String) -> ParserResult { 54 | let paths = parserPaths(urlString) 55 | let queries = parserQuerys(urlString) 56 | return (paths, queries) 57 | } 58 | 59 | static func parserSheme(_ urlString: String) -> String { 60 | if let url = canOpenURLString(urlString) { 61 | return url.scheme ?? "" 62 | } 63 | return "" 64 | } 65 | 66 | static func parserPaths(_ urlString: String) -> [String] { 67 | var paths = [String]() 68 | 69 | urlString.components(separatedBy: "#").forEach { componentString in 70 | if let url = canOpenURLString(componentString) { 71 | let result = parserPaths(url) 72 | paths += result 73 | } 74 | } 75 | return paths 76 | } 77 | 78 | static func parserQuerys(_ urlString: String) -> [String: Any] { 79 | var queries = [String: Any]() 80 | 81 | urlString.components(separatedBy: "#").forEach { componentString in 82 | if let url = canOpenURLString(componentString) { 83 | let result = parserQuerys(url) 84 | queries.la_combine(result) 85 | } 86 | } 87 | return queries 88 | } 89 | 90 | /// 解析Path (paths include the host) 91 | private static func la_parserPath(_ components: URLComponents) -> [String] { 92 | 93 | var paths = [String]() 94 | 95 | // check host 96 | if let host = components.host, host.count > 0 { 97 | paths.append(host) 98 | } 99 | 100 | // check path 101 | let path = components.path 102 | if path.count > 0 { 103 | let pathComponents = path.components(separatedBy: "/").filter { $0.count > 0} 104 | paths += pathComponents 105 | } 106 | 107 | return paths 108 | } 109 | 110 | /// 解析Query 111 | private static func la_parserQuery(_ components: URLComponents) -> [String: Any] { 112 | 113 | guard let items = components.queryItems, 114 | items.count > 0 else { 115 | return [:] 116 | } 117 | 118 | var queries = [String: Any]() 119 | items.forEach { (item) in 120 | if let value = item.value { 121 | queries[item.name] = value 122 | } else { 123 | } 124 | } 125 | 126 | return queries 127 | } 128 | 129 | /// 检查URL 130 | public static func canOpenURLString(_ urlString: String) -> URL? { 131 | 132 | let urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) 133 | guard let encodeString = urlString, encodeString.count > 0 else { 134 | return nil 135 | } 136 | 137 | guard let url = URL.init(string: encodeString) else { 138 | return nil 139 | } 140 | 141 | return url 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterPattern.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterPattern.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | import Foundation 9 | 10 | public class TheRouterPattern: TheRouterParser { 11 | 12 | public static let PatternPlaceHolder = "~LA~" 13 | 14 | public var patternString: String 15 | public var sheme: String 16 | public var patternPaths: [String] 17 | public var priority: uint 18 | public var matchString: String 19 | public var classString: String 20 | public var paramsMatchDict: [String: Int] 21 | 22 | public init(_ string: String, 23 | _ classString: String, 24 | priority: uint = 0) { 25 | 26 | self.patternString = string 27 | self.priority = priority 28 | self.sheme = TheRouterPattern.parserSheme(string) 29 | self.patternPaths = TheRouterPattern.parserPaths(string) 30 | self.paramsMatchDict = [String: Int]() 31 | self.classString = classString 32 | var matchPaths = [String]() 33 | for i in 0.. Any 10 | 11 | public final class TheRouterServiceManager { 12 | 13 | public static let `default` = TheRouterServiceManager() 14 | 15 | public init() {} 16 | 17 | /// Service 同步 18 | private let serviceQueue = DispatchQueue(label: "scheme.TheRouterServiceManager.queue") 19 | /// Service构建者 20 | public var creatorsMap: [String: LAServiceCreator] = [:] 21 | /// service缓存 22 | public var servicesCache: [String: Any] = [:] 23 | } 24 | 25 | 26 | // MARK: - Service Register & Unregister 27 | public extension TheRouterServiceManager { 28 | class func serviceName(of value: T) -> String { 29 | return String(describing: value) 30 | } 31 | 32 | // MARK: - Register With Service Name 33 | /// 通过服务名称(named)注册LAServiceCreator 34 | /// - Parameters: 35 | /// - named: 服务名称 36 | /// - creator: 服务构造者 37 | func registerService(named: String, creator: @escaping LAServiceCreator) { 38 | serviceQueue.async { 39 | self.creatorsMap[named] = creator 40 | } 41 | } 42 | 43 | /// 通过服务名称(named)注册一个服务实例 (存在缓存中) 44 | /// - Parameters: 45 | /// - named: 服务名称 46 | /// - instance: 服务实例 47 | func registerService(named: String, instance: Any) { 48 | serviceQueue.async { 49 | self.servicesCache[named] = instance 50 | } 51 | } 52 | 53 | /// 通过服务名称(named)注册LAServiceCreator 54 | /// - Parameters: 55 | /// - named: 服务名称 56 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 57 | func registerService(named: String, lazyCreator: @escaping @autoclosure LAServiceCreator) { 58 | registerService(named: named, creator: lazyCreator) 59 | } 60 | 61 | // MARK: - Register With Service Type 62 | /// 通过服务接口注册LAServiceCreator 63 | /// - Parameters: 64 | /// - service: 服务接口 65 | /// - creator: 服务构造者 66 | func registerService(_ service: Service.Type, creator: @escaping () -> Service) { 67 | registerService(named: TheRouterServiceManager.serviceName(of: service), creator: creator) 68 | } 69 | 70 | /// 通过服务接口注册LAServiceCreator 71 | /// - Parameters: 72 | /// - service: 服务接口 73 | /// - lazyCreator: 延迟实例化构造者 (如:```registerService(named: "A", lazyCreator: A())```) 74 | func registerService(_ service: Service.Type, lazyCreator: @escaping @autoclosure () -> Service) { 75 | registerService(named: TheRouterServiceManager.serviceName(of: service), creator: lazyCreator) 76 | } 77 | 78 | /// 通过服务接口注册一个服务实例 (存在缓存中) 79 | /// - Parameters: 80 | /// - service: 服务接口 81 | /// - instance: 服务实例 82 | func registerService(_ service: Service.Type, instance: Service) { 83 | registerService(named: TheRouterServiceManager.serviceName(of: service), instance: instance) 84 | } 85 | 86 | // MARK: - Unregister Service 87 | 88 | /// 通过服务名称取消注册服务 89 | /// - Parameter named: 服务名称 90 | @discardableResult 91 | func unregisterService(named: String) -> Any? { 92 | return serviceQueue.sync { 93 | self.creatorsMap.removeValue(forKey: named) 94 | return self.servicesCache.removeValue(forKey: named) 95 | } 96 | } 97 | 98 | /// 通过服务接口取消注册服务 99 | /// - Parameter service: 服务接口 100 | @discardableResult 101 | func unregisterService(_ service: Service) -> Service? { 102 | return unregisterService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 103 | } 104 | } 105 | 106 | // MARK: - Register Batch Services 107 | public extension TheRouterServiceManager { 108 | typealias BatchServiceMap = [String: LAServiceCreator] 109 | typealias ServiceEntry = BatchServiceMap.Element 110 | func registerService(_ services: BatchServiceMap) { 111 | serviceQueue.async { 112 | self.creatorsMap.merge(services, uniquingKeysWith: { _, v2 in v2 }) 113 | } 114 | } 115 | 116 | func registerService(entryLiteral entries: ServiceEntry ...) { 117 | return registerService(BatchServiceMap(entries, uniquingKeysWith: {_, v2 in v2})) 118 | } 119 | } 120 | 121 | // MARK: - Service Create 122 | public extension TheRouterServiceManager { 123 | /// 根据服务名称创建服务(如果缓存中已有服务实例,则不需要创建) 124 | /// - Parameters: 125 | /// - named: 服务名称 126 | /// - shouldCache: 是否需要缓存 127 | func createService(named: String, shouldCache: Bool = true) -> Any? { 128 | // 检查是否有缓存 129 | if let service = serviceQueue.sync(execute: { servicesCache[named] }) { 130 | return service 131 | } 132 | // 检查是否有构造者 133 | guard let creator = serviceQueue.sync(execute: { creatorsMap[named] }) else { 134 | return nil 135 | } 136 | 137 | let service = creator() 138 | if shouldCache { 139 | self.serviceQueue.async { 140 | self.servicesCache[named] = service 141 | } 142 | } 143 | return service 144 | } 145 | 146 | /// 根据服务接口创建服务(如果缓存中已有服务实例,则不需要创建) 147 | /// - Parameters: 148 | /// - service: 服务接口 149 | /// - shouldCache: 是否需要缓存 150 | func createService(_ service: Service.Type, shouldCache: Bool = true) -> Service? { 151 | return createService(named: TheRouterServiceManager.serviceName(of: service), shouldCache: shouldCache) as? Service 152 | } 153 | } 154 | 155 | // MARK: - Service Fetch 156 | public extension TheRouterServiceManager { 157 | /// 通过服务名称获取服务 158 | /// - Parameter named: 服务名称 159 | func getService(named: String) -> Any? { 160 | return self.createService(named: named) 161 | } 162 | 163 | /// 通过服务接口获取服务 164 | /// - Parameter service: 服务接口 165 | func getService(_ service: Service.Type) -> Service? { 166 | return getService(named: TheRouterServiceManager.serviceName(of: service)) as? Service 167 | } 168 | } 169 | 170 | 171 | // MARK: - Service Clean Cache 172 | public extension TheRouterServiceManager { 173 | func cleanAllServiceCache() { 174 | serviceQueue.async { 175 | self.servicesCache.removeAll() 176 | } 177 | } 178 | 179 | @discardableResult 180 | func cleanServiceCache(named: String) -> Any? { 181 | return serviceQueue.sync { 182 | return self.servicesCache.removeValue(forKey: named) 183 | } 184 | } 185 | 186 | @discardableResult 187 | func cleanServiceCache(by service: Service.Type) -> Service? { 188 | return cleanServiceCache(named: TheRouterServiceManager.serviceName(of: service)) as? Service 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterServiceProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterServiceProtocol.swift 3 | // 4 | // Created by mars.yao on 2021/9/1. 5 | // 6 | 7 | import Foundation 8 | 9 | @objc 10 | public protocol TheRouterServiceProtocol: NSObjectProtocol { 11 | init() 12 | 13 | static var seriverName: String { get } 14 | } 15 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterable/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterable/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 6.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "TheRouterable", 8 | products: [ 9 | // Products define the executables and libraries a package produces, making them visible to other packages. 10 | .library( 11 | name: "TheRouterable", 12 | targets: ["TheRouterable"]), 13 | ], 14 | targets: [ 15 | // Targets are the basic building blocks of a package, defining a module or a test suite. 16 | // Targets can depend on other targets in this package and products from dependencies. 17 | .target( 18 | name: "TheRouterable"), 19 | 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterable/Sources/TheRouter/TheRouterable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterable.swift 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2021/9/1. 6 | // 7 | 8 | 9 | public protocol TheRouterable { 10 | 11 | static var patternString: [String] { get } 12 | 13 | static var priority: UInt { get } 14 | } 15 | 16 | extension TheRouterable { 17 | public static var priority: UInt { 18 | 1000 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TheRouter/Classes/TheRouterableProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // TheRouterableProxy.h 3 | // TheRouter 4 | // 5 | // Created by mars.yao on 2024/4/8. 6 | // 7 | 8 | #import 9 | 10 | typedef NS_OPTIONS(NSUInteger, TheRouterPriority) { 11 | TheRouterPriorityLow = 1000, 12 | TheRouterPriorityDefault = 1001, 13 | TheRouterPriorityHeight = 1002 14 | }; 15 | 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | @protocol TheRouterableProxy 19 | 20 | // 使用类方法替代静态属性 21 | + (NSArray *)patternString; 22 | 23 | @optional 24 | + (NSUInteger)priority; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /TheRouterMacro/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.swift] 2 | indent_style = space 3 | indent_size = 4 4 | tab_width = 4 5 | end_of_line = crlf 6 | insert_final_newline = false 7 | max_line_length = 120 8 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /TheRouterMacro/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /TheRouterMacro/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "lldb", 5 | "request": "launch", 6 | "args": [], 7 | "cwd": "${workspaceFolder:TheRouterMacro}", 8 | "name": "Debug TheRouterMacroClient", 9 | "program": "${workspaceFolder:TheRouterMacro}/.build/debug/TheRouterMacroClient", 10 | "preLaunchTask": "swift: Build Debug TheRouterMacroClient" 11 | }, 12 | { 13 | "type": "lldb", 14 | "request": "launch", 15 | "args": [], 16 | "cwd": "${workspaceFolder:TheRouterMacro}", 17 | "name": "Release TheRouterMacroClient", 18 | "program": "${workspaceFolder:TheRouterMacro}/.build/release/TheRouterMacroClient", 19 | "preLaunchTask": "swift: Build Release TheRouterMacroClient" 20 | }, 21 | { 22 | "type": "lldb", 23 | "request": "launch", 24 | "args": [], 25 | "cwd": "${workspaceFolder:TheRouterMacro}", 26 | "name": "Debug TheRouterMacroMacros", 27 | "program": "${workspaceFolder:TheRouterMacro}/.build/debug/TheRouterMacroMacros", 28 | "preLaunchTask": "swift: Build Debug TheRouterMacroMacros" 29 | }, 30 | { 31 | "type": "lldb", 32 | "request": "launch", 33 | "args": [], 34 | "cwd": "${workspaceFolder:TheRouterMacro}", 35 | "name": "Release TheRouterMacroMacros", 36 | "program": "${workspaceFolder:TheRouterMacro}/.build/release/TheRouterMacroMacros", 37 | "preLaunchTask": "swift: Build Release TheRouterMacroMacros" 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /TheRouterMacro/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "ce76bfd6822c6069ad575052b8f6b9800f919509ff42807262a6284f80c448df", 3 | "pins" : [ 4 | { 5 | "identity" : "swift-syntax", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/swiftlang/swift-syntax.git", 8 | "state" : { 9 | "revision" : "0687f71944021d616d34d922343dcef086855920", 10 | "version" : "600.0.1" 11 | } 12 | } 13 | ], 14 | "version" : 3 15 | } 16 | -------------------------------------------------------------------------------- /TheRouterMacro/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 6.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import CompilerPluginSupport 5 | import PackageDescription 6 | 7 | let package = Package( 8 | name: "TheRouterMacro", 9 | platforms: [ 10 | .iOS(.v13), 11 | .macOS(.v10_15), 12 | ], 13 | products: [ 14 | // Products define the executables and libraries a package produces, making them visible to other packages. 15 | .executable( 16 | name: "TheRouterMacroMacros", 17 | targets: ["TheRouterMacroMacros"] 18 | ), 19 | ], 20 | dependencies: [ 21 | .package(url: "https://github.com/swiftlang/swift-syntax.git", from: "600.0.0-latest"), 22 | .package(path: "../TheRouter/Classes/TheRouterable"), 23 | ], 24 | targets: [ 25 | // Targets are the basic building blocks of a package, defining a module or a test suite. 26 | // Targets can depend on other targets in this package and products from dependencies. 27 | // Macro implementation that performs the source transformation of a macro. 28 | .executableTarget( 29 | name: "TheRouterMacroMacros", 30 | dependencies: [ 31 | .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), 32 | .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), 33 | .product(name: "TheRouterable", package: "TheRouterable"), 34 | ] 35 | ), 36 | ] 37 | ) 38 | -------------------------------------------------------------------------------- /TheRouterMacro/Sources/TheRouterMacro/TheRouterMacro.swift: -------------------------------------------------------------------------------- 1 | // The Swift Programming Language 2 | // https://docs.swift.org/swift-book 3 | 4 | @attached(extension, conformances: TheRouterable, names: named(patternString)) 5 | public macro RouterPage(_ value: [String]) = #externalMacro(module: "TheRouterMacroMacros", type: "TheRouterPageMacro") 6 | -------------------------------------------------------------------------------- /TheRouterMacro/Sources/TheRouterMacroClient/main.swift: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /TheRouterMacro/Sources/TheRouterMacroMacros/TheRouterMacroMacro.swift: -------------------------------------------------------------------------------- 1 | import SwiftCompilerPlugin 2 | import SwiftSyntax 3 | import SwiftSyntaxBuilder 4 | import SwiftSyntaxMacros 5 | 6 | enum TheRouterPageMacroError: Error, CustomStringConvertible { 7 | case onlyApplicableToViewController 8 | case onlyStringName 9 | 10 | var description: String { 11 | switch self { 12 | case .onlyApplicableToViewController: 13 | return "@TheRouterPageMacro can only be applied to a ViewController" 14 | case .onlyStringName: 15 | return "@TheRouterPageMacro can only be applied to a String name" 16 | } 17 | } 18 | } 19 | 20 | public struct TheRouterPageMacro: ExtensionMacro { 21 | public static func expansion( 22 | of node: SwiftSyntax.AttributeSyntax, 23 | attachedTo declaration: some SwiftSyntax.DeclGroupSyntax, 24 | providingExtensionsOf type: some SwiftSyntax.TypeSyntaxProtocol, 25 | conformingTo protocols: [SwiftSyntax.TypeSyntax], 26 | in context: some SwiftSyntaxMacros.MacroExpansionContext 27 | ) throws -> [SwiftSyntax.ExtensionDeclSyntax] { 28 | guard declaration.is(ClassDeclSyntax.self) else { 29 | throw TheRouterPageMacroError.onlyApplicableToViewController 30 | } 31 | guard let paths = node.arguments?.as(LabeledExprListSyntax.self)?.first?.expression else { 32 | throw TheRouterPageMacroError.onlyStringName 33 | } 34 | let patternBindingList = PatternBindingListSyntax([ 35 | PatternBindingSyntax( 36 | pattern: IdentifierPatternSyntax(identifier: .identifier("patternString")), 37 | typeAnnotation: TypeAnnotationSyntax( 38 | colon: .colonToken(), 39 | type: ArrayTypeSyntax(element: IdentifierTypeSyntax(name: .identifier("String"))) 40 | ), 41 | accessorBlock: AccessorBlockSyntax( 42 | accessors: .getter(CodeBlockItemListSyntax([ 43 | CodeBlockItemSyntax(item: .expr(paths)) 44 | ])) 45 | ) 46 | ) 47 | ]) 48 | let members = MemberBlockItemListSyntax([ 49 | MemberBlockItemSyntax(decl: VariableDeclSyntax( 50 | modifiers: DeclModifierListSyntax([DeclModifierSyntax(name: .keyword(.static))]), 51 | bindingSpecifier: .keyword(.var), 52 | bindings: patternBindingList 53 | )) 54 | ]) 55 | return [ 56 | ExtensionDeclSyntax( 57 | extensionKeyword: .keyword(.extension), 58 | extendedType: type.trimmed, 59 | inheritanceClause: InheritanceClauseSyntax( 60 | inheritedTypes: InheritedTypeListSyntax(protocols.map({ 61 | InheritedTypeSyntax(type: $0) 62 | })) 63 | ), 64 | memberBlock: MemberBlockSyntax( 65 | leftBrace: .leftBraceToken(), 66 | members: members, 67 | rightBrace: .rightBraceToken() 68 | ) 69 | ) 70 | ] 71 | } 72 | } 73 | 74 | @main 75 | struct TheRouterMacroPlugin: CompilerPlugin { 76 | let providingMacros: [Macro.Type] = [ 77 | TheRouterPageMacro.self 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /assets/IMG_7130.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/IMG_7130.JPG -------------------------------------------------------------------------------- /assets/ScreenRecording.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/ScreenRecording.gif -------------------------------------------------------------------------------- /assets/TheRouter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/TheRouter.png -------------------------------------------------------------------------------- /assets/chat_group.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/chat_group.JPG -------------------------------------------------------------------------------- /assets/fetchRouterRegisterClass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/fetchRouterRegisterClass.png -------------------------------------------------------------------------------- /assets/loadclass_cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/loadclass_cache.png -------------------------------------------------------------------------------- /assets/opt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/opt.png -------------------------------------------------------------------------------- /assets/project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/project.png -------------------------------------------------------------------------------- /assets/registerList_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/registerList_save.png -------------------------------------------------------------------------------- /assets/services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/services.png -------------------------------------------------------------------------------- /assets/services_register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/services_register.png -------------------------------------------------------------------------------- /assets/vc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuolalaTech/hll-wp-therouter-ios/50d4dac6f7f901336d51d5e3af0134e8df8389fa/assets/vc.png --------------------------------------------------------------------------------