├── .gitignore
├── Apis.podspec
├── Apis.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Demo
├── Demo.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Demo.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Demo
│ ├── Account.swift
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── FastViewController.swift
│ ├── Info.plist
│ ├── LiveViewController.swift
│ ├── LoginViewController.swift
│ ├── NeedLoginViewController.swift
│ ├── NoneViewController.swift
│ ├── Router
│ │ ├── Plugins
│ │ │ ├── RouterAccountPlugin.swift
│ │ │ ├── RouterLaunchPlugin.swift
│ │ │ └── RouterSinglePlugin.swift
│ │ ├── Router.swift
│ │ └── RouterTarget.swift
│ ├── Utils
│ │ ├── Notification.swift
│ │ └── Notificationable.swift
│ └── ViewController.swift
├── Podfile
├── Podfile.lock
└── Pods
│ ├── Local Podspecs
│ ├── Apis.podspec.json
│ └── Router.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ └── project.pbxproj
│ ├── SnapKit
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ ├── Constraint.swift
│ │ ├── ConstraintAttributes.swift
│ │ ├── ConstraintConfig.swift
│ │ ├── ConstraintConstantTarget.swift
│ │ ├── ConstraintDSL.swift
│ │ ├── ConstraintDescription.swift
│ │ ├── ConstraintDirectionalInsetTarget.swift
│ │ ├── ConstraintDirectionalInsets.swift
│ │ ├── ConstraintInsetTarget.swift
│ │ ├── ConstraintInsets.swift
│ │ ├── ConstraintItem.swift
│ │ ├── ConstraintLayoutGuide+Extensions.swift
│ │ ├── ConstraintLayoutGuide.swift
│ │ ├── ConstraintLayoutGuideDSL.swift
│ │ ├── ConstraintLayoutSupport.swift
│ │ ├── ConstraintLayoutSupportDSL.swift
│ │ ├── ConstraintMaker.swift
│ │ ├── ConstraintMakerEditable.swift
│ │ ├── ConstraintMakerExtendable.swift
│ │ ├── ConstraintMakerFinalizable.swift
│ │ ├── ConstraintMakerPriortizable.swift
│ │ ├── ConstraintMakerRelatable.swift
│ │ ├── ConstraintMultiplierTarget.swift
│ │ ├── ConstraintOffsetTarget.swift
│ │ ├── ConstraintPriority.swift
│ │ ├── ConstraintPriorityTarget.swift
│ │ ├── ConstraintRelatableTarget.swift
│ │ ├── ConstraintRelation.swift
│ │ ├── ConstraintView+Extensions.swift
│ │ ├── ConstraintView.swift
│ │ ├── ConstraintViewDSL.swift
│ │ ├── Debugging.swift
│ │ ├── LayoutConstraint.swift
│ │ ├── LayoutConstraintItem.swift
│ │ ├── Typealiases.swift
│ │ └── UILayoutSupport+Extensions.swift
│ └── Target Support Files
│ ├── Apis
│ ├── Apis-Info.plist
│ ├── Apis-dummy.m
│ ├── Apis-prefix.pch
│ ├── Apis-umbrella.h
│ ├── Apis.debug.xcconfig
│ ├── Apis.modulemap
│ ├── Apis.release.xcconfig
│ ├── ResourceBundle-Apis-Apis-Info.plist
│ └── ResourceBundle-Privacy-Apis-Info.plist
│ ├── Pods-Demo
│ ├── Pods-Demo-Info.plist
│ ├── Pods-Demo-acknowledgements.markdown
│ ├── Pods-Demo-acknowledgements.plist
│ ├── Pods-Demo-dummy.m
│ ├── Pods-Demo-frameworks-Debug-input-files.xcfilelist
│ ├── Pods-Demo-frameworks-Debug-output-files.xcfilelist
│ ├── Pods-Demo-frameworks-Release-input-files.xcfilelist
│ ├── Pods-Demo-frameworks-Release-output-files.xcfilelist
│ ├── Pods-Demo-frameworks.sh
│ ├── Pods-Demo-umbrella.h
│ ├── Pods-Demo.debug.xcconfig
│ ├── Pods-Demo.modulemap
│ └── Pods-Demo.release.xcconfig
│ └── SnapKit
│ ├── SnapKit-Info.plist
│ ├── SnapKit-dummy.m
│ ├── SnapKit-prefix.pch
│ ├── SnapKit-umbrella.h
│ ├── SnapKit.debug.xcconfig
│ ├── SnapKit.modulemap
│ └── SnapKit.release.xcconfig
├── LICENSE
├── README.md
├── README_CN.md
└── Sources
├── Apis.h
├── Context.swift
├── PrivacyInfo.xcprivacy
├── Protocol.swift
├── Provider.swift
├── UIApplicationExtension.swift
├── UIViewControllerExtension.swift
├── URLConvertible.swift
├── URLMatcher.swift
├── URLNavigator.swift
└── URLPathComponent.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/Apis.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "Apis"
4 | s.version = "1.2.2"
5 | s.summary = "基于URLNavigator抽象的URL路由组件 灵感来自Moya 配置化 插件化."
6 |
7 | s.homepage = "https://github.com/lixiang1994/Apis"
8 |
9 | s.license = { :type => "MIT", :file => "LICENSE" }
10 |
11 | s.author = { "LEE" => "18611401994@163.com" }
12 |
13 | s.platform = :ios, "9.0"
14 |
15 | s.source = { :git => "https://github.com/lixiang1994/Apis.git", :tag => s.version }
16 |
17 | s.source_files = "Sources/**/*.swift"
18 |
19 | s.requires_arc = true
20 |
21 | s.frameworks = "UIKit", "Foundation"
22 |
23 | s.swift_version = "5.0"
24 |
25 | s.subspec 'Privacy' do |ss|
26 | ss.resource_bundles = {
27 | s.name => 'Sources/PrivacyInfo.xcprivacy'
28 | }
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/Apis.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Apis.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/Demo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demo/Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/Demo/Account.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Account.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/27.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum Account {
12 |
13 | static var isLogin: Bool {
14 | return info != nil
15 | }
16 |
17 | static var info: User?
18 | }
19 |
20 | struct User {
21 | let id: Int
22 | let name: String
23 | let avatar: String
24 | /* ... */
25 | }
26 |
--------------------------------------------------------------------------------
/Demo/Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/12.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | static var shared: AppDelegate {
15 | return UIApplication.shared.delegate as! AppDelegate
16 | }
17 |
18 | var window: UIWindow?
19 | var isLaunched: Bool = false
20 |
21 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
22 |
23 | // 模拟1秒后启动完成
24 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
25 | self.isLaunched = true
26 | NotificationCenter.Delegate.post(.launched)
27 | }
28 |
29 | return true
30 | }
31 |
32 | func applicationWillResignActive(_ application: UIApplication) {
33 | // 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.
34 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
35 | }
36 |
37 | func applicationDidEnterBackground(_ application: UIApplication) {
38 | // 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.
39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
40 | }
41 |
42 | func applicationWillEnterForeground(_ application: UIApplication) {
43 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
44 | }
45 |
46 | func applicationDidBecomeActive(_ application: UIApplication) {
47 | // 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.
48 | }
49 |
50 | func applicationWillTerminate(_ application: UIApplication) {
51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
52 | }
53 |
54 |
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/Demo/Demo/Assets.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" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Demo/Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Demo/Demo/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 |
--------------------------------------------------------------------------------
/Demo/Demo/Base.lproj/Main.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 |
27 |
28 |
29 |
30 |
31 |
32 |
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 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/Demo/Demo/FastViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FastViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class FastViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | view.backgroundColor = #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)
17 |
18 | let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
19 | view.addGestureRecognizer(tap)
20 | }
21 |
22 | @objc func tapAction() {
23 | close()
24 | }
25 | }
26 |
27 | extension FastViewController: RouterSingleable {
28 |
29 | var single: RouterSingleType {
30 | return .fast
31 | }
32 |
33 | func close(will single: RouterSingleType, completion: @escaping (Bool) -> Void) {
34 | switch single {
35 | case .fast:
36 | completion(false)
37 |
38 | default:
39 | close {
40 | completion(true)
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Demo/Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Router
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLSchemes
27 |
28 | router
29 |
30 |
31 |
32 | CFBundleVersion
33 | 1
34 | LSRequiresIPhoneOS
35 |
36 | UILaunchStoryboardName
37 | LaunchScreen
38 | UIMainStoryboardFile
39 | Main
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 |
48 | UISupportedInterfaceOrientations~ipad
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationPortraitUpsideDown
52 | UIInterfaceOrientationLandscapeLeft
53 | UIInterfaceOrientationLandscapeRight
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Demo/Demo/LiveViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LiveViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LiveViewController: UIViewController {
12 |
13 | var id: String = ""
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | view.backgroundColor = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)
19 |
20 | let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
21 | view.addGestureRecognizer(tap)
22 | }
23 |
24 | @objc func tapAction() {
25 | close()
26 | }
27 | }
28 |
29 | extension LiveViewController: RouterSingleable {
30 |
31 | var single: RouterSingleType {
32 | return .live
33 | }
34 |
35 | func close(will single: RouterSingleType, completion: @escaping (Bool) -> Void) {
36 | close {
37 | completion(true)
38 | }
39 | }
40 |
41 | func open(_ completion: @escaping () -> Void) {
42 | guard let controller = UIViewController.top() else {
43 | return
44 | }
45 | controller.present(self, animated: true, completion: completion)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Demo/Demo/LoginViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/27.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SnapKit
11 |
12 | class LoginViewController: UIViewController {
13 |
14 | lazy var loginButton: UIButton = {
15 | $0.setTitle("Login", for: .normal)
16 | $0.setTitleColor(.black, for: .normal)
17 | $0.addTarget(self, action: #selector(loginAction), for: .touchUpInside)
18 | return $0
19 | } ( UIButton() )
20 |
21 | lazy var cancelButton: UIButton = {
22 | $0.setTitle("Cancel", for: .normal)
23 | $0.setTitleColor(.red, for: .normal)
24 | $0.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
25 | return $0
26 | } ( UIButton() )
27 |
28 | private var completion: ((Bool) -> Void)?
29 |
30 | init(_ completion: @escaping ((Bool) -> Void)) {
31 | self.completion = completion
32 | super.init(nibName: nil, bundle: nil)
33 | }
34 |
35 | required init?(coder aDecoder: NSCoder) {
36 | super.init(coder: aDecoder)
37 | }
38 |
39 | override func viewDidLoad() {
40 | super.viewDidLoad()
41 | setup()
42 | setupLayout()
43 | }
44 |
45 | private func setup() {
46 | view.backgroundColor = .white
47 | view.addSubview(loginButton)
48 | view.addSubview(cancelButton)
49 | }
50 |
51 | private func setupLayout() {
52 | loginButton.snp.makeConstraints { (make) in
53 | make.center.equalToSuperview()
54 | }
55 |
56 | cancelButton.snp.makeConstraints { (make) in
57 | make.centerX.equalToSuperview()
58 | make.top.equalTo(loginButton.snp.bottom).offset(40)
59 | }
60 | }
61 | }
62 |
63 | extension LoginViewController {
64 |
65 | @objc private func loginAction(_ sender: UIButton) {
66 | // 假装登录成功 存储用户信息
67 | Account.info = User(id: 1994, name: "LEE", avatar: "XXXX")
68 |
69 | dismiss(animated: true) {
70 | self.completion?(true)
71 | }
72 | }
73 |
74 | @objc private func cancelAction(_ sender: UIButton) {
75 | dismiss(animated: true) {
76 | self.completion?(false)
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Demo/Demo/NeedLoginViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NeedLoginViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/27.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NeedLoginViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | view.backgroundColor = #colorLiteral(red: 1, green: 0.3137254902, blue: 0.3137254902, alpha: 1)
17 |
18 | let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
19 | view.addGestureRecognizer(tap)
20 | }
21 |
22 | @objc func tapAction() {
23 | close()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Demo/Demo/NoneViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoneViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class NoneViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | view.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Demo/Demo/Router/Plugins/RouterAccountPlugin.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RouterAccountPlugin.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import Apis
10 |
11 | class RouterAccountPlugin: Apis.PluginType {
12 |
13 | /*
14 | 在准备打开阶段 拦截需要登录的类型, 并根据登录状态处理是否需要打开登录页面
15 | 登录成功后可执行回调继续打开流程
16 | */
17 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
18 | guard case .open_needlogin = target as? RouterTarget else {
19 | completion(true)
20 | return
21 | }
22 | guard !Account.isLogin else {
23 | completion(true)
24 | return
25 | }
26 | guard let root = AppDelegate.shared.window?.rootViewController else {
27 | completion(false)
28 | return
29 | }
30 | let controller = LoginViewController.init { (result) in
31 | completion(result)
32 | }
33 | root.present(controller, animated: true)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Demo/Demo/Router/Plugins/RouterLaunchPlugin.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RouterLaunchPlugin.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import Apis
10 |
11 | class RouterLaunchPlugin: Apis.PluginType {
12 |
13 | private var completion: ((Bool) -> Void)?
14 |
15 | init() {
16 | NotificationCenter.Delegate.add(
17 | .launched,
18 | observer: self,
19 | selector: #selector(launched)
20 | )
21 | }
22 |
23 | @objc private func launched() {
24 | completion?(true)
25 | completion = nil
26 | }
27 |
28 | /*
29 | 在准备打开阶段 处理启动状态
30 | 通常在APP启动后 我们需要进行一些必要的操作 例如: 加载必要的配置数据等等,
31 | 这些操作没完成之前就打开了某些页面 是非常危险的.
32 | 这里演示的就是根据启动完成状态延后打开操作, 常见的情景为 外部通过OpenURL启动APP打开某一页面.
33 | */
34 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
35 | guard !AppDelegate.shared.isLaunched else {
36 | completion(true)
37 | return
38 | }
39 | self.completion?(false)
40 | self.completion = completion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Demo/Demo/Router/Plugins/RouterSinglePlugin.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RouterSinglePlugin.swift
3 | // Route
4 | //
5 | // Created by 李响 on 2019/4/10.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import Apis
10 |
11 | protocol RouterSingleable: Routerable {
12 |
13 | /// 当前类型
14 | var single: RouterSingleType { get }
15 |
16 | /// 关闭
17 | ///
18 | /// - Parameters:
19 | /// - single: 即将准备打开的类型
20 | /// - completion: 关闭完成回调
21 | func close(will single: RouterSingleType, completion: @escaping (Bool) -> Void)
22 | }
23 |
24 | enum RouterSingleType {
25 | case live
26 | case fast
27 | }
28 |
29 | class RouterSinglePlugin: Apis.PluginType {
30 |
31 | /*
32 | 在准备打开阶段 拦截单一特性页面
33 | (在一些业务场景中 最多只能有一个打开, 不能同时打开的页面的这种特性 简称单一特性)
34 |
35 | 判断当前要打开的类型是否为单一特性类型.
36 | 判断当前是否有相同单一特性的页面已经打开.
37 | 告知原来已经打开的页面即将要打开一个新的页面 请求关闭处理.
38 | */
39 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
40 | guard let single = make(target) else {
41 | completion(true)
42 | return
43 | }
44 | guard let current = current?.object else {
45 | completion(true)
46 | return
47 | }
48 | current.close(will: single, completion: completion)
49 | }
50 |
51 | /*
52 | 在即将打开的方法中记录新的单一特性页面, 以供下一次打开时进行操作
53 | */
54 | func will(open target: TargetType, controller: Routerable) {
55 | guard let controller = controller as? Singleable else {
56 | return
57 | }
58 | current = WeakWrapper(controller)
59 | }
60 | }
61 |
62 | extension RouterSinglePlugin {
63 |
64 | typealias Singleable = RouterSingleable
65 | private static var currentWrapper: WeakWrapper?
66 |
67 | private var current: WeakWrapper? {
68 | get { return RouterSinglePlugin.currentWrapper }
69 | set { RouterSinglePlugin.currentWrapper = newValue }
70 | }
71 |
72 | private class WeakWrapper {
73 | weak var object: Singleable?
74 | init(_ object: Singleable?) {
75 | self.object = object
76 | }
77 | }
78 | }
79 |
80 | extension RouterSinglePlugin {
81 |
82 | func make(_ target: TargetType) -> RouterSingleType? {
83 | guard let target = target as? RouterTarget else { return nil }
84 | switch target {
85 | case .open_live: return .live
86 | case .open_fast: return .fast
87 | default: return nil
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Demo/Demo/Router/Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Router.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/12.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import Apis
12 |
13 | enum Router {
14 |
15 | // 初始化Router 并传入需要的插件
16 | static let shared = Apis.Provider(
17 | plugins:
18 | [
19 | RouterLaunchPlugin(),
20 | RouterAccountPlugin(),
21 | RouterSinglePlugin()
22 | ]
23 | )
24 | }
25 |
26 | extension Router {
27 |
28 | /// 打开
29 | ///
30 | /// - Parameters:
31 | /// - url: url
32 | /// - completion: 完成回调
33 | /// - Returns: true or false
34 | @discardableResult
35 | static func open(_ url: URLConvertible,
36 | completion: ((Bool) -> Void)? = .none) -> Bool {
37 | return shared.open(url, completion: completion)
38 | }
39 |
40 | /// 获取视图控制器
41 | ///
42 | /// - Parameters:
43 | /// - url: url
44 | /// - context: context
45 | /// - Returns: 视图控制器
46 | static func viewController(_ url: URLConvertible) -> UIViewController? {
47 | return shared.controller(url)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Demo/Demo/Router/RouterTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RouterTarget.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2021/12/10.
6 | // Copyright © 2021 swift. All rights reserved.
7 | //
8 |
9 | import Apis
10 | import SafariServices
11 |
12 | enum RouterTarget {
13 | case open_http(url: URL)
14 | case open_https(url: URL)
15 | case open_none
16 | case open_live(id: String)
17 | case open_fast
18 | case open_needlogin
19 | case open_some
20 | }
21 |
22 | extension RouterTarget: Apis.TargetType {
23 |
24 | var task: Task {
25 | switch(self) {
26 | case let .open_http(url):
27 | return .controller(SFSafariViewController(url: url))
28 |
29 | case let .open_https(url):
30 | return .controller(SFSafariViewController(url: url))
31 |
32 | case .open_none:
33 | return .controller(NoneViewController())
34 |
35 | case let .open_live(id):
36 | let controller = LiveViewController()
37 | controller.id = id
38 | return .controller(controller)
39 |
40 | case .open_fast:
41 | return .controller(FastViewController())
42 |
43 | case .open_needlogin:
44 | return .controller(NeedLoginViewController())
45 |
46 | case .open_some:
47 | return .handle { completion in
48 | // 处理一些其他事情, 结束后务必调用completion回调
49 | DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
50 | // 巴拉巴拉..
51 | print("do something")
52 | completion(true)
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
59 | private let schemes = "router"
60 |
61 | extension RouterTarget: URLTargetType {
62 |
63 | static var bindings: [URLPatternBinding] {
64 | return [
65 | .init("http://") { source in
66 | guard let url = source.url.value else { return .none }
67 | return .open_http(url: url)
68 | },
69 | .init("https://") { source in
70 | guard let url = source.url.value else { return .none }
71 | return .open_https(url: url)
72 | },
73 | .init(schemes + "://open/none") {
74 | return .open_none
75 | },
76 | .init(schemes + "://open/fast") {
77 | return .open_fast
78 | },
79 | .init(schemes + "://open/live") { source in
80 | guard let id = source.url.queryParameters["id"] else { return nil }
81 | return .open_live(id: id)
82 | },
83 | .init(schemes + "://open/needlogin") {
84 | return .open_needlogin
85 | },
86 | .init(schemes + "://open/some") {
87 | return .open_some
88 | }
89 | ]
90 | }
91 | }
92 |
93 | // 所有需要支持 Router 的视图控制器都需要实现 Routerable 协议
94 | // Routerable 协议默认实现了通用的打开关闭处理逻辑 如无法满足 可重写
95 |
96 | extension NoneViewController: Routerable { }
97 | extension NeedLoginViewController: Routerable { }
98 |
99 | extension SFSafariViewController: Routerable {
100 |
101 | public func open(with completion: @escaping () -> Void = {}) {
102 | guard let controller = UIViewController.top() else {
103 | return
104 | }
105 |
106 | controller.present(self, animated: true, completion: completion)
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Demo/Demo/Utils/Notification.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension NotificationCenter {
4 |
5 | enum Delegate: Notificationable {
6 | enum defaultKeys: String {
7 | case launched
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Demo/Demo/Utils/Notificationable.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | protocol Notificationable {
4 | associatedtype defaultKeys: RawRepresentable
5 | }
6 |
7 | extension Notificationable where defaultKeys.RawValue == String {
8 |
9 | static func post(_ name: defaultKeys, object: Any? = nil, userInfo: [AnyHashable: Any]? = nil) {
10 | NotificationCenter.default.post(
11 | name: conversion(name),
12 | object: object,
13 | userInfo: userInfo
14 | )
15 | }
16 |
17 | static func add(_ name: defaultKeys, observer: Any, selector: Selector, object: Any? = nil) {
18 | NotificationCenter.default.addObserver(
19 | observer,
20 | selector: selector,
21 | name: conversion(name),
22 | object: object
23 | )
24 | }
25 |
26 | static func add(_ name: defaultKeys,
27 | _ object: Any? = nil,
28 | queue: OperationQueue = .main,
29 | using block: @escaping (Notification) -> Void) {
30 | NotificationCenter.default.addObserver(
31 | forName: conversion(name),
32 | object: object,
33 | queue: .main,
34 | using: block
35 | )
36 | }
37 |
38 | static func remove(_ name: defaultKeys, observer: Any, object: Any? = nil) {
39 | NotificationCenter.default.removeObserver(
40 | observer,
41 | name: conversion(name),
42 | object: object
43 | )
44 | }
45 |
46 | static private func conversion(_ key: defaultKeys) -> NSNotification.Name {
47 | return NSNotification.Name("\(self).\(key.rawValue)")
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Demo/Demo/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Demo
4 | //
5 | // Created by 李响 on 2019/4/12.
6 | // Copyright © 2019 swift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | @IBOutlet weak var tableView: UITableView!
14 |
15 | private var list: [String] = [
16 | "打开http/https链接",
17 | "打开一个普通的页面",
18 | "打开一个需要登录的页面",
19 | "打开一个单一特性的页面 4s后打开另一个",
20 | "打开一个单一特性的页面 4s后打开新页面"
21 | ]
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 |
26 | setup()
27 | }
28 |
29 | private func setup() {
30 | tableView.delegate = self
31 | tableView.dataSource = self
32 | }
33 | }
34 |
35 | extension ViewController: UITableViewDelegate {
36 |
37 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
38 | return 50
39 | }
40 | }
41 |
42 | extension ViewController: UITableViewDataSource {
43 |
44 | func numberOfSections(in tableView: UITableView) -> Int {
45 | return 1
46 | }
47 |
48 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
49 | return list.count
50 | }
51 |
52 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
53 | let cell = tableView.dequeueReusableCell(
54 | withIdentifier: "cell",
55 | for: indexPath
56 | )
57 | cell.textLabel?.text = list[indexPath.row]
58 | return cell
59 | }
60 |
61 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
62 | tableView.deselectRow(at: indexPath, animated: true)
63 |
64 | switch indexPath.row {
65 | case 0: // 打开http/https链接
66 | Router.open("https://www.baidu.com")
67 |
68 | case 1: // 打开一个普通的页面
69 | Router.open("router://open/none")
70 |
71 | case 2: // 打开一个需要登录的页面
72 | Router.open("router://open/needlogin")
73 |
74 | case 3: // 打开一个单一特性的页面
75 | /*
76 | LiveViewController 和 FastViewController 在业务场景中为单一特性 (最多只能有一个打开, 不能同时打开 简称单一特性)
77 | 这里模拟 LiveViewController 打开后 因某种原因要打开 FastViewController
78 | 演示的逻辑为 关闭 LiveViewController 后再打开 FastViewController
79 | */
80 | Router.open("router://open/live?id=1")
81 |
82 | DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
83 | Router.open("router://open/fast")
84 | }
85 |
86 | case 4:
87 | /*
88 | LiveViewController 在业务场景中为单一特性 (最多只能有一个打开, 不能同时打开 简称单一特性)
89 | 这里模拟 LiveViewController 打开后 因某种原因要打开另一个 LiveViewController
90 | (比如点击某个推送通知 触发了打开一个新的 LiveViewController)
91 | 演示的逻辑为 关闭 LiveViewController 后再打开新的 LiveViewController
92 | */
93 | Router.open("router://open/live?id=1")
94 |
95 | DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
96 | Router.open("router://open/live?id=1")
97 | }
98 |
99 | default:
100 | break
101 | }
102 | }
103 | }
104 |
105 |
--------------------------------------------------------------------------------
/Demo/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '10.0'
2 | inhibit_all_warnings!
3 |
4 | target 'Demo' do
5 | use_frameworks!
6 |
7 | pod 'Apis', :path => "../"
8 | pod 'SnapKit' , '~>5.0.0'
9 |
10 | end
11 |
--------------------------------------------------------------------------------
/Demo/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Apis (1.2.2):
3 | - Apis/Privacy (= 1.2.2)
4 | - Apis/Privacy (1.2.2)
5 | - SnapKit (5.0.1)
6 |
7 | DEPENDENCIES:
8 | - Apis (from `../`)
9 | - SnapKit (~> 5.0.0)
10 |
11 | SPEC REPOS:
12 | trunk:
13 | - SnapKit
14 |
15 | EXTERNAL SOURCES:
16 | Apis:
17 | :path: "../"
18 |
19 | SPEC CHECKSUMS:
20 | Apis: e618055c841dbabc0b444f6bb9575831139758bc
21 | SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
22 |
23 | PODFILE CHECKSUM: 199c77b4710d6bba7448d0daa0a0ecd06f10ef6c
24 |
25 | COCOAPODS: 1.15.2
26 |
--------------------------------------------------------------------------------
/Demo/Pods/Local Podspecs/Apis.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Apis",
3 | "version": "1.2.2",
4 | "summary": "基于URLNavigator抽象的URL路由组件 灵感来自Moya 配置化 插件化.",
5 | "homepage": "https://github.com/lixiang1994/Apis",
6 | "license": {
7 | "type": "MIT",
8 | "file": "LICENSE"
9 | },
10 | "authors": {
11 | "LEE": "18611401994@163.com"
12 | },
13 | "platforms": {
14 | "ios": "9.0"
15 | },
16 | "source": {
17 | "git": "https://github.com/lixiang1994/Apis.git",
18 | "tag": "1.2.2"
19 | },
20 | "source_files": "Sources/**/*.swift",
21 | "requires_arc": true,
22 | "frameworks": [
23 | "UIKit",
24 | "Foundation"
25 | ],
26 | "swift_versions": "5.0",
27 | "subspecs": [
28 | {
29 | "name": "Privacy",
30 | "resource_bundles": {
31 | "Apis": "Sources/PrivacyInfo.xcprivacy"
32 | }
33 | }
34 | ],
35 | "swift_version": "5.0"
36 | }
37 |
--------------------------------------------------------------------------------
/Demo/Pods/Local Podspecs/Router.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Router",
3 | "version": "2.0.0",
4 | "summary": "基于URLNavigator抽象的路由组件 支持任意类型配置 插件机制",
5 | "homepage": "https://github.com/lixiang1994/Router",
6 | "license": {
7 | "type": "MIT",
8 | "file": "LICENSE"
9 | },
10 | "authors": {
11 | "LEE": "18611401994@163.com"
12 | },
13 | "platforms": {
14 | "ios": "9.0"
15 | },
16 | "source": {
17 | "git": "https://github.com/lixiang1994/Router.git",
18 | "tag": "2.0.0"
19 | },
20 | "source_files": "Sources/**/*.swift",
21 | "requires_arc": true,
22 | "frameworks": [
23 | "UIKit",
24 | "Foundation"
25 | ],
26 | "swift_versions": "5.0",
27 | "swift_version": "5.0"
28 | }
29 |
--------------------------------------------------------------------------------
/Demo/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Apis (1.2.2):
3 | - Apis/Privacy (= 1.2.2)
4 | - Apis/Privacy (1.2.2)
5 | - SnapKit (5.0.1)
6 |
7 | DEPENDENCIES:
8 | - Apis (from `../`)
9 | - SnapKit (~> 5.0.0)
10 |
11 | SPEC REPOS:
12 | trunk:
13 | - SnapKit
14 |
15 | EXTERNAL SOURCES:
16 | Apis:
17 | :path: "../"
18 |
19 | SPEC CHECKSUMS:
20 | Apis: e618055c841dbabc0b444f6bb9575831139758bc
21 | SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
22 |
23 | PODFILE CHECKSUM: 199c77b4710d6bba7448d0daa0a0ecd06f10ef6c
24 |
25 | COCOAPODS: 1.15.2
26 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | SnapKit is a DSL to make Auto Layout easy on both iOS and OS X.
4 |
5 | [](https://travis-ci.org/SnapKit/SnapKit)
6 | [](https://github.com/SnapKit/SnapKit)
7 | [](https://cocoapods.org/pods/SnapKit)
8 | [](https://github.com/Carthage/Carthage)
9 |
10 | #### ⚠️ **To use with Swift 4.x please ensure you are using >= 4.0.0** ⚠️
11 | #### ⚠️ **To use with Swift 5.x please ensure you are using >= 5.0.0** ⚠️
12 |
13 | ## Contents
14 |
15 | - [Requirements](#requirements)
16 | - [Migration Guides](#migration-guides)
17 | - [Communication](#communication)
18 | - [Installation](#installation)
19 | - [Usage](#usage)
20 | - [Credits](#credits)
21 | - [License](#license)
22 |
23 | ## Requirements
24 |
25 | - iOS 10.0+ / Mac OS X 10.12+ / tvOS 10.0+
26 | - Xcode 10.0+
27 | - Swift 4.0+
28 |
29 | ## Communication
30 |
31 | - If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit). (Tag 'snapkit')
32 | - If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit).
33 | - If you **found a bug**, open an issue.
34 | - If you **have a feature request**, open an issue.
35 | - If you **want to contribute**, submit a pull request.
36 |
37 |
38 | ## Installation
39 |
40 | ### CocoaPods
41 |
42 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
43 |
44 | ```bash
45 | $ gem install cocoapods
46 | ```
47 |
48 | > CocoaPods 1.1.0+ is required to build SnapKit 4.0.0+.
49 |
50 | To integrate SnapKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
51 |
52 | ```ruby
53 | source 'https://github.com/CocoaPods/Specs.git'
54 | platform :ios, '10.0'
55 | use_frameworks!
56 |
57 | target '' do
58 | pod 'SnapKit', '~> 5.0.0'
59 | end
60 | ```
61 |
62 | Then, run the following command:
63 |
64 | ```bash
65 | $ pod install
66 | ```
67 |
68 | ### Carthage
69 |
70 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
71 |
72 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
73 |
74 | ```bash
75 | $ brew update
76 | $ brew install carthage
77 | ```
78 |
79 | To integrate SnapKit into your Xcode project using Carthage, specify it in your `Cartfile`:
80 |
81 | ```ogdl
82 | github "SnapKit/SnapKit" ~> 5.0.0
83 | ```
84 |
85 | Run `carthage update` to build the framework and drag the built `SnapKit.framework` into your Xcode project.
86 |
87 | ### Manually
88 |
89 | If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually.
90 |
91 | ---
92 |
93 | ## Usage
94 |
95 | ### Quick Start
96 |
97 | ```swift
98 | import SnapKit
99 |
100 | class MyViewController: UIViewController {
101 |
102 | lazy var box = UIView()
103 |
104 | override func viewDidLoad() {
105 | super.viewDidLoad()
106 |
107 | self.view.addSubview(box)
108 | box.snp.makeConstraints { (make) -> Void in
109 | make.width.height.equalTo(50)
110 | make.center.equalTo(self.view)
111 | }
112 | }
113 |
114 | }
115 | ```
116 |
117 | ### Playground
118 | You can try SnapKit in Playground.
119 |
120 | **Note:**
121 |
122 | > To try SnapKit in playground, open `SnapKit.xcworkspace` and build SnapKit.framework for any simulator first.
123 |
124 | ### Resources
125 |
126 | - [Documentation](http://snapkit.io/docs/)
127 | - [F.A.Q.](http://snapkit.io/faq/)
128 |
129 | ## Credits
130 |
131 | - Robert Payne ([@robertjpayne](https://twitter.com/robertjpayne))
132 | - Many other contributors
133 |
134 | ## License
135 |
136 | SnapKit is released under the MIT license. See LICENSE for details.
137 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintConfig.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection
27 | #else
28 | import AppKit
29 | public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection
30 | #endif
31 |
32 |
33 | public struct ConstraintConfig {
34 |
35 | public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintDSL.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintDSL {
32 |
33 | var target: AnyObject? { get }
34 |
35 | func setLabel(_ value: String?)
36 | func label() -> String?
37 |
38 | }
39 | extension ConstraintDSL {
40 |
41 | public func setLabel(_ value: String?) {
42 | objc_setAssociatedObject(self.target as Any, &labelKey, value, .OBJC_ASSOCIATION_COPY_NONATOMIC)
43 | }
44 | public func label() -> String? {
45 | return objc_getAssociatedObject(self.target as Any, &labelKey) as? String
46 | }
47 |
48 | }
49 | private var labelKey: UInt8 = 0
50 |
51 |
52 | public protocol ConstraintBasicAttributesDSL : ConstraintDSL {
53 | }
54 | extension ConstraintBasicAttributesDSL {
55 |
56 | // MARK: Basics
57 |
58 | public var left: ConstraintItem {
59 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left)
60 | }
61 |
62 | public var top: ConstraintItem {
63 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
64 | }
65 |
66 | public var right: ConstraintItem {
67 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right)
68 | }
69 |
70 | public var bottom: ConstraintItem {
71 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
72 | }
73 |
74 | public var leading: ConstraintItem {
75 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading)
76 | }
77 |
78 | public var trailing: ConstraintItem {
79 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing)
80 | }
81 |
82 | public var width: ConstraintItem {
83 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width)
84 | }
85 |
86 | public var height: ConstraintItem {
87 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
88 | }
89 |
90 | public var centerX: ConstraintItem {
91 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX)
92 | }
93 |
94 | public var centerY: ConstraintItem {
95 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY)
96 | }
97 |
98 | public var edges: ConstraintItem {
99 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges)
100 | }
101 |
102 | public var directionalEdges: ConstraintItem {
103 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalEdges)
104 | }
105 |
106 | public var size: ConstraintItem {
107 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size)
108 | }
109 |
110 | public var center: ConstraintItem {
111 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center)
112 | }
113 |
114 | }
115 |
116 | public protocol ConstraintAttributesDSL : ConstraintBasicAttributesDSL {
117 | }
118 | extension ConstraintAttributesDSL {
119 |
120 | // MARK: Baselines
121 |
122 | @available(*, deprecated, message:"Use .lastBaseline instead")
123 | public var baseline: ConstraintItem {
124 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
125 | }
126 |
127 | @available(iOS 8.0, OSX 10.11, *)
128 | public var lastBaseline: ConstraintItem {
129 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
130 | }
131 |
132 | @available(iOS 8.0, OSX 10.11, *)
133 | public var firstBaseline: ConstraintItem {
134 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline)
135 | }
136 |
137 | // MARK: Margins
138 |
139 | @available(iOS 8.0, *)
140 | public var leftMargin: ConstraintItem {
141 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin)
142 | }
143 |
144 | @available(iOS 8.0, *)
145 | public var topMargin: ConstraintItem {
146 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin)
147 | }
148 |
149 | @available(iOS 8.0, *)
150 | public var rightMargin: ConstraintItem {
151 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin)
152 | }
153 |
154 | @available(iOS 8.0, *)
155 | public var bottomMargin: ConstraintItem {
156 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin)
157 | }
158 |
159 | @available(iOS 8.0, *)
160 | public var leadingMargin: ConstraintItem {
161 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin)
162 | }
163 |
164 | @available(iOS 8.0, *)
165 | public var trailingMargin: ConstraintItem {
166 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin)
167 | }
168 |
169 | @available(iOS 8.0, *)
170 | public var centerXWithinMargins: ConstraintItem {
171 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins)
172 | }
173 |
174 | @available(iOS 8.0, *)
175 | public var centerYWithinMargins: ConstraintItem {
176 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins)
177 | }
178 |
179 | @available(iOS 8.0, *)
180 | public var margins: ConstraintItem {
181 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins)
182 | }
183 |
184 | @available(iOS 8.0, *)
185 | public var directionalMargins: ConstraintItem {
186 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalMargins)
187 | }
188 |
189 | @available(iOS 8.0, *)
190 | public var centerWithinMargins: ConstraintItem {
191 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins)
192 | }
193 |
194 | }
195 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintDescription.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintDescription {
32 |
33 | internal let item: LayoutConstraintItem
34 | internal var attributes: ConstraintAttributes
35 | internal var relation: ConstraintRelation? = nil
36 | internal var sourceLocation: (String, UInt)? = nil
37 | internal var label: String? = nil
38 | internal var related: ConstraintItem? = nil
39 | internal var multiplier: ConstraintMultiplierTarget = 1.0
40 | internal var constant: ConstraintConstantTarget = 0.0
41 | internal var priority: ConstraintPriorityTarget = 1000.0
42 | internal lazy var constraint: Constraint? = {
43 | guard let relation = self.relation,
44 | let related = self.related,
45 | let sourceLocation = self.sourceLocation else {
46 | return nil
47 | }
48 | let from = ConstraintItem(target: self.item, attributes: self.attributes)
49 |
50 | return Constraint(
51 | from: from,
52 | to: related,
53 | relation: relation,
54 | sourceLocation: sourceLocation,
55 | label: self.label,
56 | multiplier: self.multiplier,
57 | constant: self.constant,
58 | priority: self.priority
59 | )
60 | }()
61 |
62 | // MARK: Initialization
63 |
64 | internal init(item: LayoutConstraintItem, attributes: ConstraintAttributes) {
65 | self.item = item
66 | self.attributes = attributes
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintDirectionalInsetTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 | #if os(iOS) || os(tvOS)
31 | public protocol ConstraintDirectionalInsetTarget: ConstraintConstantTarget {
32 | }
33 |
34 | @available(iOS 11.0, tvOS 11.0, *)
35 | extension ConstraintDirectionalInsets: ConstraintDirectionalInsetTarget {
36 | }
37 |
38 | extension ConstraintDirectionalInsetTarget {
39 |
40 | @available(iOS 11.0, tvOS 11.0, *)
41 | internal var constraintDirectionalInsetTargetValue: ConstraintDirectionalInsets {
42 | if let amount = self as? ConstraintDirectionalInsets {
43 | return amount
44 | } else {
45 | return ConstraintDirectionalInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
46 | }
47 | }
48 | }
49 | #endif
50 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintDirectionalInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | #if os(iOS) || os(tvOS)
32 | @available(iOS 11.0, tvOS 11.0, *)
33 | public typealias ConstraintDirectionalInsets = NSDirectionalEdgeInsets
34 | #endif
35 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintInsetTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintInsetTarget: ConstraintConstantTarget {
32 | }
33 |
34 | extension Int: ConstraintInsetTarget {
35 | }
36 |
37 | extension UInt: ConstraintInsetTarget {
38 | }
39 |
40 | extension Float: ConstraintInsetTarget {
41 | }
42 |
43 | extension Double: ConstraintInsetTarget {
44 | }
45 |
46 | extension CGFloat: ConstraintInsetTarget {
47 | }
48 |
49 | extension ConstraintInsets: ConstraintInsetTarget {
50 | }
51 |
52 | extension ConstraintInsetTarget {
53 |
54 | internal var constraintInsetTargetValue: ConstraintInsets {
55 | if let amount = self as? ConstraintInsets {
56 | return amount
57 | } else if let amount = self as? Float {
58 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
59 | } else if let amount = self as? Double {
60 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
61 | } else if let amount = self as? CGFloat {
62 | return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount)
63 | } else if let amount = self as? Int {
64 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
65 | } else if let amount = self as? UInt {
66 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
67 | } else {
68 | return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0)
69 | }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | #if os(iOS) || os(tvOS)
32 | public typealias ConstraintInsets = UIEdgeInsets
33 | #else
34 | public typealias ConstraintInsets = NSEdgeInsets
35 | #endif
36 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public final class ConstraintItem {
32 |
33 | internal weak var target: AnyObject?
34 | internal let attributes: ConstraintAttributes
35 |
36 | internal init(target: AnyObject?, attributes: ConstraintAttributes) {
37 | self.target = target
38 | self.attributes = attributes
39 | }
40 |
41 | internal var layoutConstraintItem: LayoutConstraintItem? {
42 | return self.target as? LayoutConstraintItem
43 | }
44 |
45 | }
46 |
47 | public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool {
48 | // pointer equality
49 | guard lhs !== rhs else {
50 | return true
51 | }
52 |
53 | // must both have valid targets and identical attributes
54 | guard let target1 = lhs.target,
55 | let target2 = rhs.target,
56 | target1 === target2 && lhs.attributes == rhs.attributes else {
57 | return false
58 | }
59 |
60 | return true
61 | }
62 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintLayoutGuide+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #endif
27 |
28 |
29 | @available(iOS 9.0, OSX 10.11, *)
30 | public extension ConstraintLayoutGuide {
31 |
32 | var snp: ConstraintLayoutGuideDSL {
33 | return ConstraintLayoutGuideDSL(guide: self)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintLayoutGuide.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | #if os(iOS) || os(tvOS)
32 | @available(iOS 9.0, *)
33 | public typealias ConstraintLayoutGuide = UILayoutGuide
34 | #else
35 | @available(OSX 10.11, *)
36 | public typealias ConstraintLayoutGuide = NSLayoutGuide
37 | #endif
38 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintLayoutGuideDSL.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | @available(iOS 9.0, OSX 10.11, *)
32 | public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL {
33 |
34 | @discardableResult
35 | public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
36 | return ConstraintMaker.prepareConstraints(item: self.guide, closure: closure)
37 | }
38 |
39 | public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
40 | ConstraintMaker.makeConstraints(item: self.guide, closure: closure)
41 | }
42 |
43 | public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
44 | ConstraintMaker.remakeConstraints(item: self.guide, closure: closure)
45 | }
46 |
47 | public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
48 | ConstraintMaker.updateConstraints(item: self.guide, closure: closure)
49 | }
50 |
51 | public func removeConstraints() {
52 | ConstraintMaker.removeConstraints(item: self.guide)
53 | }
54 |
55 | public var target: AnyObject? {
56 | return self.guide
57 | }
58 |
59 | internal let guide: ConstraintLayoutGuide
60 |
61 | internal init(guide: ConstraintLayoutGuide) {
62 | self.guide = guide
63 |
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintLayoutSupport.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | #if os(iOS) || os(tvOS)
32 | @available(iOS 8.0, *)
33 | public typealias ConstraintLayoutSupport = UILayoutSupport
34 | #else
35 | public class ConstraintLayoutSupport {}
36 | #endif
37 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintLayoutSupportDSL.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | @available(iOS 8.0, *)
32 | public struct ConstraintLayoutSupportDSL: ConstraintDSL {
33 |
34 | public var target: AnyObject? {
35 | return self.support
36 | }
37 |
38 | internal let support: ConstraintLayoutSupport
39 |
40 | internal init(support: ConstraintLayoutSupport) {
41 | self.support = support
42 |
43 | }
44 |
45 | public var top: ConstraintItem {
46 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
47 | }
48 |
49 | public var bottom: ConstraintItem {
50 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
51 | }
52 |
53 | public var height: ConstraintItem {
54 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMakerEditable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintMakerEditable: ConstraintMakerPriortizable {
32 |
33 | @discardableResult
34 | public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
35 | self.description.multiplier = amount
36 | return self
37 | }
38 |
39 | @discardableResult
40 | public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
41 | return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue)
42 | }
43 |
44 | @discardableResult
45 | public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable {
46 | self.description.constant = amount.constraintOffsetTargetValue
47 | return self
48 | }
49 |
50 | @discardableResult
51 | public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable {
52 | self.description.constant = amount.constraintInsetTargetValue
53 | return self
54 | }
55 |
56 | #if os(iOS) || os(tvOS)
57 | @discardableResult
58 | @available(iOS 11.0, tvOS 11.0, *)
59 | public func inset(_ amount: ConstraintDirectionalInsetTarget) -> ConstraintMakerEditable {
60 | self.description.constant = amount.constraintDirectionalInsetTargetValue
61 | return self
62 | }
63 | #endif
64 | }
65 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMakerExtendable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintMakerExtendable: ConstraintMakerRelatable {
32 |
33 | public var left: ConstraintMakerExtendable {
34 | self.description.attributes += .left
35 | return self
36 | }
37 |
38 | public var top: ConstraintMakerExtendable {
39 | self.description.attributes += .top
40 | return self
41 | }
42 |
43 | public var bottom: ConstraintMakerExtendable {
44 | self.description.attributes += .bottom
45 | return self
46 | }
47 |
48 | public var right: ConstraintMakerExtendable {
49 | self.description.attributes += .right
50 | return self
51 | }
52 |
53 | public var leading: ConstraintMakerExtendable {
54 | self.description.attributes += .leading
55 | return self
56 | }
57 |
58 | public var trailing: ConstraintMakerExtendable {
59 | self.description.attributes += .trailing
60 | return self
61 | }
62 |
63 | public var width: ConstraintMakerExtendable {
64 | self.description.attributes += .width
65 | return self
66 | }
67 |
68 | public var height: ConstraintMakerExtendable {
69 | self.description.attributes += .height
70 | return self
71 | }
72 |
73 | public var centerX: ConstraintMakerExtendable {
74 | self.description.attributes += .centerX
75 | return self
76 | }
77 |
78 | public var centerY: ConstraintMakerExtendable {
79 | self.description.attributes += .centerY
80 | return self
81 | }
82 |
83 | @available(*, deprecated, message:"Use lastBaseline instead")
84 | public var baseline: ConstraintMakerExtendable {
85 | self.description.attributes += .lastBaseline
86 | return self
87 | }
88 |
89 | public var lastBaseline: ConstraintMakerExtendable {
90 | self.description.attributes += .lastBaseline
91 | return self
92 | }
93 |
94 | @available(iOS 8.0, OSX 10.11, *)
95 | public var firstBaseline: ConstraintMakerExtendable {
96 | self.description.attributes += .firstBaseline
97 | return self
98 | }
99 |
100 | @available(iOS 8.0, *)
101 | public var leftMargin: ConstraintMakerExtendable {
102 | self.description.attributes += .leftMargin
103 | return self
104 | }
105 |
106 | @available(iOS 8.0, *)
107 | public var rightMargin: ConstraintMakerExtendable {
108 | self.description.attributes += .rightMargin
109 | return self
110 | }
111 |
112 | @available(iOS 8.0, *)
113 | public var topMargin: ConstraintMakerExtendable {
114 | self.description.attributes += .topMargin
115 | return self
116 | }
117 |
118 | @available(iOS 8.0, *)
119 | public var bottomMargin: ConstraintMakerExtendable {
120 | self.description.attributes += .bottomMargin
121 | return self
122 | }
123 |
124 | @available(iOS 8.0, *)
125 | public var leadingMargin: ConstraintMakerExtendable {
126 | self.description.attributes += .leadingMargin
127 | return self
128 | }
129 |
130 | @available(iOS 8.0, *)
131 | public var trailingMargin: ConstraintMakerExtendable {
132 | self.description.attributes += .trailingMargin
133 | return self
134 | }
135 |
136 | @available(iOS 8.0, *)
137 | public var centerXWithinMargins: ConstraintMakerExtendable {
138 | self.description.attributes += .centerXWithinMargins
139 | return self
140 | }
141 |
142 | @available(iOS 8.0, *)
143 | public var centerYWithinMargins: ConstraintMakerExtendable {
144 | self.description.attributes += .centerYWithinMargins
145 | return self
146 | }
147 |
148 | public var edges: ConstraintMakerExtendable {
149 | self.description.attributes += .edges
150 | return self
151 | }
152 | public var directionalEdges: ConstraintMakerExtendable {
153 | self.description.attributes += .directionalEdges
154 | return self
155 | }
156 | public var size: ConstraintMakerExtendable {
157 | self.description.attributes += .size
158 | return self
159 | }
160 |
161 | @available(iOS 8.0, *)
162 | public var margins: ConstraintMakerExtendable {
163 | self.description.attributes += .margins
164 | return self
165 | }
166 |
167 | @available(iOS 8.0, *)
168 | public var directionalMargins: ConstraintMakerExtendable {
169 | self.description.attributes += .directionalMargins
170 | return self
171 | }
172 |
173 | @available(iOS 8.0, *)
174 | public var centerWithinMargins: ConstraintMakerExtendable {
175 | self.description.attributes += .centerWithinMargins
176 | return self
177 | }
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMakerFinalizable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintMakerFinalizable {
32 |
33 | internal let description: ConstraintDescription
34 |
35 | internal init(_ description: ConstraintDescription) {
36 | self.description = description
37 | }
38 |
39 | @discardableResult
40 | public func labeled(_ label: String) -> ConstraintMakerFinalizable {
41 | self.description.label = label
42 | return self
43 | }
44 |
45 | public var constraint: Constraint {
46 | return self.description.constraint!
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMakerPriortizable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintMakerPriortizable: ConstraintMakerFinalizable {
32 |
33 | @discardableResult
34 | public func priority(_ amount: ConstraintPriority) -> ConstraintMakerFinalizable {
35 | self.description.priority = amount.value
36 | return self
37 | }
38 |
39 | @discardableResult
40 | public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable {
41 | self.description.priority = amount
42 | return self
43 | }
44 |
45 | @available(*, deprecated, message:"Use priority(.required) instead.")
46 | @discardableResult
47 | public func priorityRequired() -> ConstraintMakerFinalizable {
48 | return self.priority(.required)
49 | }
50 |
51 | @available(*, deprecated, message:"Use priority(.high) instead.")
52 | @discardableResult
53 | public func priorityHigh() -> ConstraintMakerFinalizable {
54 | return self.priority(.high)
55 | }
56 |
57 | @available(*, deprecated, message:"Use priority(.medium) instead.")
58 | @discardableResult
59 | public func priorityMedium() -> ConstraintMakerFinalizable {
60 | return self.priority(.medium)
61 | }
62 |
63 | @available(*, deprecated, message:"Use priority(.low) instead.")
64 | @discardableResult
65 | public func priorityLow() -> ConstraintMakerFinalizable {
66 | return self.priority(.low)
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMakerRelatable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class ConstraintMakerRelatable {
32 |
33 | internal let description: ConstraintDescription
34 |
35 | internal init(_ description: ConstraintDescription) {
36 | self.description = description
37 | }
38 |
39 | internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable {
40 | let related: ConstraintItem
41 | let constant: ConstraintConstantTarget
42 |
43 | if let other = other as? ConstraintItem {
44 | guard other.attributes == ConstraintAttributes.none ||
45 | other.attributes.layoutAttributes.count <= 1 ||
46 | other.attributes.layoutAttributes == self.description.attributes.layoutAttributes ||
47 | other.attributes == .edges && self.description.attributes == .margins ||
48 | other.attributes == .margins && self.description.attributes == .edges ||
49 | other.attributes == .directionalEdges && self.description.attributes == .directionalMargins ||
50 | other.attributes == .directionalMargins && self.description.attributes == .directionalEdges else {
51 | fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))");
52 | }
53 |
54 | related = other
55 | constant = 0.0
56 | } else if let other = other as? ConstraintView {
57 | related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
58 | constant = 0.0
59 | } else if let other = other as? ConstraintConstantTarget {
60 | related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none)
61 | constant = other
62 | } else if #available(iOS 9.0, OSX 10.11, *), let other = other as? ConstraintLayoutGuide {
63 | related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
64 | constant = 0.0
65 | } else {
66 | fatalError("Invalid constraint. (\(file), \(line))")
67 | }
68 |
69 | let editable = ConstraintMakerEditable(self.description)
70 | editable.description.sourceLocation = (file, line)
71 | editable.description.relation = relation
72 | editable.description.related = related
73 | editable.description.constant = constant
74 | return editable
75 | }
76 |
77 | @discardableResult
78 | public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
79 | return self.relatedTo(other, relation: .equal, file: file, line: line)
80 | }
81 |
82 | @discardableResult
83 | public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
84 | guard let other = self.description.item.superview else {
85 | fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
86 | }
87 | return self.relatedTo(other, relation: .equal, file: file, line: line)
88 | }
89 |
90 | @discardableResult
91 | public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
92 | return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
93 | }
94 |
95 | @discardableResult
96 | public func lessThanOrEqualToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
97 | guard let other = self.description.item.superview else {
98 | fatalError("Expected superview but found nil when attempting make constraint `lessThanOrEqualToSuperview`.")
99 | }
100 | return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
101 | }
102 |
103 | @discardableResult
104 | public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
105 | return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
106 | }
107 |
108 | @discardableResult
109 | public func greaterThanOrEqualToSuperview(_ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
110 | guard let other = self.description.item.superview else {
111 | fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.")
112 | }
113 | return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintMultiplierTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintMultiplierTarget {
32 |
33 | var constraintMultiplierTargetValue: CGFloat { get }
34 |
35 | }
36 |
37 | extension Int: ConstraintMultiplierTarget {
38 |
39 | public var constraintMultiplierTargetValue: CGFloat {
40 | return CGFloat(self)
41 | }
42 |
43 | }
44 |
45 | extension UInt: ConstraintMultiplierTarget {
46 |
47 | public var constraintMultiplierTargetValue: CGFloat {
48 | return CGFloat(self)
49 | }
50 |
51 | }
52 |
53 | extension Float: ConstraintMultiplierTarget {
54 |
55 | public var constraintMultiplierTargetValue: CGFloat {
56 | return CGFloat(self)
57 | }
58 |
59 | }
60 |
61 | extension Double: ConstraintMultiplierTarget {
62 |
63 | public var constraintMultiplierTargetValue: CGFloat {
64 | return CGFloat(self)
65 | }
66 |
67 | }
68 |
69 | extension CGFloat: ConstraintMultiplierTarget {
70 |
71 | public var constraintMultiplierTargetValue: CGFloat {
72 | return self
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintOffsetTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintOffsetTarget: ConstraintConstantTarget {
32 | }
33 |
34 | extension Int: ConstraintOffsetTarget {
35 | }
36 |
37 | extension UInt: ConstraintOffsetTarget {
38 | }
39 |
40 | extension Float: ConstraintOffsetTarget {
41 | }
42 |
43 | extension Double: ConstraintOffsetTarget {
44 | }
45 |
46 | extension CGFloat: ConstraintOffsetTarget {
47 | }
48 |
49 | extension ConstraintOffsetTarget {
50 |
51 | internal var constraintOffsetTargetValue: CGFloat {
52 | let offset: CGFloat
53 | if let amount = self as? Float {
54 | offset = CGFloat(amount)
55 | } else if let amount = self as? Double {
56 | offset = CGFloat(amount)
57 | } else if let amount = self as? CGFloat {
58 | offset = CGFloat(amount)
59 | } else if let amount = self as? Int {
60 | offset = CGFloat(amount)
61 | } else if let amount = self as? UInt {
62 | offset = CGFloat(amount)
63 | } else {
64 | offset = 0.0
65 | }
66 | return offset
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintPriority.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 | public struct ConstraintPriority : ExpressibleByFloatLiteral, Equatable, Strideable {
31 | public typealias FloatLiteralType = Float
32 |
33 | public let value: Float
34 |
35 | public init(floatLiteral value: Float) {
36 | self.value = value
37 | }
38 |
39 | public init(_ value: Float) {
40 | self.value = value
41 | }
42 |
43 | public static var required: ConstraintPriority {
44 | return 1000.0
45 | }
46 |
47 | public static var high: ConstraintPriority {
48 | return 750.0
49 | }
50 |
51 | public static var medium: ConstraintPriority {
52 | #if os(OSX)
53 | return 501.0
54 | #else
55 | return 500.0
56 | #endif
57 |
58 | }
59 |
60 | public static var low: ConstraintPriority {
61 | return 250.0
62 | }
63 |
64 | public static func ==(lhs: ConstraintPriority, rhs: ConstraintPriority) -> Bool {
65 | return lhs.value == rhs.value
66 | }
67 |
68 | // MARK: Strideable
69 |
70 | public func advanced(by n: FloatLiteralType) -> ConstraintPriority {
71 | return ConstraintPriority(floatLiteral: value + n)
72 | }
73 |
74 | public func distance(to other: ConstraintPriority) -> FloatLiteralType {
75 | return other.value - value
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintPriorityTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintPriorityTarget {
32 |
33 | var constraintPriorityTargetValue: Float { get }
34 |
35 | }
36 |
37 | extension Int: ConstraintPriorityTarget {
38 |
39 | public var constraintPriorityTargetValue: Float {
40 | return Float(self)
41 | }
42 |
43 | }
44 |
45 | extension UInt: ConstraintPriorityTarget {
46 |
47 | public var constraintPriorityTargetValue: Float {
48 | return Float(self)
49 | }
50 |
51 | }
52 |
53 | extension Float: ConstraintPriorityTarget {
54 |
55 | public var constraintPriorityTargetValue: Float {
56 | return self
57 | }
58 |
59 | }
60 |
61 | extension Double: ConstraintPriorityTarget {
62 |
63 | public var constraintPriorityTargetValue: Float {
64 | return Float(self)
65 | }
66 |
67 | }
68 |
69 | extension CGFloat: ConstraintPriorityTarget {
70 |
71 | public var constraintPriorityTargetValue: Float {
72 | return Float(self)
73 | }
74 |
75 | }
76 |
77 | #if os(iOS) || os(tvOS)
78 | extension UILayoutPriority: ConstraintPriorityTarget {
79 |
80 | public var constraintPriorityTargetValue: Float {
81 | return self.rawValue
82 | }
83 |
84 | }
85 | #endif
86 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintRelatableTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol ConstraintRelatableTarget {
32 | }
33 |
34 | extension Int: ConstraintRelatableTarget {
35 | }
36 |
37 | extension UInt: ConstraintRelatableTarget {
38 | }
39 |
40 | extension Float: ConstraintRelatableTarget {
41 | }
42 |
43 | extension Double: ConstraintRelatableTarget {
44 | }
45 |
46 | extension CGFloat: ConstraintRelatableTarget {
47 | }
48 |
49 | extension CGSize: ConstraintRelatableTarget {
50 | }
51 |
52 | extension CGPoint: ConstraintRelatableTarget {
53 | }
54 |
55 | extension ConstraintInsets: ConstraintRelatableTarget {
56 | }
57 |
58 | #if os(iOS) || os(tvOS)
59 | @available(iOS 11.0, tvOS 11.0, *)
60 | extension ConstraintDirectionalInsets: ConstraintRelatableTarget {
61 | }
62 | #endif
63 |
64 | extension ConstraintItem: ConstraintRelatableTarget {
65 | }
66 |
67 | extension ConstraintView: ConstraintRelatableTarget {
68 | }
69 |
70 | @available(iOS 9.0, OSX 10.11, *)
71 | extension ConstraintLayoutGuide: ConstraintRelatableTarget {
72 | }
73 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintRelation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | internal enum ConstraintRelation : Int {
32 | case equal = 1
33 | case lessThanOrEqual
34 | case greaterThanOrEqual
35 |
36 | internal var layoutRelation: LayoutRelation {
37 | get {
38 | switch(self) {
39 | case .equal:
40 | return .equal
41 | case .lessThanOrEqual:
42 | return .lessThanOrEqual
43 | case .greaterThanOrEqual:
44 | return .greaterThanOrEqual
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintView+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public extension ConstraintView {
32 |
33 | @available(*, deprecated, message:"Use newer snp.* syntax.")
34 | var snp_left: ConstraintItem { return self.snp.left }
35 |
36 | @available(*, deprecated, message:"Use newer snp.* syntax.")
37 | var snp_top: ConstraintItem { return self.snp.top }
38 |
39 | @available(*, deprecated, message:"Use newer snp.* syntax.")
40 | var snp_right: ConstraintItem { return self.snp.right }
41 |
42 | @available(*, deprecated, message:"Use newer snp.* syntax.")
43 | var snp_bottom: ConstraintItem { return self.snp.bottom }
44 |
45 | @available(*, deprecated, message:"Use newer snp.* syntax.")
46 | var snp_leading: ConstraintItem { return self.snp.leading }
47 |
48 | @available(*, deprecated, message:"Use newer snp.* syntax.")
49 | var snp_trailing: ConstraintItem { return self.snp.trailing }
50 |
51 | @available(*, deprecated, message:"Use newer snp.* syntax.")
52 | var snp_width: ConstraintItem { return self.snp.width }
53 |
54 | @available(*, deprecated, message:"Use newer snp.* syntax.")
55 | var snp_height: ConstraintItem { return self.snp.height }
56 |
57 | @available(*, deprecated, message:"Use newer snp.* syntax.")
58 | var snp_centerX: ConstraintItem { return self.snp.centerX }
59 |
60 | @available(*, deprecated, message:"Use newer snp.* syntax.")
61 | var snp_centerY: ConstraintItem { return self.snp.centerY }
62 |
63 | @available(*, deprecated, message:"Use newer snp.* syntax.")
64 | var snp_baseline: ConstraintItem { return self.snp.baseline }
65 |
66 | @available(*, deprecated, message:"Use newer snp.* syntax.")
67 | @available(iOS 8.0, OSX 10.11, *)
68 | var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline }
69 |
70 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
71 | @available(iOS 8.0, OSX 10.11, *)
72 | var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline }
73 |
74 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
75 | @available(iOS 8.0, *)
76 | var snp_leftMargin: ConstraintItem { return self.snp.leftMargin }
77 |
78 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
79 | @available(iOS 8.0, *)
80 | var snp_topMargin: ConstraintItem { return self.snp.topMargin }
81 |
82 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
83 | @available(iOS 8.0, *)
84 | var snp_rightMargin: ConstraintItem { return self.snp.rightMargin }
85 |
86 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
87 | @available(iOS 8.0, *)
88 | var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin }
89 |
90 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
91 | @available(iOS 8.0, *)
92 | var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin }
93 |
94 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
95 | @available(iOS 8.0, *)
96 | var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin }
97 |
98 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
99 | @available(iOS 8.0, *)
100 | var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins }
101 |
102 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
103 | @available(iOS 8.0, *)
104 | var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins }
105 |
106 | @available(*, deprecated, message:"Use newer snp.* syntax.")
107 | var snp_edges: ConstraintItem { return self.snp.edges }
108 |
109 | @available(*, deprecated, message:"Use newer snp.* syntax.")
110 | var snp_size: ConstraintItem { return self.snp.size }
111 |
112 | @available(*, deprecated, message:"Use newer snp.* syntax.")
113 | var snp_center: ConstraintItem { return self.snp.center }
114 |
115 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
116 | @available(iOS 8.0, *)
117 | var snp_margins: ConstraintItem { return self.snp.margins }
118 |
119 | @available(iOS, deprecated, message:"Use newer snp.* syntax.")
120 | @available(iOS 8.0, *)
121 | var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins }
122 |
123 | @available(*, deprecated, message:"Use newer snp.* syntax.")
124 | func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
125 | return self.snp.prepareConstraints(closure)
126 | }
127 |
128 | @available(*, deprecated, message:"Use newer snp.* syntax.")
129 | func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
130 | self.snp.makeConstraints(closure)
131 | }
132 |
133 | @available(*, deprecated, message:"Use newer snp.* syntax.")
134 | func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
135 | self.snp.remakeConstraints(closure)
136 | }
137 |
138 | @available(*, deprecated, message:"Use newer snp.* syntax.")
139 | func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
140 | self.snp.updateConstraints(closure)
141 | }
142 |
143 | @available(*, deprecated, message:"Use newer snp.* syntax.")
144 | func snp_removeConstraints() {
145 | self.snp.removeConstraints()
146 | }
147 |
148 | var snp: ConstraintViewDSL {
149 | return ConstraintViewDSL(view: self)
150 | }
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | #if os(iOS) || os(tvOS)
32 | public typealias ConstraintView = UIView
33 | #else
34 | public typealias ConstraintView = NSView
35 | #endif
36 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/ConstraintViewDSL.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public struct ConstraintViewDSL: ConstraintAttributesDSL {
32 |
33 | @discardableResult
34 | public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
35 | return ConstraintMaker.prepareConstraints(item: self.view, closure: closure)
36 | }
37 |
38 | public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
39 | ConstraintMaker.makeConstraints(item: self.view, closure: closure)
40 | }
41 |
42 | public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
43 | ConstraintMaker.remakeConstraints(item: self.view, closure: closure)
44 | }
45 |
46 | public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
47 | ConstraintMaker.updateConstraints(item: self.view, closure: closure)
48 | }
49 |
50 | public func removeConstraints() {
51 | ConstraintMaker.removeConstraints(item: self.view)
52 | }
53 |
54 | public var contentHuggingHorizontalPriority: Float {
55 | get {
56 | return self.view.contentHuggingPriority(for: .horizontal).rawValue
57 | }
58 | nonmutating set {
59 | self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .horizontal)
60 | }
61 | }
62 |
63 | public var contentHuggingVerticalPriority: Float {
64 | get {
65 | return self.view.contentHuggingPriority(for: .vertical).rawValue
66 | }
67 | nonmutating set {
68 | self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .vertical)
69 | }
70 | }
71 |
72 | public var contentCompressionResistanceHorizontalPriority: Float {
73 | get {
74 | return self.view.contentCompressionResistancePriority(for: .horizontal).rawValue
75 | }
76 | nonmutating set {
77 | self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .horizontal)
78 | }
79 | }
80 |
81 | public var contentCompressionResistanceVerticalPriority: Float {
82 | get {
83 | return self.view.contentCompressionResistancePriority(for: .vertical).rawValue
84 | }
85 | nonmutating set {
86 | self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .vertical)
87 | }
88 | }
89 |
90 | public var target: AnyObject? {
91 | return self.view
92 | }
93 |
94 | internal let view: ConstraintView
95 |
96 | internal init(view: ConstraintView) {
97 | self.view = view
98 |
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/Debugging.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 | public extension LayoutConstraint {
31 |
32 | override var description: String {
33 | var description = "<"
34 |
35 | description += descriptionForObject(self)
36 |
37 | if let firstItem = conditionalOptional(from: self.firstItem) {
38 | description += " \(descriptionForObject(firstItem))"
39 | }
40 |
41 | if self.firstAttribute != .notAnAttribute {
42 | description += ".\(descriptionForAttribute(self.firstAttribute))"
43 | }
44 |
45 | description += " \(descriptionForRelation(self.relation))"
46 |
47 | if let secondItem = self.secondItem {
48 | description += " \(descriptionForObject(secondItem))"
49 | }
50 |
51 | if self.secondAttribute != .notAnAttribute {
52 | description += ".\(descriptionForAttribute(self.secondAttribute))"
53 | }
54 |
55 | if self.multiplier != 1.0 {
56 | description += " * \(self.multiplier)"
57 | }
58 |
59 | if self.secondAttribute == .notAnAttribute {
60 | description += " \(self.constant)"
61 | } else {
62 | if self.constant > 0.0 {
63 | description += " + \(self.constant)"
64 | } else if self.constant < 0.0 {
65 | description += " - \(abs(self.constant))"
66 | }
67 | }
68 |
69 | if self.priority.rawValue != 1000.0 {
70 | description += " ^\(self.priority)"
71 | }
72 |
73 | description += ">"
74 |
75 | return description
76 | }
77 |
78 | }
79 |
80 | private func descriptionForRelation(_ relation: LayoutRelation) -> String {
81 | switch relation {
82 | case .equal: return "=="
83 | case .greaterThanOrEqual: return ">="
84 | case .lessThanOrEqual: return "<="
85 | #if swift(>=5.0)
86 | @unknown default: return "unknown"
87 | #endif
88 | }
89 | }
90 |
91 | private func descriptionForAttribute(_ attribute: LayoutAttribute) -> String {
92 | #if os(iOS) || os(tvOS)
93 | switch attribute {
94 | case .notAnAttribute: return "notAnAttribute"
95 | case .top: return "top"
96 | case .left: return "left"
97 | case .bottom: return "bottom"
98 | case .right: return "right"
99 | case .leading: return "leading"
100 | case .trailing: return "trailing"
101 | case .width: return "width"
102 | case .height: return "height"
103 | case .centerX: return "centerX"
104 | case .centerY: return "centerY"
105 | case .lastBaseline: return "lastBaseline"
106 | case .firstBaseline: return "firstBaseline"
107 | case .topMargin: return "topMargin"
108 | case .leftMargin: return "leftMargin"
109 | case .bottomMargin: return "bottomMargin"
110 | case .rightMargin: return "rightMargin"
111 | case .leadingMargin: return "leadingMargin"
112 | case .trailingMargin: return "trailingMargin"
113 | case .centerXWithinMargins: return "centerXWithinMargins"
114 | case .centerYWithinMargins: return "centerYWithinMargins"
115 | #if swift(>=5.0)
116 | @unknown default: return "unknown"
117 | #endif
118 | }
119 | #else
120 | switch attribute {
121 | case .notAnAttribute: return "notAnAttribute"
122 | case .top: return "top"
123 | case .left: return "left"
124 | case .bottom: return "bottom"
125 | case .right: return "right"
126 | case .leading: return "leading"
127 | case .trailing: return "trailing"
128 | case .width: return "width"
129 | case .height: return "height"
130 | case .centerX: return "centerX"
131 | case .centerY: return "centerY"
132 | case .lastBaseline: return "lastBaseline"
133 | case .firstBaseline: return "firstBaseline"
134 | #if swift(>=5.0)
135 | @unknown default: return "unknown"
136 | #endif
137 | }
138 | #endif
139 | }
140 |
141 | private func conditionalOptional(from object: Optional) -> Optional {
142 | return object
143 | }
144 |
145 | private func conditionalOptional(from object: T) -> Optional {
146 | return Optional.some(object)
147 | }
148 |
149 | private func descriptionForObject(_ object: AnyObject) -> String {
150 | let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object)))
151 | var desc = ""
152 |
153 | desc += type(of: object).description()
154 |
155 | if let object = object as? ConstraintView {
156 | desc += ":\(object.snp.label() ?? pointerDescription)"
157 | } else if let object = object as? LayoutConstraint {
158 | desc += ":\(object.label ?? pointerDescription)"
159 | } else {
160 | desc += ":\(pointerDescription)"
161 | }
162 |
163 | if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 {
164 | desc += "@\((file as NSString).lastPathComponent)#\(line)"
165 | }
166 |
167 | desc += ""
168 | return desc
169 | }
170 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/LayoutConstraint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public class LayoutConstraint : NSLayoutConstraint {
32 |
33 | public var label: String? {
34 | get {
35 | return self.identifier
36 | }
37 | set {
38 | self.identifier = newValue
39 | }
40 | }
41 |
42 | internal weak var constraint: Constraint? = nil
43 |
44 | }
45 |
46 | internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool {
47 | // If firstItem or secondItem on either constraint has a dangling pointer
48 | // this comparison can cause a crash. The solution for this is to ensure
49 | // your layout code hold strong references to things like Views, LayoutGuides
50 | // and LayoutAnchors as SnapKit will not keep strong references to any of these.
51 | guard lhs.firstAttribute == rhs.firstAttribute &&
52 | lhs.secondAttribute == rhs.secondAttribute &&
53 | lhs.relation == rhs.relation &&
54 | lhs.priority == rhs.priority &&
55 | lhs.multiplier == rhs.multiplier &&
56 | lhs.secondItem === rhs.secondItem &&
57 | lhs.firstItem === rhs.firstItem else {
58 | return false
59 | }
60 | return true
61 | }
62 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/LayoutConstraintItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #else
27 | import AppKit
28 | #endif
29 |
30 |
31 | public protocol LayoutConstraintItem: class {
32 | }
33 |
34 | @available(iOS 9.0, OSX 10.11, *)
35 | extension ConstraintLayoutGuide : LayoutConstraintItem {
36 | }
37 |
38 | extension ConstraintView : LayoutConstraintItem {
39 | }
40 |
41 |
42 | extension LayoutConstraintItem {
43 |
44 | internal func prepare() {
45 | if let view = self as? ConstraintView {
46 | view.translatesAutoresizingMaskIntoConstraints = false
47 | }
48 | }
49 |
50 | internal var superview: ConstraintView? {
51 | if let view = self as? ConstraintView {
52 | return view.superview
53 | }
54 |
55 | if #available(iOS 9.0, OSX 10.11, *), let guide = self as? ConstraintLayoutGuide {
56 | return guide.owningView
57 | }
58 |
59 | return nil
60 | }
61 | internal var constraints: [Constraint] {
62 | return self.constraintsSet.allObjects as! [Constraint]
63 | }
64 |
65 | internal func add(constraints: [Constraint]) {
66 | let constraintsSet = self.constraintsSet
67 | for constraint in constraints {
68 | constraintsSet.add(constraint)
69 | }
70 | }
71 |
72 | internal func remove(constraints: [Constraint]) {
73 | let constraintsSet = self.constraintsSet
74 | for constraint in constraints {
75 | constraintsSet.remove(constraint)
76 | }
77 | }
78 |
79 | private var constraintsSet: NSMutableSet {
80 | let constraintsSet: NSMutableSet
81 |
82 | if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSMutableSet {
83 | constraintsSet = existing
84 | } else {
85 | constraintsSet = NSMutableSet()
86 | objc_setAssociatedObject(self, &constraintsKey, constraintsSet, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
87 | }
88 | return constraintsSet
89 |
90 | }
91 |
92 | }
93 | private var constraintsKey: UInt8 = 0
94 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/Typealiases.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | import Foundation
25 |
26 | #if os(iOS) || os(tvOS)
27 | import UIKit
28 | #if swift(>=4.2)
29 | typealias LayoutRelation = NSLayoutConstraint.Relation
30 | typealias LayoutAttribute = NSLayoutConstraint.Attribute
31 | #else
32 | typealias LayoutRelation = NSLayoutRelation
33 | typealias LayoutAttribute = NSLayoutAttribute
34 | #endif
35 | typealias LayoutPriority = UILayoutPriority
36 | #else
37 | import AppKit
38 | typealias LayoutRelation = NSLayoutConstraint.Relation
39 | typealias LayoutAttribute = NSLayoutConstraint.Attribute
40 | typealias LayoutPriority = NSLayoutConstraint.Priority
41 | #endif
42 |
43 |
--------------------------------------------------------------------------------
/Demo/Pods/SnapKit/Source/UILayoutSupport+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnapKit
3 | //
4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in
14 | // all copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | // THE SOFTWARE.
23 |
24 | #if os(iOS) || os(tvOS)
25 | import UIKit
26 | #endif
27 |
28 |
29 | @available(iOS 8.0, *)
30 | public extension ConstraintLayoutSupport {
31 |
32 | var snp: ConstraintLayoutSupportDSL {
33 | return ConstraintLayoutSupportDSL(support: self)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis-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.2.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Apis : NSObject
3 | @end
4 | @implementation PodsDummy_Apis
5 | @end
6 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis-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 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis-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 ApisVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char ApisVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Apis
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
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}/../..
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 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis.modulemap:
--------------------------------------------------------------------------------
1 | framework module Apis {
2 | umbrella header "Apis-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/Apis.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Apis
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "UIKit"
6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
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}/../..
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 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/ResourceBundle-Apis-Apis-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | ${PODS_DEVELOPMENT_LANGUAGE}
7 | CFBundleIdentifier
8 | ${PRODUCT_BUNDLE_IDENTIFIER}
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundleName
12 | ${PRODUCT_NAME}
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.2.2
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Apis/ResourceBundle-Privacy-Apis-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | ${PODS_DEVELOPMENT_LANGUAGE}
7 | CFBundleIdentifier
8 | ${PRODUCT_BUNDLE_IDENTIFIER}
9 | CFBundleInfoDictionaryVersion
10 | 6.0
11 | CFBundleName
12 | ${PRODUCT_NAME}
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.2.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-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 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Apis
5 |
6 | MIT License
7 |
8 | Copyright (c) 2021 LEE
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 |
29 | ## SnapKit
30 |
31 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
32 |
33 | Permission is hereby granted, free of charge, to any person obtaining a copy
34 | of this software and associated documentation files (the "Software"), to deal
35 | in the Software without restriction, including without limitation the rights
36 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37 | copies of the Software, and to permit persons to whom the Software is
38 | furnished to do so, subject to the following conditions:
39 |
40 | The above copyright notice and this permission notice shall be included in
41 | all copies or substantial portions of the Software.
42 |
43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
49 | THE SOFTWARE.
50 |
51 | Generated by CocoaPods - https://cocoapods.org
52 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | MIT License
18 |
19 | Copyright (c) 2021 LEE
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all
29 | copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 | SOFTWARE.
38 |
39 | License
40 | MIT
41 | Title
42 | Apis
43 | Type
44 | PSGroupSpecifier
45 |
46 |
47 | FooterText
48 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
49 |
50 | Permission is hereby granted, free of charge, to any person obtaining a copy
51 | of this software and associated documentation files (the "Software"), to deal
52 | in the Software without restriction, including without limitation the rights
53 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
54 | copies of the Software, and to permit persons to whom the Software is
55 | furnished to do so, subject to the following conditions:
56 |
57 | The above copyright notice and this permission notice shall be included in
58 | all copies or substantial portions of the Software.
59 |
60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66 | THE SOFTWARE.
67 |
68 | License
69 | MIT
70 | Title
71 | SnapKit
72 | Type
73 | PSGroupSpecifier
74 |
75 |
76 | FooterText
77 | Generated by CocoaPods - https://cocoapods.org
78 | Title
79 |
80 | Type
81 | PSGroupSpecifier
82 |
83 |
84 | StringsTable
85 | Acknowledgements
86 | Title
87 | Acknowledgements
88 |
89 |
90 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_Demo : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_Demo
5 | @end
6 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks-Debug-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Apis/Apis.framework
3 | ${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks-Debug-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Apis.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks-Release-input-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh
2 | ${BUILT_PRODUCTS_DIR}/Apis/Apis.framework
3 | ${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks-Release-output-files.xcfilelist:
--------------------------------------------------------------------------------
1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Apis.framework
2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-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_DemoVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_DemoVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Apis" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Apis/Apis.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Apis/Apis.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Apis" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
9 | OTHER_LDFLAGS = $(inherited) -framework "Apis" -framework "Foundation" -framework "SnapKit" -framework "UIKit"
10 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
11 | PODS_BUILD_DIR = ${BUILD_DIR}
12 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
13 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
14 | PODS_ROOT = ${SRCROOT}/Pods
15 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
17 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_Demo {
2 | umbrella header "Pods-Demo-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Apis" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Apis/Apis.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers"
6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
8 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Apis/Apis.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Apis" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit"
9 | OTHER_LDFLAGS = $(inherited) -framework "Apis" -framework "Foundation" -framework "SnapKit" -framework "UIKit"
10 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
11 | PODS_BUILD_DIR = ${BUILD_DIR}
12 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
13 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
14 | PODS_ROOT = ${SRCROOT}/Pods
15 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
17 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit-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 | 5.0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_SnapKit : NSObject
3 | @end
4 | @implementation PodsDummy_SnapKit
5 | @end
6 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit-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 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit-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 SnapKitVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char SnapKitVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit.modulemap:
--------------------------------------------------------------------------------
1 | framework module SnapKit {
2 | umbrella header "SnapKit-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig:
--------------------------------------------------------------------------------
1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
6 | PODS_BUILD_DIR = ${BUILD_DIR}
7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
9 | PODS_ROOT = ${SRCROOT}
10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit
11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 LEE
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apis
2 |
3 | [](LICENSE)
4 | 
5 | 
6 | [](https://github.com/Carthage/Carthage)
7 | [](https://cocoapods.org)
8 |
9 |
10 | [URLNavigator](https://github.com/devxoul/URLNavigator) abstract routing component written in Swift, Inspired by [Moya](https://github.com/Moya/Moya).
11 |
12 | ## [天朝子民](README_CN.md)
13 |
14 | ## Features
15 |
16 | - [x] Support for different processing based on plugin mechanism.
17 | - [x] Configuration is independent and easy to manage.
18 | - [x] Good business scalability.
19 | - [x] Safer page management.
20 | - [x] Support for asynchronous completion of callbacks.
21 |
22 |
23 | ## Installation
24 |
25 | Apis officially supports CocoaPods only.
26 |
27 | **CocoaPods - Podfile**
28 |
29 | ```ruby
30 | pod 'Apis'
31 | ```
32 |
33 | ## Usage
34 |
35 | First make sure to import the framework:
36 |
37 | ```swift
38 | import Apis
39 | ```
40 |
41 | Here are some usage examples. All devices are also available as simulators:
42 |
43 | ### Create Apis
44 |
45 | ```swift
46 | let router = Apis.Provider(
47 | [RouterXXXXXXPlugin(),
48 | RouterXXXXXXPlugin(),
49 | RouterXXXXXXPlugin()]
50 | )
51 | ```
52 |
53 | ### TargetType
54 |
55 | ```swift
56 | enum RouterTarget {
57 | case open_http(url: URL)
58 | case open_https(url: URL)
59 | case open_none
60 | case open_live(id: String)
61 | case open_some
62 | }
63 |
64 | extension RouterTarget: Apis.TargetType {
65 |
66 | var task: Task {
67 | switch(self) {
68 | case let .open_http(url):
69 | return .controller(SFSafariViewController(url: url))
70 |
71 | case let .open_https(url):
72 | return .controller(SFSafariViewController(url: url))
73 |
74 | case .open_none:
75 | return .controller(NoneViewController())
76 |
77 | case let .open_live(id):
78 | let controller = LiveViewController()
79 | controller.id = id
80 | return .controller(controller)
81 |
82 | case .open_some:
83 | return .handle { completion in
84 | DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
85 | completion(true)
86 | }
87 | }
88 | }
89 | }
90 | }
91 |
92 | extension XXXXViewController: Routerable { }
93 | extension SFSafariViewController: Routerable { }
94 | ```
95 | ### URLTargetType
96 |
97 | ```swift
98 | private let schemes = "router"
99 |
100 | extension RouterTarget: URLTargetType {
101 |
102 | static var bindings: [URLPatternBinding] {
103 | return [
104 | .init("http://") { source in
105 | guard let url = source.url.value else { return .none }
106 | return .open_http(url: url)
107 | },
108 | .init("https://") { source in
109 | guard let url = source.url.value else { return .none }
110 | return .open_https(url: url)
111 | },
112 | .init(schemes + "://open/none") {
113 | return .open_none
114 | },
115 | .init(schemes + "://open/live") { source in
116 | guard let id = source.url.queryParameters["id"] else { return nil }
117 | return .open_live(id: id)
118 | },
119 | .init(schemes + "://open/some") {
120 | return .open_some
121 | }
122 | ]
123 | }
124 | }
125 | ```
126 |
127 | ### Custom plugins
128 |
129 | ```swift
130 | class RouterXXXXPlugin: Apis.PluginType {
131 |
132 | func should(open target: TargetType) -> Bool {
133 | /* ... */
134 | return true
135 | }
136 |
137 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
138 | /* ... */
139 | completion(true)
140 | }
141 |
142 | func will(open target: TargetType, controller: Routerable) {
143 | /* ... */
144 | }
145 |
146 | func did(open target: TargetType, controller: Routerable) {
147 | /* ... */
148 | }
149 | }
150 | ```
151 |
152 | ### Open
153 |
154 | ```swift
155 | // Open page based on type
156 | router.open(.open_xxxx)
157 |
158 | // Open page based on url
159 | router.open("http://xxxxxxxx")
160 |
161 | // Result callback
162 | router.open("http://xxxxxxxx") { (result) in
163 | // Success or failure
164 | }
165 |
166 | ```
167 |
168 | ## Contributing
169 |
170 | If you have the need for a specific feature that you want implemented or if you experienced a bug, please open an issue.
171 | If you extended the functionality of Apis yourself and want others to use it too, please submit a pull request.
172 |
173 |
174 | ## License
175 |
176 | Apis is under MIT license. See the [LICENSE](LICENSE) file for more info.
177 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # Apis
2 |
3 | [](LICENSE)
4 | 
5 | 
6 | [](https://github.com/Carthage/Carthage)
7 | [](https://cocoapods.org)
8 |
9 | 基于[URLNavigator](https://github.com/devxoul/URLNavigator) 抽象的路由组件, 灵感来自 [Moya](https://github.com/Moya/Moya).
10 |
11 | ## Features
12 |
13 | - [x] 支持基于插件机制的不同处理 如登录拦截等.
14 | - [x] 配置独立且易于管理.
15 | - [x] 良好的业务可扩展性.
16 | - [x] 安全的页面管理.
17 | - [x] 支持异步完成结果回调.
18 |
19 |
20 | ## 安装
21 |
22 | Apis 仅支持CocoaPods.
23 |
24 | **CocoaPods - Podfile**
25 |
26 | ```ruby
27 | pod 'Apis'
28 | ```
29 |
30 | ## 使用
31 |
32 | 首先导入framework:
33 |
34 | ```swift
35 | import Apis
36 | ```
37 |
38 | 下面是一些简单示例. 支持所有设备和模拟器:
39 |
40 | ### 创建 Apis
41 |
42 | ```swift
43 | let router = Apis.Provider(
44 | [RouterXXXXXXPlugin(),
45 | RouterXXXXXXPlugin(),
46 | RouterXXXXXXPlugin()]
47 | )
48 | ```
49 |
50 | ### TargetType
51 |
52 | ```swift
53 | // 可以通过枚举声明所有类型
54 | enum RouterTarget {
55 | case open_http(url: URL)
56 | case open_https(url: URL)
57 | case open_none
58 | case open_live(id: String)
59 | case open_some
60 | }
61 |
62 | extension RouterTarget: Apis.TargetType {
63 |
64 | var task: Task {
65 | switch(self) {
66 | case let .open_http(url):
67 | return .controller(SFSafariViewController(url: url))
68 |
69 | case let .open_https(url):
70 | return .controller(SFSafariViewController(url: url))
71 |
72 | case .open_none:
73 | return .controller(NoneViewController())
74 |
75 | case let .open_live(id):
76 | let controller = LiveViewController()
77 | controller.id = id
78 | return .controller(controller)
79 |
80 | case .open_some:
81 | return .handle { completion in
82 | // 处理一些其他事情, 结束后务必调用completion回调
83 | DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
84 | // 巴拉巴拉..
85 | completion(true)
86 | }
87 | }
88 | }
89 | }
90 | }
91 |
92 | // 每个支持路由的视图控制器需要实现 Routerable 协议
93 | extension XXXXViewController: Routerable { }
94 | extension SFSafariViewController: Routerable { }
95 | ```
96 |
97 | ### URLTargetType
98 |
99 | ```swift
100 | private let schemes = "router"
101 |
102 | extension RouterTarget: URLTargetType {
103 | // URL模板绑定 不同的模板返回不同的Target
104 | static var bindings: [URLPatternBinding] {
105 | return [
106 | .init("http://") { source in
107 | guard let url = source.url.value else { return .none }
108 | return .open_http(url: url)
109 | },
110 | .init("https://") { source in
111 | guard let url = source.url.value else { return .none }
112 | return .open_https(url: url)
113 | },
114 | .init(schemes + "://open/none") {
115 | return .open_none
116 | },
117 | .init(schemes + "://open/live") { source in
118 | guard let id = source.url.queryParameters["id"] else { return nil }
119 | return .open_live(id: id)
120 | },
121 | .init(schemes + "://open/some") {
122 | return .open_some
123 | }
124 | ]
125 | }
126 | }
127 | ```
128 |
129 | ### 自定义插件
130 |
131 | ```swift
132 | // 实现需要的方法 你可以在整个打开过程中做一切你想做的事情
133 | class RouterXXXXPlugin: Apis.PluginType {
134 |
135 | // 能否打开
136 | func should(open target: TargetType) -> Bool {
137 | /* ... */
138 | return true
139 | }
140 |
141 | // 准备打开时
142 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
143 | /* ... */
144 | completion(true)
145 | }
146 |
147 | // 即将打开
148 | func will(open target: TargetType, controller: Routerable) {
149 | /* ... */
150 | }
151 |
152 | // 已经打开
153 | func did(open target: TargetType, controller: Routerable) {
154 | /* ... */
155 | }
156 | }
157 | ```
158 |
159 | ### 打开
160 |
161 | ```swift
162 | // 根据目标类型打开页面
163 | router.open(.open_xxxx)
164 |
165 | // 根据URL打开页面
166 | router.open("http://xxxxxxxx")
167 |
168 | // 打开结果回调 打开过程中可能由于各种原因导致打开失败 例如: 这个页面需要登录 但是当前没有登录之类的
169 | router.open("http://xxxxxxxx") { (result) in
170 | // 成功或失败
171 | }
172 | ```
173 |
174 | ## 贡献
175 |
176 | 如果你需要实现特定功能或遇到错误,请打开issue。 如果你自己扩展了Apis的功能并希望其他人也使用它,请提交拉取请求。
177 |
178 |
179 | ## 协议
180 |
181 | Apis 使用 MIT 协议. 有关更多信息,请参阅 [LICENSE](LICENSE) 文件.
182 |
--------------------------------------------------------------------------------
/Sources/Apis.h:
--------------------------------------------------------------------------------
1 | //
2 | // Apis.h
3 | // Apis
4 | //
5 | // Created by 李响 on 2021/12/15.
6 | //
7 |
8 | #import
9 |
10 | //! Project version number for Apis.
11 | FOUNDATION_EXPORT double ApisVersionNumber;
12 |
13 | //! Project version string for Apis.
14 | FOUNDATION_EXPORT const unsigned char ApisVersionString[];
15 |
16 | // In this header, you should import all the public headers of your framework using statements like #import
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Sources/Context.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Context.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2019/4/1.
11 | // Copyright © 2019年 lee. All rights reserved.
12 | //
13 |
14 | import Foundation
15 |
16 | struct Context {
17 | let callback: (Bool) -> Void
18 |
19 | init(_ completion: @escaping (Bool) -> Void = { _ in }) {
20 | callback = completion
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTracking
6 |
7 | NSPrivacyAccessedAPITypes
8 |
9 | NSPrivacyTrackingDomains
10 |
11 | NSPrivacyCollectedDataTypes
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Sources/Protocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Protocol.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2019/4/1.
11 | // Copyright © 2019年 lee. All rights reserved.
12 | //
13 |
14 | import UIKit
15 |
16 | public protocol PluginType {
17 |
18 | /// 是否可以打开
19 | ///
20 | /// - Parameter target: 类型
21 | /// - Returns: true or false
22 | func should(open target: TargetType) -> Bool
23 |
24 | /// 准备打开
25 | ///
26 | /// - Parameters:
27 | /// - target: 类型
28 | /// - completion: 准备完成回调 (无论结果如何必须回调)
29 | func prepare(open target: TargetType, completion: @escaping (Bool) -> Void)
30 |
31 | /// 即将打开
32 | ///
33 | /// - Parameters:
34 | /// - target: 类型
35 | /// - controller: 视图控制器
36 | func will(open target: TargetType, controller: Routerable)
37 |
38 | /// 已经打开
39 | ///
40 | /// - Parameters:
41 | /// - target: 类型
42 | /// - controller: 视图控制器
43 | func did(open target: TargetType, controller: Routerable)
44 | }
45 |
46 | public typealias URLPattern = String
47 |
48 | public enum Task {
49 |
50 | case controller(Routerable)
51 |
52 | case handle(working: (_ completion: (@escaping (Bool) -> Void)) -> Void)
53 | }
54 |
55 | public protocol TargetType {
56 |
57 | var task: Task { get }
58 | }
59 |
60 | public struct URLPatternBinding {
61 |
62 | public struct Source {
63 | public let url: URLConvertible
64 | public let values: [String: Any]
65 | }
66 |
67 | let pattern: URLPattern
68 | let target: (Source) -> Target?
69 |
70 | public init(_ pattern: URLPattern, binding: @escaping () -> Target?) {
71 | self.pattern = pattern
72 | self.target = { _ in binding() }
73 | }
74 |
75 | public init(_ pattern: URLPattern, binding: @escaping (Source) -> Target?) {
76 | self.pattern = pattern
77 | self.target = binding
78 | }
79 | }
80 |
81 | public protocol URLTargetType: TargetType {
82 |
83 | static var bindings: [URLPatternBinding] { get }
84 | }
85 |
86 | public protocol Routerable: UIViewController {
87 |
88 | /// 打开
89 | ///
90 | /// - Parameter completion: 打开完成回调
91 | func open(with completion: @escaping () -> Void)
92 |
93 | /// 关闭
94 | ///
95 | /// - Parameters:
96 | /// - completion: 关闭完成回调
97 | func close(with completion: @escaping () -> Void)
98 | }
99 |
100 | public extension URL {
101 |
102 | func appending(_ params: [String: String]) -> String {
103 | return absoluteString.appending(params)
104 | }
105 | }
106 |
107 | public extension String {
108 |
109 | func appending(_ params: [String: String]) -> String {
110 | return appending(self, params)
111 | }
112 |
113 | func appending(_ url: String, _ params: [String: String]) -> String {
114 | guard var components = URLComponents(string: url) else {
115 | return url
116 | }
117 |
118 | let query = components.percentEncodedQuery ?? ""
119 | let temp = params.compactMap({
120 | guard !$0.isEmpty, !$1.isEmpty else { return nil }
121 | guard let _ = Foundation.URL(string: $1) else {
122 | let encoded = $1.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? $1
123 | return "\($0)=\(encoded)"
124 | }
125 |
126 | let string = "?!@#$^&%*+,:;='\"`<>()[]{}/\\| "
127 | let character = CharacterSet(charactersIn: string).inverted
128 | let encoded = $1.addingPercentEncoding(withAllowedCharacters: character) ?? $1
129 | return "\($0)=\(encoded)"
130 | }).joined(separator: "&")
131 | components.percentEncodedQuery = query.isEmpty ? temp : query + "&" + temp
132 | return components.url?.absoluteString ?? url
133 | }
134 | }
135 |
136 | extension Routerable {
137 |
138 | public func open(with completion: @escaping () -> Void = {}) {
139 | guard let controller = UIViewController.top() else {
140 | return
141 | }
142 |
143 | if let navigation = controller as? UINavigationController {
144 | CATransaction.begin()
145 | CATransaction.setCompletionBlock(completion)
146 | navigation.pushViewController(self, animated: true)
147 | CATransaction.commit()
148 |
149 | } else if let navigation = controller.navigationController {
150 | CATransaction.begin()
151 | CATransaction.setCompletionBlock(completion)
152 | navigation.pushViewController(self, animated: true)
153 | CATransaction.commit()
154 |
155 | } else {
156 | let navigation = UINavigationController(rootViewController: self)
157 | controller.present(navigation, animated: true, completion: completion)
158 | }
159 | }
160 |
161 | public func close(with completion: @escaping () -> Void = {}) {
162 | guard
163 | let navigation = navigationController,
164 | navigation.viewControllers.first != self else {
165 | let presenting = presentingViewController ?? self
166 | presenting.dismiss(animated: true, completion: completion)
167 | return
168 | }
169 | guard presentedViewController == nil else {
170 | dismiss(animated: true) { [weak self] in self?.close(with: completion) }
171 | return
172 | }
173 |
174 | func parents(_ controller: UIViewController) -> [UIViewController] {
175 | guard let parent = controller.parent else {
176 | return [controller]
177 | }
178 | return [controller] + parents(parent)
179 | }
180 |
181 | CATransaction.begin()
182 | CATransaction.setCompletionBlock(completion)
183 | if let top = navigation.topViewController, parents(self).contains(top) {
184 | navigation.popViewController(animated: true)
185 |
186 | } else {
187 | let temp = navigation.viewControllers.filter { !parents(self).contains($0) }
188 | navigation.setViewControllers(temp, animated: true)
189 | }
190 | CATransaction.commit()
191 | }
192 | }
193 |
194 | extension PluginType {
195 |
196 | public func should(open target: TargetType) -> Bool {
197 | return true
198 | }
199 |
200 | public func prepare(open target: TargetType, completion: @escaping (Bool) -> Void) {
201 | completion(true)
202 | }
203 |
204 | public func will(open target: TargetType, controller: Routerable) {
205 | }
206 |
207 | public func did(open target: TargetType, controller: Routerable) {
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/Sources/Provider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Provider.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2019/4/1.
11 | // Copyright © 2019年 lee. All rights reserved.
12 | //
13 |
14 | import UIKit
15 |
16 | private let navigator = URLNavigator()
17 |
18 | /// 打开 (全局)
19 | ///
20 | /// - Parameters:
21 | /// - url: url
22 | /// - completion: 打开完成回调
23 | /// - Returns: true or false
24 | @discardableResult
25 | public func open(_ url: URLConvertible,
26 | completion: ((Bool) -> Void)? = .none) -> Bool {
27 | return navigator.open(url, context: Context(completion ?? { _ in }))
28 | }
29 |
30 | /// 获取视图控制器 (全局)
31 | ///
32 | /// - Parameters:
33 | /// - url: url
34 | /// - context: context
35 | /// - Returns: 视图控制器
36 | public func controller(_ url: URLConvertible) -> Routerable? {
37 | return navigator.viewController(for: url) as? Routerable
38 | }
39 |
40 | public class Provider {
41 |
42 | private let plugins: [PluginType]
43 |
44 | public init(plugins: [PluginType]) {
45 | self.plugins = plugins
46 | }
47 | }
48 |
49 | extension Provider where Target: TargetType {
50 |
51 | /// 打开
52 | ///
53 | /// - Parameters:
54 | /// - target: TargetType
55 | /// - completion: 打开完成回调
56 | /// - Returns: true or false
57 | @discardableResult
58 | public func open(_ target: Target, completion: ((Bool) -> Void)? = .none) -> Bool {
59 | if self.plugins.isEmpty {
60 | switch target.task {
61 | case .controller(let controller):
62 | controller.open {
63 | completion?(true)
64 | }
65 |
66 | case .handle(working: let closure):
67 | closure { result in
68 | completion?(result)
69 | }
70 | }
71 |
72 | return true
73 |
74 | } else {
75 | guard self.plugins.contains(where: { $0.should(open: target) }) else {
76 | return false
77 | }
78 |
79 | var result = true
80 | let total = self.plugins.count
81 | var count = 0
82 | let group = DispatchGroup()
83 | self.plugins.forEach { p in
84 | group.enter()
85 | p.prepare(open: target) {
86 | // 防止插件多次回调
87 | defer { count += 1 }
88 | guard count < total else { return }
89 |
90 | result = $0 ? result : false
91 | group.leave()
92 | }
93 | }
94 |
95 | group.notify(queue: .main) { [weak self] in
96 | guard let self = self else {
97 | completion?(false)
98 | return
99 | }
100 | guard result else {
101 | completion?(false)
102 | return
103 | }
104 |
105 | switch target.task {
106 | case .controller(let controller):
107 | self.plugins.forEach {
108 | $0.will(open: target, controller: controller)
109 | }
110 |
111 | controller.open { [weak self] in
112 | guard let self = self else { return }
113 | self.plugins.forEach {
114 | $0.did(open: target, controller: controller)
115 | }
116 |
117 | completion?(true)
118 | }
119 |
120 | case .handle(working: let closure):
121 | closure { result in
122 | completion?(result)
123 | }
124 | }
125 | }
126 |
127 | return true
128 | }
129 | }
130 |
131 | /// 获取视图控制器
132 | ///
133 | /// - Parameters:
134 | /// - target: TargetType
135 | /// - Returns: 视图控制器
136 | public func controller(_ target: Target) -> Routerable? {
137 | guard case .controller(let controller) = target.task else {
138 | return nil
139 | }
140 | return controller
141 | }
142 | }
143 |
144 | extension Provider where Target: URLTargetType {
145 |
146 | /// 打开
147 | ///
148 | /// - Parameters:
149 | /// - url: url
150 | /// - completion: 打开完成回调
151 | /// - Returns: true or false
152 | @discardableResult
153 | public func open(_ url: URLConvertible,
154 | completion: ((Bool) -> Void)? = .none) -> Bool {
155 | let patterns = Target.bindings.map({ $0.pattern })
156 | guard let result = navigator.matcher.match(url, from: patterns) else {
157 | return false
158 | }
159 | guard let target = self.target(result.pattern, url, result.values) else {
160 | return false
161 | }
162 | return open(target, completion: completion)
163 | }
164 |
165 | /// 获取视图控制器
166 | ///
167 | /// - Parameters:
168 | /// - url: url
169 | /// - context: context
170 | /// - Returns: 视图控制器
171 | public func controller(_ url: URLConvertible) -> Routerable? {
172 | let patterns = Target.bindings.map({ $0.pattern })
173 | guard let result = navigator.matcher.match(url, from: patterns) else {
174 | return nil
175 | }
176 | guard let target = self.target(result.pattern, url, result.values) else {
177 | return nil
178 | }
179 | return controller(target)
180 | }
181 | }
182 |
183 | extension Provider where Target: URLTargetType {
184 |
185 | /// 加入全局
186 | public func global() {
187 | Target.bindings.forEach { binding in
188 | self.binding(binding.pattern)
189 | }
190 | }
191 |
192 | private func target(_ pattern: URLPattern, _ url: URLConvertible, _ values: [String : Any]) -> Target? {
193 | guard let binding = Target.bindings.last(where: { $0.pattern == pattern }) else {
194 | return nil
195 | }
196 | return binding.target(.init(url: url, values: values))
197 | }
198 |
199 | typealias ViewControllerFactory = (_ url: URLConvertible, _ values: [String: Any], _ context: Any?) -> Routerable?
200 |
201 | private func register(_ pattern: URLPattern, _ factory: @escaping ViewControllerFactory) {
202 | navigator.register(pattern) { (url, values, context) -> UIViewController? in
203 | return factory(url, values, context)
204 | }
205 | }
206 |
207 | private func handle(_ pattern: URLPattern, _ factory: @escaping URLOpenHandlerFactory) {
208 | navigator.handle(pattern) { (url, values, context) -> Bool in
209 | return factory(url, values, context)
210 | }
211 | }
212 |
213 | private func binding(_ pattern: URLPattern) {
214 | self.register(pattern) { [weak self] (url, values, context) -> Routerable? in
215 | guard let self = self else { return nil }
216 | guard let target = self.target(pattern, url, values) else {
217 | return nil
218 | }
219 | return self.controller(target)
220 | }
221 | self.handle(pattern) { [weak self] (url, values, context) -> Bool in
222 | guard let self = self else { return false }
223 | guard let target = self.target(pattern, url, values) else {
224 | return false
225 | }
226 | let context = context as? Context
227 | return self.open(target, completion: context?.callback)
228 | }
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/Sources/UIApplicationExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIApplicationExtension.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2021/12/10.
11 | // Copyright © 2021 lee. All rights reserved.
12 | //
13 |
14 | import UIKit
15 |
16 | extension UIApplication {
17 |
18 | var window: UIWindow? {
19 | if #available(iOS 13.0, *) {
20 | let windows: [UIWindow] = UIApplication.shared.connectedScenes.compactMap { scene in
21 | guard let scene = scene as? UIWindowScene else { return nil }
22 | guard scene.session.role == .windowApplication else { return nil }
23 | guard let delegate = scene.delegate as? UIWindowSceneDelegate else { return nil }
24 | guard let window = delegate.window else { return nil }
25 | guard let window = window else { return nil }
26 | return window
27 | }
28 |
29 | if windows.isEmpty {
30 | guard let delegate = UIApplication.shared.delegate else { return nil }
31 | guard let window = delegate.window else { return nil }
32 | return window
33 |
34 | } else {
35 | return windows.first
36 | }
37 |
38 | } else {
39 | guard let delegate = UIApplication.shared.delegate else { return nil }
40 | guard let window = delegate.window else { return nil }
41 | return window
42 | }
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/Sources/UIViewControllerExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewControllerExtension.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2021/12/10.
11 | // Copyright © 2021 lee. All rights reserved.
12 | //
13 |
14 | import UIKit
15 |
16 | extension UIViewController {
17 |
18 | /// 获取Window下的顶层控制器
19 | @objc
20 | open class func top(in window: UIWindow? = .none) -> UIViewController? {
21 | return (window ?? UIApplication.shared.window)?.rootViewController?.top()
22 | }
23 |
24 | @objc
25 | open func top() -> UIViewController {
26 | // presented view controller
27 | if let controller = presentedViewController {
28 | return controller.top()
29 | }
30 |
31 | // UITabBarController
32 | if let tabBarController = self as? UITabBarController,
33 | let controller = tabBarController.selectedViewController {
34 | return controller.top()
35 | }
36 |
37 | // UINavigationController
38 | if let navigationController = self as? UINavigationController,
39 | let controller = navigationController.visibleViewController {
40 | return controller.top()
41 | }
42 |
43 | // UIPageController
44 | if let pageViewController = self as? UIPageViewController,
45 | pageViewController.viewControllers?.count == 1 ,
46 | let controller = pageViewController.viewControllers?.first {
47 | return controller.top()
48 | }
49 |
50 | // child view controller
51 | // for subview in self.view?.subviews ?? [] {
52 | // if let controller = subview.next as? UIViewController {
53 | // return controller.top()
54 | // }
55 | // }
56 | return self
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/URLConvertible.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URLConvertible.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2021/11/30.
11 | // Copyright © 2021 lee. All rights reserved.
12 | //
13 |
14 | import Foundation
15 |
16 | /// A type which can be converted to an URL string.
17 | public protocol URLConvertible {
18 | var value: URL? { get }
19 | var stringValue: String { get }
20 |
21 | /// Returns URL query parameters. For convenience, this property will never return `nil` even if
22 | /// there's no query string in the URL. This property doesn't take care of the duplicated keys.
23 | /// For checking duplicated keys, use `queryItems` instead.
24 | ///
25 | /// - seealso: `queryItems`
26 | var queryParameters: [String: String] { get }
27 |
28 | /// Returns `queryItems` property of `URLComponents` instance.
29 | ///
30 | /// - seealso: `queryParameters`
31 | @available(iOS 8, *)
32 | var queryItems: [URLQueryItem]? { get }
33 | }
34 |
35 | extension URLConvertible {
36 |
37 | public var queryParameters: [String: String] {
38 | var parameters = [String: String]()
39 | self.value?.query?.components(separatedBy: "&").forEach { component in
40 | guard let separatorIndex = component.firstIndex(of: "=") else { return }
41 | let keyRange = component.startIndex.. Any?
22 |
23 | static let defaultURLValueConverters: [String: URLValueConverter] = [
24 | "string": { pathComponents, index in
25 | return pathComponents[index]
26 | },
27 | "int": { pathComponents, index in
28 | return Int(pathComponents[index])
29 | },
30 | "float": { pathComponents, index in
31 | return Float(pathComponents[index])
32 | },
33 | "uuid": { pathComponents, index in
34 | return UUID(uuidString: pathComponents[index])
35 | },
36 | "path": { pathComponents, index in
37 | return pathComponents[index.."])
49 | ///
50 | /// The value of the `URLPattern` from an example above is `"myapp://user/"` and the
51 | /// value of the `values` is `["id": 123]`.
52 | ///
53 | /// - parameter url: The placeholder-filled URL.
54 | /// - parameter from: The array of URL patterns.
55 | ///
56 | /// - returns: A `URLMatchComponents` struct that holds the URL pattern string, a dictionary of
57 | /// the URL placeholder values.
58 | func match(_ url: URLConvertible, from candidates: [URLPattern]) -> URLMatchResult? {
59 | let url = self.normalizeURL(url)
60 | let scheme = url.value?.scheme
61 | let stringPathComponents = self.stringPathComponents(from :url)
62 |
63 | for candidate in candidates {
64 | guard scheme == candidate.value?.scheme else { continue }
65 | if let result = self.match(stringPathComponents, with: candidate) {
66 | return result
67 | }
68 | }
69 |
70 | return nil
71 | }
72 |
73 | func match(_ stringPathComponents: [String], with candidate: URLPattern) -> URLMatchResult? {
74 | let normalizedCandidate = self.normalizeURL(candidate).stringValue
75 | let candidatePathComponents = self.pathComponents(from: normalizedCandidate)
76 | guard self.ensurePathComponentsCount(stringPathComponents, candidatePathComponents) else {
77 | return nil
78 | }
79 |
80 | var urlValues: [String: Any] = [:]
81 |
82 | let pairCount = min(stringPathComponents.count, candidatePathComponents.count)
83 | for index in 0 ..< pairCount {
84 | let result = self.matchStringPathComponent(
85 | at: index,
86 | from: stringPathComponents,
87 | with: candidatePathComponents
88 | )
89 |
90 | switch result {
91 | case let .matches(placeholderValue):
92 | if let (key, value) = placeholderValue {
93 | urlValues[key] = value
94 | }
95 |
96 | case .notMatches:
97 | return nil
98 | }
99 | }
100 |
101 | return URLMatchResult(pattern: candidate, values: urlValues)
102 | }
103 |
104 | private func normalizeURL(_ dirtyURL: URLConvertible) -> URLConvertible {
105 | guard dirtyURL.value != nil else { return dirtyURL }
106 | var urlString = dirtyURL.stringValue
107 | urlString = urlString.components(separatedBy: "?")[0].components(separatedBy: "#")[0]
108 | urlString = self.replaceRegex(":/{3,}", "://", urlString)
109 | urlString = self.replaceRegex("(? String {
115 | guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return string }
116 | let range = NSMakeRange(0, string.count)
117 | return regex.stringByReplacingMatches(in: string, options: [], range: range, withTemplate: repl)
118 | }
119 |
120 | private func ensurePathComponentsCount(
121 | _ stringPathComponents: [String],
122 | _ candidatePathComponents: [URLPathComponent]
123 | ) -> Bool {
124 | let hasSameNumberOfComponents = (stringPathComponents.count == candidatePathComponents.count)
125 | let containsPathPlaceholderComponent = candidatePathComponents.contains {
126 | if case let .placeholder(type, _) = $0, type == "path" {
127 | return true
128 | } else {
129 | return false
130 | }
131 | }
132 | return hasSameNumberOfComponents || (containsPathPlaceholderComponent && stringPathComponents.count > candidatePathComponents.count)
133 | }
134 |
135 | private func stringPathComponents(from url: URLConvertible) -> [String] {
136 | return url.stringValue.components(separatedBy: "/").lazy
137 | .filter { !$0.isEmpty }
138 | .filter { !$0.hasSuffix(":") }
139 | }
140 |
141 | private func pathComponents(from url: URLPattern) -> [URLPathComponent] {
142 | return stringPathComponents(from: url).map(URLPathComponent.init)
143 | }
144 |
145 | private func matchStringPathComponent(
146 | at index: Int,
147 | from stringPathComponents: [String],
148 | with candidatePathComponents: [URLPathComponent]
149 | ) -> URLPathComponentMatchResult {
150 | let stringPathComponent = stringPathComponents[index]
151 | let urlPathComponent = candidatePathComponents[index]
152 |
153 | switch urlPathComponent {
154 | case let .plain(value):
155 | guard stringPathComponent == value else { return .notMatches }
156 | return .matches(nil)
157 |
158 | case let .placeholder(type, key):
159 | guard let type = type, let converter = self.valueConverters[type] else {
160 | return .matches((key, stringPathComponent))
161 | }
162 | if let value = converter(stringPathComponents, index) {
163 | return .matches((key, value))
164 |
165 | } else {
166 | return .notMatches
167 | }
168 | }
169 | }
170 | }
171 |
172 |
173 | /// Represents an URL match result.
174 | struct URLMatchResult {
175 | /// The url pattern that was matched.
176 | let pattern: String
177 |
178 | /// The values extracted from the URL placeholder.
179 | let values: [String: Any]
180 | }
181 |
182 | enum URLPathComponentMatchResult {
183 | case matches((key: String, value: Any)?)
184 | case notMatches
185 | }
186 |
--------------------------------------------------------------------------------
/Sources/URLNavigator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Navigator.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2021/12/10.
11 | // Copyright © 2021 lee. All rights reserved.
12 | //
13 |
14 | import UIKit
15 |
16 | typealias ViewControllerFactory = (_ url: URLConvertible, _ values: [String: Any], _ context: Any?) -> UIViewController?
17 | typealias URLOpenHandlerFactory = (_ url: URLConvertible, _ values: [String: Any], _ context: Any?) -> Bool
18 | typealias URLOpenHandler = () -> Bool
19 |
20 | class URLNavigator {
21 |
22 | let matcher = URLMatcher()
23 |
24 | private var controllerFactories = [URLPattern: ViewControllerFactory]()
25 | private var handlerFactories = [URLPattern: URLOpenHandlerFactory]()
26 |
27 | func register(_ pattern: URLPattern, _ factory: @escaping ViewControllerFactory) {
28 | self.controllerFactories[pattern] = factory
29 | }
30 |
31 | func handle(_ pattern: URLPattern, _ factory: @escaping URLOpenHandlerFactory) {
32 | self.handlerFactories[pattern] = factory
33 | }
34 |
35 | func viewController(for url: URLConvertible, context: Any? = nil) -> UIViewController? {
36 | let urlPatterns = Array(self.controllerFactories.keys)
37 | guard let match = self.matcher.match(url, from: urlPatterns) else { return nil }
38 | guard let factory = self.controllerFactories[match.pattern] else { return nil }
39 | return factory(url, match.values, context)
40 | }
41 |
42 | func handler(for url: URLConvertible, context: Any?) -> URLOpenHandler? {
43 | let urlPatterns = Array(self.handlerFactories.keys)
44 | guard let match = self.matcher.match(url, from: urlPatterns) else { return nil }
45 | guard let handler = self.handlerFactories[match.pattern] else { return nil }
46 | return { handler(url, match.values, context) }
47 | }
48 |
49 | @discardableResult
50 | func open(_ url: URLConvertible, context: Any? = nil) -> Bool {
51 | guard let handler = self.handler(for: url, context: context) else { return false }
52 | return handler()
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/URLPathComponent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URLPathComponent.swift
3 | // ┌─┐ ┌───────┐ ┌───────┐
4 | // │ │ │ ┌─────┘ │ ┌─────┘
5 | // │ │ │ └─────┐ │ └─────┐
6 | // │ │ │ ┌─────┘ │ ┌─────┘
7 | // │ └─────┐│ └─────┐ │ └─────┐
8 | // └───────┘└───────┘ └───────┘
9 | //
10 | // Created by lee on 2021/11/30.
11 | // Copyright © 2021 lee. All rights reserved.
12 | //
13 |
14 | import Foundation
15 |
16 | enum URLPathComponent {
17 | case plain(String)
18 | case placeholder(type: String?, key: String)
19 | }
20 |
21 | extension URLPathComponent {
22 |
23 | init(_ value: String) {
24 | if value.hasPrefix("<") && value.hasSuffix(">") {
25 | let start = value.index(after: value.startIndex)
26 | let end = value.index(before: value.endIndex)
27 | let placeholder = value[start.." -> "int:id"
28 | let typeAndKey = placeholder.components(separatedBy: ":")
29 | if typeAndKey.count == 1 { // any-type placeholder
30 | self = .placeholder(type: nil, key: typeAndKey[0])
31 |
32 | } else if typeAndKey.count == 2 {
33 | self = .placeholder(type: typeAndKey[0], key: typeAndKey[1])
34 |
35 | } else {
36 | self = .plain(value)
37 | }
38 |
39 | } else {
40 | self = .plain(value)
41 | }
42 | }
43 | }
44 |
45 | extension URLPathComponent: Equatable {
46 |
47 | static func == (lhs: URLPathComponent, rhs: URLPathComponent) -> Bool {
48 | switch (lhs, rhs) {
49 | case let (.plain(leftValue), .plain(rightValue)):
50 | return leftValue == rightValue
51 |
52 | case let (.placeholder(leftType, leftKey), .placeholder(rightType, key: rightKey)):
53 | return (leftType == rightType) && (leftKey == rightKey)
54 |
55 | default:
56 | return false
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------