├── .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 | [](https://travis-ci.org/scalessec/Toast)
5 | [](http://cocoadocs.org/docsets/Toast)
6 | [](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 | 
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
--------------------------------------------------------------------------------