├── DDKitSwift.podspec ├── LICENSE ├── NOTICE ├── README.md ├── example ├── DDKitSwift.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── damon.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── damon.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── DDKitSwift.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── damon.xcuserdatad │ │ ├── IDEFindNavigatorScopes.plist │ │ └── UserInterfaceState.xcuserstate ├── DDKitSwift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── DDFileBrowser.imageset │ │ │ ├── Contents.json │ │ │ └── DDFileBrowser.png │ │ ├── DDUserDefaultManager.imageset │ │ │ ├── Contents.json │ │ │ └── DDUserDefaultManager.png │ │ ├── icon_close.imageset │ │ │ ├── Contents.json │ │ │ └── icon_close@3x.png │ │ ├── icon_home.imageset │ │ │ ├── Contents.json │ │ │ └── icon_home@3x.png │ │ ├── icon_list.imageset │ │ │ ├── Contents.json │ │ │ └── icon_list@3x.png │ │ ├── icon_notice.imageset │ │ │ ├── Contents.json │ │ │ └── icon_notice@3x.png │ │ ├── icon_search.imageset │ │ │ ├── Contents.json │ │ │ └── icon_search@3x.png │ │ ├── icon_setting.imageset │ │ │ ├── Contents.json │ │ │ └── icon_setting@3x.png │ │ ├── icon_share.imageset │ │ │ ├── Contents.json │ │ │ └── icon_share@3x.png │ │ ├── log_icon_close.imageset │ │ │ ├── Contents.json │ │ │ └── log_icon_close.png │ │ ├── log_icon_scale.imageset │ │ │ ├── Contents.json │ │ │ └── log_icon_scale.png │ │ ├── log_icon_subtract.imageset │ │ │ ├── Contents.json │ │ │ └── log_icon_subtract.png │ │ ├── logger_logo.imageset │ │ │ ├── Contents.json │ │ │ └── logger_logo@3x.png │ │ └── zx_logo.imageset │ │ │ ├── Contents.json │ │ │ └── zx_logo@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── PluginDemo.swift │ ├── PluginDemo2.swift │ ├── PluginDemo3.swift │ ├── ViewController.swift │ ├── de.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── es.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── fr.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── ja.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── ko.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── ru.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ ├── th.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings │ └── zh-Hant.lproj │ │ ├── LaunchScreen.strings │ │ └── Main.strings ├── Podfile ├── Podfile.lock └── Pods │ ├── DDLoggerSwift │ ├── LICENSE │ ├── README.md │ └── pod │ │ ├── DDLoggerSwift.swift │ │ ├── DDLoggerSwiftFloatWindow.swift │ │ ├── DDLoggerSwiftPickerWindow.swift │ │ ├── DDLoggerSwiftWindow.swift │ │ ├── HDSqliteTools.swift │ │ ├── LogContent.swift │ │ ├── assets │ │ ├── icon │ │ │ ├── icon_analyse.png │ │ │ ├── icon_back.png │ │ │ ├── icon_copy.png │ │ │ ├── icon_decrypt.png │ │ │ ├── icon_delete.png │ │ │ ├── icon_exit.png │ │ │ ├── icon_hide.png │ │ │ ├── icon_normal_back.png │ │ │ ├── icon_scale.png │ │ │ ├── icon_scroll.png │ │ │ ├── icon_search.png │ │ │ ├── icon_share.png │ │ │ ├── icon_upload.png │ │ │ ├── log_icon_close.png │ │ │ ├── log_icon_scale.png │ │ │ └── log_icon_subtract.png │ │ └── localizable │ │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ │ └── zh-Hans.lproj │ │ │ └── Localizable.strings │ │ ├── model │ │ ├── DDLoggerSwiftItem.swift │ │ └── DDLoggerSwiftTableCellModel.swift │ │ └── view │ │ ├── DDLoggerSwiftFilterTypeView.swift │ │ ├── DDLoggerSwiftMenuCollectionViewCell.swift │ │ ├── DDLoggerSwiftMenuView.swift │ │ └── DDLoggerSwiftTableViewCell.swift │ ├── DDUtils │ ├── LICENSE │ ├── README.md │ └── Sources │ │ └── core │ │ ├── core │ │ ├── DDUtils.swift │ │ └── DDUtilsNameSpace.swift │ │ ├── ui │ │ ├── DDUtils+AppStore.swift │ │ ├── DDUtils+UI.swift │ │ ├── UIColor+zx.swift │ │ ├── UIImage+zx.swift │ │ └── UIView+zx.swift │ │ └── utils │ │ ├── DDUtils+file.swift │ │ ├── DDUtils+media.swift │ │ ├── DDUtils+system.swift │ │ ├── Data+zx.swift │ │ ├── Date+zx.swift │ │ └── String+zx.swift │ ├── Manifest.lock │ ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── damon.xcuserdatad │ │ └── xcschemes │ │ ├── DDLoggerSwift-DDLoggerSwift.xcscheme │ │ ├── DDLoggerSwift.xcscheme │ │ ├── DDUtils.xcscheme │ │ ├── Pods-DDKitSwift.xcscheme │ │ └── xcschememanagement.plist │ └── Target Support Files │ ├── DDLoggerSwift │ ├── DDLoggerSwift-Info.plist │ ├── DDLoggerSwift-dummy.m │ ├── DDLoggerSwift-prefix.pch │ ├── DDLoggerSwift-umbrella.h │ ├── DDLoggerSwift.debug.xcconfig │ ├── DDLoggerSwift.modulemap │ ├── DDLoggerSwift.release.xcconfig │ └── ResourceBundle-DDLoggerSwift-DDLoggerSwift-Info.plist │ ├── DDUtils │ ├── DDUtils-Info.plist │ ├── DDUtils-dummy.m │ ├── DDUtils-prefix.pch │ ├── DDUtils-umbrella.h │ ├── DDUtils.debug.xcconfig │ ├── DDUtils.modulemap │ └── DDUtils.release.xcconfig │ └── Pods-DDKitSwift │ ├── Pods-DDKitSwift-Info.plist │ ├── Pods-DDKitSwift-acknowledgements.markdown │ ├── Pods-DDKitSwift-acknowledgements.plist │ ├── Pods-DDKitSwift-dummy.m │ ├── Pods-DDKitSwift-frameworks-Debug-input-files.xcfilelist │ ├── Pods-DDKitSwift-frameworks-Debug-output-files.xcfilelist │ ├── Pods-DDKitSwift-frameworks-Release-input-files.xcfilelist │ ├── Pods-DDKitSwift-frameworks-Release-output-files.xcfilelist │ ├── Pods-DDKitSwift-frameworks.sh │ ├── Pods-DDKitSwift-umbrella.h │ ├── Pods-DDKitSwift.debug.xcconfig │ ├── Pods-DDKitSwift.modulemap │ └── Pods-DDKitSwift.release.xcconfig ├── pod ├── DDKitSwift.swift ├── DDKitSwiftCollectionViewHeaderView.swift ├── DDKitSwiftFloatWindow.swift ├── DDKitSwiftPluginCollectionViewCell.swift ├── DDKitSwiftPluginProtocol.swift ├── DDKitSwiftUIConfig.swift ├── DDKitSwiftWindow.swift ├── assets │ ├── icon │ │ ├── icon_close@3x.png │ │ ├── icon_home@3x.png │ │ ├── icon_list@3x.png │ │ ├── icon_notice@3x.png │ │ ├── icon_search@3x.png │ │ ├── icon_setting@3x.png │ │ ├── icon_share@3x.png │ │ ├── log_icon_close.png │ │ ├── log_icon_scale.png │ │ ├── log_icon_subtract.png │ │ ├── logger_logo@3x.png │ │ └── zx_logo@3x.png │ └── localizable │ │ ├── de.lproj │ │ └── Localizable.strings │ │ ├── en.lproj │ │ └── Localizable.strings │ │ ├── es.lproj │ │ └── Localizable.strings │ │ ├── fr.lproj │ │ └── Localizable.strings │ │ ├── ja.lproj │ │ └── Localizable.strings │ │ ├── ko.lproj │ │ └── Localizable.strings │ │ ├── ru.lproj │ │ └── Localizable.strings │ │ ├── th.lproj │ │ └── Localizable.strings │ │ ├── zh-Hans.lproj │ │ └── Localizable.strings │ │ └── zh-Hant.lproj │ │ └── Localizable.strings └── extend │ └── DDLoggerSwift+ddkit.swift └── preview_1.jpg /DDKitSwift.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'DDKitSwift' 3 | s.swift_version = '5.0' 4 | s.version = '4.0.3' 5 | s.license= { :type => "MIT", :file => "LICENSE" } 6 | s.summary = 'DDKitSwift is a debugging SDK tool designed for iOS devices. It integrates a variety of practical debugging features to help developers and users identify and troubleshoot device issues.' 7 | s.homepage = 'https://github.com/DamonHu/DDKitSwift' 8 | s.authors = { 'DDKitSwift' => 'dong765@qq.com' } 9 | s.source = { :git => "https://github.com/DamonHu/DDKitSwift.git", :tag => s.version} 10 | s.requires_arc = true 11 | s.ios.deployment_target = '12.0' 12 | s.subspec 'core' do |cs| 13 | cs.resource_bundles = { 14 | 'DDKitSwift' => ['pod/assets/**/*'] 15 | } 16 | cs.source_files = "pod/*.swift", "pod/**/*.swift" 17 | cs.dependency 'DDUtils/ui', '~> 5' 18 | cs.dependency 'DDUtils/utils', '~> 5' 19 | cs.dependency 'DDLoggerSwift', '~> 5' 20 | end 21 | s.default_subspec = "core" 22 | s.documentation_url = 'https://dongge.org/blog/1307.html' 23 | end 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Damon 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 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ZXKit-code/core 2 | 3 | Copyright 2021 ZXKit and contributors. 4 | All rights reserved. 5 | 6 | This product includes software developed at 7 | ZXKit (https://zxkit.com/). 8 | 9 | This distribution has a binary dependency on zxkit/core, which is available under the Apache-2.0 License. The source code of zxkit/core can be found at https://github.com/zxkit-code/core. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DDKitSwift 2 | 3 | ![](https://img.shields.io/badge/CocoaPods-supported-brightgreen) ![](https://img.shields.io/badge/Swift-5.0-brightgreen) ![](https://img.shields.io/badge/License-MIT-brightgreen) ![](https://img.shields.io/badge/version-iOS12.0-brightgreen) 4 | 5 | Previously developed debugging frameworks were somewhat scattered, so the goal was to create a universal framework that could combine different debugging tools through a plugin structure. This tool is designed for efficient problem solving rather than being comprehensive. Therefore, features that might affect App Store submission, such as private iOS functions and disabled interfaces, are not provided by default. 6 | 7 | The previous name was `ZXKitSwift`, inspired by the novel "Zhu Xian". Due to maintenance costs for the domain and changes in the novel's ending, the name has been changed, dependencies have been removed, and updates have been made. This library is now released as DDKitSwift. 8 | 9 | ### [中文文档](https://dongge.org/blog/1307.html) 10 | 11 | ## Project Preview 12 | 13 | 14 | 15 | ## Features List 16 | 17 | The following plugins are built-in and ready to use: 18 | 19 | * 🐛 Log logging 20 | * 📡 Network Connectivity Test 21 | * 📶 Network ping detection 22 | * 📱 FPS detection 23 | * 📂 Sandbox file browsing 24 | * 📋 UserDefault data management 25 | * 🌐 Network request interception and viewing 26 | 27 | ## Integrating DDKitSwift 28 | 29 | 1. Use CocoaPods to select the functionalities you need. You can combine them as needed. 30 | 31 | **Required** 32 | 33 | ``` 34 | pod 'DDKitSwift' 35 | ``` 36 | 37 | **optional:** Each feature is packaged as an independent module and can be added or removed as needed. 38 | 39 | ``` 40 | pod 'DDKitSwift_NetCheck' 41 | pod 'DDKitSwift_Netfox' 42 | pod 'DDKitSwift_FPS' 43 | pod 'DDKitSwift_Ping' 44 | pod 'DDKitSwift_FileBrowser' 45 | pod 'DDKitSwift_UserDefaultManager' 46 | ``` 47 | 48 | ## Using DDKitSwift 49 | 50 | 2. Import the header files 51 | 52 | ``` 53 | import DDKitSwift 54 | import DDKitSwift_Netfox 55 | import DDKitSwift_FPS 56 | import DDKitSwift_Ping 57 | import DDKitSwift_FileBrowser 58 | import DDKitSwift_UserDefaultManager 59 | import DDKitSwift_NetCheck 60 | ``` 61 | 62 | 3. Register the necessary components in the `AppDelegate` startup function 63 | 64 | ``` 65 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 66 | 67 | DDKitSwift.regist(plugin: DDKitSwift_Netfox()) 68 | DDKitSwift.regist(plugin: DDKitSwift_FPS()) 69 | //Specify target URL 70 | DDKitSwift.regist(plugin: DDKitSwift_NetCheck(url: "https://baidu.com")) 71 | //Specify target URL 72 | DDKitSwift.regist(plugin: DDKitSwift_Ping(url: "https://baidu.com")) 73 | DDKitSwift.regist(plugin: DDKitSwift_FileBrowser()) 74 | DDKitSwift.regist(plugin: DDKitSwift_UserDefaultManager()) 75 | 76 | return true 77 | } 78 | ``` 79 | 80 | 4. Show the tools list 81 | 82 | ``` 83 | DDKitSwift.show() 84 | ``` 85 | 86 | 5. Hide the tools popup 87 | 88 | ``` 89 | DDKitSwift.hide() 90 | ``` 91 | 92 | 6. Close the tools popup 93 | 94 | ``` 95 | DDKitSwift.close() 96 | ``` 97 | 98 | ## Advanced Operations 99 | 100 | Advanced operations provide a way to integrate personalized plugins. The process remains simple, with the additional step of self-registration compared to direct default integration. 101 | 102 | ## Custom Plugin Integration 103 | 104 | `DDKitSwift` comes with a set of pre-installed default functions and supports custom plugin integration. Simply import the corresponding library and register it in the `AppDelegate` startup function. 105 | 106 | ## Developing Custom Plugins 107 | 108 | If you need to develop custom plugins, implement the `DDKitSwiftPluginProtocol`. Then call the `DDKitSwift.regist(plugin: )` function to automatically load and display the plugin. 109 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcodeproj/project.xcworkspace/xcuserdata/damon.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift.xcodeproj/project.xcworkspace/xcuserdata/damon.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /example/DDKitSwift.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DDKitSwift.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 4 11 | 12 | ZXKit.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 5 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcworkspace/xcuserdata/damon.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/DDKitSwift.xcworkspace/xcuserdata/damon.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift.xcworkspace/xcuserdata/damon.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /example/DDKitSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | let vc = ViewController() 18 | window?.rootViewController = vc 19 | window?.makeKeyAndVisible() 20 | return true 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/DDFileBrowser.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "DDFileBrowser.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/DDFileBrowser.imageset/DDFileBrowser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/DDFileBrowser.imageset/DDFileBrowser.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/DDUserDefaultManager.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "DDUserDefaultManager.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/DDUserDefaultManager.imageset/DDUserDefaultManager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/DDUserDefaultManager.imageset/DDUserDefaultManager.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_close@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_close.imageset/icon_close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_close.imageset/icon_close@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_home.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_home@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_home.imageset/icon_home@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_home.imageset/icon_home@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_list.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_list@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_list.imageset/icon_list@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_list.imageset/icon_list@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_notice.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_notice@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_notice.imageset/icon_notice@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_notice.imageset/icon_notice@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_search@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_search.imageset/icon_search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_search.imageset/icon_search@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_setting.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_setting@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_setting.imageset/icon_setting@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_setting.imageset/icon_setting@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "icon_share@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/icon_share.imageset/icon_share@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/icon_share.imageset/icon_share@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "log_icon_close.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_close.imageset/log_icon_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/log_icon_close.imageset/log_icon_close.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_scale.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "log_icon_scale.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_scale.imageset/log_icon_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/log_icon_scale.imageset/log_icon_scale.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_subtract.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "log_icon_subtract.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/log_icon_subtract.imageset/log_icon_subtract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/log_icon_subtract.imageset/log_icon_subtract.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/logger_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "logger_logo@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/logger_logo.imageset/logger_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/logger_logo.imageset/logger_logo@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/zx_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "zx_logo@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/DDKitSwift/Assets.xcassets/zx_logo.imageset/zx_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/DDKitSwift/Assets.xcassets/zx_logo.imageset/zx_logo@3x.png -------------------------------------------------------------------------------- /example/DDKitSwift/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 | -------------------------------------------------------------------------------- /example/DDKitSwift/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 | -------------------------------------------------------------------------------- /example/DDKitSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | DDKitSwift 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIApplicationSupportsIndirectInputEvents 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/DDKitSwift/PluginDemo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PluginDemo.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | class PluginDemo: NSObject { 11 | var isPluginRunning = true 12 | } 13 | 14 | extension PluginDemo: DDKitSwiftPluginProtocol { 15 | 16 | var pluginIdentifier: String { 17 | return "com.zxkit.pluginDemo" 18 | } 19 | 20 | var pluginIcon: UIImage? { 21 | return UIImage(named: "DDFileBrowser") 22 | } 23 | 24 | var pluginTitle: String { 25 | return "插件测试" 26 | } 27 | 28 | var pluginType: DDKitSwiftPluginType { 29 | return .ui 30 | } 31 | 32 | func start() { 33 | print("点击开始使用该插件") 34 | isPluginRunning = true 35 | } 36 | 37 | var isRunning: Bool { 38 | return isPluginRunning 39 | } 40 | 41 | func stop() { 42 | print("插件停止运行") 43 | isPluginRunning = false 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /example/DDKitSwift/PluginDemo2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PluginDemo2.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | class PluginDemo2: NSObject { 11 | 12 | } 13 | 14 | extension PluginDemo2: DDKitSwiftPluginProtocol { 15 | var pluginIdentifier: String { 16 | return "com.zxkit.pluginDemo2" 17 | } 18 | 19 | var pluginIcon: UIImage? { 20 | return UIImage(named: "zxkit2") 21 | } 22 | 23 | var pluginTitle: String { 24 | return "插件" 25 | } 26 | 27 | var pluginType: DDKitSwiftPluginType { 28 | return .data 29 | } 30 | 31 | func start() { 32 | print("点击开始使用该插件2222222") 33 | } 34 | 35 | var isRunning: Bool { 36 | return true 37 | } 38 | 39 | func stop() { 40 | print("该插件为系统插件,不能停止运行") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/DDKitSwift/PluginDemo3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PluginDemo3.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | class PluginDemo3: NSObject { 11 | 12 | } 13 | 14 | extension PluginDemo3: DDKitSwiftPluginProtocol { 15 | var pluginIdentifier: String { 16 | return "com.zxkit.pluginDemo3" 17 | } 18 | 19 | var pluginIcon: UIImage? { 20 | return UIImage(named: "DDUserDefaultManager") 21 | } 22 | 23 | var pluginTitle: String { 24 | return "其他" 25 | } 26 | 27 | var pluginType: DDKitSwiftPluginType { 28 | return .other 29 | } 30 | 31 | func start() { 32 | print("点击开始使用该插件") 33 | } 34 | 35 | var isRunning: Bool { 36 | return false 37 | } 38 | 39 | func stop() { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/DDKitSwift/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | import DDLoggerSwift 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | //regist 16 | DDKitSwift.regist(plugin: PluginDemo()) 17 | //第二种 18 | DDKitSwift.regist(plugin: PluginDemo2()) 19 | //other 20 | DDKitSwift.regist(plugin: PluginDemo3()) 21 | 22 | self.createUI() 23 | 24 | printError("error") 25 | printError("error") 26 | printError("error") 27 | } 28 | 29 | func createUI() { 30 | self.view.backgroundColor = UIColor.white 31 | let button = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 50)) 32 | button.setTitle("open debug tool", for: .normal) 33 | button.backgroundColor = UIColor.red 34 | self.view.addSubview(button) 35 | button.addTarget(self, action: #selector(_click), for: .touchUpInside) 36 | 37 | let button3 = UIButton(frame: CGRect(x: 100, y: 300, width: 200, height: 50)) 38 | button3.setTitle("change float button", for: .normal) 39 | button3.backgroundColor = UIColor.red 40 | self.view.addSubview(button3) 41 | button3.addTarget(self, action: #selector(_updateItem), for: .touchUpInside) 42 | 43 | } 44 | 45 | @objc func _click() { 46 | DDKitSwift.show() 47 | } 48 | 49 | @objc func _updateItem() { 50 | let config = DDPluginItemConfig.text(title: NSAttributedString(string: "ttt"), backgroundColor: UIColor.white) 51 | DDKitSwift.updateListItem(plugin: PluginDemo(), config: config) 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /example/DDKitSwift/de.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/de.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/es.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/es.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/fr.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/fr.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ja.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ja.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ko.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ko.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ru.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/ru.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/th.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/th.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/zh-Hant.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/DDKitSwift/zh-Hant.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | target 'DDKitSwift' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for DDKitSwift 9 | pod 'DDUtils/ui', '~> 5' 10 | pod 'DDUtils/utils', '~> 5' 11 | pod 'DDLoggerSwift', '~> 5' 12 | end 13 | -------------------------------------------------------------------------------- /example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - DDLoggerSwift (5.3.1): 3 | - DDLoggerSwift/core (= 5.3.1) 4 | - DDLoggerSwift/core (5.3.1): 5 | - DDUtils/ui (~> 5) 6 | - DDUtils/utils (~> 5) 7 | - DDUtils/core (5.0.13) 8 | - DDUtils/ui (5.0.13): 9 | - DDUtils/core 10 | - DDUtils/utils (5.0.13): 11 | - DDUtils/core 12 | 13 | DEPENDENCIES: 14 | - DDLoggerSwift (~> 5) 15 | - DDUtils/ui (~> 5) 16 | - DDUtils/utils (~> 5) 17 | 18 | SPEC REPOS: 19 | trunk: 20 | - DDLoggerSwift 21 | - DDUtils 22 | 23 | SPEC CHECKSUMS: 24 | DDLoggerSwift: c7c8776b2e56c741ef3c3de8cfaa3eadb2fcf813 25 | DDUtils: 9d1dab6514cbe6687348bde7ea0f6f2187b55222 26 | 27 | PODFILE CHECKSUM: 9adc178184525feb192ce1c94c0dd33c7c9b4ff9 28 | 29 | COCOAPODS: 1.16.2 30 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Damon 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 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/README.md: -------------------------------------------------------------------------------- 1 | # DDLoggerSwift 2 | 3 | ![](https://img.shields.io/badge/CocoaPods-supported-brightgreen) ![](https://img.shields.io/badge/Swift-5.0-brightgreen) ![](https://img.shields.io/badge/License-MIT-brightgreen) ![](https://img.shields.io/badge/version-iOS12.0-brightgreen) 4 | 5 | ### [中文文档](https://dongge.org/blog/1305.html) 6 | 7 | **DDLoggerSwift** is an iOS library that displays log output as a floating overlay on the screen. It allows easy logging and supports log file sharing and uploading, making it convenient for debugging on a real device without an Xcode connection. Users can share and filter logs effortlessly. 8 | 9 | This project uses **SQLite** for efficient log storage while ensuring insertion order. It does not affect UI performance or interactions, ensuring high runtime efficiency.Automatically converts `Array` and `Dictionary` into JSON strings for display. 10 | 11 | 12 | |Preview GIF picture|Xcode debug GIF| 13 | |----|----| 14 | |![](./readmeResources/preview.gif)|![](./readmeResources/debug.gif)| 15 | 16 | 17 | ## **1. Installation** 18 | 19 | You can install **DDLoggerSwift** using **CocoaPods** or manually by downloading the source files and adding them to your project. 20 | 21 | ### **1.1 CocoaPods Installation** 22 | Add the following line to your `Podfile` and run `pod install`: 23 | ```ruby 24 | pod 'DDLoggerSwift' 25 | ``` 26 | 27 | ### **1.2 Manual Installation** 28 | Drag and drop the files from the `pod` folder into your project. 29 | 30 | --- 31 | 32 | ## **2. Usage** 33 | 34 | ### **1. Import the Framework** 35 | ```swift 36 | import DDLoggerSwift 37 | ``` 38 | 39 | ### **2. Show the Floating Log Window** 40 | ```swift 41 | DDLoggerSwift.show() 42 | ``` 43 | 44 | ### **3. Log Output** 45 | 46 | There are **five types of log outputs**, each with different font colors. 47 | 48 | ```swift 49 | printDebug(log) // Debug output, only visible in Xcode, not stored in the log database. 50 | 51 | printLog(log) // Logs displayed in green. 52 | 53 | printWarn(log) // Logs displayed in yellow. 54 | 55 | printError(log) // Logs displayed in red. 56 | 57 | printPrivacy(log) // Outputs encrypted data. Encryption details can be found in the encryption documentation. 58 | ``` 59 | 60 | ### **4. Log Output Format** 61 | 62 | ``` 63 | ✅ [2025-03-19T03:11:59Z] [INFO] File: TalkViewModel.swift | Line: 730 | Function: _bindRequest() | 64 | --------------------------------- 65 | Log message 66 | 67 | ⚠️ [2025-03-19T03:11:59Z] [WARN] File: TalkViewModel.swift | Line: 730 | Function: _bindRequest() | 68 | --------------------------------- 69 | Warning message 70 | 71 | ❌ [2025-03-19T03:11:59Z] [ERROR] File: TalkViewModel.swift | Line: 730 | Function: _bindRequest() | 72 | --------------------------------- 73 | Error message 74 | 75 | ⛔️ [2025-03-19T03:11:59Z] [PRIVACY] File: TalkViewModel.swift | Line: 730 | Function: _bindRequest() | 76 | --------------------------------- 77 | AAuKjIm5hC2jiPqz7OKHAngWspeACyWZufDguqdOcugituhWV8jnbr/6SHYoK0/9 78 | 79 | 💜 [2025-03-19T03:11:59Z] [DEBUG] File: TalkViewModel.swift | Line: 730 | Function: _bindRequest() | 80 | --------------------------------- 81 | Test output, not stored in the database by default. 82 | ``` 83 | 84 | ## III. Advanced Usage 85 | 86 | For advanced features such as file encryption, custom formats, file retrieval, and sharing, please refer to the wiki for a complete list and detailed instructions. 87 | 88 | **[Wiki](https://github.com/DamonHu/DDLoggerSwift/wiki)** 89 | 90 | 91 | ## IV. Log viewing client 92 | 93 | This library stores log information using SQLite. You can use any generic SQLite viewer or the [DDLoggerClient](https://github.com/DamonHu/DDLoggerClient) client to view the SQLite files exported by DDLoggerSwift. 94 | 95 | The client is developed using SwiftUI and is specifically designed to parse logs from DDLoggerSwift, making log viewing more convenient. 96 | 97 | 98 | ![](./readmeResources/Jietu20220731-212644.png) 99 | 100 | 101 | ## License 102 | 103 | The project is based on the MIT License 104 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/DDLoggerSwiftFloatWindow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftFloatWindow.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2021/4/28. 6 | // Copyright © 2021 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import DDUtils 11 | 12 | class DDLoggerSwiftFloatWindow: UIWindow { 13 | 14 | @available(iOS 13.0, *) 15 | override init(windowScene: UIWindowScene) { 16 | super.init(windowScene: windowScene) 17 | self._initVC() 18 | self._createUI() 19 | } 20 | 21 | override init(frame: CGRect) { 22 | super.init(frame: frame) 23 | self._initVC() 24 | self._createUI() 25 | } 26 | 27 | required init?(coder: NSCoder) { 28 | fatalError("init(coder:) has not been implemented") 29 | } 30 | 31 | lazy var mButton: UIButton = { 32 | let button = UIButton(type: .custom) 33 | button.translatesAutoresizingMaskIntoConstraints = false 34 | button.backgroundColor = UIColor.dd.color(hexValue: 0x5dae8b) 35 | button.setTitle("Z".ZXLocaleString, for: UIControl.State.normal) 36 | button.titleLabel?.font = UIFont.systemFont(ofSize: 23, weight: .bold) 37 | button.layer.borderColor = UIColor.dd.color(hexValue: 0xffffff).cgColor 38 | button.dd.addLayerShadow(color: UIColor.dd.color(hexValue: 0x333333), offset: CGSize(width: 2, height: 2), radius: 4, cornerRadius: 30) 39 | button.layer.borderWidth = 4.0 40 | button.addTarget(self, action: #selector(_show), for: UIControl.Event.touchUpInside) 41 | button.frame = CGRect(x: 0, y: 0, width: 60, height: 60) 42 | 43 | let pan = UIPanGestureRecognizer(target: self, action: #selector(_touchMove(p:))) 44 | button.addGestureRecognizer(pan) 45 | return button 46 | }() 47 | 48 | } 49 | 50 | private extension DDLoggerSwiftFloatWindow { 51 | 52 | func _initVC() { 53 | self.rootViewController = UIViewController() 54 | self.windowLevel = UIWindow.Level.alert 55 | self.isUserInteractionEnabled = true 56 | } 57 | 58 | @objc func _show() { 59 | DDLoggerSwift.show() 60 | } 61 | 62 | func _createUI() { 63 | guard let rootViewController = self.rootViewController else { 64 | return 65 | } 66 | rootViewController.view.addSubview(mButton) 67 | mButton.leftAnchor.constraint(equalTo: rootViewController.view.leftAnchor).isActive = true 68 | mButton.rightAnchor.constraint(equalTo: rootViewController.view.rightAnchor).isActive = true 69 | mButton.topAnchor.constraint(equalTo: rootViewController.view.topAnchor).isActive = true 70 | mButton.bottomAnchor.constraint(equalTo: rootViewController.view.bottomAnchor).isActive = true 71 | } 72 | 73 | @objc private func _touchMove(p:UIPanGestureRecognizer) { 74 | guard let window = DDUtils.shared.getCurrentNormalWindow() else { return } 75 | let panPoint = p.location(in: window) 76 | //跟随手指拖拽 77 | if p.state == .changed { 78 | self.center = CGPoint(x: panPoint.x, y: panPoint.y) 79 | p.setTranslation(CGPoint.zero, in: self) 80 | } 81 | //弹回边界 82 | if p.state == .ended || p.state == .cancelled { 83 | var x: CGFloat = 50 84 | if panPoint.x > (window.bounds.size.width) / 2.0 { 85 | x = window.bounds.size.width - 50 86 | } 87 | let y = min(max(130, panPoint.y), window.bounds.size.height - 140) 88 | p.setTranslation(CGPoint.zero, in: self) 89 | UIView.animate(withDuration: 0.35) { 90 | self.center = CGPoint(x: x, y: y) 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/LogContent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogContent.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2019/6/28. 6 | // Copyright © 2019 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import DDUtils 11 | 12 | //输出内容需要遵循的协议 13 | public protocol LogContent { 14 | var logStringValue: String { get } 15 | } 16 | 17 | ///默认的几个输出类型 18 | extension Dictionary: LogContent { 19 | public var logStringValue: String { 20 | if JSONSerialization.isValidJSONObject(self) { 21 | let data = try? JSONSerialization.data(withJSONObject: self, options:JSONSerialization.WritingOptions.prettyPrinted) 22 | if let data = data { 23 | let string = String(data: data, encoding: String.Encoding.utf8) ?? "\(self)" 24 | return string 25 | } else { 26 | return "\(self)" 27 | } 28 | } else { 29 | return "\(self)" 30 | } 31 | } 32 | } 33 | 34 | extension Array: LogContent { 35 | public var logStringValue: String { 36 | if JSONSerialization.isValidJSONObject(self) { 37 | let data = try? JSONSerialization.data(withJSONObject: self, options:JSONSerialization.WritingOptions.prettyPrinted) 38 | if let data = data { 39 | let string = String(data: data, encoding: String.Encoding.utf8) ?? "\(self)" 40 | return string 41 | } else { 42 | return "\(self)" 43 | } 44 | } else { 45 | return "\(self)" 46 | } 47 | } 48 | } 49 | 50 | extension String: LogContent { 51 | public var logStringValue: String { 52 | return self 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_analyse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_analyse.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_back.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_copy.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_decrypt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_decrypt.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_delete.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_exit.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_hide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_hide.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_normal_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_normal_back.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_scale.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_scroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_scroll.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_search.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_share.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/icon_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/icon_upload.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_close.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_scale.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_subtract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/example/Pods/DDLoggerSwift/pod/assets/icon/log_icon_subtract.png -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/localizable/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDLoggerSwift 4 | 5 | Created by Damon on 2019/6/24. 6 | Copyright © 2019 Damon. All rights reserved. 7 | */ 8 | "DDLoggerSwift: Click Log To Copy" = "DDLoggerSwift: Click Log To Copy"; 9 | "Please select the log to share" = "Please select the log to share"; 10 | "Please select the log to upload" = "Please select the log to upload"; 11 | "Please select the log" = "Please select the log"; 12 | "Clean Log" = "Clean Log"; 13 | "Scale" = "Scale"; 14 | "Hide" = "Hide"; 15 | "Exit" = "Exit"; 16 | "Share" = "Share"; 17 | "Auto scroll" = "Auto scroll"; 18 | "Log has been copied" = "Log has been copied"; 19 | "Log filter and search" = "Log filter and search"; 20 | "Decrypt" = "Decrypt"; 21 | "Enter password to view" = "Enter password to view"; 22 | "The password requires 32 characters" = "The password requires 32 characters"; 23 | "Password is not set" = "Password is not set"; 24 | "Password Error" = "Password Error"; 25 | "result: 0" = "result: 0"; 26 | "Previous" = "Pre"; 27 | "Next" = "Next"; 28 | "Logger" = "Logger"; 29 | "The float button already exists" = "The float button already exists"; 30 | "System basic plug-in cannot be stopped" = "System basic plug-in cannot be stopped"; 31 | "Analyse" = "Analyse"; 32 | "Back" = "Back"; 33 | "Upload" = "Upload"; 34 | "Search" = "Search"; 35 | "Search Today's Log" = "Search Today's Log"; 36 | "Filter" = "Filter"; 37 | "Scroll" = "Scroll"; 38 | "More" = "More"; 39 | "Done" = "Done"; 40 | "Confirm" = "Confirm"; 41 | "Cancel" = "Cancel"; 42 | "LogFile count" = "LogFile count"; 43 | "LogFile total size" = "LogFile total size"; 44 | "Number of Today's Logs" = "Number of Today's Logs"; 45 | "Invalid encryption" = "Invalid encryption"; 46 | "History" = "History"; 47 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/assets/localizable/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDLoggerSwift 4 | 5 | Created by Damon on 2019/6/24. 6 | Copyright © 2019 Damon. All rights reserved. 7 | */ 8 | "DDLoggerSwift: Click Log To Copy" = "DDLoggerSwift: 点击对应日志可快速复制"; 9 | "Please select the log to share" = "请选择要分享的日志"; 10 | "Please select the log to upload" = "请选择要上传的日志"; 11 | "Please select the log" = "请选择日志文件"; 12 | "Clean Log" = "清除Log"; 13 | "Scale" = "伸缩"; 14 | "Hide" = "隐藏"; 15 | "Exit" = "退出"; 16 | "Share" = "分享Log"; 17 | "Auto scroll" = "自动滚动"; 18 | "Log has been copied" = "日志已拷贝到剪切板"; 19 | "Log filter and search" = "内容过滤查找"; 20 | "Decrypt" = "解密"; 21 | "Enter password to view" = "输入密码查看加密数据"; 22 | "The password requires 32 characters" = "密码设置长度错误,需要32个字符"; 23 | "Password Error" = "密码错误"; 24 | "Password is not set" = "密码未设置"; 25 | "result: 0" = "0条结果"; 26 | "Previous" = "上条"; 27 | "Next" = "下条"; 28 | "Logger" = "日志"; 29 | "The float button already exists" = "悬浮按钮已存在"; 30 | "System basic plug-in cannot be stopped" = "系统基础插件不能停止"; 31 | "Analyse" = "分析"; 32 | "Back" = "返回"; 33 | "Upload" = "上传"; 34 | "Search" = "搜索"; 35 | "Search Today's Log" = "搜索今日日志"; 36 | "Filter" = "筛选"; 37 | "Scroll" = "滚动"; 38 | "More" = "更多"; 39 | "Done" = "完成"; 40 | "Confirm" = "确定"; 41 | "Cancel" = "取消"; 42 | "LogFile count" = "日志文件数量"; 43 | "LogFile total size" = "日志文件总大小"; 44 | "Number of Today's Logs" = "今日日志数量"; 45 | "Invalid encryption" = "加密无效"; 46 | "History" = "历史文件"; 47 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/model/DDLoggerSwiftItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftItem.swift 3 | // DDLoggerSwiftSwift 4 | // 5 | // Created by Damon on 2020/6/10. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import DDUtils 11 | 12 | let t = Date() 13 | 14 | enum Section: CaseIterable { 15 | case main 16 | } 17 | ///log的内容 18 | public class DDLoggerSwiftItem { 19 | let identifier = UUID() //用于hash计算 20 | var databaseID: Int = 0 //存在database的id 21 | public var mLogItemType = DDLogType.debug //log类型 22 | public var mLogFile: String = "" //log调用的文件 23 | public var mLogLine: String = "" //log调用的行数 24 | public var mLogFunction: String = "" //log调用的函数名 25 | public var mLogContent: Any? = "DDLoggerSwift: Click Log To Copy" //log的内容 26 | public var mCreateDate = t //log日期 27 | 28 | private var mCurrentHighlightString = "" //当前需要高亮的字符串 29 | private var mCacheHasHighlightString = false //上次查询是否包含高亮的字符串 30 | private var mCacheHighlightCompleteString = NSMutableAttributedString(string: "") //上次包含高亮支付的富文本 31 | } 32 | 33 | public extension DDLoggerSwiftItem { 34 | func icon() -> String { 35 | switch mLogItemType { 36 | case .info: 37 | return "✅" 38 | case .warn: 39 | return "⚠️" 40 | case .error: 41 | return "❌" 42 | case .privacy: 43 | return "⛔️" 44 | default: 45 | return "💜" 46 | } 47 | } 48 | 49 | func level() -> String { 50 | switch mLogItemType { 51 | case .info: 52 | return "INFO" 53 | case .warn: 54 | return "WARN" 55 | case .error: 56 | return "ERROR" 57 | case .privacy: 58 | return "PRIVACY" 59 | default: 60 | return "DEBUG" 61 | } 62 | } 63 | 64 | //LogContent转字符串格式化 65 | func getLogContent() -> String { 66 | var contentString = "" 67 | if let mContent = mLogContent { 68 | if mContent is LogContent { 69 | contentString = (mContent as! LogContent).logStringValue 70 | } else { 71 | contentString = "\(mContent)" 72 | } 73 | if self.mLogItemType == .privacy { 74 | contentString = contentString.dd.aesCBCEncrypt(password: DDLoggerSwift.privacyLogPassword, ivString: DDLoggerSwift.privacyLogIv, encodeType: DDLoggerSwift.privacyResultEncodeType) ?? "Invalid encryption".ZXLocaleString 75 | } 76 | } 77 | return contentString 78 | } 79 | 80 | //获取完整的输出内容 81 | func getFullContentString() -> String { 82 | //日期 83 | let dateStr = DDLoggerSwift.dateFormatterISO8601.string(from: mCreateDate) 84 | //所有的内容 85 | return "\(self.icon())" + " " + "[\(dateStr)]" + " " + "[\(self.level())]" + " " + "File: \(mLogFile) | Line: \(mLogLine) | Function: \(mLogFunction) " + "\n---------------------------------\n" + self.getLogContent() + "\n" 86 | } 87 | 88 | //根据需要高亮内容查询组装高亮内容 89 | func getHighlightAttributedString(contentString: String, highlightString: String, complete:(Bool, NSAttributedString)->Void) -> Void { 90 | if highlightString.isEmpty { 91 | //空的直接返回 92 | let newString = NSMutableAttributedString(string: contentString, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 13)]) 93 | self.mCacheHighlightCompleteString = newString 94 | self.mCacheHasHighlightString = false 95 | complete(self.mCacheHasHighlightString, newString) 96 | } else if highlightString == self.mCurrentHighlightString{ 97 | //和上次高亮相同,直接用之前的回调 98 | complete(self.mCacheHasHighlightString, self.mCacheHighlightCompleteString) 99 | } else { 100 | self.mCurrentHighlightString = highlightString 101 | let newString = NSMutableAttributedString(string: contentString, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 13)]) 102 | let regx = try? NSRegularExpression(pattern: highlightString, options: NSRegularExpression.Options.caseInsensitive) 103 | if let searchRegx = regx { 104 | self.mCacheHasHighlightString = false; 105 | searchRegx.enumerateMatches(in: contentString, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: contentString.count)) { (result: NSTextCheckingResult?, flag, stop) in 106 | newString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor(red: 255.0/255.0, green: 0.0, blue: 0.0, alpha: 1.0), range: result?.range ?? NSRange(location: 0, length: 0)) 107 | if result != nil { 108 | self.mCacheHasHighlightString = true 109 | } 110 | self.mCacheHighlightCompleteString = newString 111 | complete(self.mCacheHasHighlightString, newString) 112 | } 113 | } else { 114 | self.mCacheHighlightCompleteString = newString 115 | self.mCacheHasHighlightString = false 116 | complete(self.mCacheHasHighlightString, newString) 117 | } 118 | } 119 | } 120 | } 121 | 122 | extension DDLoggerSwiftItem: Hashable { 123 | public func hash(into hasher: inout Hasher) { 124 | hasher.combine(identifier) 125 | } 126 | 127 | public static func ==(lhs: DDLoggerSwiftItem, rhs: DDLoggerSwiftItem) -> Bool { 128 | return lhs.identifier == rhs.identifier 129 | } 130 | 131 | func contains(query: String?) -> Bool { 132 | guard let query = query else { return true } 133 | guard !query.isEmpty else { return true } 134 | return self.getFullContentString().contains(query) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/model/DDLoggerSwiftTableCellModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftTableCellModel.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2025/2/21. 6 | // Copyright © 2025 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DDLoggerSwiftTableCellModel: NSObject { 12 | var logItem = DDLoggerSwiftItem() 13 | var isCollapse = false 14 | 15 | convenience init(model: DDLoggerSwiftItem) { 16 | self.init() 17 | self.logItem = model 18 | self.isCollapse = model.getFullContentString().count > DDLoggerSwift.cellDisplayCount 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/view/DDLoggerSwiftFilterTypeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftFilterTypeView.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2023/4/9. 6 | // Copyright © 2023 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol DDLoggerSwiftFilterTypeViewDelegate: AnyObject { 12 | func filterSelected(filterType: DDLogType?) 13 | } 14 | 15 | class DDLoggerSwiftFilterTypeView: UIView { 16 | private let dataList = ["none", "debug", "info", "warn", "error", "privacy"] 17 | weak var delegate: DDLoggerSwiftFilterTypeViewDelegate? 18 | 19 | override init(frame: CGRect) { 20 | super.init(frame: frame) 21 | self._createUI() 22 | } 23 | 24 | required init?(coder: NSCoder) { 25 | fatalError("init(coder:) has not been implemented") 26 | } 27 | 28 | //MARK: UI 29 | private lazy var mTableView: UITableView = { 30 | let tableView = UITableView(frame: CGRect.zero, style: UITableView.Style.plain) 31 | if #available(iOS 15.0, *) { 32 | tableView.sectionHeaderTopPadding = 0 33 | } 34 | tableView.translatesAutoresizingMaskIntoConstraints = false 35 | tableView.scrollsToTop = true 36 | tableView.dataSource = self 37 | tableView.delegate = self 38 | tableView.showsHorizontalScrollIndicator = false 39 | tableView.showsVerticalScrollIndicator = true 40 | tableView.keyboardDismissMode = UIScrollView.KeyboardDismissMode.onDrag 41 | tableView.backgroundColor = UIColor.dd.color(hexValue: 0xfcfcfc) 42 | tableView.separatorColor = UIColor.dd.color(hexValue: 0xcccccc) 43 | tableView.separatorInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) 44 | tableView.separatorStyle = UITableViewCell.SeparatorStyle.singleLine 45 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell") 46 | return tableView 47 | }() 48 | 49 | } 50 | 51 | extension DDLoggerSwiftFilterTypeView { 52 | func _createUI() { 53 | self.addSubview(mTableView) 54 | mTableView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true 55 | mTableView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true 56 | mTableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true 57 | mTableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true 58 | } 59 | } 60 | 61 | extension DDLoggerSwiftFilterTypeView: UITableViewDelegate, UITableViewDataSource { 62 | //MARK:UITableViewDelegate 63 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 64 | return self.dataList.count 65 | } 66 | 67 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 68 | let loggerItem = self.dataList[indexPath.row] 69 | 70 | let loggerCell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")! 71 | loggerCell.backgroundColor = UIColor.clear 72 | loggerCell.selectionStyle = .none 73 | loggerCell.textLabel?.text = loggerItem 74 | return loggerCell 75 | } 76 | 77 | public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 78 | if let delegate = delegate { 79 | switch indexPath.row { 80 | case 0: 81 | delegate.filterSelected(filterType: nil) 82 | case 1: 83 | delegate.filterSelected(filterType: .debug) 84 | case 2: 85 | delegate.filterSelected(filterType: .info) 86 | case 3: 87 | delegate.filterSelected(filterType: .warn) 88 | case 4: 89 | delegate.filterSelected(filterType: .error) 90 | case 5: 91 | delegate.filterSelected(filterType: .privacy) 92 | default: 93 | break 94 | } 95 | 96 | } 97 | } 98 | 99 | func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { 100 | return 40 101 | } 102 | 103 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 104 | return 40 105 | } 106 | 107 | func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { 108 | return 0.1 109 | } 110 | 111 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 112 | return 0.1 113 | } 114 | 115 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 116 | return UIView() 117 | } 118 | 119 | func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat { 120 | return 0.1 121 | } 122 | 123 | func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 124 | return 0.1 125 | } 126 | 127 | func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { 128 | return UIView() 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/view/DDLoggerSwiftMenuCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftMenuCollectionViewCell.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2021/5/21. 6 | // Copyright © 2021 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct DDLoggerSwiftMenuCollectionViewCellModel { 12 | var title = "" 13 | var image: UIImage? 14 | var isSwitchItem: Bool? 15 | } 16 | 17 | class DDLoggerSwiftMenuCollectionViewCell: UICollectionViewCell { 18 | var switchSubject: ((_ index: Int, _ isOn: Bool) -> Void)? 19 | 20 | override init(frame: CGRect) { 21 | super.init(frame: frame) 22 | self._createUI() 23 | } 24 | 25 | required init?(coder: NSCoder) { 26 | super.init(coder: coder) 27 | } 28 | 29 | func updateUI(model: DDLoggerSwiftMenuCollectionViewCellModel) { 30 | self.mTitleLabel.text = model.title 31 | self.mImageView.image = model.image 32 | if let isSwitch = model.isSwitchItem { 33 | self.mImageView.isHidden = true 34 | self.mSwitchView.isHidden = false 35 | self.mSwitchView.setOn(isSwitch, animated: true) 36 | } else { 37 | self.mImageView.isHidden = false 38 | self.mSwitchView.isHidden = true 39 | } 40 | } 41 | 42 | //MARK: UI 43 | lazy var mTitleLabel: UILabel = { 44 | let tLabel = UILabel() 45 | tLabel.translatesAutoresizingMaskIntoConstraints = false 46 | tLabel.textAlignment = NSTextAlignment.center 47 | tLabel.numberOfLines = 3 48 | tLabel.font = UIFont.systemFont(ofSize: 13) 49 | tLabel.textColor = UIColor.dd.color(hexValue: 0xffffff) 50 | return tLabel 51 | }() 52 | 53 | lazy var mImageView: UIImageView = { 54 | let tImageView = UIImageView() 55 | tImageView.translatesAutoresizingMaskIntoConstraints = false 56 | return tImageView 57 | }() 58 | 59 | lazy var mSwitchView: UISwitch = { 60 | let switchView = UISwitch() 61 | switchView.addTarget(self, action: #selector(_switchChange(target:)), for: .valueChanged) 62 | switchView.translatesAutoresizingMaskIntoConstraints = false 63 | switchView.isHidden = true 64 | switchView.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) 65 | return switchView 66 | }() 67 | } 68 | 69 | private extension DDLoggerSwiftMenuCollectionViewCell { 70 | func _createUI() { 71 | self.backgroundColor = UIColor.dd.color(hexValue: 0x323764, alpha: 0.5) 72 | self.layer.cornerRadius = 15 73 | self.contentView.addSubview(mImageView) 74 | mImageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true 75 | mImageView.bottomAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0).isActive = true 76 | mImageView.widthAnchor.constraint(equalToConstant: 26).isActive = true 77 | mImageView.heightAnchor.constraint(equalToConstant: 26).isActive = true 78 | 79 | self.contentView.addSubview(mSwitchView) 80 | mSwitchView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true 81 | mSwitchView.bottomAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0).isActive = true 82 | 83 | self.contentView.addSubview(mTitleLabel) 84 | mTitleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 10).isActive = true 85 | mTitleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -10).isActive = true 86 | mTitleLabel.topAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 10).isActive = true 87 | } 88 | 89 | @objc func _switchChange(target: UISwitch) { 90 | if let switchSubject = self.switchSubject { 91 | switchSubject(self.tag, target.isOn) 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/view/DDLoggerSwiftMenuView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftMenuView.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2021/5/21. 6 | // Copyright © 2021 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DDLoggerSwiftMenuView: UIView { 12 | var mCollectionList = [DDLoggerSwiftMenuCollectionViewCellModel]() 13 | var clickSubject: ((_ index: Int) -> Void)? 14 | override init(frame: CGRect) { 15 | super.init(frame: frame) 16 | self._createUI() 17 | self._loadData() 18 | } 19 | 20 | required init?(coder: NSCoder) { 21 | fatalError("init(coder:) has not been implemented") 22 | } 23 | 24 | lazy var mCollectionView: UICollectionView = { 25 | let tCollectionViewLayout = UICollectionViewFlowLayout() 26 | tCollectionViewLayout.scrollDirection = UICollectionView.ScrollDirection.vertical 27 | tCollectionViewLayout.itemSize = CGSize(width: 100, height: 100) 28 | tCollectionViewLayout.minimumLineSpacing = 5 29 | tCollectionViewLayout.minimumInteritemSpacing = 5 30 | tCollectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) 31 | let tCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: tCollectionViewLayout) 32 | tCollectionView.translatesAutoresizingMaskIntoConstraints = false 33 | tCollectionView.backgroundColor = UIColor.clear 34 | tCollectionView.dataSource = self 35 | tCollectionView.delegate = self 36 | tCollectionView.isPagingEnabled = false 37 | tCollectionView.showsHorizontalScrollIndicator = false 38 | tCollectionView.register(DDLoggerSwiftMenuCollectionViewCell.self, forCellWithReuseIdentifier: "DDLoggerSwiftMenuCollectionViewCell") 39 | return tCollectionView 40 | }() 41 | } 42 | 43 | private extension DDLoggerSwiftMenuView { 44 | func _createUI() { 45 | self.backgroundColor = UIColor.dd.color(hexValue: 0x272d55, alpha: 0.8) 46 | self.addSubview(mCollectionView) 47 | mCollectionView.topAnchor.constraint(equalTo: self.topAnchor, constant: 80).isActive = true 48 | mCollectionView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true 49 | mCollectionView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true 50 | mCollectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true 51 | } 52 | 53 | func _loadData() { 54 | mCollectionList.removeAll() 55 | var titleList = ["Back".ZXLocaleString, "Share".ZXLocaleString, "Decrypt".ZXLocaleString, "History".ZXLocaleString, "Analyse".ZXLocaleString] 56 | var imageList = [UIImageHDBoundle(named: "icon_back"), UIImageHDBoundle(named: "icon_share"), UIImageHDBoundle(named: "icon_decrypt"), UIImageHDBoundle(named: "icon_search"), UIImageHDBoundle(named: "icon_analyse")] 57 | 58 | if DDLoggerSwift.uploadComplete != nil { 59 | titleList.append("Upload".ZXLocaleString) 60 | imageList.append(UIImageHDBoundle(named: "icon_upload")) 61 | } 62 | 63 | for i in 0.. Int { 74 | return self.mCollectionList.count 75 | } 76 | 77 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 78 | let model = self.mCollectionList[indexPath.item] 79 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DDLoggerSwiftMenuCollectionViewCell", for: indexPath) as! DDLoggerSwiftMenuCollectionViewCell 80 | cell.updateUI(model: model) 81 | cell.tag = indexPath.item 82 | cell.switchSubject = { (tag, isOn) in 83 | 84 | } 85 | return cell 86 | } 87 | 88 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 89 | if let clickSubject = clickSubject { 90 | clickSubject(indexPath.item) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /example/Pods/DDLoggerSwift/pod/view/DDLoggerSwiftTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDLoggerSwiftTableViewCell.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2019/6/24. 6 | // Copyright © 2019 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DDLoggerSwiftTableViewCell: UITableViewCell { 12 | private lazy var mContentLabel: UILabel = { 13 | var label = UILabel() 14 | label.translatesAutoresizingMaskIntoConstraints = false 15 | label.numberOfLines = 0 16 | label.font = UIFont.systemFont(ofSize: 13) 17 | return label 18 | }() 19 | 20 | private lazy var mIDLabel: UILabel = { 21 | var label = UILabel() 22 | label.textColor = UIColor.dd.color(hexValue: 0xcccccc) 23 | label.translatesAutoresizingMaskIntoConstraints = false 24 | label.numberOfLines = 1 25 | label.font = UIFont.systemFont(ofSize: 12) 26 | return label 27 | }() 28 | 29 | override func awakeFromNib() { 30 | super.awakeFromNib() 31 | // Initialization code 32 | } 33 | 34 | override func setSelected(_ selected: Bool, animated: Bool) { 35 | super.setSelected(selected, animated: animated) 36 | 37 | // Configure the view for the selected state 38 | } 39 | 40 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 41 | super.init(style: style, reuseIdentifier: reuseIdentifier) 42 | self._createUI() 43 | } 44 | 45 | required init?(coder: NSCoder) { 46 | super.init(coder: coder) 47 | } 48 | 49 | private func _createUI() -> Void { 50 | self.backgroundColor = UIColor.clear 51 | 52 | self.contentView.addSubview(self.mContentLabel) 53 | self.mContentLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 16).isActive = true 54 | self.mContentLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -16).isActive = true 55 | self.mContentLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 15).isActive = true 56 | self.mContentLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -10).isActive = true 57 | 58 | self.contentView.addSubview(self.mIDLabel) 59 | self.mIDLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -16).isActive = true 60 | self.mIDLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 3).isActive = true 61 | } 62 | 63 | func updateWithLoggerItem(model:DDLoggerSwiftTableCellModel, highlightText:String) { 64 | let loggerItem = model.logItem 65 | self.mIDLabel.text = "#\(loggerItem.databaseID)" 66 | self.mContentLabel.textColor = loggerItem.mLogItemType.textColor() 67 | var contentString = loggerItem.getFullContentString() 68 | if model.isCollapse { 69 | contentString = contentString.dd.subString(rang: NSRange(location: 0, length: DDLoggerSwift.cellDisplayCount)) 70 | } 71 | loggerItem.getHighlightAttributedString(contentString: contentString, highlightString: highlightText) { (hasHighlightStr, hightlightAttributedString) in 72 | if model.isCollapse { 73 | let read = NSAttributedString(string: "Read more", attributes: [NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue, .underlineColor: UIColor.dd.color(hexValue: 0xeeeeee), .foregroundColor: UIColor.dd.color(hexValue: 0xeeeeee)]) 74 | 75 | let attri = NSMutableAttributedString() 76 | attri.append(hightlightAttributedString) 77 | attri.append(NSAttributedString(string: "……\n\n")) 78 | attri.append(read) 79 | self.mContentLabel.attributedText = attri 80 | } else { 81 | self.mContentLabel.attributedText = hightlightAttributedString 82 | } 83 | 84 | // if hasHighlightStr { 85 | // self.contentView.backgroundColor = UIColor.dd.color(hexValue: 0xe58e23) 86 | // } else { 87 | // self.contentView.backgroundColor = UIColor.clear 88 | // } 89 | } 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Damon 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 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/core/DDUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/2. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | open class DDUtils: NSObject { 13 | private static let instance = DDUtils() 14 | open class var shared: DDUtils { 15 | return instance 16 | } 17 | 18 | //缓存的数据 19 | var cacheHomeIndicatorHeight: CGFloat? 20 | var cacheDefaultNavigationBarHeight: CGFloat? 21 | var cacheDefaultTabbarHeight: CGFloat? 22 | } 23 | 24 | public enum ZXMainThreadType { 25 | case `default` //在主线程顺序执行,在其他线程异步回归到主线程(后续操作会优先执行,之后再执行任务,不阻塞界面) 26 | case async //不论是否在主线程,都异步操作 27 | case sync //在主线程顺序执行,在其他线程同步回归到主线程(后续操作等待当前任务完毕之后继续执行,可能会阻塞界面) 28 | } 29 | 30 | public extension DDUtils { 31 | /// 获取class\struct的所有属性 32 | /// - Parameters: 33 | /// - object: 需要获取的属性 34 | /// - debug: 是否输入调试信息 35 | /// - Returns: 属性 36 | func getDictionary(object: Any, debug: Bool = false) -> [String: Any] { 37 | let reflection = Mirror(reflecting: object).children 38 | var dictionary = [String : Any]() 39 | 40 | if debug { 41 | print("--- DDUtils.getDictionary(object:debug:) ---") 42 | } 43 | for (key, value) in reflection { 44 | if let key = key { 45 | if debug { 46 | print("--- \(key) --- \(type(of: value)) --- \(value)") 47 | } 48 | dictionary[key] = value 49 | } 50 | } 51 | return dictionary 52 | } 53 | 54 | /// 主线程执行function 55 | /// - Parameters: 56 | /// - type: ZXMainThreadType 57 | /// case `default` //在主线程顺序执行,在其他线程异步回归到主线程(即在function后面的任务会优先执行,之后再执行function任务,不阻塞界面) 58 | /// case async //不论是否在主线程,都异步操作 (即使当前在主线程,在function后面的任务会优先执行,之后再执行function任务,不阻塞界面) 59 | /// case sync //在主线程顺序执行,在其他线程同步回归到主线程(同一个线程中,function后面的任务会等待function任务完毕之后继续执行,可能会阻塞界面) 60 | /// - function: 执行的函数 61 | func runInMainThread(type: ZXMainThreadType = .default, function: @escaping ()->Void) { 62 | switch type { 63 | case .default: 64 | if Thread.isMainThread { 65 | function() 66 | } else { 67 | DispatchQueue.main.async { 68 | function() 69 | } 70 | } 71 | case .async: 72 | DispatchQueue.main.async { 73 | function() 74 | } 75 | case .sync: 76 | if Thread.isMainThread { 77 | function() 78 | } else { 79 | DispatchQueue.main.sync { 80 | function() 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/core/DDUtilsNameSpace.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtilsNameSpace.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/3. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | //实现命名空间需遵守的协议 12 | public protocol DDUtilsNameSpaceWrappable { 13 | associatedtype WrapperType 14 | var dd: WrapperType { get } 15 | static var dd: WrapperType.Type { get } 16 | } 17 | 18 | public struct DDUtilsNameSpace { 19 | let object: T //存储的实例对象 20 | static var classObject: T.Type { 21 | return T.self 22 | } 23 | internal init(object: T) { 24 | self.object = object 25 | } 26 | } 27 | 28 | //协议默认的实现方式 29 | public extension DDUtilsNameSpaceWrappable { 30 | var dd: DDUtilsNameSpace { 31 | return DDUtilsNameSpace(object: self) 32 | } 33 | 34 | static var dd: DDUtilsNameSpace.Type { 35 | return DDUtilsNameSpace.self 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/ui/DDUtils+AppStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils+AppStore.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2024/5/27. 6 | // Copyright © 2024 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | #if canImport(StoreKit) 11 | import StoreKit 12 | #endif 13 | 14 | public enum DDUtilsOpenAppStoreType { 15 | case app //应用内打开,ios10.3以下无反应 16 | case appStore //跳转到App Store 17 | case auto //ios10.3以上应用内打开,以下跳转到App Store打开 18 | } 19 | 20 | public extension DDUtils { 21 | ///打开软件对应的App Store页面 22 | func openAppStorePage(openType: DDUtilsOpenAppStoreType, appleID: String, completion: ((Bool, Error?) -> Void)? = nil) -> Void { 23 | switch openType { 24 | case .app: 25 | let storeProductVC = SKStoreProductViewController() 26 | storeProductVC.delegate = self 27 | storeProductVC.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier : appleID]) { (success, error) in 28 | if success { 29 | self.getCurrentVC()?.present(storeProductVC, animated: true, completion: { 30 | if let completion = completion { 31 | completion(true, nil) 32 | } 33 | }) 34 | } else { 35 | if let completion = completion { 36 | completion(false, error) 37 | } 38 | } 39 | } 40 | case .appStore: 41 | let url = URL(string: "https://itunes.apple.com/app/id\(appleID)")! 42 | UIApplication.shared.open(url, options: [:]) { success in 43 | if let completion = completion { 44 | completion(success, nil) 45 | } 46 | } 47 | case .auto: 48 | let storeProductVC = SKStoreProductViewController() 49 | storeProductVC.delegate = self 50 | storeProductVC.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier : appleID]) { (success, error) in 51 | if success { 52 | self.getCurrentVC()?.present(storeProductVC, animated: true, completion: { 53 | if let completion = completion { 54 | completion(true, nil) 55 | } 56 | }) 57 | } else { 58 | let url = URL(string: "https://itunes.apple.com/app/id\(appleID)")! 59 | UIApplication.shared.open(url, options: [:]) { success in 60 | if let completion = completion { 61 | completion(success, nil) 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | /// 打开软件对应的评分页面 70 | /// - Parameters: 71 | /// - openType: 打开评分页面的类型 72 | /// - appleID: 打开的appid 73 | /// - openWriteAction: 是否直接到输入评论的页面,仅对跳转到appStore有效 74 | func openAppStoreReviewPage(openType: DDUtilsOpenAppStoreType, appleID: String = "", openWriteAction: Bool = true) -> Void { 75 | switch openType { 76 | case .app: 77 | if #available(iOS 14.0, *) { 78 | var scene: UIWindowScene? 79 | for windowScene:UIWindowScene in ((UIApplication.shared.connectedScenes as? Set)!) { 80 | if windowScene.activationState == .foregroundActive { 81 | scene = windowScene 82 | break 83 | } 84 | } 85 | if let scene = scene { 86 | SKStoreReviewController.requestReview(in: scene) 87 | } else { 88 | //使用链接方式 89 | self.openAppStoreReviewPage(openType: .appStore, appleID: appleID) 90 | } 91 | } else if #available(iOS 10.3, *) { 92 | SKStoreReviewController.requestReview() 93 | } else { 94 | assert(false, "ios10.3以下版本不支持") 95 | }; 96 | case .appStore: 97 | var url = URL(string: "itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=\(appleID)&mt=8")! 98 | if openWriteAction { 99 | url = URL(string: "itms-apps://itunes.apple.com/cn/app/id\(appleID)?mt=8&action=write-review")! 100 | } 101 | UIApplication.shared.open(url, options: [:], completionHandler: nil) 102 | case .auto: 103 | if #available(iOS 10.3, *) { 104 | self.openAppStoreReviewPage(openType: .app, appleID: appleID) 105 | } else { 106 | self.openAppStoreReviewPage(openType: .appStore, appleID: appleID) 107 | } 108 | } 109 | } 110 | } 111 | 112 | 113 | extension DDUtils : SKStoreProductViewControllerDelegate { 114 | public func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) { 115 | viewController.dismiss(animated: true, completion: nil) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/ui/DDUtils+UI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils+UI.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/2. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // A B 12 | // _________ 13 | // | | 14 | // | | 15 | // --------- 16 | // C D 17 | public enum DDUtilsGradientDirection { 18 | case minXToMaxX //AC - BD 19 | case minYToMaxY //AB - CD 20 | case minXMinYToMaxXMaxY //A - D 21 | case minXMaxYToMaxXminY //C - B 22 | } 23 | 24 | 25 | public extension DDUtils { 26 | ///获取当前的normalwindow 27 | func getCurrentNormalWindow() -> UIWindow? { 28 | var window:UIWindow? = UIApplication.shared.keyWindow 29 | if #available(iOS 13.0, *) { 30 | for windowScene:UIWindowScene in ((UIApplication.shared.connectedScenes as? Set)!) { 31 | if windowScene.activationState == .foregroundActive { 32 | window = windowScene.windows.first 33 | for tmpWin in windowScene.windows { 34 | if tmpWin.windowLevel == .normal { 35 | window = tmpWin 36 | break 37 | } 38 | } 39 | break 40 | } 41 | } 42 | } 43 | if window == nil || window?.windowLevel != UIWindow.Level.normal { 44 | for tmpWin in UIApplication.shared.windows { 45 | if tmpWin.windowLevel == UIWindow.Level.normal { 46 | window = tmpWin 47 | break 48 | } 49 | } 50 | } 51 | return window 52 | } 53 | 54 | ///获取当前显示的vc 55 | func getCurrentVC(ignoreChildren: Bool = true) -> UIViewController? { 56 | let currentWindow = self.getCurrentNormalWindow() 57 | guard let window = currentWindow else { return nil } 58 | var vc: UIViewController? 59 | let frontView = window.subviews.first 60 | if let nextResponder = frontView?.next { 61 | if nextResponder is UIViewController { 62 | vc = nextResponder as? UIViewController 63 | } else { 64 | vc = window.rootViewController 65 | } 66 | } else { 67 | vc = window.rootViewController 68 | } 69 | 70 | while (vc is UINavigationController) || (vc is UITabBarController) { 71 | if vc is UITabBarController { 72 | let tabBarController = vc as! UITabBarController 73 | vc = tabBarController.selectedViewController 74 | } else if vc is UINavigationController { 75 | let navigationController = vc as! UINavigationController 76 | vc = navigationController.visibleViewController 77 | } 78 | } 79 | 80 | if !ignoreChildren, let children = vc?.children, children.count > 0 { 81 | return children.last 82 | } 83 | return vc 84 | } 85 | 86 | ///通过颜色获取纯色图片 87 | func getImage(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { 88 | let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) 89 | var image: UIImage? 90 | 91 | UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) 92 | let context: CGContext? = UIGraphicsGetCurrentContext() 93 | if let context = context { 94 | context.setFillColor(color.cgColor) 95 | context.fill(rect) 96 | image = UIGraphicsGetImageFromCurrentImageContext() 97 | UIGraphicsEndImageContext() 98 | } 99 | return image ?? UIImage() 100 | } 101 | 102 | ///线性渐变 103 | func getLinearGradientImage(colors: [UIColor], directionType: DDUtilsGradientDirection, size: CGSize = CGSize(width: 100, height: 100)) -> UIImage { 104 | if (colors.count == 0) { 105 | return UIImage() 106 | } else if (colors.count == 1) { 107 | return self.getImage(color: colors.first!) 108 | } 109 | let gradientLayer = CAGradientLayer() 110 | var cgColors = [CGColor]() 111 | var locations = [NSNumber]() 112 | for i in 0.. UIImage { 151 | if (colors.count == 0) { 152 | return UIImage() 153 | } else if (colors.count == 1) { 154 | return self.getImage(color: colors.first!) 155 | } 156 | 157 | UIGraphicsBeginImageContext(size); 158 | let path = CGMutablePath() 159 | path.addArc(center: CGPoint(x: size.width/2.0, y: size.height / 2.0), radius: raduis, startAngle: 0, endAngle: CGFloat(Double.pi) * 2, clockwise: false) 160 | 161 | let colorSpace = CGColorSpaceCreateDeviceRGB() 162 | 163 | var cgColors = [CGColor]() 164 | var locations = [CGFloat]() 165 | for i in 0.. CGFloat { 230 | if cachePrior, let cacheDefaultNavigationBarHeight = DDUtils.shared.cacheDefaultNavigationBarHeight { 231 | return cacheDefaultNavigationBarHeight 232 | } else { 233 | var height: CGFloat = 0 234 | if let navigationController = vc?.navigationController { 235 | height = navigationController.navigationBar.frame.size.height 236 | } else { 237 | height = UINavigationController(nibName: nil, bundle: nil).navigationBar.frame.size.height 238 | } 239 | DDUtils.shared.cacheDefaultNavigationBarHeight = height 240 | return height 241 | } 242 | } 243 | 244 | ///tabbar高度 245 | public func DDUtils_Default_Tabbar_Height(vc: UIViewController? = nil, cachePrior: Bool = true) -> CGFloat { 246 | if cachePrior, let cacheDefaultTabbarHeight = DDUtils.shared.cacheDefaultTabbarHeight { 247 | return cacheDefaultTabbarHeight 248 | } else { 249 | var height: CGFloat = 0 250 | if let tabbarViewController = vc?.tabBarController { 251 | height = tabbarViewController.tabBar.frame.size.height 252 | } else { 253 | height = UITabBarController(nibName: nil, bundle: nil).tabBar.frame.size.height 254 | } 255 | DDUtils.shared.cacheDefaultTabbarHeight = height 256 | return height 257 | } 258 | } 259 | 260 | ///状态栏和导航栏总高度 261 | public func DDUtils_Default_Nav_And_Status_Height(vc: UIViewController? = nil) -> CGFloat { 262 | return DDUtils_Default_NavigationBar_Height(vc: vc) + DDUtils_StatusBar_Height 263 | } 264 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/ui/UIColor+zx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+dd.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/9. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor: DDUtilsNameSpaceWrappable { 12 | 13 | } 14 | 15 | public extension DDUtilsNameSpace where T : UIColor { 16 | 17 | /// 16进制颜色转为UIColor 18 | /// - Parameters: 19 | /// - hexValue: 颜色 0xffffff 20 | /// - darkHexValue: 仅当支持暗黑模式且设置该参数,暗黑模式下才会显示该颜色。否则依旧显示hexValue 21 | /// - alpha: 透明度 22 | /// - darkAlpha: 仅当支持暗黑模式且设置该参数,暗黑模式下才会使用该透明度.否则依旧显示alpha 23 | /// - Returns: 颜色对象 24 | static func color(hexValue: Int, darkHexValue: Int? = nil, alpha: Float = 1.0, darkAlpha: Float? = nil) -> UIColor { 25 | if #available(iOS 10.0, *) { 26 | if #available(iOS 13.0, *) { 27 | let dyColor = UIColor { (traitCollection) -> UIColor in 28 | if traitCollection.userInterfaceStyle == .light { 29 | return UIColor(displayP3Red: CGFloat(((Float)((hexValue & 0xFF0000) >> 16))/255.0), green: CGFloat(((Float)((hexValue & 0xFF00) >> 8))/255.0), blue: CGFloat(((Float)(hexValue & 0xFF))/255.0), alpha: CGFloat(alpha)) 30 | } else { 31 | let displayHex = darkHexValue ?? hexValue 32 | let displayAlpha = darkAlpha ?? alpha 33 | return UIColor(displayP3Red: CGFloat(((Float)((displayHex & 0xFF0000) >> 16))/255.0), green: CGFloat(((Float)((displayHex & 0xFF00) >> 8))/255.0), blue: CGFloat(((Float)(displayHex & 0xFF))/255.0), alpha: CGFloat(displayAlpha)) 34 | } 35 | } 36 | return dyColor 37 | } else { 38 | return UIColor(displayP3Red: CGFloat(((Float)((hexValue & 0xFF0000) >> 16))/255.0), green: CGFloat(((Float)((hexValue & 0xFF00) >> 8))/255.0), blue: CGFloat(((Float)(hexValue & 0xFF))/255.0), alpha: CGFloat(alpha)) 39 | } 40 | } else { 41 | return UIColor(red: CGFloat(((Float)((hexValue & 0xFF0000) >> 16))/255.0), green: CGFloat(((Float)((hexValue & 0xFF00) >> 8))/255.0), blue: CGFloat(((Float)(hexValue & 0xFF))/255.0), alpha: CGFloat(alpha)) 42 | }; 43 | } 44 | 45 | /// 16进制字符串转为UIColor 46 | /// - Parameters: 47 | /// - hexValue: 颜色 #ffffff 48 | /// - darkHexValue: 仅当支持暗黑模式且设置该参数,暗黑模式下才会显示该颜色。否则依旧显示hexValue 49 | /// - alpha: 透明度 50 | /// - darkAlpha: 仅当支持暗黑模式且设置该参数,暗黑模式下才会使用该透明度.否则依旧显示alpha 51 | /// - Returns: 颜色对象 52 | static func color(hexString: String, darkHexString: String? = nil, alpha: CGFloat = 1.0, darkAlpha: CGFloat? = nil) -> UIColor { 53 | if #available(iOS 13.0, *) { 54 | let dyColor = UIColor { (traitCollection) -> UIColor in 55 | if traitCollection.userInterfaceStyle == .light { 56 | return self._getColor(hexString: hexString, alpha: alpha) 57 | } else { 58 | let displayHex = darkHexString ?? hexString 59 | let displayAlpha = darkAlpha ?? alpha 60 | return self._getColor(hexString: displayHex, alpha: displayAlpha) 61 | } 62 | } 63 | return dyColor 64 | } else { 65 | return self._getColor(hexString: hexString, alpha: alpha) 66 | } 67 | } 68 | } 69 | 70 | private extension DDUtilsNameSpace where T : UIColor { 71 | ///通过十六进制字符串获取颜色 72 | static func _getColor(hexString: String, alpha: CGFloat = 1.0) -> UIColor { 73 | var hex = "" 74 | if hexString.hasPrefix("#") { 75 | hex = String(hexString.suffix(hexString.count - 1)) 76 | } else if (hexString.hasPrefix("0x") || hexString.hasPrefix("0X")) { 77 | hex = String(hexString.suffix(hexString.count - 2)) 78 | } 79 | assert(hex.count == 6, "hex value invalid") 80 | guard hex.count == 6 else { 81 | //不足6位不符合 82 | return UIColor.clear 83 | } 84 | 85 | var red: UInt32 = 0 86 | var green: UInt32 = 0 87 | var blue: UInt32 = 0 88 | 89 | var startIndex = hex.startIndex 90 | var endIndex = hex.index(hex.startIndex, offsetBy: 2) 91 | 92 | Scanner(string: String(hex[startIndex.. UIImage { 18 | return DDUtils.shared.getImage(color: color, size: size) 19 | } 20 | 21 | ///线性渐变 22 | static func getLinearGradientImage(colors: [UIColor], directionType: DDUtilsGradientDirection, size: CGSize = CGSize(width: 100, height: 100)) -> UIImage { 23 | return DDUtils.shared.getLinearGradientImage(colors: colors, directionType: directionType, size: size) 24 | } 25 | 26 | ///角度渐变 27 | static func getRadialGradientImage(colors: [UIColor], raduis: CGFloat, size: CGSize = CGSize(width: 100, height: 100)) -> UIImage { 28 | return DDUtils.shared.getRadialGradientImage(colors: colors, raduis: raduis, size: size) 29 | } 30 | 31 | ///通过view专为图片 32 | static func getImage(view: UIView) -> UIImage? { 33 | if view is UIScrollView { 34 | return self._getImage(scrollView: view as! UIScrollView) 35 | } else { 36 | return self._getImage(view: view) 37 | } 38 | } 39 | 40 | ///合成两张图片合成 41 | static func combineImage(bgImage: UIImage, frontImage: UIImage?, frontPosition: CGPoint = CGPoint(x: 0, y: 0), frontSize: CGSize = CGSize.zero, bounderWidth: CGFloat = 0, bounderColor: UIColor = UIColor.clear) -> UIImage? { 42 | //生成图片大小,如果为0,就根据图片判断 43 | let frontImageWidth = frontSize.width == 0 ? frontImage?.size.width ?? 0 : frontSize.width 44 | let frontImageHeight = frontSize.height == 0 ? frontImage?.size.height ?? 0 : frontSize.height 45 | 46 | let imageSize = CGSize(width: max(bgImage.size.width, frontImageWidth) + bounderWidth * 2, height: max(bgImage.size.height, frontImageHeight) + bounderWidth * 2) 47 | 48 | UIGraphicsBeginImageContextWithOptions(imageSize, false, 0); 49 | let context = UIGraphicsGetCurrentContext(); 50 | if let imageContext = context { 51 | //画背景色 52 | imageContext.addRect(CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height)); 53 | bounderColor.set() 54 | imageContext.fillPath() 55 | //背景图片 56 | bgImage.draw(in: CGRect(x: bounderWidth, y: bounderWidth, width: bgImage.size.width, height: bgImage.size.height)) 57 | //前面的图 58 | if let frontImg = frontImage { 59 | let drwqF = CGRect(x: frontPosition.x + bounderWidth, y: frontPosition.y + bounderWidth, width: frontImageWidth, height: frontImageHeight) 60 | frontImg.draw(in: drwqF) 61 | } 62 | let image = UIGraphicsGetImageFromCurrentImageContext();//返回一个基于当前图形上下文的图片 63 | UIGraphicsEndImageContext(); 64 | return image; 65 | } else { 66 | return nil 67 | } 68 | } 69 | 70 | } 71 | 72 | private extension DDUtilsNameSpace where T : UIImage { 73 | static func _getImage(view: UIView) -> UIImage? { 74 | view.layoutIfNeeded() 75 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0) 76 | let context = UIGraphicsGetCurrentContext(); 77 | if let imageContext = context { 78 | view.layer.render(in: imageContext) 79 | let image = UIGraphicsGetImageFromCurrentImageContext(); 80 | UIGraphicsEndImageContext(); 81 | view.layer.contents = nil; 82 | return image; 83 | } else { 84 | return nil 85 | } 86 | } 87 | 88 | static func _getImage(scrollView: UIScrollView) -> UIImage? { 89 | scrollView.layoutIfNeeded() 90 | //备份位置和父类 91 | let backupFrame = scrollView.frame 92 | let backupContentOffset = scrollView.contentOffset 93 | let backupSuperView = scrollView.superview 94 | 95 | scrollView.contentOffset = CGPoint.zero 96 | 97 | scrollView.frame = CGRect(x: 0, y:0, width: max(scrollView.contentSize.width, backupFrame.size.width), height: max(scrollView.contentSize.height, backupFrame.size.height)) 98 | 99 | let tempSuperView = UIView(frame: CGRect(origin: CGPoint.zero, size: scrollView.frame.size)) 100 | scrollView.removeFromSuperview() 101 | tempSuperView.addSubview(scrollView) 102 | 103 | let image = self.getImage(view: tempSuperView) 104 | 105 | scrollView.removeFromSuperview() 106 | backupSuperView?.addSubview(scrollView) 107 | scrollView.contentOffset = backupContentOffset 108 | 109 | return image 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/ui/UIView+zx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+dd.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/5. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView: DDUtilsNameSpaceWrappable { 12 | 13 | } 14 | 15 | public extension DDUtilsNameSpace where T : UIView { 16 | ///添加阴影 17 | func addLayerShadow(color: UIColor, offset: CGSize, radius: CGFloat, cornerRadius: CGFloat? = nil) -> Void { 18 | object.layer.shadowColor = color.cgColor 19 | object.layer.shadowOffset = offset 20 | object.layer.shadowRadius = radius 21 | object.layer.shadowOpacity = 1 22 | object.layer.shouldRasterize = true 23 | object.layer.rasterizationScale = UIScreen.main.scale 24 | if let cornerRadius = cornerRadius { 25 | object.layer.cornerRadius = cornerRadius 26 | } 27 | } 28 | 29 | ///设置Frame 30 | func setFrame(x: CGFloat? = nil, y: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil) -> Void { 31 | var frame = object.frame 32 | if let x = x { 33 | object.frame = CGRect(x: x, y: frame.origin.y, width: frame.size.width, height: frame.size.height) 34 | } 35 | frame = object.frame 36 | if let y = y { 37 | object.frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: frame.size.height) 38 | } 39 | frame = object.frame 40 | if let width = width { 41 | object.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: frame.size.height) 42 | } 43 | frame = object.frame 44 | if let height = height { 45 | object.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: height) 46 | } 47 | } 48 | 49 | func className() -> String { 50 | return String("\(type(of: object))") 51 | } 52 | 53 | static func className() -> String { 54 | return String("\(classObject.self)") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/utils/DDUtils+file.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils+file.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/4. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum DDUtilsFileDirectoryType { 12 | case home //程序主目录 13 | case documents //应用中用户数据可以放在这里,iTunes备份和恢复的时候会包括此目录 14 | case tmp //存放临时文件,iTunes不会备份和恢复此目录,此目录下文件可能会在应用退出后删除 15 | case caches //存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除,硬盘资源紧张时会被删除 16 | } 17 | 18 | public extension DDUtils { 19 | ///获取文件夹路径 20 | func getFileDirectory(type: DDUtilsFileDirectoryType) -> URL { 21 | let homePath = NSHomeDirectory() 22 | switch type { 23 | case .home: 24 | return URL(fileURLWithPath: homePath) 25 | case .documents: 26 | return URL(fileURLWithPath: homePath.appending("/Documents")) 27 | case .tmp: 28 | return URL(fileURLWithPath: homePath.appending("/tmp")) 29 | case .caches: 30 | return URL(fileURLWithPath: homePath.appending("/Library/Caches")) 31 | } 32 | } 33 | 34 | /// 在指定文件夹中创建文件夹 35 | /// - Parameters: 36 | /// - type: 浮层文件夹类型 37 | /// - directoryName: 文件夹名称 38 | /// - Returns: 创建的文件夹路径 39 | func createFileDirectory(in type: DDUtilsFileDirectoryType, directoryName: String) -> URL { 40 | let manager = FileManager.default 41 | let superDirectory = self.getFileDirectory(type: type) 42 | 43 | let newFolder = superDirectory.appendingPathComponent(directoryName, isDirectory: true) 44 | 45 | var isDirectory: ObjCBool = false 46 | let isDirExist = manager.fileExists(atPath: newFolder.path, isDirectory: &isDirectory) 47 | if !isDirectory.boolValue || !isDirExist { 48 | do { 49 | try manager.createDirectory(at: newFolder, withIntermediateDirectories: true, attributes: nil) 50 | } catch { 51 | print("创建目录失败\(error)") 52 | return newFolder 53 | } 54 | } 55 | return newFolder 56 | } 57 | 58 | ///获取指定文件的大小 59 | func getFileSize(filePath: URL) -> Double { 60 | let manager = FileManager.default 61 | if manager.fileExists(atPath: filePath.path) { 62 | let fileSize = try? manager.attributesOfItem(atPath: filePath.path) 63 | return fileSize?[FileAttributeKey.size] as? Double ?? 0 64 | } 65 | return 0 66 | } 67 | 68 | ///获取文件夹大小 69 | func getFileDirectorySize(fileDirectoryPth: URL) -> Double { 70 | let manager = FileManager.default 71 | var size: Double = 0 72 | 73 | if manager.fileExists(atPath: fileDirectoryPth.path), let subPath = manager.subpaths(atPath: fileDirectoryPth.path) { 74 | for fileName in subPath { 75 | let filePath = fileDirectoryPth.path.appending("/\(fileName)") 76 | size = size + self.getFileSize(filePath: URL(fileURLWithPath: filePath)) 77 | } 78 | } 79 | return size 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/utils/DDUtils+media.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils+media.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/4. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AVFoundation 11 | 12 | private var vibrateRepeat = false //标记是否循环震动 13 | private var audioPlayer: AVAudioPlayer? //音乐播放器 14 | 15 | public extension DDUtils { 16 | 17 | ///获取指定video的时长, 单位秒 18 | func getVideoDuration(videoURL: URL) -> Double { 19 | let asset = AVURLAsset(url: videoURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: false]) 20 | return Double(asset.duration.value) / Double(asset.duration.timescale) 21 | } 22 | 23 | ///获取指定视频的分辨率,支持本地或者网络地址 24 | func getVideoSize(videoURL: URL) -> CGSize { 25 | let asset = AVURLAsset(url: videoURL, options: nil) 26 | if let track = asset.tracks(withMediaType: AVMediaType.video).first { 27 | return CGSize(width: abs(track.naturalSize.applying(track.preferredTransform).width), height: abs(track.naturalSize.applying(track.preferredTransform).height)) 28 | } else { 29 | return CGSize(width: 0, height: 0) 30 | } 31 | } 32 | 33 | /// 播放音乐 34 | /// - Parameters: 35 | /// - url: 文件地址 36 | /// - repeated: 是否重复播放 37 | /// - audioSessionCategory: 播放模式 .playback 扬声器播放,.playAndRecord听筒模式 38 | @discardableResult 39 | func playMusic(url: URL?, repeated: Bool = false, audioSessionCategory: AVAudioSession.Category = AVAudioSession.Category.playback) -> AVAudioPlayer? { 40 | guard var musicURL = url else { return nil } 41 | audioPlayer?.stop() 42 | 43 | let audioSession = AVAudioSession.sharedInstance() 44 | try? audioSession.setCategory(audioSessionCategory) 45 | try? audioSession.setActive(true, options: AVAudioSession.SetActiveOptions.init()) 46 | 47 | 48 | if musicURL.absoluteString.hasPrefix("http://") || musicURL.absoluteString.hasPrefix("https://") { 49 | guard let name = musicURL.path.dd.hashString(hashType: .md5) else { return nil } 50 | let path = DDUtils.shared.createFileDirectory(in: .caches, directoryName: "music").appendingPathComponent(name, isDirectory: false) 51 | let audioData = try? Data(contentsOf: musicURL) 52 | try? audioData?.write(to: path) 53 | musicURL = path 54 | } 55 | 56 | audioPlayer = try? AVAudioPlayer(contentsOf: musicURL, fileTypeHint: nil) 57 | if repeated { 58 | audioPlayer?.numberOfLoops = -1 59 | } else { 60 | audioPlayer?.numberOfLoops = 0 61 | } 62 | audioPlayer?.play() 63 | return audioPlayer 64 | } 65 | 66 | ///关闭音乐播放 67 | func stopMusic() -> Void { 68 | audioPlayer?.stop() 69 | } 70 | 71 | 72 | /// 播放音效,静音模式不会播放音效 73 | /// - Parameters: 74 | /// - effectURL: 音效文件地址 75 | /// - vibrate: 是否震动 76 | func playEffect(url: URL?, vibrate: Bool = false) -> Void { 77 | var soundID = SystemSoundID() 78 | 79 | if let effect = url { 80 | AudioServicesCreateSystemSoundID(effect as CFURL, &soundID) 81 | } else if vibrate { 82 | soundID = kSystemSoundID_Vibrate 83 | } 84 | if vibrate { 85 | AudioServicesPlayAlertSoundWithCompletion(soundID, nil) 86 | } else { 87 | AudioServicesPlaySystemSoundWithCompletion(soundID, nil) 88 | } 89 | } 90 | 91 | /// 开始震动 92 | /// - Parameter repeated: 是否循环震动 93 | func startVibrate(repeated: Bool = false) -> Void { 94 | vibrateRepeat = repeated 95 | if repeated { 96 | AudioServicesPlaySystemSoundWithCompletion(kSystemSoundID_Vibrate) { 97 | self.startVibrate(repeated: vibrateRepeat) 98 | } 99 | } else { 100 | AudioServicesPlaySystemSoundWithCompletion(kSystemSoundID_Vibrate) { 101 | 102 | } 103 | } 104 | } 105 | 106 | ///结束震动 107 | func stopVibrate() -> Void { 108 | vibrateRepeat = false 109 | AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/utils/DDUtils+system.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDUtils+system.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/3. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import SystemConfiguration.CaptiveNetwork 12 | 13 | public extension DDUtils { 14 | ///获取软件版本 15 | func getAppVersionString() -> String { 16 | let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String 17 | return version ?? "" 18 | } 19 | 20 | ///获取软件构建版本 21 | func getAppBuildVersionString() -> String { 22 | let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String 23 | return version ?? "" 24 | } 25 | 26 | ///获取软件名 27 | func getAppNameString() -> String { 28 | let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String 29 | return version ?? "" 30 | } 31 | 32 | ///获取系统的iOS版本 33 | func getIOSVersionString() -> String { 34 | return UIDevice.current.systemVersion 35 | } 36 | 37 | ///获取系统语言 38 | func getIOSLanguageStr() -> String { 39 | let language = Bundle.main.preferredLocalizations.first 40 | return language ?? "" 41 | } 42 | 43 | ///获取软件Bundle Identifier 44 | func getBundleIdentifier() -> String { 45 | return Bundle.main.bundleIdentifier ?? "" 46 | } 47 | 48 | ///获取本机机型标识 49 | func getSystemHardware() -> String { 50 | var systemInfo = utsname() 51 | uname(&systemInfo) 52 | let machineMirror = Mirror(reflecting: systemInfo.machine) 53 | let identifier = machineMirror.children.reduce("") { identifier, element in 54 | guard let value = element.value as? Int8, value != 0 else { return identifier } 55 | return identifier + String(UnicodeScalar(UInt8(value))) 56 | } 57 | return identifier 58 | } 59 | 60 | ///获取本机上次重启时间 61 | func getSystemUpTime() -> TimeInterval { 62 | let timeInterval = ProcessInfo.processInfo.systemUptime 63 | return Date().timeIntervalSince1970 - timeInterval 64 | } 65 | 66 | ///获取手机WIFI的MAC地址,需要开启Access WiFi information 67 | func getMacAddress() -> (ssid: String?, mac: String?) { 68 | let interfaces:NSArray = CNCopySupportedInterfaces()! 69 | var ssid: String? 70 | var mac: String? 71 | for sub in interfaces { 72 | if let dict = CFBridgingRetain(CNCopyCurrentNetworkInfo(sub as! CFString)) { 73 | ssid = dict["SSID"] as? String 74 | mac = dict["BSSID"] as? String 75 | break 76 | } 77 | } 78 | return (ssid: ssid, mac: mac) 79 | } 80 | 81 | ///打开系统设置 82 | func openSystemSetting(completion: ((Bool) -> Void)? = nil) -> Void { 83 | let url = URL(string: UIApplication.openSettingsURLString)! 84 | UIApplication.shared.open(url, options: [:], completionHandler: completion) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/utils/Date+zx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+dd.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/3. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Date: DDUtilsNameSpaceWrappable { 12 | 13 | } 14 | 15 | public extension DDUtilsNameSpace where T == Date { 16 | ///比较日期,设置是否忽略时间 17 | func compare(anotherDate: Date, ignoreTime: Bool = false) -> ComparisonResult { 18 | if !ignoreTime { 19 | return object.compare(anotherDate) 20 | } else { 21 | let calendar = Calendar.current 22 | if calendar.compare(object, to: anotherDate, toGranularity: Calendar.Component.year) != .orderedSame { 23 | return calendar.compare(object, to: anotherDate, toGranularity: Calendar.Component.year) 24 | } 25 | if calendar.compare(object, to: anotherDate, toGranularity: Calendar.Component.month) != .orderedSame { 26 | return calendar.compare(object, to: anotherDate, toGranularity: Calendar.Component.month) 27 | } 28 | return calendar.compare(object, to: anotherDate, toGranularity: Calendar.Component.day) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /example/Pods/DDUtils/Sources/core/utils/String+zx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+dd.swift 3 | // DDUtils 4 | // 5 | // Created by Damon on 2020/7/3. 6 | // Copyright © 2020 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | #if canImport(CryptoKit) 11 | import CryptoKit 12 | #endif 13 | 14 | extension String: DDUtilsNameSpaceWrappable { 15 | 16 | } 17 | 18 | public extension DDUtilsNameSpace where T == String { 19 | ///截取字符串 20 | func subString(rang: NSRange) -> String { 21 | var string = String() 22 | var subRange = rang 23 | if rang.location < 0 { 24 | subRange = NSRange(location: 0, length: rang.length) 25 | } 26 | if object.count < subRange.location + subRange.length { 27 | //直接返回完整的 28 | subRange = NSRange(location: subRange.location, length: object.count - subRange.location) 29 | } 30 | let startIndex = object.index(object.startIndex,offsetBy: subRange.location) 31 | let endIndex = object.index(object.startIndex,offsetBy: (subRange.location + subRange.length)) 32 | let subString = object[startIndex..) -> NSRange? { 39 | guard let from = range.lowerBound.samePosition(in: object.utf16), let to = range.upperBound.samePosition(in: object.utf16) else { return nil } 40 | return NSRange(location: object.utf16.distance(from: object.utf16.startIndex, to: from), length: object.utf16.distance(from: from, to: to)) 41 | } 42 | 43 | ///NSRange转换为Range 44 | func range(from nsRange: NSRange) -> Range? { 45 | guard let from16 = object.utf16.index(object.utf16.startIndex, offsetBy: nsRange.location, limitedBy: object.utf16.endIndex), 46 | let to16 = object.utf16.index(from16, offsetBy: nsRange.length,limitedBy: object.utf16.endIndex), 47 | let from = String.Index(from16, within: object), 48 | let to = String.Index(to16, within: object) else { return nil } 49 | return from ..< to 50 | } 51 | 52 | ///unicode转中文 53 | func unicodeDecode() -> String { 54 | let tempStr1 = object.replacingOccurrences(of: "\\u", with: "\\U") 55 | let tempStr2 = tempStr1.replacingOccurrences(of: "\"", with: "\\\"") 56 | let tempStr3 = "\"".appending(tempStr2).appending("\"") 57 | let tempData = tempStr3.data(using: String.Encoding.utf8) 58 | var returnStr:String = "" 59 | do { 60 | returnStr = try PropertyListSerialization.propertyList(from: tempData!, options: [.mutableContainers], format: nil) as! String 61 | } catch { 62 | print("unicodeDecode转义失败\(error)") 63 | return object 64 | } 65 | return returnStr.replacingOccurrences(of: "\\r\\n", with: "\n") 66 | } 67 | 68 | ///字符串转unicode 69 | func unicodeEncode() -> String? { 70 | return self.encodeString(from: .system(.nonLossyASCII), to: .system(.utf8)) 71 | } 72 | 73 | /// 字符串转格式 74 | /// - Parameters: 75 | /// - originType: 字符串原来的编码格式 76 | /// - encodeType: 即将转换的编码格式 77 | /// - Returns: 转换成功的新字符串 78 | func encodeString(from originType: DDUtilsEncodeType = .system(.utf8), to encodeType: DDUtilsEncodeType) -> String? { 79 | let data = Data.dd.data(from: object, encodeType: originType) 80 | return data?.dd.encodeString(encodeType: encodeType) 81 | } 82 | 83 | /* 84 | AES加密 85 | model: CBC 86 | padding: PKCS7Padding 87 | AES block Size: 128 88 | **/ 89 | func aesCBCEncrypt(password: String, ivString: String = "abcdefghijklmnop", encodeType: DDUtilsEncodeType = .base64) -> String? { 90 | let data = object.data(using:String.Encoding.utf8) 91 | return data?.dd.aesCBCEncrypt(password: password, ivString: ivString, encodeType: encodeType) 92 | } 93 | 94 | ///aes CBC解密 95 | func aesCBCDecrypt(password: String, ivString: String = "abcdefghijklmnop", encodeType: DDUtilsEncodeType = .base64) -> String? { 96 | let data = Data.dd.data(from: object, encodeType: encodeType) 97 | return data?.dd.aesCBCDecrypt(password: password, ivString: ivString) 98 | } 99 | 100 | //MARK: 加密 101 | func hashString(hashType: DDUtilsHashType, lowercase: Bool = true) -> String? { 102 | let data = object.data(using: String.Encoding.utf8) 103 | return data?.dd.hashString(hashType: hashType, lowercase: lowercase) 104 | } 105 | 106 | 107 | @available(*, deprecated, message: "Use hashString(hashType: DDUtilsHashType, lowercase: Bool) instead") 108 | func encryptString(encryType: DDUtilsHashType, lowercase: Bool = true) -> String? { 109 | return self.hashString(hashType: encryType, lowercase: lowercase) 110 | } 111 | } 112 | 113 | #if canImport(CryptoKit) 114 | @available(iOS 13.0, *) 115 | public extension DDUtilsNameSpace where T == String { 116 | /* 117 | AES加密 118 | model: GCM 119 | **/ 120 | func aesGCMEncrypt(password: String, encodeType: DDUtilsEncodeType = .base64, nonce: AES.GCM.Nonce? = AES.GCM.Nonce()) -> String? { 121 | let data = object.data(using:String.Encoding.utf8) 122 | return data?.dd.aesGCMEncrypt(password: password, encodeType: encodeType, nonce: nonce) 123 | } 124 | 125 | /* 126 | AES加密 127 | model: GCM 128 | **/ 129 | func aesGCMEncrypt(key: SymmetricKey, encodeType: DDUtilsEncodeType = .base64, nonce: AES.GCM.Nonce? = AES.GCM.Nonce()) -> String? { 130 | let data = object.data(using:String.Encoding.utf8) 131 | return data?.dd.aesGCMEncrypt(key: key, encodeType: encodeType, nonce: nonce) 132 | } 133 | 134 | /* 135 | AES解密 136 | model: GCM 137 | **/ 138 | func aesGCMDecrypt(password: String, encodeType: DDUtilsEncodeType = .base64) -> String? { 139 | let data = Data.dd.data(from: object, encodeType: encodeType) 140 | return data?.dd.aesGCMDecrypt(password: password) 141 | } 142 | 143 | /* 144 | AES解密 145 | model: GCM 146 | **/ 147 | func aesGCMDecrypt(key: SymmetricKey, encodeType: DDUtilsEncodeType = .base64) -> String? { 148 | let data = Data.dd.data(from: object, encodeType: encodeType) 149 | return data?.dd.aesGCMDecrypt(key: key) 150 | } 151 | 152 | ///HMAC计算 153 | func hmac(hashType: DDUtilsHashType, password: String, encodeType: DDUtilsEncodeType = .base64) -> String? { 154 | let data = object.data(using:String.Encoding.utf8) 155 | return data?.dd.hmac(hashType: hashType, password: password, encodeType: encodeType) 156 | } 157 | 158 | ///HMAC计算 159 | func hmac(hashType: DDUtilsHashType, key: SymmetricKey, encodeType: DDUtilsEncodeType = .base64) -> String? { 160 | let data = object.data(using:String.Encoding.utf8) 161 | return data?.dd.hmac(hashType: hashType, key: key, encodeType: encodeType) 162 | } 163 | } 164 | #endif 165 | -------------------------------------------------------------------------------- /example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - DDLoggerSwift (5.3.1): 3 | - DDLoggerSwift/core (= 5.3.1) 4 | - DDLoggerSwift/core (5.3.1): 5 | - DDUtils/ui (~> 5) 6 | - DDUtils/utils (~> 5) 7 | - DDUtils/core (5.0.13) 8 | - DDUtils/ui (5.0.13): 9 | - DDUtils/core 10 | - DDUtils/utils (5.0.13): 11 | - DDUtils/core 12 | 13 | DEPENDENCIES: 14 | - DDLoggerSwift (~> 5) 15 | - DDUtils/ui (~> 5) 16 | - DDUtils/utils (~> 5) 17 | 18 | SPEC REPOS: 19 | trunk: 20 | - DDLoggerSwift 21 | - DDUtils 22 | 23 | SPEC CHECKSUMS: 24 | DDLoggerSwift: c7c8776b2e56c741ef3c3de8cfaa3eadb2fcf813 25 | DDUtils: 9d1dab6514cbe6687348bde7ea0f6f2187b55222 26 | 27 | PODFILE CHECKSUM: 9adc178184525feb192ce1c94c0dd33c7c9b4ff9 28 | 29 | COCOAPODS: 1.16.2 30 | -------------------------------------------------------------------------------- /example/Pods/Pods.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/DDLoggerSwift-DDLoggerSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/Pods/Pods.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/DDLoggerSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/Pods/Pods.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/DDUtils.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/Pods/Pods.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/Pods-DDKitSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/Pods/Pods.xcodeproj/xcuserdata/damon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DDLoggerSwift-DDLoggerSwift.xcscheme 8 | 9 | isShown 10 | 11 | orderHint 12 | 1 13 | 14 | DDLoggerSwift.xcscheme 15 | 16 | isShown 17 | 18 | orderHint 19 | 0 20 | 21 | DDUtils.xcscheme 22 | 23 | isShown 24 | 25 | orderHint 26 | 2 27 | 28 | Pods-DDKitSwift.xcscheme 29 | 30 | isShown 31 | 32 | orderHint 33 | 3 34 | 35 | 36 | SuppressBuildableAutocreation 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift-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.3.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_DDLoggerSwift : NSObject 3 | @end 4 | @implementation PodsDummy_DDLoggerSwift 5 | @end 6 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift-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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift-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 DDLoggerSwiftVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char DDLoggerSwiftVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 6 | OTHER_LDFLAGS = $(inherited) -l"sqlite3" -framework "DDUtils" -weak_framework "CryptoKit" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/DDLoggerSwift 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift.modulemap: -------------------------------------------------------------------------------- 1 | framework module DDLoggerSwift { 2 | umbrella header "DDLoggerSwift-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/DDLoggerSwift.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 6 | OTHER_LDFLAGS = $(inherited) -l"sqlite3" -framework "DDUtils" -weak_framework "CryptoKit" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/DDLoggerSwift 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDLoggerSwift/ResourceBundle-DDLoggerSwift-DDLoggerSwift-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 | 5.3.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils-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.13 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_DDUtils : NSObject 3 | @end 4 | @implementation PodsDummy_DDUtils 5 | @end 6 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils-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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils-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 DDUtilsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char DDUtilsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DDUtils 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) -weak_framework "CryptoKit" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 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}/DDUtils 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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils.modulemap: -------------------------------------------------------------------------------- 1 | framework module DDUtils { 2 | umbrella header "DDUtils-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/DDUtils/DDUtils.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DDUtils 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) -weak_framework "CryptoKit" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 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}/DDUtils 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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## DDLoggerSwift 5 | 6 | MIT License 7 | 8 | Copyright (c) 2020 Damon 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 | ## DDUtils 30 | 31 | MIT License 32 | 33 | Copyright (c) 2020 Damon 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 51 | SOFTWARE. 52 | 53 | Generated by CocoaPods - https://cocoapods.org 54 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-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) 2020 Damon 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 | DDLoggerSwift 43 | Type 44 | PSGroupSpecifier 45 | 46 | 47 | FooterText 48 | MIT License 49 | 50 | Copyright (c) 2020 Damon 51 | 52 | Permission is hereby granted, free of charge, to any person obtaining a copy 53 | of this software and associated documentation files (the "Software"), to deal 54 | in the Software without restriction, including without limitation the rights 55 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 56 | copies of the Software, and to permit persons to whom the Software is 57 | furnished to do so, subject to the following conditions: 58 | 59 | The above copyright notice and this permission notice shall be included in all 60 | copies or substantial portions of the Software. 61 | 62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 63 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 64 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 65 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 66 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 67 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 68 | SOFTWARE. 69 | 70 | License 71 | MIT 72 | Title 73 | DDUtils 74 | Type 75 | PSGroupSpecifier 76 | 77 | 78 | FooterText 79 | Generated by CocoaPods - https://cocoapods.org 80 | Title 81 | 82 | Type 83 | PSGroupSpecifier 84 | 85 | 86 | StringsTable 87 | Acknowledgements 88 | Title 89 | Acknowledgements 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_DDKitSwift : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_DDKitSwift 5 | @end 6 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/DDLoggerSwift/DDLoggerSwift.framework 3 | ${BUILT_PRODUCTS_DIR}/DDUtils/DDUtils.framework -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DDLoggerSwift.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DDUtils.framework -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/DDLoggerSwift/DDLoggerSwift.framework 3 | ${BUILT_PRODUCTS_DIR}/DDUtils/DDUtils.framework -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DDLoggerSwift.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DDUtils.framework -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # frameworks to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 19 | 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 21 | SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 22 | BCSYMBOLMAP_DIR="BCSymbolMaps" 23 | 24 | 25 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 26 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 27 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 28 | 29 | # Copies and strips a vendored framework 30 | install_framework() 31 | { 32 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 33 | local source="${BUILT_PRODUCTS_DIR}/$1" 34 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 35 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 36 | elif [ -r "$1" ]; then 37 | local source="$1" 38 | fi 39 | 40 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 41 | 42 | if [ -L "${source}" ]; then 43 | echo "Symlinked..." 44 | source="$(readlink -f "${source}")" 45 | fi 46 | 47 | if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then 48 | # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied 49 | find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do 50 | echo "Installing $f" 51 | install_bcsymbolmap "$f" "$destination" 52 | rm "$f" 53 | done 54 | rmdir "${source}/${BCSYMBOLMAP_DIR}" 55 | fi 56 | 57 | # Use filter instead of exclude so missing patterns don't throw errors. 58 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 59 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 60 | 61 | local basename 62 | basename="$(basename -s .framework "$1")" 63 | binary="${destination}/${basename}.framework/${basename}" 64 | 65 | if ! [ -r "$binary" ]; then 66 | binary="${destination}/${basename}" 67 | elif [ -L "${binary}" ]; then 68 | echo "Destination binary is symlinked..." 69 | dirname="$(dirname "${binary}")" 70 | binary="${dirname}/$(readlink "${binary}")" 71 | fi 72 | 73 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 74 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 75 | strip_invalid_archs "$binary" 76 | fi 77 | 78 | # Resign the code if required by the build settings to avoid unstable apps 79 | code_sign_if_enabled "${destination}/$(basename "$1")" 80 | 81 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 82 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 83 | local swift_runtime_libs 84 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) 85 | for lib in $swift_runtime_libs; do 86 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 87 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 88 | code_sign_if_enabled "${destination}/${lib}" 89 | done 90 | fi 91 | } 92 | # Copies and strips a vendored dSYM 93 | install_dsym() { 94 | local source="$1" 95 | warn_missing_arch=${2:-true} 96 | if [ -r "$source" ]; then 97 | # Copy the dSYM into the targets temp dir. 98 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 99 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 100 | 101 | local basename 102 | basename="$(basename -s .dSYM "$source")" 103 | binary_name="$(ls "$source/Contents/Resources/DWARF")" 104 | binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" 105 | 106 | # Strip invalid architectures from the dSYM. 107 | if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then 108 | strip_invalid_archs "$binary" "$warn_missing_arch" 109 | fi 110 | if [[ $STRIP_BINARY_RETVAL == 0 ]]; then 111 | # Move the stripped file into its final destination. 112 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 113 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 114 | else 115 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 116 | mkdir -p "${DWARF_DSYM_FOLDER_PATH}" 117 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" 118 | fi 119 | fi 120 | } 121 | 122 | # Used as a return value for each invocation of `strip_invalid_archs` function. 123 | STRIP_BINARY_RETVAL=0 124 | 125 | # Strip invalid architectures 126 | strip_invalid_archs() { 127 | binary="$1" 128 | warn_missing_arch=${2:-true} 129 | # Get architectures for current target binary 130 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 131 | # Intersect them with the architectures we are building for 132 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 133 | # If there are no archs supported by this binary then warn the user 134 | if [[ -z "$intersected_archs" ]]; then 135 | if [[ "$warn_missing_arch" == "true" ]]; then 136 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 137 | fi 138 | STRIP_BINARY_RETVAL=1 139 | return 140 | fi 141 | stripped="" 142 | for arch in $binary_archs; do 143 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 144 | # Strip non-valid architectures in-place 145 | lipo -remove "$arch" -output "$binary" "$binary" 146 | stripped="$stripped $arch" 147 | fi 148 | done 149 | if [[ "$stripped" ]]; then 150 | echo "Stripped $binary of architectures:$stripped" 151 | fi 152 | STRIP_BINARY_RETVAL=0 153 | } 154 | 155 | # Copies the bcsymbolmap files of a vendored framework 156 | install_bcsymbolmap() { 157 | local bcsymbolmap_path="$1" 158 | local destination="${BUILT_PRODUCTS_DIR}" 159 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 160 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 161 | } 162 | 163 | # Signs a framework with the provided identity 164 | code_sign_if_enabled() { 165 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 166 | # Use the current code_sign_identity 167 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 168 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 169 | 170 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 171 | code_sign_cmd="$code_sign_cmd &" 172 | fi 173 | echo "$code_sign_cmd" 174 | eval "$code_sign_cmd" 175 | fi 176 | } 177 | 178 | if [[ "$CONFIGURATION" == "Debug" ]]; then 179 | install_framework "${BUILT_PRODUCTS_DIR}/DDLoggerSwift/DDLoggerSwift.framework" 180 | install_framework "${BUILT_PRODUCTS_DIR}/DDUtils/DDUtils.framework" 181 | fi 182 | if [[ "$CONFIGURATION" == "Release" ]]; then 183 | install_framework "${BUILT_PRODUCTS_DIR}/DDLoggerSwift/DDLoggerSwift.framework" 184 | install_framework "${BUILT_PRODUCTS_DIR}/DDUtils/DDUtils.framework" 185 | fi 186 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 187 | wait 188 | fi 189 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift-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_DDKitSwiftVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_DDKitSwiftVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift.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}/DDLoggerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift/DDLoggerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils/DDUtils.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_LDFLAGS = $(inherited) -l"sqlite3" -framework "DDLoggerSwift" -framework "DDUtils" -weak_framework "CryptoKit" 9 | OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 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 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_DDKitSwift { 2 | umbrella header "Pods-DDKitSwift-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /example/Pods/Target Support Files/Pods-DDKitSwift/Pods-DDKitSwift.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}/DDLoggerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift/DDLoggerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DDUtils/DDUtils.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_LDFLAGS = $(inherited) -l"sqlite3" -framework "DDLoggerSwift" -framework "DDUtils" -weak_framework "CryptoKit" 9 | OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/DDLoggerSwift" "-F${PODS_CONFIGURATION_BUILD_DIR}/DDUtils" 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 | -------------------------------------------------------------------------------- /pod/DDKitSwift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwift.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | import DDUtils 10 | import DDLoggerSwift 11 | 12 | extension String{ 13 | var ZXLocaleString: String { 14 | //优先使用主项目翻译 15 | let mainValue = NSLocalizedString(self, comment: "") 16 | if mainValue != self { 17 | return mainValue 18 | } 19 | //使用自己的bundle 20 | if let bundlePath = Bundle(for: DDKitSwift.self).path(forResource: "DDKitSwift", ofType: "bundle"), let bundle = Bundle(path: bundlePath) { 21 | return NSLocalizedString(self, tableName: nil, bundle: bundle, value: self, comment: "") 22 | } 23 | return self 24 | } 25 | } 26 | 27 | func UIImageHDBoundle(named: String?) -> UIImage? { 28 | guard let name = named else { return nil } 29 | guard let bundlePath = Bundle(for: DDKitSwift.self).path(forResource: "DDKitSwift", ofType: "bundle") else { return UIImage(named: name) } 30 | guard let bundle = Bundle(path: bundlePath) else { return UIImage(named: name) } 31 | return UIImage(named: name, in: bundle, compatibleWith: nil) 32 | } 33 | 34 | public extension NSNotification.Name { 35 | static let DDKitSwiftPluginRegist = NSNotification.Name("DDKitSwiftPluginRegist") 36 | static let DDKitSwiftShow = NSNotification.Name("DDKitSwiftShow") 37 | static let DDKitSwiftHide = NSNotification.Name("DDKitSwiftHide") 38 | static let DDKitSwiftClose = NSNotification.Name("DDKitSwiftClose") 39 | } 40 | 41 | public class DDKitSwift: NSObject { 42 | public static var UIConfig = DDKitSwiftUIConfig() 43 | 44 | //MARK: Private 45 | private static var hasConfig = false 46 | private static var window: DDKitSwiftWindow? 47 | internal static var floatWindow: DDKitSwiftFloatWindow? 48 | static var pluginList = [[DDKitSwiftPluginProtocol](), [DDKitSwiftPluginProtocol](), [DDKitSwiftPluginProtocol]()] 49 | } 50 | 51 | public extension DDKitSwift { 52 | static func regist(plugin: DDKitSwiftPluginProtocol) { 53 | if !hasConfig { 54 | self._initConfig() 55 | } 56 | var index = 0 57 | switch plugin.pluginType { 58 | case .ui: 59 | index = 0 60 | case .data: 61 | index = 1 62 | case .other: 63 | index = 2 64 | } 65 | if !self.pluginList[index].contains(where: { (tPlugin) -> Bool in 66 | return tPlugin.pluginIdentifier == plugin.pluginIdentifier 67 | }) { 68 | self.pluginList[index].append(plugin) 69 | plugin.didRegist() 70 | } 71 | if let window = self.window, !window.isHidden { 72 | DispatchQueue.main.async { 73 | window.reloadData() 74 | } 75 | } 76 | NotificationCenter.default.post(name: .DDKitSwiftPluginRegist, object: self.pluginList) 77 | } 78 | 79 | static func show() { 80 | if !hasConfig { 81 | self._initConfig() 82 | } 83 | NotificationCenter.default.post(name: .DDKitSwiftShow, object: nil) 84 | DispatchQueue.main.async { 85 | self.floatWindow?.isHidden = true 86 | if let window = self.window { 87 | window.isHidden = false 88 | } else { 89 | if #available(iOS 13.0, *) { 90 | for windowScene:UIWindowScene in ((UIApplication.shared.connectedScenes as? Set)!) { 91 | if windowScene.activationState == .foregroundActive { 92 | self.window = DDKitSwiftWindow(windowScene: windowScene) 93 | self.window?.frame = UIScreen.main.bounds 94 | } 95 | } 96 | } 97 | if self.window == nil { 98 | self.window = DDKitSwiftWindow(frame: UIScreen.main.bounds) 99 | } 100 | self.window?.isHidden = false 101 | self.window?.reloadData() 102 | } 103 | } 104 | } 105 | 106 | static func hide() { 107 | NotificationCenter.default.post(name: .DDKitSwiftHide, object: nil) 108 | DispatchQueue.main.async { 109 | self.window?.isHidden = true 110 | //float window 111 | if let window = self.floatWindow { 112 | window.isHidden = false 113 | } else { 114 | if #available(iOS 13.0, *) { 115 | for windowScene:UIWindowScene in ((UIApplication.shared.connectedScenes as? Set)!) { 116 | if windowScene.activationState == .foregroundActive { 117 | self.floatWindow = DDKitSwiftFloatWindow(windowScene: windowScene) 118 | self.floatWindow?.frame = CGRect(x: UIScreen.main.bounds.size.width - 80, y: 100, width: 60, height: 60) 119 | } 120 | } 121 | } 122 | if self.floatWindow == nil { 123 | self.floatWindow = DDKitSwiftFloatWindow(frame: CGRect(x: UIScreen.main.bounds.size.width - 80, y: 100, width: 60, height: 60)) 124 | } 125 | self.floatWindow?.isHidden = false 126 | } 127 | } 128 | } 129 | 130 | static func close() { 131 | NotificationCenter.default.post(name: .DDKitSwiftClose, object: nil) 132 | DispatchQueue.main.async { 133 | self.window?.isHidden = true 134 | self.floatWindow?.isHidden = true 135 | } 136 | } 137 | 138 | static func updateListItem(plugin: DDKitSwiftPluginProtocol, config: DDPluginItemConfig) { 139 | self.window?.updateListItem(plugin: plugin, config: config) 140 | } 141 | 142 | static func getCurrentNavigationVC() -> UINavigationController? { 143 | return self.window?.currentNavVC 144 | } 145 | } 146 | 147 | private extension DDKitSwift { 148 | static func _initConfig() { 149 | if hasConfig { 150 | return 151 | } 152 | self.hasConfig = true 153 | //初始化内置插件 154 | self.regist(plugin: DDLoggerSwift.shared) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /pod/DDKitSwiftCollectionViewHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftCollectionViewHeaderView.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | class DDKitSwiftCollectionViewHeaderView: UICollectionViewCell { 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | self.createUI() 14 | } 15 | 16 | required init?(coder: NSCoder) { 17 | fatalError("init(coder:) has not been implemented") 18 | } 19 | 20 | func createUI() { 21 | self.contentView.backgroundColor = DDKitSwift.UIConfig.collectionViewTitleBackgroundColor 22 | self.contentView.addSubview(mTitleLabel) 23 | 24 | mTitleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20).isActive = true 25 | mTitleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20).isActive = true 26 | mTitleLabel.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor).isActive = true 27 | } 28 | 29 | func updateUI(title: String) { 30 | mTitleLabel.text = title 31 | } 32 | 33 | //MARK: UI 34 | lazy var mTitleLabel: UILabel = { 35 | let tLabel = UILabel() 36 | tLabel.translatesAutoresizingMaskIntoConstraints = false 37 | tLabel.numberOfLines = 2 38 | tLabel.textAlignment = .left 39 | tLabel.font = .systemFont(ofSize: 16, weight: .medium) 40 | tLabel.textColor = DDKitSwift.UIConfig.collectionViewTitleColor 41 | return tLabel 42 | }() 43 | } 44 | -------------------------------------------------------------------------------- /pod/DDKitSwiftFloatWindow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftFloatWindow.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/25. 6 | // 7 | 8 | import UIKit 9 | import DDUtils 10 | import DDLoggerSwift 11 | 12 | class DDKitSwiftFloatWindow: UIWindow { 13 | @available(iOS 13.0, *) 14 | override init(windowScene: UIWindowScene) { 15 | super.init(windowScene: windowScene) 16 | self._initVC() 17 | self._createUI() 18 | } 19 | 20 | override init(frame: CGRect) { 21 | super.init(frame: frame) 22 | self._initVC() 23 | self._createUI() 24 | } 25 | 26 | required init?(coder: NSCoder) { 27 | fatalError("init(coder:) has not been implemented") 28 | } 29 | 30 | //MARK: UI 31 | lazy var mLogoImageView: UIImageView = { 32 | let imageView = UIImageView(image: UIImageHDBoundle(named: "zx_logo")) 33 | imageView.isUserInteractionEnabled = false 34 | imageView.translatesAutoresizingMaskIntoConstraints = false 35 | return imageView 36 | }() 37 | 38 | lazy var mButton: UIButton = { 39 | let button = UIButton(type: .custom) 40 | button.translatesAutoresizingMaskIntoConstraints = false 41 | button.backgroundColor = DDKitSwift.UIConfig.floatButtonColor 42 | button.dd.addLayerShadow(color: UIColor.dd.color(hexValue: 0x171619), offset: CGSize(width: 0, height: 0), radius: 5, cornerRadius: 30) 43 | button.layer.borderColor = UIColor.dd.color(hexValue: 0xffffff, alpha: 0.9).cgColor 44 | button.layer.borderWidth = 3.5 45 | button.addTarget(self, action: #selector(_clickFloatButton), for: .touchUpInside) 46 | let pan = UIPanGestureRecognizer(target: self, action: #selector(_touchMove(p:))) 47 | button.addGestureRecognizer(pan) 48 | return button 49 | }() 50 | } 51 | 52 | private extension DDKitSwiftFloatWindow { 53 | func _initVC() { 54 | self.rootViewController = UIViewController() 55 | self.windowLevel = UIWindow.Level.alert 56 | self.isUserInteractionEnabled = true 57 | } 58 | 59 | func _createUI() { 60 | guard let rootViewController = self.rootViewController else { 61 | return 62 | } 63 | rootViewController.view.addSubview(mButton) 64 | mButton.centerXAnchor.constraint(equalTo: rootViewController.view.centerXAnchor).isActive = true 65 | mButton.centerYAnchor.constraint(equalTo: rootViewController.view.centerYAnchor).isActive = true 66 | mButton.widthAnchor.constraint(equalToConstant: 60).isActive = true 67 | mButton.heightAnchor.constraint(equalToConstant: 60).isActive = true 68 | 69 | mButton.addSubview(mLogoImageView) 70 | mLogoImageView.centerXAnchor.constraint(equalTo: mButton.centerXAnchor).isActive = true 71 | mLogoImageView.centerYAnchor.constraint(equalTo: mButton.centerYAnchor).isActive = true 72 | mLogoImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true 73 | mLogoImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true 74 | } 75 | 76 | @objc func _touchMove(p:UIPanGestureRecognizer) { 77 | guard let window = DDUtils.shared.getCurrentNormalWindow() else { return } 78 | let panPoint = p.location(in: window) 79 | //跟随手指拖拽 80 | if p.state == .changed { 81 | self.center = CGPoint(x: panPoint.x, y: panPoint.y) 82 | p.setTranslation(CGPoint.zero, in: self) 83 | } 84 | //弹回边界 85 | if p.state == .ended || p.state == .cancelled { 86 | self._resetPosition() 87 | p.setTranslation(CGPoint.zero, in: self) 88 | } 89 | } 90 | 91 | func _resetPosition() { 92 | guard let window = DDUtils.shared.getCurrentNormalWindow() else { return } 93 | var x: CGFloat = 50 94 | if self.center.x > (window.bounds.size.width) / 2.0 { 95 | x = window.bounds.size.width - 50 96 | } else { 97 | x = 50 98 | } 99 | let y = min(max(130, self.center.y), window.bounds.size.height - 140) 100 | UIView.animate(withDuration: 0.35) { 101 | self.center = CGPoint(x: x, y: y) 102 | } 103 | } 104 | 105 | @objc func _clickFloatButton() { 106 | DDKitSwift.show() 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pod/DDKitSwiftPluginCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftPluginCollectionViewCell.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | class DDKitSwiftPluginCollectionViewCell: UICollectionViewCell { 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | self.createUI() 14 | } 15 | 16 | required init?(coder: NSCoder) { 17 | fatalError("init(coder:) has not been implemented") 18 | } 19 | 20 | func createUI() { 21 | self.contentView.addSubview(mContentView) 22 | mContentView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 13).isActive = true 23 | mContentView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true 24 | mContentView.widthAnchor.constraint(equalToConstant: 50).isActive = true 25 | mContentView.heightAnchor.constraint(equalToConstant: 50).isActive = true 26 | 27 | mContentView.addSubview(mIconImageView) 28 | mIconImageView.centerXAnchor.constraint(equalTo: self.mContentView.centerXAnchor).isActive = true 29 | mIconImageView.centerYAnchor.constraint(equalTo: self.mContentView.centerYAnchor).isActive = true 30 | mIconImageView.widthAnchor.constraint(equalToConstant: 23).isActive = true 31 | mIconImageView.heightAnchor.constraint(equalToConstant: 23).isActive = true 32 | 33 | mContentView.addSubview(mContentLabel) 34 | mContentLabel.topAnchor.constraint(equalTo: self.mContentView.topAnchor).isActive = true 35 | mContentLabel.bottomAnchor.constraint(equalTo: self.mContentView.bottomAnchor).isActive = true 36 | mContentLabel.leftAnchor.constraint(equalTo: self.mContentView.leftAnchor).isActive = true 37 | mContentLabel.rightAnchor.constraint(equalTo: self.mContentView.rightAnchor).isActive = true 38 | 39 | self.contentView.addSubview(mStatusView) 40 | mStatusView.topAnchor.constraint(equalTo: self.mContentView.topAnchor, constant: -2).isActive = true 41 | mStatusView.leftAnchor.constraint(equalTo: self.mContentView.leftAnchor, constant: -2).isActive = true 42 | mStatusView.widthAnchor.constraint(equalToConstant: 10).isActive = true 43 | mStatusView.heightAnchor.constraint(equalToConstant: 10).isActive = true 44 | 45 | 46 | self.contentView.addSubview(mTitleLabel) 47 | mTitleLabel.topAnchor.constraint(equalTo: self.mContentView.bottomAnchor, constant: 4).isActive = true 48 | mTitleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 10).isActive = true 49 | mTitleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -10).isActive = true 50 | } 51 | 52 | func updateUI(plugin: DDKitSwiftPluginProtocol, config: DDPluginItemConfig) { 53 | mTitleLabel.text = plugin.pluginTitle 54 | mStatusView.isHidden = !plugin.isRunning 55 | 56 | self.mContentView.backgroundColor = UIColor.dd.color(hexValue: 0x171619) 57 | switch config { 58 | case .default: 59 | self.mContentLabel.isHidden = true 60 | self.mIconImageView.isHidden = false 61 | self.mIconImageView.image = plugin.pluginIcon 62 | case .text(let title, let backgroundColor): 63 | self.mContentLabel.isHidden = false 64 | self.mIconImageView.isHidden = true 65 | self.mContentView.backgroundColor = backgroundColor 66 | self.mContentLabel.attributedText = title 67 | case .image(let image): 68 | self.mContentLabel.isHidden = true 69 | self.mIconImageView.isHidden = false 70 | self.mIconImageView.image = image 71 | } 72 | } 73 | 74 | //MARK: UI 75 | lazy var mContentView: UIView = { 76 | let view = UIView() 77 | view.translatesAutoresizingMaskIntoConstraints = false 78 | view.backgroundColor = UIColor.dd.color(hexValue: 0x171619) 79 | view.layer.masksToBounds = true 80 | view.layer.cornerRadius = 25 81 | view.layer.borderWidth = 3.5 82 | view.layer.borderColor = UIColor.dd.color(hexValue: 0xd8e3e7).cgColor 83 | return view 84 | }() 85 | lazy var mIconImageView: UIImageView = { 86 | let tImageView = UIImageView() 87 | tImageView.translatesAutoresizingMaskIntoConstraints = false 88 | return tImageView 89 | }() 90 | 91 | lazy var mContentLabel: UILabel = { 92 | let tLabel = UILabel() 93 | tLabel.isHidden = true 94 | tLabel.translatesAutoresizingMaskIntoConstraints = false 95 | tLabel.numberOfLines = 2 96 | tLabel.textAlignment = .center 97 | tLabel.font = .systemFont(ofSize: 13, weight: .medium) 98 | tLabel.textColor = UIColor.dd.color(hexValue: 0x333333) 99 | tLabel.layer.masksToBounds = true 100 | tLabel.layer.cornerRadius = 22 101 | tLabel.layer.borderWidth = 3 102 | tLabel.layer.borderColor = UIColor.dd.color(hexValue: 0xd8e3e7).cgColor 103 | return tLabel 104 | }() 105 | 106 | 107 | lazy var mTitleLabel: UILabel = { 108 | let tLabel = UILabel() 109 | tLabel.translatesAutoresizingMaskIntoConstraints = false 110 | tLabel.numberOfLines = 2 111 | tLabel.textAlignment = .center 112 | tLabel.font = .systemFont(ofSize: 13, weight: .medium) 113 | tLabel.textColor = UIColor.dd.color(hexValue: 0x1a1a1a) 114 | return tLabel 115 | }() 116 | 117 | lazy var mStatusView: UIView = { 118 | let tView = UIView() 119 | tView.translatesAutoresizingMaskIntoConstraints = false 120 | tView.isHidden = true 121 | tView.backgroundColor = UIColor.dd.color(hexValue: 0x81b214) 122 | tView.layer.masksToBounds = true 123 | tView.layer.cornerRadius = 5 124 | return tView 125 | }() 126 | } 127 | -------------------------------------------------------------------------------- /pod/DDKitSwiftPluginProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftPluginProtocol.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | public enum DDKitSwiftPluginType { 11 | case ui 12 | case data 13 | case other 14 | } 15 | 16 | public protocol DDKitSwiftPluginProtocol { 17 | var pluginIdentifier: String { get } 18 | var pluginIcon: UIImage? { get } 19 | var pluginTitle: String { get } 20 | var pluginType: DDKitSwiftPluginType { get } 21 | var isRunning: Bool { get } 22 | 23 | func didRegist() 24 | func willStart() 25 | func start() 26 | func willStop() 27 | func stop() 28 | } 29 | 30 | public extension DDKitSwiftPluginProtocol { 31 | func didRegist() { 32 | 33 | } 34 | 35 | func willStart() { 36 | 37 | } 38 | 39 | func willStop() { 40 | 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /pod/DDKitSwiftUIConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftUIConfig.swift 3 | // DDKitSwiftCore 4 | // 5 | // Created by Damon on 2022/7/23. 6 | // 7 | 8 | import Foundation 9 | import DDUtils 10 | 11 | public struct DDKitSwiftUIConfig { 12 | public var floatButtonColor = UIColor.dd.color(hexValue: 0x333333) //悬浮窗按钮颜色 13 | public var collectionViewBackgroundColor = UIColor.dd.color(hexValue: 0xffffff, alpha: 0.9) 14 | public var collectionViewTitleColor = UIColor.dd.color(hexValue: 0xffffff) 15 | public var collectionViewTitleBackgroundColor = UIColor.dd.color(hexValue: 0x5dae8b) 16 | } 17 | -------------------------------------------------------------------------------- /pod/DDKitSwiftWindow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DDKitSwiftWindow.swift 3 | // DDKitSwift 4 | // 5 | // Created by Damon on 2021/4/23. 6 | // 7 | 8 | import UIKit 9 | 10 | public enum DDPluginItemConfig { 11 | case `default` 12 | case text(title: NSAttributedString, backgroundColor: UIColor) 13 | case image(image: UIImage) 14 | } 15 | 16 | class DDKitSwiftWindow: UIWindow { 17 | var currentNavVC: UINavigationController? 18 | var collectionList: [[(DDKitSwiftPluginProtocol, DDPluginItemConfig)]] = [] 19 | 20 | @available(iOS 13.0, *) 21 | override init(windowScene: UIWindowScene) { 22 | super.init(windowScene: windowScene) 23 | self._initVC() 24 | self._loadData() 25 | self._createUI() 26 | } 27 | 28 | override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | self._initVC() 31 | self._createUI() 32 | } 33 | 34 | required init?(coder: NSCoder) { 35 | fatalError("init(coder:) has not been implemented") 36 | } 37 | 38 | //MARK: UI 39 | lazy var mCollectionView: UICollectionView = { 40 | let tCollectionViewLayout = UICollectionViewFlowLayout() 41 | tCollectionViewLayout.itemSize = CGSize(width: UIScreen.main.bounds.width / 4, height: UIScreen.main.bounds.width / 4) 42 | tCollectionViewLayout.scrollDirection = UICollectionView.ScrollDirection.vertical 43 | tCollectionViewLayout.minimumLineSpacing = 0 44 | tCollectionViewLayout.minimumInteritemSpacing = 0 45 | tCollectionViewLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 40) 46 | let tCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: tCollectionViewLayout) 47 | tCollectionView.translatesAutoresizingMaskIntoConstraints = false 48 | tCollectionView.contentInsetAdjustmentBehavior = .never 49 | tCollectionView.backgroundColor = UIColor.clear 50 | tCollectionView.dataSource = self 51 | tCollectionView.delegate = self 52 | tCollectionView.isPagingEnabled = false 53 | tCollectionView.showsHorizontalScrollIndicator = false 54 | tCollectionView.register(DDKitSwiftPluginCollectionViewCell.self, forCellWithReuseIdentifier: "DDKitSwiftPluginCollectionViewCell") 55 | tCollectionView.register(DDKitSwiftCollectionViewHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "DDKitSwiftCollectionViewHeaderView") 56 | return tCollectionView 57 | }() 58 | } 59 | 60 | extension DDKitSwiftWindow { 61 | func reloadData() { 62 | self.mCollectionView.reloadData() 63 | } 64 | 65 | func updateListItem(plugin: DDKitSwiftPluginProtocol, config: DDPluginItemConfig) { 66 | var section = 0 67 | switch plugin.pluginType { 68 | case .ui: 69 | section = 0 70 | case .data: 71 | section = 1 72 | case .other: 73 | section = 2 74 | } 75 | let list = self.collectionList[section] 76 | if let index = list.firstIndex(where: { item in 77 | return item.0.pluginIdentifier == plugin.pluginIdentifier 78 | }) { 79 | var item = list[index] 80 | item.1 = config 81 | self.collectionList[section][index] = item 82 | self.mCollectionView.reloadItems(at: [IndexPath(item: index, section: section)]) 83 | } 84 | } 85 | } 86 | 87 | extension DDKitSwiftWindow: UICollectionViewDelegate,UICollectionViewDataSource { 88 | func numberOfSections(in collectionView: UICollectionView) -> Int { 89 | return self.collectionList.count 90 | } 91 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 92 | return self.collectionList[section].count 93 | } 94 | 95 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 96 | let pluginItem = self.collectionList[indexPath.section][indexPath.item] 97 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DDKitSwiftPluginCollectionViewCell", for: indexPath) as! DDKitSwiftPluginCollectionViewCell 98 | cell.updateUI(plugin: pluginItem.0, config: pluginItem.1) 99 | return cell 100 | } 101 | 102 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 103 | let title = ["UI".ZXLocaleString, "Data".ZXLocaleString, "Other".ZXLocaleString] 104 | let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "DDKitSwiftCollectionViewHeaderView", for: indexPath) as! DDKitSwiftCollectionViewHeaderView 105 | cell.updateUI(title: title[indexPath.section]) 106 | return cell 107 | } 108 | 109 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 110 | let plugin = DDKitSwift.pluginList[indexPath.section][indexPath.item] 111 | if plugin.isRunning { 112 | plugin.willStop() 113 | plugin.stop() 114 | self.reloadData() 115 | } else { 116 | plugin.willStart() 117 | plugin.start() 118 | self.reloadData() 119 | } 120 | 121 | } 122 | } 123 | 124 | private extension DDKitSwiftWindow { 125 | func _initVC() { 126 | self.backgroundColor = DDKitSwift.UIConfig.collectionViewBackgroundColor 127 | let rootViewController = UIViewController() 128 | 129 | self.currentNavVC = UINavigationController(rootViewController: rootViewController) 130 | self.currentNavVC!.navigationBar.barTintColor = UIColor.white 131 | //set title 132 | let view = UIView() 133 | let label = UILabel() 134 | label.translatesAutoresizingMaskIntoConstraints = false 135 | label.attributedText = NSAttributedString(string: "DDKitSwift", attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: 18, weight: .medium), NSAttributedString.Key.foregroundColor:UIColor.black]) 136 | view.addSubview(label) 137 | label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 138 | label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 139 | 140 | rootViewController.navigationItem.titleView = view 141 | //navigationBar 142 | let button = UIButton(frame: .init(x: 0, y: 0, width: 25, height: 25)) 143 | button.setImage(UIImageHDBoundle(named: "log_icon_close"), for: .normal) 144 | button.addTarget(self, action: #selector(_closeBarItemClick), for: .touchUpInside) 145 | NSLayoutConstraint(item: button, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 25).isActive = true 146 | NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 25).isActive = true 147 | let leftbarItem = UIBarButtonItem(customView: button) 148 | 149 | let button1 = UIButton(frame: .init(x: 0, y: 0, width: 25, height: 25)) 150 | button1.setImage(UIImageHDBoundle(named: "log_icon_subtract"), for: .normal) 151 | button1.addTarget(self, action: #selector(_hideBarItemClick), for: .touchUpInside) 152 | NSLayoutConstraint(item: button1, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 25).isActive = true 153 | NSLayoutConstraint(item: button1, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 25).isActive = true 154 | let leftbarItem1 = UIBarButtonItem(customView: button1) 155 | rootViewController.navigationItem.leftBarButtonItems = [leftbarItem, leftbarItem1] 156 | // 157 | self.rootViewController = self.currentNavVC 158 | self.windowLevel = UIWindow.Level.alert 159 | self.isUserInteractionEnabled = true 160 | } 161 | 162 | @objc func _hideBarItemClick() { 163 | DDKitSwift.hide() 164 | } 165 | 166 | @objc func _closeBarItemClick() { 167 | DDKitSwift.close() 168 | } 169 | 170 | func _loadData() { 171 | self.collectionList = DDKitSwift.pluginList.map({ protocolList in 172 | return protocolList.map { protocolItem in 173 | return (protocolItem, .default) 174 | } 175 | }) 176 | } 177 | 178 | func _createUI() { 179 | guard let navigationController = self.rootViewController as? UINavigationController, let rootViewController = navigationController.topViewController else { 180 | return 181 | } 182 | 183 | rootViewController.view.addSubview(mCollectionView) 184 | mCollectionView.leftAnchor.constraint(equalTo: rootViewController.view.leftAnchor).isActive = true 185 | mCollectionView.rightAnchor.constraint(equalTo: rootViewController.view.rightAnchor).isActive = true 186 | mCollectionView.topAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.topAnchor).isActive = true 187 | mCollectionView.bottomAnchor.constraint(equalTo: rootViewController.view.safeAreaLayoutGuide.bottomAnchor).isActive = true 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /pod/assets/icon/icon_close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_close@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_home@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_home@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_list@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_list@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_notice@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_notice@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_search@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_setting@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_setting@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/icon_share@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/icon_share@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/log_icon_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/log_icon_close.png -------------------------------------------------------------------------------- /pod/assets/icon/log_icon_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/log_icon_scale.png -------------------------------------------------------------------------------- /pod/assets/icon/log_icon_subtract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/log_icon_subtract.png -------------------------------------------------------------------------------- /pod/assets/icon/logger_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/logger_logo@3x.png -------------------------------------------------------------------------------- /pod/assets/icon/zx_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/pod/assets/icon/zx_logo@3x.png -------------------------------------------------------------------------------- /pod/assets/localizable/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "Benutzeroberfläche"; 9 | "Data" = "Daten"; 10 | "Other" = "Andere"; 11 | "App Log" = "App-Log"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "UI"; 9 | "Data" = "Data"; 10 | "Other" = "Other"; 11 | "App Log" = "App Log"; 12 | -------------------------------------------------------------------------------- /pod/assets/localizable/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "Interfaz"; 9 | "Data" = "Datos"; 10 | "Other" = "Otro"; 11 | "App Log" = "Registro de la aplicación"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "Interface"; 9 | "Data" = "Données"; 10 | "Other" = "Autre"; 11 | "App Log" = "Journal de l'app"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "UI"; 9 | "Data" = "データ"; 10 | "Other" = "その他"; 11 | "App Log" = "アプリログ"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/ko.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "UI"; 9 | "Data" = "데이터"; 10 | "Other" = "기타"; 11 | "App Log" = "앱 로그"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/ru.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "Интерфейс"; 9 | "Data" = "Данные"; 10 | "Other" = "Другое"; 11 | "App Log" = "Журнал приложения"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/th.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "อินเทอร์เฟซ"; 9 | "Data" = "ข้อมูล"; 10 | "Other" = "อื่นๆ"; 11 | "App Log" = "บันทึกแอป"; 12 | 13 | -------------------------------------------------------------------------------- /pod/assets/localizable/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "UI界面"; 9 | "Data" = "数据相关"; 10 | "Other" = "其他工具"; 11 | "App Log" = "App日志"; 12 | -------------------------------------------------------------------------------- /pod/assets/localizable/zh-Hant.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | DDKitSwift 4 | 5 | Created by Damon on 2021/4/25. 6 | 7 | */ 8 | "UI" = "介面"; 9 | "Data" = "資料"; 10 | "Other" = "其他"; 11 | "App Log" = "App日誌"; 12 | 13 | -------------------------------------------------------------------------------- /pod/extend/DDLoggerSwift+ddkit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZXLogger+zxkit.swift 3 | // DDLoggerSwift 4 | // 5 | // Created by Damon on 2021/4/25. 6 | // Copyright © 2021 Damon. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import DDLoggerSwift 11 | 12 | //DDKitSwiftPlugin 13 | extension DDLoggerSwift: DDKitSwiftPluginProtocol { 14 | public var pluginIdentifier: String { 15 | return "com.zxkit.zxkitLogger" 16 | } 17 | 18 | public var pluginIcon: UIImage? { 19 | return UIImageHDBoundle(named: "logger_logo") 20 | } 21 | 22 | public var pluginTitle: String { 23 | return "App Log".ZXLocaleString 24 | } 25 | 26 | public var pluginType: DDKitSwiftPluginType { 27 | return .data 28 | } 29 | 30 | public func didRegist() { 31 | NotificationCenter.default.addObserver(self, selector: #selector(_loggerDidHidden), name: .DDLoggerSwiftDidHidden, object: nil) 32 | } 33 | 34 | public func start() { 35 | DDKitSwift.hide() 36 | DDLoggerSwift.show() 37 | } 38 | 39 | public var isRunning: Bool { 40 | return true 41 | } 42 | 43 | public func stop() { 44 | DDKitSwift.hide() 45 | DDLoggerSwift.show() 46 | } 47 | } 48 | 49 | extension DDLoggerSwift { 50 | @objc func _loggerDidHidden() { 51 | DDLoggerSwift.close() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /preview_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DamonHu/DDKitSwift/cc3a40a2014391cc89734acddab66d7ee9a0c2c7/preview_1.jpg --------------------------------------------------------------------------------