diff --git a/Android Tool/Assembling Tool/AssemblingFileTool.exe b/Android Tool/Assembling Tool/AssemblingFileTool.exe deleted file mode 100644 index 9a64dfa..0000000 Binary files a/Android Tool/Assembling Tool/AssemblingFileTool.exe and /dev/null differ diff --git a/Android Tool/CH583_OTA Upgrade Tool Manual.pdf b/Android Tool/CH583_OTA Upgrade Tool Manual.pdf deleted file mode 100644 index 2a541e3..0000000 Binary files a/Android Tool/CH583_OTA Upgrade Tool Manual.pdf and /dev/null differ diff --git "a/Android Tool/CH583_OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" "b/Android Tool/CH583_OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" deleted file mode 100644 index 4f21433..0000000 Binary files "a/Android Tool/CH583_OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" and /dev/null differ diff --git a/Android Tool/OTA Tool source/CH583Update.zip b/Android Tool/OTA Tool source/CH583Update.zip deleted file mode 100644 index bac809e..0000000 Binary files a/Android Tool/OTA Tool source/CH583Update.zip and /dev/null differ diff --git a/Android Tool/OTA Tool/CH583 OTA Tool.apk b/Android Tool/OTA Tool/CH583 OTA Tool.apk deleted file mode 100644 index 6f218ba..0000000 Binary files a/Android Tool/OTA Tool/CH583 OTA Tool.apk and /dev/null differ diff --git "a/Android Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.pdf" "b/Android Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.pdf" deleted file mode 100644 index a8e9268..0000000 Binary files "a/Android Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.pdf" and /dev/null differ diff --git a/Tool/AssemblingFileTool/WCH_AssemblingFileTool.exe b/Tool/AssemblingFileTool/WCH_AssemblingFileTool.exe new file mode 100644 index 0000000..dad7e21 Binary files /dev/null and b/Tool/AssemblingFileTool/WCH_AssemblingFileTool.exe differ diff --git a/Tool/OTA_Tool/BLE_OTA_Android/WCHOTAUpdate_V1.2.apk b/Tool/OTA_Tool/BLE_OTA_Android/WCHOTAUpdate_V1.2.apk new file mode 100644 index 0000000..c05b8fa Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_Android/WCHOTAUpdate_V1.2.apk differ diff --git a/Tool/OTA_Tool/BLE_OTA_Android/demo/OTAUpdate.zip b/Tool/OTA_Tool/BLE_OTA_Android/demo/OTAUpdate.zip new file mode 100644 index 0000000..10728b4 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_Android/demo/OTAUpdate.zip differ diff --git "a/Tool/OTA_Tool/BLE_OTA_Android/\345\256\211\345\215\223OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" "b/Tool/OTA_Tool/BLE_OTA_Android/\345\256\211\345\215\223OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" new file mode 100644 index 0000000..455d4d7 Binary files /dev/null and "b/Tool/OTA_Tool/BLE_OTA_Android/\345\256\211\345\215\223OTA\345\215\207\347\272\247\345\267\245\345\205\267\344\275\277\347\224\250\350\257\264\346\230\216.pdf" differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.pbxproj b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.pbxproj new file mode 100644 index 0000000..95be170 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.pbxproj @@ -0,0 +1,392 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 775CC93328127F1A0032CFE4 /* HexToBin.h in Headers */ = {isa = PBXBuildFile; fileRef = 775CC93128127F1A0032CFE4 /* HexToBin.h */; }; + 775CC93428127F1A0032CFE4 /* HexToBin.m in Sources */ = {isa = PBXBuildFile; fileRef = 775CC93228127F1A0032CFE4 /* HexToBin.m */; }; + 777D6DFF280563FE003E2728 /* CurrentImageObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 777D6DFD280563FE003E2728 /* CurrentImageObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 777D6E00280563FE003E2728 /* CurrentImageObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 777D6DFE280563FE003E2728 /* CurrentImageObject.m */; }; + 77B81B862806544F001BFF9B /* BLEOTACmd.h in Headers */ = {isa = PBXBuildFile; fileRef = 77B81B842806544F001BFF9B /* BLEOTACmd.h */; }; + 77B81B872806544F001BFF9B /* BLEOTACmd.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B81B852806544F001BFF9B /* BLEOTACmd.m */; }; + 77E19F2327FE781000FE6D8D /* BLEOTALibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E19F2227FE781000FE6D8D /* BLEOTALibrary.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77E19F3927FE794700FE6D8D /* BLEOTAManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E19F3727FE794700FE6D8D /* BLEOTAManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77E19F3A27FE794700FE6D8D /* BLEOTAManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E19F3827FE794700FE6D8D /* BLEOTAManager.m */; }; + 77E19F3D27FE79DC00FE6D8D /* CBAdvertisementData.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E19F3B27FE79DC00FE6D8D /* CBAdvertisementData.h */; }; + 77E19F3E27FE79DC00FE6D8D /* CBAdvertisementData.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E19F3C27FE79DC00FE6D8D /* CBAdvertisementData.m */; }; + 77E19F4427FE837500FE6D8D /* Constant.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E19F4327FE837500FE6D8D /* Constant.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 775CC93128127F1A0032CFE4 /* HexToBin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HexToBin.h; sourceTree = ""; }; + 775CC93228127F1A0032CFE4 /* HexToBin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HexToBin.m; sourceTree = ""; }; + 777D6DFD280563FE003E2728 /* CurrentImageObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CurrentImageObject.h; sourceTree = ""; }; + 777D6DFE280563FE003E2728 /* CurrentImageObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CurrentImageObject.m; sourceTree = ""; }; + 77B81B842806544F001BFF9B /* BLEOTACmd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BLEOTACmd.h; sourceTree = ""; }; + 77B81B852806544F001BFF9B /* BLEOTACmd.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BLEOTACmd.m; sourceTree = ""; }; + 77E19F1F27FE781000FE6D8D /* BLEOTALibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BLEOTALibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 77E19F2227FE781000FE6D8D /* BLEOTALibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BLEOTALibrary.h; sourceTree = ""; }; + 77E19F3727FE794700FE6D8D /* BLEOTAManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BLEOTAManager.h; sourceTree = ""; }; + 77E19F3827FE794700FE6D8D /* BLEOTAManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BLEOTAManager.m; sourceTree = ""; }; + 77E19F3B27FE79DC00FE6D8D /* CBAdvertisementData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CBAdvertisementData.h; sourceTree = ""; }; + 77E19F3C27FE79DC00FE6D8D /* CBAdvertisementData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CBAdvertisementData.m; sourceTree = ""; }; + 77E19F4327FE837500FE6D8D /* Constant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constant.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 77E19F1C27FE781000FE6D8D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 77E19F1527FE781000FE6D8D = { + isa = PBXGroup; + children = ( + 77E19F2127FE781000FE6D8D /* BLEOTALibrary */, + 77E19F2027FE781000FE6D8D /* Products */, + ); + sourceTree = ""; + }; + 77E19F2027FE781000FE6D8D /* Products */ = { + isa = PBXGroup; + children = ( + 77E19F1F27FE781000FE6D8D /* BLEOTALibrary.framework */, + ); + name = Products; + sourceTree = ""; + }; + 77E19F2127FE781000FE6D8D /* BLEOTALibrary */ = { + isa = PBXGroup; + children = ( + 77E19F4327FE837500FE6D8D /* Constant.h */, + 77E19F2227FE781000FE6D8D /* BLEOTALibrary.h */, + 77E19F3727FE794700FE6D8D /* BLEOTAManager.h */, + 77E19F3827FE794700FE6D8D /* BLEOTAManager.m */, + 775CC93128127F1A0032CFE4 /* HexToBin.h */, + 775CC93228127F1A0032CFE4 /* HexToBin.m */, + 77B81B842806544F001BFF9B /* BLEOTACmd.h */, + 77B81B852806544F001BFF9B /* BLEOTACmd.m */, + 777D6DFD280563FE003E2728 /* CurrentImageObject.h */, + 777D6DFE280563FE003E2728 /* CurrentImageObject.m */, + 77E19F3B27FE79DC00FE6D8D /* CBAdvertisementData.h */, + 77E19F3C27FE79DC00FE6D8D /* CBAdvertisementData.m */, + ); + path = BLEOTALibrary; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 77E19F1A27FE781000FE6D8D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 77E19F4427FE837500FE6D8D /* Constant.h in Headers */, + 77E19F3D27FE79DC00FE6D8D /* CBAdvertisementData.h in Headers */, + 775CC93328127F1A0032CFE4 /* HexToBin.h in Headers */, + 77B81B862806544F001BFF9B /* BLEOTACmd.h in Headers */, + 777D6DFF280563FE003E2728 /* CurrentImageObject.h in Headers */, + 77E19F3927FE794700FE6D8D /* BLEOTAManager.h in Headers */, + 77E19F2327FE781000FE6D8D /* BLEOTALibrary.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 77E19F1E27FE781000FE6D8D /* BLEOTALibrary */ = { + isa = PBXNativeTarget; + buildConfigurationList = 77E19F2627FE781000FE6D8D /* Build configuration list for PBXNativeTarget "BLEOTALibrary" */; + buildPhases = ( + 77E19F1A27FE781000FE6D8D /* Headers */, + 77E19F1B27FE781000FE6D8D /* Sources */, + 77E19F1C27FE781000FE6D8D /* Frameworks */, + 77E19F1D27FE781000FE6D8D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BLEOTALibrary; + productName = BLEOTALibrary; + productReference = 77E19F1F27FE781000FE6D8D /* BLEOTALibrary.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 77E19F1627FE781000FE6D8D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1310; + TargetAttributes = { + 77E19F1E27FE781000FE6D8D = { + CreatedOnToolsVersion = 13.1; + LastSwiftMigration = 1310; + }; + }; + }; + buildConfigurationList = 77E19F1927FE781000FE6D8D /* Build configuration list for PBXProject "BLEOTALibrary" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 77E19F1527FE781000FE6D8D; + productRefGroup = 77E19F2027FE781000FE6D8D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 77E19F1E27FE781000FE6D8D /* BLEOTALibrary */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 77E19F1D27FE781000FE6D8D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 77E19F1B27FE781000FE6D8D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 775CC93428127F1A0032CFE4 /* HexToBin.m in Sources */, + 77E19F3E27FE79DC00FE6D8D /* CBAdvertisementData.m in Sources */, + 77B81B872806544F001BFF9B /* BLEOTACmd.m in Sources */, + 777D6E00280563FE003E2728 /* CurrentImageObject.m in Sources */, + 77E19F3A27FE794700FE6D8D /* BLEOTAManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 77E19F2427FE781000FE6D8D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 77E19F2527FE781000FE6D8D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 77E19F2727FE781000FE6D8D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 5JZGQTGU4W; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UISupportsDocumentBrowser = YES; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cn.wch.BLEOTALibrary; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 77E19F2827FE781000FE6D8D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 5JZGQTGU4W; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UISupportsDocumentBrowser = YES; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cn.wch.BLEOTALibrary; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 77E19F1927FE781000FE6D8D /* Build configuration list for PBXProject "BLEOTALibrary" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 77E19F2427FE781000FE6D8D /* Debug */, + 77E19F2527FE781000FE6D8D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 77E19F2627FE781000FE6D8D /* Build configuration list for PBXNativeTarget "BLEOTALibrary" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 77E19F2727FE781000FE6D8D /* Debug */, + 77E19F2827FE781000FE6D8D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 77E19F1627FE781000FE6D8D /* Project object */; +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ab97bba Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..b8afd0a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + BLEOTALibrary.xcscheme_^#shared#^_ + + orderHint + 7 + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.h new file mode 100644 index 0000000..d6cd1ff --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.h @@ -0,0 +1,32 @@ +// +// BLEOTACmd.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/13. +// + +#import +#import "Constant.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface BLEOTACmd : NSObject + ++ (NSInteger)updateMTU:(NSInteger)mtu; + ++ (void)updateAddressBase:(ChipType)type; + ++ (NSData *)getImageInfoCommand; + ++ (NSData *)getEraseCommand:(NSInteger)addr block:(NSInteger)block; + ++ (NSData *)getProgrammeCommand:(NSInteger)addr data:(NSData *)bytes; + ++ (NSData *)getVerifyCommand:(NSInteger)addr data:(NSData *)bytes; + + ++ (NSData *)getEndCommand; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.m new file mode 100644 index 0000000..f85c87d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTACmd.m @@ -0,0 +1,132 @@ +// +// BLEOTACmd.m +// BLEOTALibrary +// +// Created by moyun on 2022/4/13. +// + +#import "BLEOTACmd.h" + + +#define CMD_ISP_PROGRAM 0x80 +#define CMD_ISP_ERASE 0x81 +#define CMD_ISP_VERIFY 0x82 +#define CMD_ISP_END 0x83 +#define CMD_ISP_INFO 0x84 + + +NSInteger DATA_LEN = 20; +//地址需要除以它 +//573,583的地址除以16,CH579除以4 +NSInteger ADDRESS_BASE = 16; + +@implementation BLEOTACmd + +//为了提高发送速度编程前交换MTU ++ (NSInteger)updateMTU:(NSInteger)mtu { + DATA_LEN = mtu; + return DATA_LEN; +} + ++ (void)updateAddressBase:(ChipType)type { + if (type == ChipType_CH579 || type == ChipType_UNKNOW) { + ADDRESS_BASE = 4; + }else if (type == ChipType_CH573) { + ADDRESS_BASE = 16; + }else if (type == ChipType_CH583) { + ADDRESS_BASE = 16; + } +} + ++ (NSData *)getImageInfoCommand { + +// struct Info info = {}; +// info.cmd = 0x84; +// info.len = 0x12; +// +// Byte buf[IAP_LEN - 2] = {}; +// memset(buf, 0x00, IAP_LEN - 2); +// memmove(info.buf, buf, IAP_LEN - 2); +// +// NSData *infoCmd = [[NSData alloc] initWithBytes:&info length:sizeof(info)]; + + Byte byteBuffer[IAP_LEN] = {}; + memset(byteBuffer, 0, IAP_LEN); + + byteBuffer[0] = CMD_ISP_INFO; + byteBuffer[1] = IAP_LEN - 2; + + NSData *data = [[NSData alloc] initWithBytes:byteBuffer length:IAP_LEN]; + return data; +} + ++ (NSData *)getEraseCommand:(NSInteger)addr block:(NSInteger)block { + + Byte byteBuffer[IAP_LEN] = {}; + memset(byteBuffer, 0, IAP_LEN); + + byteBuffer[0] = CMD_ISP_ERASE; + byteBuffer[1] = 0x00; + byteBuffer[2] = addr / ADDRESS_BASE; + byteBuffer[3] = ((addr / ADDRESS_BASE) >> 8); + byteBuffer[4] = block; + byteBuffer[5] = block >> 8; + + NSData *data = [[NSData alloc] initWithBytes:byteBuffer length:IAP_LEN]; + return data; +} + ++ (NSData *)getProgrammeCommand:(NSInteger)addr data:(NSData *)bytes { + Byte *byteBuffer = malloc(DATA_LEN); + memset(byteBuffer, 0, DATA_LEN); + + byteBuffer[0] = CMD_ISP_PROGRAM; + byteBuffer[1] = bytes.length; + byteBuffer[2] = addr / ADDRESS_BASE; + byteBuffer[3] = ((addr / ADDRESS_BASE) >> 8); + +// NSLog(@"编程地址:%ld offset:%ld", addr / ADDRESS_BASE, addr); + + Byte *dataByte = (Byte *)[bytes bytes]; + memmove(byteBuffer + 4, dataByte, bytes.length); + + NSData *data = [[NSData alloc] initWithBytes:byteBuffer length:DATA_LEN]; + free(byteBuffer); + + return data; +} + + ++ (NSData *)getVerifyCommand:(NSInteger)addr data:(NSData *)bytes { + Byte *byteBuffer = malloc(DATA_LEN); + memset(byteBuffer, 0, DATA_LEN); + + byteBuffer[0] = CMD_ISP_VERIFY; + byteBuffer[1] = bytes.length; + byteBuffer[2] = addr / ADDRESS_BASE; + byteBuffer[3] = ((addr / ADDRESS_BASE) >> 8); + +// NSLog(@"认证地址:%ld offset:%ld", addr / ADDRESS_BASE, addr); + + Byte *dataByte = (Byte *)[bytes bytes]; + memmove(byteBuffer + 4, dataByte, bytes.length); + + NSData *data = [[NSData alloc] initWithBytes:byteBuffer length:DATA_LEN]; + free(byteBuffer); + + return data; +} + + ++ (NSData *)getEndCommand { + Byte byteBuffer[IAP_LEN] = {}; + memset(byteBuffer, 0, IAP_LEN); + + byteBuffer[0] = CMD_ISP_END; + byteBuffer[1] = IAP_LEN - 2; + + NSData *data = [[NSData alloc] initWithBytes:byteBuffer length:IAP_LEN]; + return data; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTALibrary.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTALibrary.h new file mode 100644 index 0000000..2e4504c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTALibrary.h @@ -0,0 +1,18 @@ +// +// BLEOTALibrary.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/7. +// + +#import + +//! Project version number for BLEOTALibrary. +FOUNDATION_EXPORT double BLEOTALibraryVersionNumber; + +//! Project version string for BLEOTALibrary. +FOUNDATION_EXPORT const unsigned char BLEOTALibraryVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#import "BLEOTAManager.h" diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.h new file mode 100644 index 0000000..e3e6711 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.h @@ -0,0 +1,133 @@ +// +// BLEOTAManager.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/7. +// + +#import +#import +#import "CurrentImageObject.h" + +//OTA升级进度类型 +typedef NS_ENUM(NSUInteger, progressType) { + progressType_Erase = 0, + progressType_EraseSuccess = 1, + progressType_EraseFailed = 2, + progressType_Program = 3, + progressType_ProgramWait = 4, + progressType_ProgramSuccess = 5, + progressType_ProgramFailed = 6, + progressType_Verify = 7, + progressType_VerifyWait = 8, + progressType_VerifySuccess = 9, + progressType_VerifyFailed = 10, + progressType_End = 11, +}; + +typedef void(^writeDataCallBack)(NSInteger); +typedef void(^OTAProgressCallBack)(progressType); +typedef void(^rssiCallBack)(NSNumber *); + +#pragma mark - 代理方法 +@protocol BLEOTADelegate + +//蓝牙状态回调 +- (void)BLEManagerDidUpdateState:(NSError *)error; + +//监听设备连接状态变更通知 +- (void)BLEManagerDidPeripheralConnectUpateState:(CBPeripheral *)peripheral error:(NSError *)error; + +//发现设备回调 +- (void)BLEManagerDidDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; + +//发现服务回调 +- (void)BLEManagerPeriphearl:(CBPeripheral *)peripheral services:(NSArray *)services error:(NSError *)error; + +//发现服务特征回调 +- (void)BLEManagerService:(CBService *)service characteristics:(NSArray *)characteristics error:(NSError *)error; + +//特征通道的值发生改变 +- (void)BLEManagerUpdateValueForCharacteristic:(CBPeripheral *)peripheral Characteristic:(CBCharacteristic *)characteristic error:(NSError *)error; + +@end + +@interface BLEOTAManager : NSObject + +//代理对象 +@property (nonatomic, weak) id delegate; + +//开启调试信息 +@property (nonatomic, assign)BOOL isDebug; + +//可以根据传入的UUID扫描服务 +@property (nonatomic, strong) NSArray * serviceUUIDS; + +/* + *@method 生成单列 + */ ++ (instancetype) shareInstance; + +/* + *@method 开始扫描 + *@param serviceUUIDs 指定的UUID服务 + *@param scanRuler 扫描过滤规则 + */ +- (void)startScan:(NSArray *)serviceUUIDs options:(NSDictionary *)scanRuler; + +/* + *@method 停止扫描 + */ +- (void)stopScan; + +/* + *@method 连接设备 + */ +- (void)connect:(CBPeripheral *)peripheral; + +/* + *@method 断开连接 + */ +- (void)disconnect:(CBPeripheral *)peripheral; + +/* + *@method 获取当前连接的蓝牙设备硬件信息 + *@discussion 返回当前硬件设备的属性对象 + */ +- (CurrentImageObject *)getCurrentImageInfo; + +/* + *@method 设置芯片类型 + *@discussion 对于芯片类型没有获取到的设备建议手动设置 + */ +- (void)setChipType:(ChipType)type; + +/* + *@method hex文件数据转bin + *@param data hex文件的NSData + *@discussion 返回bin格式的data + */ +- (NSData *)hex2BinData:(NSData *)data; + +/* + *@method 开始OTA升级 + *@param data 转换成bin后的NSData + *@param eraseAddr 擦除地址 + *@param writeCallBack 升级步骤回调 + *@param progressCallBack 进度条回调 + */ +- (void)startOTAUpdate:(NSData *)data eraseAddr:(NSInteger)eraseAddr writeCallBack:(writeDataCallBack)writeBlock progressCallBack:(OTAProgressCallBack)progressBlock; + +/* + *@method 取消OTA升级 + */ +- (void)cancleOTAUpdate; + +/* + *@method 读取信号 + @param peripheral 外设对象 + @param rssiCallBack 信号强度回调 + */ +- (void)readRSSI:(CBPeripheral *)peripheral rssiCallBack:(rssiCallBack)rssiBlock; + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.m new file mode 100644 index 0000000..d028ca8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/BLEOTAManager.m @@ -0,0 +1,954 @@ +// +// BLEOTAManager.m +// BLEOTALibrary +// +// Created by moyun on 2022/4/7. +// + +#import "BLEOTAManager.h" +#import "Constant.h" +#import "BLEOTACmd.h" +#import "HexToBin.h" + +@interface BLEOTAManager() + +//蓝牙中心设备主机模式 +@property(nonatomic, strong)CBCentralManager *centralManager; + +//扫描选项 +@property(nonatomic, strong)NSDictionary *scanOptions; + +//============================================================ +//已连接的外设 +@property(nonatomic, strong)CBPeripheral *peripheral; + +//连接中的外设 +@property(nonatomic, strong)CBPeripheral *connectingPeripheral; + +//============================================================ +@property(nonatomic, strong)NSOperationQueue *writeQueue; +@property(nonatomic, strong)NSOperationQueue *cmdQueue; + +//最大的写入数据 +@property(nonatomic, assign)NSInteger writeWithoutMaxLen; +@property(nonatomic, assign)NSInteger writeWithMaxLen; + +//无响应写入 +@property(nonatomic, assign)BOOL canSendWrite; + +//================================================== + +@property (nonatomic, copy) rssiCallBack rssiBlock; + +//OTA升级通道 +@property (nonatomic, strong) CBCharacteristic *otaCharacter; +//是否正在读 +@property (nonatomic, assign) BOOL readResponse; +//是否正在写 +@property (nonatomic, assign) BOOL writeResponse; +//擦除地址是否成功 +@property (nonatomic, assign) BOOL eraseResponse; +//编程是否成功 +@property (nonatomic, assign) BOOL programRespone; +//认证是否成功 +@property (nonatomic, assign) BOOL verifyRespone; + +@property (nonatomic, assign) BOOL cancleUpdate; +//信号量 +@property (nonatomic, strong) dispatch_semaphore_t semaphore; +//芯片信息 +@property (nonatomic, strong) CurrentImageObject *currentImageObject; + +@end + +@implementation BLEOTAManager + +//生成单列 ++ (instancetype) shareInstance { + static BLEOTAManager *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[super allocWithZone:NULL] init]; + }); + + return instance; +} + +// 如果别人init了这个类,就会创建一个新的对象,要保证永远都只为单例对象分配一次内存空间,写法如下: ++ (id)allocWithZone:(struct _NSZone *)zone { + return [BLEOTAManager shareInstance]; +} + +- (id)copyWithZone:(struct _NSZone *)zone { + return [BLEOTAManager shareInstance]; +} + +//初始化方法 +- (instancetype)init { + self = [super init]; + if (self) { + [self setupBLE]; + } + return self; +} + +//设置蓝牙中心管理器 +- (void)setupBLE { + if (self.centralManager == nil) { + NSDictionary *option=@{CBCentralManagerOptionShowPowerAlertKey:@NO}; + CBCentralManager *manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:option]; + self.centralManager = manager; + } + self.isDebug = YES; + self.readResponse = YES; + self.writeResponse = YES; + self.cancleUpdate = NO; + + if (nil == self.cmdQueue) { + self.cmdQueue = [[NSOperationQueue alloc] init]; + } + self.cmdQueue.maxConcurrentOperationCount = 1; +} + +#pragma mark - 扫描外设 + +- (void)startScan:(NSArray *)serviceUUIDs options:(NSDictionary *)scanRuler; { + [self scanBLE:serviceUUIDs options:scanRuler]; +} + +//扫描方法 +- (void)scanBLE:(nullable NSArray *)serviceUUIDs options:(nullable NSDictionary *)options{ + + if (nil == self.centralManager) { + [self setupBLE]; + } + + if (self.centralManager.isScanning) { + [self BLEManagerState:ERROR_INFO_CANCEL_SCAN]; + return; + } + //保存扫描规则 + self.scanOptions = options; + //存在已连接的设备 + if (self.peripheral != nil && self.peripheral.state == CBPeripheralStateConnected) { + //断开当前设备 + [self.centralManager cancelPeripheralConnection:self.peripheral]; + } + [self.centralManager scanForPeripheralsWithServices:serviceUUIDs options:options]; +} + +//停止扫描 +- (void)stopScan { + if (self.centralManager.isScanning) { + [self.centralManager stopScan]; + } +} + +- (NSArray *)retrievePeripheralsWithIdentifiers:(NSArray *)identifiers { + return [self.centralManager retrievePeripheralsWithIdentifiers:identifiers]; +} + +#pragma mark - 发现外设-连接-断开 +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { + + NSString *log = [[NSString alloc] initWithFormat:@"发现设备:%@ 信号:%@ advertisementData:%@", peripheral, RSSI, advertisementData]; + + if (_isDebug){ + NSLog(@"%@", log); + } + + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerDidDiscoverPeripheral:advertisementData:RSSI:)]) { + [self.delegate BLEManagerDidDiscoverPeripheral:peripheral advertisementData:advertisementData RSSI:RSSI]; + } +} + +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { + + NSString *log = [[NSString alloc] initWithFormat:@"连接成功%@", peripheral]; + + if (_isDebug) { + NSLog(@"%@", log); + } + + //取消延迟检测器 + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(checkConnectinState) object:nil]; + [self.centralManager stopScan]; + self.peripheral = peripheral; + self.connectingPeripheral = nil; + //返回连接的外设回调 + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerDidPeripheralConnectUpateState:error:)]){ + [self.delegate BLEManagerDidPeripheralConnectUpateState:peripheral error:nil]; + } + //开始扫描服务 + [self startScanServiceForPeripheral:peripheral]; +} + +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { + + NSString *log = [[NSString alloc] initWithFormat:@"连接失败%@, error:%@", peripheral, error]; + if (_isDebug) { + NSLog(@"%@", log); + } + + if (self.connectingPeripheral == peripheral) { + error = [[NSError alloc] initWithDomain:@"连接超时" code:1001 userInfo:@{NSUnderlyingErrorKey:@"连接超时"}]; + self.connectingPeripheral = nil; + } + + if (self.peripheral == peripheral) { + error = [[NSError alloc] initWithDomain:@"已断开连接" code:1001 userInfo:@{NSUnderlyingErrorKey:@"已断开连接"}]; + self.peripheral = nil; + } + + //返回连接的外设回调 + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerDidPeripheralConnectUpateState:error:)]){ + [self.delegate BLEManagerDidPeripheralConnectUpateState:peripheral error:error]; + } +} + +//连接设备 +- (void)connect:(CBPeripheral *)peripheral { + + if (peripheral == nil) { + NSString *log = [[NSString alloc] initWithFormat:@"没有连接的外设"]; + if (_isDebug) { + NSLog(@"%@", log); + } + return; + } + //断开已经连接的设备 + [self disconnect:self.peripheral]; + + self.connectingPeripheral = peripheral; + //发起连接 + self.peripheral = nil; + [self.centralManager connectPeripheral:peripheral options:nil]; + //延时执行,获取连接状态 +// __weak typeof(self) weakSelf = self; + [self performSelector:@selector(checkConnectinState) withObject:nil afterDelay:2.0f]; +} + +//断开连接 +- (void)disconnect:(CBPeripheral *)peripheral { + + if (peripheral == nil) { + NSString *log = [[NSString alloc] initWithFormat:@"没有连接的外设"]; + if (_isDebug) { + NSLog(@"%@", log); + } + return; + } + + NSString *log = [[NSString alloc] initWithFormat:@"关闭外设连接"]; + if (_isDebug) { + NSLog(@"%@", log); + } + [self.centralManager cancelPeripheralConnection:peripheral]; + self.currentImageObject = nil; +} + +//检查连接状体 +-(void)checkConnectinState { + if (self.peripheral == nil) { + //连接未成功 + NSString *log = [[NSString alloc] initWithFormat:@"外设连接超时、取消连接"]; + if (_isDebug){ + NSLog(@"%@", log); + } + if (self.connectingPeripheral != nil) { + [self.centralManager cancelPeripheralConnection:self.connectingPeripheral]; + } + } +} + +- (CurrentImageObject *)getCurrentImageInfo { + //连接成功 + return self.currentImageObject; +} + + +//获取芯片参数信息 +- (void)sendImageCommand { + + if (!self.readResponse || !self.writeResponse) { + return; + } + + __weak typeof(self) weakSelf = self; + NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ + NSData *data = [BLEOTACmd getImageInfoCommand]; + [weakSelf writeData:data peripheral:weakSelf.peripheral writeForChar:weakSelf.otaCharacter type:CBCharacteristicWriteWithResponse]; + + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.writeResponse) { + break; + } + } + }]; + + operation.completionBlock = ^{ + + if (weakSelf.writeResponse) { + + [weakSelf readData:weakSelf.peripheral readValueForChar:weakSelf.otaCharacter]; + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.readResponse) { + break; + } + } + if (weakSelf.readResponse) { + NSData *valueData = [weakSelf.otaCharacter value]; + weakSelf.currentImageObject = [CurrentImageObject phraseImageFromResponse:valueData]; + } + } + weakSelf.readResponse = YES; + weakSelf.writeResponse = YES; + }; + + [self.cmdQueue addOperation:operation]; + +} + +//发送擦除命令 +- (void)sendEraseCmmand:(NSInteger)addr block:(NSInteger)block { + + if (!self.readResponse || !self.writeResponse) { + return; + } + + self.eraseResponse = NO; + + __weak typeof(self) weakSelf = self; + NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ + if (weakSelf.cancleUpdate) { + return; + } + + NSData *data = [BLEOTACmd getEraseCommand:addr block:block]; + [weakSelf writeData:data peripheral:weakSelf.peripheral writeForChar:weakSelf.otaCharacter type:CBCharacteristicWriteWithResponse]; + + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.writeResponse) { + break; + } + } + }]; + + operation.completionBlock = ^{ + + if (weakSelf.writeResponse) { + + if (weakSelf.currentImageObject.chipType == ChipType_CH579 || weakSelf.currentImageObject.chipType == ChipType_UNKNOW) { + [NSThread sleepForTimeInterval:2]; + } + + [weakSelf readData:weakSelf.peripheral readValueForChar:weakSelf.otaCharacter]; + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.readResponse) { + break; + } + } + if (weakSelf.readResponse) { + NSData *valueData = [weakSelf.otaCharacter value]; + Byte *response = (Byte *)[valueData bytes]; + if (response != nil && valueData.length > 0 && response[0] == 0x00) { + weakSelf.eraseResponse = YES; + } + } + } + weakSelf.readResponse = YES; + weakSelf.writeResponse = YES; + }; + + [self.cmdQueue addOperation:operation]; + +} + +//发送结束命令 +- (void)sendEndCmmand:(OTAProgressCallBack)progressCallBack { + + if (!self.readResponse || !self.writeResponse) { + return; + } + + self.eraseResponse = NO; + + __weak typeof(self) weakSelf = self; + NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ + if (weakSelf.cancleUpdate) { + return; + } + + NSData *data = [BLEOTACmd getEndCommand]; + [weakSelf writeData:data peripheral:weakSelf.peripheral writeForChar:weakSelf.otaCharacter type:CBCharacteristicWriteWithResponse]; + + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.writeResponse) { + break; + } + } + }]; + + operation.completionBlock = ^{ + weakSelf.writeResponse = YES; + if (nil != progressCallBack) { + progressCallBack(progressType_End); + } + }; + + [self.cmdQueue addOperation:operation]; +} + +- (void)udpataDataStream:(NSData *)data startAddr:(NSInteger)startAddr writeCallBack:(writeDataCallBack)writeBlock progressCallBack:(OTAProgressCallBack)progressBlock isProgram:(BOOL)isProgram { + + //升级数据为空,不存在 + if (data == nil) { + return; + } + + if (self.cancleUpdate) { + return; + } + + //数据下发队列 + self.writeQueue = [[NSOperationQueue alloc] init]; + + self.writeQueue.maxConcurrentOperationCount = 1; + [self.writeQueue cancelAllOperations]; + [self.writeQueue setSuspended:NO]; + + //初始化信号量 + self.semaphore = dispatch_semaphore_create(0); + + //是否可编程 + if (isProgram) { + self.programRespone = NO; + }else { + self.verifyRespone = NO; + } + + + NSInteger maxLen; + //蓝牙一包数据的最大长度 + maxLen = [BLEOTACmd updateMTU:[self getSpecificMaxPacketForOTAAlign:self.writeWithoutMaxLen]] - 4; + + NSInteger dataLen = data.length; + NSInteger writeNum = 0; + __block NSInteger offset = 0; + + //分解数据包 + if (dataLen <= maxLen) { + writeNum = 1; + }else { + writeNum = ceilf(dataLen / (float)maxLen); + } + + if (isProgram) { + //编程流程 + if (nil != progressBlock) { + progressBlock(progressType_Program); + } + }else { + //校验流程 + if (nil != progressBlock) { + progressBlock(progressType_Verify); + } + } + + @autoreleasepool { + + //进行数据异步发包 + for (int i = 0; i < writeNum; i++) { + + NSData *writeData = nil; + if (dataLen >= (i + 1) * maxLen) { + writeData = [data subdataWithRange:NSMakeRange(i * maxLen, maxLen)]; + }else { + NSInteger spaceSize = dataLen - i * maxLen; + writeData = [data subdataWithRange:NSMakeRange(i * maxLen, spaceSize)]; + } + + __weak typeof(self) weakSelf = self; + NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ + + if (weakSelf.cancleUpdate) { + [weakSelf.writeQueue cancelAllOperations]; + return; + } + + [weakSelf.writeQueue setSuspended:YES]; + weakSelf.canSendWrite = [weakSelf.peripheral canSendWriteWithoutResponse]; + + if (!weakSelf.canSendWrite) { + //等待无响应写数据超时 + for (int i = 1; i <= TIMEOUT_REPEAT_NUM; i++) { + [NSThread sleepForTimeInterval:SleepTimeGap]; + weakSelf.canSendWrite = [weakSelf.peripheral canSendWriteWithoutResponse]; + if (weakSelf.canSendWrite) { + //无响应写结果返回 + break; + } + + //无响应写超时 + if (i == TIMEOUT_REPEAT_NUM) { + [weakSelf.writeQueue cancelAllOperations]; + if (isProgram) { + if (nil != progressBlock) { + progressBlock(progressType_ProgramFailed); + } + }else { + if (nil != progressBlock) { + progressBlock(progressType_VerifyFailed); + } + } + dispatch_semaphore_signal(weakSelf.semaphore); + return; + } + } + } + + //开始组包 + NSData *sendData; + + if (isProgram) { + sendData = [BLEOTACmd getProgrammeCommand:offset + startAddr data:writeData]; + }else { + sendData = [BLEOTACmd getVerifyCommand:offset + startAddr data:writeData]; + } + + //组包后位置偏移 + offset += writeData.length; + [weakSelf writeData:sendData peripheral:self.peripheral writeForChar:self.otaCharacter type:CBCharacteristicWriteWithoutResponse]; + }]; + + //每包数据写完后的回调 + operation.completionBlock = ^{ + + if (weakSelf.cancleUpdate) { + [weakSelf.writeQueue cancelAllOperations]; + return; + } + + + if (nil != writeBlock) { + writeBlock(writeData.length); + } + + //如果是最后一包,读取数据下发状态 + if (i == writeNum - 1) { + + [NSThread sleepForTimeInterval:1]; + if (isProgram) { + + weakSelf.programRespone = YES; + if (weakSelf.currentImageObject.chipType == ChipType_CH579) { + + + }else { + //读取编程结果 + [weakSelf readData:weakSelf.peripheral readValueForChar:weakSelf.otaCharacter]; + //等待结果读取 + + if (nil != progressBlock) { + progressBlock(progressType_ProgramWait); + } + + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.01]; + if (weakSelf.readResponse) { + break; + } + } + + if (weakSelf.readResponse) { + + NSData *valueData = [weakSelf.otaCharacter value]; + Byte *response = (Byte *)[valueData bytes]; + if (response != nil && valueData.length > 0 && response[0] == 0x00) { + weakSelf.programRespone = YES; + if (nil != progressBlock) { + progressBlock(progressType_ProgramSuccess); + } + }else { + weakSelf.programRespone = NO; + if (nil != progressBlock) { + progressBlock(progressType_ProgramFailed); + } + } + }else { + weakSelf.programRespone = NO; + if (nil != progressBlock) { + progressBlock(progressType_ProgramFailed); + } + } + + //读取操作复位 + weakSelf.readResponse = YES; + } + + }else { + + weakSelf.verifyRespone = YES; + //读取校验结果 + [weakSelf readData:weakSelf.peripheral readValueForChar:weakSelf.otaCharacter]; + //等待校验读取 + if (nil != progressBlock) { + progressBlock(progressType_VerifyWait); + } + + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.01]; + if (weakSelf.readResponse) { + break; + } + } + + if (weakSelf.readResponse) { + NSData *valueData = [weakSelf.otaCharacter value]; + Byte *response = (Byte *)[valueData bytes]; + if (response != nil && valueData.length > 0 && response[0] == 0x00) { + weakSelf.verifyRespone = YES; + if (nil != progressBlock) { + progressBlock(progressType_VerifySuccess); + } + }else { + weakSelf.verifyRespone = NO; + if (nil != progressBlock) { + progressBlock(progressType_VerifyFailed); + } + } + }else { + weakSelf.verifyRespone = NO; + if (nil != progressBlock) { + progressBlock(progressType_VerifyFailed); + } + } + weakSelf.readResponse = YES; + } + dispatch_semaphore_signal(weakSelf.semaphore); + } + + [weakSelf.writeQueue setSuspended:NO]; + }; + + [weakSelf.writeQueue addOperation:operation]; + } + } +} + + +#pragma mark -- Peripheral + +- (void)startScanServiceForPeripheral:(CBPeripheral *)peripheral { + //设置服务代理回调 + [peripheral setDelegate:self]; + [peripheral discoverServices:self.serviceUUIDS]; +} + +#pragma mark -- CBPeripheralDelegate + +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { + NSString *log = [[NSString alloc] initWithFormat:@"发现服务:%@", peripheral.services]; + if (_isDebug) { + NSLog(@"%@", log); + } + + for (CBService *service in peripheral.services){ + [peripheral discoverCharacteristics:nil forService:service]; + } + + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerPeriphearl:services:error:)]) { + [self.delegate BLEManagerPeriphearl:peripheral services:peripheral.services error:error]; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { + + NSString *log = [[NSString alloc] initWithFormat:@"发现特征通道:%@", service.characteristics]; + if (_isDebug){ + NSLog(@"%@", log); + } + + for (CBCharacteristic *characteristic in service.characteristics) { + NSString *characterUUID = characteristic.UUID.UUIDString; + if ([characterUUID isEqualToString:READ_WRITE_CHARACTER_UUID] && [service.UUID.UUIDString isEqualToString:SERVICE_UUID]) { + self.otaCharacter = characteristic; + _writeWithMaxLen = [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithResponse]; + _writeWithoutMaxLen = [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse]; + log = [[NSString alloc] initWithFormat:@"特征通道写长度:%ld %ld",(long)_writeWithMaxLen, (long)_writeWithoutMaxLen]; + if (_isDebug){ + NSLog(@"%@", log); + } + + [self sendImageCommand]; + [self peripheralNotify:peripheral setNotifyForChar:characteristic]; + } + } + + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerService:characteristics:error:)]) { + [self.delegate BLEManagerService:service characteristics:service.characteristics error:error]; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { + + NSString *log = [[NSString alloc] initWithFormat:@"通知状态改变:%@", characteristic.isNotifying ? @"开启" : @"关闭"]; + if (_isDebug){ + NSLog(@"%@", log); + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { + + NSString *log = [[NSString alloc] initWithFormat:@"监听到了数据:%@, 特征:%@, error:%@", peripheral, characteristic, error]; + if (_isDebug){ + NSLog(@"%@", log); + } + + self.readResponse = YES; + + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerUpdateValueForCharacteristic:Characteristic:error:)]) { + [self.delegate BLEManagerUpdateValueForCharacteristic:peripheral Characteristic:characteristic error:error]; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { + + NSString *log = [[NSString alloc] initWithFormat:@"写入数据:%@ 是否出错:%@", characteristic, error]; + if (_isDebug){ + NSLog(@"%@", log); + } + self.writeResponse = YES; +} + +- (void)peripheralIsReadyToSendWriteWithoutResponse:(CBPeripheral *)peripheral{ + self.canSendWrite = [peripheral canSendWriteWithoutResponse]; + NSString *log = [[NSString alloc] initWithFormat:@"无响应写回调:IsReadyToSendWriteWithoutResponse"]; + if (_isDebug){ + NSLog(@"%@", log); + } +} + +#pragma mark - public func 读/写/订阅 + +- (void)cancleOTAUpdate { + self.cancleUpdate = YES; +} + +- (void)startOTAUpdate:(NSData *)data eraseAddr:(NSInteger)eraseAddr writeCallBack:(writeDataCallBack)writeBlock progressCallBack:(OTAProgressCallBack)progressBlock { + + if (self.currentImageObject == nil || self.peripheral == nil || self.otaCharacter == nil || data == nil) { + return; + } + + self.cancleUpdate = NO; + NSInteger startAddr = 0; + if (self.currentImageObject.chipType == ChipType_CH573 || self.currentImageObject.chipType == ChipType_CH583) { + //CH583/CH573 + //BIN文件擦除地址由用户自己输入 + //HEX文件需要从调用 + startAddr = eraseAddr; + + }else if (self.currentImageObject.chipType == ChipType_CH579) { + if (self.currentImageObject.type == ImageType_A) { + startAddr = self.currentImageObject.offset; + }else if (self.currentImageObject.type == ImageType_B) { + startAddr = 0; + } + } + + NSInteger blockSize = self.currentImageObject.blockSize; + NSInteger nBlocks = (data.length + (blockSize - 1)) / blockSize; + + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + if (nil != progressBlock) { + progressBlock(progressType_Erase); + } + + //发送擦除命令 + [weakSelf sendEraseCmmand:startAddr block:nBlocks]; + + //等待擦除信息返回 + for (int i = 0; i < TIMEOUT_REPEAT_NUM ; i++) { + [NSThread sleepForTimeInterval:0.001]; + if (weakSelf.eraseResponse) { + break; + } + } + + if (weakSelf.eraseResponse) { + //擦除成功开始进行编程 + if (nil != progressBlock) { + progressBlock(progressType_EraseSuccess); + } + [weakSelf udpataDataStream:data startAddr:startAddr writeCallBack:writeBlock progressCallBack:progressBlock isProgram:YES]; + }else { + if (nil != progressBlock) { + progressBlock(progressType_EraseFailed); + } + return; + } + //使用信号量等待更新完成 + if (weakSelf.semaphore) { + dispatch_semaphore_wait(weakSelf.semaphore, DISPATCH_TIME_FOREVER); + } + + //编程完成开始校验 + if (weakSelf.programRespone) { + [weakSelf udpataDataStream:data startAddr:startAddr writeCallBack:writeBlock progressCallBack:progressBlock isProgram:NO]; + }else { + if (nil != progressBlock) { + progressBlock(progressType_ProgramFailed); + } + return; + } + //使用信号量等待校验完成 + if (weakSelf.semaphore) { + dispatch_semaphore_wait(weakSelf.semaphore, DISPATCH_TIME_FOREVER); + } + + //校验成功发送结束 + if (weakSelf.verifyRespone) { + [weakSelf sendEndCmmand:progressBlock]; + }else { + if (nil != progressBlock) { + progressBlock(progressType_VerifyFailed); + } + } + }); +} + +//发送数据 +//@data 待发送数据 +- (void)writeData:(NSData *)data peripheral:(CBPeripheral *)peripheral writeForChar:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type { + + if (nil == peripheral) { + if (_isDebug) { + NSLog(@"写时未获度外设对象"); + } + return; + } + + if (type == CBCharacteristicWriteWithResponse) { + if (characteristic.properties & CBCharacteristicPropertyWrite) { + self.writeResponse = NO; + [peripheral writeValue:data forCharacteristic:characteristic type:type]; + } + } + + if (type == CBCharacteristicWriteWithoutResponse) { + if (characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) { + self.canSendWrite = NO; + [peripheral writeValue:data forCharacteristic:characteristic type:type]; + } + } +} + +//读取数据 +- (void)readData:(CBPeripheral *)peripheral readValueForChar:(CBCharacteristic *)characteristic{ + if (characteristic.properties & CBCharacteristicPropertyRead) { + self.readResponse = NO; + [peripheral readValueForCharacteristic:characteristic]; + } +} + +//订阅某个特征值 +- (void)peripheralNotify:(CBPeripheral *)peripheral setNotifyForChar:(CBCharacteristic *)characteristic{ + if (characteristic.properties & CBCharacteristicPropertyNotify) { + [peripheral setNotifyValue:YES forCharacteristic:characteristic]; + } +} + +//取消某个订阅 +- (void)peripheralNotify:(CBPeripheral *)peripheral cancleNotifyForChar:(CBCharacteristic *)characteristic{ + [peripheral setNotifyValue:NO forCharacteristic:characteristic]; +} + +#pragma mark - RSSI + +- (void)readRSSI:(CBPeripheral *)peripheral rssiCallBack:(rssiCallBack)rssiBlock{ + [peripheral readRSSI]; + if (nil != rssiBlock) { + self.rssiBlock = rssiBlock; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error { + if (self.rssiBlock != nil) { + self.rssiBlock(RSSI); + } +} + +#pragma mark - CBCentralManagerDelegate +//蓝牙状态 +- (void)centralManagerDidUpdateState:(CBCentralManager *)central { + [self BLEDidUpdateState:central.state]; +} + +//蓝牙状态 +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { + [self BLEDidUpdateState:peripheral.state]; +} + +-(void)BLEDidUpdateState:(CBManagerState)state{ + switch (state) { + case CBManagerStatePoweredOn: + // 扫描所有蓝牙设备 + [self startScan:nil options:nil]; + break; + case CBManagerStateUnsupported: + [self BLEManagerState:Manager_State_Unsupported]; + break; + case CBManagerStatePoweredOff: + [self BLEManagerState:Manager_State_PoweredOff]; + break; + case CBManagerStateResetting: + [self BLEManagerState:Manager_State_Resetting]; + break; + case CBManagerStateUnauthorized: + [self BLEManagerState:Manager_State_Unauthorized]; + break; + default: + [self BLEManagerState:Manager_State_Unknow]; + break; + } +} + +//扫描出错 +-(void)BLEManagerState:(NSError*)error{ + if (self.delegate && [self.delegate respondsToSelector:@selector(BLEManagerDidUpdateState:)]) { + [self.delegate BLEManagerDidUpdateState:error]; + } +} + +//OTA字节对齐 +- (NSInteger)getSpecificMaxPacketForOTAAlign:(NSInteger)mtu { + NSInteger frameMaxLen = mtu; + NSInteger dataMaxLen = frameMaxLen - 4; + + NSInteger dataCount = (dataMaxLen / 16) * 16; + return dataCount + 4; +} + +- (NSData *)hex2BinData:(NSData *)data { + u_long size = data.length; + Byte *biBuf = malloc(size * sizeof(Byte)); + [HexToBin HexToBin:(Byte *)[data bytes] hexLen:data.length binBuf:biBuf binLen:&size]; + NSData *binData = [[NSData alloc] initWithBytes:biBuf length:size]; + free(biBuf); + return binData; +} + +- (void)setChipType:(ChipType)type { + self.currentImageObject.chipType = type; + [BLEOTACmd updateAddressBase:type]; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.h new file mode 100644 index 0000000..30a7c4f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.h @@ -0,0 +1,20 @@ +// +// CBAdvertisementData.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/7. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface CBAdvertisementData : NSObject + ++ (NSString *)getAdvertisementDataName:(NSString *)key; + ++ (NSString *)getAdvertisementDataStringValue:(NSDictionary *)datas Key:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.m new file mode 100644 index 0000000..b149312 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CBAdvertisementData.m @@ -0,0 +1,79 @@ +// +// CBAdvertisementData.m +// BLEOTALibrary +// +// Created by moyun on 2022/4/7. +// + +#import "CBAdvertisementData.h" +#import + +@implementation CBAdvertisementData + ++ (NSString *)getAdvertisementDataName:(NSString *)key{ + if ([key isEqual: CBAdvertisementDataLocalNameKey]) { + return @"Local Name"; + } else if ([key isEqual: CBAdvertisementDataTxPowerLevelKey]) { + return @"Tx Power Level"; + } else if ([key isEqual: CBAdvertisementDataServiceUUIDsKey]) { + return @"Service UUIDs"; + } else if ([key isEqual: CBAdvertisementDataServiceDataKey]) { + return @"Service Data"; + } else if ([key isEqual: CBAdvertisementDataManufacturerDataKey]) { + return @"Manufacturer Data"; + } else if ([key isEqual: CBAdvertisementDataOverflowServiceUUIDsKey]) { + return @"Overflow Service UUIDs"; + } else if ([key isEqual: CBAdvertisementDataIsConnectable]){ + return @"Device is Connectable"; + } else if ([key isEqual: CBAdvertisementDataSolicitedServiceUUIDsKey]) { + return @"Solicited Service UUIDs"; + } + return key; +} + ++ (NSString *)getAdvertisementDataStringValue:(NSDictionary *)datas Key:(NSString *)key{ + NSString *resultString = @""; + if ([key isEqual:CBAdvertisementDataLocalNameKey]) { + resultString = datas[CBAdvertisementDataLocalNameKey]; + } + else if ([key isEqual: CBAdvertisementDataTxPowerLevelKey]) { + resultString = datas[CBAdvertisementDataTxPowerLevelKey]; + } + else if ([key isEqual: CBAdvertisementDataServiceUUIDsKey]) { + NSArray *serviceUUIDs = datas[CBAdvertisementDataServiceUUIDsKey]; + if (serviceUUIDs == nil) { + return @""; + } + for (int i = 0; i < [serviceUUIDs count]; i++){ + resultString = [NSString stringWithFormat:@"%@%@,",resultString,[serviceUUIDs objectAtIndex:i]]; + } + resultString = [resultString substringToIndex:[resultString length]-1];; + } + else if ([key isEqual: CBAdvertisementDataServiceDataKey]) { + NSDictionary *data = datas[CBAdvertisementDataServiceDataKey]; + if (data == nil) { + return @""; + } + NSLog(@"%@",data); + resultString = [[[data description] stringByReplacingOccurrencesOfString:@"\n" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""]; + } + else if ([key isEqual: CBAdvertisementDataManufacturerDataKey]) { + NSData *data = datas[CBAdvertisementDataManufacturerDataKey]; + resultString = [NSString stringWithFormat:@"%lu bytes",(unsigned long)data.length]; + } else if ([key isEqual: CBAdvertisementDataOverflowServiceUUIDsKey]) { + resultString = @""; + } else if ([key isEqual: CBAdvertisementDataIsConnectable]){ + NSNumber *connectable = datas[key]; + if (connectable){ + resultString = connectable.boolValue ? @"true" : @"false"; + } + } else if ([key isEqual: CBAdvertisementDataSolicitedServiceUUIDsKey]) { + resultString = @""; + } + if (resultString == nil) { + resultString = @""; + } + return resultString; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/Constant.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/Constant.h new file mode 100644 index 0000000..0b26091 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/Constant.h @@ -0,0 +1,85 @@ +// +// Constant.h +// WCHBLELibrary +// +// Created by 娟华 胡 on 2021/3/15. +// + +#ifndef Constant_h +#define Constant_h + +#define SERVICE_UUID @"FEE0" +#define READ_WRITE_CHARACTER_UUID @"FEE1" + +#define SleepTimeGap 0.001 + +#define CONNECT_DOMAIN_INFO @"Info" +#define ERROR_INFO_CANCEL_SCAN [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:1 userInfo:@{NSUnderlyingErrorKey:@"已经在扫描请先取消"}] +#define Manager_State_Unsupported [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:1 userInfo:@{NSUnderlyingErrorKey:@"该设备不支持蓝牙"}] +#define Manager_State_PoweredOff [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:2 userInfo:@{NSUnderlyingErrorKey:@"蓝牙已关闭"}] +#define Manager_State_Resetting [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:2 userInfo:@{NSUnderlyingErrorKey:@"蓝牙正在重置"}] +#define Manager_State_Unauthorized [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:2 userInfo:@{NSUnderlyingErrorKey:@"蓝牙未授权"}] +#define Manager_State_Unknow [NSError errorWithDomain:CONNECT_DOMAIN_INFO code:2 userInfo:@{NSUnderlyingErrorKey:@"蓝牙存在未知问题"}] + +#define READ_MAX_REPEAT 20 +#define READ_INTERVAL 0.1 + +#define TIMEOUT_REPEAT_NUM 10000 +#define IAP_LEN 20 + +typedef NS_ENUM(NSUInteger, ChipType) { + ChipType_UNKNOW = 0, + ChipType_CH583 = 1, + ChipType_CH573 = 2, + ChipType_CH579 = 3, +}; + +typedef NS_ENUM(NSUInteger, ImageType) { + ImageType_UNKNOW = 0, + ImageType_A = 1, + ImageType_B = 2, +}; + +//擦除命令 +struct Erase { + Byte cmd; /*命令码0x81*/ + Byte len; /*后续数据长度*/ + Byte addr[2]; /*擦除地址*/ + Byte block_num[2]; /*擦除块数*/ +}; + +//结束命令 +struct End { + Byte cmd; /*命令码0x83*/ + Byte len; /*后续数据长度*/ + Byte status[2]; /*两字节状态,保留*/ +}; + +//校验命令 +struct Verify { + Byte cmd; /*命令码0x82*/ + Byte len; /*后续数据长度*/ + Byte addr[2]; /*校验地址*/ + Byte buf[IAP_LEN - 4];/*校验数据*/ +}; + +//编程命令 +struct Program { + Byte cmd; /*命令码0x80*/ + Byte len; /*后续数据长度*/ + Byte addr[2]; /*地址*/ + Byte buf[IAP_LEN - 4];/*后续数据*/ +}; + +//编程命令 +struct Info { + Byte cmd; /*命令码0x84*/ + Byte len; /*后续数据长度*/ + Byte buf[IAP_LEN - 2];/*后续数据*/ +}; + +struct Other { + Byte buf[IAP_LEN]; /*接收数据包*/ +}; + +#endif /* Constant_h */ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.h new file mode 100644 index 0000000..f00aadb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.h @@ -0,0 +1,29 @@ +// +// CurrentImageObject.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/12. +// + +#import +#import "Constant.h" + +@interface CurrentImageObject : NSObject + +@property (nonatomic, assign) ImageType type; + +@property (nonatomic, assign) ChipType chipType; + +@property (nonatomic, assign) NSInteger offset; + +@property (nonatomic, assign) NSInteger blockSize; + +@property (nonatomic, strong) NSString *version; + ++ (CurrentImageObject *)phraseImageFromResponse:(NSData *)data; + +@end + +@interface FileElement : NSObject + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.m new file mode 100644 index 0000000..ae77e7a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/CurrentImageObject.m @@ -0,0 +1,71 @@ +// +// CurrentImageObject.m +// BLEOTALibrary +// +// Created by moyun on 2022/4/12. +// + +#import "CurrentImageObject.h" +#import "BLEOTACmd.h" + +@implementation CurrentImageObject + ++ (CurrentImageObject *)phraseImageFromResponse:(NSData *)data { + if (data == nil || data.length != 20) { + return nil; + } + + Byte *response = (Byte *)[data bytes]; + CurrentImageObject *object = [[CurrentImageObject alloc] init]; + if (response[0] == 0x01) { + object.type = ImageType_A; + }else if (response[0] == 0x02) { + object.type = ImageType_B; + }else { + object.type = ImageType_UNKNOW; + } + + object.offset = [CurrentImageObject bytesToIntLittleEndian:response start:1]; + + object.blockSize = (response[6] & 0xff) * 256 + (response[5] & 0xff); + + Byte b1 = response[7] & 0xff; + Byte b2 = response[8] & 0xff; + + if (b1 == 0x83 & b2 == 0x00) { + object.chipType = ChipType_CH583; + }else if (b1 == 0x79 && b2 == 0x00) { + object.chipType = ChipType_CH579; + }else if (b1 == 0x73 && b2 == 0x00) { + object.chipType = ChipType_CH573; + }else { + object.chipType = ChipType_UNKNOW; + } + + [BLEOTACmd updateAddressBase:object.chipType]; + + return object; +} + ++ (int)bytesToIntLittleEndian:(Byte *)byte start:(UInt8)start { + int s = 0; + int s0 = byte[start + 3] & 0xff; + int s1 = byte[start + 2] & 0xff; + int s2 = byte[start + 1] & 0xff; + int s3 = byte[start + 0] & 0xff; + + s0 <<= 24; + s1 <<= 16; + s2 <<= 8; + + s = s0 | s1 | s2 | s3; + + return s; +} + +@end + + +@implementation FileElement + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.h new file mode 100644 index 0000000..3f7a2c2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.h @@ -0,0 +1,25 @@ +// +// HexToBin.h +// BLEOTALibrary +// +// Created by moyun on 2022/4/22. +// + +#import + +//NSData *data = [[NSData alloc] initWithContentsOfURL:filePath]; +//u_long size = data.length; +//Byte *biBuf = malloc(size * sizeof(Byte)); +//[HexToBin HexToBin:(Byte *)[data bytes] hexLen:data.length binBuf:biBuf binLen:&size]; +//NSData *binData = [[NSData alloc] initWithBytes:biBuf length:size]; +//free(biBuf); + +NS_ASSUME_NONNULL_BEGIN + +@interface HexToBin : NSObject + ++ (BOOL)HexToBin:(Byte *)Hexbuf hexLen:(u_long)iHexBufLen binBuf:(Byte *)Binbuf binLen:(u_long *)iBinLen; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.m new file mode 100644 index 0000000..1efdf2c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Module/BLEOTALibrary/BLEOTALibrary/HexToBin.m @@ -0,0 +1,179 @@ +// +// HexToBin.m +// BLEOTALibrary +// +// Created by moyun on 2022/4/22. +// + +#import "HexToBin.h" + +@implementation HexToBin + +/* + *把两个字符串转换成一个十六进制数值 + *pInChar 待转换的2个字符缓冲区 + *pOutChar 待换后是十六进制数值 + */ ++ (BOOL)char2ToHex:(char *)pInChar outChar:(unsigned char *)pOutChar { + unsigned char h, l; + + h = pInChar[0]; //高4位 + l = pInChar[1]; //低4位 + + if (l >= '0' && l <= '9') { + l = l - '0'; + }else if (l >= 'a' && l <= 'f') { + l = l - 'a' + 0xa; + }else if (l >= 'A' && l <= 'F') { + l = l - 'A' + 0xa; + }else { + return NO; + } + + if (h >= '0' && h <= '9') { + h = h - '0'; + }else if (h >= 'a' && h <= 'f') { + h = h - 'a' + 0xa; + }else if (h >= 'A' && h <= 'F') { + h = h - 'A' + 0xa; + }else { + return NO; + } + + h <<= 4; + h |= l; + *pOutChar = h; + return YES; +} + + +/* + *HEX格式文件转换成BIN格式 + *Hexbuf + */ ++ (BOOL)HexToBin:(Byte *)Hexbuf hexLen:(u_long)iHexBufLen binBuf:(Byte *)Binbuf binLen:(u_long *)iBinLen { + + if (Hexbuf == NULL || Binbuf == NULL) { + return NO; + } + + unsigned char *hp; + u_long StartPos; + unsigned char DataBuf[256]; + ushort ExtAdr; + ushort SegAdr; + ushort OfsArd; + u_long WriteAdr = 0, StartAddr = 0; + BOOL bIsFrist = YES; + u_long OffsetAdr = 0; + + memset(Binbuf, 0x00, iHexBufLen); + + StartPos = 0; + ExtAdr = 0; + SegAdr = 0; + hp = (unsigned char *)Hexbuf; + *iBinLen = 0; + + while (true) { + if ((StartPos + 2) > iHexBufLen) { + return NO; + } + + if (hp[StartPos] == ':') { + unsigned char i; + u_long Len = 0; + unsigned char checkSum; + + [HexToBin char2ToHex:(char *)(hp + StartPos + 1) outChar:(unsigned char *)&Len]; + + for (checkSum = (unsigned char)Len, i = 0; i < (Len + 4); ++i) { + [HexToBin char2ToHex:(char *)(hp + StartPos + 3 + i + i) outChar:(unsigned char *)(DataBuf + i)]; + checkSum += DataBuf[i]; + } + + if (checkSum != 0) { + return NO; + } + + switch (DataBuf[2]) { + case 0: + { + OfsArd = DataBuf[0] * 256 + DataBuf[1]; + WriteAdr = ExtAdr * 65536 + SegAdr * 16 + OfsArd; + + if (bIsFrist) { + StartAddr = WriteAdr; + bIsFrist = NO; + } + + if (WriteAdr >= 0x08000000) { + + if (StartAddr != 0) { + WriteAdr -= StartAddr; + }else { + WriteAdr -= (ExtAdr * 65536); + } + + }else { + + if (OffsetAdr == 0) { + OffsetAdr = WriteAdr; + }else { + if (WriteAdr < OffsetAdr) { + OffsetAdr = WriteAdr; + } + } + } + + memcpy(&(((unsigned char *)Binbuf)[WriteAdr]), &DataBuf[3], Len); + StartPos += Len * 2 + 13; + + if ((WriteAdr + Len) > *iBinLen) { + *iBinLen = WriteAdr + Len; + } + } + break; + + case 2: + { + SegAdr = DataBuf[3] * 256 + DataBuf[4]; + StartPos += 17; + } + break; + + case 4: + { + ExtAdr = DataBuf[3] * 256 + DataBuf[4]; + StartPos += 17; + } + break; + + case 5: + { + StartPos += 21; + } + break; + + case 3: + { + StartPos += 21; + } + break; + case 1: + { + return YES; + } + + default: + return NO; + } + } + } + + return NO; +} + + + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile new file mode 100644 index 0000000..5cfb0c1 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile @@ -0,0 +1,15 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'WCHBLEOTA' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for WCHBLEOTA + + pod 'MBProgressHUD' #https://github.com/jdg/MBProgressHUD + pod 'SnapKit' #Autolayout DSL https://github.com/SnapKit/SnapKit + pod 'XCGLogger' + pod 'MJRefresh' + +end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile.lock b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile.lock new file mode 100644 index 0000000..5a4e65e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Podfile.lock @@ -0,0 +1,36 @@ +PODS: + - MBProgressHUD (1.2.0) + - MJRefresh (3.7.5) + - ObjcExceptionBridging (1.0.1): + - ObjcExceptionBridging/ObjcExceptionBridging (= 1.0.1) + - ObjcExceptionBridging/ObjcExceptionBridging (1.0.1) + - SnapKit (5.0.1) + - XCGLogger (7.0.1): + - XCGLogger/Core (= 7.0.1) + - XCGLogger/Core (7.0.1): + - ObjcExceptionBridging + +DEPENDENCIES: + - MBProgressHUD + - MJRefresh + - SnapKit + - XCGLogger + +SPEC REPOS: + trunk: + - MBProgressHUD + - MJRefresh + - ObjcExceptionBridging + - SnapKit + - XCGLogger + +SPEC CHECKSUMS: + MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 + MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961 + ObjcExceptionBridging: c30e00eb3700467e695faeea30e26e18bd445001 + SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb + XCGLogger: 1943831ef907df55108b0b18657953f868de973b + +PODFILE CHECKSUM: 76caff9f808ce208c01dda28cd7af894c0ed1ca9 + +COCOAPODS: 1.11.2 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/LICENSE b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/LICENSE new file mode 100644 index 0000000..d7f0647 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/LICENSE @@ -0,0 +1,19 @@ +Copyright © 2009-2020 Matej Bukovinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.h new file mode 100644 index 0000000..38b5004 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.h @@ -0,0 +1,411 @@ +// +// MBProgressHUD.h +// Version 1.2.0 +// Created by Matej Bukovinski on 2.4.09. +// + +// This code is distributed under the terms and conditions of the MIT license. + +// Copyright © 2009-2016 Matej Bukovinski +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import +#import +#import + +@class MBBackgroundView; +@protocol MBProgressHUDDelegate; + + +extern CGFloat const MBProgressMaxOffset; + +typedef NS_ENUM(NSInteger, MBProgressHUDMode) { + /// UIActivityIndicatorView. + MBProgressHUDModeIndeterminate, + /// A round, pie-chart like, progress view. + MBProgressHUDModeDeterminate, + /// Horizontal progress bar. + MBProgressHUDModeDeterminateHorizontalBar, + /// Ring-shaped progress view. + MBProgressHUDModeAnnularDeterminate, + /// Shows a custom view. + MBProgressHUDModeCustomView, + /// Shows only labels. + MBProgressHUDModeText +}; + +typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { + /// Opacity animation + MBProgressHUDAnimationFade, + /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) + MBProgressHUDAnimationZoom, + /// Opacity + scale animation (zoom out style) + MBProgressHUDAnimationZoomOut, + /// Opacity + scale animation (zoom in style) + MBProgressHUDAnimationZoomIn +}; + +typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { + /// Solid color background + MBProgressHUDBackgroundStyleSolidColor, + /// UIVisualEffectView or UIToolbar.layer background view + MBProgressHUDBackgroundStyleBlur +}; + +typedef void (^MBProgressHUDCompletionBlock)(void); + + +NS_ASSUME_NONNULL_BEGIN + + +/** + * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. + * + * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. + * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all + * user input on this region, thereby preventing the user operations on components below the view. + * + * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. + * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. + */ +@interface MBProgressHUD : UIView + +/** + * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. + * + * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. + * + * @param view The view that the HUD will be added to + * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use + * animations while appearing. + * @return A reference to the created HUD. + * + * @see hideHUDForView:animated: + * @see animationType + */ ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; + +/// @name Showing and hiding + +/** + * Finds the top-most HUD subview that hasn't finished and hides it. The counterpart to this method is showHUDAddedTo:animated:. + * + * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. + * + * @param view The view that is going to be searched for a HUD subview. + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * @return YES if a HUD was found and removed, NO otherwise. + * + * @see showHUDAddedTo:animated: + * @see animationType + */ ++ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; + +/** + * Finds the top-most HUD subview that hasn't finished and returns it. + * + * @param view The view that is going to be searched. + * @return A reference to the last HUD subview discovered. + */ ++ (nullable MBProgressHUD *)HUDForView:(UIView *)view NS_SWIFT_NAME(forView(_:)); + +/** + * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with + * view.bounds as the parameter. + * + * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as + * the HUD's superview (i.e., the view that the HUD will be added to). + */ +- (instancetype)initWithView:(UIView *)view; + +/** + * Displays the HUD. + * + * @note You need to make sure that the main thread completes its run loop soon after this method call so that + * the user interface can be updated. Call this method when your task is already set up to be executed in a new thread + * (e.g., when using something like NSOperation or making an asynchronous call like NSURLRequest). + * + * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use + * animations while appearing. + * + * @see animationType + */ +- (void)showAnimated:(BOOL)animated; + +/** + * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * hide the HUD when your task completes. + * + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * + * @see animationType + */ +- (void)hideAnimated:(BOOL)animated; + +/** + * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * hide the HUD when your task completes. + * + * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use + * animations while disappearing. + * @param delay Delay in seconds until the HUD is hidden. + * + * @see animationType + */ +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; + +/** + * The HUD delegate object. Receives HUD state notifications. + */ +@property (weak, nonatomic) id delegate; + +/** + * Called after the HUD is hidden. + */ +@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock; + +/** + * Grace period is the time (in seconds) that the invoked method may be run without + * showing the HUD. If the task finishes before the grace time runs out, the HUD will + * not be shown at all. + * This may be used to prevent HUD display for very short tasks. + * Defaults to 0 (no grace time). + * @note The graceTime needs to be set before the hud is shown. You thus can't use `showHUDAddedTo:animated:`, + * but instead need to alloc / init the HUD, configure the grace time and than show it manually. + */ +@property (assign, nonatomic) NSTimeInterval graceTime; + +/** + * The minimum time (in seconds) that the HUD is shown. + * This avoids the problem of the HUD being shown and than instantly hidden. + * Defaults to 0 (no minimum show time). + */ +@property (assign, nonatomic) NSTimeInterval minShowTime; + +/** + * Removes the HUD from its parent view when hidden. + * Defaults to NO. + */ +@property (assign, nonatomic) BOOL removeFromSuperViewOnHide; + +/// @name Appearance + +/** + * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. + */ +@property (assign, nonatomic) MBProgressHUDMode mode; + +/** + * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor + * for custom views on iOS 7+. Set to nil to manage color individually. + * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. + */ +@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; + +/** + * The animation type that should be used when the HUD is shown and hidden. + */ +@property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; + +/** + * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset + * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. + * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. + */ +@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; + +/** + * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). + * This also represents the minimum bezel distance to the edge of the HUD view. + * Defaults to 20.f + */ +@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; + +/** + * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). + */ +@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; + +/** + * Force the HUD dimensions to be equal if possible. + */ +@property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; + +/** + * When enabled, the bezel center gets slightly affected by the device accelerometer data. + * Defaults to NO. + * + * @note This can cause main thread checker assertions on certain devices. https://github.com/jdg/MBProgressHUD/issues/552 + */ +@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; + +/// @name Progress + +/** + * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. + */ +@property (assign, nonatomic) float progress; + +/// @name ProgressObject + +/** + * The NSProgress object feeding the progress information to the progress indicator. + */ +@property (strong, nonatomic, nullable) NSProgress *progressObject; + +/// @name Views + +/** + * The view containing the labels and indicator (or customView). + */ +@property (strong, nonatomic, readonly) MBBackgroundView *bezelView; + +/** + * View covering the entire HUD area, placed behind bezelView. + */ +@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; + +/** + * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. + * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixels. + */ +@property (strong, nonatomic, nullable) UIView *customView; + +/** + * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit + * the entire text. + */ +@property (strong, nonatomic, readonly) UILabel *label; + +/** + * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. + */ +@property (strong, nonatomic, readonly) UILabel *detailsLabel; + +/** + * A button that is placed below the labels. Visible only if a target / action is added and a title is assigned.. + */ +@property (strong, nonatomic, readonly) UIButton *button; + +@end + + +@protocol MBProgressHUDDelegate + +@optional + +/** + * Called after the HUD was fully hidden from the screen. + */ +- (void)hudWasHidden:(MBProgressHUD *)hud; + +@end + + +/** + * A progress view for showing definite progress by filling up a circle (pie chart). + */ +@interface MBRoundProgressView : UIView + +/** + * Progress (0.0 to 1.0) + */ +@property (nonatomic, assign) float progress; + +/** + * Indicator progress color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *progressTintColor; + +/** + * Indicator background (non-progress) color. + * Only applicable on iOS versions older than iOS 7. + * Defaults to translucent white (alpha 0.1). + */ +@property (nonatomic, strong) UIColor *backgroundTintColor; + +/* + * Display mode - NO = round or YES = annular. Defaults to round. + */ +@property (nonatomic, assign, getter = isAnnular) BOOL annular; + +@end + + +/** + * A flat bar progress view. + */ +@interface MBBarProgressView : UIView + +/** + * Progress (0.0 to 1.0) + */ +@property (nonatomic, assign) float progress; + +/** + * Bar border line color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *lineColor; + +/** + * Bar background color. + * Defaults to clear [UIColor clearColor]; + */ +@property (nonatomic, strong) UIColor *progressRemainingColor; + +/** + * Bar progress color. + * Defaults to white [UIColor whiteColor]. + */ +@property (nonatomic, strong) UIColor *progressColor; + +@end + + +@interface MBBackgroundView : UIView + +/** + * The background style. + * Defaults to MBProgressHUDBackgroundStyleBlur. + */ +@property (nonatomic) MBProgressHUDBackgroundStyle style; + +/** + * The blur effect style, when using MBProgressHUDBackgroundStyleBlur. + * Defaults to UIBlurEffectStyleLight. + */ +@property (nonatomic) UIBlurEffectStyle blurEffectStyle; + +/** + * The background color or the blur tint color. + * + * Defaults to nil on iOS 13 and later and + * `[UIColor colorWithWhite:0.8f alpha:0.6f]` + * on older systems. + */ +@property (nonatomic, strong, nullable) UIColor *color; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.m new file mode 100644 index 0000000..a2829a3 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/MBProgressHUD.m @@ -0,0 +1,1194 @@ +// +// MBProgressHUD.m +// Version 1.2.0 +// Created by Matej Bukovinski on 2.4.09. +// + +#import "MBProgressHUD.h" +#import + +#define MBMainThreadAssert() NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); + +CGFloat const MBProgressMaxOffset = 1000000.f; + +static const CGFloat MBDefaultPadding = 4.f; +static const CGFloat MBDefaultLabelFontSize = 16.f; +static const CGFloat MBDefaultDetailsLabelFontSize = 12.f; + + +@interface MBProgressHUD () + +@property (nonatomic, assign) BOOL useAnimation; +@property (nonatomic, assign, getter=hasFinished) BOOL finished; +@property (nonatomic, strong) UIView *indicator; +@property (nonatomic, strong) NSDate *showStarted; +@property (nonatomic, strong) NSArray *paddingConstraints; +@property (nonatomic, strong) NSArray *bezelConstraints; +@property (nonatomic, strong) UIView *topSpacer; +@property (nonatomic, strong) UIView *bottomSpacer; +@property (nonatomic, strong) UIMotionEffectGroup *bezelMotionEffects; +@property (nonatomic, weak) NSTimer *graceTimer; +@property (nonatomic, weak) NSTimer *minShowTimer; +@property (nonatomic, weak) NSTimer *hideDelayTimer; +@property (nonatomic, weak) CADisplayLink *progressObjectDisplayLink; + +@end + + +@interface MBProgressHUDRoundedButton : UIButton +@end + + +@implementation MBProgressHUD + +#pragma mark - Class methods + ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { + MBProgressHUD *hud = [[self alloc] initWithView:view]; + hud.removeFromSuperViewOnHide = YES; + [view addSubview:hud]; + [hud showAnimated:animated]; + return hud; +} + ++ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { + MBProgressHUD *hud = [self HUDForView:view]; + if (hud != nil) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:animated]; + return YES; + } + return NO; +} + ++ (MBProgressHUD *)HUDForView:(UIView *)view { + NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; + for (UIView *subview in subviewsEnum) { + if ([subview isKindOfClass:self]) { + MBProgressHUD *hud = (MBProgressHUD *)subview; + if (hud.hasFinished == NO) { + return hud; + } + } + } + return nil; +} + +#pragma mark - Lifecycle + +- (void)commonInit { + // Set default values for properties + _animationType = MBProgressHUDAnimationFade; + _mode = MBProgressHUDModeIndeterminate; + _margin = 20.0f; + _defaultMotionEffectsEnabled = NO; + + if (@available(iOS 13.0, tvOS 13, *)) { + _contentColor = [[UIColor labelColor] colorWithAlphaComponent:0.7f]; + } else { + _contentColor = [UIColor colorWithWhite:0.f alpha:0.7f]; + } + + // Transparent background + self.opaque = NO; + self.backgroundColor = [UIColor clearColor]; + // Make it invisible for now + self.alpha = 0.0f; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.layer.allowsGroupOpacity = NO; + + [self setupViews]; + [self updateIndicators]; + [self registerForNotifications]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if ((self = [super initWithCoder:aDecoder])) { + [self commonInit]; + } + return self; +} + +- (id)initWithView:(UIView *)view { + NSAssert(view, @"View must not be nil."); + return [self initWithFrame:view.bounds]; +} + +- (void)dealloc { + [self unregisterFromNotifications]; +} + +#pragma mark - Show & hide + +- (void)showAnimated:(BOOL)animated { + MBMainThreadAssert(); + [self.minShowTimer invalidate]; + self.useAnimation = animated; + self.finished = NO; + // If the grace time is set, postpone the HUD display + if (self.graceTime > 0.0) { + NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.graceTimer = timer; + } + // ... otherwise show the HUD immediately + else { + [self showUsingAnimation:self.useAnimation]; + } +} + +- (void)hideAnimated:(BOOL)animated { + MBMainThreadAssert(); + [self.graceTimer invalidate]; + self.useAnimation = animated; + self.finished = YES; + // If the minShow time is set, calculate how long the HUD was shown, + // and postpone the hiding operation if necessary + if (self.minShowTime > 0.0 && self.showStarted) { + NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted]; + if (interv < self.minShowTime) { + NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.minShowTimer = timer; + return; + } + } + // ... otherwise hide the HUD immediately + [self hideUsingAnimation:self.useAnimation]; +} + +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { + // Cancel any scheduled hideAnimated:afterDelay: calls + [self.hideDelayTimer invalidate]; + + NSTimer *timer = [NSTimer timerWithTimeInterval:delay target:self selector:@selector(handleHideTimer:) userInfo:@(animated) repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.hideDelayTimer = timer; +} + +#pragma mark - Timer callbacks + +- (void)handleGraceTimer:(NSTimer *)theTimer { + // Show the HUD only if the task is still running + if (!self.hasFinished) { + [self showUsingAnimation:self.useAnimation]; + } +} + +- (void)handleMinShowTimer:(NSTimer *)theTimer { + [self hideUsingAnimation:self.useAnimation]; +} + +- (void)handleHideTimer:(NSTimer *)timer { + [self hideAnimated:[timer.userInfo boolValue]]; +} + +#pragma mark - View Hierrarchy + +- (void)didMoveToSuperview { + [self updateForCurrentOrientationAnimated:NO]; +} + +#pragma mark - Internal show & hide operations + +- (void)showUsingAnimation:(BOOL)animated { + // Cancel any previous animations + [self.bezelView.layer removeAllAnimations]; + [self.backgroundView.layer removeAllAnimations]; + + // Cancel any scheduled hideAnimated:afterDelay: calls + [self.hideDelayTimer invalidate]; + + self.showStarted = [NSDate date]; + self.alpha = 1.f; + + // Needed in case we hide and re-show with the same NSProgress object attached. + [self setNSProgressDisplayLinkEnabled:YES]; + + // Set up motion effects only at this point to avoid needlessly + // creating the effect if it was disabled after initialization. + [self updateBezelMotionEffects]; + + if (animated) { + [self animateIn:YES withType:self.animationType completion:NULL]; + } else { + self.bezelView.alpha = 1.f; + self.backgroundView.alpha = 1.f; + } +} + +- (void)hideUsingAnimation:(BOOL)animated { + // Cancel any scheduled hideAnimated:afterDelay: calls. + // This needs to happen here instead of in done, + // to avoid races if another hideAnimated:afterDelay: + // call comes in while the HUD is animating out. + [self.hideDelayTimer invalidate]; + + if (animated && self.showStarted) { + self.showStarted = nil; + [self animateIn:NO withType:self.animationType completion:^(BOOL finished) { + [self done]; + }]; + } else { + self.showStarted = nil; + self.bezelView.alpha = 0.f; + self.backgroundView.alpha = 1.f; + [self done]; + } +} + +- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion { + // Automatically determine the correct zoom animation type + if (type == MBProgressHUDAnimationZoom) { + type = animatingIn ? MBProgressHUDAnimationZoomIn : MBProgressHUDAnimationZoomOut; + } + + CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f); + CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f); + + // Set starting state + UIView *bezelView = self.bezelView; + if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = small; + } else if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = large; + } + + // Perform animations + dispatch_block_t animations = ^{ + if (animatingIn) { + bezelView.transform = CGAffineTransformIdentity; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = large; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = small; + } + CGFloat alpha = animatingIn ? 1.f : 0.f; + bezelView.alpha = alpha; + self.backgroundView.alpha = alpha; + }; + [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; +} + +- (void)done { + [self setNSProgressDisplayLinkEnabled:NO]; + + if (self.hasFinished) { + self.alpha = 0.0f; + if (self.removeFromSuperViewOnHide) { + [self removeFromSuperview]; + } + } + MBProgressHUDCompletionBlock completionBlock = self.completionBlock; + if (completionBlock) { + completionBlock(); + } + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { + [delegate performSelector:@selector(hudWasHidden:) withObject:self]; + } +} + +#pragma mark - UI + +- (void)setupViews { + UIColor *defaultColor = self.contentColor; + + MBBackgroundView *backgroundView = [[MBBackgroundView alloc] initWithFrame:self.bounds]; + backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + backgroundView.backgroundColor = [UIColor clearColor]; + backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + backgroundView.alpha = 0.f; + [self addSubview:backgroundView]; + _backgroundView = backgroundView; + + MBBackgroundView *bezelView = [MBBackgroundView new]; + bezelView.translatesAutoresizingMaskIntoConstraints = NO; + bezelView.layer.cornerRadius = 5.f; + bezelView.alpha = 0.f; + [self addSubview:bezelView]; + _bezelView = bezelView; + + UILabel *label = [UILabel new]; + label.adjustsFontSizeToFitWidth = NO; + label.textAlignment = NSTextAlignmentCenter; + label.textColor = defaultColor; + label.font = [UIFont boldSystemFontOfSize:MBDefaultLabelFontSize]; + label.opaque = NO; + label.backgroundColor = [UIColor clearColor]; + _label = label; + + UILabel *detailsLabel = [UILabel new]; + detailsLabel.adjustsFontSizeToFitWidth = NO; + detailsLabel.textAlignment = NSTextAlignmentCenter; + detailsLabel.textColor = defaultColor; + detailsLabel.numberOfLines = 0; + detailsLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + detailsLabel.opaque = NO; + detailsLabel.backgroundColor = [UIColor clearColor]; + _detailsLabel = detailsLabel; + + UIButton *button = [MBProgressHUDRoundedButton buttonWithType:UIButtonTypeCustom]; + button.titleLabel.textAlignment = NSTextAlignmentCenter; + button.titleLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + [button setTitleColor:defaultColor forState:UIControlStateNormal]; + _button = button; + + for (UIView *view in @[label, detailsLabel, button]) { + view.translatesAutoresizingMaskIntoConstraints = NO; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + [bezelView addSubview:view]; + } + + UIView *topSpacer = [UIView new]; + topSpacer.translatesAutoresizingMaskIntoConstraints = NO; + topSpacer.hidden = YES; + [bezelView addSubview:topSpacer]; + _topSpacer = topSpacer; + + UIView *bottomSpacer = [UIView new]; + bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO; + bottomSpacer.hidden = YES; + [bezelView addSubview:bottomSpacer]; + _bottomSpacer = bottomSpacer; +} + +- (void)updateIndicators { + UIView *indicator = self.indicator; + BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; + BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; + + MBProgressHUDMode mode = self.mode; + if (mode == MBProgressHUDModeIndeterminate) { + if (!isActivityIndicator) { + // Update to indeterminate indicator + UIActivityIndicatorView *activityIndicator; + [indicator removeFromSuperview]; +#if !TARGET_OS_MACCATALYST + if (@available(iOS 13.0, tvOS 13.0, *)) { +#endif + activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge]; + activityIndicator.color = [UIColor whiteColor]; +#if !TARGET_OS_MACCATALYST + } else { + activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + } +#endif + [activityIndicator startAnimating]; + indicator = activityIndicator; + [self.bezelView addSubview:indicator]; + } + } + else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { + // Update to bar determinate indicator + [indicator removeFromSuperview]; + indicator = [[MBBarProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { + if (!isRoundIndicator) { + // Update to determinante indicator + [indicator removeFromSuperview]; + indicator = [[MBRoundProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + if (mode == MBProgressHUDModeAnnularDeterminate) { + [(MBRoundProgressView *)indicator setAnnular:YES]; + } + } + else if (mode == MBProgressHUDModeCustomView && self.customView != indicator) { + // Update custom view indicator + [indicator removeFromSuperview]; + indicator = self.customView; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeText) { + [indicator removeFromSuperview]; + indicator = nil; + } + indicator.translatesAutoresizingMaskIntoConstraints = NO; + self.indicator = indicator; + + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } + + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + + [self updateViewsForColor:self.contentColor]; + [self setNeedsUpdateConstraints]; +} + +- (void)updateViewsForColor:(UIColor *)color { + if (!color) return; + + self.label.textColor = color; + self.detailsLabel.textColor = color; + [self.button setTitleColor:color forState:UIControlStateNormal]; + + // UIAppearance settings are prioritized. If they are preset the set color is ignored. + + UIView *indicator = self.indicator; + if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { + UIActivityIndicatorView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + // For iOS 9+ + appearance = [UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + + if (appearance.color == nil) { + ((UIActivityIndicatorView *)indicator).color = color; + } + } else if ([indicator isKindOfClass:[MBRoundProgressView class]]) { + MBRoundProgressView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [MBRoundProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + appearance = [MBRoundProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + if (appearance.progressTintColor == nil) { + ((MBRoundProgressView *)indicator).progressTintColor = color; + } + if (appearance.backgroundTintColor == nil) { + ((MBRoundProgressView *)indicator).backgroundTintColor = [color colorWithAlphaComponent:0.1]; + } + } else if ([indicator isKindOfClass:[MBBarProgressView class]]) { + MBBarProgressView *appearance = nil; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + appearance = [MBBarProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; +#else + appearance = [MBBarProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; +#endif + if (appearance.progressColor == nil) { + ((MBBarProgressView *)indicator).progressColor = color; + } + if (appearance.lineColor == nil) { + ((MBBarProgressView *)indicator).lineColor = color; + } + } else { + [indicator setTintColor:color]; + } +} + +- (void)updateBezelMotionEffects { + MBBackgroundView *bezelView = self.bezelView; + UIMotionEffectGroup *bezelMotionEffects = self.bezelMotionEffects; + + if (self.defaultMotionEffectsEnabled && !bezelMotionEffects) { + CGFloat effectOffset = 10.f; + UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + effectX.maximumRelativeValue = @(effectOffset); + effectX.minimumRelativeValue = @(-effectOffset); + + UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + effectY.maximumRelativeValue = @(effectOffset); + effectY.minimumRelativeValue = @(-effectOffset); + + UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; + group.motionEffects = @[effectX, effectY]; + + self.bezelMotionEffects = group; + [bezelView addMotionEffect:group]; + } else if (bezelMotionEffects) { + self.bezelMotionEffects = nil; + [bezelView removeMotionEffect:bezelMotionEffects]; + } +} + +#pragma mark - Layout + +- (void)updateConstraints { + UIView *bezel = self.bezelView; + UIView *topSpacer = self.topSpacer; + UIView *bottomSpacer = self.bottomSpacer; + CGFloat margin = self.margin; + NSMutableArray *bezelConstraints = [NSMutableArray array]; + NSDictionary *metrics = @{@"margin": @(margin)}; + + NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.detailsLabel, self.button, self.bottomSpacer, nil]; + if (self.indicator) [subviews insertObject:self.indicator atIndex:1]; + + // Remove existing constraints + [self removeConstraints:self.constraints]; + [topSpacer removeConstraints:topSpacer.constraints]; + [bottomSpacer removeConstraints:bottomSpacer.constraints]; + if (self.bezelConstraints) { + [bezel removeConstraints:self.bezelConstraints]; + self.bezelConstraints = nil; + } + + // Center bezel in container (self), applying the offset if set + CGPoint offset = self.offset; + NSMutableArray *centeringConstraints = [NSMutableArray array]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]]; + [self applyPriority:998.f toConstraints:centeringConstraints]; + [self addConstraints:centeringConstraints]; + + // Ensure minimum side margin is kept + NSMutableArray *sideConstraints = [NSMutableArray array]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [self applyPriority:999.f toConstraints:sideConstraints]; + [self addConstraints:sideConstraints]; + + // Minimum bezel size, if set + CGSize minimumSize = self.minSize; + if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { + NSMutableArray *minSizeConstraints = [NSMutableArray array]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]]; + [self applyPriority:997.f toConstraints:minSizeConstraints]; + [bezelConstraints addObjectsFromArray:minSizeConstraints]; + } + + // Square aspect ratio, if set + if (self.square) { + NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0]; + square.priority = 997.f; + [bezelConstraints addObject:square]; + } + + // Top and bottom spacing + [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + // Top and bottom spaces should be equal + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]]; + + // Layout subviews in bezel + NSMutableArray *paddingConstraints = [NSMutableArray new]; + [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { + // Center in bezel + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]]; + // Ensure the minimum edge margin is kept + [bezelConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]]; + // Element spacing + if (idx == 0) { + // First, ensure spacing to bezel edge + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]]; + } else if (idx == subviews.count - 1) { + // Last, ensure spacing to bezel edge + [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]]; + } + if (idx > 0) { + // Has previous + NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]; + [bezelConstraints addObject:padding]; + [paddingConstraints addObject:padding]; + } + }]; + + [bezel addConstraints:bezelConstraints]; + self.bezelConstraints = bezelConstraints; + + self.paddingConstraints = [paddingConstraints copy]; + [self updatePaddingConstraints]; + + [super updateConstraints]; +} + +- (void)layoutSubviews { + // There is no need to update constraints if they are going to + // be recreated in [super layoutSubviews] due to needsUpdateConstraints being set. + // This also avoids an issue on iOS 8, where updatePaddingConstraints + // would trigger a zombie object access. + if (!self.needsUpdateConstraints) { + [self updatePaddingConstraints]; + } + [super layoutSubviews]; +} + +- (void)updatePaddingConstraints { + // Set padding dynamically, depending on whether the view is visible or not + __block BOOL hasVisibleAncestors = NO; + [self.paddingConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *padding, NSUInteger idx, BOOL *stop) { + UIView *firstView = (UIView *)padding.firstItem; + UIView *secondView = (UIView *)padding.secondItem; + BOOL firstVisible = !firstView.hidden && !CGSizeEqualToSize(firstView.intrinsicContentSize, CGSizeZero); + BOOL secondVisible = !secondView.hidden && !CGSizeEqualToSize(secondView.intrinsicContentSize, CGSizeZero); + // Set if both views are visible or if there's a visible view on top that doesn't have padding + // added relative to the current view yet + padding.constant = (firstVisible && (secondVisible || hasVisibleAncestors)) ? MBDefaultPadding : 0.f; + hasVisibleAncestors |= secondVisible; + }]; +} + +- (void)applyPriority:(UILayoutPriority)priority toConstraints:(NSArray *)constraints { + for (NSLayoutConstraint *constraint in constraints) { + constraint.priority = priority; + } +} + +#pragma mark - Properties + +- (void)setMode:(MBProgressHUDMode)mode { + if (mode != _mode) { + _mode = mode; + [self updateIndicators]; + } +} + +- (void)setCustomView:(UIView *)customView { + if (customView != _customView) { + _customView = customView; + if (self.mode == MBProgressHUDModeCustomView) { + [self updateIndicators]; + } + } +} + +- (void)setOffset:(CGPoint)offset { + if (!CGPointEqualToPoint(offset, _offset)) { + _offset = offset; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMargin:(CGFloat)margin { + if (margin != _margin) { + _margin = margin; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMinSize:(CGSize)minSize { + if (!CGSizeEqualToSize(minSize, _minSize)) { + _minSize = minSize; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setSquare:(BOOL)square { + if (square != _square) { + _square = square; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setProgressObjectDisplayLink:(CADisplayLink *)progressObjectDisplayLink { + if (progressObjectDisplayLink != _progressObjectDisplayLink) { + [_progressObjectDisplayLink invalidate]; + + _progressObjectDisplayLink = progressObjectDisplayLink; + + [_progressObjectDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; + } +} + +- (void)setProgressObject:(NSProgress *)progressObject { + if (progressObject != _progressObject) { + _progressObject = progressObject; + [self setNSProgressDisplayLinkEnabled:YES]; + } +} + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + UIView *indicator = self.indicator; + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } + } +} + +- (void)setContentColor:(UIColor *)contentColor { + if (contentColor != _contentColor && ![contentColor isEqual:_contentColor]) { + _contentColor = contentColor; + [self updateViewsForColor:contentColor]; + } +} + +- (void)setDefaultMotionEffectsEnabled:(BOOL)defaultMotionEffectsEnabled { + if (defaultMotionEffectsEnabled != _defaultMotionEffectsEnabled) { + _defaultMotionEffectsEnabled = defaultMotionEffectsEnabled; + [self updateBezelMotionEffects]; + } +} + +#pragma mark - NSProgress + +- (void)setNSProgressDisplayLinkEnabled:(BOOL)enabled { + // We're using CADisplayLink, because NSProgress can change very quickly and observing it may starve the main thread, + // so we're refreshing the progress only every frame draw + if (enabled && self.progressObject) { + // Only create if not already active. + if (!self.progressObjectDisplayLink) { + self.progressObjectDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgressFromProgressObject)]; + } + } else { + self.progressObjectDisplayLink = nil; + } +} + +- (void)updateProgressFromProgressObject { + self.progress = self.progressObject.fractionCompleted; +} + +#pragma mark - Notifications + +- (void)registerForNotifications { +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) + name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif +} + +- (void)unregisterFromNotifications { +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif +} + +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST +- (void)statusBarOrientationDidChange:(NSNotification *)notification { + UIView *superview = self.superview; + if (!superview) { + return; + } else { + [self updateForCurrentOrientationAnimated:YES]; + } +} +#endif + +- (void)updateForCurrentOrientationAnimated:(BOOL)animated { + // Stay in sync with the superview in any case + if (self.superview) { + self.frame = self.superview.bounds; + } + + // Not needed on iOS 8+, compile out when the deployment target allows, + // to avoid sharedApplication problems on extension targets +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 + // Only needed pre iOS 8 when added to a window + BOOL iOS8OrLater = kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0; + if (iOS8OrLater || ![self.superview isKindOfClass:[UIWindow class]]) return; + + // Make extension friendly. Will not get called on extensions (iOS 8+) due to the above check. + // This just ensures we don't get a warning about extension-unsafe API. + Class UIApplicationClass = NSClassFromString(@"UIApplication"); + if (!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) return; + + UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; + UIInterfaceOrientation orientation = application.statusBarOrientation; + CGFloat radians = 0; + + if (UIInterfaceOrientationIsLandscape(orientation)) { + radians = orientation == UIInterfaceOrientationLandscapeLeft ? -(CGFloat)M_PI_2 : (CGFloat)M_PI_2; + // Window coordinates differ! + self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); + } else { + radians = orientation == UIInterfaceOrientationPortraitUpsideDown ? (CGFloat)M_PI : 0.f; + } + + if (animated) { + [UIView animateWithDuration:0.3 animations:^{ + self.transform = CGAffineTransformMakeRotation(radians); + }]; + } else { + self.transform = CGAffineTransformMakeRotation(radians); + } +#endif +} + +@end + + +@implementation MBRoundProgressView + +#pragma mark - Lifecycle + +- (id)init { + return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; +} + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + _progress = 0.f; + _annular = NO; + _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; + _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + return CGSizeMake(37.f, 37.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressTintColor:(UIColor *)progressTintColor { + NSAssert(progressTintColor, @"The color should not be nil."); + if (progressTintColor != _progressTintColor && ![progressTintColor isEqual:_progressTintColor]) { + _progressTintColor = progressTintColor; + [self setNeedsDisplay]; + } +} + +- (void)setBackgroundTintColor:(UIColor *)backgroundTintColor { + NSAssert(backgroundTintColor, @"The color should not be nil."); + if (backgroundTintColor != _backgroundTintColor && ![backgroundTintColor isEqual:_backgroundTintColor]) { + _backgroundTintColor = backgroundTintColor; + [self setNeedsDisplay]; + } +} + +#pragma mark - Drawing + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + + if (_annular) { + // Draw background + CGFloat lineWidth = 2.f; + UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; + processBackgroundPath.lineWidth = lineWidth; + processBackgroundPath.lineCapStyle = kCGLineCapButt; + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + CGFloat radius = (self.bounds.size.width - lineWidth)/2; + CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees + CGFloat endAngle = (2 * (float)M_PI) + startAngle; + [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_backgroundTintColor set]; + [processBackgroundPath stroke]; + // Draw progress + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = kCGLineCapSquare; + processPath.lineWidth = lineWidth; + endAngle = (self.progress * 2 * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_progressTintColor set]; + [processPath stroke]; + } else { + // Draw background + CGFloat lineWidth = 2.f; + CGRect allRect = self.bounds; + CGRect circleRect = CGRectInset(allRect, lineWidth/2.f, lineWidth/2.f); + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + [_progressTintColor setStroke]; + [_backgroundTintColor setFill]; + CGContextSetLineWidth(context, lineWidth); + CGContextStrokeEllipseInRect(context, circleRect); + // 90 degrees + CGFloat startAngle = - ((float)M_PI / 2.f); + // Draw progress + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = kCGLineCapButt; + processPath.lineWidth = lineWidth * 2.f; + CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - (processPath.lineWidth / 2.f); + CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + // Ensure that we don't get color overlapping when _progressTintColor alpha < 1.f. + CGContextSetBlendMode(context, kCGBlendModeCopy); + [_progressTintColor set]; + [processPath stroke]; + } +} + +@end + + +@implementation MBBarProgressView + +#pragma mark - Lifecycle + +- (id)init { + return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; +} + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _progress = 0.f; + _lineColor = [UIColor whiteColor]; + _progressColor = [UIColor whiteColor]; + _progressRemainingColor = [UIColor clearColor]; + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + return CGSizeMake(120.f, 10.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressColor:(UIColor *)progressColor { + NSAssert(progressColor, @"The color should not be nil."); + if (progressColor != _progressColor && ![progressColor isEqual:_progressColor]) { + _progressColor = progressColor; + [self setNeedsDisplay]; + } +} + +- (void)setProgressRemainingColor:(UIColor *)progressRemainingColor { + NSAssert(progressRemainingColor, @"The color should not be nil."); + if (progressRemainingColor != _progressRemainingColor && ![progressRemainingColor isEqual:_progressRemainingColor]) { + _progressRemainingColor = progressRemainingColor; + [self setNeedsDisplay]; + } +} + +#pragma mark - Drawing + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(context, 2); + CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); + CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); + + // Draw background and Border + CGFloat radius = (rect.size.height / 2) - 2; + CGContextMoveToPoint(context, 2, rect.size.height/2); + CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); + CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); + CGContextDrawPath(context, kCGPathFillStroke); + + CGContextSetFillColorWithColor(context, [_progressColor CGColor]); + radius = radius - 2; + CGFloat amount = self.progress * rect.size.width; + + // Progress in the middle area + if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, amount, 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, amount, rect.size.height - 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextFillPath(context); + } + + // Progress in the right arc + else if (amount > radius + 4) { + CGFloat x = amount - (rect.size.width - radius - 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); + CGFloat angle = -acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); + angle = acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextFillPath(context); + } + + // Progress is in the left arc + else if (amount < radius + 4 && amount > 0) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextFillPath(context); + } +} + +@end + + +@interface MBBackgroundView () + +@property UIVisualEffectView *effectView; + +@end + + +@implementation MBBackgroundView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + _style = MBProgressHUDBackgroundStyleBlur; + if (@available(iOS 13.0, *)) { + #if TARGET_OS_TV + _blurEffectStyle = UIBlurEffectStyleRegular; + #else + _blurEffectStyle = UIBlurEffectStyleSystemThickMaterial; + #endif + // Leaving the color unassigned yields best results. + } else { + _blurEffectStyle = UIBlurEffectStyleLight; + _color = [UIColor colorWithWhite:0.8f alpha:0.6f]; + } + + self.clipsToBounds = YES; + + [self updateForBackgroundStyle]; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + // Smallest size possible. Content pushes against this. + return CGSizeZero; +} + +#pragma mark - Appearance + +- (void)setStyle:(MBProgressHUDBackgroundStyle)style { + if (_style != style) { + _style = style; + [self updateForBackgroundStyle]; + } +} + +- (void)setColor:(UIColor *)color { + NSAssert(color, @"The color should not be nil."); + if (color != _color && ![color isEqual:_color]) { + _color = color; + [self updateViewsForColor:color]; + } +} + +- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle { + if (_blurEffectStyle == blurEffectStyle) { + return; + } + + _blurEffectStyle = blurEffectStyle; + + [self updateForBackgroundStyle]; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Views + +- (void)updateForBackgroundStyle { + [self.effectView removeFromSuperview]; + self.effectView = nil; + + MBProgressHUDBackgroundStyle style = self.style; + if (style == MBProgressHUDBackgroundStyleBlur) { + UIBlurEffect *effect = [UIBlurEffect effectWithStyle:self.blurEffectStyle]; + UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; + [self insertSubview:effectView atIndex:0]; + effectView.frame = self.bounds; + effectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.backgroundColor = self.color; + self.layer.allowsGroupOpacity = NO; + self.effectView = effectView; + } else { + self.backgroundColor = self.color; + } +} + +- (void)updateViewsForColor:(UIColor *)color { + if (self.style == MBProgressHUDBackgroundStyleBlur) { + self.backgroundColor = self.color; + } else { + self.backgroundColor = self.color; + } +} + +@end + + +@implementation MBProgressHUDRoundedButton + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + CALayer *layer = self.layer; + layer.borderWidth = 1.f; + } + return self; +} + +#pragma mark - Layout + +- (void)layoutSubviews { + [super layoutSubviews]; + // Fully rounded corners + CGFloat height = CGRectGetHeight(self.bounds); + self.layer.cornerRadius = ceil(height / 2.f); +} + +- (CGSize)intrinsicContentSize { + // Only show if we have associated control events and a title + if ((self.allControlEvents == 0) || ([self titleForState:UIControlStateNormal].length == 0)) + return CGSizeZero; + CGSize size = [super intrinsicContentSize]; + // Add some side padding + size.width += 20.f; + return size; +} + +#pragma mark - Color + +- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state { + [super setTitleColor:color forState:state]; + // Update related colors + [self setHighlighted:self.highlighted]; + self.layer.borderColor = color.CGColor; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + UIColor *baseColor = [self titleColorForState:UIControlStateSelected]; + self.backgroundColor = highlighted ? [baseColor colorWithAlphaComponent:0.1f] : [UIColor clearColor]; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/README.mdown b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/README.mdown new file mode 100644 index 0000000..c90f5c6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MBProgressHUD/README.mdown @@ -0,0 +1,138 @@ +# MBProgressHUD + +[![Build Status](https://travis-ci.org/matej/MBProgressHUD.svg?branch=master)](https://travis-ci.org/matej/MBProgressHUD) [![codecov.io](https://codecov.io/github/matej/MBProgressHUD/coverage.svg?branch=master)](https://codecov.io/github/matej/MBProgressHUD?branch=master) + [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) [![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio) [![CocoaPods compatible](https://img.shields.io/cocoapods/v/MBProgressHUD.svg?style=flat)](https://cocoapods.org/pods/MBProgressHUD) [![License: MIT](https://img.shields.io/cocoapods/l/MBProgressHUD.svg?style=flat)](http://opensource.org/licenses/MIT) + +`MBProgressHUD` is an iOS drop-in class that displays a translucent HUD with an indicator and/or labels while work is being done in a background thread. The HUD is meant as a replacement for the undocumented, private `UIKit` `UIProgressHUD` with some additional features. + +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6.png) +[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7.png) + +**NOTE:** The class has recently undergone a major rewrite. The old version is available in the [legacy](https://github.com/jdg/MBProgressHUD/tree/legacy) branch, should you need it. + +## Requirements + +`MBProgressHUD` works on iOS 9.0+. It depends on the following Apple frameworks, which should already be included with most Xcode templates: + +* Foundation.framework +* UIKit.framework +* CoreGraphics.framework + +You will need the latest developer tools in order to build `MBProgressHUD`. Old Xcode versions might work, but compatibility will not be explicitly maintained. + +## Adding MBProgressHUD to your project + +### CocoaPods + +[CocoaPods](http://cocoapods.org) is the recommended way to add MBProgressHUD to your project. + +1. Add a pod entry for MBProgressHUD to your Podfile `pod 'MBProgressHUD', '~> 1.2.0'` +2. Install the pod(s) by running `pod install`. +3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. + +### Carthage + +1. Add MBProgressHUD to your Cartfile. e.g., `github "jdg/MBProgressHUD" ~> 1.2.0` +2. Run `carthage update` +3. Follow the rest of the [standard Carthage installation instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add MBProgressHUD to your project. + +### SwiftPM / Accio + +1. Add the following to your `Package.swift`: + ```swift + .package(url: "https://github.com/jdg/MBProgressHUD.git", .upToNextMajor(from: "1.2.0")), + ``` +2. Next, add `MBProgressHUD` to your App targets dependencies like so: + ```swift + .target(name: "App", dependencies: ["MBProgressHUD"]), + ``` +3. Then open your project in Xcode 11+ (SwiftPM) or run `accio update` (Accio). + +### Source files + +Alternatively you can directly add the `MBProgressHUD.h` and `MBProgressHUD.m` source files to your project. + +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. +3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. + +### Static library + +You can also add MBProgressHUD as a static library to your project or workspace. + +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). +3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. +4. Include MBProgressHUD wherever you need it with `#import `. + +## Usage + +The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. + +```objective-c +[MBProgressHUD showHUDAddedTo:self.view animated:YES]; +dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + // Do something... + dispatch_async(dispatch_get_main_queue(), ^{ + [MBProgressHUD hideHUDForView:self.view animated:YES]; + }); +}); +``` + +You can add the HUD on any view or window. It is however a good idea to avoid adding the HUD to certain `UIKit` views with complex view hierarchies - like `UITableView` or `UICollectionView`. Those can mutate their subviews in unexpected ways and thereby break HUD display. + +If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. + +```objective-c +MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; +hud.mode = MBProgressHUDModeAnnularDeterminate; +hud.label.text = @"Loading"; +[self doSomethingInBackgroundWithProgressCallback:^(float progress) { + hud.progress = progress; +} completionCallback:^{ + [hud hideAnimated:YES]; +}]; +``` + +You can also use a `NSProgress` object and MBProgressHUD will update itself when there is progress reported through that object. + +```objective-c +MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; +hud.mode = MBProgressHUDModeAnnularDeterminate; +hud.label.text = @"Loading"; +NSProgress *progress = [self doSomethingInBackgroundCompletion:^{ + [hud hideAnimated:YES]; +}]; +hud.progressObject = progress; +``` + +Keep in mind that UI updates, inclining calls to MBProgressHUD should always be done on the main thread. + +If you need to run your long-running task in the main thread, you should perform it with a slight delay, so UIKit will have enough time to update the UI (i.e., draw the HUD) before you block the main thread with your task. + +```objective-c +[MBProgressHUD showHUDAddedTo:self.view animated:YES]; +dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC); +dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + // Do something... + [MBProgressHUD hideHUDForView:self.view animated:YES]; +}); +``` + +You should be aware that any HUD updates issued inside the above block won't be displayed until the block completes. + +For more examples, including how to use MBProgressHUD with asynchronous operations such as NSURLConnection, take a look at the bundled demo project. Extensive API documentation is provided in the header file (MBProgressHUD.h). + + +## License + +This code is distributed under the terms and conditions of the [MIT license](LICENSE). + +## Change-log + +A brief summary of each MBProgressHUD release can be found in the [CHANGELOG](CHANGELOG.mdown). diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/LICENSE b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/LICENSE new file mode 100644 index 0000000..11bf234 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h new file mode 100644 index 0000000..e4eb872 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h @@ -0,0 +1,34 @@ +// +// MJRefreshAutoFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshAutoFooter : MJRefreshFooter +/** 是否自动刷新(默认为YES) */ +@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh; + +/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */ +@property (assign, nonatomic) CGFloat appearencePercentTriggerAutoRefresh MJRefreshDeprecated("请使用triggerAutomaticallyRefreshPercent属性"); + +/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */ +@property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent; + +/** 自动触发次数, 默认为 1, 仅在拖拽 ScrollView 时才生效, + + 如果为 -1, 则为无限触发 + */ +@property (nonatomic) NSInteger autoTriggerTimes; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m new file mode 100644 index 0000000..b1b93fb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m @@ -0,0 +1,216 @@ +// +// MJRefreshAutoFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshAutoFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +@interface MJRefreshAutoFooter() +/** 一个新的拖拽 */ +@property (nonatomic) BOOL triggerByDrag; +@property (nonatomic) NSInteger leftTriggerTimes; +@end + +@implementation MJRefreshAutoFooter + +#pragma mark - 初始化 +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + + if (newSuperview) { // 新的父控件 + if (self.hidden == NO) { + self.scrollView.mj_insetB += self.mj_h; + } + + // 设置位置 + self.mj_y = _scrollView.mj_contentH; + } else { // 被移除了 + if (self.hidden == NO) { + self.scrollView.mj_insetB -= self.mj_h; + } + } +} + +#pragma mark - 过期方法 +- (void)setAppearencePercentTriggerAutoRefresh:(CGFloat)appearencePercentTriggerAutoRefresh +{ + self.triggerAutomaticallyRefreshPercent = appearencePercentTriggerAutoRefresh; +} + +- (CGFloat)appearencePercentTriggerAutoRefresh +{ + return self.triggerAutomaticallyRefreshPercent; +} + +#pragma mark - 实现父类的方法 +- (void)prepare +{ + [super prepare]; + + // 默认底部控件100%出现时才会自动刷新 + self.triggerAutomaticallyRefreshPercent = 1.0; + + // 设置为默认状态 + self.automaticallyRefresh = YES; + + self.autoTriggerTimes = 1; +} + +- (void)scrollViewContentSizeDidChange:(NSDictionary *)change +{ + [super scrollViewContentSizeDidChange:change]; + + CGSize size = [change[NSKeyValueChangeNewKey] CGSizeValue]; + CGFloat contentHeight = size.height == 0 ? self.scrollView.mj_contentH : size.height; + // 设置位置 + CGFloat y = contentHeight + self.ignoredScrollViewContentInsetBottom; + if (self.mj_y != y) { + self.mj_y = y; + } +} + +- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change +{ + [super scrollViewContentOffsetDidChange:change]; + + if (self.state != MJRefreshStateIdle || !self.automaticallyRefresh || self.mj_y == 0) return; + + if (_scrollView.mj_insetT + _scrollView.mj_contentH > _scrollView.mj_h) { // 内容超过一个屏幕 + // 这里的_scrollView.mj_contentH替换掉self.mj_y更为合理 + if (_scrollView.mj_offsetY >= _scrollView.mj_contentH - _scrollView.mj_h + self.mj_h * self.triggerAutomaticallyRefreshPercent + _scrollView.mj_insetB - self.mj_h) { + // 防止手松开时连续调用 + CGPoint old = [change[@"old"] CGPointValue]; + CGPoint new = [change[@"new"] CGPointValue]; + if (new.y <= old.y) return; + + if (_scrollView.isDragging) { + self.triggerByDrag = YES; + } + // 当底部刷新控件完全出现时,才刷新 + [self beginRefreshing]; + } + } +} + +- (void)scrollViewPanStateDidChange:(NSDictionary *)change +{ + [super scrollViewPanStateDidChange:change]; + + if (self.state != MJRefreshStateIdle) return; + + UIGestureRecognizerState panState = _scrollView.panGestureRecognizer.state; + + switch (panState) { + // 手松开 + case UIGestureRecognizerStateEnded: { + if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) { // 不够一个屏幕 + if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽 + self.triggerByDrag = YES; + [self beginRefreshing]; + } + } else { // 超出一个屏幕 + if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) { + self.triggerByDrag = YES; + [self beginRefreshing]; + } + } + } + break; + + case UIGestureRecognizerStateBegan: { + [self resetTriggerTimes]; + } + break; + + default: + break; + } +} + +- (BOOL)unlimitedTrigger { + return self.leftTriggerTimes == -1; +} + +- (void)beginRefreshing +{ + if (self.triggerByDrag && self.leftTriggerTimes <= 0 && !self.unlimitedTrigger) { + return; + } + + [super beginRefreshing]; +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + if (state == MJRefreshStateRefreshing) { + [self executeRefreshingCallback]; + } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { + if (self.triggerByDrag) { + if (!self.unlimitedTrigger) { + self.leftTriggerTimes -= 1; + } + self.triggerByDrag = NO; + } + + if (MJRefreshStateRefreshing == oldState) { + if (self.scrollView.pagingEnabled) { + CGPoint offset = self.scrollView.contentOffset; + offset.y -= self.scrollView.mj_insetB; + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + self.scrollView.contentOffset = offset; + + if (self.endRefreshingAnimationBeginAction) { + self.endRefreshingAnimationBeginAction(); + } + } completion:^(BOOL finished) { + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + }]; + return; + } + + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + } + } +} + +- (void)resetTriggerTimes { + self.leftTriggerTimes = self.autoTriggerTimes; +} + +- (void)setHidden:(BOOL)hidden +{ + BOOL lastHidden = self.isHidden; + + [super setHidden:hidden]; + + if (!lastHidden && hidden) { + self.state = MJRefreshStateIdle; + + self.scrollView.mj_insetB -= self.mj_h; + } else if (lastHidden && !hidden) { + self.scrollView.mj_insetB += self.mj_h; + + // 设置位置 + self.mj_y = _scrollView.mj_contentH; + } +} + +- (void)setAutoTriggerTimes:(NSInteger)autoTriggerTimes { + _autoTriggerTimes = autoTriggerTimes; + self.leftTriggerTimes = autoTriggerTimes; +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h new file mode 100644 index 0000000..8484372 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h @@ -0,0 +1,21 @@ +// +// MJRefreshBackFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshBackFooter : MJRefreshFooter + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m new file mode 100644 index 0000000..4990ca5 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m @@ -0,0 +1,158 @@ +// +// MJRefreshBackFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshBackFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +@interface MJRefreshBackFooter() +@property (assign, nonatomic) NSInteger lastRefreshCount; +@property (assign, nonatomic) CGFloat lastBottomDelta; +@end + +@implementation MJRefreshBackFooter + +#pragma mark - 初始化 +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + + [self scrollViewContentSizeDidChange:nil]; +} + +#pragma mark - 实现父类的方法 +- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change +{ + [super scrollViewContentOffsetDidChange:change]; + + // 如果正在刷新,直接返回 + if (self.state == MJRefreshStateRefreshing) return; + + _scrollViewOriginalInset = self.scrollView.mj_inset; + + // 当前的contentOffset + CGFloat currentOffsetY = self.scrollView.mj_offsetY; + // 尾部控件刚好出现的offsetY + CGFloat happenOffsetY = [self happenOffsetY]; + // 如果是向下滚动到看不见尾部控件,直接返回 + if (currentOffsetY <= happenOffsetY) return; + + CGFloat pullingPercent = (currentOffsetY - happenOffsetY) / self.mj_h; + + // 如果已全部加载,仅设置pullingPercent,然后返回 + if (self.state == MJRefreshStateNoMoreData) { + self.pullingPercent = pullingPercent; + return; + } + + if (self.scrollView.isDragging) { + self.pullingPercent = pullingPercent; + // 普通 和 即将刷新 的临界点 + CGFloat normal2pullingOffsetY = happenOffsetY + self.mj_h; + + if (self.state == MJRefreshStateIdle && currentOffsetY > normal2pullingOffsetY) { + // 转为即将刷新状态 + self.state = MJRefreshStatePulling; + } else if (self.state == MJRefreshStatePulling && currentOffsetY <= normal2pullingOffsetY) { + // 转为普通状态 + self.state = MJRefreshStateIdle; + } + } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开 + // 开始刷新 + [self beginRefreshing]; + } else if (pullingPercent < 1) { + self.pullingPercent = pullingPercent; + } +} + +- (void)scrollViewContentSizeDidChange:(NSDictionary *)change +{ + [super scrollViewContentSizeDidChange:change]; + + CGSize size = [change[NSKeyValueChangeNewKey] CGSizeValue]; + CGFloat contentHeight = size.height == 0 ? self.scrollView.mj_contentH : size.height; + // 内容的高度 + contentHeight += self.ignoredScrollViewContentInsetBottom; + // 表格的高度 + CGFloat scrollHeight = self.scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom; + // 设置位置 + CGFloat y = MAX(contentHeight, scrollHeight); + if (self.mj_y != y) { + self.mj_y = y; + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态来设置属性 + if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { + // 刷新完毕 + if (MJRefreshStateRefreshing == oldState) { + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + if (self.endRefreshingAnimationBeginAction) { + self.endRefreshingAnimationBeginAction(); + } + + self.scrollView.mj_insetB -= self.lastBottomDelta; + // 自动调整透明度 + if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0; + } completion:^(BOOL finished) { + self.pullingPercent = 0.0; + + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + }]; + } + + CGFloat deltaH = [self heightForContentBreakView]; + // 刚刷新完毕 + if (MJRefreshStateRefreshing == oldState && deltaH > 0 && self.scrollView.mj_totalDataCount != self.lastRefreshCount) { + self.scrollView.mj_offsetY = self.scrollView.mj_offsetY; + } + } else if (state == MJRefreshStateRefreshing) { + // 记录刷新前的数量 + self.lastRefreshCount = self.scrollView.mj_totalDataCount; + + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + CGFloat bottom = self.mj_h + self.scrollViewOriginalInset.bottom; + CGFloat deltaH = [self heightForContentBreakView]; + if (deltaH < 0) { // 如果内容高度小于view的高度 + bottom -= deltaH; + } + self.lastBottomDelta = bottom - self.scrollView.mj_insetB; + self.scrollView.mj_insetB = bottom; + self.scrollView.mj_offsetY = [self happenOffsetY] + self.mj_h; + } completion:^(BOOL finished) { + [self executeRefreshingCallback]; + }]; + } +} +#pragma mark - 私有方法 +#pragma mark 获得scrollView的内容 超出 view 的高度 +- (CGFloat)heightForContentBreakView +{ + CGFloat h = self.scrollView.frame.size.height - self.scrollViewOriginalInset.bottom - self.scrollViewOriginalInset.top; + return self.scrollView.contentSize.height - h; +} + +#pragma mark 刚好看到上拉刷新控件时的contentOffset.y +- (CGFloat)happenOffsetY +{ + CGFloat deltaH = [self heightForContentBreakView]; + if (deltaH > 0) { + return deltaH - self.scrollViewOriginalInset.top; + } else { + return - self.scrollViewOriginalInset.top; + } +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h new file mode 100644 index 0000000..f098101 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h @@ -0,0 +1,151 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshComponent.h +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// 刷新控件的基类 + +#import +#if __has_include() +#import +#else +#import "MJRefreshConst.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** 刷新控件的状态 */ +typedef NS_ENUM(NSInteger, MJRefreshState) { + /** 普通闲置状态 */ + MJRefreshStateIdle = 1, + /** 松开就可以进行刷新的状态 */ + MJRefreshStatePulling, + /** 正在刷新中的状态 */ + MJRefreshStateRefreshing, + /** 即将刷新的状态 */ + MJRefreshStateWillRefresh, + /** 所有数据加载完毕,没有更多的数据了 */ + MJRefreshStateNoMoreData +}; + +/** 进入刷新状态的回调 */ +typedef void (^MJRefreshComponentRefreshingBlock)(void) MJRefreshDeprecated("first deprecated in 3.3.0 - Use `MJRefreshComponentAction` instead"); +/** 开始刷新后的回调(进入刷新状态后的回调) */ +typedef void (^MJRefreshComponentBeginRefreshingCompletionBlock)(void) MJRefreshDeprecated("first deprecated in 3.3.0 - Use `MJRefreshComponentAction` instead"); +/** 结束刷新后的回调 */ +typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void) MJRefreshDeprecated("first deprecated in 3.3.0 - Use `MJRefreshComponentAction` instead"); + +/** 刷新用到的回调类型 */ +typedef void (^MJRefreshComponentAction)(void); + +/** 刷新控件的基类 */ +@interface MJRefreshComponent : UIView +{ + /** 记录scrollView刚开始的inset */ + UIEdgeInsets _scrollViewOriginalInset; + /** 父控件 */ + __weak UIScrollView *_scrollView; +} + +#pragma mark - 刷新动画时间控制 +/** 快速动画时间(一般用在刷新开始的回弹动画), 默认 0.25 */ +@property (nonatomic) NSTimeInterval fastAnimationDuration; +/** 慢速动画时间(一般用在刷新结束后的回弹动画), 默认 0.4*/ +@property (nonatomic) NSTimeInterval slowAnimationDuration; +/** 关闭全部默认动画效果, 可以简单粗暴地解决 CollectionView 的回弹动画 bug */ +- (instancetype)setAnimationDisabled; + +#pragma mark - 刷新回调 +/** 正在刷新的回调 */ +@property (copy, nonatomic, nullable) MJRefreshComponentAction refreshingBlock; +/** 设置回调对象和回调方法 */ +- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** 回调对象 */ +@property (weak, nonatomic) id refreshingTarget; +/** 回调方法 */ +@property (assign, nonatomic) SEL refreshingAction; +/** 触发回调(交给子类去调用) */ +- (void)executeRefreshingCallback; + +#pragma mark - 刷新状态控制 +/** 进入刷新状态 */ +- (void)beginRefreshing; +- (void)beginRefreshingWithCompletionBlock:(void (^)(void))completionBlock; +/** 开始刷新后的回调(进入刷新状态后的回调) */ +@property (copy, nonatomic, nullable) MJRefreshComponentAction beginRefreshingCompletionBlock; +/** 带动画的结束刷新的回调 */ +@property (copy, nonatomic, nullable) MJRefreshComponentAction endRefreshingAnimateCompletionBlock MJRefreshDeprecated("first deprecated in 3.3.0 - Use `endRefreshingAnimationBeginAction` instead"); +@property (copy, nonatomic, nullable) MJRefreshComponentAction endRefreshingAnimationBeginAction; +/** 结束刷新的回调 */ +@property (copy, nonatomic, nullable) MJRefreshComponentAction endRefreshingCompletionBlock; +/** 结束刷新状态 */ +- (void)endRefreshing; +- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock; +/** 是否正在刷新 */ +@property (assign, nonatomic, readonly, getter=isRefreshing) BOOL refreshing; + +/** 刷新状态 一般交给子类内部实现 */ +@property (assign, nonatomic) MJRefreshState state; + +#pragma mark - 交给子类去访问 +/** 记录scrollView刚开始的inset */ +@property (assign, nonatomic, readonly) UIEdgeInsets scrollViewOriginalInset; +/** 父控件 */ +@property (weak, nonatomic, readonly) UIScrollView *scrollView; + +#pragma mark - 交给子类们去实现 +/** 初始化 */ +- (void)prepare NS_REQUIRES_SUPER; +/** 摆放子控件frame */ +- (void)placeSubviews NS_REQUIRES_SUPER; +/** 当scrollView的contentOffset发生改变的时候调用 */ +- (void)scrollViewContentOffsetDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER; +/** 当scrollView的contentSize发生改变的时候调用 */ +- (void)scrollViewContentSizeDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER; +/** 当scrollView的拖拽状态发生改变的时候调用 */ +- (void)scrollViewPanStateDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER; + +/** 多语言配置 language 发生变化时调用 + + `MJRefreshConfig.defaultConfig.language` 发生改变时调用. + + ⚠️ 父类会调用 `placeSubviews` 方法, 请勿在 placeSubviews 中调用本方法, 造成死循环. 子类在需要重新布局时, 在配置完修改后, 最后再调用 super 方法, 否则可能导致配置修改后, 定位先于修改执行. + */ +- (void)i18nDidChange NS_REQUIRES_SUPER; + +#pragma mark - 其他 +/** 拉拽的百分比(交给子类重写) */ +@property (assign, nonatomic) CGFloat pullingPercent; +/** 根据拖拽比例自动切换透明度 */ +@property (assign, nonatomic, getter=isAutoChangeAlpha) BOOL autoChangeAlpha MJRefreshDeprecated("请使用automaticallyChangeAlpha属性"); +/** 根据拖拽比例自动切换透明度 */ +@property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha; +@end + +@interface UILabel(MJRefresh) ++ (instancetype)mj_label; +- (CGFloat)mj_textWidth; +@end + +@interface MJRefreshComponent (ChainingGrammar) + +#pragma mark - <<< 为 Swift 扩展链式语法 >>> - +/// 自动变化透明度 +- (instancetype)autoChangeTransparency:(BOOL)isAutoChange; +/// 刷新开始后立即调用的回调 +- (instancetype)afterBeginningAction:(MJRefreshComponentAction)action; +/// 刷新动画开始后立即调用的回调 +- (instancetype)endingAnimationBeginningAction:(MJRefreshComponentAction)action; +/// 刷新结束后立即调用的回调 +- (instancetype)afterEndingAction:(MJRefreshComponentAction)action; + + +/// 需要子类必须实现 +/// @param scrollView 赋值给的 ScrollView 的 Header/Footer/Trailer +- (instancetype)linkTo:(UIScrollView *)scrollView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m new file mode 100644 index 0000000..785df18 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m @@ -0,0 +1,323 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshComponent.m +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshComponent.h" +#import "MJRefreshConst.h" +#import "MJRefreshConfig.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" +#import "NSBundle+MJRefresh.h" + +@interface MJRefreshComponent() +@property (strong, nonatomic) UIPanGestureRecognizer *pan; +@end + +@implementation MJRefreshComponent +#pragma mark - 初始化 +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + // 准备工作 + [self prepare]; + + // 默认是普通状态 + self.state = MJRefreshStateIdle; + self.fastAnimationDuration = 0.25; + self.slowAnimationDuration = 0.4; + } + return self; +} + +- (void)prepare +{ + // 基本属性 + self.autoresizingMask = UIViewAutoresizingFlexibleWidth; + self.backgroundColor = [UIColor clearColor]; +} + +- (void)layoutSubviews +{ + [self placeSubviews]; + + [super layoutSubviews]; +} + +- (void)placeSubviews{} + +- (void)willMoveToSuperview:(UIView *)newSuperview +{ + [super willMoveToSuperview:newSuperview]; + + // 如果不是UIScrollView,不做任何事情 + if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) return; + + // 旧的父控件移除监听 + [self removeObservers]; + + if (newSuperview) { // 新的父控件 + // 记录UIScrollView + _scrollView = (UIScrollView *)newSuperview; + + // 设置宽度 + self.mj_w = _scrollView.mj_w; + // 设置位置 + self.mj_x = -_scrollView.mj_insetL; + + // 设置永远支持垂直弹簧效果 + _scrollView.alwaysBounceVertical = YES; + // 记录UIScrollView最开始的contentInset + _scrollViewOriginalInset = _scrollView.mj_inset; + + // 添加监听 + [self addObservers]; + } +} + +- (void)drawRect:(CGRect)rect +{ + [super drawRect:rect]; + + if (self.state == MJRefreshStateWillRefresh) { + // 预防view还没显示出来就调用了beginRefreshing + self.state = MJRefreshStateRefreshing; + } +} + +#pragma mark - KVO监听 +- (void)addObservers +{ + NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld; + [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil]; + [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil]; + self.pan = self.scrollView.panGestureRecognizer; + [self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil]; + + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(i18nDidChange) name:MJRefreshDidChangeLanguageNotification object:MJRefreshConfig.defaultConfig]; +} + +- (void)removeObservers +{ + [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset]; + [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize]; + [self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState]; + self.pan = nil; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + // 遇到这些情况就直接返回 + if (!self.userInteractionEnabled) return; + + // 这个就算看不见也需要处理 + if ([keyPath isEqualToString:MJRefreshKeyPathContentSize]) { + [self scrollViewContentSizeDidChange:change]; + } + + // 看不见 + if (self.hidden) return; + if ([keyPath isEqualToString:MJRefreshKeyPathContentOffset]) { + [self scrollViewContentOffsetDidChange:change]; + } else if ([keyPath isEqualToString:MJRefreshKeyPathPanState]) { + [self scrollViewPanStateDidChange:change]; + } +} + +- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{} +- (void)scrollViewContentSizeDidChange:(NSDictionary *)change{} +- (void)scrollViewPanStateDidChange:(NSDictionary *)change{} + +- (void)i18nDidChange { + [self placeSubviews]; +} + +#pragma mark - 公共方法 +#pragma mark 设置回调对象和回调方法 +- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action +{ + self.refreshingTarget = target; + self.refreshingAction = action; +} + +- (void)setState:(MJRefreshState)state +{ + _state = state; + + // 加入主队列的目的是等setState:方法调用完毕、设置完文字后再去布局子控件 + MJRefreshDispatchAsyncOnMainQueue([self setNeedsLayout];) +} + +#pragma mark 进入刷新状态 +- (void)beginRefreshing +{ + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.alpha = 1.0; + }]; + self.pullingPercent = 1.0; + // 只要正在刷新,就完全显示 + if (self.window) { + self.state = MJRefreshStateRefreshing; + } else { + // 预防正在刷新中时,调用本方法使得header inset回置失败 + if (self.state != MJRefreshStateRefreshing) { + self.state = MJRefreshStateWillRefresh; + // 刷新(预防从另一个控制器回到这个控制器的情况,回来要重新刷新一下) + [self setNeedsDisplay]; + } + } +} + +- (void)beginRefreshingWithCompletionBlock:(void (^)(void))completionBlock +{ + self.beginRefreshingCompletionBlock = completionBlock; + + [self beginRefreshing]; +} + +#pragma mark 结束刷新状态 +- (void)endRefreshing +{ + MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;) +} + +- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock +{ + self.endRefreshingCompletionBlock = completionBlock; + + [self endRefreshing]; +} + +#pragma mark 是否正在刷新 +- (BOOL)isRefreshing +{ + return self.state == MJRefreshStateRefreshing || self.state == MJRefreshStateWillRefresh; +} + +#pragma mark 自动切换透明度 +- (void)setAutoChangeAlpha:(BOOL)autoChangeAlpha +{ + self.automaticallyChangeAlpha = autoChangeAlpha; +} + +- (BOOL)isAutoChangeAlpha +{ + return self.isAutomaticallyChangeAlpha; +} + +- (void)setAutomaticallyChangeAlpha:(BOOL)automaticallyChangeAlpha +{ + _automaticallyChangeAlpha = automaticallyChangeAlpha; + + if (self.isRefreshing) return; + + if (automaticallyChangeAlpha) { + self.alpha = self.pullingPercent; + } else { + self.alpha = 1.0; + } +} + +#pragma mark 根据拖拽进度设置透明度 +- (void)setPullingPercent:(CGFloat)pullingPercent +{ + _pullingPercent = pullingPercent; + + if (self.isRefreshing) return; + + if (self.isAutomaticallyChangeAlpha) { + self.alpha = pullingPercent; + } +} + +#pragma mark - 内部方法 +- (void)executeRefreshingCallback +{ + if (self.refreshingBlock) { + self.refreshingBlock(); + } + if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) { + MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self); + } + if (self.beginRefreshingCompletionBlock) { + self.beginRefreshingCompletionBlock(); + } +} + +#pragma mark - 刷新动画时间控制 +- (instancetype)setAnimationDisabled { + self.fastAnimationDuration = 0; + self.slowAnimationDuration = 0; + + return self; +} + +#pragma mark - <<< Deprecation compatible function >>> - +- (void)setEndRefreshingAnimateCompletionBlock:(MJRefreshComponentEndRefreshingCompletionBlock)endRefreshingAnimateCompletionBlock { + _endRefreshingAnimationBeginAction = endRefreshingAnimateCompletionBlock; +} +@end + +@implementation UILabel(MJRefresh) ++ (instancetype)mj_label +{ + UILabel *label = [[self alloc] init]; + label.font = MJRefreshLabelFont; + label.textColor = MJRefreshLabelTextColor; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth; + label.textAlignment = NSTextAlignmentCenter; + label.backgroundColor = [UIColor clearColor]; + return label; +} + +- (CGFloat)mj_textWidth { + CGFloat stringWidth = 0; + CGSize size = CGSizeMake(MAXFLOAT, MAXFLOAT); + + if (self.attributedText) { + if (self.attributedText.length == 0) { return 0; } + stringWidth = [self.attributedText boundingRectWithSize:size + options:NSStringDrawingUsesLineFragmentOrigin + context:nil].size.width; + } else { + if (self.text.length == 0) { return 0; } + NSAssert(self.font != nil, @"请检查 mj_label's `font` 是否设置正确"); + stringWidth = [self.text boundingRectWithSize:size + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{NSFontAttributeName:self.font} + context:nil].size.width; + } + return stringWidth; +} +@end + + +#pragma mark - <<< 为 Swift 扩展链式语法 >>> - +@implementation MJRefreshComponent (ChainingGrammar) + +- (instancetype)autoChangeTransparency:(BOOL)isAutoChange { + self.automaticallyChangeAlpha = isAutoChange; + return self; +} +- (instancetype)afterBeginningAction:(MJRefreshComponentAction)action { + self.beginRefreshingCompletionBlock = action; + return self; +} +- (instancetype)endingAnimationBeginningAction:(MJRefreshComponentAction)action { + self.endRefreshingAnimationBeginAction = action; + return self; +} +- (instancetype)afterEndingAction:(MJRefreshComponentAction)action { + self.endRefreshingCompletionBlock = action; + return self; +} + +- (instancetype)linkTo:(UIScrollView *)scrollView { + return self; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h new file mode 100644 index 0000000..7b7c7b6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h @@ -0,0 +1,37 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/3/5. +// Copyright (c) 2015年 小码哥. All rights reserved. +// 上拉刷新控件 + +#if __has_include() +#import +#else +#import "MJRefreshComponent.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshFooter : MJRefreshComponent +/** 创建footer */ ++ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock; +/** 创建footer */ ++ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** 提示没有更多的数据 */ +- (void)endRefreshingWithNoMoreData; +- (void)noticeNoMoreData MJRefreshDeprecated("使用endRefreshingWithNoMoreData"); + +/** 重置没有更多的数据(消除没有更多数据的状态) */ +- (void)resetNoMoreData; + +/** 忽略多少scrollView的contentInset的bottom */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom; + +/** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏。默认是NO) */ +@property (assign, nonatomic, getter=isAutomaticallyHidden) BOOL automaticallyHidden MJRefreshDeprecated("已废弃此属性,开发者请自行控制footer的显示和隐藏"); +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m new file mode 100644 index 0000000..8096fdb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m @@ -0,0 +1,71 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/3/5. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshFooter.h" +#import "UIScrollView+MJRefresh.h" +#import "UIView+MJExtension.h" + +@interface MJRefreshFooter() + +@end + +@implementation MJRefreshFooter +#pragma mark - 构造方法 ++ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock +{ + MJRefreshFooter *cmp = [[self alloc] init]; + cmp.refreshingBlock = refreshingBlock; + return cmp; +} ++ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action +{ + MJRefreshFooter *cmp = [[self alloc] init]; + [cmp setRefreshingTarget:target refreshingAction:action]; + return cmp; +} + +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + + // 设置自己的高度 + self.mj_h = MJRefreshFooterHeight; + + // 默认不会自动隐藏 +// self.automaticallyHidden = NO; +} + +#pragma mark . 链式语法部分 . + +- (instancetype)linkTo:(UIScrollView *)scrollView { + scrollView.mj_footer = self; + return self; +} + +#pragma mark - 公共方法 +- (void)endRefreshingWithNoMoreData +{ + MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateNoMoreData;) +} + +- (void)noticeNoMoreData +{ + [self endRefreshingWithNoMoreData]; +} + +- (void)resetNoMoreData +{ + MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;) +} + +- (void)setAutomaticallyHidden:(BOOL)automaticallyHidden +{ + _automaticallyHidden = automaticallyHidden; +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h new file mode 100644 index 0000000..95d8cb2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h @@ -0,0 +1,35 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshHeader.h +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// 下拉刷新控件:负责监控用户下拉的状态 + +#if __has_include() +#import +#else +#import "MJRefreshComponent.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshHeader : MJRefreshComponent +/** 创建header */ ++ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock; +/** 创建header */ ++ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** 这个key用来存储上一次下拉刷新成功的时间 */ +@property (copy, nonatomic) NSString *lastUpdatedTimeKey; +/** 上一次下拉刷新成功的时间 */ +@property (strong, nonatomic, readonly, nullable) NSDate *lastUpdatedTime; + +/** 忽略多少scrollView的contentInset的top */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop; + +/** 默认是关闭状态, 如果遇到 CollectionView 的动画异常问题可以尝试打开 */ +@property (nonatomic) BOOL isCollectionViewAnimationBug; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m new file mode 100644 index 0000000..9baf17a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m @@ -0,0 +1,297 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// MJRefreshHeader.m +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshHeader.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +NSString * const MJRefreshHeaderRefreshing2IdleBoundsKey = @"MJRefreshHeaderRefreshing2IdleBounds"; +NSString * const MJRefreshHeaderRefreshingBoundsKey = @"MJRefreshHeaderRefreshingBounds"; + +@interface MJRefreshHeader() +@property (assign, nonatomic) CGFloat insetTDelta; +@end + +@implementation MJRefreshHeader +#pragma mark - 构造方法 ++ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock +{ + MJRefreshHeader *cmp = [[self alloc] init]; + cmp.refreshingBlock = refreshingBlock; + return cmp; +} ++ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action +{ + MJRefreshHeader *cmp = [[self alloc] init]; + [cmp setRefreshingTarget:target refreshingAction:action]; + return cmp; +} + +#pragma mark - 覆盖父类的方法 +- (void)prepare +{ + [super prepare]; + + // 设置key + self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey; + + // 设置高度 + self.mj_h = MJRefreshHeaderHeight; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + // 设置y值(当自己的高度发生改变了,肯定要重新调整Y值,所以放到placeSubviews方法中设置y值) + self.mj_y = - self.mj_h - self.ignoredScrollViewContentInsetTop; +} + +- (void)resetInset { + if (@available(iOS 11.0, *)) { + } else { + // 如果 iOS 10 及以下系统在刷新时, push 新的 VC, 等待刷新完成后回来, 会导致顶部 Insets.top 异常, 不能 resetInset, 检查一下这种特殊情况 + if (!self.window) { return; } + } + + // sectionheader停留解决 + CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top; + insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT; + self.insetTDelta = _scrollViewOriginalInset.top - insetT; + // 避免 CollectionView 在使用根据 Autolayout 和 内容自动伸缩 Cell, 刷新时导致的 Layout 异常渲染问题 + if (self.scrollView.mj_insetT != insetT) { + self.scrollView.mj_insetT = insetT; + } +} + +- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change +{ + [super scrollViewContentOffsetDidChange:change]; + + // 在刷新的refreshing状态 + if (self.state == MJRefreshStateRefreshing) { + [self resetInset]; + return; + } + + // 跳转到下一个控制器时,contentInset可能会变 + _scrollViewOriginalInset = self.scrollView.mj_inset; + + // 当前的contentOffset + CGFloat offsetY = self.scrollView.mj_offsetY; + // 头部控件刚好出现的offsetY + CGFloat happenOffsetY = - self.scrollViewOriginalInset.top; + + // 如果是向上滚动到看不见头部控件,直接返回 + // >= -> > + if (offsetY > happenOffsetY) return; + + // 普通 和 即将刷新 的临界点 + CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h; + CGFloat pullingPercent = (happenOffsetY - offsetY) / self.mj_h; + + if (self.scrollView.isDragging) { // 如果正在拖拽 + self.pullingPercent = pullingPercent; + if (self.state == MJRefreshStateIdle && offsetY < normal2pullingOffsetY) { + // 转为即将刷新状态 + self.state = MJRefreshStatePulling; + } else if (self.state == MJRefreshStatePulling && offsetY >= normal2pullingOffsetY) { + // 转为普通状态 + self.state = MJRefreshStateIdle; + } + } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开 + // 开始刷新 + [self beginRefreshing]; + } else if (pullingPercent < 1) { + self.pullingPercent = pullingPercent; + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStateIdle) { + if (oldState != MJRefreshStateRefreshing) return; + + [self headerEndingAction]; + } else if (state == MJRefreshStateRefreshing) { + [self headerRefreshingAction]; + } +} + +- (void)headerEndingAction { + // 保存刷新时间 + [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + // 默认使用 UIViewAnimation 动画 + if (!self.isCollectionViewAnimationBug) { + // 恢复inset和offset + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + self.scrollView.mj_insetT += self.insetTDelta; + + if (self.endRefreshingAnimationBeginAction) { + self.endRefreshingAnimationBeginAction(); + } + // 自动调整透明度 + if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0; + } completion:^(BOOL finished) { + self.pullingPercent = 0.0; + + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + }]; + + return; + } + + /** + 这个解决方法的思路出自 https://github.com/CoderMJLee/MJRefresh/pull/844 + 修改了用+ [UIView animateWithDuration: animations:]实现的修改contentInset的动画 + fix issue#225 https://github.com/CoderMJLee/MJRefresh/issues/225 + 另一种解法 pull#737 https://github.com/CoderMJLee/MJRefresh/pull/737 + + 同时, 处理了 Refreshing 中的动画替换. + */ + + // 由于修改 Inset 会导致 self.pullingPercent 联动设置 self.alpha, 故提前获取 alpha 值, 后续用于还原 alpha 动画 + CGFloat viewAlpha = self.alpha; + + self.scrollView.mj_insetT += self.insetTDelta; + // 禁用交互, 如果不禁用可能会引起渲染问题. + self.scrollView.userInteractionEnabled = NO; + + //CAAnimation keyPath 不支持 contentInset 用Bounds的动画代替 + CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; + boundsAnimation.fromValue = [NSValue valueWithCGRect:CGRectOffset(self.scrollView.bounds, 0, self.insetTDelta)]; + boundsAnimation.duration = self.slowAnimationDuration; + //在delegate里移除 + boundsAnimation.removedOnCompletion = NO; + boundsAnimation.fillMode = kCAFillModeBoth; + boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + boundsAnimation.delegate = self; + [boundsAnimation setValue:MJRefreshHeaderRefreshing2IdleBoundsKey forKey:@"identity"]; + + [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshing2IdleBoundsKey]; + + if (self.endRefreshingAnimationBeginAction) { + self.endRefreshingAnimationBeginAction(); + } + // 自动调整透明度的动画 + if (self.isAutomaticallyChangeAlpha) { + CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; + opacityAnimation.fromValue = @(viewAlpha); + opacityAnimation.toValue = @(0.0); + opacityAnimation.duration = self.slowAnimationDuration; + opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + [self.layer addAnimation:opacityAnimation forKey:@"MJRefreshHeaderRefreshing2IdleOpacity"]; + + // 由于修改了 inset 导致, pullingPercent 被设置值, alpha 已经被提前修改为 0 了. 所以这里不用置 0, 但为了代码的严谨性, 不依赖其他的特殊实现方式, 这里还是置 0. + self.alpha = 0; + } +} + +- (void)headerRefreshingAction { + // 默认使用 UIViewAnimation 动画 + if (!self.isCollectionViewAnimationBug) { + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) { + CGFloat top = self.scrollViewOriginalInset.top + self.mj_h; + // 增加滚动区域top + self.scrollView.mj_insetT = top; + // 设置滚动位置 + CGPoint offset = self.scrollView.contentOffset; + offset.y = -top; + [self.scrollView setContentOffset:offset animated:NO]; + } + } completion:^(BOOL finished) { + [self executeRefreshingCallback]; + }]; + return; + } + + if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) { + CGFloat top = self.scrollViewOriginalInset.top + self.mj_h; + // 禁用交互, 如果不禁用可能会引起渲染问题. + self.scrollView.userInteractionEnabled = NO; + + // CAAnimation keyPath不支持 contentOffset 用Bounds的动画代替 + CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; + CGRect bounds = self.scrollView.bounds; + bounds.origin.y = -top; + boundsAnimation.fromValue = [NSValue valueWithCGRect:self.scrollView.bounds]; + boundsAnimation.toValue = [NSValue valueWithCGRect:bounds]; + boundsAnimation.duration = self.fastAnimationDuration; + //在delegate里移除 + boundsAnimation.removedOnCompletion = NO; + boundsAnimation.fillMode = kCAFillModeBoth; + boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + boundsAnimation.delegate = self; + [boundsAnimation setValue:MJRefreshHeaderRefreshingBoundsKey forKey:@"identity"]; + [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshingBoundsKey]; + } else { + [self executeRefreshingCallback]; + } +} + +#pragma mark . 链式语法部分 . + +- (instancetype)linkTo:(UIScrollView *)scrollView { + scrollView.mj_header = self; + return self; +} + +#pragma mark - CAAnimationDelegate +- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { + NSString *identity = [anim valueForKey:@"identity"]; + if ([identity isEqualToString:MJRefreshHeaderRefreshing2IdleBoundsKey]) { + self.pullingPercent = 0.0; + self.scrollView.userInteractionEnabled = YES; + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + } else if ([identity isEqualToString:MJRefreshHeaderRefreshingBoundsKey]) { + // 避免出现 end 先于 Refreshing 状态 + if (self.state != MJRefreshStateIdle) { + CGFloat top = self.scrollViewOriginalInset.top + self.mj_h; + self.scrollView.mj_insetT = top; + // 设置最终滚动位置 + CGPoint offset = self.scrollView.contentOffset; + offset.y = -top; + [self.scrollView setContentOffset:offset animated:NO]; + } + self.scrollView.userInteractionEnabled = YES; + [self executeRefreshingCallback]; + } + + if ([self.scrollView.layer animationForKey:MJRefreshHeaderRefreshing2IdleBoundsKey]) { + [self.scrollView.layer removeAnimationForKey:MJRefreshHeaderRefreshing2IdleBoundsKey]; + } + + if ([self.scrollView.layer animationForKey:MJRefreshHeaderRefreshingBoundsKey]) { + [self.scrollView.layer removeAnimationForKey:MJRefreshHeaderRefreshingBoundsKey]; + } +} + +#pragma mark - 公共方法 +- (NSDate *)lastUpdatedTime +{ + return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey]; +} + +- (void)setIgnoredScrollViewContentInsetTop:(CGFloat)ignoredScrollViewContentInsetTop { + _ignoredScrollViewContentInsetTop = ignoredScrollViewContentInsetTop; + + self.mj_y = - self.mj_h - _ignoredScrollViewContentInsetTop; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.h new file mode 100644 index 0000000..ca4c7ea --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.h @@ -0,0 +1,30 @@ +// +// MJRefreshTrailer.h +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshComponent.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshTrailer : MJRefreshComponent + +/** 创建trailer*/ ++ (instancetype)trailerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock; +/** 创建trailer */ ++ (instancetype)trailerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** 忽略多少scrollView的contentInset的right */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetRight; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.m new file mode 100644 index 0000000..da66f20 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Base/MJRefreshTrailer.m @@ -0,0 +1,179 @@ +// +// MJRefreshTrailer.m +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#import "MJRefreshTrailer.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" +#import "UIScrollView+MJExtension.h" + +@interface MJRefreshTrailer() +@property (assign, nonatomic) NSInteger lastRefreshCount; +@property (assign, nonatomic) CGFloat lastRightDelta; +@end + +@implementation MJRefreshTrailer + +#pragma mark - 构造方法 ++ (instancetype)trailerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock { + MJRefreshTrailer *cmp = [[self alloc] init]; + cmp.refreshingBlock = refreshingBlock; + return cmp; +} + ++ (instancetype)trailerWithRefreshingTarget:(id)target refreshingAction:(SEL)action { + MJRefreshTrailer *cmp = [[self alloc] init]; + [cmp setRefreshingTarget:target refreshingAction:action]; + return cmp; +} + +- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change { + [super scrollViewContentOffsetDidChange:change]; + + // 如果正在刷新,直接返回 + if (self.state == MJRefreshStateRefreshing) return; + + _scrollViewOriginalInset = self.scrollView.mj_inset; + + // 当前的contentOffset + CGFloat currentOffsetX = self.scrollView.mj_offsetX; + // 尾部控件刚好出现的offsetX + CGFloat happenOffsetX = [self happenOffsetX]; + // 如果是向右滚动到看不见右边控件,直接返回 + if (currentOffsetX <= happenOffsetX) return; + + CGFloat pullingPercent = (currentOffsetX - happenOffsetX) / self.mj_w; + + // 如果已全部加载,仅设置pullingPercent,然后返回 + if (self.state == MJRefreshStateNoMoreData) { + self.pullingPercent = pullingPercent; + return; + } + + if (self.scrollView.isDragging) { + self.pullingPercent = pullingPercent; + // 普通 和 即将刷新 的临界点 + CGFloat normal2pullingOffsetX = happenOffsetX + self.mj_w; + + if (self.state == MJRefreshStateIdle && currentOffsetX > normal2pullingOffsetX) { + self.state = MJRefreshStatePulling; + } else if (self.state == MJRefreshStatePulling && currentOffsetX <= normal2pullingOffsetX) { + // 转为普通状态 + self.state = MJRefreshStateIdle; + } + } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开 + // 开始刷新 + [self beginRefreshing]; + } else if (pullingPercent < 1) { + self.pullingPercent = pullingPercent; + } +} + +- (void)setState:(MJRefreshState)state { + MJRefreshCheckState + // 根据状态来设置属性 + if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { + // 刷新完毕 + if (MJRefreshStateRefreshing == oldState) { + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + if (self.endRefreshingAnimationBeginAction) { + self.endRefreshingAnimationBeginAction(); + } + + self.scrollView.mj_insetR -= self.lastRightDelta; + // 自动调整透明度 + if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0; + } completion:^(BOOL finished) { + self.pullingPercent = 0.0; + + if (self.endRefreshingCompletionBlock) { + self.endRefreshingCompletionBlock(); + } + }]; + } + + CGFloat deltaW = [self widthForContentBreakView]; + // 刚刷新完毕 + if (MJRefreshStateRefreshing == oldState && deltaW > 0 && self.scrollView.mj_totalDataCount != self.lastRefreshCount) { + self.scrollView.mj_offsetX = self.scrollView.mj_offsetX; + } + } else if (state == MJRefreshStateRefreshing) { + // 记录刷新前的数量 + self.lastRefreshCount = self.scrollView.mj_totalDataCount; + + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + CGFloat right = self.mj_w + self.scrollViewOriginalInset.right; + CGFloat deltaW = [self widthForContentBreakView]; + if (deltaW < 0) { // 如果内容宽度小于view的宽度 + right -= deltaW; + } + self.lastRightDelta = right - self.scrollView.mj_insetR; + self.scrollView.mj_insetR = right; + + // 设置滚动位置 + CGPoint offset = self.scrollView.contentOffset; + offset.x = [self happenOffsetX] + self.mj_w; + [self.scrollView setContentOffset:offset animated:NO]; + } completion:^(BOOL finished) { + [self executeRefreshingCallback]; + }]; + } +} + +- (void)scrollViewContentSizeDidChange:(NSDictionary *)change { + [super scrollViewContentSizeDidChange:change]; + + // 内容的宽度 + CGFloat contentWidth = self.scrollView.mj_contentW + self.ignoredScrollViewContentInsetRight; + // 表格的宽度 + CGFloat scrollWidth = self.scrollView.mj_w - self.scrollViewOriginalInset.left - self.scrollViewOriginalInset.right + self.ignoredScrollViewContentInsetRight; + // 设置位置和尺寸 + self.mj_x = MAX(contentWidth, scrollWidth); +} + +- (void)placeSubviews { + [super placeSubviews]; + + self.mj_h = _scrollView.mj_h; + // 设置自己的宽度 + self.mj_w = MJRefreshTrailWidth; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + + if (newSuperview) { + // 设置支持水平弹簧效果 + _scrollView.alwaysBounceHorizontal = YES; + _scrollView.alwaysBounceVertical = NO; + } +} + +#pragma mark . 链式语法部分 . + +- (instancetype)linkTo:(UIScrollView *)scrollView { + scrollView.mj_trailer = self; + return self; +} + +#pragma mark - 刚好看到上拉刷新控件时的contentOffset.x +- (CGFloat)happenOffsetX { + CGFloat deltaW = [self widthForContentBreakView]; + if (deltaW > 0) { + return deltaW - self.scrollViewOriginalInset.left; + } else { + return - self.scrollViewOriginalInset.left; + } +} + +#pragma mark 获得scrollView的内容 超出 view 的宽度 +- (CGFloat)widthForContentBreakView { + CGFloat w = self.scrollView.frame.size.width - self.scrollViewOriginalInset.right - self.scrollViewOriginalInset.left; + return self.scrollView.contentSize.width - w; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h new file mode 100644 index 0000000..f346157 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h @@ -0,0 +1,25 @@ +// +// MJRefreshAutoGifFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshAutoStateFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshAutoGifFooter : MJRefreshAutoStateFooter +@property (weak, nonatomic, readonly) UIImageView *gifView; + +/** 设置state状态下的动画图片images 动画持续时间duration*/ +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m new file mode 100644 index 0000000..213f69f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m @@ -0,0 +1,121 @@ +// +// MJRefreshAutoGifFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshAutoGifFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +@interface MJRefreshAutoGifFooter() +{ + __unsafe_unretained UIImageView *_gifView; +} +/** 所有状态对应的动画图片 */ +@property (strong, nonatomic) NSMutableDictionary *stateImages; +/** 所有状态对应的动画时间 */ +@property (strong, nonatomic) NSMutableDictionary *stateDurations; +@end + +@implementation MJRefreshAutoGifFooter +#pragma mark - 懒加载 +- (UIImageView *)gifView +{ + if (!_gifView) { + UIImageView *gifView = [[UIImageView alloc] init]; + [self addSubview:_gifView = gifView]; + } + return _gifView; +} + +- (NSMutableDictionary *)stateImages +{ + if (!_stateImages) { + self.stateImages = [NSMutableDictionary dictionary]; + } + return _stateImages; +} + +- (NSMutableDictionary *)stateDurations +{ + if (!_stateDurations) { + self.stateDurations = [NSMutableDictionary dictionary]; + } + return _stateDurations; +} + +#pragma mark - 公共方法 +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state +{ + if (images == nil) return self; + + self.stateImages[@(state)] = images; + self.stateDurations[@(state)] = @(duration); + + /* 根据图片设置控件的高度 */ + UIImage *image = [images firstObject]; + if (image.size.height > self.mj_h) { + self.mj_h = image.size.height; + } + return self; +} + +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state +{ + return [self setImages:images duration:images.count * 0.1 forState:state]; +} + +#pragma mark - 实现父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = 20; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.gifView.constraints.count) return; + + self.gifView.frame = self.bounds; + if (self.isRefreshingTitleHidden) { + self.gifView.contentMode = UIViewContentModeCenter; + } else { + self.gifView.contentMode = UIViewContentModeRight; + self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWidth * 0.5; + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStateRefreshing) { + NSArray *images = self.stateImages[@(state)]; + if (images.count == 0) return; + [self.gifView stopAnimating]; + + self.gifView.hidden = NO; + if (images.count == 1) { // 单张图片 + self.gifView.image = [images lastObject]; + } else { // 多张图片 + self.gifView.animationImages = images; + self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; + [self.gifView startAnimating]; + } + } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { + [self.gifView stopAnimating]; + self.gifView.hidden = YES; + } +} +@end + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h new file mode 100644 index 0000000..f8d1e04 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h @@ -0,0 +1,25 @@ +// +// MJRefreshAutoNormalFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshAutoStateFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshAutoNormalFooter : MJRefreshAutoStateFooter +@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView; + +/** 菊花的样式 */ +@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle MJRefreshDeprecated("first deprecated in 3.2.2 - Use `loadingView` property"); +@end + + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m new file mode 100644 index 0000000..9e6a03d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m @@ -0,0 +1,81 @@ +// +// MJRefreshAutoNormalFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshAutoNormalFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +@interface MJRefreshAutoNormalFooter() +@property (weak, nonatomic) UIActivityIndicatorView *loadingView; +@end + +@implementation MJRefreshAutoNormalFooter +#pragma mark - 懒加载子控件 +- (UIActivityIndicatorView *)loadingView +{ + if (!_loadingView) { + UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle]; + loadingView.hidesWhenStopped = YES; + [self addSubview:_loadingView = loadingView]; + } + return _loadingView; +} + +- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle +{ + _activityIndicatorViewStyle = activityIndicatorViewStyle; + + [self.loadingView removeFromSuperview]; + self.loadingView = nil; + [self setNeedsLayout]; +} +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, *)) { + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium; + return; + } +#endif + + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.loadingView.constraints.count) return; + + // 圈圈 + CGFloat loadingCenterX = self.mj_w * 0.5; + if (!self.isRefreshingTitleHidden) { + loadingCenterX -= self.stateLabel.mj_textWidth * 0.5 + self.labelLeftInset; + } + CGFloat loadingCenterY = self.mj_h * 0.5; + self.loadingView.center = CGPointMake(loadingCenterX, loadingCenterY); +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) { + [self.loadingView stopAnimating]; + } else if (state == MJRefreshStateRefreshing) { + [self.loadingView startAnimating]; + } +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h new file mode 100644 index 0000000..c83622d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h @@ -0,0 +1,30 @@ +// +// MJRefreshAutoStateFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/6/13. +// Copyright © 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshAutoFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshAutoStateFooter : MJRefreshAutoFooter +/** 文字距离圈圈、箭头的距离 */ +@property (assign, nonatomic) CGFloat labelLeftInset; +/** 显示刷新状态的label */ +@property (weak, nonatomic, readonly) UILabel *stateLabel; + +/** 设置state状态下的文字 */ +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state; + +/** 隐藏刷新状态的文字 */ +@property (assign, nonatomic, getter=isRefreshingTitleHidden) BOOL refreshingTitleHidden; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m new file mode 100644 index 0000000..e5ff652 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m @@ -0,0 +1,119 @@ +// +// MJRefreshAutoStateFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/6/13. +// Copyright © 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshAutoStateFooter.h" +#import "NSBundle+MJRefresh.h" + +@interface MJRefreshAutoFooter (TapTriggerFix) + +- (void)beginRefreshingWithoutValidation; +@end + + +@implementation MJRefreshAutoFooter (TapTriggerFix) + +- (void)beginRefreshingWithoutValidation { + [super beginRefreshing]; +} + +@end + +@interface MJRefreshAutoStateFooter() +{ + /** 显示刷新状态的label */ + __unsafe_unretained UILabel *_stateLabel; +} +/** 所有状态对应的文字 */ +@property (strong, nonatomic) NSMutableDictionary *stateTitles; +@end + +@implementation MJRefreshAutoStateFooter +#pragma mark - 懒加载 +- (NSMutableDictionary *)stateTitles +{ + if (!_stateTitles) { + self.stateTitles = [NSMutableDictionary dictionary]; + } + return _stateTitles; +} + +- (UILabel *)stateLabel +{ + if (!_stateLabel) { + [self addSubview:_stateLabel = [UILabel mj_label]]; + } + return _stateLabel; +} + +#pragma mark - 公共方法 +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state +{ + if (title == nil) return self; + self.stateTitles[@(state)] = title; + self.stateLabel.text = self.stateTitles[@(self.state)]; + return self; +} + +#pragma mark - 私有方法 +- (void)stateLabelClick +{ + if (self.state == MJRefreshStateIdle) { + [super beginRefreshingWithoutValidation]; + } +} + +- (void)textConfiguration { + // 初始化文字 + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterIdleText] forState:MJRefreshStateIdle]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterRefreshingText] forState:MJRefreshStateRefreshing]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterNoMoreDataText] forState:MJRefreshStateNoMoreData]; +} + +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = MJRefreshLabelLeftInset; + + [self textConfiguration]; + + // 监听label + self.stateLabel.userInteractionEnabled = YES; + [self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]]; +} + +- (void)i18nDidChange { + [self textConfiguration]; + + [super i18nDidChange]; +} + + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.stateLabel.constraints.count) return; + + // 状态标签 + self.stateLabel.frame = self.bounds; +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + if (self.isRefreshingTitleHidden && state == MJRefreshStateRefreshing) { + self.stateLabel.text = nil; + } else { + self.stateLabel.text = self.stateTitles[@(state)]; + } +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h new file mode 100644 index 0000000..a7ba065 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h @@ -0,0 +1,25 @@ +// +// MJRefreshBackGifFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshBackStateFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshBackGifFooter : MJRefreshBackStateFooter +@property (weak, nonatomic, readonly) UIImageView *gifView; + +/** 设置state状态下的动画图片images 动画持续时间duration*/ +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m new file mode 100644 index 0000000..23c626c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m @@ -0,0 +1,132 @@ +// +// MJRefreshBackGifFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshBackGifFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" + +@interface MJRefreshBackGifFooter() +{ + __unsafe_unretained UIImageView *_gifView; +} +/** 所有状态对应的动画图片 */ +@property (strong, nonatomic) NSMutableDictionary *stateImages; +/** 所有状态对应的动画时间 */ +@property (strong, nonatomic) NSMutableDictionary *stateDurations; +@end + +@implementation MJRefreshBackGifFooter +#pragma mark - 懒加载 +- (UIImageView *)gifView +{ + if (!_gifView) { + UIImageView *gifView = [[UIImageView alloc] init]; + [self addSubview:_gifView = gifView]; + } + return _gifView; +} + +- (NSMutableDictionary *)stateImages +{ + if (!_stateImages) { + self.stateImages = [NSMutableDictionary dictionary]; + } + return _stateImages; +} + +- (NSMutableDictionary *)stateDurations +{ + if (!_stateDurations) { + self.stateDurations = [NSMutableDictionary dictionary]; + } + return _stateDurations; +} + +#pragma mark - 公共方法 +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state +{ + if (images == nil) return self; + + self.stateImages[@(state)] = images; + self.stateDurations[@(state)] = @(duration); + + /* 根据图片设置控件的高度 */ + UIImage *image = [images firstObject]; + if (image.size.height > self.mj_h) { + self.mj_h = image.size.height; + } + return self; +} + +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state +{ + return [self setImages:images duration:images.count * 0.1 forState:state]; +} + +#pragma mark - 实现父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = 20; +} + +- (void)setPullingPercent:(CGFloat)pullingPercent +{ + [super setPullingPercent:pullingPercent]; + NSArray *images = self.stateImages[@(MJRefreshStateIdle)]; + if (self.state != MJRefreshStateIdle || images.count == 0) return; + [self.gifView stopAnimating]; + NSUInteger index = images.count * pullingPercent; + if (index >= images.count) index = images.count - 1; + self.gifView.image = images[index]; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.gifView.constraints.count) return; + + self.gifView.frame = self.bounds; + if (self.stateLabel.hidden) { + self.gifView.contentMode = UIViewContentModeCenter; + } else { + self.gifView.contentMode = UIViewContentModeRight; + self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWidth * 0.5; + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) { + NSArray *images = self.stateImages[@(state)]; + if (images.count == 0) return; + + self.gifView.hidden = NO; + [self.gifView stopAnimating]; + if (images.count == 1) { // 单张图片 + self.gifView.image = [images lastObject]; + } else { // 多张图片 + self.gifView.animationImages = images; + self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; + [self.gifView startAnimating]; + } + } else if (state == MJRefreshStateIdle) { + self.gifView.hidden = NO; + } else if (state == MJRefreshStateNoMoreData) { + self.gifView.hidden = YES; + } +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h new file mode 100644 index 0000000..d255807 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h @@ -0,0 +1,25 @@ +// +// MJRefreshBackNormalFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshBackStateFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshBackNormalFooter : MJRefreshBackStateFooter +@property (weak, nonatomic, readonly) UIImageView *arrowView; +@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView; + +/** 菊花的样式 */ +@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle MJRefreshDeprecated("first deprecated in 3.2.2 - Use `loadingView` property"); +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m new file mode 100644 index 0000000..932af76 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m @@ -0,0 +1,132 @@ +// +// MJRefreshBackNormalFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshBackNormalFooter.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" + +@interface MJRefreshBackNormalFooter() +{ + __unsafe_unretained UIImageView *_arrowView; +} +@property (weak, nonatomic) UIActivityIndicatorView *loadingView; +@end + +@implementation MJRefreshBackNormalFooter +#pragma mark - 懒加载子控件 +- (UIImageView *)arrowView +{ + if (!_arrowView) { + UIImageView *arrowView = [[UIImageView alloc] initWithImage:[NSBundle mj_arrowImage]]; + [self addSubview:_arrowView = arrowView]; + } + return _arrowView; +} + + +- (UIActivityIndicatorView *)loadingView +{ + if (!_loadingView) { + UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle]; + loadingView.hidesWhenStopped = YES; + [self addSubview:_loadingView = loadingView]; + } + return _loadingView; +} + +- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle +{ + _activityIndicatorViewStyle = activityIndicatorViewStyle; + + [self.loadingView removeFromSuperview]; + self.loadingView = nil; + [self setNeedsLayout]; +} +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, *)) { + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium; + return; + } +#endif + + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + // 箭头的中心点 + CGFloat arrowCenterX = self.mj_w * 0.5; + if (!self.stateLabel.hidden) { + arrowCenterX -= self.labelLeftInset + self.stateLabel.mj_textWidth * 0.5; + } + CGFloat arrowCenterY = self.mj_h * 0.5; + CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY); + + // 箭头 + if (self.arrowView.constraints.count == 0) { + self.arrowView.mj_size = self.arrowView.image.size; + self.arrowView.center = arrowCenter; + } + + // 圈圈 + if (self.loadingView.constraints.count == 0) { + self.loadingView.center = arrowCenter; + } + + self.arrowView.tintColor = self.stateLabel.textColor; +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStateIdle) { + if (oldState == MJRefreshStateRefreshing) { + self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + self.loadingView.alpha = 0.0; + } completion:^(BOOL finished) { + // 防止动画结束后,状态已经不是MJRefreshStateIdle + if (self.state != MJRefreshStateIdle) return; + + self.loadingView.alpha = 1.0; + [self.loadingView stopAnimating]; + + self.arrowView.hidden = NO; + }]; + } else { + self.arrowView.hidden = NO; + [self.loadingView stopAnimating]; + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); + }]; + } + } else if (state == MJRefreshStatePulling) { + self.arrowView.hidden = NO; + [self.loadingView stopAnimating]; + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformIdentity; + }]; + } else if (state == MJRefreshStateRefreshing) { + self.arrowView.hidden = YES; + [self.loadingView startAnimating]; + } else if (state == MJRefreshStateNoMoreData) { + self.arrowView.hidden = YES; + [self.loadingView stopAnimating]; + } +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h new file mode 100644 index 0000000..c6897f4 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h @@ -0,0 +1,29 @@ +// +// MJRefreshBackStateFooter.h +// MJRefresh +// +// Created by MJ Lee on 15/6/13. +// Copyright © 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshBackFooter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshBackStateFooter : MJRefreshBackFooter +/** 文字距离圈圈、箭头的距离 */ +@property (assign, nonatomic) CGFloat labelLeftInset; +/** 显示刷新状态的label */ +@property (weak, nonatomic, readonly) UILabel *stateLabel; +/** 设置state状态下的文字 */ +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state; + +/** 获取state状态下的title */ +- (NSString *)titleForState:(MJRefreshState)state; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m new file mode 100644 index 0000000..70f4024 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m @@ -0,0 +1,93 @@ +// +// MJRefreshBackStateFooter.m +// MJRefresh +// +// Created by MJ Lee on 15/6/13. +// Copyright © 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshBackStateFooter.h" +#import "NSBundle+MJRefresh.h" + +@interface MJRefreshBackStateFooter() +{ + /** 显示刷新状态的label */ + __unsafe_unretained UILabel *_stateLabel; +} +/** 所有状态对应的文字 */ +@property (strong, nonatomic) NSMutableDictionary *stateTitles; +@end + +@implementation MJRefreshBackStateFooter +#pragma mark - 懒加载 +- (NSMutableDictionary *)stateTitles +{ + if (!_stateTitles) { + self.stateTitles = [NSMutableDictionary dictionary]; + } + return _stateTitles; +} + +- (UILabel *)stateLabel +{ + if (!_stateLabel) { + [self addSubview:_stateLabel = [UILabel mj_label]]; + } + return _stateLabel; +} + +#pragma mark - 公共方法 +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state +{ + if (title == nil) return self; + self.stateTitles[@(state)] = title; + self.stateLabel.text = self.stateTitles[@(self.state)]; + return self; +} + +- (NSString *)titleForState:(MJRefreshState)state { + return self.stateTitles[@(state)]; +} + +- (void)textConfiguration { + // 初始化文字 + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterIdleText] forState:MJRefreshStateIdle]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterPullingText] forState:MJRefreshStatePulling]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterRefreshingText] forState:MJRefreshStateRefreshing]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterNoMoreDataText] forState:MJRefreshStateNoMoreData]; +} + +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = MJRefreshLabelLeftInset; + [self textConfiguration]; +} + +- (void)i18nDidChange { + [self textConfiguration]; + + [super i18nDidChange]; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.stateLabel.constraints.count) return; + + // 状态标签 + self.stateLabel.frame = self.bounds; +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 设置状态文字 + self.stateLabel.text = self.stateTitles[@(state)]; +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h new file mode 100644 index 0000000..afa4a13 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h @@ -0,0 +1,25 @@ +// +// MJRefreshGifHeader.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshStateHeader.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshGifHeader : MJRefreshStateHeader +@property (weak, nonatomic, readonly) UIImageView *gifView; + +/** 设置state状态下的动画图片images 动画持续时间duration*/ +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state; +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m new file mode 100644 index 0000000..707e466 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m @@ -0,0 +1,135 @@ +// +// MJRefreshGifHeader.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshGifHeader.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" + +@interface MJRefreshGifHeader() +{ + __unsafe_unretained UIImageView *_gifView; +} +/** 所有状态对应的动画图片 */ +@property (strong, nonatomic) NSMutableDictionary *stateImages; +/** 所有状态对应的动画时间 */ +@property (strong, nonatomic) NSMutableDictionary *stateDurations; +@end + +@implementation MJRefreshGifHeader +#pragma mark - 懒加载 +- (UIImageView *)gifView +{ + if (!_gifView) { + UIImageView *gifView = [[UIImageView alloc] init]; + [self addSubview:_gifView = gifView]; + } + return _gifView; +} + +- (NSMutableDictionary *)stateImages +{ + if (!_stateImages) { + self.stateImages = [NSMutableDictionary dictionary]; + } + return _stateImages; +} + +- (NSMutableDictionary *)stateDurations +{ + if (!_stateDurations) { + self.stateDurations = [NSMutableDictionary dictionary]; + } + return _stateDurations; +} + +#pragma mark - 公共方法 +- (instancetype)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state { + if (images == nil) return self; + + self.stateImages[@(state)] = images; + self.stateDurations[@(state)] = @(duration); + + /* 根据图片设置控件的高度 */ + UIImage *image = [images firstObject]; + if (image.size.height > self.mj_h) { + self.mj_h = image.size.height; + } + return self; +} + +- (instancetype)setImages:(NSArray *)images forState:(MJRefreshState)state +{ + return [self setImages:images duration:images.count * 0.1 forState:state]; +} + +#pragma mark - 实现父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = 20; +} + +- (void)setPullingPercent:(CGFloat)pullingPercent +{ + [super setPullingPercent:pullingPercent]; + NSArray *images = self.stateImages[@(MJRefreshStateIdle)]; + if (self.state != MJRefreshStateIdle || images.count == 0) return; + // 停止动画 + [self.gifView stopAnimating]; + // 设置当前需要显示的图片 + NSUInteger index = images.count * pullingPercent; + if (index >= images.count) index = images.count - 1; + self.gifView.image = images[index]; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.gifView.constraints.count) return; + + self.gifView.frame = self.bounds; + if (self.stateLabel.hidden && self.lastUpdatedTimeLabel.hidden) { + self.gifView.contentMode = UIViewContentModeCenter; + } else { + self.gifView.contentMode = UIViewContentModeRight; + + CGFloat stateWidth = self.stateLabel.mj_textWidth; + CGFloat timeWidth = 0.0; + if (!self.lastUpdatedTimeLabel.hidden) { + timeWidth = self.lastUpdatedTimeLabel.mj_textWidth; + } + CGFloat textWidth = MAX(stateWidth, timeWidth); + self.gifView.mj_w = self.mj_w * 0.5 - textWidth * 0.5 - self.labelLeftInset; + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) { + NSArray *images = self.stateImages[@(state)]; + if (images.count == 0) return; + + [self.gifView stopAnimating]; + if (images.count == 1) { // 单张图片 + self.gifView.image = [images lastObject]; + } else { // 多张图片 + self.gifView.animationImages = images; + self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue]; + [self.gifView startAnimating]; + } + } else if (state == MJRefreshStateIdle) { + [self.gifView stopAnimating]; + } +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h new file mode 100644 index 0000000..2bfef39 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h @@ -0,0 +1,26 @@ +// +// MJRefreshNormalHeader.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshStateHeader.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshNormalHeader : MJRefreshStateHeader +@property (weak, nonatomic, readonly) UIImageView *arrowView; +@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView; + + +/** 菊花的样式 */ +@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle MJRefreshDeprecated("first deprecated in 3.2.2 - Use `loadingView` property"); +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m new file mode 100644 index 0000000..84a66cb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m @@ -0,0 +1,137 @@ +// +// MJRefreshNormalHeader.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshNormalHeader.h" +#import "NSBundle+MJRefresh.h" +#import "UIScrollView+MJRefresh.h" +#import "UIView+MJExtension.h" + +@interface MJRefreshNormalHeader() +{ + __unsafe_unretained UIImageView *_arrowView; +} +@property (weak, nonatomic) UIActivityIndicatorView *loadingView; +@end + +@implementation MJRefreshNormalHeader +#pragma mark - 懒加载子控件 +- (UIImageView *)arrowView +{ + if (!_arrowView) { + UIImageView *arrowView = [[UIImageView alloc] initWithImage:[NSBundle mj_arrowImage]]; + [self addSubview:_arrowView = arrowView]; + } + return _arrowView; +} + +- (UIActivityIndicatorView *)loadingView +{ + if (!_loadingView) { + UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle]; + loadingView.hidesWhenStopped = YES; + [self addSubview:_loadingView = loadingView]; + } + return _loadingView; +} + +#pragma mark - 公共方法 +- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle +{ + _activityIndicatorViewStyle = activityIndicatorViewStyle; + + [self.loadingView removeFromSuperview]; + self.loadingView = nil; + [self setNeedsLayout]; +} + +#pragma mark - 重写父类的方法 +- (void)prepare +{ + [super prepare]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, *)) { + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium; + return; + } +#endif + + _activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + // 箭头的中心点 + CGFloat arrowCenterX = self.mj_w * 0.5; + if (!self.stateLabel.hidden) { + CGFloat stateWidth = self.stateLabel.mj_textWidth; + CGFloat timeWidth = 0.0; + if (!self.lastUpdatedTimeLabel.hidden) { + timeWidth = self.lastUpdatedTimeLabel.mj_textWidth; + } + CGFloat textWidth = MAX(stateWidth, timeWidth); + arrowCenterX -= textWidth / 2 + self.labelLeftInset; + } + CGFloat arrowCenterY = self.mj_h * 0.5; + CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY); + + // 箭头 + if (self.arrowView.constraints.count == 0) { + self.arrowView.mj_size = self.arrowView.image.size; + self.arrowView.center = arrowCenter; + } + + // 圈圈 + if (self.loadingView.constraints.count == 0) { + self.loadingView.center = arrowCenter; + } + + self.arrowView.tintColor = self.stateLabel.textColor; +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 根据状态做事情 + if (state == MJRefreshStateIdle) { + if (oldState == MJRefreshStateRefreshing) { + self.arrowView.transform = CGAffineTransformIdentity; + + [UIView animateWithDuration:self.slowAnimationDuration animations:^{ + self.loadingView.alpha = 0.0; + } completion:^(BOOL finished) { + // 如果执行完动画发现不是idle状态,就直接返回,进入其他状态 + if (self.state != MJRefreshStateIdle) return; + + self.loadingView.alpha = 1.0; + [self.loadingView stopAnimating]; + self.arrowView.hidden = NO; + }]; + } else { + [self.loadingView stopAnimating]; + self.arrowView.hidden = NO; + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformIdentity; + }]; + } + } else if (state == MJRefreshStatePulling) { + [self.loadingView stopAnimating]; + self.arrowView.hidden = NO; + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI); + }]; + } else if (state == MJRefreshStateRefreshing) { + self.loadingView.alpha = 1.0; // 防止refreshing -> idle的动画完毕动作没有被执行 + [self.loadingView startAnimating]; + self.arrowView.hidden = YES; + } +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h new file mode 100644 index 0000000..8e1d108 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h @@ -0,0 +1,39 @@ +// +// MJRefreshStateHeader.h +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshHeader.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshStateHeader : MJRefreshHeader +#pragma mark - 刷新时间相关 +/** 利用这个block来决定显示的更新时间文字 */ +@property (copy, nonatomic, nullable) NSString *(^lastUpdatedTimeText)(NSDate * _Nullable lastUpdatedTime); +/** 显示上一次刷新时间的label */ +@property (weak, nonatomic, readonly) UILabel *lastUpdatedTimeLabel; + +#pragma mark - 状态相关 +/** 文字距离圈圈、箭头的距离 */ +@property (assign, nonatomic) CGFloat labelLeftInset; +/** 显示刷新状态的label */ +@property (weak, nonatomic, readonly) UILabel *stateLabel; +/** 设置state状态下的文字 */ +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state; +@end + +@interface MJRefreshStateHeader (ChainingGrammar) + +- (instancetype)modifyLastUpdatedTimeText:(NSString * (^)(NSDate * _Nullable lastUpdatedTime))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m new file mode 100644 index 0000000..62d1ddc --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m @@ -0,0 +1,191 @@ +// +// MJRefreshStateHeader.m +// MJRefresh +// +// Created by MJ Lee on 15/4/24. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "MJRefreshStateHeader.h" +#import "MJRefreshConst.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" +#import "UIScrollView+MJExtension.h" + +@interface MJRefreshStateHeader() +{ + /** 显示上一次刷新时间的label */ + __unsafe_unretained UILabel *_lastUpdatedTimeLabel; + /** 显示刷新状态的label */ + __unsafe_unretained UILabel *_stateLabel; +} +/** 所有状态对应的文字 */ +@property (strong, nonatomic) NSMutableDictionary *stateTitles; +@end + +@implementation MJRefreshStateHeader +#pragma mark - 懒加载 +- (NSMutableDictionary *)stateTitles +{ + if (!_stateTitles) { + self.stateTitles = [NSMutableDictionary dictionary]; + } + return _stateTitles; +} + +- (UILabel *)stateLabel +{ + if (!_stateLabel) { + [self addSubview:_stateLabel = [UILabel mj_label]]; + } + return _stateLabel; +} + +- (UILabel *)lastUpdatedTimeLabel +{ + if (!_lastUpdatedTimeLabel) { + [self addSubview:_lastUpdatedTimeLabel = [UILabel mj_label]]; + } + return _lastUpdatedTimeLabel; +} + +- (void)setLastUpdatedTimeText:(NSString * _Nonnull (^)(NSDate * _Nullable))lastUpdatedTimeText{ + _lastUpdatedTimeText = lastUpdatedTimeText; + // 重新设置key(重新显示时间) + self.lastUpdatedTimeKey = self.lastUpdatedTimeKey; +} + +#pragma mark - 公共方法 +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state +{ + if (title == nil) return self; + self.stateTitles[@(state)] = title; + self.stateLabel.text = self.stateTitles[@(self.state)]; + return self; +} + +#pragma mark key的处理 +- (void)setLastUpdatedTimeKey:(NSString *)lastUpdatedTimeKey +{ + [super setLastUpdatedTimeKey:lastUpdatedTimeKey]; + + // 如果label隐藏了,就不用再处理 + if (self.lastUpdatedTimeLabel.hidden) return; + + NSDate *lastUpdatedTime = [[NSUserDefaults standardUserDefaults] objectForKey:lastUpdatedTimeKey]; + + // 如果有block + if (self.lastUpdatedTimeText) { + self.lastUpdatedTimeLabel.text = self.lastUpdatedTimeText(lastUpdatedTime); + return; + } + + if (lastUpdatedTime) { + // 1.获得年月日 + NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute; + NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:lastUpdatedTime]; + NSDateComponents *cmp2 = [calendar components:unitFlags fromDate:[NSDate date]]; + + // 2.格式化日期 + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + BOOL isToday = NO; + if ([cmp1 day] == [cmp2 day]) { // 今天 + formatter.dateFormat = @" HH:mm"; + isToday = YES; + } else if ([cmp1 year] == [cmp2 year]) { // 今年 + formatter.dateFormat = @"MM-dd HH:mm"; + } else { + formatter.dateFormat = @"yyyy-MM-dd HH:mm"; + } + NSString *time = [formatter stringFromDate:lastUpdatedTime]; + + // 3.显示日期 + self.lastUpdatedTimeLabel.text = [NSString stringWithFormat:@"%@%@%@", + [NSBundle mj_localizedStringForKey:MJRefreshHeaderLastTimeText], + isToday ? [NSBundle mj_localizedStringForKey:MJRefreshHeaderDateTodayText] : @"", + time]; + } else { + self.lastUpdatedTimeLabel.text = [NSString stringWithFormat:@"%@%@", + [NSBundle mj_localizedStringForKey:MJRefreshHeaderLastTimeText], + [NSBundle mj_localizedStringForKey:MJRefreshHeaderNoneLastDateText]]; + } +} + + +- (void)textConfiguration { + // 初始化文字 + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderIdleText] forState:MJRefreshStateIdle]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderPullingText] forState:MJRefreshStatePulling]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderRefreshingText] forState:MJRefreshStateRefreshing]; + self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey; +} + +#pragma mark - 覆盖父类的方法 +- (void)prepare +{ + [super prepare]; + + // 初始化间距 + self.labelLeftInset = MJRefreshLabelLeftInset; + [self textConfiguration]; +} + +- (void)i18nDidChange { + [self textConfiguration]; + + [super i18nDidChange]; +} + +- (void)placeSubviews +{ + [super placeSubviews]; + + if (self.stateLabel.hidden) return; + + BOOL noConstrainsOnStatusLabel = self.stateLabel.constraints.count == 0; + + if (self.lastUpdatedTimeLabel.hidden) { + // 状态 + if (noConstrainsOnStatusLabel) self.stateLabel.frame = self.bounds; + } else { + CGFloat stateLabelH = self.mj_h * 0.5; + // 状态 + if (noConstrainsOnStatusLabel) { + self.stateLabel.mj_x = 0; + self.stateLabel.mj_y = 0; + self.stateLabel.mj_w = self.mj_w; + self.stateLabel.mj_h = stateLabelH; + } + + // 更新时间 + if (self.lastUpdatedTimeLabel.constraints.count == 0) { + self.lastUpdatedTimeLabel.mj_x = 0; + self.lastUpdatedTimeLabel.mj_y = stateLabelH; + self.lastUpdatedTimeLabel.mj_w = self.mj_w; + self.lastUpdatedTimeLabel.mj_h = self.mj_h - self.lastUpdatedTimeLabel.mj_y; + } + } +} + +- (void)setState:(MJRefreshState)state +{ + MJRefreshCheckState + + // 设置状态文字 + self.stateLabel.text = self.stateTitles[@(state)]; + + // 重新设置key(重新显示时间) + self.lastUpdatedTimeKey = self.lastUpdatedTimeKey; +} +@end + +#pragma mark - <<< 为 Swift 扩展链式语法 >>> - +@implementation MJRefreshStateHeader (ChainingGrammar) + +- (instancetype)modifyLastUpdatedTimeText:(NSString * _Nonnull (^)(NSDate * _Nullable))handler { + self.lastUpdatedTimeText = handler; + return self; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h new file mode 100644 index 0000000..97385d7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h @@ -0,0 +1,23 @@ +// +// MJRefreshNormalTrailer.h +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshStateTrailer.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshNormalTrailer : MJRefreshStateTrailer + +@property (weak, nonatomic, readonly) UIImageView *arrowView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m new file mode 100644 index 0000000..4b269f2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m @@ -0,0 +1,80 @@ +// +// MJRefreshNormalTrailer.m +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#import "MJRefreshNormalTrailer.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" + +@interface MJRefreshNormalTrailer() { + __unsafe_unretained UIImageView *_arrowView; +} +@end + +@implementation MJRefreshNormalTrailer +#pragma mark - 懒加载子控件 +- (UIImageView *)arrowView { + if (!_arrowView) { + UIImageView *arrowView = [[UIImageView alloc] initWithImage:[NSBundle mj_trailArrowImage]]; + [self addSubview:_arrowView = arrowView]; + } + return _arrowView; +} + +- (void)placeSubviews { + [super placeSubviews]; + + CGSize arrowSize = self.arrowView.image.size; + // 箭头的中心点 + CGPoint selfCenter = CGPointMake(self.mj_w * 0.5, self.mj_h * 0.5); + CGPoint arrowCenter = CGPointMake(arrowSize.width * 0.5 + 5, self.mj_h * 0.5); + BOOL stateHidden = self.stateLabel.isHidden; + + if (self.arrowView.constraints.count == 0) { + self.arrowView.mj_size = self.arrowView.image.size; + self.arrowView.center = stateHidden ? selfCenter : arrowCenter ; + } + self.arrowView.tintColor = self.stateLabel.textColor; + + if (stateHidden) return; + + BOOL noConstrainsOnStatusLabel = self.stateLabel.constraints.count == 0; + CGFloat stateLabelW = ceil(self.stateLabel.font.pointSize); + // 状态 + if (noConstrainsOnStatusLabel) { + BOOL arrowHidden = self.arrowView.isHidden; + CGFloat stateCenterX = (self.mj_w + arrowSize.width) * 0.5; + self.stateLabel.center = arrowHidden ? selfCenter : CGPointMake(stateCenterX, self.mj_h * 0.5); + self.stateLabel.mj_size = CGSizeMake(stateLabelW, self.mj_h) ; + } +} + +- (void)setState:(MJRefreshState)state { + MJRefreshCheckState + // 根据状态做事情 + if (state == MJRefreshStateIdle) { + if (oldState == MJRefreshStateRefreshing) { + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformMakeRotation(M_PI); + } completion:^(BOOL finished) { + self.arrowView.transform = CGAffineTransformIdentity; + }]; + } else { + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformIdentity; + }]; + } + } else if (state == MJRefreshStatePulling) { + [UIView animateWithDuration:self.fastAnimationDuration animations:^{ + self.arrowView.transform = CGAffineTransformMakeRotation(M_PI); + }]; + } +} + + + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h new file mode 100644 index 0000000..92ac203 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h @@ -0,0 +1,28 @@ +// +// MJRefreshStateTrailer.h +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#if __has_include() +#import +#else +#import "MJRefreshTrailer.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + + +@interface MJRefreshStateTrailer : MJRefreshTrailer + +#pragma mark - 状态相关 +/** 显示刷新状态的label */ +@property (weak, nonatomic, readonly) UILabel *stateLabel; +/** 设置state状态下的文字 */ +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m new file mode 100644 index 0000000..3ce0ba6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m @@ -0,0 +1,87 @@ +// +// MJRefreshStateTrailer.m +// MJRefresh +// +// Created by kinarobin on 2020/5/3. +// Copyright © 2020 小码哥. All rights reserved. +// + +#import "MJRefreshStateTrailer.h" +#import "NSBundle+MJRefresh.h" +#import "UIView+MJExtension.h" + +@interface MJRefreshStateTrailer() { + /** 显示刷新状态的label */ + __unsafe_unretained UILabel *_stateLabel; +} +/** 所有状态对应的文字 */ +@property (strong, nonatomic) NSMutableDictionary *stateTitles; +@end + +@implementation MJRefreshStateTrailer +#pragma mark - 懒加载 +- (NSMutableDictionary *)stateTitles { + if (!_stateTitles) { + self.stateTitles = [NSMutableDictionary dictionary]; + } + return _stateTitles; +} + +- (UILabel *)stateLabel { + if (!_stateLabel) { + UILabel *stateLabel = [UILabel mj_label]; + stateLabel.numberOfLines = 0; + [self addSubview:_stateLabel = stateLabel]; + } + return _stateLabel; +} + +#pragma mark - 公共方法 +- (instancetype)setTitle:(NSString *)title forState:(MJRefreshState)state { + if (title == nil) return self; + self.stateTitles[@(state)] = title; + self.stateLabel.text = self.stateTitles[@(self.state)]; + return self; +} + +- (void)textConfiguration { + // 初始化文字 + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerIdleText] forState:MJRefreshStateIdle]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerPullingText] forState:MJRefreshStatePulling]; + [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshTrailerPullingText] forState:MJRefreshStateRefreshing]; +} + +#pragma mark - 覆盖父类的方法 +- (void)prepare { + [super prepare]; + + [self textConfiguration]; +} + +- (void)i18nDidChange { + [self textConfiguration]; + + [super i18nDidChange]; +} + +- (void)setState:(MJRefreshState)state { + MJRefreshCheckState + // 设置状态文字 + self.stateLabel.text = self.stateTitles[@(state)]; +} + +- (void)placeSubviews { + [super placeSubviews]; + + if (self.stateLabel.hidden) return; + + BOOL noConstrainsOnStatusLabel = self.stateLabel.constraints.count == 0; + CGFloat stateLabelW = ceil(self.stateLabel.font.pointSize); + // 状态 + if (noConstrainsOnStatusLabel) { + self.stateLabel.center = CGPointMake(self.mj_w * 0.5, self.mj_h * 0.5); + self.stateLabel.mj_size = CGSizeMake(stateLabelW, self.mj_h) ; + } +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/arrow@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/arrow@2x.png new file mode 100644 index 0000000..b1078de Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/arrow@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/en.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/en.lproj/Localizable.strings new file mode 100644 index 0000000..bf56786 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/en.lproj/Localizable.strings differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ko.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ko.lproj/Localizable.strings new file mode 100644 index 0000000..ac25579 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ko.lproj/Localizable.strings @@ -0,0 +1,16 @@ +"MJRefreshHeaderIdleText" = "아래로 당겨 새로고침"; +"MJRefreshHeaderPullingText" = "놓으면 새로고침"; +"MJRefreshHeaderRefreshingText" = "로딩중..."; + +"MJRefreshAutoFooterIdleText" = "탭 또는 위로 당겨 로드함"; +"MJRefreshAutoFooterRefreshingText" = "로딩중..."; +"MJRefreshAutoFooterNoMoreDataText" = "더이상 데이터 없음"; + +"MJRefreshBackFooterIdleText" = "위로 당겨 더 로드 가능"; +"MJRefreshBackFooterPullingText" = "놓으면 더 로드됨."; +"MJRefreshBackFooterRefreshingText" = "로딩중..."; +"MJRefreshBackFooterNoMoreDataText" = "더이상 데이터 없음"; + +"MJRefreshHeaderLastTimeText" = "마지막 업데이트: "; +"MJRefreshHeaderDateTodayText" = "오늘"; +"MJRefreshHeaderNoneLastDateText" = "기록 없음"; diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ru.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ru.lproj/Localizable.strings new file mode 100644 index 0000000..7890e7b Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/ru.lproj/Localizable.strings differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/trail_arrow@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/trail_arrow@2x.png new file mode 100644 index 0000000..a45f933 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/trail_arrow@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/uk.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/uk.lproj/Localizable.strings new file mode 100644 index 0000000..3557940 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/uk.lproj/Localizable.strings differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hans.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..1066e3d Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hans.lproj/Localizable.strings differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hant.lproj/Localizable.strings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hant.lproj/Localizable.strings new file mode 100644 index 0000000..17417b5 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hant.lproj/Localizable.strings @@ -0,0 +1,19 @@ +"MJRefreshHeaderIdleText" = "下拉可以刷新"; +"MJRefreshHeaderPullingText" = "鬆開立即刷新"; +"MJRefreshHeaderRefreshingText" = "正在刷新數據中..."; + +"MJRefreshTrailerIdleText" = "滑動查看圖文詳情"; +"MJRefreshTrailerPullingText" = "釋放查看圖文詳情"; + +"MJRefreshAutoFooterIdleText" = "點擊或上拉加載更多"; +"MJRefreshAutoFooterRefreshingText" = "正在加載更多的數據..."; +"MJRefreshAutoFooterNoMoreDataText" = "已經全部加載完畢"; + +"MJRefreshBackFooterIdleText" = "上拉可以加載更多"; +"MJRefreshBackFooterPullingText" = "鬆開立即加載更多"; +"MJRefreshBackFooterRefreshingText" = "正在加載更多的數據..."; +"MJRefreshBackFooterNoMoreDataText" = "已經全部加載完畢"; + +"MJRefreshHeaderLastTimeText" = "最後更新:"; +"MJRefreshHeaderDateTodayText" = "今天"; +"MJRefreshHeaderNoneLastDateText" = "無記錄"; diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.h new file mode 100644 index 0000000..d878212 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefresh.h @@ -0,0 +1,42 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh + +#import + +#if __has_include() +FOUNDATION_EXPORT double MJRefreshVersionNumber; +FOUNDATION_EXPORT const unsigned char MJRefreshVersionString[]; + +#import +#import +#import + +#import +#import + +#import +#import +#import +#import + +#import +#import +#import +#import +#else +#import "UIScrollView+MJRefresh.h" +#import "UIScrollView+MJExtension.h" +#import "UIView+MJExtension.h" + +#import "MJRefreshNormalHeader.h" +#import "MJRefreshGifHeader.h" + +#import "MJRefreshBackNormalFooter.h" +#import "MJRefreshBackGifFooter.h" +#import "MJRefreshAutoNormalFooter.h" +#import "MJRefreshAutoGifFooter.h" + +#import "MJRefreshNormalTrailer.h" +#import "MJRefreshConfig.h" +#import "NSBundle+MJRefresh.h" +#import "MJRefreshConst.h" +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.h new file mode 100644 index 0000000..b2c808f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.h @@ -0,0 +1,36 @@ +// +// MJRefreshConfig.h +// +// Created by Frank on 2018/11/27. +// Copyright © 2018 小码哥. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MJRefreshConfig : NSObject + +/** 默认使用的语言版本, 默认为 nil. 将随系统的语言自动改变 */ +@property (copy, nonatomic, nullable) NSString *languageCode; + +/** 默认使用的语言资源文件名, 默认为 nil, 即默认的 Localizable.strings. + + - Attention: 文件名不包含后缀.strings + */ +@property (copy, nonatomic, nullable) NSString *i18nFilename; +/** i18n 多语言资源加载自定义 Bundle. + + - Attention: 默认为 nil 采用内置逻辑. 这里设置后将忽略内置逻辑的多语言模式, 采用自定义的多语言 bundle + */ +@property (nonatomic, nullable) NSBundle *i18nBundle; + +/** Singleton Config instance */ +@property (class, nonatomic, readonly) MJRefreshConfig *defaultConfig; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.m new file mode 100644 index 0000000..680b95a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConfig.m @@ -0,0 +1,42 @@ +// +// MJRefreshConfig.m +// +// Created by Frank on 2018/11/27. +// Copyright © 2018 小码哥. All rights reserved. +// + +#import "MJRefreshConfig.h" +#import "MJRefreshConst.h" +#import "NSBundle+MJRefresh.h" + +@interface MJRefreshConfig (Bundle) + ++ (void)resetLanguageResourceCache; + +@end + +@implementation MJRefreshConfig + +static MJRefreshConfig *mj_RefreshConfig = nil; + ++ (instancetype)defaultConfig { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + mj_RefreshConfig = [[self alloc] init]; + }); + return mj_RefreshConfig; +} + +- (void)setLanguageCode:(NSString *)languageCode { + if ([languageCode isEqualToString:_languageCode]) { + return; + } + + _languageCode = languageCode; + // 重置语言资源 + [MJRefreshConfig resetLanguageResourceCache]; + [NSNotificationCenter.defaultCenter + postNotificationName:MJRefreshDidChangeLanguageNotification object:self]; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.h new file mode 100644 index 0000000..6881115 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.h @@ -0,0 +1,115 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +#import +#import +#import + +// 弱引用 +#define MJWeakSelf __weak typeof(self) weakSelf = self; + +// 日志输出 +#ifdef DEBUG +#define MJRefreshLog(...) NSLog(__VA_ARGS__) +#else +#define MJRefreshLog(...) +#endif + +// 过期提醒 +#define MJRefreshDeprecated(DESCRIPTION) __attribute__((deprecated(DESCRIPTION))) + +// 运行时objc_msgSend +#define MJRefreshMsgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__) +#define MJRefreshMsgTarget(target) (__bridge void *)(target) + +// RGB颜色 +#define MJRefreshColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] + +// 文字颜色 +#define MJRefreshLabelTextColor MJRefreshColor(90, 90, 90) + +// 字体大小 +#define MJRefreshLabelFont [UIFont boldSystemFontOfSize:14] + +// 常量 +UIKIT_EXTERN const CGFloat MJRefreshLabelLeftInset; +UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight; +UIKIT_EXTERN const CGFloat MJRefreshFooterHeight; +UIKIT_EXTERN const CGFloat MJRefreshTrailWidth; +UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration; +UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration; + + +UIKIT_EXTERN NSString *const MJRefreshKeyPathContentOffset; +UIKIT_EXTERN NSString *const MJRefreshKeyPathContentSize; +UIKIT_EXTERN NSString *const MJRefreshKeyPathContentInset; +UIKIT_EXTERN NSString *const MJRefreshKeyPathPanState; + +UIKIT_EXTERN NSString *const MJRefreshHeaderLastUpdatedTimeKey; + +UIKIT_EXTERN NSString *const MJRefreshHeaderIdleText; +UIKIT_EXTERN NSString *const MJRefreshHeaderPullingText; +UIKIT_EXTERN NSString *const MJRefreshHeaderRefreshingText; + +UIKIT_EXTERN NSString *const MJRefreshTrailerIdleText; +UIKIT_EXTERN NSString *const MJRefreshTrailerPullingText; + +UIKIT_EXTERN NSString *const MJRefreshAutoFooterIdleText; +UIKIT_EXTERN NSString *const MJRefreshAutoFooterRefreshingText; +UIKIT_EXTERN NSString *const MJRefreshAutoFooterNoMoreDataText; + +UIKIT_EXTERN NSString *const MJRefreshBackFooterIdleText; +UIKIT_EXTERN NSString *const MJRefreshBackFooterPullingText; +UIKIT_EXTERN NSString *const MJRefreshBackFooterRefreshingText; +UIKIT_EXTERN NSString *const MJRefreshBackFooterNoMoreDataText; + +UIKIT_EXTERN NSString *const MJRefreshHeaderLastTimeText; +UIKIT_EXTERN NSString *const MJRefreshHeaderDateTodayText; +UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText; + +UIKIT_EXTERN NSString *const MJRefreshDidChangeLanguageNotification; + +// 状态检查 +#define MJRefreshCheckState \ +MJRefreshState oldState = self.state; \ +if (state == oldState) return; \ +[super setState:state]; + +// 异步主线程执行,不强持有Self +#define MJRefreshDispatchAsyncOnMainQueue(x) \ +__weak typeof(self) weakSelf = self; \ +dispatch_async(dispatch_get_main_queue(), ^{ \ +typeof(weakSelf) self = weakSelf; \ +{x} \ +}); + +/// 替换方法实现 +/// @param _fromClass 源类 +/// @param _originSelector 源类的 Selector +/// @param _toClass 目标类 +/// @param _newSelector 目标类的 Selector +CG_INLINE BOOL MJRefreshExchangeImplementations( + Class _fromClass, SEL _originSelector, + Class _toClass, SEL _newSelector) { + if (!_fromClass || !_toClass) { + return NO; + } + + Method oriMethod = class_getInstanceMethod(_fromClass, _originSelector); + Method newMethod = class_getInstanceMethod(_toClass, _newSelector); + if (!newMethod) { + return NO; + } + + BOOL isAddedMethod = class_addMethod(_fromClass, _originSelector, + method_getImplementation(newMethod), + method_getTypeEncoding(newMethod)); + if (isAddedMethod) { + // 如果 class_addMethod 成功了,说明之前 fromClass 里并不存在 originSelector,所以要用一个空的方法代替它,以避免 class_replaceMethod 后,后续 toClass 的这个方法被调用时可能会 crash + IMP emptyIMP = imp_implementationWithBlock(^(id selfObject) {}); + IMP oriMethodIMP = method_getImplementation(oriMethod) ?: emptyIMP; + const char *oriMethodTypeEncoding = method_getTypeEncoding(oriMethod) ?: "v@:"; + class_replaceMethod(_toClass, _newSelector, oriMethodIMP, oriMethodTypeEncoding); + } else { + method_exchangeImplementations(oriMethod, newMethod); + } + return YES; +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.m new file mode 100644 index 0000000..704d4c7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/MJRefreshConst.m @@ -0,0 +1,39 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +#import + +const CGFloat MJRefreshLabelLeftInset = 25; +const CGFloat MJRefreshHeaderHeight = 54.0; +const CGFloat MJRefreshFooterHeight = 44.0; +const CGFloat MJRefreshTrailWidth = 60.0; +const CGFloat MJRefreshFastAnimationDuration = 0.25; +const CGFloat MJRefreshSlowAnimationDuration = 0.4; + + +NSString *const MJRefreshKeyPathContentOffset = @"contentOffset"; +NSString *const MJRefreshKeyPathContentInset = @"contentInset"; +NSString *const MJRefreshKeyPathContentSize = @"contentSize"; +NSString *const MJRefreshKeyPathPanState = @"state"; + +NSString *const MJRefreshHeaderLastUpdatedTimeKey = @"MJRefreshHeaderLastUpdatedTimeKey"; + +NSString *const MJRefreshHeaderIdleText = @"MJRefreshHeaderIdleText"; +NSString *const MJRefreshHeaderPullingText = @"MJRefreshHeaderPullingText"; +NSString *const MJRefreshHeaderRefreshingText = @"MJRefreshHeaderRefreshingText"; + +NSString *const MJRefreshTrailerIdleText = @"MJRefreshTrailerIdleText"; +NSString *const MJRefreshTrailerPullingText = @"MJRefreshTrailerPullingText"; + +NSString *const MJRefreshAutoFooterIdleText = @"MJRefreshAutoFooterIdleText"; +NSString *const MJRefreshAutoFooterRefreshingText = @"MJRefreshAutoFooterRefreshingText"; +NSString *const MJRefreshAutoFooterNoMoreDataText = @"MJRefreshAutoFooterNoMoreDataText"; + +NSString *const MJRefreshBackFooterIdleText = @"MJRefreshBackFooterIdleText"; +NSString *const MJRefreshBackFooterPullingText = @"MJRefreshBackFooterPullingText"; +NSString *const MJRefreshBackFooterRefreshingText = @"MJRefreshBackFooterRefreshingText"; +NSString *const MJRefreshBackFooterNoMoreDataText = @"MJRefreshBackFooterNoMoreDataText"; + +NSString *const MJRefreshHeaderLastTimeText = @"MJRefreshHeaderLastTimeText"; +NSString *const MJRefreshHeaderDateTodayText = @"MJRefreshHeaderDateTodayText"; +NSString *const MJRefreshHeaderNoneLastDateText = @"MJRefreshHeaderNoneLastDateText"; + +NSString *const MJRefreshDidChangeLanguageNotification = @"MJRefreshDidChangeLanguageNotification"; diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.h new file mode 100644 index 0000000..a1f56f4 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.h @@ -0,0 +1,21 @@ +// +// NSBundle+MJRefresh.h +// MJRefresh +// +// Created by MJ Lee on 16/6/13. +// Copyright © 2016年 小码哥. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSBundle (MJRefresh) ++ (instancetype)mj_refreshBundle; ++ (UIImage *)mj_arrowImage; ++ (UIImage *)mj_trailArrowImage; ++ (NSString *)mj_localizedStringForKey:(NSString *)key value:(nullable NSString *)value; ++ (NSString *)mj_localizedStringForKey:(NSString *)key; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.m new file mode 100644 index 0000000..c19cbe8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.m @@ -0,0 +1,116 @@ +// +// NSBundle+MJRefresh.m +// MJRefresh +// +// Created by MJ Lee on 16/6/13. +// Copyright © 2016年 小码哥. All rights reserved. +// + +#import "NSBundle+MJRefresh.h" +#import "MJRefreshComponent.h" +#import "MJRefreshConfig.h" + +static NSBundle *mj_defaultI18nBundle = nil; +static NSBundle *mj_systemI18nBundle = nil; + +@implementation NSBundle (MJRefresh) ++ (instancetype)mj_refreshBundle +{ + static NSBundle *refreshBundle = nil; + if (refreshBundle == nil) { +#ifdef SWIFT_PACKAGE + NSBundle *containnerBundle = SWIFTPM_MODULE_BUNDLE; +#else + NSBundle *containnerBundle = [NSBundle bundleForClass:[MJRefreshComponent class]]; +#endif + refreshBundle = [NSBundle bundleWithPath:[containnerBundle pathForResource:@"MJRefresh" ofType:@"bundle"]]; + } + return refreshBundle; +} + ++ (UIImage *)mj_arrowImage +{ + static UIImage *arrowImage = nil; + if (arrowImage == nil) { + arrowImage = [[UIImage imageWithContentsOfFile:[[self mj_refreshBundle] pathForResource:@"arrow@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + return arrowImage; +} + ++ (UIImage *)mj_trailArrowImage { + static UIImage *arrowImage = nil; + if (arrowImage == nil) { + arrowImage = [[UIImage imageWithContentsOfFile:[[self mj_refreshBundle] pathForResource:@"trail_arrow@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + return arrowImage; +} + ++ (NSString *)mj_localizedStringForKey:(NSString *)key +{ + return [self mj_localizedStringForKey:key value:nil]; +} + ++ (NSString *)mj_localizedStringForKey:(NSString *)key value:(NSString *)value +{ + NSString *table = MJRefreshConfig.defaultConfig.i18nFilename; + + // 如果没有缓存, 则走初始化逻辑 + if (mj_defaultI18nBundle == nil) { + NSString *language = MJRefreshConfig.defaultConfig.languageCode; + // 如果配置中没有配置语言 + if (!language) { + language = [NSLocale preferredLanguages].firstObject; + } + NSBundle *bundle = MJRefreshConfig.defaultConfig.i18nBundle; + // 首先优先使用公共配置中的 i18nBundle, 如果为空则使用 mainBundle + bundle = bundle ? bundle : NSBundle.mainBundle; + // 按语言选取语言包 + NSString *i18nFolderPath = [bundle pathForResource:language ofType:@"lproj"]; + mj_defaultI18nBundle = [NSBundle bundleWithPath:i18nFolderPath]; + // 检查语言包, 如果没有查找到, 则默认使用 mainBundle + mj_defaultI18nBundle = mj_defaultI18nBundle ? mj_defaultI18nBundle : NSBundle.mainBundle; + + // 获取 MJRefresh 自有的语言包 + if (mj_systemI18nBundle == nil) { + mj_systemI18nBundle = [self mj_defaultI18nBundleWithLanguage:language]; + } + } + // 首先在 MJRefresh 内置语言文件中寻找 + value = [mj_systemI18nBundle localizedStringForKey:key value:value table:nil]; + // 然后在 MainBundle 对应语言文件中寻找 + value = [mj_defaultI18nBundle localizedStringForKey:key value:value table:table]; + return value; +} + ++ (NSBundle *)mj_defaultI18nBundleWithLanguage:(NSString *)language { + if ([language hasPrefix:@"en"]) { + language = @"en"; + } else if ([language hasPrefix:@"zh"]) { + if ([language rangeOfString:@"Hans"].location != NSNotFound) { + language = @"zh-Hans"; // 简体中文 + } else { // zh-Hant\zh-HK\zh-TW + language = @"zh-Hant"; // 繁體中文 + } + } else if ([language hasPrefix:@"ko"]) { + language = @"ko"; + } else if ([language hasPrefix:@"ru"]) { + language = @"ru"; + } else if ([language hasPrefix:@"uk"]) { + language = @"uk"; + } else { + language = @"en"; + } + + // 从MJRefresh.bundle中查找资源 + return [NSBundle bundleWithPath:[[NSBundle mj_refreshBundle] pathForResource:language ofType:@"lproj"]]; +} +@end + +@implementation MJRefreshConfig (Bundle) + ++ (void)resetLanguageResourceCache { + mj_defaultI18nBundle = nil; + mj_systemI18nBundle = nil; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.h new file mode 100644 index 0000000..df0423d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.h @@ -0,0 +1,20 @@ +// +// UICollectionViewLayout+MJRefresh.h +// +// 该类是用来解决 Footer 在底端加载完成后, 仍停留在原处的 bug. +// 此问题出现在 iOS 14 及以下系统上. +// Reference: https://github.com/CoderMJLee/MJRefresh/issues/1552 +// +// Created by jiasong on 2021/11/15. +// Copyright © 2021 小码哥. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UICollectionViewLayout (MJRefresh) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.m new file mode 100644 index 0000000..00d030e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UICollectionViewLayout+MJRefresh.m @@ -0,0 +1,45 @@ +// +// UICollectionViewLayout+MJRefresh.m +// +// 该类是用来解决 Footer 在底端加载完成后, 仍停留在原处的 bug. +// 此问题出现在 iOS 14 及以下系统上. +// Reference: https://github.com/CoderMJLee/MJRefresh/issues/1552 +// +// Created by jiasong on 2021/11/15. +// Copyright © 2021 小码哥. All rights reserved. +// + +#import "UICollectionViewLayout+MJRefresh.h" +#import "MJRefreshConst.h" +#import "MJRefreshFooter.h" +#import "UIScrollView+MJRefresh.h" + +@implementation UICollectionViewLayout (MJRefresh) + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + MJRefreshExchangeImplementations(self.class, @selector(finalizeCollectionViewUpdates), + self.class, @selector(mj_finalizeCollectionViewUpdates)); + }); +} + +- (void)mj_finalizeCollectionViewUpdates { + [self mj_finalizeCollectionViewUpdates]; + + __kindof MJRefreshFooter *footer = self.collectionView.mj_footer; + CGSize newSize = self.collectionViewContentSize; + CGSize oldSize = self.collectionView.contentSize; + if (footer != nil && !CGSizeEqualToSize(newSize, oldSize)) { + NSDictionary *changed = @{ + NSKeyValueChangeNewKey: [NSValue valueWithCGSize:newSize], + NSKeyValueChangeOldKey: [NSValue valueWithCGSize:oldSize], + }; + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [footer scrollViewContentSizeDidChange:changed]; + [CATransaction commit]; + } +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.h new file mode 100644 index 0000000..1b46d59 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.h @@ -0,0 +1,28 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIScrollView+Extension.h +// MJRefresh +// +// Created by MJ Lee on 14-5-28. +// Copyright (c) 2014年 小码哥. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIScrollView (MJExtension) +@property (readonly, nonatomic) UIEdgeInsets mj_inset; + +@property (assign, nonatomic) CGFloat mj_insetT; +@property (assign, nonatomic) CGFloat mj_insetB; +@property (assign, nonatomic) CGFloat mj_insetL; +@property (assign, nonatomic) CGFloat mj_insetR; + +@property (assign, nonatomic) CGFloat mj_offsetX; +@property (assign, nonatomic) CGFloat mj_offsetY; + +@property (assign, nonatomic) CGFloat mj_contentW; +@property (assign, nonatomic) CGFloat mj_contentH; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.m new file mode 100644 index 0000000..1c43721 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJExtension.m @@ -0,0 +1,153 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIScrollView+Extension.m +// MJRefresh +// +// Created by MJ Lee on 14-5-28. +// Copyright (c) 2014年 小码哥. All rights reserved. +// + +#import "UIScrollView+MJExtension.h" +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability-new" + +@implementation UIScrollView (MJExtension) + +static BOOL respondsToAdjustedContentInset_; + ++ (void)load +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + respondsToAdjustedContentInset_ = [self instancesRespondToSelector:@selector(adjustedContentInset)]; + }); +} + +- (UIEdgeInsets)mj_inset +{ +#ifdef __IPHONE_11_0 + if (respondsToAdjustedContentInset_) { + return self.adjustedContentInset; + } +#endif + return self.contentInset; +} + +- (void)setMj_insetT:(CGFloat)mj_insetT +{ + UIEdgeInsets inset = self.contentInset; + inset.top = mj_insetT; +#ifdef __IPHONE_11_0 + if (respondsToAdjustedContentInset_) { + inset.top -= (self.adjustedContentInset.top - self.contentInset.top); + } +#endif + self.contentInset = inset; +} + +- (CGFloat)mj_insetT +{ + return self.mj_inset.top; +} + +- (void)setMj_insetB:(CGFloat)mj_insetB +{ + UIEdgeInsets inset = self.contentInset; + inset.bottom = mj_insetB; +#ifdef __IPHONE_11_0 + if (respondsToAdjustedContentInset_) { + inset.bottom -= (self.adjustedContentInset.bottom - self.contentInset.bottom); + } +#endif + self.contentInset = inset; +} + +- (CGFloat)mj_insetB +{ + return self.mj_inset.bottom; +} + +- (void)setMj_insetL:(CGFloat)mj_insetL +{ + UIEdgeInsets inset = self.contentInset; + inset.left = mj_insetL; +#ifdef __IPHONE_11_0 + if (respondsToAdjustedContentInset_) { + inset.left -= (self.adjustedContentInset.left - self.contentInset.left); + } +#endif + self.contentInset = inset; +} + +- (CGFloat)mj_insetL +{ + return self.mj_inset.left; +} + +- (void)setMj_insetR:(CGFloat)mj_insetR +{ + UIEdgeInsets inset = self.contentInset; + inset.right = mj_insetR; +#ifdef __IPHONE_11_0 + if (respondsToAdjustedContentInset_) { + inset.right -= (self.adjustedContentInset.right - self.contentInset.right); + } +#endif + self.contentInset = inset; +} + +- (CGFloat)mj_insetR +{ + return self.mj_inset.right; +} + +- (void)setMj_offsetX:(CGFloat)mj_offsetX +{ + CGPoint offset = self.contentOffset; + offset.x = mj_offsetX; + self.contentOffset = offset; +} + +- (CGFloat)mj_offsetX +{ + return self.contentOffset.x; +} + +- (void)setMj_offsetY:(CGFloat)mj_offsetY +{ + CGPoint offset = self.contentOffset; + offset.y = mj_offsetY; + self.contentOffset = offset; +} + +- (CGFloat)mj_offsetY +{ + return self.contentOffset.y; +} + +- (void)setMj_contentW:(CGFloat)mj_contentW +{ + CGSize size = self.contentSize; + size.width = mj_contentW; + self.contentSize = size; +} + +- (CGFloat)mj_contentW +{ + return self.contentSize.width; +} + +- (void)setMj_contentH:(CGFloat)mj_contentH +{ + CGSize size = self.contentSize; + size.height = mj_contentH; + self.contentSize = size; +} + +- (CGFloat)mj_contentH +{ + return self.contentSize.height; +} +@end +#pragma clang diagnostic pop diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.h new file mode 100644 index 0000000..8ce3282 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.h @@ -0,0 +1,36 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIScrollView+MJRefresh.h +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// 给ScrollView增加下拉刷新、上拉刷新、 左滑刷新的功能 + +#import +#if __has_include() +#import +#else +#import "MJRefreshConst.h" +#endif + +@class MJRefreshHeader, MJRefreshFooter, MJRefreshTrailer; + +NS_ASSUME_NONNULL_BEGIN + +@interface UIScrollView (MJRefresh) +/** 下拉刷新控件 */ +@property (strong, nonatomic, nullable) MJRefreshHeader *mj_header; +@property (strong, nonatomic, nullable) MJRefreshHeader *header MJRefreshDeprecated("使用mj_header"); +/** 上拉刷新控件 */ +@property (strong, nonatomic, nullable) MJRefreshFooter *mj_footer; +@property (strong, nonatomic, nullable) MJRefreshFooter *footer MJRefreshDeprecated("使用mj_footer"); + +/** 左滑刷新控件 */ +@property (strong, nonatomic, nullable) MJRefreshTrailer *mj_trailer; + +#pragma mark - other +- (NSInteger)mj_totalDataCount; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.m new file mode 100644 index 0000000..3bb85da --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIScrollView+MJRefresh.m @@ -0,0 +1,120 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIScrollView+MJRefresh.m +// MJRefresh +// +// Created by MJ Lee on 15/3/4. +// Copyright (c) 2015年 小码哥. All rights reserved. +// + +#import "UIScrollView+MJRefresh.h" +#import "MJRefreshHeader.h" +#import "MJRefreshFooter.h" +#import "MJRefreshTrailer.h" +#import + +@implementation UIScrollView (MJRefresh) + +#pragma mark - header +static const char MJRefreshHeaderKey = '\0'; +- (void)setMj_header:(MJRefreshHeader *)mj_header +{ + if (mj_header != self.mj_header) { + // 删除旧的,添加新的 + [self.mj_header removeFromSuperview]; + + if (mj_header) { + [self insertSubview:mj_header atIndex:0]; + } + // 存储新的 + objc_setAssociatedObject(self, &MJRefreshHeaderKey, + mj_header, OBJC_ASSOCIATION_RETAIN); + } +} + +- (MJRefreshHeader *)mj_header +{ + return objc_getAssociatedObject(self, &MJRefreshHeaderKey); +} + +#pragma mark - footer +static const char MJRefreshFooterKey = '\0'; +- (void)setMj_footer:(MJRefreshFooter *)mj_footer +{ + if (mj_footer != self.mj_footer) { + // 删除旧的,添加新的 + [self.mj_footer removeFromSuperview]; + if (mj_footer) { + [self insertSubview:mj_footer atIndex:0]; + } + // 存储新的 + objc_setAssociatedObject(self, &MJRefreshFooterKey, + mj_footer, OBJC_ASSOCIATION_RETAIN); + } +} + +- (MJRefreshFooter *)mj_footer +{ + return objc_getAssociatedObject(self, &MJRefreshFooterKey); +} + +#pragma mark - footer +static const char MJRefreshTrailerKey = '\0'; +- (void)setMj_trailer:(MJRefreshTrailer *)mj_trailer { + if (mj_trailer != self.mj_trailer) { + // 删除旧的,添加新的 + [self.mj_trailer removeFromSuperview]; + if (mj_trailer) { + [self insertSubview:mj_trailer atIndex:0]; + } + // 存储新的 + objc_setAssociatedObject(self, &MJRefreshTrailerKey, + mj_trailer, OBJC_ASSOCIATION_RETAIN); + } +} + +- (MJRefreshTrailer *)mj_trailer { + return objc_getAssociatedObject(self, &MJRefreshTrailerKey); +} + +#pragma mark - 过期 +- (void)setFooter:(MJRefreshFooter *)footer +{ + self.mj_footer = footer; +} + +- (MJRefreshFooter *)footer +{ + return self.mj_footer; +} + +- (void)setHeader:(MJRefreshHeader *)header +{ + self.mj_header = header; +} + +- (MJRefreshHeader *)header +{ + return self.mj_header; +} + +#pragma mark - other +- (NSInteger)mj_totalDataCount +{ + NSInteger totalCount = 0; + if ([self isKindOfClass:[UITableView class]]) { + UITableView *tableView = (UITableView *)self; + + for (NSInteger section = 0; section < tableView.numberOfSections; section++) { + totalCount += [tableView numberOfRowsInSection:section]; + } + } else if ([self isKindOfClass:[UICollectionView class]]) { + UICollectionView *collectionView = (UICollectionView *)self; + + for (NSInteger section = 0; section < collectionView.numberOfSections; section++) { + totalCount += [collectionView numberOfItemsInSection:section]; + } + } + return totalCount; +} + +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.h new file mode 100644 index 0000000..0ac0968 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.h @@ -0,0 +1,22 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIView+Extension.h +// MJRefresh +// +// Created by MJ Lee on 14-5-28. +// Copyright (c) 2014年 小码哥. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (MJExtension) +@property (assign, nonatomic) CGFloat mj_x; +@property (assign, nonatomic) CGFloat mj_y; +@property (assign, nonatomic) CGFloat mj_w; +@property (assign, nonatomic) CGFloat mj_h; +@property (assign, nonatomic) CGSize mj_size; +@property (assign, nonatomic) CGPoint mj_origin; +@end + +NS_ASSUME_NONNULL_END diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.m new file mode 100644 index 0000000..f4dcf44 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/MJRefresh/UIView+MJExtension.m @@ -0,0 +1,83 @@ +// 代码地址: https://github.com/CoderMJLee/MJRefresh +// UIView+Extension.m +// MJRefresh +// +// Created by MJ Lee on 14-5-28. +// Copyright (c) 2014年 小码哥. All rights reserved. +// + +#import "UIView+MJExtension.h" + +@implementation UIView (MJExtension) +- (void)setMj_x:(CGFloat)mj_x +{ + CGRect frame = self.frame; + frame.origin.x = mj_x; + self.frame = frame; +} + +- (CGFloat)mj_x +{ + return self.frame.origin.x; +} + +- (void)setMj_y:(CGFloat)mj_y +{ + CGRect frame = self.frame; + frame.origin.y = mj_y; + self.frame = frame; +} + +- (CGFloat)mj_y +{ + return self.frame.origin.y; +} + +- (void)setMj_w:(CGFloat)mj_w +{ + CGRect frame = self.frame; + frame.size.width = mj_w; + self.frame = frame; +} + +- (CGFloat)mj_w +{ + return self.frame.size.width; +} + +- (void)setMj_h:(CGFloat)mj_h +{ + CGRect frame = self.frame; + frame.size.height = mj_h; + self.frame = frame; +} + +- (CGFloat)mj_h +{ + return self.frame.size.height; +} + +- (void)setMj_size:(CGSize)mj_size +{ + CGRect frame = self.frame; + frame.size = mj_size; + self.frame = frame; +} + +- (CGSize)mj_size +{ + return self.frame.size; +} + +- (void)setMj_origin:(CGPoint)mj_origin +{ + CGRect frame = self.frame; + frame.origin = mj_origin; + self.frame = frame; +} + +- (CGPoint)mj_origin +{ + return self.frame.origin; +} +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/README.md b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/README.md new file mode 100644 index 0000000..0746fbe --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/MJRefresh/README.md @@ -0,0 +1,457 @@ +## MJRefresh +[![SPM supported](https://img.shields.io/badge/SPM-supported-4BC51D.svg?style=flat)](https://github.com/apple/swift-package-manager) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![podversion](https://img.shields.io/cocoapods/v/MJRefresh.svg)](https://cocoapods.org/pods/MJRefresh) + +* An easy way to use pull-to-refresh + +[📜✍🏻**Release Notes**: more details](https://github.com/CoderMJLee/MJRefresh/releases) + +## Contents + +- New Features + - [Dynamic i18n Switching](#dynamic_i18n_switching) + - [SPM Supported](#spm_supported) + - [Swift Chaining Grammar Supported](#swift_chaining_grammar_supported) + +* Getting Started + * [Features【Support what kinds of controls to refresh】](#Support_what_kinds_of_controls_to_refresh) + * [Installation【How to use MJRefresh】](#How_to_use_MJRefresh) + * [Who's using【More than hundreds of Apps are using MJRefresh】](#More_than_hundreds_of_Apps_are_using_MJRefresh) + * [Classes【The Class Structure Chart of MJRefresh】](#The_Class_Structure_Chart_of_MJRefresh) +* Comment API + * [MJRefreshComponent.h](#MJRefreshComponent.h) + * [MJRefreshHeader.h](#MJRefreshHeader.h) + * [MJRefreshFooter.h](#MJRefreshFooter.h) + * [MJRefreshAutoFooter.h](#MJRefreshAutoFooter.h) + * [MJRefreshTrailer.h](#MJRefreshTrailer.h) +* Examples + * [Reference](#Reference) + * [The drop-down refresh 01-Default](#The_drop-down_refresh_01-Default) + * [The drop-down refresh 02-Animation image](#The_drop-down_refresh_02-Animation_image) + * [The drop-down refresh 03-Hide the time](#The_drop-down_refresh_03-Hide_the_time) + * [The drop-down refresh 04-Hide status and time](#The_drop-down_refresh_04-Hide_status_and_time) + * [The drop-down refresh 05-DIY title](#The_drop-down_refresh_05-DIY_title) + * [The drop-down refresh 06-DIY the control of refresh](#The_drop-down_refresh_06-DIY_the_control_of_refresh) + * [The pull to refresh 01-Default](#The_pull_to_refresh_01-Default) + * [The pull to refresh 02-Animation image](#The_pull_to_refresh_02-Animation_image) + * [The pull to refresh 03-Hide the title of refresh status](#The_pull_to_refresh_03-Hide_the_title_of_refresh_status) + * [The pull to refresh 04-All loaded](#The_pull_to_refresh_04-All_loaded) + * [The pull to refresh 05-DIY title](#The_pull_to_refresh_05-DIY_title) + * [The pull to refresh 06-Hidden After loaded](#The_pull_to_refresh_06-Hidden_After_loaded) + * [The pull to refresh 07-Automatic back of the pull01](#The_pull_to_refresh_07-Automatic_back_of_the_pull01) + * [The pull to refresh 08-Automatic back of the pull02](#The_pull_to_refresh_08-Automatic_back_of_the_pull02) + * [The pull to refresh 09-DIY the control of refresh(Automatic refresh)](#The_pull_to_refresh_09-DIY_the_control_of_refresh(Automatic_refresh)) + * [The pull to refresh 10-DIY the control of refresh(Automatic back)](#The_pull_to_refresh_10-DIY_the_control_of_refresh(Automatic_back)) + * [UICollectionView01-The pull and drop-down refresh](#UICollectionView01-The_pull_and_drop-down_refresh) + * [UICollectionView02-The trailer refresh](#UICollectionView02-The_trailer_refresh) + * [WKWebView01-The drop-down refresh](#WKWebView01-The_drop-down_refresh) +* [Hope](#Hope) + +## New Features +### Dynamic i18n Switching + +Now `MJRefresh components` will be rerendered automatically with `MJRefreshConfig.default.language` setting. + +#### Example + +Go `i18n` folder and see lots of cases. Simulator example is behind `i18n tab` in right-top corner. + +#### Setting language + +```swift +MJRefreshConfig.default.language = "zh-hans" +``` + +#### Setting i18n file name + +```swift +MJRefreshConfig.default.i18nFilename = "i18n File Name(not include type<.strings>)" +``` + +#### Setting i18n language bundle + +```swift +MJRefreshConfig.default.i18nBundle = +``` + +#### Adopting the feature in your DIY component + +1. Just override `i18nDidChange` function and reset texts. + +```swift +// must use this localization methods +Bundle.mj_localizedString(forKey: "") +// or +Bundle.mj_localizedString(forKey: "", value:"") + +override func i18nDidChange() { + // Reset texts function + setupTexts() + // Make sure to call super after resetting texts. It will call placeSubViews for applying new layout. + super.i18nDidChange() +} +``` + +2. Receiving `MJRefreshDidChangeLanguageNotification` notification. + +### SPM Supported + +Released from [`3.7.1`](https://github.com/CoderMJLee/MJRefresh/releases/tag/3.7.1) + +### Swift Chaining Grammar Supported + +```swift + // Example as MJRefreshNormalHeader + func addRefreshHeader() { + MJRefreshNormalHeader { [weak self] in + // load some data + }.autoChangeTransparency(true) + .link(to: tableView) + } +``` + +## Support what kinds of controls to refresh + +* `UIScrollView`、`UITableView`、`UICollectionView`、`WKWebView` + +## How to use MJRefresh +* Installation with CocoaPods:`pod 'MJRefresh'` +* Installation with [Carthage](https://github.com/Carthage/Carthage):`github "CoderMJLee/MJRefresh"` +* Manual import: + * Drag All files in the `MJRefresh` folder to project + * Import the main file:`#import "MJRefresh.h"` + +```objc +Base Custom +MJRefresh.bundle MJRefresh.h +MJRefreshConst.h MJRefreshConst.m +UIScrollView+MJExtension.h UIScrollView+MJExtension.m +UIScrollView+MJRefresh.h UIScrollView+MJRefresh.m +UIView+MJExtension.h UIView+MJExtension.m +``` + +## More than hundreds of Apps are using MJRefresh + +* More information of App can focus on:[M了个J-博客园](http://www.cnblogs.com/mjios/p/4409853.html) + +## The Class Structure Chart of MJRefresh +![](http://images0.cnblogs.com/blog2015/497279/201506/132232456139177.png) +- `The class of red text` in the chart:You can use them directly + - The drop-down refresh control types + - Normal:`MJRefreshNormalHeader` + - Gif:`MJRefreshGifHeader` + - The pull to refresh control types + - Auto refresh + - Normal:`MJRefreshAutoNormalFooter` + - Gif:`MJRefreshAutoGifFooter` + - Auto Back + - Normal:`MJRefreshBackNormalFooter` + - Gif:`MJRefreshBackGifFooter` + +- `The class of non-red text` in the chart:For inheritance,to use DIY the control of refresh + +- About how to DIY the control of refresh,You can refer the Class in below Chart
+ + + +## MJRefreshComponent.h +```objc +/** The Base Class of refresh control */ +@interface MJRefreshComponent : UIView +#pragma mark - Control the state of Refresh + +/** BeginRefreshing */ +- (void)beginRefreshing; +/** EndRefreshing */ +- (void)endRefreshing; +/** IsRefreshing */ +- (BOOL)isRefreshing; + +#pragma mark - Other +/** According to the drag ratio to change alpha automatically */ +@property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha; +@end +``` + +## MJRefreshHeader.h +```objc +@interface MJRefreshHeader : MJRefreshComponent +/** Creat header */ ++ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; +/** Creat header */ ++ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** This key is used to storage the time that the last time of drown-down successfully */ +@property (copy, nonatomic) NSString *lastUpdatedTimeKey; +/** The last time of drown-down successfully */ +@property (strong, nonatomic, readonly) NSDate *lastUpdatedTime; + +/** Ignored scrollView contentInset top */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop; +@end +``` + +## MJRefreshFooter.h +```objc +@interface MJRefreshFooter : MJRefreshComponent +/** Creat footer */ ++ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock; +/** Creat footer */ ++ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** NoticeNoMoreData */ +- (void)noticeNoMoreData; +/** ResetNoMoreData(Clear the status of NoMoreData ) */ +- (void)resetNoMoreData; + +/** Ignored scrollView contentInset bottom */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom; +@end +``` + +## MJRefreshAutoFooter.h +```objc +@interface MJRefreshAutoFooter : MJRefreshFooter +/** Is Automatically Refresh(Default is Yes) */ +@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh; + +/** When there is much at the bottom of the control is automatically refresh(Default is 1.0,Is at the bottom of the control appears in full, will refresh automatically) */ +@property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent; +@end +``` + +## MJRefreshTrailer.h +```objc +@interface MJRefreshTrailer : MJRefreshComponent + +/** 创建trailer */ ++ (instancetype)trailerWithRefreshingBlock:(MJRefreshComponentAction)refreshingBlock; +/** 创建trailer */ ++ (instancetype)trailerWithRefreshingTarget:(id)target refreshingAction:(SEL)action; + +/** 忽略多少scrollView的contentInset的right */ +@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetRight; + +@end +``` + +## Reference +```objc +* Due to there are more functions of this framework,Don't write specific text describe its usage +* You can directly reference examples MJTableViewController、MJCollectionViewController、MJWebViewController,More intuitive and fast. +``` + + +## The drop-down refresh 01-Default + +```objc +self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; +或 +// Set the callback(Once you enter the refresh status,then call the action of target,that is call [self loadNewData]) +self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; + +// Enter the refresh status immediately +[self.tableView.mj_header beginRefreshing]; +``` +![(下拉刷新01-普通)](http://images0.cnblogs.com/blog2015/497279/201506/141204343486151.gif) + +## The drop-down refresh 02-Animation image +```objc +// Set the callback(一Once you enter the refresh status,then call the action of target,that is call [self loadNewData]) +MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; +// Set the ordinary state of animated images +[header setImages:idleImages forState:MJRefreshStateIdle]; +// Set the pulling state of animated images(Enter the status of refreshing as soon as loosen) +[header setImages:pullingImages forState:MJRefreshStatePulling]; +// Set the refreshing state of animated images +[header setImages:refreshingImages forState:MJRefreshStateRefreshing]; +// Set header +self.tableView.mj_header = header; +``` +![(下拉刷新02-动画图片)](http://images0.cnblogs.com/blog2015/497279/201506/141204402238389.gif) + +## The drop-down refresh 03-Hide the time +```objc +// Hide the time +header.lastUpdatedTimeLabel.hidden = YES; +``` +![(下拉刷新03-隐藏时间)](http://images0.cnblogs.com/blog2015/497279/201506/141204456132944.gif) + +## The drop-down refresh 04-Hide status and time +```objc +// Hide the time +header.lastUpdatedTimeLabel.hidden = YES; + +// Hide the status +header.stateLabel.hidden = YES; +``` +![(下拉刷新04-隐藏状态和时间0)](http://images0.cnblogs.com/blog2015/497279/201506/141204508639539.gif) + +## The drop-down refresh 05-DIY title +```objc +// Set title +[header setTitle:@"Pull down to refresh" forState:MJRefreshStateIdle]; +[header setTitle:@"Release to refresh" forState:MJRefreshStatePulling]; +[header setTitle:@"Loading ..." forState:MJRefreshStateRefreshing]; + +// Set font +header.stateLabel.font = [UIFont systemFontOfSize:15]; +header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14]; + +// Set textColor +header.stateLabel.textColor = [UIColor redColor]; +header.lastUpdatedTimeLabel.textColor = [UIColor blueColor]; +``` +![(下拉刷新05-自定义文字)](http://images0.cnblogs.com/blog2015/497279/201506/141204563633593.gif) + +## The drop-down refresh 06-DIY the control of refresh +```objc +self.tableView.mj_header = [MJDIYHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; +// Implementation reference to MJDIYHeader.h和MJDIYHeader.m +``` +![(下拉刷新06-自定义刷新控件)](http://images0.cnblogs.com/blog2015/497279/201506/141205019261159.gif) + +## The pull to refresh 01-Default +```objc +self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; +或 +// Set the callback(Once you enter the refresh status,then call the action of target,that is call [self loadMoreData]) +self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; +``` +![(上拉刷新01-默认)](http://images0.cnblogs.com/blog2015/497279/201506/141205090047696.gif) + +## The pull to refresh 02-Animation image +```objc +// Set the callback(Once you enter the refresh status,then call the action of target,that is call [self loadMoreData]) +MJRefreshAutoGifFooter *footer = [MJRefreshAutoGifFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; + +// Set the refresh image +[footer setImages:refreshingImages forState:MJRefreshStateRefreshing]; + +// Set footer +self.tableView.mj_footer = footer; +``` +![(上拉刷新02-动画图片)](http://images0.cnblogs.com/blog2015/497279/201506/141205141445793.gif) + +## The pull to refresh 03-Hide the title of refresh status +```objc +// Hide the title of refresh status +footer.refreshingTitleHidden = YES; +// If does have not above method,then use footer.stateLabel.hidden = YES; +``` +![(上拉刷新03-隐藏刷新状态的文字)](http://images0.cnblogs.com/blog2015/497279/201506/141205200985774.gif) + +## The pull to refresh 04-All loaded +```objc +//Become the status of NoMoreData +[footer noticeNoMoreData]; +``` +![(上拉刷新04-全部加载完毕)](http://images0.cnblogs.com/blog2015/497279/201506/141205248634686.gif) + +## The pull to refresh 05-DIY title +```objc +// Set title +[footer setTitle:@"Click or drag up to refresh" forState:MJRefreshStateIdle]; +[footer setTitle:@"Loading more ..." forState:MJRefreshStateRefreshing]; +[footer setTitle:@"No more data" forState:MJRefreshStateNoMoreData]; + +// Set font +footer.stateLabel.font = [UIFont systemFontOfSize:17]; + +// Set textColor +footer.stateLabel.textColor = [UIColor blueColor]; +``` +![(上拉刷新05-自定义文字)](http://images0.cnblogs.com/blog2015/497279/201506/141205295511153.gif) + +## The pull to refresh 06-Hidden After loaded +```objc +//Hidden current control of the pull to refresh +self.tableView.mj_footer.hidden = YES; +``` +![(上拉刷新06-加载后隐藏)](http://images0.cnblogs.com/blog2015/497279/201506/141205343481821.gif) + +## The pull to refresh 07-Automatic back of the pull01 +```objc +self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; +``` +![(上拉刷新07-自动回弹的上拉01)](http://images0.cnblogs.com/blog2015/497279/201506/141205392239231.gif) + +## The pull to refresh 08-Automatic back of the pull02 +```objc +MJRefreshBackGifFooter *footer = [MJRefreshBackGifFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; + +// Set the normal state of the animated image +[footer setImages:idleImages forState:MJRefreshStateIdle]; +// Set the pulling state of animated images(Enter the status of refreshing as soon as loosen) +[footer setImages:pullingImages forState:MJRefreshStatePulling]; +// Set the refreshing state of animated images +[footer setImages:refreshingImages forState:MJRefreshStateRefreshing]; + +// Set footer +self.tableView.mj_footer = footer; +``` +![(上拉刷新07-自动回弹的上拉02)](http://images0.cnblogs.com/blog2015/497279/201506/141205441443628.gif) + +## The pull to refresh 09-DIY the control of refresh(Automatic refresh) +```objc +self.tableView.mj_footer = [MJDIYAutoFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; +// Implementation reference to MJDIYAutoFooter.h和MJDIYAutoFooter.m +``` +![(上拉刷新09-自定义刷新控件(自动刷新))](http://images0.cnblogs.com/blog2015/497279/201506/141205500195866.gif) + +## The pull to refresh 10-DIY the control of refresh(Automatic back) +```objc +self.tableView.mj_footer = [MJDIYBackFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; +// Implementation reference to MJDIYBackFooter.h和MJDIYBackFooter.m +``` +![(上拉刷新10-自定义刷新控件(自动回弹))](http://images0.cnblogs.com/blog2015/497279/201506/141205560666819.gif) + +## UICollectionView01-The pull and drop-down refresh +```objc +// The drop-down refresh +self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; + +// The pull to refresh +self.collectionView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; +``` +![(UICollectionView01-上下拉刷新)](http://images0.cnblogs.com/blog2015/497279/201506/141206021603758.gif) + +## UICollectionView02-The trailer refresh +```objc +// The trailer refresh +self.collectionView.mj_trailer = [MJRefreshNormalTrailer trailerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; + +``` +![(UICollectionView02-左拉刷新)](Gif/trailer_refresh.gif) + +## WKWebView01-The drop-down refresh +```objc +//Add the control of The drop-down refresh +self.webView.scrollView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + //Call this Block When enter the refresh status automatically +}]; +``` +![(UICollectionView01-上下拉刷新)](http://images0.cnblogs.com/blog2015/497279/201506/141206080514524.gif) + +## Remind +* ARC +* iOS>=9.0 +* iPhone \ iPad screen anyway + +## 寻求志同道合的小伙伴 + +- 因本人工作忙,没有太多时间去维护MJRefresh,在此向广大框架使用者说声:非常抱歉!😞 +- 现寻求志同道合的小伙伴一起维护此框架,有兴趣的小伙伴可以[发邮件](mailto:richermj123go@vip.qq.com)给我,非常感谢😊 +- 如果一切OK,我将开放框架维护权限(github、pod等) +- 目前已经找到3位小伙伴(^-^)V diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Manifest.lock b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Manifest.lock new file mode 100644 index 0000000..5a4e65e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Manifest.lock @@ -0,0 +1,36 @@ +PODS: + - MBProgressHUD (1.2.0) + - MJRefresh (3.7.5) + - ObjcExceptionBridging (1.0.1): + - ObjcExceptionBridging/ObjcExceptionBridging (= 1.0.1) + - ObjcExceptionBridging/ObjcExceptionBridging (1.0.1) + - SnapKit (5.0.1) + - XCGLogger (7.0.1): + - XCGLogger/Core (= 7.0.1) + - XCGLogger/Core (7.0.1): + - ObjcExceptionBridging + +DEPENDENCIES: + - MBProgressHUD + - MJRefresh + - SnapKit + - XCGLogger + +SPEC REPOS: + trunk: + - MBProgressHUD + - MJRefresh + - ObjcExceptionBridging + - SnapKit + - XCGLogger + +SPEC CHECKSUMS: + MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 + MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961 + ObjcExceptionBridging: c30e00eb3700467e695faeea30e26e18bd445001 + SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb + XCGLogger: 1943831ef907df55108b0b18657953f868de973b + +PODFILE CHECKSUM: 76caff9f808ce208c01dda28cd7af894c0ed1ca9 + +COCOAPODS: 1.11.2 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/LICENSE.txt b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/LICENSE.txt new file mode 100644 index 0000000..58aaa4d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/README.md b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/README.md new file mode 100644 index 0000000..aeddc91 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/README.md @@ -0,0 +1,583 @@ +![XCGLogger][xcglogger-logo] + +[![badge-language]][swift.org] +[![badge-platforms]][swift.org] +[![badge-license]][license] + +[![badge-travis]][travis] +[![badge-swiftpm]][swiftpm] +[![badge-cocoapods]][cocoapods-xcglogger] +[![badge-carthage]][carthage] + +[![badge-sponsors]][cerebral-gardens] +[![badge-twitter]][twitter-davewoodx] + +## tl;dr +XCGLogger is the original debug log module for use in Swift projects. + +Swift does not include a C preprocessor so developers are unable to use the debug log `#define` macros they would use in Objective-C. This means our traditional way of generating nice debug logs no longer works. Resorting to just plain old `print` calls means you lose a lot of helpful information, or requires you to type a lot more code. + +XCGLogger allows you to log details to the console (and optionally a file, or other custom destinations), just like you would have with `NSLog()` or `print()`, but with additional information, such as the date, function name, filename and line number. + +Go from this: + +```Simple message``` + +to this: + +```2014-06-09 06:44:43.600 [Debug] [AppDelegate.swift:40] application(_:didFinishLaunchingWithOptions:): Simple message``` + +#### Example +Example + +### Communication _(Hat Tip AlamoFire)_ + +* If you need help, use [Stack Overflow][stackoverflow] (Tag '[xcglogger][stackoverflow]'). +* If you'd like to ask a general question, use [Stack Overflow][stackoverflow]. +* If you've found a bug, open an issue. +* If you have a feature request, open an issue. +* If you want to contribute, submit a pull request. +* If you use XCGLogger, please Star the project on [GitHub][github-xcglogger] + +## Installation + +### Git Submodule + +Execute: + +```git submodule add https://github.com/DaveWoodCom/XCGLogger.git``` + +in your repository folder. + +### [Carthage][carthage] + +Add the following line to your `Cartfile`. + +```github "DaveWoodCom/XCGLogger" ~> 5.0.1``` + +Then run `carthage update --no-use-binaries` or just `carthage update`. For details of the installation and usage of Carthage, visit [it's project page][carthage]. + +### [CocoaPods][cocoapods] + +Add something similar to the following lines to your `Podfile`. You may need to adjust based on your platform, version/branch etc. + +``` +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' +use_frameworks! + +pod 'XCGLogger', '~> 5.0.1' +``` + +Specifying the pod `XCGLogger` on its own will include the core framework. We're starting to add subspecs to allow you to include optional components as well: + +`pod 'XCGLogger/UserInfoHelpers', '~> 5.0.1'`: Include some experimental code to help deal with using UserInfo dictionaries to tag log messages. + +Then run `pod install`. For details of the installation and usage of CocoaPods, visit [it's official web site][cocoapods]. + +### [Swift Package Manager][swiftpm] + +Add the following entry to your package's dependencies: + +``` +.Package(url: "https://github.com/DaveWoodCom/XCGLogger.git", majorVersion: 5) +``` + +### Backwards Compatibility + +Use: +* XCGLogger version [5.0.1][xcglogger-5.0.1] for Swift 3.0-3.1 +* XCGLogger version [3.6.0][xcglogger-3.6.0] for Swift 2.3 +* XCGLogger version [3.5.3][xcglogger-3.5.3] for Swift 2.2 +* XCGLogger version [3.2][xcglogger-3.2] for Swift 2.0-2.1 +* XCGLogger version [2.x][xcglogger-2.x] for Swift 1.2 +* XCGLogger version [1.x][xcglogger-1.x] for Swift 1.1 and below. + +## Basic Usage (Quick Start) + +_This quick start method is intended just to get you up and running with the logger. You should however use the [advanced usage below](#advanced-usage-recommended) to get the most out of this library._ + +Add the XCGLogger project as a subproject to your project, and add the appropriate library as a dependancy of your target(s). +Under the `General` tab of your target, add `XCGLogger.framework` and `ObjcExceptionBridging.framework` to the `Embedded Binaries` section. + +Then, in each source file: + +```Swift +import XCGLogger +``` + +In your AppDelegate (or other global file), declare a global constant to the default XCGLogger instance. + +```Swift +let log = XCGLogger.default +``` + +In the +```Swift +application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) // iOS, tvOS +``` + +or + +```Swift +applicationDidFinishLaunching(_ notification: Notification) // macOS +``` + +function, configure the options you need: + +```Swift +log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: "path/to/file", fileLevel: .debug) +``` + +The value for `writeToFile:` can be a `String` or `URL`. If the file already exists, it will be cleared before we use it. Omit the parameter or set it to `nil` to log to the console only. You can optionally set a different log level for the file output using the `fileLevel:` parameter. Set it to `nil` or omit it to use the same log level as the console. + +Then, whenever you'd like to log something, use one of the convenience methods: + +```Swift +log.verbose("A verbose message, usually useful when working on a specific problem") +log.debug("A debug message") +log.info("An info message, probably useful to power users looking in console.app") +log.warning("A warning message, may indicate a possible error") +log.error("An error occurred, but it's recoverable, just info about what happened") +log.severe("A severe error occurred, we are likely about to crash now") +``` + +The different methods set the log level of the message. XCGLogger will only print messages with a log level that is greater to or equal to it's current log level setting. So a logger with a level of `.error` will only output log messages with a level of `.error`, or `.severe`. + +## Advanced Usage (Recommended) + +XCGLogger aims to be simple to use and get you up and running quickly with as few as 2 lines of code above. But it allows for much greater control and flexibility. + +A logger can be configured to deliver log messages to a variety of destinations. Using the basic setup above, the logger will output log messages to the standard Xcode debug console, and optionally a file if a path is provided. It's quite likely you'll want to send logs to more interesting places, such as the Apple System Console, a database, third party server, or another application such as [NSLogger][NSLogger]. This is accomplished by adding the destination to the logger. + +Here's an example of configuring the logger to output to the Apple System Log as well as a file. + +```Swift +// Create a logger object with no destinations +let log = XCGLogger(identifier: "advancedLogger", includeDefaultDestinations: false) + +// Create a destination for the system console log (via NSLog) +let systemDestination = AppleSystemLogDestination(identifier: "advancedLogger.systemDestination") + +// Optionally set some configuration options +systemDestination.outputLevel = .Debug +systemDestination.showLogIdentifier = false +systemDestination.showFunctionName = true +systemDestination.showThreadName = true +systemDestination.showLevel = true +systemDestination.showFileName = true +systemDestination.showLineNumber = true +systemDestination.showDate = true + +// Add the destination to the logger +log.add(destination: systemDestination) + +// Create a file log destination +let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination") + +// Optionally set some configuration options +fileDestination.outputLevel = .Debug +fileDestination.showLogIdentifier = false +fileDestination.showFunctionName = true +fileDestination.showThreadName = true +fileDestination.showLevel = true +fileDestination.showFileName = true +fileDestination.showLineNumber = true +fileDestination.showDate = true + +// Process this destination in the background +fileDestination.logQueue = XCGLogger.logQueue + +// Add the destination to the logger +log.add(destination: fileDestination) + +// Add basic app info, version info etc, to the start of the logs +log.logAppDetails() +``` + +You can configure each log destination with different options depending on your needs. + +Another common usage pattern is to have multiple loggers, perhaps one for UI issues, one for networking, and another for data issues. + +Each log destination can have its own log level. As a convenience, you can set the log level on the log object itself and it will pass that level to each destination. Then set the destinations that need to be different. + +**Note**: A destination object can only be added to one logger object, adding it to a second will remove it from the first. + +### Initialization Using A Closure + +Alternatively you can use a closure to initialize your global variable, so that all initialization is done in one place +```Swift +let log: XCGLogger = { + let log = XCGLogger(identifier: "advancedLogger", includeDefaultDestinations: false) + + // Customize as needed + + return log +}() +``` + +**Note**: This creates the log object lazily, which means it's not created until it's actually needed. This delays the initial output of the app information details. Because of this, I recommend forcing the log object to be created at app launch by adding the line `let _ = log` at the top of your `didFinishLaunching` method if you don't already log something on app launch. + +### Log Anything + +You can log strings: + +```Swift +log.debug("Hi there!") +``` + +or pretty much anything you want: + +```Swift +log.debug(true) +log.debug(CGPoint(x: 1.1, y: 2.2)) +log.debug(MyEnum.Option) +log.debug((4, 2)) +log.debug(["Device": "iPhone", "Version": 7]) +``` + +### Filtering Log Messages + +New to XCGLogger 4, you can now create filters to apply to your logger (or to specific destinations). Create and configure your filters (examples below), and then add them to the logger or destination objects by setting the optional `filters` property to an array containing the filters. Filters are applied in the order they exist in the array. During processing, each filter is asked if the log message should be excluded from the log. If any filter excludes the log message, it's excluded. Filters have no way to reverse the exclusion of another filter. + +If a destination's `filters` property is `nil`, the log's `filters` property is used instead. To have one destination log everything, while having all other destinations filter something, add the filters to the log object and set the one destination's `filters` property to an empty array `[]`. + +**Note**: Unlike destinations, you can add the same filter object to multiple loggers and/or multiple destinations. + +#### Filter by Filename + +To exclude all log messages from a specific file, create an exclusion filter like so: + +```Swift +log.filters = [FileNameFilter(excludeFrom: ["AppDelegate.swift"], excludePathWhenMatching: true)] +``` + +`excludeFrom:` takes an `Array` or `Set` so you can specify multiple files at the same time. + +`excludePathWhenMatching:` defaults to `true` so you can omit it unless you want to match path's as well. + +To include log messages only for a specific set to files, create the filter using the `includeFrom:` initializer. It's also possible to just toggle the `inverse` property to flip the exclusion filter to an inclusion filter. + +#### Filter by Tag + +In order to filter log messages by tag, you must of course be able to set a tag on the log messages. Each log message can now have additional, user defined data attached to them, to be used by filters (and/or formatters etc). This is handled with a `userInfo: Dictionary` object. The dictionary key should be a namespaced string to avoid collisions with future additions. Official keys will begin with `com.cerebralgardens.xcglogger`. The tag key can be accessed by `XCGLogger.Constants.userInfoKeyTags`. You definitely don't want to be typing that, so feel free to create a global shortcut: `let tags = XCGLogger.Constants.userInfoKeyTags`. Now you can easily tag your logs: + +```Swift +let sensitiveTag = "Sensitive" +log.debug("A tagged log message", userInfo: [tags: sensitiveTag]) +``` + +The value for tags can be an `Array`, `Set`, or just a `String`, depending on your needs. They'll all work the same way when filtered. + +Depending on your workflow and usage, you'll probably create faster methods to set up the `userInfo` dictionary. See [below](#mixing-and-matching) for other possible shortcuts. + +Now that you have your logs tagged, you can filter easily: + +```Swift +log.filters = [TagFilter(excludeFrom: [sensitiveTag])] +``` + +Just like the `FileNameFilter`, you can use `includeFrom:` or toggle `inverse` to include only log messages that have the specified tags. + +#### Filter by Developer + +Filtering by developer is exactly like filtering by tag, only using the `userInfo` key of `XCGLogger.Constants.userInfoKeyDevs`. In fact, both filters are subclasses of the `UserInfoFilter` class that you can use to create additional filters. See [Extending XCGLogger](#extending-xcglogger) below. + +#### Mixing and Matching + +In large projects with multiple developers, you'll probably want to start tagging log messages, as well as indicate the developer that added the message. + +While extremely flexible, the `userInfo` dictionary can be a little cumbersome to use. There are a few possible methods you can use to simply things. I'm still testing these out myself so they're not officially part of the library yet (I'd love feedback or other suggestions). + +I have created some experimental code to help create the UserInfo dictionaries. (Include the optional `UserInfoHelpers` subspec if using CocoaPods). Check the iOS Demo app to see it in use. + +There are two structs that conform to the `UserInfoTaggingProtocol` protocol. `Tag` and `Dev`. + +You can create an extension on each of these that suit your project. For example: + +```Swift +extension Tag { + static let sensitive = Tag("sensitive") + static let ui = Tag("ui") + static let data = Tag("data") +} + +extension Dev { + static let dave = Dev("dave") + static let sabby = Dev("sabby") +} +``` + +Along with these types, there's an overloaded operator `|` that can be used to merge them together into a dictionary compatible with the `UserInfo:` parameter of the logging calls. + +Then you can log messages like this: + +```Swift +log.debug("A tagged log message", userInfo: Dev.dave | Tag.sensitive) +``` + +There are some current issues I see with these `UserInfoHelpers`, which is why I've made it optional/experimental for now. I'd love to hear comments/suggestions for improvements. + +1. The overloaded operator `|` merges dictionaries so long as there are no `Set`s. If one of the dictionaries contains a `Set`, it'll use one of them, without merging them. Preferring the left hand side if both sides have a set for the same key. +2. Since the `userInfo:` parameter needs a dictionary, you can't pass in a single Dev or Tag object. You need to use at least two with the `|` operator to have it automatically convert to a compatible dictionary. If you only want one Tag for example, you must access the `.dictionary` parameter manually: `userInfo: Tag("Blah").dictionary`. + +### Selectively Executing Code + +All log methods operate on closures. Using the same syntactic sugar as Swift's `assert()` function, this approach ensures we don't waste resources building log messages that won't be output anyway, while at the same time preserving a clean call site. + +For example, the following log statement won't waste resources if the debug log level is suppressed: + +```Swift +log.debug("The description of \(thisObject) is really expensive to create") +``` + +Similarly, let's say you have to iterate through a loop in order to do some calculation before logging the result. In Objective-C, you could put that code block between `#if` `#endif`, and prevent the code from running. But in Swift, previously you would need to still process that loop, wasting resources. With `XCGLogger` it's as simple as: + +```Swift +log.debug { + var total = 0.0 + for receipt in receipts { + total += receipt.total + } + + return "Total of all receipts: \(total)" +} +``` + +In cases where you wish to selectively execute code without generating a log line, return `nil`, or use one of the methods: `verboseExec`, `debugExec`, `infoExec`, `warningExec`, `errorExec`, and `severeExec`. + +### Custom Date Formats + +You can create your own `DateFormatter` object and assign it to the logger. + +```Swift +let dateFormatter = DateFormatter() +dateFormatter.dateFormat = "MM/dd/yyyy hh:mma" +dateFormatter.locale = Locale.current +log.dateFormatter = dateFormatter +``` + +### Enhancing Log Messages With Colour + +XCGLogger supports adding formatting codes to your log messages to enable colour in various places. The original option was to use the [XcodeColors plug-in][XcodeColors]. However, Xcode 8 no longer officially supports plug-ins. You can still view your logs in colour, just not in Xcode 8 at the moment ([see note below](#restore-plug-in-support)). You can still use Xcode 7 if desired (after adding the Swift 3 toolchain), or you can use the new ANSI colour support to add colour to your fileDestination objects and view your logs via a terminal window. This gives you some extra options such as adding Bold, Italics, or (please don't) Blinking! + +Once enabled, each log level can have its own colour. These colours can be customized as desired. If using multiple loggers, you could alternatively set each logger to its own colour. + +An example of setting up the ANSI formatter: + +```Swift +if let fileDestination: FileDestination = log.destination(withIdentifier: XCGLogger.Constants.fileDestinationIdentifier) as? FileDestination { + let ansiColorLogFormatter: ANSIColorLogFormatter = ANSIColorLogFormatter() + ansiColorLogFormatter.colorize(level: .verbose, with: .colorIndex(number: 244), options: [.faint]) + ansiColorLogFormatter.colorize(level: .debug, with: .black) + ansiColorLogFormatter.colorize(level: .info, with: .blue, options: [.underline]) + ansiColorLogFormatter.colorize(level: .warning, with: .red, options: [.faint]) + ansiColorLogFormatter.colorize(level: .error, with: .red, options: [.bold]) + ansiColorLogFormatter.colorize(level: .severe, with: .white, on: .red) + fileDestination.formatters = [ansiColorLogFormatter] +} +``` + +As with filters, you can use the same formatter objects for multiple loggers and/or multiple destinations. If a destination's `formatters` property is `nil`, the logger's `formatters` property will be used instead. + +See [Extending XCGLogger](#extending-xcglogger) below for info on creating your own custom formatters. + +### Alternate Configurations + +By using Swift build flags, different log levels can be used in debugging versus staging/production. +Go to Build Settings -> Swift Compiler - Custom Flags -> Other Swift Flags and add `-DDEBUG` to the Debug entry. + +```Swift +#if DEBUG + log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#else + log.setup(level: .severe, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#endif +``` + +You can set any number of options up in a similar fashion. See the updated iOSDemo app for an example of using different log destinations based on options, search for `USE_NSLOG`. + +### Background Log Processing + +By default, the supplied log destinations will process the logs on the thread they're called on. This is to ensure the log message is displayed immediately when debugging an application. You can add a breakpoint immediately after a log call and see the results when the breakpoint hits. + +However, if you're not actively debugging the application, processing the logs on the current thread can introduce a performance hit. You can now specify a destination process it's logs on a dispatch queue of your choice (or even use a default supplied one). + +```Swift +fileDestination.logQueue = XCGLogger.logQueue +``` + +or even + +```Swift +fileDestination.logQueue = DispatchQueue.global(qos: .background) +``` + +This works extremely well when combined with the [Alternate Configurations](#alternate-configurations) method above. + +```Swift +#if DEBUG + log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#else + log.setup(level: .severe, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) + if let consoleLog = log.logDestination(XCGLogger.Constants.baseConsoleDestinationIdentifier) as? ConsoleDestination { + consoleLog.logQueue = XCGLogger.logQueue + } +#endif +``` + +### Append To Existing Log File + +When using the advanced configuration of the logger (see [Advanced Usage above](#advanced-usage-recommended)), you can now specify that the logger append to an existing log file, instead of automatically overwriting it. + +Add the optional `shouldAppend:` parameter when initializing the `FileDestination` object. You can also add the `appendMarker:` parameter to add a marker to the log file indicating where a new instance of your app started appending. By default we'll add `-- ** ** ** --` if the parameter is omitted. Set it to `nil` to skip appending the marker. + +```let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination", shouldAppend: true, appendMarker: "-- Relauched App --")``` + + +### Automatic Log File Rotation + +When logging to a file, you have the option to automatically rotate the log file to an archived destination, and have the logger automatically create a new log file in place of the old one. + +Create a destination using the `AutoRotatingFileDestination` class and set the following properties: + +`targetMaxFileSize`: Auto rotate once the file is larger than this + +`targetMaxTimeInterval`: Auto rotate after this many seconds + +`targetMaxLogFiles`: Number of archived log files to keep, older ones are automatically deleted + +Those are all guidelines for the logger, not hard limits. + +### Extending XCGLogger + +You can create alternate log destinations (besides the built in ones). Your custom log destination must implement the `DestinationProtocol` protocol. Instantiate your object, configure it, and then add it to the `XCGLogger` object with `add(destination:)`. There are two base destination classes (`BaseDestination` and `BaseQueuedDestination`) you can inherit from to handle most of the process for you, requiring you to only implement one additional method in your custom class. Take a look at `ConsoleDestination` and `FileDestination` for examples. + +You can also create custom filters or formatters. Take a look at the provided versions as a starting point. Note that filters and formatters have the ability to alter the log messages as they're processed. This means you can create a filter that strips passwords, highlights specific words, encrypts messages, etc. + +## Contributing + +XCGLogger is the best logger available for Swift because of the contributions from the community like you. There are many ways you can help continue to make it great. + +1. Star the project on [GitHub][github-xcglogger]. +2. Report issues/bugs you find. +3. Suggest features. +4. Submit pull requests. + +**Note**: when submitting a pull request, please use lots of small commits verses one huge commit. It makes it much easier to merge in when there are several pull requests that need to be combined for a new version. + +## Third Party Tools That Work With XCGLogger + +**Note**: These plug-ins no longer 'officially' work in Xcode 8. File a [bug report](http://openradar.appspot.com/27447585) if you'd like to see plug-ins return to Xcode. See [below](#xcode_8_tips) for a workaround... + +[**XcodeColors:**][XcodeColors] Enable colour in the Xcode console +
+[**KZLinkedConsole:**][KZLinkedConsole] Link from a log line directly to the code that produced it + +**Note**: These may not yet work with the Swift 3 version of XCGLogger. + +[**XCGLoggerNSLoggerConnector:**][XCGLoggerNSLoggerConnector] Send your logs to [NSLogger][NSLogger] + +## Xcode 8 Tips + +### Restore Plug-In Support + +One of the biggest issues you'll notice when using Xcode 8, is that by default it will no longer load plug-ins. Personally, I really like the benefits the plug-ins add to Xcode, especially XcodeColors. With so many other frameworks, or even Xcode itself spewing messages into the debug console, it's really helpful to be able to have your logs stand out with colour. It is currently possible to re-enable plug-ins in Xcode 8. If you do so, you'll be able to use the new `XcodeColorsLogFormatter` class to colour your log messages again. See the demo apps for example code. + +**Be Warned**: If you follow these instructions to re-enable plug-ins, there could be unforeseen consequences. I would definitely only do this on a development machine, with the assumption that you have another machine (or at least an unmodified version of Xcode) to do your App Store/Distribution builds. **Do not** attempt to upload a binary to Apple that was built with a modified version of Xcode. **I take no responsibility for anything that happens if you follow these instructions. You have been warned**. + +Now, assuming you've read the above warning, and you have a development only machine, and you really want to use your awesome plug-ins, here's my recommended method to re-enable plug-ins. + +1. Clone the [unsign](https://github.com/steakknife/unsign) repository. +2. Build it following their dead-simple instructions (`make`). +3. Close Xcode if it's open. +4. In your favourite shell/terminal, execute the following commands (may need to be root, or just `sudo`): + + + `cd /Applications/Xcode.app/Contents/MacOS` *Substitute another Xcode path if you like* + + `/path/to/unsign Xcode` *Creates a new `Xcode.unsigned` binary* + + `mv Xcode Xcode.signed` *Move the original file* + + `ln -sf Xcode.unsigned Xcode` *Link the unsigned version to the original filename* + +5. Launch Xcode and use your favourite plug-ins. You may have to reauthorize access to your keychain, but it should be a one time task. +6. You can flip back and forth between the signed and unsigned versions by repeating the `ln -sf Xcode.unsigned Xcode` command, just changing `.unsigned` to `.signed` etc. +7. Do not use this version of Xcode to submit apps! +8. Pray Apple doesn't disable this workaround. +9. File a radar requesting official plug-in support again. You can dup this [radar](http://openradar.appspot.com/27447585). + +Thanks to [@inket](https://github.com/inket/update_xcode_plugins) and [@steakknife](https://github.com/steakknife/unsign) for providing the knowledge and tools for this tip! + + + +## To Do + +- Add more examples of some advanced use cases +- Add additional log destination types +- Add Objective-C support +- Add Linux support + +## More + +If you find this library helpful, you'll definitely find these other tools helpful: + +Watchdog: http://watchdogforxcode.com/ +Slender: http://martiancraft.com/products/slender +Briefs: http://giveabrief.com/ + +Also, please check out some of my other projects: + +Rudoku: [App Store](https://itunes.apple.com/app/apple-store/id965105321?pt=17255&ct=github&mt=8&at=11lMGu) +TV Tune Up: https://www.cerebralgardens.com/tvtuneup + +### Change Log + +The change log is now in it's own file: [CHANGELOG.md](CHANGELOG.md) + +[xcglogger-logo]: https://github.com/DaveWoodCom/XCGLogger/raw/master/ReadMeImages/XCGLoggerLogo_326x150.png +[swift.org]: https://swift.org/ +[license]: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +[travis]: https://travis-ci.org/DaveWoodCom/XCGLogger +[swiftpm]: https://swift.org/package-manager/ +[cocoapods]: https://cocoapods.org/ +[cocoapods-xcglogger]: https://cocoapods.org/pods/XCGLogger +[carthage]: https://github.com/Carthage/Carthage +[cerebral-gardens]: https://www.cerebralgardens.com/ +[twitter-davewoodx]: https://twitter.com/davewoodx +[github-xcglogger]: https://github.com/DaveWoodCom/XCGLogger +[stackoverflow]: http://stackoverflow.com/questions/tagged/xcglogger + +[badge-language]: https://img.shields.io/badge/Swift-1.x%20%7C%202.x%20%7C%203.x-orange.svg?style=flat +[badge-platforms]: https://img.shields.io/badge/Platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgray.svg?style=flat +[badge-license]: https://img.shields.io/badge/License-MIT-lightgrey.svg?style=flat +[badge-travis]: https://img.shields.io/travis/DaveWoodCom/XCGLogger/master.svg?style=flat +[badge-swiftpm]: https://img.shields.io/badge/Swift_Package_Manager-v5.0.1-64a6dd.svg?style=flat +[badge-cocoapods]: https://img.shields.io/cocoapods/v/XCGLogger.svg?style=flat +[badge-carthage]: https://img.shields.io/badge/Carthage-v5.0.1-64a6dd.svg?style=flat + +[badge-sponsors]: https://img.shields.io/badge/Sponsors-Cerebral%20Gardens-orange.svg?style=flat +[badge-twitter]: https://img.shields.io/twitter/follow/DaveWoodX.svg?style=social + +[XcodeColors]: https://github.com/robbiehanson/XcodeColors +[KZLinkedConsole]: https://github.com/krzysztofzablocki/KZLinkedConsole +[NSLogger]: https://github.com/fpillet/NSLogger +[XCGLoggerNSLoggerConnector]: https://github.com/markuswinkler/XCGLoggerNSLoggerConnector +[Firelog]: http://jogabo.github.io/firelog/ +[Firebase]: https://www.firebase.com/ + +[xcglogger-5.0.1]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/5.0.1 +[xcglogger-3.6.0]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.6.0 +[xcglogger-3.5.3]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.5.3 +[xcglogger-3.2]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.2.0 +[xcglogger-2.x]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/2.4.0 +[xcglogger-1.x]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/1.8.1 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/ObjectiveCMarker.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/ObjectiveCMarker.m new file mode 100644 index 0000000..2734893 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/ObjectiveCMarker.m @@ -0,0 +1,3 @@ +// +// This file is unused and only exists so the Swift Package Manager can identify this module as one using Objective-C. +// diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/include/ObjcExceptionBridging.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/include/ObjcExceptionBridging.h new file mode 100644 index 0000000..9589704 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/ObjcExceptionBridging/Sources/ObjcExceptionBridging/include/ObjcExceptionBridging.h @@ -0,0 +1,51 @@ +// +// ObjcExceptionBridging.h +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +#import + +//! Project version number for ObjcExceptionBridging. +FOUNDATION_EXPORT double ObjcExceptionBridgingVersionNumber; + +//! Project version string for ObjcExceptionBridging. +FOUNDATION_EXPORT const unsigned char ObjcExceptionBridgingVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +/** + Execute Swift code that could generate an Objective-C exception in here to catch and handle it gracefully (ie don't crash) + + @param tryBlock Block/Closure to execute that could thrown an Objective-C exception + @param catchBlock Block/Closure to use if an exception is thrown in the tryBlock + @param finallyBlock Block/Closure to execute after the tryBlock (or catchBlock if an exception was thrown) + + @note Loosely based on the code here: https://stackoverflow.com/a/35003095/144857 and here: https://github.com/williamFalcon/SwiftTryCatch + */ +NS_INLINE void _try_objc(void(^_Nonnull tryBlock)(void), void(^_Nonnull catchBlock)(NSException* _Nonnull exception), void(^_Nonnull finallyBlock)(void)) { + @try { + tryBlock(); + } + @catch (NSException* exception) { + catchBlock(exception); + } + @finally { + finallyBlock(); + } +} + +/** + Throw an Objective-C exception + + @param exception NSException object to throw + + @note Loosely based on the code here: https://github.com/williamFalcon/SwiftTryCatch + */ +NS_INLINE void _throw_objc(NSException* _Nonnull exception) +{ + @throw exception; +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/project.pbxproj b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3fe1163 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1823 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 0097064E7F7D3F413161738CC5C25EEC /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E308F616373FF00806119782C0CC0F5 /* MBProgressHUD.m */; }; + 00CE14690879775C12718E86157670EC /* TagFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD117AEA133A33989D0636E9762558C /* TagFilter.swift */; }; + 0A4ACE3AFFFCB7846F824A803645CC5F /* MJRefreshTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA95D516BD1F821770905806DB0CF70 /* MJRefreshTrailer.m */; }; + 0A93D725DA34E6ACB26D9B2A714BBEB6 /* UIScrollView+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 30D3D48161DF4AC8C2FF9E1A816F0B40 /* UIScrollView+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0AA33EBB857A5205F87C09CCB99EAC74 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + 0E214FD3632D8023EF46E6D73A311DAF /* ObjcExceptionBridging-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A88F77DB8C0D142958C19D1939F896A /* ObjcExceptionBridging-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 144DA93A55A598F5197F10C729FBDD69 /* UILayoutSupport+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0473DF7971D9DF6A6DC6D462AF9EBC35 /* UILayoutSupport+Extensions.swift */; }; + 17BE0F4E51B0FB968125F1A520607FD8 /* ConstraintMultiplierTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9844FA722175BBEDA6E181FBE5FE40A0 /* ConstraintMultiplierTarget.swift */; }; + 1E9EEA756F2774D73347F1660EEFE3E9 /* ConstraintView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D43382FADF2042B5D9CCA9D87EDF2B /* ConstraintView+Extensions.swift */; }; + 20076D79F24AD3B3D2BD250181EA065A /* PrePostFixLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F026398EB05B37B5971B925DDBFF8DF1 /* PrePostFixLogFormatter.swift */; }; + 274DF0E2BF04F6F4F9F1E70CF513A4F2 /* ConstraintLayoutSupportDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = F039D6A62932D8E5A48E7D5ADBFAE128 /* ConstraintLayoutSupportDSL.swift */; }; + 29421B5D519A5B0801CB6E0716B5DB30 /* MJRefreshTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = 80186E74E939C7E381E481C77C71A130 /* MJRefreshTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2CCA4FDF86BC8A8984E599CE97B4BB4B /* AppleSystemLogDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3969A76D5675C33C0765C2D0666122B7 /* AppleSystemLogDestination.swift */; }; + 31005F5A8B58CA1089E5B7DA1097A424 /* MJRefreshBackFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 75BA5385628498E1B6A562CECC8AA175 /* MJRefreshBackFooter.m */; }; + 33A4F6D2199266B0F53AB5D2A91FD53C /* MJRefreshStateHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = A03EC8B82C94EE8B11ABD9FCAE5C6D4C /* MJRefreshStateHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B60C02F6E42FD06B128473E00A94224 /* ConstraintLayoutSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0307308156123105D9F15D2F9053EF39 /* ConstraintLayoutSupport.swift */; }; + 3C66AE060AE5B7B0DBF2DF4779C9AC3A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + 3CD5FAFC746A76D73C3F501734199DFF /* Typealiases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94742AE1CB8B69F4CC269EE4FAA7DFD1 /* Typealiases.swift */; }; + 3D3FA74047C3C06B2E269C3BC8DED98D /* BaseQueuedDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B717583415DA0AE28E2A43427EA4D /* BaseQueuedDestination.swift */; }; + 3D9A2FF659102C6C74B9CAF068E07813 /* URL+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A476DBE5E58FB4E95F00B11D215466AE /* URL+XCGAdditions.swift */; }; + 3DDC5EF8F09F2A192618936067DFE41F /* MJRefreshBackGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EC62499787AF5E1442586C5E772A332 /* MJRefreshBackGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3DEDFA52B3A196F6D3E1F0937617628A /* ConstraintLayoutGuide+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EB2EFBB5A69D7B0F9B254450697B193 /* ConstraintLayoutGuide+Extensions.swift */; }; + 3F57997C48B9AC2E8157E45521B6F662 /* MJRefresh-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A89602C63F3616646938A3F289A37A0A /* MJRefresh-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 43863B6D6A0E47B6648BB7B469736EDD /* LayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29400E1EDB811D7D6E9B304E022DCDC6 /* LayoutConstraint.swift */; }; + 43967A52DF5DF083B0771199EE89F88A /* MJRefreshAutoGifFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 35A2E8BC85E3768618CDBA045CC92E84 /* MJRefreshAutoGifFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4502D7E8FA8F03A1C87EE48533FEB8C0 /* MJRefresh-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AB0A645D433D4526B2E61E6D78A6A64 /* MJRefresh-dummy.m */; }; + 4642D790995C23BA033D1117B6E86510 /* Pods-WCHBLEOTA-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 19A332AFF11A391D10ACACC79EA2AB55 /* Pods-WCHBLEOTA-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 46CABB2581EDC02E6646E5FE296CEF9C /* MJRefreshBackStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = B7579EA00DB0471476E0AF2BA77B8C14 /* MJRefreshBackStateFooter.m */; }; + 484548C5D780A8DA124E24C3A27720CD /* MJRefreshStateTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0485C0DCE251B0CFD359F1FDC509EC91 /* MJRefreshStateTrailer.m */; }; + 4B1A328B82EB2CE389FDE9A5E0E2755F /* LogDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD16571C05DBAD8DB990BA6EA683F104 /* LogDetails.swift */; }; + 4CA13A0527BC57DE2C54A0F3B5ED8652 /* LayoutConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CCD7136FD635C45A31DC017DB6414E /* LayoutConstraintItem.swift */; }; + 4D31CCA291F1AAB8DB56EAC5E5100D16 /* MJRefreshAutoStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = D07CB7DE04A4071EF6A4A19836805021 /* MJRefreshAutoStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 51A4A1046676D304410544EB56732A49 /* Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C4CC786BB059717BE6C8C59E01F193 /* Constraint.swift */; }; + 5427DBACB1D189B22A74A5F95ECC6F7C /* MJRefreshBackNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D9FCAA5C5829BD5FC2E2A29A135476 /* MJRefreshBackNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 569C9596A1EE66A0867C2F27DB4434FD /* MJRefreshComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 23A47F84A7174C0312631A2ECA84D979 /* MJRefreshComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 572DBDC37429318F768FD7A21F1C0B70 /* MJRefreshBackStateFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = AB78F6D68F74D48331E2D38FB1B911EB /* MJRefreshBackStateFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 58C91B4AB36E6B16421106CA634C58EF /* MBProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 42F183B84988A24D1F7DC73D47CE8410 /* MBProgressHUD-dummy.m */; }; + 5A013AE4976A5EF0E621278FAEE1BED6 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 6A827092D813EC5DD7D8A220C5E4BDCE /* .swift-version */; }; + 5A82E2848549F14A452E1D5F921F2668 /* XcodeColorsLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4137AA0A313F5745D553B325B14931 /* XcodeColorsLogFormatter.swift */; }; + 5BAC1EF86D0E57E44E404B2796993561 /* MBProgressHUD-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 95CF50952986206AD082D14A16333BF5 /* MBProgressHUD-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D53F8210FE8D8FE739303AB0CE4BDA0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + 5E8BA529DFB4529006967624044FEC1C /* ConstraintViewDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62E87E07694724FCDF0AE95526A6344 /* ConstraintViewDSL.swift */; }; + 5F24CA2DAA215F6E0AEC5AC773198F95 /* MJRefreshConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A0E8BABB1305E41529A6A620016D7BC /* MJRefreshConfig.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 62F299B4704A7C95FB5866C6CDE2E2FD /* ConstraintOffsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51CDD644B115BDB28476FA956E471EB /* ConstraintOffsetTarget.swift */; }; + 6302E2433D0108058251F5C0979595AD /* Pods-WCHBLEOTA-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F187913C8B5C412131FC81D53E744039 /* Pods-WCHBLEOTA-dummy.m */; }; + 6372AFD5512AA9D634536E7543652957 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 31A2E24C40DB8B1F2D1BF28DFB66AF4B /* UIScrollView+MJRefresh.m */; }; + 6579F1B66AB9CADABB69B726F8F15225 /* NSBundle+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = EAB4F6DBC0C99FE9DDFBB32366F95E8C /* NSBundle+MJRefresh.m */; }; + 67E941CADB3CDDEEDF8CE4EE4A4A05BB /* MBProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = C3392BBCD96AD5D3B90938E0974E2F5F /* MBProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6866BDC5DB2452285680090A490EFD64 /* MJRefreshNormalTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = FBA8CA6946B4168A9EDEC8900E3BEEA2 /* MJRefreshNormalTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69359A20750375B3BF91D193B60C406D /* MJRefreshFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0A5D315B8CC9F18C808DF04AD3C58C /* MJRefreshFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6AD7614826D1F0E5C7BF58B08373B9B7 /* Base64LogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9DA57D98A78DC8380CBF2FB13FE453 /* Base64LogFormatter.swift */; }; + 6D7EE0E37B82EC69E80A480DA3F564C6 /* MJRefreshConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F1D27157FD0258D65764E1D010D5EB2 /* MJRefreshConfig.m */; }; + 752B36F5BBCF8DED01BF1E444D975546 /* UICollectionViewLayout+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3C18CC38C79C93240C4DC62DA3F8DF /* UICollectionViewLayout+MJRefresh.m */; }; + 7580FAAB1BDA52F5A969E5571D1A5973 /* ConstraintAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9A0EAEE037B4BA6052A5394CECE25E /* ConstraintAttributes.swift */; }; + 7764AA5F6BBFC6ECE43959923DD007D3 /* ConstraintDirectionalInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8C7DFE72EAF1502227BD7DB988B629 /* ConstraintDirectionalInsetTarget.swift */; }; + 7D24D21B28B00E91354E3A5A8A7EAD66 /* UIView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = B8E3654E10BC59749B4730997392D39D /* UIView+MJExtension.m */; }; + 825062025906CE93C5D124E1FD9A811E /* ConstraintMakerExtendable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ACB81A4631A3F95508A783E2D4D0DAF /* ConstraintMakerExtendable.swift */; }; + 8367A150606C504F9DED8DE524A6437B /* ObjectiveCMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = C16BFBB6246BFFA1D2112A94EB980087 /* ObjectiveCMarker.m */; }; + 8449EB1DFD43E222D687D5A8D2088D2D /* ConstraintLayoutGuideDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAE74D3A6DE92AA6F23207BA67E12935 /* ConstraintLayoutGuideDSL.swift */; }; + 8462FBECC31A3DEB90BA896639DF7C71 /* ConsoleDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = C48F9099CC5F261997F9601825C2A9A0 /* ConsoleDestination.swift */; }; + 8496B2BE600628C923C9C89473DD0CF3 /* XCGLogger-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A221F5C1C65D0A419950E4D5754422BC /* XCGLogger-dummy.m */; }; + 85BC413BB35DE20594B6D84572FB49FC /* MJRefreshNormalTrailer.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1EAF82C6879A150F30FBB3AFFC9B9A /* MJRefreshNormalTrailer.m */; }; + 87ECEF7F4D9C689B39FC644CFD25D8AD /* FilterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BFD819E995227B58C8F7A8A9A60D4F /* FilterProtocol.swift */; }; + 8C6546C1EF4F153DF3795CC6FE189E5B /* ConstraintInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08BF8FD395F1E75D4D2A8762126FAEE0 /* ConstraintInsets.swift */; }; + 8FD9CD608C4EAAFDE6AC7B8B9EF0FF5E /* ConstraintDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4992F78D4C18E4C9233949DB4083C1 /* ConstraintDescription.swift */; }; + 90FD5AE525E138A473723FD79AF73273 /* ConstraintDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2DFCFD3BE5D4500C118E2C93D8D5C0 /* ConstraintDSL.swift */; }; + 925214372EC186625DC2566F1D7649DA /* DestinationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 900DB585A502532FF6F02E988BAF46C3 /* DestinationProtocol.swift */; }; + 927DF15A74376F9FD582A3D17A293EC5 /* MJRefreshAutoFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 20886CE777EE4252D58593CCF5AA07CC /* MJRefreshAutoFooter.m */; }; + 968B4874A9F12D67C8B901136C9C8157 /* SnapKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE2405D5E01A5F75D1677679D55F806 /* SnapKit-dummy.m */; }; + 9807BF49C74281A14440DACC71E07C4A /* MJRefreshBackFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A9C5856EC0CEFCF75F24C7F691B72C6 /* MJRefreshBackFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 98EAF4CA985CD43CFE416B235817CEFA /* MJRefreshGifHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBBF194605AE5B1790C7918DD0D6484 /* MJRefreshGifHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C41EF0E685AD816D8C26D83B93AB6AF /* MJRefreshStateHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8249D8CA7D75A6779BF4584E840CC7B9 /* MJRefreshStateHeader.m */; }; + 9E0112B58B68FBB94E23113BCAE41FBC /* DispatchQueue+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6831550F1319E304D9A14F35AA102E /* DispatchQueue+XCGAdditions.swift */; }; + 9FFAC41FD637E5C6FA1FFFE33FA138A6 /* XCGLogger-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A7ECEE2839C1D2330A0A877622782D2A /* XCGLogger-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A0F754C88A64972A40A9008B0AD52109 /* ConstraintDirectionalInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3587683B7C228761F92C6F7B217C7099 /* ConstraintDirectionalInsets.swift */; }; + A32FEE92F0765B9415E6DD0721992B2C /* BaseDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E002304191A6E4C83BAFF97F4BB428F /* BaseDestination.swift */; }; + A4467357581E8345DD348683CC4111AF /* SnapKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7959A414BB18756DEA5C2E54302248E3 /* SnapKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A4D4B0B7C69670D030B4398F31584025 /* DevFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59CEFCD8384F01F5B133F9CCC5FBD1CC /* DevFilter.swift */; }; + A53D3AF15CE8D348306EF11619C5D166 /* ConstraintMakerEditable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD771C56A60D3F00739BB38A6A6B2FE1 /* ConstraintMakerEditable.swift */; }; + AB5958BA59F34460139B065451B7D71D /* MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 3398E4CC29CE84D0775298FE6F888E16 /* MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AE0FF5B3C55AFD12E15909F98595C848 /* UIView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = DF5C2228DE7BF94931BE70CA75103D1F /* UIView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AF4B3C88EF24097513282E7551F33385 /* MJRefreshNormalHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D9BC929CD3989AEB52AEA7BFA7107CF4 /* MJRefreshNormalHeader.m */; }; + AFAC1D4EBD53A048346210536741DF13 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CABB98090B02C131F86931CB9BE54B7A /* CoreGraphics.framework */; }; + AFFCC49584308828ACCDBC67418D1354 /* ObjcExceptionBridging.h in Headers */ = {isa = PBXBuildFile; fileRef = F5790145554C30672C60EA47E9C421BC /* ObjcExceptionBridging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B52177FF72FDAC3EDB7195DE98F5501E /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51AB40693B18F443F75126966ED13E47 /* QuartzCore.framework */; }; + B5402265E04D513FAD8EA1EB234A969F /* MJRefreshGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D5632FCE11080E682411F7EBDCF540E8 /* MJRefreshGifHeader.m */; }; + B543FD108C1C6AF6129CB4991553218B /* ConstraintConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287B9C5B5E94734E31B6D97C18015B8E /* ConstraintConfig.swift */; }; + B5B122B965516FA9349250A502C3A58D /* MJRefreshStateTrailer.h in Headers */ = {isa = PBXBuildFile; fileRef = C71CCD3C78628887833EF0F7AC7E4E05 /* MJRefreshStateTrailer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BAA4C06A1DE43F74573C2E49EC85D9B5 /* MJRefreshComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = F7400427CCD55ED39B10B24A4B440733 /* MJRefreshComponent.m */; }; + BC08210D922B8C20A382E850A6AB91FD /* UserInfoFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E504D97286B0028DF4218C8E3A7852E /* UserInfoFilter.swift */; }; + BC29069E8C5679A176E284888F597C32 /* MJRefreshBackNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F577BA256F926E30B7B2CE50CF2E5F8 /* MJRefreshBackNormalFooter.m */; }; + BD333CDBCF5D2FD55920336FC271DF33 /* ConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F118F2C96966DD535ABBE603315797 /* ConstraintItem.swift */; }; + BDFF68F76ED8639B0031A55390727068 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = DC32CDF719DDEF5517E315A7B273BC3F /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE6C672F9D4B3CE0D0D83079B8A740F2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + BEBF920FEB959B46A76BAADF22E5CD15 /* ConstraintInsetTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B48C74096F2152386C09CDEF1DFC81 /* ConstraintInsetTarget.swift */; }; + BF1A148832BC2A213384F7F3700CF8B5 /* UICollectionViewLayout+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B6AA7D76B5A86C6F48A3A39A5F06B8 /* UICollectionViewLayout+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C28E73E7C990B5831ABCDDA6F8275FD0 /* MJRefresh.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3770A26C10C48DAD2D45AB2B66B161C1 /* MJRefresh.bundle */; }; + C3A160E82826D84E59889F7AC3157F42 /* MJRefreshAutoGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = CB24CC23B44D370AD73814FD64D67802 /* MJRefreshAutoGifFooter.m */; }; + C61D3BC32A28A405C934C00039AD2583 /* ConstraintConstantTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F8BC070373B0D6EC87396AFDA09B0D /* ConstraintConstantTarget.swift */; }; + CA05F14AC92A10A39A7E866FA72C4582 /* ANSIColorLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76478C08F80019F7E4B3E287A1BE0EDB /* ANSIColorLogFormatter.swift */; }; + CB194156C900B767B0160AF72EDF354D /* ConstraintMaker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B3A572589BCBAEFE63CED23274AA3FB /* ConstraintMaker.swift */; }; + CB8E4BF0D710970BE2CB4C87ED1043E4 /* ConstraintMakerRelatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C02730B57F73388C744310E3E851610F /* ConstraintMakerRelatable.swift */; }; + CCA22C9F421C9E8C13009947816D8C82 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + D0038F642442AAE53C12ECA3240B5A6D /* MJRefreshAutoNormalFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B83A6DA44E20F31A94C03E6560BB23F /* MJRefreshAutoNormalFooter.m */; }; + D0665D6E3CD34DD382F7E85551753C0A /* MJRefreshBackGifFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 440EDEF7F36D826A1C29A684F0763DFE /* MJRefreshBackGifFooter.m */; }; + D13D417B236E736EEAE7217B5CE3EC5C /* ConstraintMakerFinalizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C731B6B6663CD7F3E3AED52FFD7F87BC /* ConstraintMakerFinalizable.swift */; }; + D24ACD6E03DC5394C6909011D3518756 /* LogFormatterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4919B7F4D4495B9C8501A69E1D58D446 /* LogFormatterProtocol.swift */; }; + D275EEDA6F16D7745DC91A0A36CB64C4 /* TestDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10EE524E8B9A0F08D6BEBD5B509DE361 /* TestDestination.swift */; }; + D43C0E831750DB310012D56EDB8F36A1 /* MJRefreshConst.h in Headers */ = {isa = PBXBuildFile; fileRef = D04701C582132FF795EF0CD633B34C20 /* MJRefreshConst.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D4E03538CEF69CA99F48CFB303C8BFAA /* FileNameFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43F6DD46C278A70E9BB67459F43A9C0 /* FileNameFilter.swift */; }; + D59C2826AD288ECFF576B2AFA312716C /* ConstraintRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD271341F1A37A59A654DE2F15E83CC /* ConstraintRelation.swift */; }; + E15214E66D7A6069AA5E0B470A16F92F /* MJRefreshConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F9189144F133519EE2727A7F8D9408 /* MJRefreshConst.m */; }; + E36244E8BF4AC941E82DAF16DDF4BBC2 /* ConstraintPriorityTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED7584BF94B16247A9F7573A6725925D /* ConstraintPriorityTarget.swift */; }; + E3A90F4FB659B5DDCF5DA603DDEF9E66 /* MJRefreshAutoStateFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = F58063240B4CBC87DE8AA85F5ED41FAA /* MJRefreshAutoStateFooter.m */; }; + E579107E3F34A6761997CE937C6DFF1A /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = F104C71811402770F88CF009CD1EEED6 /* UIScrollView+MJExtension.m */; }; + E6D1E0657F2E7190956CA155F09136A4 /* MJRefreshNormalHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 917731EE8F4A15585476C661E6CE8BCB /* MJRefreshNormalHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E8EAADACF3BAE33BDECBC7214EAE9CD2 /* ConstraintRelatableTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24B7751CF994BFC1621794356F52CD1 /* ConstraintRelatableTarget.swift */; }; + E96DEA6D681BB273A4A97517D884D669 /* XCGLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = B245C43E94A7C07EE9FD0FFE3ECE3CB7 /* XCGLogger.swift */; }; + EC7A19215B0957CF1EFFF58A1D79F273 /* MJRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9031C8512782AD9559E06E12C6660D31 /* MJRefreshFooter.m */; }; + EDCB17E097C5491E3A38447CDBEFA465 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */; }; + EE6C364198A763EBBF49237035D86439 /* ConstraintLayoutGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123D41DDAB20F7DEBC06B177757A187B /* ConstraintLayoutGuide.swift */; }; + EE85A2DDCED7EE7AB3F57DE292D36C18 /* MJRefreshHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 71D2F845700AB78DAB55A75F5BEEB228 /* MJRefreshHeader.m */; }; + EEFD0F7603E62B64F5FDE4659324786F /* HelperFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 922045560C4CE88865DC104E4DA71225 /* HelperFunctions.swift */; }; + EFE14A8E7C02BDD16B252181BB381247 /* ObjcExceptionBridging-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7D7BF4032A8CEB6A3DC80DB3966E54 /* ObjcExceptionBridging-dummy.m */; }; + F0AD0E9222DC4A06FFC0B07737CE2FEA /* MJRefreshAutoFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = C16F62C14613F548A168922299BC73FE /* MJRefreshAutoFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F10586462FB54CEA169A1A7A469A926D /* Debugging.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E88D95D3ABF6883E32E81E6598B1D0 /* Debugging.swift */; }; + F24D06C23DAB2F52A30C886A7A8177C7 /* ConstraintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 500D9C2E75567DEF8214B7330EFCCD99 /* ConstraintView.swift */; }; + F2C817C166B2DE613222C41015A586C9 /* ConstraintMakerPriortizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D6371DC57B6810FA3591218D0DA966 /* ConstraintMakerPriortizable.swift */; }; + F319DD3C0DE3B8896C4E45584BFFFD01 /* AutoRotatingFileDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 236823FD2A5BF79FF8B9C6D798FEB378 /* AutoRotatingFileDestination.swift */; }; + F343BA4E457FFDB0165492AECAEF0BCC /* ConstraintPriority.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E093A4CDCDC8834EE597D76065D4CC /* ConstraintPriority.swift */; }; + F71117E3C5158BD6036AA7F8AB71FC47 /* NSBundle+MJRefresh.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AE170B6A339AB3517E21DE4B88F9126 /* NSBundle+MJRefresh.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FA482C6F33494F529CF642D22DBA3B44 /* MJRefreshHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 40953BDE3CADA62CFAB96F29F16A56F0 /* MJRefreshHeader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FC42711B8E37AD9B5C2F735EDDAD441A /* MJRefreshAutoNormalFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 75A2D8EDDC781EA9891F331EFBA73616 /* MJRefreshAutoNormalFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FC929DBC35F43F5BBE4741611AF43D2D /* FileDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B2F8AAF015031E79B8DE7C3706B498 /* FileDestination.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 26413B1DB1B7FBEBD39D96CE00E9571A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; + remoteInfo = MBProgressHUD; + }; + 4CD66CC9E7C428897EF4927C1AB63851 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 746615E9A06AABA6F288B49A10B63E10; + remoteInfo = ObjcExceptionBridging; + }; + 55169CF6334530C597A08E51B29EDFFB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 746615E9A06AABA6F288B49A10B63E10; + remoteInfo = ObjcExceptionBridging; + }; + 95CC381A3166EB4C44B22C605FA35DCB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 19622742EBA51E823D6DAE3F8CDBFAD4; + remoteInfo = SnapKit; + }; + A909B4707D3A3F267E3DCA1E045EA348 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 07AFE6B9C0D64C3222F1B3FAA995664C; + remoteInfo = XCGLogger; + }; + C3F1368A08CDAEE0A7DBFD8718CFD65E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6868056D761E163D10FDAF8CF1C4D9B8; + remoteInfo = MJRefresh; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0307308156123105D9F15D2F9053EF39 /* ConstraintLayoutSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupport.swift; path = Source/ConstraintLayoutSupport.swift; sourceTree = ""; }; + 03D6371DC57B6810FA3591218D0DA966 /* ConstraintMakerPriortizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerPriortizable.swift; path = Source/ConstraintMakerPriortizable.swift; sourceTree = ""; }; + 0473DF7971D9DF6A6DC6D462AF9EBC35 /* UILayoutSupport+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UILayoutSupport+Extensions.swift"; path = "Source/UILayoutSupport+Extensions.swift"; sourceTree = ""; }; + 0485C0DCE251B0CFD359F1FDC509EC91 /* MJRefreshStateTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.m; sourceTree = ""; }; + 06BFD819E995227B58C8F7A8A9A60D4F /* FilterProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FilterProtocol.swift; path = Sources/XCGLogger/Filters/FilterProtocol.swift; sourceTree = ""; }; + 08BF8FD395F1E75D4D2A8762126FAEE0 /* ConstraintInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsets.swift; path = Source/ConstraintInsets.swift; sourceTree = ""; }; + 0D9A0EAEE037B4BA6052A5394CECE25E /* ConstraintAttributes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintAttributes.swift; path = Source/ConstraintAttributes.swift; sourceTree = ""; }; + 0E308F616373FF00806119782C0CC0F5 /* MBProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = MBProgressHUD.m; sourceTree = ""; }; + 0F1D27157FD0258D65764E1D010D5EB2 /* MJRefreshConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConfig.m; path = MJRefresh/MJRefreshConfig.m; sourceTree = ""; }; + 10EE524E8B9A0F08D6BEBD5B509DE361 /* TestDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TestDestination.swift; path = Sources/XCGLogger/Destinations/TestDestination.swift; sourceTree = ""; }; + 11B2F8AAF015031E79B8DE7C3706B498 /* FileDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FileDestination.swift; path = Sources/XCGLogger/Destinations/FileDestination.swift; sourceTree = ""; }; + 123D41DDAB20F7DEBC06B177757A187B /* ConstraintLayoutGuide.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuide.swift; path = Source/ConstraintLayoutGuide.swift; sourceTree = ""; }; + 18B48C74096F2152386C09CDEF1DFC81 /* ConstraintInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintInsetTarget.swift; path = Source/ConstraintInsetTarget.swift; sourceTree = ""; }; + 19A332AFF11A391D10ACACC79EA2AB55 /* Pods-WCHBLEOTA-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-WCHBLEOTA-umbrella.h"; sourceTree = ""; }; + 1A50366DF331B46ADD864A90B571244F /* SnapKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.debug.xcconfig; sourceTree = ""; }; + 1A88F77DB8C0D142958C19D1939F896A /* ObjcExceptionBridging-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ObjcExceptionBridging-umbrella.h"; sourceTree = ""; }; + 1A9C5856EC0CEFCF75F24C7F691B72C6 /* MJRefreshBackFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackFooter.h; path = MJRefresh/Base/MJRefreshBackFooter.h; sourceTree = ""; }; + 1AB0A645D433D4526B2E61E6D78A6A64 /* MJRefresh-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MJRefresh-dummy.m"; sourceTree = ""; }; + 1B83A6DA44E20F31A94C03E6560BB23F /* MJRefreshAutoNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoNormalFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m; sourceTree = ""; }; + 1CAB16A12A28E8BE749202B03552307A /* ObjcExceptionBridging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ObjcExceptionBridging.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1D3C18CC38C79C93240C4DC62DA3F8DF /* UICollectionViewLayout+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionViewLayout+MJRefresh.m"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.m"; sourceTree = ""; }; + 1DAB275BA042282988CA24043264E931 /* XCGLogger.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = XCGLogger.debug.xcconfig; sourceTree = ""; }; + 201A71B3656F2DD58A5B93CD7839FF8D /* MJRefresh.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.debug.xcconfig; sourceTree = ""; }; + 20886CE777EE4252D58593CCF5AA07CC /* MJRefreshAutoFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoFooter.m; path = MJRefresh/Base/MJRefreshAutoFooter.m; sourceTree = ""; }; + 236823FD2A5BF79FF8B9C6D798FEB378 /* AutoRotatingFileDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AutoRotatingFileDestination.swift; path = Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift; sourceTree = ""; }; + 23A47F84A7174C0312631A2ECA84D979 /* MJRefreshComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshComponent.h; path = MJRefresh/Base/MJRefreshComponent.h; sourceTree = ""; }; + 287B9C5B5E94734E31B6D97C18015B8E /* ConstraintConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConfig.swift; path = Source/ConstraintConfig.swift; sourceTree = ""; }; + 29400E1EDB811D7D6E9B304E022DCDC6 /* LayoutConstraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraint.swift; path = Source/LayoutConstraint.swift; sourceTree = ""; }; + 2E504D97286B0028DF4218C8E3A7852E /* UserInfoFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserInfoFilter.swift; path = Sources/XCGLogger/Filters/UserInfoFilter.swift; sourceTree = ""; }; + 30D3D48161DF4AC8C2FF9E1A816F0B40 /* UIScrollView+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJRefresh.h"; path = "MJRefresh/UIScrollView+MJRefresh.h"; sourceTree = ""; }; + 31668972FE66425BE3AE1D558784E7A5 /* ObjcExceptionBridging-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ObjcExceptionBridging-Info.plist"; sourceTree = ""; }; + 31A2E24C40DB8B1F2D1BF28DFB66AF4B /* UIScrollView+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJRefresh.m"; path = "MJRefresh/UIScrollView+MJRefresh.m"; sourceTree = ""; }; + 3398E4CC29CE84D0775298FE6F888E16 /* MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefresh.h; path = MJRefresh/MJRefresh.h; sourceTree = ""; }; + 3587683B7C228761F92C6F7B217C7099 /* ConstraintDirectionalInsets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsets.swift; path = Source/ConstraintDirectionalInsets.swift; sourceTree = ""; }; + 35A2E8BC85E3768618CDBA045CC92E84 /* MJRefreshAutoGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoGifFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h; sourceTree = ""; }; + 35F9189144F133519EE2727A7F8D9408 /* MJRefreshConst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshConst.m; path = MJRefresh/MJRefreshConst.m; sourceTree = ""; }; + 36968FA970A046A15C4DA1F0AAD19652 /* XCGLogger.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = XCGLogger.modulemap; sourceTree = ""; }; + 3770A26C10C48DAD2D45AB2B66B161C1 /* MJRefresh.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MJRefresh.bundle; path = MJRefresh/MJRefresh.bundle; sourceTree = ""; }; + 37F8BC070373B0D6EC87396AFDA09B0D /* ConstraintConstantTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintConstantTarget.swift; path = Source/ConstraintConstantTarget.swift; sourceTree = ""; }; + 3969A76D5675C33C0765C2D0666122B7 /* AppleSystemLogDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppleSystemLogDestination.swift; path = Sources/XCGLogger/Destinations/AppleSystemLogDestination.swift; sourceTree = ""; }; + 39F2ABDF0134E0CC910CD6E3F46D400E /* MJRefresh.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MJRefresh.modulemap; sourceTree = ""; }; + 3AD4B93E917C8EC79F4EC178F8F46657 /* SnapKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapKit.release.xcconfig; sourceTree = ""; }; + 3CE2405D5E01A5F75D1677679D55F806 /* SnapKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapKit-dummy.m"; sourceTree = ""; }; + 3D256BC218B1BDB0D6783764AE2C5BC9 /* Pods-WCHBLEOTA.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WCHBLEOTA.release.xcconfig"; sourceTree = ""; }; + 40953BDE3CADA62CFAB96F29F16A56F0 /* MJRefreshHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshHeader.h; path = MJRefresh/Base/MJRefreshHeader.h; sourceTree = ""; }; + 42F183B84988A24D1F7DC73D47CE8410 /* MBProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MBProgressHUD-dummy.m"; sourceTree = ""; }; + 440EDEF7F36D826A1C29A684F0763DFE /* MJRefreshBackGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackGifFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m; sourceTree = ""; }; + 4919B7F4D4495B9C8501A69E1D58D446 /* LogFormatterProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LogFormatterProtocol.swift; path = Sources/XCGLogger/LogFormatters/LogFormatterProtocol.swift; sourceTree = ""; }; + 4ACB81A4631A3F95508A783E2D4D0DAF /* ConstraintMakerExtendable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerExtendable.swift; path = Source/ConstraintMakerExtendable.swift; sourceTree = ""; }; + 4EB6E2B145D1FAB64A596A2A95DD4BD5 /* MJRefresh-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MJRefresh-Info.plist"; sourceTree = ""; }; + 4EC62499787AF5E1442586C5E772A332 /* MJRefreshBackGifFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackGifFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h; sourceTree = ""; }; + 500D9C2E75567DEF8214B7330EFCCD99 /* ConstraintView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintView.swift; path = Source/ConstraintView.swift; sourceTree = ""; }; + 51AB40693B18F443F75126966ED13E47 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 52B6AA7D76B5A86C6F48A3A39A5F06B8 /* UICollectionViewLayout+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionViewLayout+MJRefresh.h"; path = "MJRefresh/UICollectionViewLayout+MJRefresh.h"; sourceTree = ""; }; + 52C4CC786BB059717BE6C8C59E01F193 /* Constraint.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Constraint.swift; path = Source/Constraint.swift; sourceTree = ""; }; + 5625991627A605DD96004F4EF065E987 /* SnapKit-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapKit-Info.plist"; sourceTree = ""; }; + 578D38AC14311ED8185A99EB825B0204 /* Pods-WCHBLEOTA */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-WCHBLEOTA"; path = Pods_WCHBLEOTA.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 59CEFCD8384F01F5B133F9CCC5FBD1CC /* DevFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DevFilter.swift; path = Sources/XCGLogger/Filters/DevFilter.swift; sourceTree = ""; }; + 5AE170B6A339AB3517E21DE4B88F9126 /* NSBundle+MJRefresh.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSBundle+MJRefresh.h"; path = "MJRefresh/NSBundle+MJRefresh.h"; sourceTree = ""; }; + 5DBBF194605AE5B1790C7918DD0D6484 /* MJRefreshGifHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshGifHeader.h; path = MJRefresh/Custom/Header/MJRefreshGifHeader.h; sourceTree = ""; }; + 5F577BA256F926E30B7B2CE50CF2E5F8 /* MJRefreshBackNormalFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackNormalFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m; sourceTree = ""; }; + 6064D8E08CDBB2310CF6DC733F48C72C /* Pods-WCHBLEOTA-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-WCHBLEOTA-acknowledgements.markdown"; sourceTree = ""; }; + 62FEBC53F51E160CFA155623DD092FEA /* ObjcExceptionBridging-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ObjcExceptionBridging-prefix.pch"; sourceTree = ""; }; + 6A827092D813EC5DD7D8A220C5E4BDCE /* .swift-version */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = ".swift-version"; sourceTree = ""; }; + 6B3A572589BCBAEFE63CED23274AA3FB /* ConstraintMaker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMaker.swift; path = Source/ConstraintMaker.swift; sourceTree = ""; }; + 6D4137AA0A313F5745D553B325B14931 /* XcodeColorsLogFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XcodeColorsLogFormatter.swift; path = Sources/XCGLogger/LogFormatters/XcodeColorsLogFormatter.swift; sourceTree = ""; }; + 6D6BADB5AF89C9778E115964F7E134D4 /* XCGLogger-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "XCGLogger-Info.plist"; sourceTree = ""; }; + 71D2F845700AB78DAB55A75F5BEEB228 /* MJRefreshHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshHeader.m; path = MJRefresh/Base/MJRefreshHeader.m; sourceTree = ""; }; + 75A2D8EDDC781EA9891F331EFBA73616 /* MJRefreshAutoNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoNormalFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h; sourceTree = ""; }; + 75BA5385628498E1B6A562CECC8AA175 /* MJRefreshBackFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackFooter.m; path = MJRefresh/Base/MJRefreshBackFooter.m; sourceTree = ""; }; + 75D43382FADF2042B5D9CCA9D87EDF2B /* ConstraintView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintView+Extensions.swift"; path = "Source/ConstraintView+Extensions.swift"; sourceTree = ""; }; + 76478C08F80019F7E4B3E287A1BE0EDB /* ANSIColorLogFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ANSIColorLogFormatter.swift; path = Sources/XCGLogger/LogFormatters/ANSIColorLogFormatter.swift; sourceTree = ""; }; + 7959A414BB18756DEA5C2E54302248E3 /* SnapKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-umbrella.h"; sourceTree = ""; }; + 7A0E8BABB1305E41529A6A620016D7BC /* MJRefreshConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConfig.h; path = MJRefresh/MJRefreshConfig.h; sourceTree = ""; }; + 7E002304191A6E4C83BAFF97F4BB428F /* BaseDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseDestination.swift; path = Sources/XCGLogger/Destinations/BaseDestination.swift; sourceTree = ""; }; + 80186E74E939C7E381E481C77C71A130 /* MJRefreshTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshTrailer.h; path = MJRefresh/Base/MJRefreshTrailer.h; sourceTree = ""; }; + 821919445F1740BB0FE272BA5CBC0126 /* MBProgressHUD.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.release.xcconfig; sourceTree = ""; }; + 8249D8CA7D75A6779BF4584E840CC7B9 /* MJRefreshStateHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshStateHeader.m; path = MJRefresh/Custom/Header/MJRefreshStateHeader.m; sourceTree = ""; }; + 84E093A4CDCDC8834EE597D76065D4CC /* ConstraintPriority.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriority.swift; path = Source/ConstraintPriority.swift; sourceTree = ""; }; + 860C4A82A65521A9B0E68AB9F6BC1F20 /* SnapKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapKit.modulemap; sourceTree = ""; }; + 8741A977BF903A4874E25FDB4910D218 /* XCGLogger-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCGLogger-prefix.pch"; sourceTree = ""; }; + 87C0D16CC94AABFA9D32F502251C2306 /* ObjcExceptionBridging.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = ObjcExceptionBridging.modulemap; sourceTree = ""; }; + 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MBProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D09C96E9147C1A474724F57A24FF7A3 /* MBProgressHUD-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MBProgressHUD-Info.plist"; sourceTree = ""; }; + 8EA95D516BD1F821770905806DB0CF70 /* MJRefreshTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshTrailer.m; path = MJRefresh/Base/MJRefreshTrailer.m; sourceTree = ""; }; + 8EB2EFBB5A69D7B0F9B254450697B193 /* ConstraintLayoutGuide+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ConstraintLayoutGuide+Extensions.swift"; path = "Source/ConstraintLayoutGuide+Extensions.swift"; sourceTree = ""; }; + 900DB585A502532FF6F02E988BAF46C3 /* DestinationProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DestinationProtocol.swift; path = Sources/XCGLogger/Destinations/DestinationProtocol.swift; sourceTree = ""; }; + 9031C8512782AD9559E06E12C6660D31 /* MJRefreshFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshFooter.m; path = MJRefresh/Base/MJRefreshFooter.m; sourceTree = ""; }; + 91648AD383E8321DCF006378BFFBC683 /* Pods-WCHBLEOTA.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-WCHBLEOTA.modulemap"; sourceTree = ""; }; + 917731EE8F4A15585476C661E6CE8BCB /* MJRefreshNormalHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalHeader.h; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.h; sourceTree = ""; }; + 922045560C4CE88865DC104E4DA71225 /* HelperFunctions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelperFunctions.swift; path = Sources/XCGLogger/Misc/HelperFunctions.swift; sourceTree = ""; }; + 94742AE1CB8B69F4CC269EE4FAA7DFD1 /* Typealiases.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Typealiases.swift; path = Source/Typealiases.swift; sourceTree = ""; }; + 95CF50952986206AD082D14A16333BF5 /* MBProgressHUD-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-umbrella.h"; sourceTree = ""; }; + 979486118B3E90C08386079D57962701 /* SnapKit */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SnapKit; path = SnapKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9844FA722175BBEDA6E181FBE5FE40A0 /* ConstraintMultiplierTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMultiplierTarget.swift; path = Source/ConstraintMultiplierTarget.swift; sourceTree = ""; }; + 9C8C7DFE72EAF1502227BD7DB988B629 /* ConstraintDirectionalInsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDirectionalInsetTarget.swift; path = Source/ConstraintDirectionalInsetTarget.swift; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A03EC8B82C94EE8B11ABD9FCAE5C6D4C /* MJRefreshStateHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateHeader.h; path = MJRefresh/Custom/Header/MJRefreshStateHeader.h; sourceTree = ""; }; + A06030E4DABE38F84AD4275226ED93F2 /* MJRefresh-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-prefix.pch"; sourceTree = ""; }; + A221F5C1C65D0A419950E4D5754422BC /* XCGLogger-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "XCGLogger-dummy.m"; sourceTree = ""; }; + A476DBE5E58FB4E95F00B11D215466AE /* URL+XCGAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "URL+XCGAdditions.swift"; path = "Sources/XCGLogger/Extensions/URL+XCGAdditions.swift"; sourceTree = ""; }; + A7CCD7136FD635C45A31DC017DB6414E /* LayoutConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LayoutConstraintItem.swift; path = Source/LayoutConstraintItem.swift; sourceTree = ""; }; + A7D9FCAA5C5829BD5FC2E2A29A135476 /* MJRefreshBackNormalFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackNormalFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h; sourceTree = ""; }; + A7ECEE2839C1D2330A0A877622782D2A /* XCGLogger-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCGLogger-umbrella.h"; sourceTree = ""; }; + A89602C63F3616646938A3F289A37A0A /* MJRefresh-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MJRefresh-umbrella.h"; sourceTree = ""; }; + AB78F6D68F74D48331E2D38FB1B911EB /* MJRefreshBackStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshBackStateFooter.h; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h; sourceTree = ""; }; + ABA583DE11109CDD4DE3F5450E271CF2 /* Pods-WCHBLEOTA-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-WCHBLEOTA-Info.plist"; sourceTree = ""; }; + AC8698CCBAE21AC376B843F7B3C2E026 /* MBProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-prefix.pch"; sourceTree = ""; }; + ADD271341F1A37A59A654DE2F15E83CC /* ConstraintRelation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelation.swift; path = Source/ConstraintRelation.swift; sourceTree = ""; }; + B245C43E94A7C07EE9FD0FFE3ECE3CB7 /* XCGLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XCGLogger.swift; path = Sources/XCGLogger/XCGLogger.swift; sourceTree = ""; }; + B3885705F1FC1F964A6B2B4A510DEAB3 /* SnapKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SnapKit-prefix.pch"; sourceTree = ""; }; + B62E87E07694724FCDF0AE95526A6344 /* ConstraintViewDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintViewDSL.swift; path = Source/ConstraintViewDSL.swift; sourceTree = ""; }; + B74777DE48547F4532D5AF0FDF265C38 /* ObjcExceptionBridging.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ObjcExceptionBridging.release.xcconfig; sourceTree = ""; }; + B7579EA00DB0471476E0AF2BA77B8C14 /* MJRefreshBackStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshBackStateFooter.m; path = MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m; sourceTree = ""; }; + B8E3654E10BC59749B4730997392D39D /* UIView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MJExtension.m"; path = "MJRefresh/UIView+MJExtension.m"; sourceTree = ""; }; + BAD117AEA133A33989D0636E9762558C /* TagFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TagFilter.swift; path = Sources/XCGLogger/Filters/TagFilter.swift; sourceTree = ""; }; + BC1EAF82C6879A150F30FBB3AFFC9B9A /* MJRefreshNormalTrailer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalTrailer.m; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.m; sourceTree = ""; }; + BE2DFCFD3BE5D4500C118E2C93D8D5C0 /* ConstraintDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDSL.swift; path = Source/ConstraintDSL.swift; sourceTree = ""; }; + C02730B57F73388C744310E3E851610F /* ConstraintMakerRelatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerRelatable.swift; path = Source/ConstraintMakerRelatable.swift; sourceTree = ""; }; + C16BFBB6246BFFA1D2112A94EB980087 /* ObjectiveCMarker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = ObjectiveCMarker.m; path = Sources/ObjcExceptionBridging/ObjectiveCMarker.m; sourceTree = ""; }; + C16F62C14613F548A168922299BC73FE /* MJRefreshAutoFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoFooter.h; path = MJRefresh/Base/MJRefreshAutoFooter.h; sourceTree = ""; }; + C1D73242C23DC09CE53DC41DC76BBAF5 /* Pods-WCHBLEOTA-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-WCHBLEOTA-acknowledgements.plist"; sourceTree = ""; }; + C3392BBCD96AD5D3B90938E0974E2F5F /* MBProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = ""; }; + C48F9099CC5F261997F9601825C2A9A0 /* ConsoleDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConsoleDestination.swift; path = Sources/XCGLogger/Destinations/ConsoleDestination.swift; sourceTree = ""; }; + C663C5CE412FCB36E0FE8E27E5164405 /* XCGLogger.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = XCGLogger.release.xcconfig; sourceTree = ""; }; + C71CCD3C78628887833EF0F7AC7E4E05 /* MJRefreshStateTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshStateTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshStateTrailer.h; sourceTree = ""; }; + C731B6B6663CD7F3E3AED52FFD7F87BC /* ConstraintMakerFinalizable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerFinalizable.swift; path = Source/ConstraintMakerFinalizable.swift; sourceTree = ""; }; + C8F118F2C96966DD535ABBE603315797 /* ConstraintItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintItem.swift; path = Source/ConstraintItem.swift; sourceTree = ""; }; + CABB98090B02C131F86931CB9BE54B7A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + CAE74D3A6DE92AA6F23207BA67E12935 /* ConstraintLayoutGuideDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutGuideDSL.swift; path = Source/ConstraintLayoutGuideDSL.swift; sourceTree = ""; }; + CB24CC23B44D370AD73814FD64D67802 /* MJRefreshAutoGifFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoGifFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m; sourceTree = ""; }; + CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + CC02394341D63F245D96A73C3BB7B568 /* MBProgressHUD.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MBProgressHUD.modulemap; sourceTree = ""; }; + CC0A5D315B8CC9F18C808DF04AD3C58C /* MJRefreshFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshFooter.h; path = MJRefresh/Base/MJRefreshFooter.h; sourceTree = ""; }; + D04701C582132FF795EF0CD633B34C20 /* MJRefreshConst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshConst.h; path = MJRefresh/MJRefreshConst.h; sourceTree = ""; }; + D07CB7DE04A4071EF6A4A19836805021 /* MJRefreshAutoStateFooter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshAutoStateFooter.h; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h; sourceTree = ""; }; + D24B7751CF994BFC1621794356F52CD1 /* ConstraintRelatableTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintRelatableTarget.swift; path = Source/ConstraintRelatableTarget.swift; sourceTree = ""; }; + D43F6DD46C278A70E9BB67459F43A9C0 /* FileNameFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FileNameFilter.swift; path = Sources/XCGLogger/Filters/FileNameFilter.swift; sourceTree = ""; }; + D51CDD644B115BDB28476FA956E471EB /* ConstraintOffsetTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintOffsetTarget.swift; path = Source/ConstraintOffsetTarget.swift; sourceTree = ""; }; + D5632FCE11080E682411F7EBDCF540E8 /* MJRefreshGifHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshGifHeader.m; path = MJRefresh/Custom/Header/MJRefreshGifHeader.m; sourceTree = ""; }; + D65B717583415DA0AE28E2A43427EA4D /* BaseQueuedDestination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseQueuedDestination.swift; path = Sources/XCGLogger/Destinations/BaseQueuedDestination.swift; sourceTree = ""; }; + D9721E4386156EEE17B71B5F047D2069 /* MBProgressHUD.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.debug.xcconfig; sourceTree = ""; }; + D9BC929CD3989AEB52AEA7BFA7107CF4 /* MJRefreshNormalHeader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshNormalHeader.m; path = MJRefresh/Custom/Header/MJRefreshNormalHeader.m; sourceTree = ""; }; + DB6831550F1319E304D9A14F35AA102E /* DispatchQueue+XCGAdditions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+XCGAdditions.swift"; path = "Sources/XCGLogger/Extensions/DispatchQueue+XCGAdditions.swift"; sourceTree = ""; }; + DC32CDF719DDEF5517E315A7B273BC3F /* UIScrollView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+MJExtension.h"; path = "MJRefresh/UIScrollView+MJExtension.h"; sourceTree = ""; }; + DC7D7BF4032A8CEB6A3DC80DB3966E54 /* ObjcExceptionBridging-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ObjcExceptionBridging-dummy.m"; sourceTree = ""; }; + DF5C2228DE7BF94931BE70CA75103D1F /* UIView+MJExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MJExtension.h"; path = "MJRefresh/UIView+MJExtension.h"; sourceTree = ""; }; + E1BE94717CE56633433237CA60217118 /* Pods-WCHBLEOTA-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-WCHBLEOTA-frameworks.sh"; sourceTree = ""; }; + E2E88D95D3ABF6883E32E81E6598B1D0 /* Debugging.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Debugging.swift; path = Source/Debugging.swift; sourceTree = ""; }; + E45021D43A4F52B11D6AD37C3226B8EF /* ObjcExceptionBridging.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ObjcExceptionBridging.debug.xcconfig; sourceTree = ""; }; + E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = MJRefresh; path = MJRefresh.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EA4992F78D4C18E4C9233949DB4083C1 /* ConstraintDescription.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintDescription.swift; path = Source/ConstraintDescription.swift; sourceTree = ""; }; + EAB4F6DBC0C99FE9DDFBB32366F95E8C /* NSBundle+MJRefresh.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSBundle+MJRefresh.m"; path = "MJRefresh/NSBundle+MJRefresh.m"; sourceTree = ""; }; + ED7584BF94B16247A9F7573A6725925D /* ConstraintPriorityTarget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintPriorityTarget.swift; path = Source/ConstraintPriorityTarget.swift; sourceTree = ""; }; + ED9DA57D98A78DC8380CBF2FB13FE453 /* Base64LogFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Base64LogFormatter.swift; path = Sources/XCGLogger/LogFormatters/Base64LogFormatter.swift; sourceTree = ""; }; + F026398EB05B37B5971B925DDBFF8DF1 /* PrePostFixLogFormatter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PrePostFixLogFormatter.swift; path = Sources/XCGLogger/LogFormatters/PrePostFixLogFormatter.swift; sourceTree = ""; }; + F039D6A62932D8E5A48E7D5ADBFAE128 /* ConstraintLayoutSupportDSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintLayoutSupportDSL.swift; path = Source/ConstraintLayoutSupportDSL.swift; sourceTree = ""; }; + F104C71811402770F88CF009CD1EEED6 /* UIScrollView+MJExtension.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+MJExtension.m"; path = "MJRefresh/UIScrollView+MJExtension.m"; sourceTree = ""; }; + F187913C8B5C412131FC81D53E744039 /* Pods-WCHBLEOTA-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-WCHBLEOTA-dummy.m"; sourceTree = ""; }; + F5790145554C30672C60EA47E9C421BC /* ObjcExceptionBridging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ObjcExceptionBridging.h; path = Sources/ObjcExceptionBridging/include/ObjcExceptionBridging.h; sourceTree = ""; }; + F58063240B4CBC87DE8AA85F5ED41FAA /* MJRefreshAutoStateFooter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshAutoStateFooter.m; path = MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m; sourceTree = ""; }; + F6803BF84EE1C1CDEAAD218EF7159C0E /* MJRefresh.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MJRefresh.release.xcconfig; sourceTree = ""; }; + F7400427CCD55ED39B10B24A4B440733 /* MJRefreshComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MJRefreshComponent.m; path = MJRefresh/Base/MJRefreshComponent.m; sourceTree = ""; }; + FA90C0887A827503A60DD64A0D68DB3C /* Pods-WCHBLEOTA.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WCHBLEOTA.debug.xcconfig"; sourceTree = ""; }; + FBA8CA6946B4168A9EDEC8900E3BEEA2 /* MJRefreshNormalTrailer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MJRefreshNormalTrailer.h; path = MJRefresh/Custom/Trailer/MJRefreshNormalTrailer.h; sourceTree = ""; }; + FC21E11599264BC8297EB97354A9423F /* XCGLogger.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCGLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FD16571C05DBAD8DB990BA6EA683F104 /* LogDetails.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LogDetails.swift; path = Sources/XCGLogger/Misc/LogDetails.swift; sourceTree = ""; }; + FD771C56A60D3F00739BB38A6A6B2FE1 /* ConstraintMakerEditable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ConstraintMakerEditable.swift; path = Source/ConstraintMakerEditable.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 15ED0E037D2A733D7609DD163CDE54D7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BE6C672F9D4B3CE0D0D83079B8A740F2 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33F9D42E86F99108B2A53187FF56C2F0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C66AE060AE5B7B0DBF2DF4779C9AC3A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4FF1BCA1F04DC419776BF74263663DA1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D53F8210FE8D8FE739303AB0CE4BDA0 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9B30433E568C40FCE04D5188A9715448 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CCA22C9F421C9E8C13009947816D8C82 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BE7A2BE67D4C7E5FC8A923D25661CF5B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EDCB17E097C5491E3A38447CDBEFA465 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D6DC8F0C2894774845C1DD2E7CA07B0C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AFAC1D4EBD53A048346210536741DF13 /* CoreGraphics.framework in Frameworks */, + 0AA33EBB857A5205F87C09CCB99EAC74 /* Foundation.framework in Frameworks */, + B52177FF72FDAC3EDB7195DE98F5501E /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 004019675F702E51BDD57BD081126B88 /* ObjcExceptionBridging */ = { + isa = PBXGroup; + children = ( + 411B9ADDFB0D18EA327E7B749B57BFC7 /* ObjcExceptionBridging */, + 2889AB3B593E606D76EE0049CCD5A1B6 /* Support Files */, + ); + path = ObjcExceptionBridging; + sourceTree = ""; + }; + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4D6691D8CB3D493006A8661C7CFED31A /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 09A75ADA55313F00B3F499B5D48F3AE1 /* XCGLogger */ = { + isa = PBXGroup; + children = ( + 7E5AE44D691350615B450A23FBE87C6F /* Core */, + B2DCD4FCAEF16D0DEC706C93BDAC873C /* Support Files */, + ); + path = XCGLogger; + sourceTree = ""; + }; + 1AEB7109662D4F2581EBB0E4287D4C96 /* Pods */ = { + isa = PBXGroup; + children = ( + 4E80688D45E3FED195E62F691299DB7D /* MBProgressHUD */, + 8D25AE646D16EF477728418B67BD84EC /* MJRefresh */, + 004019675F702E51BDD57BD081126B88 /* ObjcExceptionBridging */, + 8AF42191407615142071F4BE275D67BB /* SnapKit */, + 09A75ADA55313F00B3F499B5D48F3AE1 /* XCGLogger */, + ); + name = Pods; + sourceTree = ""; + }; + 2889AB3B593E606D76EE0049CCD5A1B6 /* Support Files */ = { + isa = PBXGroup; + children = ( + 87C0D16CC94AABFA9D32F502251C2306 /* ObjcExceptionBridging.modulemap */, + DC7D7BF4032A8CEB6A3DC80DB3966E54 /* ObjcExceptionBridging-dummy.m */, + 31668972FE66425BE3AE1D558784E7A5 /* ObjcExceptionBridging-Info.plist */, + 62FEBC53F51E160CFA155623DD092FEA /* ObjcExceptionBridging-prefix.pch */, + 1A88F77DB8C0D142958C19D1939F896A /* ObjcExceptionBridging-umbrella.h */, + E45021D43A4F52B11D6AD37C3226B8EF /* ObjcExceptionBridging.debug.xcconfig */, + B74777DE48547F4532D5AF0FDF265C38 /* ObjcExceptionBridging.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/ObjcExceptionBridging"; + sourceTree = ""; + }; + 2E61D57DB39127D1B861EA85959720F6 /* Resources */ = { + isa = PBXGroup; + children = ( + 3770A26C10C48DAD2D45AB2B66B161C1 /* MJRefresh.bundle */, + ); + name = Resources; + sourceTree = ""; + }; + 411B9ADDFB0D18EA327E7B749B57BFC7 /* ObjcExceptionBridging */ = { + isa = PBXGroup; + children = ( + F5790145554C30672C60EA47E9C421BC /* ObjcExceptionBridging.h */, + C16BFBB6246BFFA1D2112A94EB980087 /* ObjectiveCMarker.m */, + ); + name = ObjcExceptionBridging; + sourceTree = ""; + }; + 4D6691D8CB3D493006A8661C7CFED31A /* iOS */ = { + isa = PBXGroup; + children = ( + CABB98090B02C131F86931CB9BE54B7A /* CoreGraphics.framework */, + CB342FF58CA5A5D1282C84E02280A34F /* Foundation.framework */, + 51AB40693B18F443F75126966ED13E47 /* QuartzCore.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 4E80688D45E3FED195E62F691299DB7D /* MBProgressHUD */ = { + isa = PBXGroup; + children = ( + C3392BBCD96AD5D3B90938E0974E2F5F /* MBProgressHUD.h */, + 0E308F616373FF00806119782C0CC0F5 /* MBProgressHUD.m */, + E52A4A2D41F99F4C90913390BFA46D79 /* Support Files */, + ); + path = MBProgressHUD; + sourceTree = ""; + }; + 715E287FB8540DCB7C7DFFAC95D85BFC /* Resources */ = { + isa = PBXGroup; + children = ( + 6A827092D813EC5DD7D8A220C5E4BDCE /* .swift-version */, + ); + name = Resources; + sourceTree = ""; + }; + 7E5AE44D691350615B450A23FBE87C6F /* Core */ = { + isa = PBXGroup; + children = ( + 76478C08F80019F7E4B3E287A1BE0EDB /* ANSIColorLogFormatter.swift */, + 3969A76D5675C33C0765C2D0666122B7 /* AppleSystemLogDestination.swift */, + 236823FD2A5BF79FF8B9C6D798FEB378 /* AutoRotatingFileDestination.swift */, + ED9DA57D98A78DC8380CBF2FB13FE453 /* Base64LogFormatter.swift */, + 7E002304191A6E4C83BAFF97F4BB428F /* BaseDestination.swift */, + D65B717583415DA0AE28E2A43427EA4D /* BaseQueuedDestination.swift */, + C48F9099CC5F261997F9601825C2A9A0 /* ConsoleDestination.swift */, + 900DB585A502532FF6F02E988BAF46C3 /* DestinationProtocol.swift */, + 59CEFCD8384F01F5B133F9CCC5FBD1CC /* DevFilter.swift */, + DB6831550F1319E304D9A14F35AA102E /* DispatchQueue+XCGAdditions.swift */, + 11B2F8AAF015031E79B8DE7C3706B498 /* FileDestination.swift */, + D43F6DD46C278A70E9BB67459F43A9C0 /* FileNameFilter.swift */, + 06BFD819E995227B58C8F7A8A9A60D4F /* FilterProtocol.swift */, + 922045560C4CE88865DC104E4DA71225 /* HelperFunctions.swift */, + FD16571C05DBAD8DB990BA6EA683F104 /* LogDetails.swift */, + 4919B7F4D4495B9C8501A69E1D58D446 /* LogFormatterProtocol.swift */, + F026398EB05B37B5971B925DDBFF8DF1 /* PrePostFixLogFormatter.swift */, + BAD117AEA133A33989D0636E9762558C /* TagFilter.swift */, + 10EE524E8B9A0F08D6BEBD5B509DE361 /* TestDestination.swift */, + A476DBE5E58FB4E95F00B11D215466AE /* URL+XCGAdditions.swift */, + 2E504D97286B0028DF4218C8E3A7852E /* UserInfoFilter.swift */, + B245C43E94A7C07EE9FD0FFE3ECE3CB7 /* XCGLogger.swift */, + 6D4137AA0A313F5745D553B325B14931 /* XcodeColorsLogFormatter.swift */, + 715E287FB8540DCB7C7DFFAC95D85BFC /* Resources */, + ); + name = Core; + sourceTree = ""; + }; + 849FB5C4B5048A5964BA8881F7E2F58C /* Support Files */ = { + isa = PBXGroup; + children = ( + 860C4A82A65521A9B0E68AB9F6BC1F20 /* SnapKit.modulemap */, + 3CE2405D5E01A5F75D1677679D55F806 /* SnapKit-dummy.m */, + 5625991627A605DD96004F4EF065E987 /* SnapKit-Info.plist */, + B3885705F1FC1F964A6B2B4A510DEAB3 /* SnapKit-prefix.pch */, + 7959A414BB18756DEA5C2E54302248E3 /* SnapKit-umbrella.h */, + 1A50366DF331B46ADD864A90B571244F /* SnapKit.debug.xcconfig */, + 3AD4B93E917C8EC79F4EC178F8F46657 /* SnapKit.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/SnapKit"; + sourceTree = ""; + }; + 8AF42191407615142071F4BE275D67BB /* SnapKit */ = { + isa = PBXGroup; + children = ( + 52C4CC786BB059717BE6C8C59E01F193 /* Constraint.swift */, + 0D9A0EAEE037B4BA6052A5394CECE25E /* ConstraintAttributes.swift */, + 287B9C5B5E94734E31B6D97C18015B8E /* ConstraintConfig.swift */, + 37F8BC070373B0D6EC87396AFDA09B0D /* ConstraintConstantTarget.swift */, + EA4992F78D4C18E4C9233949DB4083C1 /* ConstraintDescription.swift */, + 3587683B7C228761F92C6F7B217C7099 /* ConstraintDirectionalInsets.swift */, + 9C8C7DFE72EAF1502227BD7DB988B629 /* ConstraintDirectionalInsetTarget.swift */, + BE2DFCFD3BE5D4500C118E2C93D8D5C0 /* ConstraintDSL.swift */, + 08BF8FD395F1E75D4D2A8762126FAEE0 /* ConstraintInsets.swift */, + 18B48C74096F2152386C09CDEF1DFC81 /* ConstraintInsetTarget.swift */, + C8F118F2C96966DD535ABBE603315797 /* ConstraintItem.swift */, + 123D41DDAB20F7DEBC06B177757A187B /* ConstraintLayoutGuide.swift */, + 8EB2EFBB5A69D7B0F9B254450697B193 /* ConstraintLayoutGuide+Extensions.swift */, + CAE74D3A6DE92AA6F23207BA67E12935 /* ConstraintLayoutGuideDSL.swift */, + 0307308156123105D9F15D2F9053EF39 /* ConstraintLayoutSupport.swift */, + F039D6A62932D8E5A48E7D5ADBFAE128 /* ConstraintLayoutSupportDSL.swift */, + 6B3A572589BCBAEFE63CED23274AA3FB /* ConstraintMaker.swift */, + FD771C56A60D3F00739BB38A6A6B2FE1 /* ConstraintMakerEditable.swift */, + 4ACB81A4631A3F95508A783E2D4D0DAF /* ConstraintMakerExtendable.swift */, + C731B6B6663CD7F3E3AED52FFD7F87BC /* ConstraintMakerFinalizable.swift */, + 03D6371DC57B6810FA3591218D0DA966 /* ConstraintMakerPriortizable.swift */, + C02730B57F73388C744310E3E851610F /* ConstraintMakerRelatable.swift */, + 9844FA722175BBEDA6E181FBE5FE40A0 /* ConstraintMultiplierTarget.swift */, + D51CDD644B115BDB28476FA956E471EB /* ConstraintOffsetTarget.swift */, + 84E093A4CDCDC8834EE597D76065D4CC /* ConstraintPriority.swift */, + ED7584BF94B16247A9F7573A6725925D /* ConstraintPriorityTarget.swift */, + D24B7751CF994BFC1621794356F52CD1 /* ConstraintRelatableTarget.swift */, + ADD271341F1A37A59A654DE2F15E83CC /* ConstraintRelation.swift */, + 500D9C2E75567DEF8214B7330EFCCD99 /* ConstraintView.swift */, + 75D43382FADF2042B5D9CCA9D87EDF2B /* ConstraintView+Extensions.swift */, + B62E87E07694724FCDF0AE95526A6344 /* ConstraintViewDSL.swift */, + E2E88D95D3ABF6883E32E81E6598B1D0 /* Debugging.swift */, + 29400E1EDB811D7D6E9B304E022DCDC6 /* LayoutConstraint.swift */, + A7CCD7136FD635C45A31DC017DB6414E /* LayoutConstraintItem.swift */, + 94742AE1CB8B69F4CC269EE4FAA7DFD1 /* Typealiases.swift */, + 0473DF7971D9DF6A6DC6D462AF9EBC35 /* UILayoutSupport+Extensions.swift */, + 849FB5C4B5048A5964BA8881F7E2F58C /* Support Files */, + ); + path = SnapKit; + sourceTree = ""; + }; + 8D25AE646D16EF477728418B67BD84EC /* MJRefresh */ = { + isa = PBXGroup; + children = ( + 3398E4CC29CE84D0775298FE6F888E16 /* MJRefresh.h */, + C16F62C14613F548A168922299BC73FE /* MJRefreshAutoFooter.h */, + 20886CE777EE4252D58593CCF5AA07CC /* MJRefreshAutoFooter.m */, + 35A2E8BC85E3768618CDBA045CC92E84 /* MJRefreshAutoGifFooter.h */, + CB24CC23B44D370AD73814FD64D67802 /* MJRefreshAutoGifFooter.m */, + 75A2D8EDDC781EA9891F331EFBA73616 /* MJRefreshAutoNormalFooter.h */, + 1B83A6DA44E20F31A94C03E6560BB23F /* MJRefreshAutoNormalFooter.m */, + D07CB7DE04A4071EF6A4A19836805021 /* MJRefreshAutoStateFooter.h */, + F58063240B4CBC87DE8AA85F5ED41FAA /* MJRefreshAutoStateFooter.m */, + 1A9C5856EC0CEFCF75F24C7F691B72C6 /* MJRefreshBackFooter.h */, + 75BA5385628498E1B6A562CECC8AA175 /* MJRefreshBackFooter.m */, + 4EC62499787AF5E1442586C5E772A332 /* MJRefreshBackGifFooter.h */, + 440EDEF7F36D826A1C29A684F0763DFE /* MJRefreshBackGifFooter.m */, + A7D9FCAA5C5829BD5FC2E2A29A135476 /* MJRefreshBackNormalFooter.h */, + 5F577BA256F926E30B7B2CE50CF2E5F8 /* MJRefreshBackNormalFooter.m */, + AB78F6D68F74D48331E2D38FB1B911EB /* MJRefreshBackStateFooter.h */, + B7579EA00DB0471476E0AF2BA77B8C14 /* MJRefreshBackStateFooter.m */, + 23A47F84A7174C0312631A2ECA84D979 /* MJRefreshComponent.h */, + F7400427CCD55ED39B10B24A4B440733 /* MJRefreshComponent.m */, + 7A0E8BABB1305E41529A6A620016D7BC /* MJRefreshConfig.h */, + 0F1D27157FD0258D65764E1D010D5EB2 /* MJRefreshConfig.m */, + D04701C582132FF795EF0CD633B34C20 /* MJRefreshConst.h */, + 35F9189144F133519EE2727A7F8D9408 /* MJRefreshConst.m */, + CC0A5D315B8CC9F18C808DF04AD3C58C /* MJRefreshFooter.h */, + 9031C8512782AD9559E06E12C6660D31 /* MJRefreshFooter.m */, + 5DBBF194605AE5B1790C7918DD0D6484 /* MJRefreshGifHeader.h */, + D5632FCE11080E682411F7EBDCF540E8 /* MJRefreshGifHeader.m */, + 40953BDE3CADA62CFAB96F29F16A56F0 /* MJRefreshHeader.h */, + 71D2F845700AB78DAB55A75F5BEEB228 /* MJRefreshHeader.m */, + 917731EE8F4A15585476C661E6CE8BCB /* MJRefreshNormalHeader.h */, + D9BC929CD3989AEB52AEA7BFA7107CF4 /* MJRefreshNormalHeader.m */, + FBA8CA6946B4168A9EDEC8900E3BEEA2 /* MJRefreshNormalTrailer.h */, + BC1EAF82C6879A150F30FBB3AFFC9B9A /* MJRefreshNormalTrailer.m */, + A03EC8B82C94EE8B11ABD9FCAE5C6D4C /* MJRefreshStateHeader.h */, + 8249D8CA7D75A6779BF4584E840CC7B9 /* MJRefreshStateHeader.m */, + C71CCD3C78628887833EF0F7AC7E4E05 /* MJRefreshStateTrailer.h */, + 0485C0DCE251B0CFD359F1FDC509EC91 /* MJRefreshStateTrailer.m */, + 80186E74E939C7E381E481C77C71A130 /* MJRefreshTrailer.h */, + 8EA95D516BD1F821770905806DB0CF70 /* MJRefreshTrailer.m */, + 5AE170B6A339AB3517E21DE4B88F9126 /* NSBundle+MJRefresh.h */, + EAB4F6DBC0C99FE9DDFBB32366F95E8C /* NSBundle+MJRefresh.m */, + 52B6AA7D76B5A86C6F48A3A39A5F06B8 /* UICollectionViewLayout+MJRefresh.h */, + 1D3C18CC38C79C93240C4DC62DA3F8DF /* UICollectionViewLayout+MJRefresh.m */, + DC32CDF719DDEF5517E315A7B273BC3F /* UIScrollView+MJExtension.h */, + F104C71811402770F88CF009CD1EEED6 /* UIScrollView+MJExtension.m */, + 30D3D48161DF4AC8C2FF9E1A816F0B40 /* UIScrollView+MJRefresh.h */, + 31A2E24C40DB8B1F2D1BF28DFB66AF4B /* UIScrollView+MJRefresh.m */, + DF5C2228DE7BF94931BE70CA75103D1F /* UIView+MJExtension.h */, + B8E3654E10BC59749B4730997392D39D /* UIView+MJExtension.m */, + 2E61D57DB39127D1B861EA85959720F6 /* Resources */, + FB8DD21CA65D6D6ED5CA90953E6C22BF /* Support Files */, + ); + path = MJRefresh; + sourceTree = ""; + }; + B2DCD4FCAEF16D0DEC706C93BDAC873C /* Support Files */ = { + isa = PBXGroup; + children = ( + 36968FA970A046A15C4DA1F0AAD19652 /* XCGLogger.modulemap */, + A221F5C1C65D0A419950E4D5754422BC /* XCGLogger-dummy.m */, + 6D6BADB5AF89C9778E115964F7E134D4 /* XCGLogger-Info.plist */, + 8741A977BF903A4874E25FDB4910D218 /* XCGLogger-prefix.pch */, + A7ECEE2839C1D2330A0A877622782D2A /* XCGLogger-umbrella.h */, + 1DAB275BA042282988CA24043264E931 /* XCGLogger.debug.xcconfig */, + C663C5CE412FCB36E0FE8E27E5164405 /* XCGLogger.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/XCGLogger"; + sourceTree = ""; + }; + B36B3DCD7F76A6F219E9B382F936411E /* Products */ = { + isa = PBXGroup; + children = ( + 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD.framework */, + E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */, + 1CAB16A12A28E8BE749202B03552307A /* ObjcExceptionBridging.framework */, + 578D38AC14311ED8185A99EB825B0204 /* Pods-WCHBLEOTA */, + 979486118B3E90C08386079D57962701 /* SnapKit */, + FC21E11599264BC8297EB97354A9423F /* XCGLogger.framework */, + ); + name = Products; + sourceTree = ""; + }; + B887C207A428196AB7B4AC197927F232 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + F422FD094D468EFE7FB1C8B99D21C679 /* Pods-WCHBLEOTA */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */, + 1AEB7109662D4F2581EBB0E4287D4C96 /* Pods */, + B36B3DCD7F76A6F219E9B382F936411E /* Products */, + B887C207A428196AB7B4AC197927F232 /* Targets Support Files */, + ); + sourceTree = ""; + }; + E52A4A2D41F99F4C90913390BFA46D79 /* Support Files */ = { + isa = PBXGroup; + children = ( + CC02394341D63F245D96A73C3BB7B568 /* MBProgressHUD.modulemap */, + 42F183B84988A24D1F7DC73D47CE8410 /* MBProgressHUD-dummy.m */, + 8D09C96E9147C1A474724F57A24FF7A3 /* MBProgressHUD-Info.plist */, + AC8698CCBAE21AC376B843F7B3C2E026 /* MBProgressHUD-prefix.pch */, + 95CF50952986206AD082D14A16333BF5 /* MBProgressHUD-umbrella.h */, + D9721E4386156EEE17B71B5F047D2069 /* MBProgressHUD.debug.xcconfig */, + 821919445F1740BB0FE272BA5CBC0126 /* MBProgressHUD.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/MBProgressHUD"; + sourceTree = ""; + }; + F422FD094D468EFE7FB1C8B99D21C679 /* Pods-WCHBLEOTA */ = { + isa = PBXGroup; + children = ( + 91648AD383E8321DCF006378BFFBC683 /* Pods-WCHBLEOTA.modulemap */, + 6064D8E08CDBB2310CF6DC733F48C72C /* Pods-WCHBLEOTA-acknowledgements.markdown */, + C1D73242C23DC09CE53DC41DC76BBAF5 /* Pods-WCHBLEOTA-acknowledgements.plist */, + F187913C8B5C412131FC81D53E744039 /* Pods-WCHBLEOTA-dummy.m */, + E1BE94717CE56633433237CA60217118 /* Pods-WCHBLEOTA-frameworks.sh */, + ABA583DE11109CDD4DE3F5450E271CF2 /* Pods-WCHBLEOTA-Info.plist */, + 19A332AFF11A391D10ACACC79EA2AB55 /* Pods-WCHBLEOTA-umbrella.h */, + FA90C0887A827503A60DD64A0D68DB3C /* Pods-WCHBLEOTA.debug.xcconfig */, + 3D256BC218B1BDB0D6783764AE2C5BC9 /* Pods-WCHBLEOTA.release.xcconfig */, + ); + name = "Pods-WCHBLEOTA"; + path = "Target Support Files/Pods-WCHBLEOTA"; + sourceTree = ""; + }; + FB8DD21CA65D6D6ED5CA90953E6C22BF /* Support Files */ = { + isa = PBXGroup; + children = ( + 39F2ABDF0134E0CC910CD6E3F46D400E /* MJRefresh.modulemap */, + 1AB0A645D433D4526B2E61E6D78A6A64 /* MJRefresh-dummy.m */, + 4EB6E2B145D1FAB64A596A2A95DD4BD5 /* MJRefresh-Info.plist */, + A06030E4DABE38F84AD4275226ED93F2 /* MJRefresh-prefix.pch */, + A89602C63F3616646938A3F289A37A0A /* MJRefresh-umbrella.h */, + 201A71B3656F2DD58A5B93CD7839FF8D /* MJRefresh.debug.xcconfig */, + F6803BF84EE1C1CDEAAD218EF7159C0E /* MJRefresh.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/MJRefresh"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3B921547E999920F44EBD58F955423CC /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A4467357581E8345DD348683CC4111AF /* SnapKit-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5D82C29ACD851E6EA219B34A73C961F5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 67E941CADB3CDDEEDF8CE4EE4A4A05BB /* MBProgressHUD.h in Headers */, + 5BAC1EF86D0E57E44E404B2796993561 /* MBProgressHUD-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9FC529FC0DC2959EB29D13F04EB00F30 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4642D790995C23BA033D1117B6E86510 /* Pods-WCHBLEOTA-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C43ED734FBFFBF36A7C56538219A4AAF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9FFAC41FD637E5C6FA1FFFE33FA138A6 /* XCGLogger-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF663F3ACEFBB5CE45E7BF8421800100 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AFFCC49584308828ACCDBC67418D1354 /* ObjcExceptionBridging.h in Headers */, + 0E214FD3632D8023EF46E6D73A311DAF /* ObjcExceptionBridging-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3A99BF609E9614D9F831DDD947266D1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AB5958BA59F34460139B065451B7D71D /* MJRefresh.h in Headers */, + 3F57997C48B9AC2E8157E45521B6F662 /* MJRefresh-umbrella.h in Headers */, + F0AD0E9222DC4A06FFC0B07737CE2FEA /* MJRefreshAutoFooter.h in Headers */, + 43967A52DF5DF083B0771199EE89F88A /* MJRefreshAutoGifFooter.h in Headers */, + FC42711B8E37AD9B5C2F735EDDAD441A /* MJRefreshAutoNormalFooter.h in Headers */, + 4D31CCA291F1AAB8DB56EAC5E5100D16 /* MJRefreshAutoStateFooter.h in Headers */, + 9807BF49C74281A14440DACC71E07C4A /* MJRefreshBackFooter.h in Headers */, + 3DDC5EF8F09F2A192618936067DFE41F /* MJRefreshBackGifFooter.h in Headers */, + 5427DBACB1D189B22A74A5F95ECC6F7C /* MJRefreshBackNormalFooter.h in Headers */, + 572DBDC37429318F768FD7A21F1C0B70 /* MJRefreshBackStateFooter.h in Headers */, + 569C9596A1EE66A0867C2F27DB4434FD /* MJRefreshComponent.h in Headers */, + 5F24CA2DAA215F6E0AEC5AC773198F95 /* MJRefreshConfig.h in Headers */, + D43C0E831750DB310012D56EDB8F36A1 /* MJRefreshConst.h in Headers */, + 69359A20750375B3BF91D193B60C406D /* MJRefreshFooter.h in Headers */, + 98EAF4CA985CD43CFE416B235817CEFA /* MJRefreshGifHeader.h in Headers */, + FA482C6F33494F529CF642D22DBA3B44 /* MJRefreshHeader.h in Headers */, + E6D1E0657F2E7190956CA155F09136A4 /* MJRefreshNormalHeader.h in Headers */, + 6866BDC5DB2452285680090A490EFD64 /* MJRefreshNormalTrailer.h in Headers */, + 33A4F6D2199266B0F53AB5D2A91FD53C /* MJRefreshStateHeader.h in Headers */, + B5B122B965516FA9349250A502C3A58D /* MJRefreshStateTrailer.h in Headers */, + 29421B5D519A5B0801CB6E0716B5DB30 /* MJRefreshTrailer.h in Headers */, + F71117E3C5158BD6036AA7F8AB71FC47 /* NSBundle+MJRefresh.h in Headers */, + BF1A148832BC2A213384F7F3700CF8B5 /* UICollectionViewLayout+MJRefresh.h in Headers */, + BDFF68F76ED8639B0031A55390727068 /* UIScrollView+MJExtension.h in Headers */, + 0A93D725DA34E6ACB26D9B2A714BBEB6 /* UIScrollView+MJRefresh.h in Headers */, + AE0FF5B3C55AFD12E15909F98595C848 /* UIView+MJExtension.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 07AFE6B9C0D64C3222F1B3FAA995664C /* XCGLogger */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3AC56FE573B89CCC361928BCB728BF66 /* Build configuration list for PBXNativeTarget "XCGLogger" */; + buildPhases = ( + C43ED734FBFFBF36A7C56538219A4AAF /* Headers */, + 9A34C353BF7D4D22AEE7A1DE2A8FB53F /* Sources */, + BE7A2BE67D4C7E5FC8A923D25661CF5B /* Frameworks */, + C5948C45ECD912E6FB37BB0854AA6881 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D43AA102EE1DAF224BED151879F20368 /* PBXTargetDependency */, + ); + name = XCGLogger; + productName = XCGLogger; + productReference = FC21E11599264BC8297EB97354A9423F /* XCGLogger.framework */; + productType = "com.apple.product-type.framework"; + }; + 17DE9E5D6B4ED069A63A598178D68C3B /* Pods-WCHBLEOTA */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DC7EC58C63B3D5D1BCA4BC998716490 /* Build configuration list for PBXNativeTarget "Pods-WCHBLEOTA" */; + buildPhases = ( + 9FC529FC0DC2959EB29D13F04EB00F30 /* Headers */, + 45D0DE87BEF9805905C5D5AFAFF9D2BC /* Sources */, + 4FF1BCA1F04DC419776BF74263663DA1 /* Frameworks */, + 7799983A46EA5240C077D17664CE4B20 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9AE1EA08E8159EC6298818D877F9DE6D /* PBXTargetDependency */, + 04061D3593E5C368CFB1D913513AEE99 /* PBXTargetDependency */, + 89CB8095F9B498AE870E59ACBD76F3C8 /* PBXTargetDependency */, + CF28C264AAD49C16EF836E1B6B401F51 /* PBXTargetDependency */, + A90A0A3BFD0D61D177F7AF725EF8EDF9 /* PBXTargetDependency */, + ); + name = "Pods-WCHBLEOTA"; + productName = Pods_WCHBLEOTA; + productReference = 578D38AC14311ED8185A99EB825B0204 /* Pods-WCHBLEOTA */; + productType = "com.apple.product-type.framework"; + }; + 19622742EBA51E823D6DAE3F8CDBFAD4 /* SnapKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4949A940CD53B7E293859B71C91C88F3 /* Build configuration list for PBXNativeTarget "SnapKit" */; + buildPhases = ( + 3B921547E999920F44EBD58F955423CC /* Headers */, + 06A02EF810C9B8F84BA558BBDB9E5D6E /* Sources */, + 9B30433E568C40FCE04D5188A9715448 /* Frameworks */, + DBFBC99C6F5D9B1D57CC9D1C6E9209EB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SnapKit; + productName = SnapKit; + productReference = 979486118B3E90C08386079D57962701 /* SnapKit */; + productType = "com.apple.product-type.framework"; + }; + 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */ = { + isa = PBXNativeTarget; + buildConfigurationList = FAA2EC63F721708EC257E816806AC5E0 /* Build configuration list for PBXNativeTarget "MJRefresh" */; + buildPhases = ( + D3A99BF609E9614D9F831DDD947266D1 /* Headers */, + CB56C88BF9587D0062D919E0C96F51CD /* Sources */, + 15ED0E037D2A733D7609DD163CDE54D7 /* Frameworks */, + 31878AEE0AE7F7144A2F4FD5CEA126F5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MJRefresh; + productName = MJRefresh; + productReference = E49D6D248DD1CEE584E6776B9164A1B2 /* MJRefresh */; + productType = "com.apple.product-type.framework"; + }; + 746615E9A06AABA6F288B49A10B63E10 /* ObjcExceptionBridging */ = { + isa = PBXNativeTarget; + buildConfigurationList = C799736AA4FA2B97E2EA90F8F7ECECBE /* Build configuration list for PBXNativeTarget "ObjcExceptionBridging" */; + buildPhases = ( + CF663F3ACEFBB5CE45E7BF8421800100 /* Headers */, + 2DC1A29317C17CA588652C46C20364A2 /* Sources */, + 33F9D42E86F99108B2A53187FF56C2F0 /* Frameworks */, + 3BDFC35378E1B7643C2E9B0B470302BE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ObjcExceptionBridging; + productName = ObjcExceptionBridging; + productReference = 1CAB16A12A28E8BE749202B03552307A /* ObjcExceptionBridging.framework */; + productType = "com.apple.product-type.framework"; + }; + 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */ = { + isa = PBXNativeTarget; + buildConfigurationList = A7BD2681E97C00DCC2EF91B0EBA76110 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */; + buildPhases = ( + 5D82C29ACD851E6EA219B34A73C961F5 /* Headers */, + 7E957D4020E4C4BC633BF50F7F51E5F6 /* Sources */, + D6DC8F0C2894774845C1DD2E7CA07B0C /* Frameworks */, + C0E0F7D28F4D633128D0F53BEAE34D3D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MBProgressHUD; + productName = MBProgressHUD; + productReference = 8B8FAB0D627B17EDE1366984278705D9 /* MBProgressHUD.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = B36B3DCD7F76A6F219E9B382F936411E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */, + 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */, + 746615E9A06AABA6F288B49A10B63E10 /* ObjcExceptionBridging */, + 17DE9E5D6B4ED069A63A598178D68C3B /* Pods-WCHBLEOTA */, + 19622742EBA51E823D6DAE3F8CDBFAD4 /* SnapKit */, + 07AFE6B9C0D64C3222F1B3FAA995664C /* XCGLogger */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 31878AEE0AE7F7144A2F4FD5CEA126F5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C28E73E7C990B5831ABCDDA6F8275FD0 /* MJRefresh.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3BDFC35378E1B7643C2E9B0B470302BE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7799983A46EA5240C077D17664CE4B20 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0E0F7D28F4D633128D0F53BEAE34D3D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C5948C45ECD912E6FB37BB0854AA6881 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5A013AE4976A5EF0E621278FAEE1BED6 /* .swift-version in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBFBC99C6F5D9B1D57CC9D1C6E9209EB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 06A02EF810C9B8F84BA558BBDB9E5D6E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 51A4A1046676D304410544EB56732A49 /* Constraint.swift in Sources */, + 7580FAAB1BDA52F5A969E5571D1A5973 /* ConstraintAttributes.swift in Sources */, + B543FD108C1C6AF6129CB4991553218B /* ConstraintConfig.swift in Sources */, + C61D3BC32A28A405C934C00039AD2583 /* ConstraintConstantTarget.swift in Sources */, + 8FD9CD608C4EAAFDE6AC7B8B9EF0FF5E /* ConstraintDescription.swift in Sources */, + A0F754C88A64972A40A9008B0AD52109 /* ConstraintDirectionalInsets.swift in Sources */, + 7764AA5F6BBFC6ECE43959923DD007D3 /* ConstraintDirectionalInsetTarget.swift in Sources */, + 90FD5AE525E138A473723FD79AF73273 /* ConstraintDSL.swift in Sources */, + 8C6546C1EF4F153DF3795CC6FE189E5B /* ConstraintInsets.swift in Sources */, + BEBF920FEB959B46A76BAADF22E5CD15 /* ConstraintInsetTarget.swift in Sources */, + BD333CDBCF5D2FD55920336FC271DF33 /* ConstraintItem.swift in Sources */, + EE6C364198A763EBBF49237035D86439 /* ConstraintLayoutGuide.swift in Sources */, + 3DEDFA52B3A196F6D3E1F0937617628A /* ConstraintLayoutGuide+Extensions.swift in Sources */, + 8449EB1DFD43E222D687D5A8D2088D2D /* ConstraintLayoutGuideDSL.swift in Sources */, + 3B60C02F6E42FD06B128473E00A94224 /* ConstraintLayoutSupport.swift in Sources */, + 274DF0E2BF04F6F4F9F1E70CF513A4F2 /* ConstraintLayoutSupportDSL.swift in Sources */, + CB194156C900B767B0160AF72EDF354D /* ConstraintMaker.swift in Sources */, + A53D3AF15CE8D348306EF11619C5D166 /* ConstraintMakerEditable.swift in Sources */, + 825062025906CE93C5D124E1FD9A811E /* ConstraintMakerExtendable.swift in Sources */, + D13D417B236E736EEAE7217B5CE3EC5C /* ConstraintMakerFinalizable.swift in Sources */, + F2C817C166B2DE613222C41015A586C9 /* ConstraintMakerPriortizable.swift in Sources */, + CB8E4BF0D710970BE2CB4C87ED1043E4 /* ConstraintMakerRelatable.swift in Sources */, + 17BE0F4E51B0FB968125F1A520607FD8 /* ConstraintMultiplierTarget.swift in Sources */, + 62F299B4704A7C95FB5866C6CDE2E2FD /* ConstraintOffsetTarget.swift in Sources */, + F343BA4E457FFDB0165492AECAEF0BCC /* ConstraintPriority.swift in Sources */, + E36244E8BF4AC941E82DAF16DDF4BBC2 /* ConstraintPriorityTarget.swift in Sources */, + E8EAADACF3BAE33BDECBC7214EAE9CD2 /* ConstraintRelatableTarget.swift in Sources */, + D59C2826AD288ECFF576B2AFA312716C /* ConstraintRelation.swift in Sources */, + F24D06C23DAB2F52A30C886A7A8177C7 /* ConstraintView.swift in Sources */, + 1E9EEA756F2774D73347F1660EEFE3E9 /* ConstraintView+Extensions.swift in Sources */, + 5E8BA529DFB4529006967624044FEC1C /* ConstraintViewDSL.swift in Sources */, + F10586462FB54CEA169A1A7A469A926D /* Debugging.swift in Sources */, + 43863B6D6A0E47B6648BB7B469736EDD /* LayoutConstraint.swift in Sources */, + 4CA13A0527BC57DE2C54A0F3B5ED8652 /* LayoutConstraintItem.swift in Sources */, + 968B4874A9F12D67C8B901136C9C8157 /* SnapKit-dummy.m in Sources */, + 3CD5FAFC746A76D73C3F501734199DFF /* Typealiases.swift in Sources */, + 144DA93A55A598F5197F10C729FBDD69 /* UILayoutSupport+Extensions.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2DC1A29317C17CA588652C46C20364A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EFE14A8E7C02BDD16B252181BB381247 /* ObjcExceptionBridging-dummy.m in Sources */, + 8367A150606C504F9DED8DE524A6437B /* ObjectiveCMarker.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 45D0DE87BEF9805905C5D5AFAFF9D2BC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6302E2433D0108058251F5C0979595AD /* Pods-WCHBLEOTA-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E957D4020E4C4BC633BF50F7F51E5F6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0097064E7F7D3F413161738CC5C25EEC /* MBProgressHUD.m in Sources */, + 58C91B4AB36E6B16421106CA634C58EF /* MBProgressHUD-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9A34C353BF7D4D22AEE7A1DE2A8FB53F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CA05F14AC92A10A39A7E866FA72C4582 /* ANSIColorLogFormatter.swift in Sources */, + 2CCA4FDF86BC8A8984E599CE97B4BB4B /* AppleSystemLogDestination.swift in Sources */, + F319DD3C0DE3B8896C4E45584BFFFD01 /* AutoRotatingFileDestination.swift in Sources */, + 6AD7614826D1F0E5C7BF58B08373B9B7 /* Base64LogFormatter.swift in Sources */, + A32FEE92F0765B9415E6DD0721992B2C /* BaseDestination.swift in Sources */, + 3D3FA74047C3C06B2E269C3BC8DED98D /* BaseQueuedDestination.swift in Sources */, + 8462FBECC31A3DEB90BA896639DF7C71 /* ConsoleDestination.swift in Sources */, + 925214372EC186625DC2566F1D7649DA /* DestinationProtocol.swift in Sources */, + A4D4B0B7C69670D030B4398F31584025 /* DevFilter.swift in Sources */, + 9E0112B58B68FBB94E23113BCAE41FBC /* DispatchQueue+XCGAdditions.swift in Sources */, + FC929DBC35F43F5BBE4741611AF43D2D /* FileDestination.swift in Sources */, + D4E03538CEF69CA99F48CFB303C8BFAA /* FileNameFilter.swift in Sources */, + 87ECEF7F4D9C689B39FC644CFD25D8AD /* FilterProtocol.swift in Sources */, + EEFD0F7603E62B64F5FDE4659324786F /* HelperFunctions.swift in Sources */, + 4B1A328B82EB2CE389FDE9A5E0E2755F /* LogDetails.swift in Sources */, + D24ACD6E03DC5394C6909011D3518756 /* LogFormatterProtocol.swift in Sources */, + 20076D79F24AD3B3D2BD250181EA065A /* PrePostFixLogFormatter.swift in Sources */, + 00CE14690879775C12718E86157670EC /* TagFilter.swift in Sources */, + D275EEDA6F16D7745DC91A0A36CB64C4 /* TestDestination.swift in Sources */, + 3D9A2FF659102C6C74B9CAF068E07813 /* URL+XCGAdditions.swift in Sources */, + BC08210D922B8C20A382E850A6AB91FD /* UserInfoFilter.swift in Sources */, + E96DEA6D681BB273A4A97517D884D669 /* XCGLogger.swift in Sources */, + 8496B2BE600628C923C9C89473DD0CF3 /* XCGLogger-dummy.m in Sources */, + 5A82E2848549F14A452E1D5F921F2668 /* XcodeColorsLogFormatter.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB56C88BF9587D0062D919E0C96F51CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4502D7E8FA8F03A1C87EE48533FEB8C0 /* MJRefresh-dummy.m in Sources */, + 927DF15A74376F9FD582A3D17A293EC5 /* MJRefreshAutoFooter.m in Sources */, + C3A160E82826D84E59889F7AC3157F42 /* MJRefreshAutoGifFooter.m in Sources */, + D0038F642442AAE53C12ECA3240B5A6D /* MJRefreshAutoNormalFooter.m in Sources */, + E3A90F4FB659B5DDCF5DA603DDEF9E66 /* MJRefreshAutoStateFooter.m in Sources */, + 31005F5A8B58CA1089E5B7DA1097A424 /* MJRefreshBackFooter.m in Sources */, + D0665D6E3CD34DD382F7E85551753C0A /* MJRefreshBackGifFooter.m in Sources */, + BC29069E8C5679A176E284888F597C32 /* MJRefreshBackNormalFooter.m in Sources */, + 46CABB2581EDC02E6646E5FE296CEF9C /* MJRefreshBackStateFooter.m in Sources */, + BAA4C06A1DE43F74573C2E49EC85D9B5 /* MJRefreshComponent.m in Sources */, + 6D7EE0E37B82EC69E80A480DA3F564C6 /* MJRefreshConfig.m in Sources */, + E15214E66D7A6069AA5E0B470A16F92F /* MJRefreshConst.m in Sources */, + EC7A19215B0957CF1EFFF58A1D79F273 /* MJRefreshFooter.m in Sources */, + B5402265E04D513FAD8EA1EB234A969F /* MJRefreshGifHeader.m in Sources */, + EE85A2DDCED7EE7AB3F57DE292D36C18 /* MJRefreshHeader.m in Sources */, + AF4B3C88EF24097513282E7551F33385 /* MJRefreshNormalHeader.m in Sources */, + 85BC413BB35DE20594B6D84572FB49FC /* MJRefreshNormalTrailer.m in Sources */, + 9C41EF0E685AD816D8C26D83B93AB6AF /* MJRefreshStateHeader.m in Sources */, + 484548C5D780A8DA124E24C3A27720CD /* MJRefreshStateTrailer.m in Sources */, + 0A4ACE3AFFFCB7846F824A803645CC5F /* MJRefreshTrailer.m in Sources */, + 6579F1B66AB9CADABB69B726F8F15225 /* NSBundle+MJRefresh.m in Sources */, + 752B36F5BBCF8DED01BF1E444D975546 /* UICollectionViewLayout+MJRefresh.m in Sources */, + E579107E3F34A6761997CE937C6DFF1A /* UIScrollView+MJExtension.m in Sources */, + 6372AFD5512AA9D634536E7543652957 /* UIScrollView+MJRefresh.m in Sources */, + 7D24D21B28B00E91354E3A5A8A7EAD66 /* UIView+MJExtension.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 04061D3593E5C368CFB1D913513AEE99 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MJRefresh; + target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */; + targetProxy = C3F1368A08CDAEE0A7DBFD8718CFD65E /* PBXContainerItemProxy */; + }; + 89CB8095F9B498AE870E59ACBD76F3C8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ObjcExceptionBridging; + target = 746615E9A06AABA6F288B49A10B63E10 /* ObjcExceptionBridging */; + targetProxy = 55169CF6334530C597A08E51B29EDFFB /* PBXContainerItemProxy */; + }; + 9AE1EA08E8159EC6298818D877F9DE6D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = MBProgressHUD; + target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; + targetProxy = 26413B1DB1B7FBEBD39D96CE00E9571A /* PBXContainerItemProxy */; + }; + A90A0A3BFD0D61D177F7AF725EF8EDF9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = XCGLogger; + target = 07AFE6B9C0D64C3222F1B3FAA995664C /* XCGLogger */; + targetProxy = A909B4707D3A3F267E3DCA1E045EA348 /* PBXContainerItemProxy */; + }; + CF28C264AAD49C16EF836E1B6B401F51 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = SnapKit; + target = 19622742EBA51E823D6DAE3F8CDBFAD4 /* SnapKit */; + targetProxy = 95CC381A3166EB4C44B22C605FA35DCB /* PBXContainerItemProxy */; + }; + D43AA102EE1DAF224BED151879F20368 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ObjcExceptionBridging; + target = 746615E9A06AABA6F288B49A10B63E10 /* ObjcExceptionBridging */; + targetProxy = 4CD66CC9E7C428897EF4927C1AB63851 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0FFFD177440D556AC451E2CA2ED3D998 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F6803BF84EE1C1CDEAAD218EF7159C0E /* MJRefresh.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MJRefresh/MJRefresh-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; + PRODUCT_MODULE_NAME = MJRefresh; + PRODUCT_NAME = MJRefresh; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 59B5EC788F59C4343F9BE0E5458BF9C0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FA90C0887A827503A60DD64A0D68DB3C /* Pods-WCHBLEOTA.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 5A747A057B3E3DCED365403351790650 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1DAB275BA042282988CA24043264E931 /* XCGLogger.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/XCGLogger/XCGLogger-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/XCGLogger/XCGLogger-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/XCGLogger/XCGLogger.modulemap"; + PRODUCT_MODULE_NAME = XCGLogger; + PRODUCT_NAME = XCGLogger; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 66E0895F1143CC96D577E98C084AE25B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3D256BC218B1BDB0D6783764AE2C5BC9 /* Pods-WCHBLEOTA.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 72238AD5BFEA94CC2420606D4053EE58 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E45021D43A4F52B11D6AD37C3226B8EF /* ObjcExceptionBridging.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.modulemap"; + PRODUCT_MODULE_NAME = ObjcExceptionBridging; + PRODUCT_NAME = ObjcExceptionBridging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 9E406C6AAF85E580207CD97B0044DEAB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + C3C37B487645A54D043C2C18BF002F24 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 821919445F1740BB0FE272BA5CBC0126 /* MBProgressHUD.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = MBProgressHUD; + PRODUCT_NAME = MBProgressHUD; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + CB8A79F7382B0A1227C38D59E7968EEA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1A50366DF331B46ADD864A90B571244F /* SnapKit.debug.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SnapKit/SnapKit-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SnapKit/SnapKit-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SnapKit/SnapKit.modulemap"; + PRODUCT_MODULE_NAME = SnapKit; + PRODUCT_NAME = SnapKit; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D3FCB4EB0F57442B8A9E6627EBD43952 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B74777DE48547F4532D5AF0FDF265C38 /* ObjcExceptionBridging.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.modulemap"; + PRODUCT_MODULE_NAME = ObjcExceptionBridging; + PRODUCT_NAME = ObjcExceptionBridging; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DE569755C8FE69395D8E6C347DC7A5F8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D9721E4386156EEE17B71B5F047D2069 /* MBProgressHUD.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/MBProgressHUD/MBProgressHUD.modulemap"; + PRODUCT_MODULE_NAME = MBProgressHUD; + PRODUCT_NAME = MBProgressHUD; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DFFD31690F9CC8449FD1F803388E1D46 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3AD4B93E917C8EC79F4EC178F8F46657 /* SnapKit.release.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/SnapKit/SnapKit-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SnapKit/SnapKit-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/SnapKit/SnapKit.modulemap"; + PRODUCT_MODULE_NAME = SnapKit; + PRODUCT_NAME = SnapKit; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + E90159A44266FD029CC33D7C1E65BD00 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C663C5CE412FCB36E0FE8E27E5164405 /* XCGLogger.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/XCGLogger/XCGLogger-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/XCGLogger/XCGLogger-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/XCGLogger/XCGLogger.modulemap"; + PRODUCT_MODULE_NAME = XCGLogger; + PRODUCT_NAME = XCGLogger; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + FEB2E2F8BE8C2C7960D6CC1629D0A998 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 201A71B3656F2DD58A5B93CD7839FF8D /* MJRefresh.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/MJRefresh/MJRefresh-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/MJRefresh/MJRefresh-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/MJRefresh/MJRefresh.modulemap"; + PRODUCT_MODULE_NAME = MJRefresh; + PRODUCT_NAME = MJRefresh; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DC7EC58C63B3D5D1BCA4BC998716490 /* Build configuration list for PBXNativeTarget "Pods-WCHBLEOTA" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 59B5EC788F59C4343F9BE0E5458BF9C0 /* Debug */, + 66E0895F1143CC96D577E98C084AE25B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3AC56FE573B89CCC361928BCB728BF66 /* Build configuration list for PBXNativeTarget "XCGLogger" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5A747A057B3E3DCED365403351790650 /* Debug */, + E90159A44266FD029CC33D7C1E65BD00 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */, + 9E406C6AAF85E580207CD97B0044DEAB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4949A940CD53B7E293859B71C91C88F3 /* Build configuration list for PBXNativeTarget "SnapKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB8A79F7382B0A1227C38D59E7968EEA /* Debug */, + DFFD31690F9CC8449FD1F803388E1D46 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A7BD2681E97C00DCC2EF91B0EBA76110 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DE569755C8FE69395D8E6C347DC7A5F8 /* Debug */, + C3C37B487645A54D043C2C18BF002F24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C799736AA4FA2B97E2EA90F8F7ECECBE /* Build configuration list for PBXNativeTarget "ObjcExceptionBridging" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 72238AD5BFEA94CC2420606D4053EE58 /* Debug */, + D3FCB4EB0F57442B8A9E6627EBD43952 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FAA2EC63F721708EC257E816806AC5E0 /* Build configuration list for PBXNativeTarget "MJRefresh" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FEB2E2F8BE8C2C7960D6CC1629D0A998 /* Debug */, + 0FFFD177440D556AC451E2CA2ED3D998 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MBProgressHUD.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MBProgressHUD.xcscheme new file mode 100644 index 0000000..2a75d0c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MBProgressHUD.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MJRefresh.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MJRefresh.xcscheme new file mode 100644 index 0000000..3e39cfe --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/MJRefresh.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/ObjcExceptionBridging.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/ObjcExceptionBridging.xcscheme new file mode 100644 index 0000000..6c4f8ae --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/ObjcExceptionBridging.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/Pods-WCHBLEOTA.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/Pods-WCHBLEOTA.xcscheme new file mode 100644 index 0000000..11fef23 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/Pods-WCHBLEOTA.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/SnapKit.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/SnapKit.xcscheme new file mode 100644 index 0000000..ee0a410 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/SnapKit.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/XCGLogger.xcscheme b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/XCGLogger.xcscheme new file mode 100644 index 0000000..4eacc60 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/XCGLogger.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..124fc4e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Pods.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,53 @@ + + + + + SchemeUserState + + MBProgressHUD.xcscheme + + isShown + + orderHint + 0 + + MJRefresh.xcscheme + + isShown + + orderHint + 1 + + ObjcExceptionBridging.xcscheme + + isShown + + orderHint + 2 + + Pods-WCHBLEOTA.xcscheme + + isShown + + orderHint + 3 + + SnapKit.xcscheme + + isShown + + orderHint + 4 + + XCGLogger.xcscheme + + isShown + + orderHint + 5 + + + SuppressBuildableAutocreation + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/LICENSE b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/LICENSE new file mode 100644 index 0000000..a18ccfb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/README.md b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/README.md new file mode 100644 index 0000000..0945ce6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/README.md @@ -0,0 +1,136 @@ + + +SnapKit is a DSL to make Auto Layout easy on both iOS and OS X. + +[![Build Status](https://travis-ci.org/SnapKit/SnapKit.svg)](https://travis-ci.org/SnapKit/SnapKit) +[![Platform](https://img.shields.io/cocoapods/p/SnapKit.svg?style=flat)](https://github.com/SnapKit/SnapKit) +[![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SnapKit.svg)](https://cocoapods.org/pods/SnapKit) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +#### ⚠️ **To use with Swift 4.x please ensure you are using >= 4.0.0** ⚠️ +#### ⚠️ **To use with Swift 5.x please ensure you are using >= 5.0.0** ⚠️ + +## Contents + +- [Requirements](#requirements) +- [Migration Guides](#migration-guides) +- [Communication](#communication) +- [Installation](#installation) +- [Usage](#usage) +- [Credits](#credits) +- [License](#license) + +## Requirements + +- iOS 10.0+ / Mac OS X 10.12+ / tvOS 10.0+ +- Xcode 10.0+ +- Swift 4.0+ + +## Communication + +- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit). (Tag 'snapkit') +- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit). +- If you **found a bug**, open an issue. +- If you **have a feature request**, open an issue. +- If you **want to contribute**, submit a pull request. + + +## Installation + +### CocoaPods + +[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: + +```bash +$ gem install cocoapods +``` + +> CocoaPods 1.1.0+ is required to build SnapKit 4.0.0+. + +To integrate SnapKit into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```ruby +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '10.0' +use_frameworks! + +target '' do + pod 'SnapKit', '~> 5.0.0' +end +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](http://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate SnapKit into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "SnapKit/SnapKit" ~> 5.0.0 +``` + +Run `carthage update` to build the framework and drag the built `SnapKit.framework` into your Xcode project. + +### Manually + +If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually. + +--- + +## Usage + +### Quick Start + +```swift +import SnapKit + +class MyViewController: UIViewController { + + lazy var box = UIView() + + override func viewDidLoad() { + super.viewDidLoad() + + self.view.addSubview(box) + box.snp.makeConstraints { (make) -> Void in + make.width.height.equalTo(50) + make.center.equalTo(self.view) + } + } + +} +``` + +### Playground +You can try SnapKit in Playground. + +**Note:** + +> To try SnapKit in playground, open `SnapKit.xcworkspace` and build SnapKit.framework for any simulator first. + +### Resources + +- [Documentation](http://snapkit.io/docs/) +- [F.A.Q.](http://snapkit.io/faq/) + +## Credits + +- Robert Payne ([@robertjpayne](https://twitter.com/robertjpayne)) +- Many other contributors + +## License + +SnapKit is released under the MIT license. See LICENSE for details. diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Constraint.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Constraint.swift new file mode 100644 index 0000000..390629e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Constraint.swift @@ -0,0 +1,341 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + +public final class Constraint { + + internal let sourceLocation: (String, UInt) + internal let label: String? + + private let from: ConstraintItem + private let to: ConstraintItem + private let relation: ConstraintRelation + private let multiplier: ConstraintMultiplierTarget + private var constant: ConstraintConstantTarget { + didSet { + self.updateConstantAndPriorityIfNeeded() + } + } + private var priority: ConstraintPriorityTarget { + didSet { + self.updateConstantAndPriorityIfNeeded() + } + } + public var layoutConstraints: [LayoutConstraint] + + public var isActive: Bool { + set { + if newValue { + activate() + } + else { + deactivate() + } + } + + get { + for layoutConstraint in self.layoutConstraints { + if layoutConstraint.isActive { + return true + } + } + return false + } + } + + // MARK: Initialization + + internal init(from: ConstraintItem, + to: ConstraintItem, + relation: ConstraintRelation, + sourceLocation: (String, UInt), + label: String?, + multiplier: ConstraintMultiplierTarget, + constant: ConstraintConstantTarget, + priority: ConstraintPriorityTarget) { + self.from = from + self.to = to + self.relation = relation + self.sourceLocation = sourceLocation + self.label = label + self.multiplier = multiplier + self.constant = constant + self.priority = priority + self.layoutConstraints = [] + + // get attributes + let layoutFromAttributes = self.from.attributes.layoutAttributes + let layoutToAttributes = self.to.attributes.layoutAttributes + + // get layout from + let layoutFrom = self.from.layoutConstraintItem! + + // get relation + let layoutRelation = self.relation.layoutRelation + + for layoutFromAttribute in layoutFromAttributes { + // get layout to attribute + let layoutToAttribute: LayoutAttribute + #if os(iOS) || os(tvOS) + if layoutToAttributes.count > 0 { + if self.from.attributes == .edges && self.to.attributes == .margins { + switch layoutFromAttribute { + case .left: + layoutToAttribute = .leftMargin + case .right: + layoutToAttribute = .rightMargin + case .top: + layoutToAttribute = .topMargin + case .bottom: + layoutToAttribute = .bottomMargin + default: + fatalError() + } + } else if self.from.attributes == .margins && self.to.attributes == .edges { + switch layoutFromAttribute { + case .leftMargin: + layoutToAttribute = .left + case .rightMargin: + layoutToAttribute = .right + case .topMargin: + layoutToAttribute = .top + case .bottomMargin: + layoutToAttribute = .bottom + default: + fatalError() + } + } else if self.from.attributes == .directionalEdges && self.to.attributes == .directionalMargins { + switch layoutFromAttribute { + case .leading: + layoutToAttribute = .leadingMargin + case .trailing: + layoutToAttribute = .trailingMargin + case .top: + layoutToAttribute = .topMargin + case .bottom: + layoutToAttribute = .bottomMargin + default: + fatalError() + } + } else if self.from.attributes == .directionalMargins && self.to.attributes == .directionalEdges { + switch layoutFromAttribute { + case .leadingMargin: + layoutToAttribute = .leading + case .trailingMargin: + layoutToAttribute = .trailing + case .topMargin: + layoutToAttribute = .top + case .bottomMargin: + layoutToAttribute = .bottom + default: + fatalError() + } + } else if self.from.attributes == self.to.attributes { + layoutToAttribute = layoutFromAttribute + } else { + layoutToAttribute = layoutToAttributes[0] + } + } else { + if self.to.target == nil && (layoutFromAttribute == .centerX || layoutFromAttribute == .centerY) { + layoutToAttribute = layoutFromAttribute == .centerX ? .left : .top + } else { + layoutToAttribute = layoutFromAttribute + } + } + #else + if self.from.attributes == self.to.attributes { + layoutToAttribute = layoutFromAttribute + } else if layoutToAttributes.count > 0 { + layoutToAttribute = layoutToAttributes[0] + } else { + layoutToAttribute = layoutFromAttribute + } + #endif + + // get layout constant + let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute) + + // get layout to + var layoutTo: AnyObject? = self.to.target + + // use superview if possible + if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height { + layoutTo = layoutFrom.superview + } + + // create layout constraint + let layoutConstraint = LayoutConstraint( + item: layoutFrom, + attribute: layoutFromAttribute, + relatedBy: layoutRelation, + toItem: layoutTo, + attribute: layoutToAttribute, + multiplier: self.multiplier.constraintMultiplierTargetValue, + constant: layoutConstant + ) + + // set label + layoutConstraint.label = self.label + + // set priority + layoutConstraint.priority = LayoutPriority(rawValue: self.priority.constraintPriorityTargetValue) + + // set constraint + layoutConstraint.constraint = self + + // append + self.layoutConstraints.append(layoutConstraint) + } + } + + // MARK: Public + + @available(*, deprecated, message:"Use activate().") + public func install() { + self.activate() + } + + @available(*, deprecated, message:"Use deactivate().") + public func uninstall() { + self.deactivate() + } + + public func activate() { + self.activateIfNeeded() + } + + public func deactivate() { + self.deactivateIfNeeded() + } + + @discardableResult + public func update(offset: ConstraintOffsetTarget) -> Constraint { + self.constant = offset.constraintOffsetTargetValue + return self + } + + @discardableResult + public func update(inset: ConstraintInsetTarget) -> Constraint { + self.constant = inset.constraintInsetTargetValue + return self + } + + #if os(iOS) || os(tvOS) + @discardableResult + @available(iOS 11.0, tvOS 11.0, *) + public func update(inset: ConstraintDirectionalInsetTarget) -> Constraint { + self.constant = inset.constraintDirectionalInsetTargetValue + return self + } + #endif + + @discardableResult + public func update(priority: ConstraintPriorityTarget) -> Constraint { + self.priority = priority.constraintPriorityTargetValue + return self + } + + @discardableResult + public func update(priority: ConstraintPriority) -> Constraint { + self.priority = priority.value + return self + } + + @available(*, deprecated, message:"Use update(offset: ConstraintOffsetTarget) instead.") + public func updateOffset(amount: ConstraintOffsetTarget) -> Void { self.update(offset: amount) } + + @available(*, deprecated, message:"Use update(inset: ConstraintInsetTarget) instead.") + public func updateInsets(amount: ConstraintInsetTarget) -> Void { self.update(inset: amount) } + + @available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.") + public func updatePriority(amount: ConstraintPriorityTarget) -> Void { self.update(priority: amount) } + + @available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.") + public func updatePriorityRequired() -> Void {} + + @available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.") + public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") } + + @available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.") + public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") } + + @available(*, deprecated, message:"Use update(priority: ConstraintPriorityTarget) instead.") + public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") } + + // MARK: Internal + + internal func updateConstantAndPriorityIfNeeded() { + for layoutConstraint in self.layoutConstraints { + let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute + layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute) + + let requiredPriority = ConstraintPriority.required.value + if (layoutConstraint.priority.rawValue < requiredPriority), (self.priority.constraintPriorityTargetValue != requiredPriority) { + layoutConstraint.priority = LayoutPriority(rawValue: self.priority.constraintPriorityTargetValue) + } + } + } + + internal func activateIfNeeded(updatingExisting: Bool = false) { + guard let item = self.from.layoutConstraintItem else { + print("WARNING: SnapKit failed to get from item from constraint. Activate will be a no-op.") + return + } + let layoutConstraints = self.layoutConstraints + + if updatingExisting { + var existingLayoutConstraints: [LayoutConstraint] = [] + for constraint in item.constraints { + existingLayoutConstraints += constraint.layoutConstraints + } + + for layoutConstraint in layoutConstraints { + let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint } + guard let updateLayoutConstraint = existingLayoutConstraint else { + fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)") + } + + let updateLayoutAttribute = (updateLayoutConstraint.secondAttribute == .notAnAttribute) ? updateLayoutConstraint.firstAttribute : updateLayoutConstraint.secondAttribute + updateLayoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: updateLayoutAttribute) + } + } else { + NSLayoutConstraint.activate(layoutConstraints) + item.add(constraints: [self]) + } + } + + internal func deactivateIfNeeded() { + guard let item = self.from.layoutConstraintItem else { + print("WARNING: SnapKit failed to get from item from constraint. Deactivate will be a no-op.") + return + } + let layoutConstraints = self.layoutConstraints + NSLayoutConstraint.deactivate(layoutConstraints) + item.remove(constraints: [self]) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintAttributes.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintAttributes.swift new file mode 100644 index 0000000..2f0fbe9 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintAttributes.swift @@ -0,0 +1,199 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +internal struct ConstraintAttributes : OptionSet, ExpressibleByIntegerLiteral { + + typealias IntegerLiteralType = UInt + + internal init(rawValue: UInt) { + self.rawValue = rawValue + } + internal init(_ rawValue: UInt) { + self.init(rawValue: rawValue) + } + internal init(nilLiteral: ()) { + self.rawValue = 0 + } + internal init(integerLiteral rawValue: IntegerLiteralType) { + self.init(rawValue: rawValue) + } + + internal private(set) var rawValue: UInt + internal static var allZeros: ConstraintAttributes { return 0 } + internal static func convertFromNilLiteral() -> ConstraintAttributes { return 0 } + internal var boolValue: Bool { return self.rawValue != 0 } + + internal func toRaw() -> UInt { return self.rawValue } + internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) } + internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) } + + // normal + + internal static var none: ConstraintAttributes { return 0 } + internal static var left: ConstraintAttributes { return 1 } + internal static var top: ConstraintAttributes { return 2 } + internal static var right: ConstraintAttributes { return 4 } + internal static var bottom: ConstraintAttributes { return 8 } + internal static var leading: ConstraintAttributes { return 16 } + internal static var trailing: ConstraintAttributes { return 32 } + internal static var width: ConstraintAttributes { return 64 } + internal static var height: ConstraintAttributes { return 128 } + internal static var centerX: ConstraintAttributes { return 256 } + internal static var centerY: ConstraintAttributes { return 512 } + internal static var lastBaseline: ConstraintAttributes { return 1024 } + + @available(iOS 8.0, OSX 10.11, *) + internal static var firstBaseline: ConstraintAttributes { return 2048 } + + @available(iOS 8.0, *) + internal static var leftMargin: ConstraintAttributes { return 4096 } + + @available(iOS 8.0, *) + internal static var rightMargin: ConstraintAttributes { return 8192 } + + @available(iOS 8.0, *) + internal static var topMargin: ConstraintAttributes { return 16384 } + + @available(iOS 8.0, *) + internal static var bottomMargin: ConstraintAttributes { return 32768 } + + @available(iOS 8.0, *) + internal static var leadingMargin: ConstraintAttributes { return 65536 } + + @available(iOS 8.0, *) + internal static var trailingMargin: ConstraintAttributes { return 131072 } + + @available(iOS 8.0, *) + internal static var centerXWithinMargins: ConstraintAttributes { return 262144 } + + @available(iOS 8.0, *) + internal static var centerYWithinMargins: ConstraintAttributes { return 524288 } + + // aggregates + + internal static var edges: ConstraintAttributes { return 15 } + internal static var directionalEdges: ConstraintAttributes { return 58 } + internal static var size: ConstraintAttributes { return 192 } + internal static var center: ConstraintAttributes { return 768 } + + @available(iOS 8.0, *) + internal static var margins: ConstraintAttributes { return 61440 } + + @available(iOS 8.0, *) + internal static var directionalMargins: ConstraintAttributes { return 245760 } + + @available(iOS 8.0, *) + internal static var centerWithinMargins: ConstraintAttributes { return 786432 } + + internal var layoutAttributes:[LayoutAttribute] { + var attrs = [LayoutAttribute]() + if (self.contains(ConstraintAttributes.left)) { + attrs.append(.left) + } + if (self.contains(ConstraintAttributes.top)) { + attrs.append(.top) + } + if (self.contains(ConstraintAttributes.right)) { + attrs.append(.right) + } + if (self.contains(ConstraintAttributes.bottom)) { + attrs.append(.bottom) + } + if (self.contains(ConstraintAttributes.leading)) { + attrs.append(.leading) + } + if (self.contains(ConstraintAttributes.trailing)) { + attrs.append(.trailing) + } + if (self.contains(ConstraintAttributes.width)) { + attrs.append(.width) + } + if (self.contains(ConstraintAttributes.height)) { + attrs.append(.height) + } + if (self.contains(ConstraintAttributes.centerX)) { + attrs.append(.centerX) + } + if (self.contains(ConstraintAttributes.centerY)) { + attrs.append(.centerY) + } + if (self.contains(ConstraintAttributes.lastBaseline)) { + attrs.append(.lastBaseline) + } + + #if os(iOS) || os(tvOS) + if (self.contains(ConstraintAttributes.firstBaseline)) { + attrs.append(.firstBaseline) + } + if (self.contains(ConstraintAttributes.leftMargin)) { + attrs.append(.leftMargin) + } + if (self.contains(ConstraintAttributes.rightMargin)) { + attrs.append(.rightMargin) + } + if (self.contains(ConstraintAttributes.topMargin)) { + attrs.append(.topMargin) + } + if (self.contains(ConstraintAttributes.bottomMargin)) { + attrs.append(.bottomMargin) + } + if (self.contains(ConstraintAttributes.leadingMargin)) { + attrs.append(.leadingMargin) + } + if (self.contains(ConstraintAttributes.trailingMargin)) { + attrs.append(.trailingMargin) + } + if (self.contains(ConstraintAttributes.centerXWithinMargins)) { + attrs.append(.centerXWithinMargins) + } + if (self.contains(ConstraintAttributes.centerYWithinMargins)) { + attrs.append(.centerYWithinMargins) + } + #endif + + return attrs + } +} + +internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes { + return left.union(right) +} + +internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) { + left.formUnion(right) +} + +internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) { + left.subtract(right) +} + +internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool { + return left.rawValue == right.rawValue +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConfig.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConfig.swift new file mode 100644 index 0000000..2746b7d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConfig.swift @@ -0,0 +1,37 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit + public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection +#else + import AppKit + public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection +#endif + + +public struct ConstraintConfig { + + public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConstantTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConstantTarget.swift new file mode 100644 index 0000000..7f54907 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintConstantTarget.swift @@ -0,0 +1,213 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintConstantTarget { +} + +extension CGPoint: ConstraintConstantTarget { +} + +extension CGSize: ConstraintConstantTarget { +} + +extension ConstraintInsets: ConstraintConstantTarget { +} + +#if os(iOS) || os(tvOS) +@available(iOS 11.0, tvOS 11.0, *) +extension ConstraintDirectionalInsets: ConstraintConstantTarget { +} +#endif + +extension ConstraintConstantTarget { + + internal func constraintConstantTargetValueFor(layoutAttribute: LayoutAttribute) -> CGFloat { + if let value = self as? CGFloat { + return value + } + + if let value = self as? Float { + return CGFloat(value) + } + + if let value = self as? Double { + return CGFloat(value) + } + + if let value = self as? Int { + return CGFloat(value) + } + + if let value = self as? UInt { + return CGFloat(value) + } + + if let value = self as? CGSize { + if layoutAttribute == .width { + return value.width + } else if layoutAttribute == .height { + return value.height + } else { + return 0.0 + } + } + + if let value = self as? CGPoint { + #if os(iOS) || os(tvOS) + switch layoutAttribute { + case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins: + return value.x + case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline: + return value.y + case .width, .height, .notAnAttribute: + return 0.0 + #if swift(>=5.0) + @unknown default: + return 0.0 + #endif + } + #else + switch layoutAttribute { + case .left, .right, .leading, .trailing, .centerX: + return value.x + case .top, .bottom, .centerY, .lastBaseline, .firstBaseline: + return value.y + case .width, .height, .notAnAttribute: + return 0.0 + #if swift(>=5.0) + @unknown default: + return 0.0 + #endif + } + #endif + } + + if let value = self as? ConstraintInsets { + #if os(iOS) || os(tvOS) + switch layoutAttribute { + case .left, .leftMargin: + return value.left + case .top, .topMargin, .firstBaseline: + return value.top + case .right, .rightMargin: + return -value.right + case .bottom, .bottomMargin, .lastBaseline: + return -value.bottom + case .leading, .leadingMargin: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right + case .trailing, .trailingMargin: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left + case .centerX, .centerXWithinMargins: + return (value.left - value.right) / 2 + case .centerY, .centerYWithinMargins: + return (value.top - value.bottom) / 2 + case .width: + return -(value.left + value.right) + case .height: + return -(value.top + value.bottom) + case .notAnAttribute: + return 0.0 + #if swift(>=5.0) + @unknown default: + return 0.0 + #endif + } + #else + switch layoutAttribute { + case .left: + return value.left + case .top, .firstBaseline: + return value.top + case .right: + return -value.right + case .bottom, .lastBaseline: + return -value.bottom + case .leading: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right + case .trailing: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left + case .centerX: + return (value.left - value.right) / 2 + case .centerY: + return (value.top - value.bottom) / 2 + case .width: + return -(value.left + value.right) + case .height: + return -(value.top + value.bottom) + case .notAnAttribute: + return 0.0 + #if swift(>=5.0) + @unknown default: + return 0.0 + #endif + } + #endif + } + + #if os(iOS) || os(tvOS) + if #available(iOS 11.0, tvOS 11.0, *), let value = self as? ConstraintDirectionalInsets { + switch layoutAttribute { + case .left, .leftMargin: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.leading : value.trailing + case .top, .topMargin, .firstBaseline: + return value.top + case .right, .rightMargin: + return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.trailing : -value.leading + case .bottom, .bottomMargin, .lastBaseline: + return -value.bottom + case .leading, .leadingMargin: + return value.leading + case .trailing, .trailingMargin: + return -value.trailing + case .centerX, .centerXWithinMargins: + return (value.leading - value.trailing) / 2 + case .centerY, .centerYWithinMargins: + return (value.top - value.bottom) / 2 + case .width: + return -(value.leading + value.trailing) + case .height: + return -(value.top + value.bottom) + case .notAnAttribute: + return 0.0 + #if swift(>=5.0) + @unknown default: + return 0.0 + #else + default: + return 0.0 + #endif + } + } + #endif + + return 0.0 + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDSL.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDSL.swift new file mode 100644 index 0000000..ecc5173 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDSL.swift @@ -0,0 +1,194 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintDSL { + + var target: AnyObject? { get } + + func setLabel(_ value: String?) + func label() -> String? + +} +extension ConstraintDSL { + + public func setLabel(_ value: String?) { + objc_setAssociatedObject(self.target as Any, &labelKey, value, .OBJC_ASSOCIATION_COPY_NONATOMIC) + } + public func label() -> String? { + return objc_getAssociatedObject(self.target as Any, &labelKey) as? String + } + +} +private var labelKey: UInt8 = 0 + + +public protocol ConstraintBasicAttributesDSL : ConstraintDSL { +} +extension ConstraintBasicAttributesDSL { + + // MARK: Basics + + public var left: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left) + } + + public var top: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top) + } + + public var right: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right) + } + + public var bottom: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom) + } + + public var leading: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading) + } + + public var trailing: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing) + } + + public var width: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width) + } + + public var height: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height) + } + + public var centerX: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX) + } + + public var centerY: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY) + } + + public var edges: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges) + } + + public var directionalEdges: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalEdges) + } + + public var size: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size) + } + + public var center: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center) + } + +} + +public protocol ConstraintAttributesDSL : ConstraintBasicAttributesDSL { +} +extension ConstraintAttributesDSL { + + // MARK: Baselines + + @available(*, deprecated, message:"Use .lastBaseline instead") + public var baseline: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline) + } + + @available(iOS 8.0, OSX 10.11, *) + public var lastBaseline: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline) + } + + @available(iOS 8.0, OSX 10.11, *) + public var firstBaseline: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline) + } + + // MARK: Margins + + @available(iOS 8.0, *) + public var leftMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin) + } + + @available(iOS 8.0, *) + public var topMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin) + } + + @available(iOS 8.0, *) + public var rightMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin) + } + + @available(iOS 8.0, *) + public var bottomMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin) + } + + @available(iOS 8.0, *) + public var leadingMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin) + } + + @available(iOS 8.0, *) + public var trailingMargin: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin) + } + + @available(iOS 8.0, *) + public var centerXWithinMargins: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins) + } + + @available(iOS 8.0, *) + public var centerYWithinMargins: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins) + } + + @available(iOS 8.0, *) + public var margins: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins) + } + + @available(iOS 8.0, *) + public var directionalMargins: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.directionalMargins) + } + + @available(iOS 8.0, *) + public var centerWithinMargins: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins) + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDescription.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDescription.swift new file mode 100644 index 0000000..3521f9f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDescription.swift @@ -0,0 +1,69 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintDescription { + + internal let item: LayoutConstraintItem + internal var attributes: ConstraintAttributes + internal var relation: ConstraintRelation? = nil + internal var sourceLocation: (String, UInt)? = nil + internal var label: String? = nil + internal var related: ConstraintItem? = nil + internal var multiplier: ConstraintMultiplierTarget = 1.0 + internal var constant: ConstraintConstantTarget = 0.0 + internal var priority: ConstraintPriorityTarget = 1000.0 + internal lazy var constraint: Constraint? = { + guard let relation = self.relation, + let related = self.related, + let sourceLocation = self.sourceLocation else { + return nil + } + let from = ConstraintItem(target: self.item, attributes: self.attributes) + + return Constraint( + from: from, + to: related, + relation: relation, + sourceLocation: sourceLocation, + label: self.label, + multiplier: self.multiplier, + constant: self.constant, + priority: self.priority + ) + }() + + // MARK: Initialization + + internal init(item: LayoutConstraintItem, attributes: ConstraintAttributes) { + self.item = item + self.attributes = attributes + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsetTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsetTarget.swift new file mode 100644 index 0000000..955aec3 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsetTarget.swift @@ -0,0 +1,49 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) +import UIKit +#else +import AppKit +#endif + +#if os(iOS) || os(tvOS) +public protocol ConstraintDirectionalInsetTarget: ConstraintConstantTarget { +} + +@available(iOS 11.0, tvOS 11.0, *) +extension ConstraintDirectionalInsets: ConstraintDirectionalInsetTarget { +} + +extension ConstraintDirectionalInsetTarget { + + @available(iOS 11.0, tvOS 11.0, *) + internal var constraintDirectionalInsetTargetValue: ConstraintDirectionalInsets { + if let amount = self as? ConstraintDirectionalInsets { + return amount + } else { + return ConstraintDirectionalInsets(top: 0, leading: 0, bottom: 0, trailing: 0) + } + } +} +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsets.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsets.swift new file mode 100644 index 0000000..ada8ed5 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintDirectionalInsets.swift @@ -0,0 +1,34 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +#if os(iOS) || os(tvOS) + @available(iOS 11.0, tvOS 11.0, *) + public typealias ConstraintDirectionalInsets = NSDirectionalEdgeInsets +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsetTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsetTarget.swift new file mode 100644 index 0000000..ba8a0f3 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsetTarget.swift @@ -0,0 +1,72 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintInsetTarget: ConstraintConstantTarget { +} + +extension Int: ConstraintInsetTarget { +} + +extension UInt: ConstraintInsetTarget { +} + +extension Float: ConstraintInsetTarget { +} + +extension Double: ConstraintInsetTarget { +} + +extension CGFloat: ConstraintInsetTarget { +} + +extension ConstraintInsets: ConstraintInsetTarget { +} + +extension ConstraintInsetTarget { + + internal var constraintInsetTargetValue: ConstraintInsets { + if let amount = self as? ConstraintInsets { + return amount + } else if let amount = self as? Float { + return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) + } else if let amount = self as? Double { + return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) + } else if let amount = self as? CGFloat { + return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount) + } else if let amount = self as? Int { + return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) + } else if let amount = self as? UInt { + return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) + } else { + return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0) + } + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsets.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsets.swift new file mode 100644 index 0000000..738ca05 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintInsets.swift @@ -0,0 +1,35 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +#if os(iOS) || os(tvOS) + public typealias ConstraintInsets = UIEdgeInsets +#else + public typealias ConstraintInsets = NSEdgeInsets +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintItem.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintItem.swift new file mode 100644 index 0000000..a342c1d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintItem.swift @@ -0,0 +1,61 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public final class ConstraintItem { + + internal weak var target: AnyObject? + internal let attributes: ConstraintAttributes + + internal init(target: AnyObject?, attributes: ConstraintAttributes) { + self.target = target + self.attributes = attributes + } + + internal var layoutConstraintItem: LayoutConstraintItem? { + return self.target as? LayoutConstraintItem + } + +} + +public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool { + // pointer equality + guard lhs !== rhs else { + return true + } + + // must both have valid targets and identical attributes + guard let target1 = lhs.target, + let target2 = rhs.target, + target1 === target2 && lhs.attributes == rhs.attributes else { + return false + } + + return true +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide+Extensions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide+Extensions.swift new file mode 100644 index 0000000..d429e0c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide+Extensions.swift @@ -0,0 +1,36 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#endif + + +@available(iOS 9.0, OSX 10.11, *) +public extension ConstraintLayoutGuide { + + var snp: ConstraintLayoutGuideDSL { + return ConstraintLayoutGuideDSL(guide: self) + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide.swift new file mode 100644 index 0000000..e3e50c8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuide.swift @@ -0,0 +1,37 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +#if os(iOS) || os(tvOS) + @available(iOS 9.0, *) + public typealias ConstraintLayoutGuide = UILayoutGuide +#else + @available(OSX 10.11, *) + public typealias ConstraintLayoutGuide = NSLayoutGuide +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuideDSL.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuideDSL.swift new file mode 100644 index 0000000..0007819 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutGuideDSL.swift @@ -0,0 +1,66 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +@available(iOS 9.0, OSX 10.11, *) +public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL { + + @discardableResult + public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { + return ConstraintMaker.prepareConstraints(item: self.guide, closure: closure) + } + + public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.makeConstraints(item: self.guide, closure: closure) + } + + public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.remakeConstraints(item: self.guide, closure: closure) + } + + public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.updateConstraints(item: self.guide, closure: closure) + } + + public func removeConstraints() { + ConstraintMaker.removeConstraints(item: self.guide) + } + + public var target: AnyObject? { + return self.guide + } + + internal let guide: ConstraintLayoutGuide + + internal init(guide: ConstraintLayoutGuide) { + self.guide = guide + + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupport.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupport.swift new file mode 100644 index 0000000..e92e9fb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupport.swift @@ -0,0 +1,36 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +#if os(iOS) || os(tvOS) + @available(iOS 8.0, *) + public typealias ConstraintLayoutSupport = UILayoutSupport +#else + public class ConstraintLayoutSupport {} +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupportDSL.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupportDSL.swift new file mode 100644 index 0000000..5d6ae89 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintLayoutSupportDSL.swift @@ -0,0 +1,56 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +@available(iOS 8.0, *) +public struct ConstraintLayoutSupportDSL: ConstraintDSL { + + public var target: AnyObject? { + return self.support + } + + internal let support: ConstraintLayoutSupport + + internal init(support: ConstraintLayoutSupport) { + self.support = support + + } + + public var top: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top) + } + + public var bottom: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom) + } + + public var height: ConstraintItem { + return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMaker.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMaker.swift new file mode 100644 index 0000000..38f4d31 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMaker.swift @@ -0,0 +1,212 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + +public class ConstraintMaker { + + public var left: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.left) + } + + public var top: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.top) + } + + public var bottom: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.bottom) + } + + public var right: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.right) + } + + public var leading: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.leading) + } + + public var trailing: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.trailing) + } + + public var width: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.width) + } + + public var height: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.height) + } + + public var centerX: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerX) + } + + public var centerY: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerY) + } + + @available(*, deprecated, message:"Use lastBaseline instead") + public var baseline: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.lastBaseline) + } + + public var lastBaseline: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.lastBaseline) + } + + @available(iOS 8.0, OSX 10.11, *) + public var firstBaseline: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.firstBaseline) + } + + @available(iOS 8.0, *) + public var leftMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.leftMargin) + } + + @available(iOS 8.0, *) + public var rightMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.rightMargin) + } + + @available(iOS 8.0, *) + public var topMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.topMargin) + } + + @available(iOS 8.0, *) + public var bottomMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.bottomMargin) + } + + @available(iOS 8.0, *) + public var leadingMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.leadingMargin) + } + + @available(iOS 8.0, *) + public var trailingMargin: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.trailingMargin) + } + + @available(iOS 8.0, *) + public var centerXWithinMargins: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerXWithinMargins) + } + + @available(iOS 8.0, *) + public var centerYWithinMargins: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerYWithinMargins) + } + + public var edges: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.edges) + } + public var directionalEdges: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.directionalEdges) + } + public var size: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.size) + } + public var center: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.center) + } + + @available(iOS 8.0, *) + public var margins: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.margins) + } + + @available(iOS 8.0, *) + public var directionalMargins: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.directionalMargins) + } + + @available(iOS 8.0, *) + public var centerWithinMargins: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerWithinMargins) + } + + private let item: LayoutConstraintItem + private var descriptions = [ConstraintDescription]() + + internal init(item: LayoutConstraintItem) { + self.item = item + self.item.prepare() + } + + internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable { + let description = ConstraintDescription(item: self.item, attributes: attributes) + self.descriptions.append(description) + return ConstraintMakerExtendable(description) + } + + internal static func prepareConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { + let maker = ConstraintMaker(item: item) + closure(maker) + var constraints: [Constraint] = [] + for description in maker.descriptions { + guard let constraint = description.constraint else { + continue + } + constraints.append(constraint) + } + return constraints + } + + internal static func makeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) { + let constraints = prepareConstraints(item: item, closure: closure) + for constraint in constraints { + constraint.activateIfNeeded(updatingExisting: false) + } + } + + internal static func remakeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) { + self.removeConstraints(item: item) + self.makeConstraints(item: item, closure: closure) + } + + internal static func updateConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) { + guard item.constraints.count > 0 else { + self.makeConstraints(item: item, closure: closure) + return + } + + let constraints = prepareConstraints(item: item, closure: closure) + for constraint in constraints { + constraint.activateIfNeeded(updatingExisting: true) + } + } + + internal static func removeConstraints(item: LayoutConstraintItem) { + let constraints = item.constraints + for constraint in constraints { + constraint.deactivateIfNeeded() + } + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerEditable.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerEditable.swift new file mode 100644 index 0000000..f768a17 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerEditable.swift @@ -0,0 +1,64 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintMakerEditable: ConstraintMakerPriortizable { + + @discardableResult + public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { + self.description.multiplier = amount + return self + } + + @discardableResult + public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { + return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue) + } + + @discardableResult + public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable { + self.description.constant = amount.constraintOffsetTargetValue + return self + } + + @discardableResult + public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable { + self.description.constant = amount.constraintInsetTargetValue + return self + } + + #if os(iOS) || os(tvOS) + @discardableResult + @available(iOS 11.0, tvOS 11.0, *) + public func inset(_ amount: ConstraintDirectionalInsetTarget) -> ConstraintMakerEditable { + self.description.constant = amount.constraintDirectionalInsetTargetValue + return self + } + #endif +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerExtendable.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerExtendable.swift new file mode 100644 index 0000000..ce47169 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerExtendable.swift @@ -0,0 +1,179 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintMakerExtendable: ConstraintMakerRelatable { + + public var left: ConstraintMakerExtendable { + self.description.attributes += .left + return self + } + + public var top: ConstraintMakerExtendable { + self.description.attributes += .top + return self + } + + public var bottom: ConstraintMakerExtendable { + self.description.attributes += .bottom + return self + } + + public var right: ConstraintMakerExtendable { + self.description.attributes += .right + return self + } + + public var leading: ConstraintMakerExtendable { + self.description.attributes += .leading + return self + } + + public var trailing: ConstraintMakerExtendable { + self.description.attributes += .trailing + return self + } + + public var width: ConstraintMakerExtendable { + self.description.attributes += .width + return self + } + + public var height: ConstraintMakerExtendable { + self.description.attributes += .height + return self + } + + public var centerX: ConstraintMakerExtendable { + self.description.attributes += .centerX + return self + } + + public var centerY: ConstraintMakerExtendable { + self.description.attributes += .centerY + return self + } + + @available(*, deprecated, message:"Use lastBaseline instead") + public var baseline: ConstraintMakerExtendable { + self.description.attributes += .lastBaseline + return self + } + + public var lastBaseline: ConstraintMakerExtendable { + self.description.attributes += .lastBaseline + return self + } + + @available(iOS 8.0, OSX 10.11, *) + public var firstBaseline: ConstraintMakerExtendable { + self.description.attributes += .firstBaseline + return self + } + + @available(iOS 8.0, *) + public var leftMargin: ConstraintMakerExtendable { + self.description.attributes += .leftMargin + return self + } + + @available(iOS 8.0, *) + public var rightMargin: ConstraintMakerExtendable { + self.description.attributes += .rightMargin + return self + } + + @available(iOS 8.0, *) + public var topMargin: ConstraintMakerExtendable { + self.description.attributes += .topMargin + return self + } + + @available(iOS 8.0, *) + public var bottomMargin: ConstraintMakerExtendable { + self.description.attributes += .bottomMargin + return self + } + + @available(iOS 8.0, *) + public var leadingMargin: ConstraintMakerExtendable { + self.description.attributes += .leadingMargin + return self + } + + @available(iOS 8.0, *) + public var trailingMargin: ConstraintMakerExtendable { + self.description.attributes += .trailingMargin + return self + } + + @available(iOS 8.0, *) + public var centerXWithinMargins: ConstraintMakerExtendable { + self.description.attributes += .centerXWithinMargins + return self + } + + @available(iOS 8.0, *) + public var centerYWithinMargins: ConstraintMakerExtendable { + self.description.attributes += .centerYWithinMargins + return self + } + + public var edges: ConstraintMakerExtendable { + self.description.attributes += .edges + return self + } + public var directionalEdges: ConstraintMakerExtendable { + self.description.attributes += .directionalEdges + return self + } + public var size: ConstraintMakerExtendable { + self.description.attributes += .size + return self + } + + @available(iOS 8.0, *) + public var margins: ConstraintMakerExtendable { + self.description.attributes += .margins + return self + } + + @available(iOS 8.0, *) + public var directionalMargins: ConstraintMakerExtendable { + self.description.attributes += .directionalMargins + return self + } + + @available(iOS 8.0, *) + public var centerWithinMargins: ConstraintMakerExtendable { + self.description.attributes += .centerWithinMargins + return self + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerFinalizable.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerFinalizable.swift new file mode 100644 index 0000000..4e1379e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerFinalizable.swift @@ -0,0 +1,49 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintMakerFinalizable { + + internal let description: ConstraintDescription + + internal init(_ description: ConstraintDescription) { + self.description = description + } + + @discardableResult + public func labeled(_ label: String) -> ConstraintMakerFinalizable { + self.description.label = label + return self + } + + public var constraint: Constraint { + return self.description.constraint! + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerPriortizable.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerPriortizable.swift new file mode 100644 index 0000000..e0d452d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerPriortizable.swift @@ -0,0 +1,68 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintMakerPriortizable: ConstraintMakerFinalizable { + + @discardableResult + public func priority(_ amount: ConstraintPriority) -> ConstraintMakerFinalizable { + self.description.priority = amount.value + return self + } + + @discardableResult + public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable { + self.description.priority = amount + return self + } + + @available(*, deprecated, message:"Use priority(.required) instead.") + @discardableResult + public func priorityRequired() -> ConstraintMakerFinalizable { + return self.priority(.required) + } + + @available(*, deprecated, message:"Use priority(.high) instead.") + @discardableResult + public func priorityHigh() -> ConstraintMakerFinalizable { + return self.priority(.high) + } + + @available(*, deprecated, message:"Use priority(.medium) instead.") + @discardableResult + public func priorityMedium() -> ConstraintMakerFinalizable { + return self.priority(.medium) + } + + @available(*, deprecated, message:"Use priority(.low) instead.") + @discardableResult + public func priorityLow() -> ConstraintMakerFinalizable { + return self.priority(.low) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerRelatable.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerRelatable.swift new file mode 100644 index 0000000..7889532 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMakerRelatable.swift @@ -0,0 +1,115 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class ConstraintMakerRelatable { + + internal let description: ConstraintDescription + + internal init(_ description: ConstraintDescription) { + self.description = description + } + + internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable { + let related: ConstraintItem + let constant: ConstraintConstantTarget + + if let other = other as? ConstraintItem { + guard other.attributes == ConstraintAttributes.none || + other.attributes.layoutAttributes.count <= 1 || + other.attributes.layoutAttributes == self.description.attributes.layoutAttributes || + other.attributes == .edges && self.description.attributes == .margins || + other.attributes == .margins && self.description.attributes == .edges || + other.attributes == .directionalEdges && self.description.attributes == .directionalMargins || + other.attributes == .directionalMargins && self.description.attributes == .directionalEdges else { + fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))"); + } + + related = other + constant = 0.0 + } else if let other = other as? ConstraintView { + related = ConstraintItem(target: other, attributes: ConstraintAttributes.none) + constant = 0.0 + } else if let other = other as? ConstraintConstantTarget { + related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none) + constant = other + } else if #available(iOS 9.0, OSX 10.11, *), let other = other as? ConstraintLayoutGuide { + related = ConstraintItem(target: other, attributes: ConstraintAttributes.none) + constant = 0.0 + } else { + fatalError("Invalid constraint. (\(file), \(line))") + } + + let editable = ConstraintMakerEditable(self.description) + editable.description.sourceLocation = (file, line) + editable.description.relation = relation + editable.description.related = related + editable.description.constant = constant + return editable + } + + @discardableResult + public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { + return self.relatedTo(other, relation: .equal, file: file, line: line) + } + + @discardableResult + public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { + guard let other = self.description.item.superview else { + fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.") + } + return self.relatedTo(other, relation: .equal, file: file, line: line) + } + + @discardableResult + public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { + return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line) + } + + @discardableResult + public func lessThanOrEqualToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { + guard let other = self.description.item.superview else { + fatalError("Expected superview but found nil when attempting make constraint `lessThanOrEqualToSuperview`.") + } + return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line) + } + + @discardableResult + public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable { + return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line) + } + + @discardableResult + public func greaterThanOrEqualToSuperview(_ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable { + guard let other = self.description.item.superview else { + fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.") + } + return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMultiplierTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMultiplierTarget.swift new file mode 100644 index 0000000..6fecd33 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintMultiplierTarget.swift @@ -0,0 +1,75 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintMultiplierTarget { + + var constraintMultiplierTargetValue: CGFloat { get } + +} + +extension Int: ConstraintMultiplierTarget { + + public var constraintMultiplierTargetValue: CGFloat { + return CGFloat(self) + } + +} + +extension UInt: ConstraintMultiplierTarget { + + public var constraintMultiplierTargetValue: CGFloat { + return CGFloat(self) + } + +} + +extension Float: ConstraintMultiplierTarget { + + public var constraintMultiplierTargetValue: CGFloat { + return CGFloat(self) + } + +} + +extension Double: ConstraintMultiplierTarget { + + public var constraintMultiplierTargetValue: CGFloat { + return CGFloat(self) + } + +} + +extension CGFloat: ConstraintMultiplierTarget { + + public var constraintMultiplierTargetValue: CGFloat { + return self + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintOffsetTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintOffsetTarget.swift new file mode 100644 index 0000000..bd9e0a1 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintOffsetTarget.swift @@ -0,0 +1,69 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintOffsetTarget: ConstraintConstantTarget { +} + +extension Int: ConstraintOffsetTarget { +} + +extension UInt: ConstraintOffsetTarget { +} + +extension Float: ConstraintOffsetTarget { +} + +extension Double: ConstraintOffsetTarget { +} + +extension CGFloat: ConstraintOffsetTarget { +} + +extension ConstraintOffsetTarget { + + internal var constraintOffsetTargetValue: CGFloat { + let offset: CGFloat + if let amount = self as? Float { + offset = CGFloat(amount) + } else if let amount = self as? Double { + offset = CGFloat(amount) + } else if let amount = self as? CGFloat { + offset = CGFloat(amount) + } else if let amount = self as? Int { + offset = CGFloat(amount) + } else if let amount = self as? UInt { + offset = CGFloat(amount) + } else { + offset = 0.0 + } + return offset + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriority.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriority.swift new file mode 100644 index 0000000..f9dab16 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriority.swift @@ -0,0 +1,77 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + +public struct ConstraintPriority : ExpressibleByFloatLiteral, Equatable, Strideable { + public typealias FloatLiteralType = Float + + public let value: Float + + public init(floatLiteral value: Float) { + self.value = value + } + + public init(_ value: Float) { + self.value = value + } + + public static var required: ConstraintPriority { + return 1000.0 + } + + public static var high: ConstraintPriority { + return 750.0 + } + + public static var medium: ConstraintPriority { + #if os(OSX) + return 501.0 + #else + return 500.0 + #endif + + } + + public static var low: ConstraintPriority { + return 250.0 + } + + public static func ==(lhs: ConstraintPriority, rhs: ConstraintPriority) -> Bool { + return lhs.value == rhs.value + } + + // MARK: Strideable + + public func advanced(by n: FloatLiteralType) -> ConstraintPriority { + return ConstraintPriority(floatLiteral: value + n) + } + + public func distance(to other: ConstraintPriority) -> FloatLiteralType { + return other.value - value + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriorityTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriorityTarget.swift new file mode 100644 index 0000000..064f750 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintPriorityTarget.swift @@ -0,0 +1,85 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintPriorityTarget { + + var constraintPriorityTargetValue: Float { get } + +} + +extension Int: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return Float(self) + } + +} + +extension UInt: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return Float(self) + } + +} + +extension Float: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return self + } + +} + +extension Double: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return Float(self) + } + +} + +extension CGFloat: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return Float(self) + } + +} + +#if os(iOS) || os(tvOS) +extension UILayoutPriority: ConstraintPriorityTarget { + + public var constraintPriorityTargetValue: Float { + return self.rawValue + } + +} +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelatableTarget.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelatableTarget.swift new file mode 100644 index 0000000..d517a61 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelatableTarget.swift @@ -0,0 +1,72 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol ConstraintRelatableTarget { +} + +extension Int: ConstraintRelatableTarget { +} + +extension UInt: ConstraintRelatableTarget { +} + +extension Float: ConstraintRelatableTarget { +} + +extension Double: ConstraintRelatableTarget { +} + +extension CGFloat: ConstraintRelatableTarget { +} + +extension CGSize: ConstraintRelatableTarget { +} + +extension CGPoint: ConstraintRelatableTarget { +} + +extension ConstraintInsets: ConstraintRelatableTarget { +} + +#if os(iOS) || os(tvOS) +@available(iOS 11.0, tvOS 11.0, *) +extension ConstraintDirectionalInsets: ConstraintRelatableTarget { +} +#endif + +extension ConstraintItem: ConstraintRelatableTarget { +} + +extension ConstraintView: ConstraintRelatableTarget { +} + +@available(iOS 9.0, OSX 10.11, *) +extension ConstraintLayoutGuide: ConstraintRelatableTarget { +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelation.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelation.swift new file mode 100644 index 0000000..446aaf7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintRelation.swift @@ -0,0 +1,48 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +internal enum ConstraintRelation : Int { + case equal = 1 + case lessThanOrEqual + case greaterThanOrEqual + + internal var layoutRelation: LayoutRelation { + get { + switch(self) { + case .equal: + return .equal + case .lessThanOrEqual: + return .lessThanOrEqual + case .greaterThanOrEqual: + return .greaterThanOrEqual + } + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView+Extensions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView+Extensions.swift new file mode 100644 index 0000000..a4898dc --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView+Extensions.swift @@ -0,0 +1,152 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public extension ConstraintView { + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_left: ConstraintItem { return self.snp.left } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_top: ConstraintItem { return self.snp.top } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_right: ConstraintItem { return self.snp.right } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_bottom: ConstraintItem { return self.snp.bottom } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_leading: ConstraintItem { return self.snp.leading } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_trailing: ConstraintItem { return self.snp.trailing } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_width: ConstraintItem { return self.snp.width } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_height: ConstraintItem { return self.snp.height } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_centerX: ConstraintItem { return self.snp.centerX } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_centerY: ConstraintItem { return self.snp.centerY } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_baseline: ConstraintItem { return self.snp.baseline } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, OSX 10.11, *) + var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, OSX 10.11, *) + var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_leftMargin: ConstraintItem { return self.snp.leftMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_topMargin: ConstraintItem { return self.snp.topMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_rightMargin: ConstraintItem { return self.snp.rightMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_edges: ConstraintItem { return self.snp.edges } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_size: ConstraintItem { return self.snp.size } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + var snp_center: ConstraintItem { return self.snp.center } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_margins: ConstraintItem { return self.snp.margins } + + @available(iOS, deprecated, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) + var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { + return self.snp.prepareConstraints(closure) + } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + self.snp.makeConstraints(closure) + } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + self.snp.remakeConstraints(closure) + } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + self.snp.updateConstraints(closure) + } + + @available(*, deprecated, message:"Use newer snp.* syntax.") + func snp_removeConstraints() { + self.snp.removeConstraints() + } + + var snp: ConstraintViewDSL { + return ConstraintViewDSL(view: self) + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView.swift new file mode 100644 index 0000000..6ff8a76 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintView.swift @@ -0,0 +1,35 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +#if os(iOS) || os(tvOS) + public typealias ConstraintView = UIView +#else + public typealias ConstraintView = NSView +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintViewDSL.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintViewDSL.swift new file mode 100644 index 0000000..a0187f9 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/ConstraintViewDSL.swift @@ -0,0 +1,101 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public struct ConstraintViewDSL: ConstraintAttributesDSL { + + @discardableResult + public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { + return ConstraintMaker.prepareConstraints(item: self.view, closure: closure) + } + + public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.makeConstraints(item: self.view, closure: closure) + } + + public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.remakeConstraints(item: self.view, closure: closure) + } + + public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { + ConstraintMaker.updateConstraints(item: self.view, closure: closure) + } + + public func removeConstraints() { + ConstraintMaker.removeConstraints(item: self.view) + } + + public var contentHuggingHorizontalPriority: Float { + get { + return self.view.contentHuggingPriority(for: .horizontal).rawValue + } + nonmutating set { + self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .horizontal) + } + } + + public var contentHuggingVerticalPriority: Float { + get { + return self.view.contentHuggingPriority(for: .vertical).rawValue + } + nonmutating set { + self.view.setContentHuggingPriority(LayoutPriority(rawValue: newValue), for: .vertical) + } + } + + public var contentCompressionResistanceHorizontalPriority: Float { + get { + return self.view.contentCompressionResistancePriority(for: .horizontal).rawValue + } + nonmutating set { + self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .horizontal) + } + } + + public var contentCompressionResistanceVerticalPriority: Float { + get { + return self.view.contentCompressionResistancePriority(for: .vertical).rawValue + } + nonmutating set { + self.view.setContentCompressionResistancePriority(LayoutPriority(rawValue: newValue), for: .vertical) + } + } + + public var target: AnyObject? { + return self.view + } + + internal let view: ConstraintView + + internal init(view: ConstraintView) { + self.view = view + + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Debugging.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Debugging.swift new file mode 100644 index 0000000..a78579a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Debugging.swift @@ -0,0 +1,169 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + +public extension LayoutConstraint { + + override var description: String { + var description = "<" + + description += descriptionForObject(self) + + if let firstItem = conditionalOptional(from: self.firstItem) { + description += " \(descriptionForObject(firstItem))" + } + + if self.firstAttribute != .notAnAttribute { + description += ".\(descriptionForAttribute(self.firstAttribute))" + } + + description += " \(descriptionForRelation(self.relation))" + + if let secondItem = self.secondItem { + description += " \(descriptionForObject(secondItem))" + } + + if self.secondAttribute != .notAnAttribute { + description += ".\(descriptionForAttribute(self.secondAttribute))" + } + + if self.multiplier != 1.0 { + description += " * \(self.multiplier)" + } + + if self.secondAttribute == .notAnAttribute { + description += " \(self.constant)" + } else { + if self.constant > 0.0 { + description += " + \(self.constant)" + } else if self.constant < 0.0 { + description += " - \(abs(self.constant))" + } + } + + if self.priority.rawValue != 1000.0 { + description += " ^\(self.priority)" + } + + description += ">" + + return description + } + +} + +private func descriptionForRelation(_ relation: LayoutRelation) -> String { + switch relation { + case .equal: return "==" + case .greaterThanOrEqual: return ">=" + case .lessThanOrEqual: return "<=" + #if swift(>=5.0) + @unknown default: return "unknown" + #endif + } +} + +private func descriptionForAttribute(_ attribute: LayoutAttribute) -> String { + #if os(iOS) || os(tvOS) + switch attribute { + case .notAnAttribute: return "notAnAttribute" + case .top: return "top" + case .left: return "left" + case .bottom: return "bottom" + case .right: return "right" + case .leading: return "leading" + case .trailing: return "trailing" + case .width: return "width" + case .height: return "height" + case .centerX: return "centerX" + case .centerY: return "centerY" + case .lastBaseline: return "lastBaseline" + case .firstBaseline: return "firstBaseline" + case .topMargin: return "topMargin" + case .leftMargin: return "leftMargin" + case .bottomMargin: return "bottomMargin" + case .rightMargin: return "rightMargin" + case .leadingMargin: return "leadingMargin" + case .trailingMargin: return "trailingMargin" + case .centerXWithinMargins: return "centerXWithinMargins" + case .centerYWithinMargins: return "centerYWithinMargins" + #if swift(>=5.0) + @unknown default: return "unknown" + #endif + } + #else + switch attribute { + case .notAnAttribute: return "notAnAttribute" + case .top: return "top" + case .left: return "left" + case .bottom: return "bottom" + case .right: return "right" + case .leading: return "leading" + case .trailing: return "trailing" + case .width: return "width" + case .height: return "height" + case .centerX: return "centerX" + case .centerY: return "centerY" + case .lastBaseline: return "lastBaseline" + case .firstBaseline: return "firstBaseline" + #if swift(>=5.0) + @unknown default: return "unknown" + #endif + } + #endif +} + +private func conditionalOptional(from object: Optional) -> Optional { + return object +} + +private func conditionalOptional(from object: T) -> Optional { + return Optional.some(object) +} + +private func descriptionForObject(_ object: AnyObject) -> String { + let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object))) + var desc = "" + + desc += type(of: object).description() + + if let object = object as? ConstraintView { + desc += ":\(object.snp.label() ?? pointerDescription)" + } else if let object = object as? LayoutConstraint { + desc += ":\(object.label ?? pointerDescription)" + } else { + desc += ":\(pointerDescription)" + } + + if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 { + desc += "@\((file as NSString).lastPathComponent)#\(line)" + } + + desc += "" + return desc +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraint.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraint.swift new file mode 100644 index 0000000..5425ea8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraint.swift @@ -0,0 +1,61 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public class LayoutConstraint : NSLayoutConstraint { + + public var label: String? { + get { + return self.identifier + } + set { + self.identifier = newValue + } + } + + internal weak var constraint: Constraint? = nil + +} + +internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool { + // If firstItem or secondItem on either constraint has a dangling pointer + // this comparison can cause a crash. The solution for this is to ensure + // your layout code hold strong references to things like Views, LayoutGuides + // and LayoutAnchors as SnapKit will not keep strong references to any of these. + guard lhs.firstAttribute == rhs.firstAttribute && + lhs.secondAttribute == rhs.secondAttribute && + lhs.relation == rhs.relation && + lhs.priority == rhs.priority && + lhs.multiplier == rhs.multiplier && + lhs.secondItem === rhs.secondItem && + lhs.firstItem === rhs.firstItem else { + return false + } + return true +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraintItem.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraintItem.swift new file mode 100644 index 0000000..a59de6b --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/LayoutConstraintItem.swift @@ -0,0 +1,93 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#else + import AppKit +#endif + + +public protocol LayoutConstraintItem: class { +} + +@available(iOS 9.0, OSX 10.11, *) +extension ConstraintLayoutGuide : LayoutConstraintItem { +} + +extension ConstraintView : LayoutConstraintItem { +} + + +extension LayoutConstraintItem { + + internal func prepare() { + if let view = self as? ConstraintView { + view.translatesAutoresizingMaskIntoConstraints = false + } + } + + internal var superview: ConstraintView? { + if let view = self as? ConstraintView { + return view.superview + } + + if #available(iOS 9.0, OSX 10.11, *), let guide = self as? ConstraintLayoutGuide { + return guide.owningView + } + + return nil + } + internal var constraints: [Constraint] { + return self.constraintsSet.allObjects as! [Constraint] + } + + internal func add(constraints: [Constraint]) { + let constraintsSet = self.constraintsSet + for constraint in constraints { + constraintsSet.add(constraint) + } + } + + internal func remove(constraints: [Constraint]) { + let constraintsSet = self.constraintsSet + for constraint in constraints { + constraintsSet.remove(constraint) + } + } + + private var constraintsSet: NSMutableSet { + let constraintsSet: NSMutableSet + + if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSMutableSet { + constraintsSet = existing + } else { + constraintsSet = NSMutableSet() + objc_setAssociatedObject(self, &constraintsKey, constraintsSet, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return constraintsSet + + } + +} +private var constraintsKey: UInt8 = 0 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Typealiases.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Typealiases.swift new file mode 100644 index 0000000..ded96cc --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/Typealiases.swift @@ -0,0 +1,42 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +#if os(iOS) || os(tvOS) + import UIKit +#if swift(>=4.2) + typealias LayoutRelation = NSLayoutConstraint.Relation + typealias LayoutAttribute = NSLayoutConstraint.Attribute +#else + typealias LayoutRelation = NSLayoutRelation + typealias LayoutAttribute = NSLayoutAttribute +#endif + typealias LayoutPriority = UILayoutPriority +#else + import AppKit + typealias LayoutRelation = NSLayoutConstraint.Relation + typealias LayoutAttribute = NSLayoutConstraint.Attribute + typealias LayoutPriority = NSLayoutConstraint.Priority +#endif + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/UILayoutSupport+Extensions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/UILayoutSupport+Extensions.swift new file mode 100644 index 0000000..8e7644c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/SnapKit/Source/UILayoutSupport+Extensions.swift @@ -0,0 +1,36 @@ +// +// SnapKit +// +// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(iOS) || os(tvOS) + import UIKit +#endif + + +@available(iOS 8.0, *) +public extension ConstraintLayoutSupport { + + var snp: ConstraintLayoutSupportDSL { + return ConstraintLayoutSupportDSL(support: self) + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist new file mode 100644 index 0000000..2a9158a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m new file mode 100644 index 0000000..67a74df --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_MBProgressHUD : NSObject +@end +@implementation PodsDummy_MBProgressHUD +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-umbrella.h new file mode 100644 index 0000000..8522a01 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "MBProgressHUD.h" + +FOUNDATION_EXPORT double MBProgressHUDVersionNumber; +FOUNDATION_EXPORT const unsigned char MBProgressHUDVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig new file mode 100644 index 0000000..0d8c31d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "QuartzCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/MBProgressHUD +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig new file mode 100644 index 0000000..0d8c31d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "QuartzCore" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/MBProgressHUD +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-Info.plist new file mode 100644 index 0000000..1c0dd95 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.7.5 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-dummy.m new file mode 100644 index 0000000..d43259d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_MJRefresh : NSObject +@end +@implementation PodsDummy_MJRefresh +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-umbrella.h new file mode 100644 index 0000000..7168200 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh-umbrella.h @@ -0,0 +1,41 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "MJRefreshAutoFooter.h" +#import "MJRefreshBackFooter.h" +#import "MJRefreshComponent.h" +#import "MJRefreshFooter.h" +#import "MJRefreshHeader.h" +#import "MJRefreshTrailer.h" +#import "MJRefreshAutoGifFooter.h" +#import "MJRefreshAutoNormalFooter.h" +#import "MJRefreshAutoStateFooter.h" +#import "MJRefreshBackGifFooter.h" +#import "MJRefreshBackNormalFooter.h" +#import "MJRefreshBackStateFooter.h" +#import "MJRefreshGifHeader.h" +#import "MJRefreshNormalHeader.h" +#import "MJRefreshStateHeader.h" +#import "MJRefreshNormalTrailer.h" +#import "MJRefreshStateTrailer.h" +#import "MJRefresh.h" +#import "MJRefreshConfig.h" +#import "MJRefreshConst.h" +#import "NSBundle+MJRefresh.h" +#import "UICollectionViewLayout+MJRefresh.h" +#import "UIScrollView+MJExtension.h" +#import "UIScrollView+MJRefresh.h" +#import "UIView+MJExtension.h" + +FOUNDATION_EXPORT double MJRefreshVersionNumber; +FOUNDATION_EXPORT const unsigned char MJRefreshVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.debug.xcconfig new file mode 100644 index 0000000..e2b85ee --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.debug.xcconfig @@ -0,0 +1,11 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/MJRefresh +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.release.xcconfig new file mode 100644 index 0000000..e2b85ee --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/MJRefresh/MJRefresh.release.xcconfig @@ -0,0 +1,11 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/MJRefresh +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-Info.plist new file mode 100644 index 0000000..3c175b6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-dummy.m new file mode 100644 index 0000000..81536fb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ObjcExceptionBridging : NSObject +@end +@implementation PodsDummy_ObjcExceptionBridging +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-umbrella.h new file mode 100644 index 0000000..f7feb37 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "ObjcExceptionBridging.h" + +FOUNDATION_EXPORT double ObjcExceptionBridgingVersionNumber; +FOUNDATION_EXPORT const unsigned char ObjcExceptionBridgingVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.debug.xcconfig new file mode 100644 index 0000000..a49dee8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.debug.xcconfig @@ -0,0 +1,11 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/ObjcExceptionBridging +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.release.xcconfig new file mode 100644 index 0000000..a49dee8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/ObjcExceptionBridging/ObjcExceptionBridging.release.xcconfig @@ -0,0 +1,11 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/ObjcExceptionBridging +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.markdown b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.markdown new file mode 100644 index 0000000..2b29d38 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.markdown @@ -0,0 +1,121 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## MBProgressHUD + +Copyright © 2009-2020 Matej Bukovinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +## MJRefresh + +Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## ObjcExceptionBridging + +The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +## SnapKit + +Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +## XCGLogger + +The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.plist new file mode 100644 index 0000000..8ee1ae1 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-acknowledgements.plist @@ -0,0 +1,177 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright © 2009-2020 Matej Bukovinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + License + MIT + Title + MBProgressHUD + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + MJRefresh + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + ObjcExceptionBridging + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + SnapKit + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Title + XCGLogger + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-dummy.m new file mode 100644 index 0000000..86690d8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_WCHBLEOTA : NSObject +@end +@implementation PodsDummy_Pods_WCHBLEOTA +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-input-files.xcfilelist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..6ebfba2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,6 @@ +${PODS_ROOT}/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh +${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework +${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework +${BUILT_PRODUCTS_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework +${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework +${BUILT_PRODUCTS_DIR}/XCGLogger/XCGLogger.framework \ No newline at end of file diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-output-files.xcfilelist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..6b26b1a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,5 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjcExceptionBridging.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/XCGLogger.framework \ No newline at end of file diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-input-files.xcfilelist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..6ebfba2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,6 @@ +${PODS_ROOT}/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh +${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework +${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework +${BUILT_PRODUCTS_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework +${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework +${BUILT_PRODUCTS_DIR}/XCGLogger/XCGLogger.framework \ No newline at end of file diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-output-files.xcfilelist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..6b26b1a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,5 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjcExceptionBridging.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/XCGLogger.framework \ No newline at end of file diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh new file mode 100644 index 0000000..5ed5add --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh @@ -0,0 +1,194 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" + + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + 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}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + 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}\"" + 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}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures from the dSYM. + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then + # Move the stripped file into its final destination. + 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}\"" + 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}" + else + # 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. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=1 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=0 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + 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}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XCGLogger/XCGLogger.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework" + install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" + install_framework "${BUILT_PRODUCTS_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework" + install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework" + install_framework "${BUILT_PRODUCTS_DIR}/XCGLogger/XCGLogger.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-umbrella.h new file mode 100644 index 0000000..ea4b1f7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_WCHBLEOTAVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_WCHBLEOTAVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.debug.xcconfig new file mode 100644 index 0000000..173cc6d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.debug.xcconfig @@ -0,0 +1,15 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger/XCGLogger.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "MBProgressHUD" -framework "MJRefresh" -framework "ObjcExceptionBridging" -framework "QuartzCore" -framework "SnapKit" -framework "XCGLogger" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.release.xcconfig new file mode 100644 index 0000000..173cc6d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.release.xcconfig @@ -0,0 +1,15 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging/ObjcExceptionBridging.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger/XCGLogger.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "MBProgressHUD" -framework "MJRefresh" -framework "ObjcExceptionBridging" -framework "QuartzCore" -framework "SnapKit" -framework "XCGLogger" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-Info.plist new file mode 100644 index 0000000..8d87a1a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 5.0.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-dummy.m new file mode 100644 index 0000000..b44e8e5 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_SnapKit : NSObject +@end +@implementation PodsDummy_SnapKit +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h new file mode 100644 index 0000000..1b1be64 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double SnapKitVersionNumber; +FOUNDATION_EXPORT const unsigned char SnapKitVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig new file mode 100644 index 0000000..03fb3c1 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig new file mode 100644 index 0000000..03fb3c1 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig @@ -0,0 +1,13 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-Info.plist new file mode 100644 index 0000000..3f2c147 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 7.0.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-dummy.m b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-dummy.m new file mode 100644 index 0000000..3850b97 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_XCGLogger : NSObject +@end +@implementation PodsDummy_XCGLogger +@end diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-umbrella.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-umbrella.h new file mode 100644 index 0000000..4008b8f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double XCGLoggerVersionNumber; +FOUNDATION_EXPORT const unsigned char XCGLoggerVersionString[]; + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.debug.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.debug.xcconfig new file mode 100644 index 0000000..22e924c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.debug.xcconfig @@ -0,0 +1,16 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "ObjcExceptionBridging" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/XCGLogger +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_VERSION = 5.0 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.release.xcconfig b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.release.xcconfig new file mode 100644 index 0000000..22e924c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/Target Support Files/XCGLogger/XCGLogger.release.xcconfig @@ -0,0 +1,16 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/XCGLogger +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ObjcExceptionBridging" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift +OTHER_LDFLAGS = $(inherited) -framework "ObjcExceptionBridging" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/XCGLogger +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_VERSION = 5.0 +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/.swift-version b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/.swift-version new file mode 100644 index 0000000..819e07a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/.swift-version @@ -0,0 +1 @@ +5.0 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/LICENSE.txt b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/LICENSE.txt new file mode 100644 index 0000000..58aaa4d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Dave Wood, Cerebral Gardens http://www.cerebralgardens.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/README.md b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/README.md new file mode 100644 index 0000000..8511b6f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/README.md @@ -0,0 +1,596 @@ +![XCGLogger][xcglogger-logo] + +[![badge-language]][swift.org] +[![badge-platforms]][swift.org] +[![badge-license]][license] + +[![badge-travis]][travis] +[![badge-swiftpm]][swiftpm] +[![badge-cocoapods]][cocoapods-xcglogger] +[![badge-carthage]][carthage] + +[![badge-mastodon]][mastodon-davewoodx] +[![badge-twitter]][twitter-davewoodx] + +[![badge-sponsors]][cerebral-gardens] +[![badge-patreon]][patreon-davewoodx] + +## tl;dr +XCGLogger is the original debug log module for use in Swift projects. + +Swift does not include a C preprocessor so developers are unable to use the debug log `#define` macros they would use in Objective-C. This means our traditional way of generating nice debug logs no longer works. Resorting to just plain old `print` calls means you lose a lot of helpful information, or requires you to type a lot more code. + +XCGLogger allows you to log details to the console (and optionally a file, or other custom destinations), just like you would have with `NSLog()` or `print()`, but with additional information, such as the date, function name, filename and line number. + +Go from this: + +```Simple message``` + +to this: + +```2014-06-09 06:44:43.600 [Debug] [AppDelegate.swift:40] application(_:didFinishLaunchingWithOptions:): Simple message``` + +#### Example +Example + +### Communication _(Hat Tip AlamoFire)_ + +* If you need help, use [Stack Overflow][stackoverflow] (Tag '[xcglogger][stackoverflow]'). +* If you'd like to ask a general question, use [Stack Overflow][stackoverflow]. +* If you've found a bug, open an issue. +* If you have a feature request, open an issue. +* If you want to contribute, submit a pull request. +* If you use XCGLogger, please Star the project on [GitHub][github-xcglogger] + +## Installation + +### Git Submodule + +Execute: + +```git submodule add https://github.com/DaveWoodCom/XCGLogger.git``` + +in your repository folder. + +### [Carthage][carthage] + +Add the following line to your `Cartfile`. + +```github "DaveWoodCom/XCGLogger" ~> 7.0.1``` + +Then run `carthage update --no-use-binaries` or just `carthage update`. For details of the installation and usage of Carthage, visit [its project page][carthage]. + +Developers running 5.0 and above in Swift will need to add `$(SRCROOT)/Carthage/Build/iOS/ObjcExceptionBridging.framework` to their Input Files in the Copy Carthage Frameworks Build Phase. + +### [CocoaPods][cocoapods] + +Add something similar to the following lines to your `Podfile`. You may need to adjust based on your platform, version/branch etc. + +``` +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' +use_frameworks! + +pod 'XCGLogger', '~> 7.0.1' +``` + +Specifying the pod `XCGLogger` on its own will include the core framework. We're starting to add subspecs to allow you to include optional components as well: + +`pod 'XCGLogger/UserInfoHelpers', '~> 7.0.1'`: Include some experimental code to help deal with using UserInfo dictionaries to tag log messages. + +Then run `pod install`. For details of the installation and usage of CocoaPods, visit [its official web site][cocoapods]. + +Note: Before CocoaPods 1.4.0 it was not possible to use multiple pods with a mixture of Swift versions. You may need to ensure each pod is configured for the correct Swift version (check the targets in the pod project of your workspace). If you manually adjust the Swift version for a project, it'll reset the next time you run `pod install`. You can add a `post_install` hook into your podfile to automate setting the correct Swift versions. This is largely untested, and I'm not sure it's a good solution, but it seems to work: + +``` +post_install do |installer| + installer.pods_project.targets.each do |target| + if ['SomeTarget-iOS', 'SomeTarget-watchOS'].include? "#{target}" + print "Setting #{target}'s SWIFT_VERSION to 4.2\n" + target.build_configurations.each do |config| + config.build_settings['SWIFT_VERSION'] = '4.2' + end + else + print "Setting #{target}'s SWIFT_VERSION to Undefined (Xcode will automatically resolve)\n" + target.build_configurations.each do |config| + config.build_settings.delete('SWIFT_VERSION') + end + end + end + + print "Setting the default SWIFT_VERSION to 3.2\n" + installer.pods_project.build_configurations.each do |config| + config.build_settings['SWIFT_VERSION'] = '3.2' + end +end +``` + +You can adjust that to suit your needs of course. + +### [Swift Package Manager][swiftpm] + +Add the following entry to your package's dependencies: + +``` +.Package(url: "https://github.com/DaveWoodCom/XCGLogger.git", majorVersion: 7) +``` + +### Backwards Compatibility + +Use: +* XCGLogger version [7.0.1][xcglogger-7.0.1] for Swift 5.0 +* XCGLogger version [6.1.0][xcglogger-6.1.0] for Swift 4.2 +* XCGLogger version [6.0.4][xcglogger-6.0.4] for Swift 4.1 +* XCGLogger version [6.0.2][xcglogger-6.0.2] for Swift 4.0 +* XCGLogger version [5.0.5][xcglogger-5.0.5] for Swift 3.0-3.2 +* XCGLogger version [3.6.0][xcglogger-3.6.0] for Swift 2.3 +* XCGLogger version [3.5.3][xcglogger-3.5.3] for Swift 2.2 +* XCGLogger version [3.2][xcglogger-3.2] for Swift 2.0-2.1 +* XCGLogger version [2.x][xcglogger-2.x] for Swift 1.2 +* XCGLogger version [1.x][xcglogger-1.x] for Swift 1.1 and below. + +## Basic Usage (Quick Start) + +_This quick start method is intended just to get you up and running with the logger. You should however use the [advanced usage below](#advanced-usage-recommended) to get the most out of this library._ + +Add the XCGLogger project as a subproject to your project, and add the appropriate library as a dependency of your target(s). +Under the `General` tab of your target, add `XCGLogger.framework` and `ObjcExceptionBridging.framework` to the `Embedded Binaries` section. + +Then, in each source file: + +```Swift +import XCGLogger +``` + +In your AppDelegate (or other global file), declare a global constant to the default XCGLogger instance. + +```Swift +let log = XCGLogger.default +``` + +In the +```Swift +application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) // iOS, tvOS +``` + +or + +```Swift +applicationDidFinishLaunching(_ notification: Notification) // macOS +``` + +function, configure the options you need: + +```Swift +log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: "path/to/file", fileLevel: .debug) +``` + +The value for `writeToFile:` can be a `String` or `URL`. If the file already exists, it will be cleared before we use it. Omit the parameter or set it to `nil` to log to the console only. You can optionally set a different log level for the file output using the `fileLevel:` parameter. Set it to `nil` or omit it to use the same log level as the console. + +Then, whenever you'd like to log something, use one of the convenience methods: + +```Swift +log.verbose("A verbose message, usually useful when working on a specific problem") +log.debug("A debug message") +log.info("An info message, probably useful to power users looking in console.app") +log.notice("A notice message") +log.warning("A warning message, may indicate a possible error") +log.error("An error occurred, but it's recoverable, just info about what happened") +log.severe("A severe error occurred, we are likely about to crash now") +log.alert("An alert error occurred, a log destination could be made to email someone") +log.emergency("An emergency error occurred, a log destination could be made to text someone") +``` + +The different methods set the log level of the message. XCGLogger will only print messages with a log level that is greater to or equal to its current log level setting. So a logger with a level of `.error` will only output log messages with a level of `.error`, `.severe`, `.alert`, or `.emergency`. + +## Advanced Usage (Recommended) + +XCGLogger aims to be simple to use and get you up and running quickly with as few as 2 lines of code above. But it allows for much greater control and flexibility. + +A logger can be configured to deliver log messages to a variety of destinations. Using the basic setup above, the logger will output log messages to the standard Xcode debug console, and optionally a file if a path is provided. It's quite likely you'll want to send logs to more interesting places, such as the Apple System Console, a database, third party server, or another application such as [NSLogger][NSLogger]. This is accomplished by adding the destination to the logger. + +Here's an example of configuring the logger to output to the Apple System Log as well as a file. + +```Swift +// Create a logger object with no destinations +let log = XCGLogger(identifier: "advancedLogger", includeDefaultDestinations: false) + +// Create a destination for the system console log (via NSLog) +let systemDestination = AppleSystemLogDestination(identifier: "advancedLogger.systemDestination") + +// Optionally set some configuration options +systemDestination.outputLevel = .debug +systemDestination.showLogIdentifier = false +systemDestination.showFunctionName = true +systemDestination.showThreadName = true +systemDestination.showLevel = true +systemDestination.showFileName = true +systemDestination.showLineNumber = true +systemDestination.showDate = true + +// Add the destination to the logger +log.add(destination: systemDestination) + +// Create a file log destination +let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination") + +// Optionally set some configuration options +fileDestination.outputLevel = .debug +fileDestination.showLogIdentifier = false +fileDestination.showFunctionName = true +fileDestination.showThreadName = true +fileDestination.showLevel = true +fileDestination.showFileName = true +fileDestination.showLineNumber = true +fileDestination.showDate = true + +// Process this destination in the background +fileDestination.logQueue = XCGLogger.logQueue + +// Add the destination to the logger +log.add(destination: fileDestination) + +// Add basic app info, version info etc, to the start of the logs +log.logAppDetails() +``` + +You can configure each log destination with different options depending on your needs. + +Another common usage pattern is to have multiple loggers, perhaps one for UI issues, one for networking, and another for data issues. + +Each log destination can have its own log level. As a convenience, you can set the log level on the log object itself and it will pass that level to each destination. Then set the destinations that need to be different. + +**Note**: A destination object can only be added to one logger object, adding it to a second will remove it from the first. + +### Initialization Using A Closure + +Alternatively you can use a closure to initialize your global variable, so that all initialization is done in one place +```Swift +let log: XCGLogger = { + let log = XCGLogger(identifier: "advancedLogger", includeDefaultDestinations: false) + + // Customize as needed + + return log +}() +``` + +**Note**: This creates the log object lazily, which means it's not created until it's actually needed. This delays the initial output of the app information details. Because of this, I recommend forcing the log object to be created at app launch by adding the line `let _ = log` at the top of your `didFinishLaunching` method if you don't already log something on app launch. + +### Log Anything + +You can log strings: + +```Swift +log.debug("Hi there!") +``` + +or pretty much anything you want: + +```Swift +log.debug(true) +log.debug(CGPoint(x: 1.1, y: 2.2)) +log.debug(MyEnum.Option) +log.debug((4, 2)) +log.debug(["Device": "iPhone", "Version": 7]) +``` + +### Filtering Log Messages + +New to XCGLogger 4, you can now create filters to apply to your logger (or to specific destinations). Create and configure your filters (examples below), and then add them to the logger or destination objects by setting the optional `filters` property to an array containing the filters. Filters are applied in the order they exist in the array. During processing, each filter is asked if the log message should be excluded from the log. If any filter excludes the log message, it's excluded. Filters have no way to reverse the exclusion of another filter. + +If a destination's `filters` property is `nil`, the log's `filters` property is used instead. To have one destination log everything, while having all other destinations filter something, add the filters to the log object and set the one destination's `filters` property to an empty array `[]`. + +**Note**: Unlike destinations, you can add the same filter object to multiple loggers and/or multiple destinations. + +#### Filter by Filename + +To exclude all log messages from a specific file, create an exclusion filter like so: + +```Swift +log.filters = [FileNameFilter(excludeFrom: ["AppDelegate.swift"], excludePathWhenMatching: true)] +``` + +`excludeFrom:` takes an `Array` or `Set` so you can specify multiple files at the same time. + +`excludePathWhenMatching:` defaults to `true` so you can omit it unless you want to match path's as well. + +To include log messages only for a specific set to files, create the filter using the `includeFrom:` initializer. It's also possible to just toggle the `inverse` property to flip the exclusion filter to an inclusion filter. + +#### Filter by Tag + +In order to filter log messages by tag, you must of course be able to set a tag on the log messages. Each log message can now have additional, user defined data attached to them, to be used by filters (and/or formatters etc). This is handled with a `userInfo: Dictionary` object. The dictionary key should be a namespaced string to avoid collisions with future additions. Official keys will begin with `com.cerebralgardens.xcglogger`. The tag key can be accessed by `XCGLogger.Constants.userInfoKeyTags`. You definitely don't want to be typing that, so feel free to create a global shortcut: `let tags = XCGLogger.Constants.userInfoKeyTags`. Now you can easily tag your logs: + +```Swift +let sensitiveTag = "Sensitive" +log.debug("A tagged log message", userInfo: [tags: sensitiveTag]) +``` + +The value for tags can be an `Array`, `Set`, or just a `String`, depending on your needs. They'll all work the same way when filtered. + +Depending on your workflow and usage, you'll probably create faster methods to set up the `userInfo` dictionary. See [below](#mixing-and-matching) for other possible shortcuts. + +Now that you have your logs tagged, you can filter easily: + +```Swift +log.filters = [TagFilter(excludeFrom: [sensitiveTag])] +``` + +Just like the `FileNameFilter`, you can use `includeFrom:` or toggle `inverse` to include only log messages that have the specified tags. + +#### Filter by Developer + +Filtering by developer is exactly like filtering by tag, only using the `userInfo` key of `XCGLogger.Constants.userInfoKeyDevs`. In fact, both filters are subclasses of the `UserInfoFilter` class that you can use to create additional filters. See [Extending XCGLogger](#extending-xcglogger) below. + +#### Mixing and Matching + +In large projects with multiple developers, you'll probably want to start tagging log messages, as well as indicate the developer that added the message. + +While extremely flexible, the `userInfo` dictionary can be a little cumbersome to use. There are a few possible methods you can use to simply things. I'm still testing these out myself so they're not officially part of the library yet (I'd love feedback or other suggestions). + +I have created some experimental code to help create the UserInfo dictionaries. (Include the optional `UserInfoHelpers` subspec if using CocoaPods). Check the iOS Demo app to see it in use. + +There are two structs that conform to the `UserInfoTaggingProtocol` protocol. `Tag` and `Dev`. + +You can create an extension on each of these that suit your project. For example: + +```Swift +extension Tag { + static let sensitive = Tag("sensitive") + static let ui = Tag("ui") + static let data = Tag("data") +} + +extension Dev { + static let dave = Dev("dave") + static let sabby = Dev("sabby") +} +``` + +Along with these types, there's an overloaded operator `|` that can be used to merge them together into a dictionary compatible with the `UserInfo:` parameter of the logging calls. + +Then you can log messages like this: + +```Swift +log.debug("A tagged log message", userInfo: Dev.dave | Tag.sensitive) +``` + +There are some current issues I see with these `UserInfoHelpers`, which is why I've made it optional/experimental for now. I'd love to hear comments/suggestions for improvements. + +1. The overloaded operator `|` merges dictionaries so long as there are no `Set`s. If one of the dictionaries contains a `Set`, it'll use one of them, without merging them. Preferring the left hand side if both sides have a set for the same key. +2. Since the `userInfo:` parameter needs a dictionary, you can't pass in a single Dev or Tag object. You need to use at least two with the `|` operator to have it automatically convert to a compatible dictionary. If you only want one Tag for example, you must access the `.dictionary` parameter manually: `userInfo: Tag("Blah").dictionary`. + +### Selectively Executing Code + +All log methods operate on closures. Using the same syntactic sugar as Swift's `assert()` function, this approach ensures we don't waste resources building log messages that won't be output anyway, while at the same time preserving a clean call site. + +For example, the following log statement won't waste resources if the debug log level is suppressed: + +```Swift +log.debug("The description of \(thisObject) is really expensive to create") +``` + +Similarly, let's say you have to iterate through a loop in order to do some calculation before logging the result. In Objective-C, you could put that code block between `#if` `#endif`, and prevent the code from running. But in Swift, previously you would need to still process that loop, wasting resources. With `XCGLogger` it's as simple as: + +```Swift +log.debug { + var total = 0.0 + for receipt in receipts { + total += receipt.total + } + + return "Total of all receipts: \(total)" +} +``` + +In cases where you wish to selectively execute code without generating a log line, return `nil`, or use one of the methods: `verboseExec`, `debugExec`, `infoExec`, `warningExec`, `errorExec`, and `severeExec`. + +### Custom Date Formats + +You can create your own `DateFormatter` object and assign it to the logger. + +```Swift +let dateFormatter = DateFormatter() +dateFormatter.dateFormat = "MM/dd/yyyy hh:mma" +dateFormatter.locale = Locale.current +log.dateFormatter = dateFormatter +``` + +### Enhancing Log Messages With Colour + +XCGLogger supports adding formatting codes to your log messages to enable colour in various places. The original option was to use the [XcodeColors plug-in][XcodeColors]. However, Xcode (as of version 8) no longer officially supports plug-ins. You can still view your logs in colour, just not in Xcode at the moment. You can use the ANSI colour support to add colour to your fileDestination objects and view your logs via a terminal window. This gives you some extra options such as adding Bold, Italics, or (please don't) Blinking! + +Once enabled, each log level can have its own colour. These colours can be customized as desired. If using multiple loggers, you could alternatively set each logger to its own colour. + +An example of setting up the ANSI formatter: + +```Swift +if let fileDestination: FileDestination = log.destination(withIdentifier: XCGLogger.Constants.fileDestinationIdentifier) as? FileDestination { + let ansiColorLogFormatter: ANSIColorLogFormatter = ANSIColorLogFormatter() + ansiColorLogFormatter.colorize(level: .verbose, with: .colorIndex(number: 244), options: [.faint]) + ansiColorLogFormatter.colorize(level: .debug, with: .black) + ansiColorLogFormatter.colorize(level: .info, with: .blue, options: [.underline]) + ansiColorLogFormatter.colorize(level: .notice, with: .green, options: [.italic]) + ansiColorLogFormatter.colorize(level: .warning, with: .red, options: [.faint]) + ansiColorLogFormatter.colorize(level: .error, with: .red, options: [.bold]) + ansiColorLogFormatter.colorize(level: .severe, with: .white, on: .red) + ansiColorLogFormatter.colorize(level: .alert, with: .white, on: .red, options: [.bold]) + ansiColorLogFormatter.colorize(level: .emergency, with: .white, on: .red, options: [.bold, .blink]) + fileDestination.formatters = [ansiColorLogFormatter] +} +``` + +As with filters, you can use the same formatter objects for multiple loggers and/or multiple destinations. If a destination's `formatters` property is `nil`, the logger's `formatters` property will be used instead. + +See [Extending XCGLogger](#extending-xcglogger) below for info on creating your own custom formatters. + +### Alternate Configurations + +By using Swift build flags, different log levels can be used in debugging versus staging/production. +Go to Build Settings -> Swift Compiler - Custom Flags -> Other Swift Flags and add `-DDEBUG` to the Debug entry. + +```Swift +#if DEBUG + log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#else + log.setup(level: .severe, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#endif +``` + +You can set any number of options up in a similar fashion. See the updated iOSDemo app for an example of using different log destinations based on options, search for `USE_NSLOG`. + +### Background Log Processing + +By default, the supplied log destinations will process the logs on the thread they're called on. This is to ensure the log message is displayed immediately when debugging an application. You can add a breakpoint immediately after a log call and see the results when the breakpoint hits. + +However, if you're not actively debugging the application, processing the logs on the current thread can introduce a performance hit. You can now specify a destination process its logs on a dispatch queue of your choice (or even use a default supplied one). + +```Swift +fileDestination.logQueue = XCGLogger.logQueue +``` + +or even + +```Swift +fileDestination.logQueue = DispatchQueue.global(qos: .background) +``` + +This works extremely well when combined with the [Alternate Configurations](#alternate-configurations) method above. + +```Swift +#if DEBUG + log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) +#else + log.setup(level: .severe, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true) + if let consoleLog = log.logDestination(XCGLogger.Constants.baseConsoleDestinationIdentifier) as? ConsoleDestination { + consoleLog.logQueue = XCGLogger.logQueue + } +#endif +``` + +### Append To Existing Log File + +When using the advanced configuration of the logger (see [Advanced Usage above](#advanced-usage-recommended)), you can now specify that the logger append to an existing log file, instead of automatically overwriting it. + +Add the optional `shouldAppend:` parameter when initializing the `FileDestination` object. You can also add the `appendMarker:` parameter to add a marker to the log file indicating where a new instance of your app started appending. By default we'll add `-- ** ** ** --` if the parameter is omitted. Set it to `nil` to skip appending the marker. + +```let fileDestination = FileDestination(writeToFile: "/path/to/file", identifier: "advancedLogger.fileDestination", shouldAppend: true, appendMarker: "-- Relauched App --")``` + + +### Automatic Log File Rotation + +When logging to a file, you have the option to automatically rotate the log file to an archived destination, and have the logger automatically create a new log file in place of the old one. + +Create a destination using the `AutoRotatingFileDestination` class and set the following properties: + +`targetMaxFileSize`: Auto rotate once the file is larger than this + +`targetMaxTimeInterval`: Auto rotate after this many seconds + +`targetMaxLogFiles`: Number of archived log files to keep, older ones are automatically deleted + +Those are all guidelines for the logger, not hard limits. + +### Extending XCGLogger + +You can create alternate log destinations (besides the built in ones). Your custom log destination must implement the `DestinationProtocol` protocol. Instantiate your object, configure it, and then add it to the `XCGLogger` object with `add(destination:)`. There are two base destination classes (`BaseDestination` and `BaseQueuedDestination`) you can inherit from to handle most of the process for you, requiring you to only implement one additional method in your custom class. Take a look at `ConsoleDestination` and `FileDestination` for examples. + +You can also create custom filters or formatters. Take a look at the provided versions as a starting point. Note that filters and formatters have the ability to alter the log messages as they're processed. This means you can create a filter that strips passwords, highlights specific words, encrypts messages, etc. + +## Contributing + +XCGLogger is the best logger available for Swift because of the contributions from the community like you. There are many ways you can help continue to make it great. + +1. Star the project on [GitHub][github-xcglogger]. +2. Report issues/bugs you find. +3. Suggest features. +4. Submit pull requests. +5. Download and install one of my apps: [https://www.cerebralgardens.com/apps/][cerebral-gardens-apps] Try my newest app: [All the Rings][all-the-rings]. +6. You can visit my [Patreon][patreon-davewoodx] and contribute financially. + +**Note**: when submitting a pull request, please use lots of small commits verses one huge commit. It makes it much easier to merge in when there are several pull requests that need to be combined for a new version. + + + +## To Do + +- Add more examples of some advanced use cases +- Add additional log destination types +- Add Objective-C support +- Add Linux support + +## More + +If you find this library helpful, you'll definitely find this other tool helpful: + +Watchdog: https://watchdogforxcode.com/ + +Also, please check out some of my other projects: + +- All the Rings: [App Store](https://itunes.apple.com/app/all-the-rings/id1186956966?pt=17255&ct=github&mt=8&at=11lMGu) +- Rudoku: [App Store](https://itunes.apple.com/app/rudoku/id965105321?pt=17255&ct=github&mt=8&at=11lMGu) +- TV Tune Up: https://www.cerebralgardens.com/tvtuneup + +### Change Log + +The change log is now in its own file: [CHANGELOG.md](CHANGELOG.md) + +[xcglogger-logo]: https://github.com/DaveWoodCom/XCGLogger/raw/master/ReadMeImages/XCGLoggerLogo_326x150.png +[swift.org]: https://swift.org/ +[license]: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +[travis]: https://travis-ci.org/DaveWoodCom/XCGLogger +[swiftpm]: https://swift.org/package-manager/ +[cocoapods]: https://cocoapods.org/ +[cocoapods-xcglogger]: https://cocoapods.org/pods/XCGLogger +[carthage]: https://github.com/Carthage/Carthage +[cerebral-gardens]: https://www.cerebralgardens.com/ +[cerebral-gardens-apps]: https://www.cerebralgardens.com/apps/ +[all-the-rings]: https://alltherings.fit/?s=GH3 +[mastodon-davewoodx]: https://mastodon.social/@davewoodx +[twitter-davewoodx]: https://twitter.com/davewoodx +[github-xcglogger]: https://github.com/DaveWoodCom/XCGLogger +[stackoverflow]: https://stackoverflow.com/questions/tagged/xcglogger +[patreon-davewoodx]: https://www.patreon.com/DaveWoodX + +[badge-language]: https://img.shields.io/badge/Swift-1.x%20%7C%202.x%20%7C%203.x%20%7C%204.x%20%7C%205.x-orange.svg?style=flat +[badge-platforms]: https://img.shields.io/badge/Platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgray.svg?style=flat +[badge-license]: https://img.shields.io/badge/License-MIT-lightgrey.svg?style=flat +[badge-travis]: https://img.shields.io/travis/DaveWoodCom/XCGLogger/master.svg?style=flat +[badge-swiftpm]: https://img.shields.io/badge/Swift_Package_Manager-v7.0.1-64a6dd.svg?style=flat +[badge-cocoapods]: https://img.shields.io/cocoapods/v/XCGLogger.svg?style=flat +[badge-carthage]: https://img.shields.io/badge/Carthage-v7.0.1-64a6dd.svg?style=flat + +[badge-sponsors]: https://img.shields.io/badge/Sponsors-Cerebral%20Gardens-orange.svg?style=flat +[badge-mastodon]: https://img.shields.io/badge/Mastodon-DaveWoodX-606A84.svg?style=flat +[badge-twitter]: https://img.shields.io/twitter/follow/DaveWoodX.svg?style=social +[badge-patreon]: https://img.shields.io/badge/Patreon-DaveWoodX-F96854.svg?style=flat + +[XcodeColors]: https://github.com/robbiehanson/XcodeColors +[KZLinkedConsole]: https://github.com/krzysztofzablocki/KZLinkedConsole +[NSLogger]: https://github.com/fpillet/NSLogger +[XCGLoggerNSLoggerConnector]: https://github.com/markuswinkler/XCGLoggerNSLoggerConnector +[Firelog]: http://jogabo.github.io/firelog/ +[Firebase]: https://www.firebase.com/ + +[xcglogger-7.0.1]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/7.0.1 +[xcglogger-6.1.0]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.1.0 +[xcglogger-6.0.4]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.0.4 +[xcglogger-6.0.2]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/6.0.2 +[xcglogger-5.0.5]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/5.0.5 +[xcglogger-3.6.0]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.6.0 +[xcglogger-3.5.3]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.5.3 +[xcglogger-3.2]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/3.2.0 +[xcglogger-2.x]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/2.4.0 +[xcglogger-1.x]: https://github.com/DaveWoodCom/XCGLogger/releases/tag/1.8.1 diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AppleSystemLogDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AppleSystemLogDestination.swift new file mode 100644 index 0000000..416067a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AppleSystemLogDestination.swift @@ -0,0 +1,38 @@ +// +// AppleSystemLogDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation +import Dispatch + +// MARK: - AppleSystemLogDestination +/// A standard destination that outputs log details to the Apple System Log using NSLog instead of print +open class AppleSystemLogDestination: BaseQueuedDestination { + // MARK: - Properties + /// Option: whether or not to output the date the log was created (Always false for this destination) + open override var showDate: Bool { + get { + return false + } + set { + // ignored, NSLog adds the date, so we always want showDate to be false in this subclass + } + } + + // MARK: - Overridden Methods + /// Print the log to the Apple System Log facility (using NSLog). + /// + /// - Parameters: + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open override func write(message: String) { + NSLog("%@", message) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift new file mode 100644 index 0000000..f37bfde --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/AutoRotatingFileDestination.swift @@ -0,0 +1,286 @@ +// +// AutoRotatingFileDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2017-03-31. +// Copyright © 2017 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation + +// MARK: - AutoRotatingFileDestination +/// A destination that outputs log details to files in a log folder, with auto-rotate options (by size or by time) +open class AutoRotatingFileDestination: FileDestination { + // MARK: - Constants + public static let autoRotatingFileDefaultMaxFileSize: UInt64 = 1_048_576 + public static let autoRotatingFileDefaultMaxTimeInterval: TimeInterval = 600 + + // MARK: - Properties + /// Option: desired maximum size of a log file, if 0, no maximum (log files may exceed this, it's a guideline only) + open var targetMaxFileSize: UInt64 = autoRotatingFileDefaultMaxFileSize { + didSet { + if targetMaxFileSize < 1 { + targetMaxFileSize = .max + } + } + } + + /// Option: desired maximum time in seconds stored in a log file, if 0, no maximum (log files may exceed this, it's a guideline only) + open var targetMaxTimeInterval: TimeInterval = autoRotatingFileDefaultMaxTimeInterval { + didSet { + if targetMaxTimeInterval < 1 { + targetMaxTimeInterval = 0 + } + } + } + + /// Option: the desired number of archived log files to keep (number of log files may exceed this, it's a guideline only) + open var targetMaxLogFiles: UInt8 = 10 { + didSet { + cleanUpLogFiles() + } + } + + /// Option: the URL of the folder to store archived log files (defaults to the same folder as the initial log file) + open var archiveFolderURL: URL? = nil { + didSet { + guard let archiveFolderURL = archiveFolderURL else { return } + try? FileManager.default.createDirectory(at: archiveFolderURL, withIntermediateDirectories: true) + } + } + + /// Option: an optional closure to execute whenever the log is auto rotated + open var autoRotationCompletion: ((_ success: Bool) -> Void)? = nil + + /// A custom date formatter object to use as the suffix of archived log files + internal var _customArchiveSuffixDateFormatter: DateFormatter? = nil + /// The date formatter object to use as the suffix of archived log files + open var archiveSuffixDateFormatter: DateFormatter! { + get { + guard _customArchiveSuffixDateFormatter == nil else { return _customArchiveSuffixDateFormatter } + struct Statics { + static var archiveSuffixDateFormatter: DateFormatter = { + let defaultArchiveSuffixDateFormatter = DateFormatter() + defaultArchiveSuffixDateFormatter.locale = NSLocale.current + defaultArchiveSuffixDateFormatter.dateFormat = "_yyyy-MM-dd_HHmmss" + return defaultArchiveSuffixDateFormatter + }() + } + + return Statics.archiveSuffixDateFormatter + } + set { + _customArchiveSuffixDateFormatter = newValue + } + } + + /// Size of the current log file + internal var currentLogFileSize: UInt64 = 0 + + /// Start time of the current log file + internal var currentLogStartTimeInterval: TimeInterval = 0 + + /// The base file name of the log file + internal var baseFileName: String = "xcglogger" + + /// The extension of the log file name + internal var fileExtension: String = "log" + + // MARK: - Class Properties + /// A default folder for storing archived logs if one isn't supplied + open class var defaultLogFolderURL: URL { + #if os(OSX) + let defaultLogFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("log") + try? FileManager.default.createDirectory(at: defaultLogFolderURL, withIntermediateDirectories: true) + return defaultLogFolderURL + #elseif os(iOS) || os(tvOS) || os(watchOS) + let urls = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask) + let defaultLogFolderURL = urls[urls.endIndex - 1].appendingPathComponent("log") + try? FileManager.default.createDirectory(at: defaultLogFolderURL, withIntermediateDirectories: true) + return defaultLogFolderURL + #endif + } + + // MARK: - Life Cycle + public init(owner: XCGLogger? = nil, writeToFile: Any, identifier: String = "", shouldAppend: Bool = false, appendMarker: String? = "-- ** ** ** --", attributes: [FileAttributeKey: Any]? = nil, maxFileSize: UInt64 = autoRotatingFileDefaultMaxFileSize, maxTimeInterval: TimeInterval = autoRotatingFileDefaultMaxTimeInterval, archiveSuffixDateFormatter: DateFormatter? = nil, targetMaxLogFiles: UInt8 = 10) { + super.init(owner: owner, writeToFile: writeToFile, identifier: identifier, shouldAppend: true, appendMarker: shouldAppend ? appendMarker : nil, attributes: attributes) + + currentLogStartTimeInterval = Date().timeIntervalSince1970 + self.archiveSuffixDateFormatter = archiveSuffixDateFormatter + self.shouldAppend = shouldAppend + self.targetMaxFileSize = maxFileSize < 1 ? .max : maxFileSize + self.targetMaxTimeInterval = maxTimeInterval < 1 ? 0 : maxTimeInterval + self.targetMaxLogFiles = targetMaxLogFiles + + guard let writeToFileURL = writeToFileURL else { return } + + // Calculate some details for naming archived logs based on the current log file path/name + fileExtension = writeToFileURL.pathExtension + baseFileName = writeToFileURL.lastPathComponent + if let fileExtensionRange: Range = baseFileName.range(of: ".\(fileExtension)", options: .backwards), + fileExtensionRange.upperBound >= baseFileName.endIndex { + baseFileName = String(baseFileName[baseFileName.startIndex ..< fileExtensionRange.lowerBound]) + } + + let filePath: String = writeToFileURL.path + let logFileName: String = "\(baseFileName).\(fileExtension)" + if let logFileNameRange: Range = filePath.range(of: logFileName, options: .backwards), + logFileNameRange.upperBound >= filePath.endIndex { + let archiveFolderPath: String = String(filePath[filePath.startIndex ..< logFileNameRange.lowerBound]) + archiveFolderURL = URL(fileURLWithPath: "\(archiveFolderPath)") + } + if archiveFolderURL == nil { + archiveFolderURL = type(of: self).defaultLogFolderURL + } + + do { + // Initialize starting values for file size and start time so shouldRotate calculations are valid + let fileAttributes: [FileAttributeKey: Any] = try FileManager.default.attributesOfItem(atPath: filePath) + currentLogFileSize = fileAttributes[.size] as? UInt64 ?? 0 + currentLogStartTimeInterval = (fileAttributes[.creationDate] as? Date ?? Date()).timeIntervalSince1970 + } + catch let error as NSError { + owner?._logln("Unable to determine current file attributes of log file: \(error.localizedDescription)", level: .warning) + } + + // Because we always start by appending, regardless of the shouldAppend setting, we now need to handle the cases where we don't want to append or that we have now reached the rotation threshold for our current log file + if !shouldAppend || shouldRotate() { + rotateFile() + } + } + + /// Scan the log folder and delete log files that are no longer relevant. + /// + /// - Parameters: None. + /// + /// - Returns: Nothing. + /// + open func cleanUpLogFiles() { + var archivedFileURLs: [URL] = self.archivedFileURLs() + guard archivedFileURLs.count > Int(targetMaxLogFiles) else { return } + + archivedFileURLs.removeFirst(Int(targetMaxLogFiles)) + + let fileManager: FileManager = FileManager.default + for archivedFileURL in archivedFileURLs { + do { + try fileManager.removeItem(at: archivedFileURL) + } + catch let error as NSError { + owner?._logln("Unable to delete old archived log file \(archivedFileURL.path): \(error.localizedDescription)", level: .error) + } + } + } + + /// Delete all archived log files. + /// + /// - Parameters: None. + /// + /// - Returns: Nothing. + /// + open func purgeArchivedLogFiles() { + let fileManager: FileManager = FileManager.default + for archivedFileURL in archivedFileURLs() { + do { + try fileManager.removeItem(at: archivedFileURL) + } + catch let error as NSError { + owner?._logln("Unable to delete old archived log file \(archivedFileURL.path): \(error.localizedDescription)", level: .error) + } + } + } + + /// Get the URLs of the archived log files. + /// + /// - Parameters: None. + /// + /// - Returns: An array of file URLs pointing to previously archived log files, sorted with the most recent logs first. + /// + open func archivedFileURLs() -> [URL] { + let archiveFolderURL: URL = (self.archiveFolderURL ?? type(of: self).defaultLogFolderURL) + guard let fileURLs = try? FileManager.default.contentsOfDirectory(at: archiveFolderURL, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) else { return [] } + guard let identifierData: Data = identifier.data(using: .utf8) else { return [] } + + var archivedDetails: [(url: URL, timestamp: String)] = [] + for fileURL in fileURLs { + guard let archivedLogIdentifierOptionalData = ((try? fileURL.extendedAttribute(forName: XCGLogger.Constants.extendedAttributeArchivedLogIdentifierKey)) as Data??) else { continue } + guard let archivedLogIdentifierData = archivedLogIdentifierOptionalData else { continue } + guard archivedLogIdentifierData == identifierData else { continue } + + guard let timestampOptionalData = ((try? fileURL.extendedAttribute(forName: XCGLogger.Constants.extendedAttributeArchivedLogTimestampKey)) as Data??) else { continue } + guard let timestampData = timestampOptionalData else { continue } + guard let timestamp = String(data: timestampData, encoding: .utf8) else { continue } + + archivedDetails.append((fileURL, timestamp)) + } + + archivedDetails.sort(by: { (lhs, rhs) -> Bool in lhs.timestamp > rhs.timestamp }) + var archivedFileURLs: [URL] = [] + for archivedDetail in archivedDetails { + archivedFileURLs.append(archivedDetail.url) + } + + return archivedFileURLs + } + + /// Rotate the current log file. + /// + /// - Parameters: None. + /// + /// - Returns: Nothing. + /// + open func rotateFile() { + var archiveFolderURL: URL = (self.archiveFolderURL ?? type(of: self).defaultLogFolderURL) + archiveFolderURL = archiveFolderURL.appendingPathComponent("\(baseFileName)\(archiveSuffixDateFormatter.string(from: Date()))") + archiveFolderURL = archiveFolderURL.appendingPathExtension(fileExtension) + rotateFile(to: archiveFolderURL, closure: autoRotationCompletion) + + currentLogStartTimeInterval = Date().timeIntervalSince1970 + currentLogFileSize = 0 + + cleanUpLogFiles() + } + + /// Determine if the log file should be rotated. + /// + /// - Parameters: None. + /// + /// - Returns: + /// - true: The log file should be rotated. + /// - false: The log file doesn't have to be rotated. + /// + open func shouldRotate() -> Bool { + // Do not rotate until critical setup has been completed so that we do not accidentally rotate once to the defaultLogFolderURL before determining the desired log location + guard archiveFolderURL != nil else { return false } + + // File Size + guard currentLogFileSize < targetMaxFileSize else { return true } + + // Time Interval, zero = never rotate + guard targetMaxTimeInterval > 0 else { return false } + + // Time Interval, else check time + guard Date().timeIntervalSince1970 - currentLogStartTimeInterval < targetMaxTimeInterval else { return true } + + return false + } + + // MARK: - Overridden Methods + /// Write the log to the log file. + /// + /// - Parameters: + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open override func write(message: String) { + currentLogFileSize += UInt64(message.count) + + super.write(message: message) + + if shouldRotate() { + rotateFile() + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseDestination.swift new file mode 100644 index 0000000..470d755 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseDestination.swift @@ -0,0 +1,181 @@ +// +// BaseDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation + +// MARK: - BaseDestination +/// A base class destination that doesn't actually output the log anywhere and is intended to be subclassed +open class BaseDestination: DestinationProtocol, CustomDebugStringConvertible { + // MARK: - Properties + /// Logger that owns the destination object + open var owner: XCGLogger? + + /// Identifier for the destination (should be unique) + open var identifier: String + + /// Log level for this destination + open var outputLevel: XCGLogger.Level = .debug + + /// Flag whether or not we've logged the app details to this destination + open var haveLoggedAppDetails: Bool = false + + /// Array of log formatters to apply to messages before they're output + open var formatters: [LogFormatterProtocol]? = nil + + /// Array of log filters to apply to messages before they're output + open var filters: [FilterProtocol]? = nil + + /// Option: whether or not to output the log identifier + open var showLogIdentifier: Bool = false + + /// Option: whether or not to output the function name that generated the log + open var showFunctionName: Bool = true + + /// Option: whether or not to output the thread's name the log was created on + open var showThreadName: Bool = false + + /// Option: whether or not to output the fileName that generated the log + open var showFileName: Bool = true + + /// Option: whether or not to output the line number where the log was generated + open var showLineNumber: Bool = true + + /// Option: whether or not to output the log level of the log + open var showLevel: Bool = true + + /// Option: whether or not to output the date the log was created + open var showDate: Bool = true + + /// Option: override descriptions of log levels + open var levelDescriptions: [XCGLogger.Level: String] = [:] + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + return "\(extractTypeName(self)): \(identifier) - Level: \(outputLevel) showLogIdentifier: \(showLogIdentifier) showFunctionName: \(showFunctionName) showThreadName: \(showThreadName) showLevel: \(showLevel) showFileName: \(showFileName) showLineNumber: \(showLineNumber) showDate: \(showDate)" + } + } + + // MARK: - Life Cycle + public init(owner: XCGLogger? = nil, identifier: String = "") { + self.owner = owner + self.identifier = identifier + } + + // MARK: - Methods to Process Log Details + /// Process the log details. + /// + /// - Parameters: + /// - logDetails: Structure with all of the details for the log to process. + /// + /// - Returns: Nothing + /// + open func process(logDetails: LogDetails) { + guard let owner = owner else { return } + + var extendedDetails: String = "" + + if showDate { + extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: logDetails.date) : logDetails.date.description) " + } + + if showLevel { + extendedDetails += "[\(levelDescriptions[logDetails.level] ?? owner.levelDescriptions[logDetails.level] ?? logDetails.level.description)] " + } + + if showLogIdentifier { + extendedDetails += "[\(owner.identifier)] " + } + + if showThreadName { + if Thread.isMainThread { + extendedDetails += "[main] " + } + else { + if let threadName = Thread.current.name, !threadName.isEmpty { + extendedDetails += "[\(threadName)] " + } + else if let queueName = DispatchQueue.currentQueueLabel, !queueName.isEmpty { + extendedDetails += "[\(queueName)] " + } + else { + extendedDetails += String(format: "[%p] ", Thread.current) + } + } + } + + if showFileName { + extendedDetails += "[\((logDetails.fileName as NSString).lastPathComponent)\((showLineNumber ? ":" + String(logDetails.lineNumber) : ""))] " + } + else if showLineNumber { + extendedDetails += "[\(logDetails.lineNumber)] " + } + + if showFunctionName { + extendedDetails += "\(logDetails.functionName) " + } + + output(logDetails: logDetails, message: "\(extendedDetails)> \(logDetails.message)") + } + + /// Process the log details (internal use, same as process(logDetails:) but omits function/file/line info). + /// + /// - Parameters: + /// - logDetails: Structure with all of the details for the log to process. + /// + /// - Returns: Nothing + /// + open func processInternal(logDetails: LogDetails) { + guard let owner = owner else { return } + + var extendedDetails: String = "" + + if showDate { + extendedDetails += "\((owner.dateFormatter != nil) ? owner.dateFormatter!.string(from: logDetails.date) : logDetails.date.description) " + } + + if showLevel { + extendedDetails += "[\(logDetails.level)] " + } + + if showLogIdentifier { + extendedDetails += "[\(owner.identifier)] " + } + + output(logDetails: logDetails, message: "\(extendedDetails)> \(logDetails.message)") + } + + // MARK: - Misc methods + /// Check if the destination's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: The log level to check. + /// + /// - Returns: + /// - true: Log destination is at the log level specified or lower. + /// - false: Log destination is at a higher log level. + /// + open func isEnabledFor(level: XCGLogger.Level) -> Bool { + return level >= self.outputLevel + } + + // MARK: - Methods that must be overridden in subclasses + /// Output the log to the destination. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open func output(logDetails: LogDetails, message: String) { + // Do something with the text in an overridden version of this method + precondition(false, "Must override this") + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseQueuedDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseQueuedDestination.swift new file mode 100644 index 0000000..bd17d2d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/BaseQueuedDestination.swift @@ -0,0 +1,64 @@ +// +// BaseQueuedDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2017-04-02. +// Copyright © 2017 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation +import Dispatch + +// MARK: - BaseQueuedDestination +/// A base class destination (with a possible DispatchQueue) that doesn't actually output the log anywhere and is intended to be subclassed +open class BaseQueuedDestination: BaseDestination { + // MARK: - Properties + /// The dispatch queue to process the log on + open var logQueue: DispatchQueue? = nil + + // MARK: - Life Cycle + + // MARK: - Overridden Methods + /// Apply filters and formatters to the message before queuing it to be written by the write method. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Message ready to be formatted for output. + /// + /// - Returns: Nothing + /// + open override func output(logDetails: LogDetails, message: String) { + let outputClosure = { + // Create mutable versions of our parameters + var logDetails = logDetails + var message = message + + // Apply filters, if any indicate we should drop the message, we abort before doing the actual logging + guard !self.shouldExclude(logDetails: &logDetails, message: &message) else { return } + + self.applyFormatters(logDetails: &logDetails, message: &message) + self.write(message: message) + } + + if let logQueue = logQueue { + logQueue.async(execute: outputClosure) + } + else { + outputClosure() + } + } + + // MARK: - Methods that must be overridden in subclasses + /// Write the log message to the destination. + /// + /// - Parameters: + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open func write(message: String) { + // Do something with the message in an overridden version of this method + precondition(false, "Must override this") + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/ConsoleDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/ConsoleDestination.swift new file mode 100644 index 0000000..1683cdf --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/ConsoleDestination.swift @@ -0,0 +1,26 @@ +// +// ConsoleDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Dispatch + +// MARK: - ConsoleDestination +/// A standard destination that outputs log details to the console +open class ConsoleDestination: BaseQueuedDestination { + // MARK: - Overridden Methods + /// Print the log to the console. + /// + /// - Parameters: + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open override func write(message: String) { + print(message) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/DestinationProtocol.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/DestinationProtocol.swift new file mode 100644 index 0000000..d10e761 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/DestinationProtocol.swift @@ -0,0 +1,124 @@ +// +// DestinationProtocol.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - DestinationProtocol +/// Protocol for destination classes to conform to +public protocol DestinationProtocol: CustomDebugStringConvertible { + // MARK: - Properties + /// Logger that owns the destination object + var owner: XCGLogger? {get set} + + /// Identifier for the destination (should be unique) + var identifier: String {get set} + + /// Log level for this destination + var outputLevel: XCGLogger.Level {get set} + + /// Flag whether or not we've logged the app details to this destination + var haveLoggedAppDetails: Bool { get set } + + /// Array of log formatters to apply to messages before they're output + var formatters: [LogFormatterProtocol]? { get set } + + /// Array of log filters to apply to messages before they're output + var filters: [FilterProtocol]? { get set } + + // MARK: - Methods + /// Process the log details. + /// + /// - Parameters: + /// - logDetails: Structure with all of the details for the log to process. + /// + /// - Returns: Nothing + /// + func process(logDetails: LogDetails) + + /// Process the log details (internal use, same as processLogDetails but omits function/file/line info). + /// + /// - Parameters: + /// - logDetails: Structure with all of the details for the log to process. + /// + /// - Returns: Nothing + /// + func processInternal(logDetails: LogDetails) + + /// Check if the destination's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: The log level to check. + /// + /// - Returns: + /// - true: Log destination is at the log level specified or lower. + /// - false: Log destination is at a higher log level. + /// + func isEnabledFor(level: XCGLogger.Level) -> Bool + + /// Apply filters to determine if the log message should be logged. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: + /// - true: Drop this log message. + /// - false: Keep this log message and continue processing. + /// + func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool + + /// Apply formatters. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + func applyFormatters(logDetails: inout LogDetails, message: inout String) +} + +extension DestinationProtocol { + + /// Iterate over all of the log filters in this destination, or the logger if none set for the destination. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: + /// - true: Drop this log message. + /// - false: Keep this log message and continue processing. + /// + public func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool { + guard let filters = self.filters ?? self.owner?.filters, filters.count > 0 else { return false } + + for filter in filters { + if filter.shouldExclude(logDetails: &logDetails, message: &message) { + return true + } + } + + return false + } + + /// Iterate over all of the log formatters in this destination, or the logger if none set for the destination. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + public func applyFormatters(logDetails: inout LogDetails, message: inout String) { + guard let formatters = self.formatters ?? self.owner?.formatters, formatters.count > 0 else { return } + + for formatter in formatters { + formatter.format(logDetails: &logDetails, message: &message) + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/FileDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/FileDestination.swift new file mode 100644 index 0000000..c0f5def --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/FileDestination.swift @@ -0,0 +1,245 @@ +// +// FileDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation +import Dispatch + +// MARK: - FileDestination +/// A standard destination that outputs log details to a file +open class FileDestination: BaseQueuedDestination { + // MARK: - Properties + /// Logger that owns the destination object + open override var owner: XCGLogger? { + didSet { + if owner != nil { + openFile() + } + else { + closeFile() + } + } + } + + /// FileURL of the file to log to + open var writeToFileURL: URL? = nil { + didSet { + openFile() + } + } + + /// File handle for the log file + internal var logFileHandle: FileHandle? = nil + + /// Option: whether or not to append to the log file if it already exists + internal var shouldAppend: Bool + + /// Option: if appending to the log file, the string to output at the start to mark where the append took place + internal var appendMarker: String? + + /// Option: Attributes to use when creating a new file + internal var fileAttributes: [FileAttributeKey: Any]? = nil + + // MARK: - Life Cycle + public init(owner: XCGLogger? = nil, writeToFile: Any, identifier: String = "", shouldAppend: Bool = false, appendMarker: String? = "-- ** ** ** --", attributes: [FileAttributeKey: Any]? = nil) { + self.shouldAppend = shouldAppend + self.appendMarker = appendMarker + self.fileAttributes = attributes + + if writeToFile is NSString { + writeToFileURL = URL(fileURLWithPath: writeToFile as! String) + } + else if let writeToFile = writeToFile as? URL, writeToFile.isFileURL { + writeToFileURL = writeToFile + } + else { + writeToFileURL = nil + } + + super.init(owner: owner, identifier: identifier) + + if owner != nil { + openFile() + } + } + + deinit { + // close file stream if open + closeFile() + } + + // MARK: - File Handling Methods + /// Open the log file for writing. + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + private func openFile() { + guard let owner = owner else { return } + + if logFileHandle != nil { + closeFile() + } + + guard let writeToFileURL = writeToFileURL else { return } + + let fileManager: FileManager = FileManager.default + let fileExists: Bool = fileManager.fileExists(atPath: writeToFileURL.path) + if !shouldAppend || !fileExists { + fileManager.createFile(atPath: writeToFileURL.path, contents: nil, attributes: fileAttributes) + } + + do { + logFileHandle = try FileHandle(forWritingTo: writeToFileURL) + if fileExists && shouldAppend { + logFileHandle?.seekToEndOfFile() + + if let appendMarker = appendMarker, + let encodedData = "\(appendMarker)\n".data(using: String.Encoding.utf8) { + + _try({ + self.logFileHandle?.write(encodedData) + }, + catch: { (exception: NSException) in + print("Objective-C Exception occurred: \(exception)") + }) + } + } + } + catch let error as NSError { + owner._logln("Attempt to open log file for \(fileExists && shouldAppend ? "appending" : "writing") failed: \(error.localizedDescription)", level: .error, source: self) + logFileHandle = nil + return + } + + owner.logAppDetails(selectedDestination: self) + + let logDetails = LogDetails(level: .info, date: Date(), message: "XCGLogger " + (fileExists && shouldAppend ? "appending" : "writing") + " log to: " + writeToFileURL.absoluteString, functionName: "", fileName: "", lineNumber: 0, userInfo: XCGLogger.Constants.internalUserInfo) + owner._logln(logDetails.message, level: logDetails.level, source: self) + if owner.destination(withIdentifier: identifier) == nil { + processInternal(logDetails: logDetails) + } + } + + /// Close the log file. + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + private func closeFile() { + logFileHandle?.synchronizeFile() + logFileHandle?.closeFile() + logFileHandle = nil + } + + /// Force any buffered data to be written to the file. + /// + /// - Parameters: + /// - closure: An optional closure to execute after the file has been rotated. + /// + /// - Returns: Nothing. + /// + open func flush(closure: (() -> Void)? = nil) { + if let logQueue = logQueue { + logQueue.async { + self.logFileHandle?.synchronizeFile() + closure?() + } + } + else { + logFileHandle?.synchronizeFile() + closure?() + } + } + + /// Rotate the log file, storing the existing log file in the specified location. + /// + /// - Parameters: + /// - archiveToFile: FileURL or path (as String) to where the existing log file should be rotated to. + /// - closure: An optional closure to execute after the file has been rotated. + /// + /// - Returns: + /// - true: Log file rotated successfully. + /// - false: Error rotating the log file. + /// + @discardableResult open func rotateFile(to archiveToFile: Any, closure: ((_ success: Bool) -> Void)? = nil) -> Bool { + var archiveToFileURL: URL? = nil + + if archiveToFile is NSString { + archiveToFileURL = URL(fileURLWithPath: archiveToFile as! String) + } + else if let archiveToFile = archiveToFile as? URL, archiveToFile.isFileURL { + archiveToFileURL = archiveToFile + } + else { + closure?(false) + return false + } + + if let archiveToFileURL = archiveToFileURL, + let writeToFileURL = writeToFileURL { + + let fileManager: FileManager = FileManager.default + guard !fileManager.fileExists(atPath: archiveToFileURL.path) else { closure?(false); return false } + + closeFile() + haveLoggedAppDetails = false + + do { + try fileManager.moveItem(atPath: writeToFileURL.path, toPath: archiveToFileURL.path) + } + catch let error as NSError { + openFile() + owner?._logln("Unable to rotate file \(writeToFileURL.path) to \(archiveToFileURL.path): \(error.localizedDescription)", level: .error, source: self) + closure?(false) + return false + } + + do { + if let identifierData: Data = identifier.data(using: .utf8) { + try archiveToFileURL.setExtendedAttribute(data: identifierData, forName: XCGLogger.Constants.extendedAttributeArchivedLogIdentifierKey) + } + if let timestampData: Data = "\(Date().timeIntervalSince1970)".data(using: .utf8) { + try archiveToFileURL.setExtendedAttribute(data: timestampData, forName: XCGLogger.Constants.extendedAttributeArchivedLogTimestampKey) + } + } + catch let error as NSError { + owner?._logln("Unable to set extended file attributes on file \(archiveToFileURL.path): \(error.localizedDescription)", level: .error, source: self) + } + + owner?._logln("Rotated file \(writeToFileURL.path) to \(archiveToFileURL.path)", level: .info, source: self) + openFile() + closure?(true) + return true + } + + closure?(false) + return false + } + + // MARK: - Overridden Methods + /// Write the log to the log file. + /// + /// - Parameters: + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open override func write(message: String) { + if let encodedData = "\(message)\n".data(using: String.Encoding.utf8) { + _try({ + self.logFileHandle?.write(encodedData) + }, + catch: { (exception: NSException) in + print("Objective-C Exception occurred: \(exception)") + }) + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/TestDestination.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/TestDestination.swift new file mode 100644 index 0000000..fae5f51 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Destinations/TestDestination.swift @@ -0,0 +1,109 @@ +// +// TestDestination.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-26. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Dispatch + +// MARK: - TestDestination +/// A destination for testing, preload it with the expected logs, send your logs, then check for success +open class TestDestination: BaseQueuedDestination { + // MARK: - Properties + /// Array of all expected log messages + open var expectedLogMessages: [String] = [] + + /// Array of received, unexpected log messages + open var unexpectedLogMessages: [String] = [] + + /// Number of log messages still expected + open var remainingNumberOfExpectedLogMessages: Int { + get { + return expectedLogMessages.count + } + } + + /// Number of unexpected log messages + open var numberOfUnexpectedLogMessages: Int { + get { + return unexpectedLogMessages.count + } + } + + /// Add the messages you expect to be logged + /// + /// - Parameters: + /// - expectedLogMessage: The log message, formated as you expect it to be received. + /// + /// - Returns: Nothing + /// + open func add(expectedLogMessage message: String) { + sync { + expectedLogMessages.append(message) + } + } + + /// Execute a closure on the logQueue if it exists, otherwise just execute on the current thread + /// + /// - Parameters: + /// - closure: The closure to execute. + /// + /// - Returns: Nothing + /// + fileprivate func sync(closure: () -> ()) { + if let logQueue = logQueue { + logQueue.sync { + closure() + } + } + else { + closure() + } + } + + /// Reset our expectations etc for additional tests + /// + /// - Parameters: Nothing + /// + /// - Returns: Nothing + /// + open func reset() { + haveLoggedAppDetails = false + expectedLogMessages = [] + unexpectedLogMessages = [] + } + + // MARK: - Overridden Methods + /// Removes line from expected log messages if there's a match, otherwise adds to unexpected log messages. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + open override func output(logDetails: LogDetails, message: String) { + sync { + var logDetails = logDetails + var message = message + + // Apply filters, if any indicate we should drop the message, we abort before doing the actual logging + if self.shouldExclude(logDetails: &logDetails, message: &message) { + return + } + + applyFormatters(logDetails: &logDetails, message: &message) + + let index = expectedLogMessages.firstIndex(of: message) + if let index = index { + expectedLogMessages.remove(at: index) + } + else { + unexpectedLogMessages.append(message) + } + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/DispatchQueue+XCGAdditions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/DispatchQueue+XCGAdditions.swift new file mode 100644 index 0000000..0e17e2f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/DispatchQueue+XCGAdditions.swift @@ -0,0 +1,19 @@ +// +// DispatchQueue+XCGAdditions.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-26. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Dispatch + +/// Extensions to the DispatchQueue class +extension DispatchQueue { + + /// Extract the current dispatch queue's label name (Temp workaround until this is added to Swift 3.0 properly) + public static var currentQueueLabel: String? { + return String(validatingUTF8: __dispatch_queue_get_label(nil)) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/URL+XCGAdditions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/URL+XCGAdditions.swift new file mode 100644 index 0000000..ba8f605 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Extensions/URL+XCGAdditions.swift @@ -0,0 +1,82 @@ +// +// URL+ExtendedAttributes.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2017-04-04. +// Copyright © 2017 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// +// Based on code by Martin-R here: https://stackoverflow.com/a/38343753/144857 + +import Foundation + +extension URL { + + /// Get extended attribute. + func extendedAttribute(forName name: String) throws -> Data? { + let data: Data? = try self.withUnsafeFileSystemRepresentation { (fileSystemPath: (UnsafePointer?)) -> Data? in + // Determine attribute size + let length: Int = getxattr(fileSystemPath, name, nil, 0, 0, 0) + guard length >= 0 else { return nil } + + // Create buffer with required size + var data: Data = Data(count: length) + + // Retrieve attribute + let result: Int = data.withUnsafeMutableBytes { [count = data.count] (body: UnsafeMutableRawBufferPointer) -> Int in + getxattr(fileSystemPath, name, body.baseAddress, count, 0, 0) + } + guard result >= 0 else { throw URL.posixError(errno) } + return data + } + + return data + } + + /// Set extended attribute. + func setExtendedAttribute(data: Data, forName name: String) throws { + try self.withUnsafeFileSystemRepresentation { fileSystemPath in + let result: Int32 = data.withUnsafeBytes { [count = data.count] (body: UnsafeRawBufferPointer) -> Int32 in + setxattr(fileSystemPath, name, body.baseAddress, count, 0, 0) + } + guard result >= 0 else { throw URL.posixError(errno) } + } + } + + /// Remove extended attribute. + func removeExtendedAttribute(forName name: String) throws { + try self.withUnsafeFileSystemRepresentation { fileSystemPath in + let result: Int32 = removexattr(fileSystemPath, name, 0) + guard result >= 0 else { throw URL.posixError(errno) } + } + } + + /// Get list of all extended attributes. + func listExtendedAttributes() throws -> [String] { + let list: [String] = try self.withUnsafeFileSystemRepresentation { (fileSystemPath: (UnsafePointer?)) -> [String] in + let length: Int = listxattr(fileSystemPath, nil, 0, 0) + guard length >= 0 else { throw URL.posixError(errno) } + + // Create buffer with required size + var data: Data = Data(count: length) + + // Retrieve attribute list + let result: Int = data.withUnsafeMutableBytes { [count = data.count] (body: UnsafeMutableRawBufferPointer) -> Int in + return listxattr(fileSystemPath, UnsafeMutablePointer(OpaquePointer(body.baseAddress)), count, 0) + } + guard result >= 0 else { throw URL.posixError(errno) } + + // Extract attribute names + let list: [String] = data.split(separator: 0).compactMap { + String(data: Data($0), encoding: .utf8) + } + return list + } + return list + } + + /// Helper function to create an NSError from a Unix errno. + private static func posixError(_ err: Int32) -> NSError { + return NSError(domain: NSPOSIXErrorDomain, code: Int(err), userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))]) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/DevFilter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/DevFilter.swift new file mode 100644 index 0000000..101f889 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/DevFilter.swift @@ -0,0 +1,37 @@ +// +// DevFilter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-09-01. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - DevFilter +/// Filter log messages by devs +open class DevFilter: UserInfoFilter { + + /// Initializer to create an inclusion list of devs to match against + /// + /// Note: Only log messages with a specific dev will be logged, all others will be excluded + /// + /// - Parameters: + /// - devs: Set or Array of devs to match against. + /// + public override init(includeFrom devs: S) where S.Iterator.Element == String { + super.init(includeFrom: devs) + userInfoKey = XCGLogger.Constants.userInfoKeyDevs + } + + /// Initializer to create an exclusion list of devs to match against + /// + /// Note: Log messages with a specific dev will be excluded from logging + /// + /// - Parameters: + /// - devs: Set or Array of devs to match against. + /// + public override init(excludeFrom devs: S) where S.Iterator.Element == String { + super.init(excludeFrom: devs) + userInfoKey = XCGLogger.Constants.userInfoKeyDevs + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FileNameFilter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FileNameFilter.swift new file mode 100644 index 0000000..a5f2d80 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FileNameFilter.swift @@ -0,0 +1,126 @@ +// +// FileNameFilter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-31. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation + +// MARK: - FileNameFilter +/// Filter log messages by fileName +open class FileNameFilter: FilterProtocol { + + /// Option to toggle the match results + open var inverse: Bool = false + + /// Option to match full path or just the fileName + private var excludePath: Bool = true + + /// Internal list of fileNames to match against + private var fileNamesToMatch: Set = [] + + /// Initializer to create an inclusion list of fileNames to match against + /// + /// Note: Only log messages from the specified files will be logged, all others will be excluded + /// + /// - Parameters: + /// - fileNames: Set or Array of fileNames to match against. + /// - excludePathWhenMatching: Whether or not to ignore the path for matches. **Default: true ** + /// + public init(includeFrom fileNames: S, excludePathWhenMatching: Bool = true) where S.Iterator.Element == String { + inverse = true + excludePath = excludePathWhenMatching + add(fileNames: fileNames) + } + + /// Initializer to create an exclusion list of fileNames to match against + /// + /// Note: Log messages from the specified files will be excluded from logging + /// + /// - Parameters: + /// - fileNames: Set or Array of fileNames to match against. + /// - excludePathWhenMatching: Whether or not to ignore the path for matches. **Default: true ** + /// + public init(excludeFrom fileNames: S, excludePathWhenMatching: Bool = true) where S.Iterator.Element == String { + inverse = false + excludePath = excludePathWhenMatching + add(fileNames: fileNames) + } + + /// Add another fileName to the list of names to match against. + /// + /// - Parameters: + /// - fileName: Name of the file to match against. + /// + /// - Returns: + /// - true: FileName added. + /// - false: FileName already added. + /// + @discardableResult open func add(fileName: String) -> Bool { + return fileNamesToMatch.insert(excludePath ? (fileName as NSString).lastPathComponent : fileName).inserted + } + + /// Add a list of fileNames to the list of names to match against. + /// + /// - Parameters: + /// - fileNames: Set or Array of fileNames to match against. + /// + /// - Returns: Nothing + /// + open func add(fileNames: S) where S.Iterator.Element == String { + for fileName in fileNames { + add(fileName: fileName) + } + } + + /// Clear the list of fileNames to match against. + /// + /// - Note: Doesn't change whether or not the filter is inclusive of exclusive + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func clear() { + fileNamesToMatch = [] + } + + /// Check if the log message should be excluded from logging. + /// + /// - Note: If the fileName matches + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: + /// - true: Drop this log message. + /// - false: Keep this log message and continue processing. + /// + open func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool { + var matched: Bool = fileNamesToMatch.contains(excludePath ? (logDetails.fileName as NSString).lastPathComponent : logDetails.fileName) + if inverse { + matched = !matched + } + + return matched + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): " + (inverse ? "Including only matches for: " : "Excluding matches for: ") + if fileNamesToMatch.count > 5 { + description += "\n\t- " + fileNamesToMatch.sorted().joined(separator: "\n\t- ") + } + else { + description += fileNamesToMatch.sorted().joined(separator: ", ") + } + + return description + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FilterProtocol.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FilterProtocol.swift new file mode 100644 index 0000000..acb3edb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/FilterProtocol.swift @@ -0,0 +1,25 @@ +// +// FilterProtocol.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-31. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - FilterProtocol +/// Protocol for log filter classes to conform to +public protocol FilterProtocol: CustomDebugStringConvertible { + + /// Check if the log message should be excluded from logging. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: + /// - true: Drop this log message. + /// - false: Keep this log message and continue processing. + /// + func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/TagFilter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/TagFilter.swift new file mode 100644 index 0000000..edb20f8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/TagFilter.swift @@ -0,0 +1,37 @@ +// +// TagFilter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-09-01. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - TagFilter +/// Filter log messages by tags +open class TagFilter: UserInfoFilter { + + /// Initializer to create an inclusion list of tags to match against + /// + /// Note: Only log messages with a specific tag will be logged, all others will be excluded + /// + /// - Parameters: + /// - tags: Set or Array of tags to match against. + /// + public override init(includeFrom tags: S) where S.Iterator.Element == String { + super.init(includeFrom: tags) + userInfoKey = XCGLogger.Constants.userInfoKeyTags + } + + /// Initializer to create an exclusion list of tags to match against + /// + /// Note: Log messages with a specific tag will be excluded from logging + /// + /// - Parameters: + /// - tags: Set or Array of tags to match against. + /// + public override init(excludeFrom tags: S) where S.Iterator.Element == String { + super.init(excludeFrom: tags) + userInfoKey = XCGLogger.Constants.userInfoKeyTags + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/UserInfoFilter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/UserInfoFilter.swift new file mode 100644 index 0000000..a397c33 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Filters/UserInfoFilter.swift @@ -0,0 +1,143 @@ +// +// UserInfoFilter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-09-01. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - UserInfoFilter +/// Filter log messages by the contents of a key in the UserInfo dictionary +/// Note: - This is intended to be subclassed, unlikely you'll use it directly +open class UserInfoFilter: FilterProtocol { + + /// The key to check in the LogDetails.userInfo dictionary + open var userInfoKey: String = "" + + /// Option to also apply the filter to internal messages (ie, app details, error's opening files etc) + open var applyFilterToInternalMessages: Bool = false + + /// Option to toggle the match results + open var inverse: Bool = false + + /// Internal list of items to match against + private var itemsToMatch: Set = [] + + /// Initializer to create an inclusion list of items to match against + /// + /// Note: Only log messages with a specific item will be logged, all others will be excluded + /// + /// - Parameters: + /// - items: Set or Array of items to match against. + /// + public init(includeFrom items: S) where S.Iterator.Element == String { + inverse = true + add(items: items) + } + + /// Initializer to create an exclusion list of items to match against + /// + /// Note: Log messages with a specific item will be excluded from logging + /// + /// - Parameters: + /// - items: Set or Array of items to match against. + /// + public init(excludeFrom items: S) where S.Iterator.Element == String { + inverse = false + add(items: items) + } + + /// Add another fileName to the list of names to match against. + /// + /// - Parameters: + /// - item: Item to match against. + /// + /// - Returns: + /// - true: FileName added. + /// - false: FileName already added. + /// + @discardableResult open func add(item: String) -> Bool { + return itemsToMatch.insert(item).inserted + } + + /// Add a list of fileNames to the list of names to match against. + /// + /// - Parameters: + /// - items: Set or Array of fileNames to match against. + /// + /// - Returns: Nothing + /// + open func add(items: S) where S.Iterator.Element == String { + for item in items { + add(item: item) + } + } + + /// Clear the list of fileNames to match against. + /// + /// - Note: Doesn't change whether or not the filter is inclusive of exclusive + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func clear() { + itemsToMatch = [] + } + + /// Check if the log message should be excluded from logging. + /// + /// - Note: If the fileName matches + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: + /// - true: Drop this log message. + /// - false: Keep this log message and continue processing. + /// + open func shouldExclude(logDetails: inout LogDetails, message: inout String) -> Bool { + var matched: Bool = false + + if !applyFilterToInternalMessages, + let isInternal = logDetails.userInfo[XCGLogger.Constants.userInfoKeyInternal] as? Bool, + isInternal { + return inverse + } + + if let messageItemsObject = logDetails.userInfo[userInfoKey] { + if let messageItemsSet: Set = messageItemsObject as? Set { + matched = itemsToMatch.intersection(messageItemsSet).count > 0 + } + else if let messageItemsArray: Array = messageItemsObject as? Array { + matched = itemsToMatch.intersection(messageItemsArray).count > 0 + } + else if let messageItem = messageItemsObject as? String { + matched = itemsToMatch.contains(messageItem) + } + } + + if inverse { + matched = !matched + } + + return matched + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): \(applyFilterToInternalMessages ? "(Filtering Internal) " : "")" + (inverse ? "Including only matches for: " : "Excluding matches for: ") + if itemsToMatch.count > 5 { + description += "\n\t- " + itemsToMatch.sorted().joined(separator: "\n\t- ") + } + else { + description += itemsToMatch.sorted().joined(separator: ", ") + } + + return description + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/ANSIColorLogFormatter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/ANSIColorLogFormatter.swift new file mode 100644 index 0000000..20ed8de --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/ANSIColorLogFormatter.swift @@ -0,0 +1,342 @@ +// +// ANSIColorLogFormatter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-30. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - ANSIColorLogFormatter +/// A log formatter that will add ANSI colour codes to the message +open class ANSIColorLogFormatter: LogFormatterProtocol, CustomDebugStringConvertible { + + /// ANSI Escape code + public static let escape: String = "\u{001b}[" + + /// ANSI Reset colours code + public static let reset: String = "\(escape)m" + + /// Enum to specify ANSI colours + public enum ANSIColor: CustomStringConvertible { + case black + case red + case green + case yellow + case blue + case magenta + case cyan + case lightGrey, lightGray + case darkGrey, darkGray + case lightRed + case lightGreen + case lightYellow + case lightBlue + case lightMagenta + case lightCyan + case white + case `default` + case rgb(red: Int, green: Int, blue: Int) + case colorIndex(number: Int) + + public var foregroundCode: String { + switch self { + case .black: + return "30" + case .red: + return "31" + case .green: + return "32" + case .yellow: + return "33" + case .blue: + return "34" + case .magenta: + return "35" + case .cyan: + return "36" + case .lightGrey, .lightGray: + return "37" + case .darkGrey, .darkGray: + return "90" + case .lightRed: + return "91" + case .lightGreen: + return "92" + case .lightYellow: + return "93" + case .lightBlue: + return "94" + case .lightMagenta: + return "95" + case .lightCyan: + return "96" + case .white: + return "97" + case .default: // Note: Different from the default: at the end of a switch, this is the `default` colour + return "39" + case .rgb(let red, let green, let blue): + return "38;2;\(min(max(0, red), 255));\(min(max(0, green), 255));\(min(max(0, blue), 255))" + case .colorIndex(let number): + return "38;5;\(min(max(0, number), 255))" + } + } + + public var backgroundCode: String { + switch self { + case .black: + return "40" + case .red: + return "41" + case .green: + return "42" + case .yellow: + return "43" + case .blue: + return "44" + case .magenta: + return "45" + case .cyan: + return "46" + case .lightGrey, .lightGray: + return "47" + case .darkGrey, .darkGray: + return "100" + case .lightRed: + return "101" + case .lightGreen: + return "102" + case .lightYellow: + return "103" + case .lightBlue: + return "104" + case .lightMagenta: + return "105" + case .lightCyan: + return "106" + case .white: + return "107" + case .default: // Note: Different from the default: at the end of a switch, this is the `default` colour + return "49" + case .rgb(let red, let green, let blue): + return "48;2;\(min(max(0, red), 255));\(min(max(0, green), 255));\(min(max(0, blue), 255))" + case .colorIndex(let number): + return "48;5;\(min(max(0, number), 255))" + } + } + + /// Human readable description of this colour (CustomStringConvertible) + public var description: String { + switch self { + case .black: + return "Black" + case .red: + return "Red" + case .green: + return "Green" + case .yellow: + return "Yellow" + case .blue: + return "Blue" + case .magenta: + return "Magenta" + case .cyan: + return "Cyan" + case .lightGrey, .lightGray: + return "Light Grey" + case .darkGrey, .darkGray: + return "Dark Grey" + case .lightRed: + return "Light Red" + case .lightGreen: + return "Light Green" + case .lightYellow: + return "Light Yellow" + case .lightBlue: + return "Light Blue" + case .lightMagenta: + return "Light Magenta" + case .lightCyan: + return "Light Cyan" + case .white: + return "White" + case .default: // Note: Different from the default: at the end of a switch, this is the `default` colour + return "Default" + case .rgb(let red, let green, let blue): + return String(format: "(r: %d, g: %d, b: %d) #%02X%02X%02X", red, green, blue, red, green, blue) + case .colorIndex(let number): + return "ANSI color index: \(number)" + } + } + } + + /// Enum to specific ANSI options + public enum ANSIOption: CustomStringConvertible { + case bold + case faint + case italic + case underline + case blink + case blinkFast + case strikethrough + + public var code: String { + switch self { + case .bold: + return "1" + case .faint: + return "2" + case .italic: + return "3" + case .underline: + return "4" + case .blink: + return "5" + case .blinkFast: + return "6" + case .strikethrough: + return "9" + } + } + + public var description: String { + switch self { + case .bold: + return "Bold" + case .faint: + return "Faint" + case .italic: + return "Italic" + case .underline: + return "Underline" + case .blink: + return "Blink" + case .blinkFast: + return "Blink Fast" + case .strikethrough: + return "Strikethrough" + } + } + } + + /// Internal cache of the ANSI codes for each log level + internal var formatStrings: [XCGLogger.Level: String] = [:] + + /// Internal cache of the description for each log level + internal var descriptionStrings: [XCGLogger.Level: String] = [:] + + public init() { + resetFormatting() + } + + /// Set the colours and/or options for a specific log level. + /// + /// - Parameters: + /// - level: The log level. + /// - foregroundColor: The text colour of the message. **Default:** Restore default text colour + /// - backgroundColor: The background colour of the message. **Default:** Restore default background colour + /// - options: Array of ANSIOptions to apply to the message. **Default:** No options + /// + /// - Returns: Nothing + /// + open func colorize(level: XCGLogger.Level, with foregroundColor: ANSIColor = .default, on backgroundColor: ANSIColor = .default, options: [ANSIOption] = []) { + var codes: [String] = [foregroundColor.foregroundCode, backgroundColor.backgroundCode] + var description: String = "\(foregroundColor) on \(backgroundColor)" + + for option in options { + codes.append(option.code) + description += "/\(option)" + } + + formatStrings[level] = ANSIColorLogFormatter.escape + codes.joined(separator: ";") + "m" + descriptionStrings[level] = description + } + + /// Set the colours and/or options for a specific log level. + /// + /// - Parameters: + /// - level: The log level. + /// - custom: A specific ANSI code to use. + /// + /// - Returns: Nothing + /// + open func colorize(level: XCGLogger.Level, custom: String) { + if custom.hasPrefix(ANSIColorLogFormatter.escape) { + formatStrings[level] = "\(custom)" + descriptionStrings[level] = "Custom: \(custom[custom.index(custom.startIndex, offsetBy: ANSIColorLogFormatter.escape.lengthOfBytes(using: .utf8)) ..< custom.endIndex])" + } + else { + formatStrings[level] = ANSIColorLogFormatter.escape + "\(custom)" + descriptionStrings[level] = "Custom: \(custom)" + } + } + + /// Get the cached ANSI codes for the specified log level. + /// + /// - Parameters: + /// - level: The log level. + /// + /// - Returns: The ANSI codes for the specified log level. + /// + internal func formatString(for level: XCGLogger.Level) -> String { + return formatStrings[level] ?? ANSIColorLogFormatter.reset + } + + /// Apply a default set of colours. + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func resetFormatting() { + colorize(level: .verbose, with: .white, options: [.bold]) + colorize(level: .debug, with: .black) + colorize(level: .info, with: .blue) + colorize(level: .warning, with: .yellow) + colorize(level: .error, with: .red, options: [.bold]) + colorize(level: .severe, with: .white, on: .red) + colorize(level: .none) + } + + /// Clear all previously set colours. (Sets each log level back to default) + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func clearFormatting() { + colorize(level: .verbose) + colorize(level: .debug) + colorize(level: .info) + colorize(level: .warning) + colorize(level: .error) + colorize(level: .severe) + colorize(level: .none) + } + + // MARK: - LogFormatterProtocol + /// Apply some additional formatting to the message if appropriate. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: message with the additional formatting + /// + @discardableResult open func format(logDetails: inout LogDetails, message: inout String) -> String { + message = "\(formatString(for: logDetails.level))\(message)\(ANSIColorLogFormatter.reset)" + return message + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): " + for level in XCGLogger.Level.allCases { + description += "\n\t- \(level) > \(descriptionStrings[level] ?? "None")" + } + + return description + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/Base64LogFormatter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/Base64LogFormatter.swift new file mode 100644 index 0000000..63f5809 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/Base64LogFormatter.swift @@ -0,0 +1,40 @@ +// +// Base64LogFormatter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-30. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - Base64LogFormatter +/// An example log formatter to show how encryption could be used to secure log messages, in this case, we just Base64 encode them +open class Base64LogFormatter: LogFormatterProtocol, CustomDebugStringConvertible { + + // MARK: - LogFormatterProtocol + /// Apply some additional formatting to the message if appropriate. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: message with the additional formatting + /// + @discardableResult open func format(logDetails: inout LogDetails, message: inout String) -> String { + guard let utf8Message = message.data(using: .utf8) else { return message } + + message = utf8Message.base64EncodedString() + return message + } + + /// Initializer, doesn't do anything other than make the class publicly available + public init() { + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + return "\(extractTypeName(self))" + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/LogFormatterProtocol.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/LogFormatterProtocol.swift new file mode 100644 index 0000000..be34293 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/LogFormatterProtocol.swift @@ -0,0 +1,23 @@ +// +// LogFormatterProtocol.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-30. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +// MARK: - LogFormatterProtocol +/// Protocol for log formatter classes to conform to +public protocol LogFormatterProtocol: CustomDebugStringConvertible { + + /// Apply some additional formatting to the message if appropriate. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: Nothing + /// + @discardableResult func format(logDetails: inout LogDetails, message: inout String) -> String +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/PrePostFixLogFormatter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/PrePostFixLogFormatter.swift new file mode 100644 index 0000000..a42090a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/PrePostFixLogFormatter.swift @@ -0,0 +1,100 @@ +// +// PrePostFixLogFormatter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-09-20. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +#if os(macOS) + import AppKit +#elseif os(iOS) || os(tvOS) || os(watchOS) + import UIKit +#endif + +// MARK: - PrePostFixLogFormatter +/// A log formatter that will optionally add a prefix, and/or postfix string to a message +open class PrePostFixLogFormatter: LogFormatterProtocol, CustomDebugStringConvertible { + + /// Internal cache of the prefix strings for each log level + internal var prefixStrings: [XCGLogger.Level: String] = [:] + + /// Internal cache of the postfix strings codes for each log level + internal var postfixStrings: [XCGLogger.Level: String] = [:] + + public init() { + } + + /// Set the prefix/postfix strings for a specific log level. + /// + /// - Parameters: + /// - prefix: A string to prepend to log messages. + /// - postfix: A string to postpend to log messages. + /// - level: The log level. + /// + /// - Returns: Nothing + /// + open func apply(prefix: String? = nil, postfix: String? = nil, to level: XCGLogger.Level? = nil) { + guard let level = level else { + guard prefix != nil || postfix != nil else { clearFormatting(); return } + + // No level specified, so, apply to all levels + for level in XCGLogger.Level.allCases { + self.apply(prefix: prefix, postfix: postfix, to: level) + } + return + } + + if let prefix = prefix { + prefixStrings[level] = prefix + } + else { + prefixStrings.removeValue(forKey: level) + } + + if let postfix = postfix { + postfixStrings[level] = postfix + } + else { + postfixStrings.removeValue(forKey: level) + } + } + + /// Clear all previously set colours. (Sets each log level back to default) + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func clearFormatting() { + prefixStrings = [:] + postfixStrings = [:] + } + + // MARK: - LogFormatterProtocol + /// Apply some additional formatting to the message if appropriate. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: message with the additional formatting + /// + @discardableResult open func format(logDetails: inout LogDetails, message: inout String) -> String { + message = "\(prefixStrings[logDetails.level] ?? "")\(message)\(postfixStrings[logDetails.level] ?? "")" + return message + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): " + for level in XCGLogger.Level.allCases { + description += "\n\t- \(level) > \(prefixStrings[level] ?? "None") | \(postfixStrings[level] ?? "None")" + } + + return description + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/XcodeColorsLogFormatter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/XcodeColorsLogFormatter.swift new file mode 100644 index 0000000..3e0670b --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/LogFormatters/XcodeColorsLogFormatter.swift @@ -0,0 +1,257 @@ +// +// XcodeColorsLogFormatter.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2016-08-30. +// Copyright © 2016 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +#if os(macOS) + import AppKit +#elseif os(iOS) || os(tvOS) || os(watchOS) + import UIKit +#endif + +// MARK: - XcodeColorsLogFormatter +/// A log formatter that will add colour codes for the [XcodeColor plug-in](https://github.com/robbiehanson/XcodeColors) to the message +open class XcodeColorsLogFormatter: LogFormatterProtocol, CustomDebugStringConvertible { + + /// XcodeColors escape code + public static let escape: String = "\u{001b}[" + + /// XcodeColors code to reset the foreground colour + public static let resetForeground = "\(escape)fg;" + + /// XcodeColors code to reset the background colour + public static let resetBackground = "\(escape)bg;" + + /// XcodeColors code to reset both the foreground and background colours + public static let reset: String = "\(escape);" + + /// Struct to store RGB values + public struct XcodeColor: CustomStringConvertible { + /// Red component + public var red: Int = 0 { + didSet { + guard red < 0 || red > 255 else { return } + red = 0 + } + } + + /// Green component + public var green: Int = 0 { + didSet { + guard green < 0 || green > 255 else { return } + green = 0 + } + } + + /// Blue component + public var blue: Int = 0 { + didSet { + guard blue < 0 || blue > 255 else { return } + blue = 0 + } + } + + /// Foreground code + public var foregroundCode: String { + return "fg\(red),\(green),\(blue)" + } + + /// Background code + public var backgroundCode: String { + return "bg\(red),\(green),\(blue)" + } + + public init(red: Int, green: Int, blue: Int) { + self.red = red + self.green = green + self.blue = blue + } + + public init(_ red: Int, _ green: Int, _ blue: Int) { + self.red = red + self.green = green + self.blue = blue + } + +#if os(macOS) + public init(color: NSColor) { + if let colorSpaceCorrected = color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) { + self.red = Int(colorSpaceCorrected.redComponent * 255) + self.green = Int(colorSpaceCorrected.greenComponent * 255) + self.blue = Int(colorSpaceCorrected.blueComponent * 255) + } + } +#elseif os(iOS) || os(tvOS) || os(watchOS) + public init(color: UIColor) { + var redComponent: CGFloat = 0 + var greenComponent: CGFloat = 0 + var blueComponent: CGFloat = 0 + var alphaComponent: CGFloat = 0 + + color.getRed(&redComponent, green: &greenComponent, blue: &blueComponent, alpha:&alphaComponent) + + self.red = Int(redComponent * 255) + self.green = Int(greenComponent * 255) + self.blue = Int(blueComponent * 255) + } +#endif + + /// Human readable description of this colour (CustomStringConvertible) + public var description: String { + return String(format: "(r: %d, g: %d, b: %d) #%02X%02X%02X", red, green, blue, red, green, blue) + } + + /// Preset colour: Red + public static let red: XcodeColor = { return XcodeColor(red: 255, green: 0, blue: 0) }() + + /// Preset colour: Green + public static let green: XcodeColor = { return XcodeColor(red: 0, green: 255, blue: 0) }() + + /// Preset colour: Blue + public static let blue: XcodeColor = { return XcodeColor(red: 0, green: 0, blue: 255) }() + + /// Preset colour: Black + public static let black: XcodeColor = { return XcodeColor(red: 0, green: 0, blue: 0) }() + + /// Preset colour: White + public static let white: XcodeColor = { return XcodeColor(red: 255, green: 255, blue: 255) }() + + /// Preset colour: Light Grey + public static let lightGrey: XcodeColor = { return XcodeColor(red: 211, green: 211, blue: 211) }() + + /// Preset colour: Dark Grey + public static let darkGrey: XcodeColor = { return XcodeColor(red: 169, green: 169, blue: 169) }() + + /// Preset colour: Orange + public static let orange: XcodeColor = { return XcodeColor(red: 255, green: 165, blue: 0) }() + + /// Preset colour: Purple + public static let purple: XcodeColor = { return XcodeColor(red: 170, green: 0, blue: 170) }() + + /// Preset colour: Dark Green + public static let darkGreen: XcodeColor = { return XcodeColor(red: 0, green: 128, blue: 0) }() + + /// Preset colour: Cyan + public static let cyan: XcodeColor = { return XcodeColor(red: 0, green: 170, blue: 170) }() + } + + /// Internal cache of the XcodeColors codes for each log level + internal var formatStrings: [XCGLogger.Level: String] = [:] + + /// Internal cache of the description for each log level + internal var descriptionStrings: [XCGLogger.Level: String] = [:] + + public init() { + resetFormatting() + } + + /// Set the colours and/or options for a specific log level. + /// + /// - Parameters: + /// - level: The log level. + /// - foregroundColor: The text colour of the message. **Default:** Restore default text colour + /// - backgroundColor: The background colour of the message. **Default:** Restore default background colour + /// + /// - Returns: Nothing + /// + open func colorize(level: XCGLogger.Level, with foregroundColor: XcodeColor? = nil, on backgroundColor: XcodeColor? = nil) { + guard foregroundColor != nil || backgroundColor != nil else { + // neither set, use reset code + formatStrings[level] = XcodeColorsLogFormatter.reset + descriptionStrings[level] = "None" + return + } + + var formatString: String = "" + + if let foregroundColor = foregroundColor { + formatString += "\(XcodeColorsLogFormatter.escape)fg\(foregroundColor.red),\(foregroundColor.green),\(foregroundColor.blue);" + } + else { + formatString += XcodeColorsLogFormatter.resetForeground + } + + if let backgroundColor = backgroundColor { + formatString += "\(XcodeColorsLogFormatter.escape)bg\(backgroundColor.red),\(backgroundColor.green),\(backgroundColor.blue);" + } + else { + formatString += XcodeColorsLogFormatter.resetBackground + } + + formatStrings[level] = formatString + descriptionStrings[level] = "\(foregroundColor?.description ?? "Default") on \(backgroundColor?.description ?? "Default")" + } + + /// Get the cached XcodeColors codes for the specified log level. + /// + /// - Parameters: + /// - level: The log level. + /// + /// - Returns: The XcodeColors codes for the specified log level. + /// + internal func formatString(for level: XCGLogger.Level) -> String { + return formatStrings[level] ?? XcodeColorsLogFormatter.reset + } + + /// Apply a default set of colours. + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func resetFormatting() { + colorize(level: .verbose, with: .lightGrey) + colorize(level: .debug, with: .darkGrey) + colorize(level: .info, with: .blue) + colorize(level: .warning, with: .orange) + colorize(level: .error, with: .red) + colorize(level: .severe, with: .white, on: .red) + colorize(level: .none) + } + + /// Clear all previously set colours. (Sets each log level back to default) + /// + /// - Parameters: None + /// + /// - Returns: Nothing + /// + open func clearFormatting() { + colorize(level: .verbose) + colorize(level: .debug) + colorize(level: .info) + colorize(level: .warning) + colorize(level: .error) + colorize(level: .severe) + colorize(level: .none) + } + + // MARK: - LogFormatterProtocol + /// Apply some additional formatting to the message if appropriate. + /// + /// - Parameters: + /// - logDetails: The log details. + /// - message: Formatted/processed message ready for output. + /// + /// - Returns: message with the additional formatting + /// + @discardableResult open func format(logDetails: inout LogDetails, message: inout String) -> String { + message = "\(formatString(for: logDetails.level))\(message)\(XcodeColorsLogFormatter.reset)" + return message + } + + // MARK: - CustomDebugStringConvertible + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): " + for level in XCGLogger.Level.allCases { + description += "\n\t- \(level) > \(descriptionStrings[level] ?? "None")" + } + + return description + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/HelperFunctions.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/HelperFunctions.swift new file mode 100644 index 0000000..d8aed1f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/HelperFunctions.swift @@ -0,0 +1,39 @@ +// +// HelperFunctions.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation +import ObjcExceptionBridging + +/// Extract the type name from the given object +/// +/// - parameter someObject: the object for which you need the type name +/// +/// - returns: the type name of the object +func extractTypeName(_ someObject: Any) -> String { + return (someObject is Any.Type) ? "\(someObject)" : "\(type(of: someObject))" +} + +// MARK: - Swiftier interface to the Objective-C exception handling functions +/// Throw an Objective-C exception with the specified name/message/info +/// +/// - parameter name: The name of the exception to throw +/// - parameter message: The message to include in the exception (why it occurred) +/// - parameter userInfo: A dictionary with arbitrary info to be passed along with the exception +func _try(_ tryClosure: @escaping () -> (), catch catchClosure: @escaping (_ exception: NSException) -> (), finally finallyClosure: (() -> ())? = nil) { + _try_objc(tryClosure, catchClosure, finallyClosure ?? {}) +} + +/// Throw an Objective-C exception with the specified name/message/info +/// +/// - parameter name: The name of the exception to throw +/// - parameter message: The message to include in the exception (why it occurred) +/// - parameter userInfo: A dictionary with arbitrary info to be passed along with the exception +func _throw(name: String, message: String? = nil, userInfo: [AnyHashable: Any]? = nil) { + _throw_objc(NSException(name: NSExceptionName(rawValue: name), reason: message ?? name, userInfo: userInfo)) +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/LogDetails.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/LogDetails.swift new file mode 100644 index 0000000..c346f57 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/Misc/LogDetails.swift @@ -0,0 +1,46 @@ +// +// LogDetails.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +import Foundation + +// MARK: - LogDetails +/// Data structure to hold all info about a log message, passed to destination classes +public struct LogDetails { + + /// Log level required to display this log + public var level: XCGLogger.Level + + /// Date this log was sent + public var date: Date + + /// The log message to display + public var message: String + + /// Name of the function that generated this log + public var functionName: String + + /// Name of the file the function exists in + public var fileName: String + + /// The line number that generated this log + public var lineNumber: Int + + /// Dictionary to store miscellaneous data about the log, can be used by formatters and filters etc. Please prefix any keys to help avoid collissions. + public var userInfo: [String: Any] + + public init(level: XCGLogger.Level, date: Date, message: String, functionName: String, fileName: String, lineNumber: Int, userInfo: [String: Any] = [:]) { + self.level = level + self.date = date + self.message = message + self.functionName = functionName + self.fileName = fileName + self.lineNumber = lineNumber + self.userInfo = userInfo + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/XCGLogger.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/XCGLogger.swift new file mode 100644 index 0000000..b694b76 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/Pods/XCGLogger/Sources/XCGLogger/XCGLogger.swift @@ -0,0 +1,1553 @@ +// +// XCGLogger.swift +// XCGLogger: https://github.com/DaveWoodCom/XCGLogger +// +// Created by Dave Wood on 2014-06-06. +// Copyright © 2014 Dave Wood, Cerebral Gardens. +// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt +// + +#if os(macOS) + import AppKit +#elseif os(iOS) || os(tvOS) || os(watchOS) + import UIKit +#endif + +// MARK: - XCGLogger +/// The main logging class +open class XCGLogger: CustomDebugStringConvertible { + // MARK: - Constants + public struct Constants { + /// Prefix identifier to use for all other identifiers + public static let baseIdentifier = "com.cerebralgardens.xcglogger" + + /// Identifier for the default instance of XCGLogger + public static let defaultInstanceIdentifier = "\(baseIdentifier).defaultInstance" + + /// Identifer for the Xcode console destination + public static let baseConsoleDestinationIdentifier = "\(baseIdentifier).logdestination.console" + + /// Identifier for the Apple System Log destination + public static let systemLogDestinationIdentifier = "\(baseIdentifier).logdestination.console.nslog" + + /// Identifier for the file logging destination + public static let fileDestinationIdentifier = "\(baseIdentifier).logdestination.file" + + /// Identifier for the default dispatch queue + public static let logQueueIdentifier = "\(baseIdentifier).queue" + + /// UserInfo Key - tags + public static let userInfoKeyTags = "\(baseIdentifier).tags" + + /// UserInfo Key - devs + public static let userInfoKeyDevs = "\(baseIdentifier).devs" + + /// UserInfo Key - internal + public static let userInfoKeyInternal = "\(baseIdentifier).internal" + + /// Library version number + public static let versionString = "7.0.1" + + /// Internal userInfo + internal static let internalUserInfo: [String: Any] = [XCGLogger.Constants.userInfoKeyInternal: true] + + /// Extended file attributed key to use when storing the logger's identifier on an archived log file + public static let extendedAttributeArchivedLogIdentifierKey = "\(baseIdentifier).archived.by" + + /// Extended file attributed key to use when storing the time a log file was archived + public static let extendedAttributeArchivedLogTimestampKey = "\(baseIdentifier).archived.at" + } + + // MARK: - Enums + /// Enum defining our log levels + public enum Level: Int, CaseIterable, Comparable, CustomStringConvertible { + case verbose + case debug + case info + case notice + case warning + case error + case severe // aka critical + case alert + case emergency + case none + + public var description: String { + switch self { + case .verbose: + return "Verbose" + case .debug: + return "Debug" + case .info: + return "Info" + case .notice: + return "Notice" + case .warning: + return "Warning" + case .error: + return "Error" + case .severe: + return "Severe" + case .alert: + return "Alert" + case .emergency: + return "Emergency" + case .none: + return "None" + } + } + + @available(*, deprecated, renamed: "allCases") + public static let all: [Level] = [.verbose, .debug, .info, .notice, .warning, .error, .severe, .alert, .emergency] + } + + // MARK: - Default instance + /// The default XCGLogger object + public static let `default`: XCGLogger = XCGLogger(identifier: XCGLogger.Constants.defaultInstanceIdentifier) + + // MARK: - Properties + /// Identifier for this logger object (should be unique) + open var identifier: String = "" + + /// The log level of this logger, any logs received at this level or higher will be output to the destinations + open var outputLevel: Level = .debug { + didSet { + for index in 0 ..< destinations.count { + destinations[index].outputLevel = outputLevel + } + } + } + + /// Option: a closure to execute whenever a logging method is called without a log message + open var noMessageClosure: () -> Any? = { return "" } + + /// Option: override descriptions of log levels + open var levelDescriptions: [XCGLogger.Level: String] = [:] + + /// Array of log formatters to apply to messages before they're output + open var formatters: [LogFormatterProtocol]? = nil + + /// Array of log filters to apply to messages before they're output + open var filters: [FilterProtocol]? = nil + + /// The default dispatch queue used for logging + public static let logQueue: DispatchQueue = DispatchQueue(label: XCGLogger.Constants.logQueueIdentifier, attributes: []) + + /// A custom date formatter object to use when displaying the dates of log messages (internal storage) + internal var _customDateFormatter: DateFormatter? = nil + /// The date formatter object to use when displaying the dates of log messages + open var dateFormatter: DateFormatter? { + get { + guard _customDateFormatter == nil else { return _customDateFormatter } + struct Statics { + static var dateFormatter: DateFormatter = { + let defaultDateFormatter = DateFormatter() + defaultDateFormatter.locale = NSLocale.current + defaultDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" + return defaultDateFormatter + }() + } + + return Statics.dateFormatter + } + set { + _customDateFormatter = newValue + } + } + + /// Array containing all of the destinations for this logger + open var destinations: [DestinationProtocol] = [] + + // MARK: - Life Cycle + public init(identifier: String = "", includeDefaultDestinations: Bool = true) { + self.identifier = identifier + + if includeDefaultDestinations { + // Setup a standard console destination + add(destination: ConsoleDestination(identifier: XCGLogger.Constants.baseConsoleDestinationIdentifier)) + } + } + + // MARK: - Setup methods + /// A shortcut method to configure the default logger instance. + /// + /// - Note: The function exists to get you up and running quickly, but it's recommended that you use the advanced usage configuration for most projects. See https://github.com/DaveWoodCom/XCGLogger/blob/master/README.md#advanced-usage-recommended + /// + /// - Parameters: + /// - level: The log level of this logger, any logs received at this level or higher will be output to the destinations. **Default:** Debug + /// - showLogIdentifier: Whether or not to output the log identifier. **Default:** false + /// - showFunctionName: Whether or not to output the function name that generated the log. **Default:** true + /// - showThreadName: Whether or not to output the thread's name the log was created on. **Default:** false + /// - showLevel: Whether or not to output the log level of the log. **Default:** true + /// - showFileNames: Whether or not to output the fileName that generated the log. **Default:** true + /// - showLineNumbers: Whether or not to output the line number where the log was generated. **Default:** true + /// - showDate: Whether or not to output the date the log was created. **Default:** true + /// - writeToFile: FileURL or path (as String) to a file to log all messages to (this file is overwritten each time the logger is created). **Default:** nil => no log file + /// - fileLevel: An alternate log level for the file destination. **Default:** nil => use the same log level as the console destination + /// + /// - Returns: Nothing + /// + open class func setup(level: Level = .debug, showLogIdentifier: Bool = false, showFunctionName: Bool = true, showThreadName: Bool = false, showLevel: Bool = true, showFileNames: Bool = true, showLineNumbers: Bool = true, showDate: Bool = true, writeToFile: Any? = nil, fileLevel: Level? = nil) { + self.default.setup(level: level, showLogIdentifier: showLogIdentifier, showFunctionName: showFunctionName, showThreadName: showThreadName, showLevel: showLevel, showFileNames: showFileNames, showLineNumbers: showLineNumbers, showDate: showDate, writeToFile: writeToFile) + } + + /// A shortcut method to configure the logger. + /// + /// - Note: The function exists to get you up and running quickly, but it's recommended that you use the advanced usage configuration for most projects. See https://github.com/DaveWoodCom/XCGLogger/blob/master/README.md#advanced-usage-recommended + /// + /// - Parameters: + /// - level: The log level of this logger, any logs received at this level or higher will be output to the destinations. **Default:** Debug + /// - showLogIdentifier: Whether or not to output the log identifier. **Default:** false + /// - showFunctionName: Whether or not to output the function name that generated the log. **Default:** true + /// - showThreadName: Whether or not to output the thread's name the log was created on. **Default:** false + /// - showLevel: Whether or not to output the log level of the log. **Default:** true + /// - showFileNames: Whether or not to output the fileName that generated the log. **Default:** true + /// - showLineNumbers: Whether or not to output the line number where the log was generated. **Default:** true + /// - showDate: Whether or not to output the date the log was created. **Default:** true + /// - writeToFile: FileURL or path (as String) to a file to log all messages to (this file is overwritten each time the logger is created). **Default:** nil => no log file + /// - fileLevel: An alternate log level for the file destination. **Default:** nil => use the same log level as the console destination + /// + /// - Returns: Nothing + /// + open func setup(level: Level = .debug, showLogIdentifier: Bool = false, showFunctionName: Bool = true, showThreadName: Bool = false, showLevel: Bool = true, showFileNames: Bool = true, showLineNumbers: Bool = true, showDate: Bool = true, writeToFile: Any? = nil, fileLevel: Level? = nil) { + outputLevel = level + + if let standardConsoleDestination = destination(withIdentifier: XCGLogger.Constants.baseConsoleDestinationIdentifier) as? ConsoleDestination { + standardConsoleDestination.showLogIdentifier = showLogIdentifier + standardConsoleDestination.showFunctionName = showFunctionName + standardConsoleDestination.showThreadName = showThreadName + standardConsoleDestination.showLevel = showLevel + standardConsoleDestination.showFileName = showFileNames + standardConsoleDestination.showLineNumber = showLineNumbers + standardConsoleDestination.showDate = showDate + standardConsoleDestination.outputLevel = level + } + + if let writeToFile: Any = writeToFile { + // We've been passed a file to use for logging, set up a file logger + let standardFileDestination: FileDestination = FileDestination(writeToFile: writeToFile, identifier: XCGLogger.Constants.fileDestinationIdentifier) + + standardFileDestination.showLogIdentifier = showLogIdentifier + standardFileDestination.showFunctionName = showFunctionName + standardFileDestination.showThreadName = showThreadName + standardFileDestination.showLevel = showLevel + standardFileDestination.showFileName = showFileNames + standardFileDestination.showLineNumber = showLineNumbers + standardFileDestination.showDate = showDate + standardFileDestination.outputLevel = fileLevel ?? level + + add(destination: standardFileDestination) + } + + logAppDetails() + } + + // MARK: - Logging methods + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing + /// + open class func logln(_ closure: @autoclosure () -> Any?, level: Level = .debug, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing + /// + open class func logln(_ level: Level = .debug, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing + /// + open class func logln(_ level: Level = .debug, functionName: String = #function, fileName: String = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing + /// + open func logln(_ closure: @autoclosure () -> Any?, level: Level = .debug, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(level, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing + /// + open func logln(_ level: Level = .debug, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + logln(level, functionName: String(describing: functionName), fileName: String(describing: fileName), lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing + /// + open func logln(_ level: Level = .debug, functionName: String = #function, fileName: String = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + let enabledDestinations = destinations.filter({$0.isEnabledFor(level: level)}) + guard enabledDestinations.count > 0 else { return } + guard let closureResult = closure() else { return } + + let logDetails: LogDetails = LogDetails(level: level, date: Date(), message: String(describing: closureResult), functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo) + for destination in enabledDestinations { + destination.process(logDetails: logDetails) + } + } + + /// Execute some code only when at the specified log level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func exec(_ level: Level = .debug, closure: () -> () = {}) { + self.default.exec(level, closure: closure) + } + + /// Execute some code only when at the specified log level. + /// + /// - Parameters: + /// - level: Specified log level **Default:** *Debug*. + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func exec(_ level: Level = .debug, closure: () -> () = {}) { + guard isEnabledFor(level:level) else { return } + + closure() + } + + /// Generate logs to display your app's vitals (app name, version, etc) as well as XCGLogger's version and log level. + /// + /// - Parameters: + /// - selectedDestination: A specific destination to log the vitals on, if omitted, will log to all destinations + /// + /// - Returns: Nothing. + /// + open func logAppDetails(selectedDestination: DestinationProtocol? = nil) { + let date = Date() + + var buildString = "" + if let infoDictionary = Bundle.main.infoDictionary { + if let CFBundleShortVersionString = infoDictionary["CFBundleShortVersionString"] as? String { + buildString = "Version: \(CFBundleShortVersionString) " + } + if let CFBundleVersion = infoDictionary["CFBundleVersion"] as? String { + buildString += "Build: \(CFBundleVersion) " + } + } + + let processInfo: ProcessInfo = ProcessInfo.processInfo + let XCGLoggerVersionNumber = XCGLogger.Constants.versionString + + var logDetails: [LogDetails] = [] + logDetails.append(LogDetails(level: .info, date: date, message: "\(processInfo.processName) \(buildString)PID: \(processInfo.processIdentifier)", functionName: "", fileName: "", lineNumber: 0, userInfo: XCGLogger.Constants.internalUserInfo)) + logDetails.append(LogDetails(level: .info, date: date, message: "XCGLogger Version: \(XCGLoggerVersionNumber) - Level: \(outputLevel)", functionName: "", fileName: "", lineNumber: 0, userInfo: XCGLogger.Constants.internalUserInfo)) + + for var destination in (selectedDestination != nil ? [selectedDestination!] : destinations) where !destination.haveLoggedAppDetails { + for logDetail in logDetails { + guard destination.isEnabledFor(level:.info) else { continue } + + destination.haveLoggedAppDetails = true + destination.processInternal(logDetails: logDetail) + } + } + } + + // MARK: - Convenience logging methods + // MARK: * Verbose + /// Log something at the Verbose log level. This format of verbose() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func verbose(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Verbose log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func verbose(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Verbose log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func verbose(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Verbose log level. This format of verbose() isn't provided the object to log, instead the property *`noMessageClosure`* is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func verbose(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Verbose log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func verbose(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Verbose log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func verbose(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.verbose, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Debug + /// Log something at the Debug log level. This format of debug() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func debug(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Debug log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func debug(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Debug log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func debug(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Debug log level. This format of debug() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func debug(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Debug log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func debug(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Debug log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func debug(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.debug, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Info + /// Log something at the Info log level. This format of info() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func info(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Info log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func info(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Info log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func info(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Info log level. This format of info() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func info(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Info log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func info(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Info log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func info(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.info, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Notice + /// Log something at the Notice log level. This format of notice() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func notice(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. This format of notice() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func notice(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Notice log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func notice(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.notice, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Warning + /// Log something at the Warning log level. This format of warning() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func warning(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Warning log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func warning(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Warning log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func warning(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Warning log level. This format of warning() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func warning(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Warning log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func warning(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Warning log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func warning(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.warning, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Error + /// Log something at the Error log level. This format of error() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func error(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Error log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func error(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Error log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func error(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Error log level. This format of error() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func error(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Error log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func error(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Error log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func error(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.error, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Severe + /// Log something at the Severe log level. This format of severe() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func severe(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Severe log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func severe(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Severe log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func severe(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Severe log level. This format of severe() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func severe(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Severe log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func severe(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Severe log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func severe(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.severe, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Alert + /// Log something at the Alert log level. This format of alert() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func alert(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. This format of alert() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func alert(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Alert log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func alert(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.alert, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: * Emergency + /// Log something at the Emergency log level. This format of emergency() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.default.noMessageClosure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open class func emergency(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open class func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.default.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. This format of emergency() isn't provided the object to log, instead the property `noMessageClosure` is executed instead. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: self.noMessageClosure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - closure: A closure that returns the object to be logged. + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// + /// - Returns: Nothing. + /// + open func emergency(_ closure: @autoclosure () -> Any?, functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:]) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + /// Log something at the Emergency log level. + /// + /// - Parameters: + /// - functionName: Normally omitted **Default:** *#function*. + /// - fileName: Normally omitted **Default:** *#file*. + /// - lineNumber: Normally omitted **Default:** *#line*. + /// - userInfo: Dictionary for adding arbitrary data to the log message, can be used by filters/formatters etc + /// - closure: A closure that returns the object to be logged. + /// + /// - Returns: Nothing. + /// + open func emergency(_ functionName: StaticString = #function, fileName: StaticString = #file, lineNumber: Int = #line, userInfo: [String: Any] = [:], closure: () -> Any?) { + self.logln(.emergency, functionName: functionName, fileName: fileName, lineNumber: lineNumber, userInfo: userInfo, closure: closure) + } + + // MARK: - Exec Methods + // MARK: * Verbose + /// Execute some code only when at the Verbose log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func verboseExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.verbose, closure: closure) + } + + /// Execute some code only when at the Verbose log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func verboseExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.verbose, closure: closure) + } + + // MARK: * Debug + /// Execute some code only when at the Debug or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func debugExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.debug, closure: closure) + } + + /// Execute some code only when at the Debug or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func debugExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.debug, closure: closure) + } + + // MARK: * Info + /// Execute some code only when at the Info or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func infoExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.info, closure: closure) + } + + /// Execute some code only when at the Info or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func infoExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.info, closure: closure) + } + + // MARK: * Notice + /// Execute some code only when at the Notice or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func noticeExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.notice, closure: closure) + } + + /// Execute some code only when at the Notice or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func noticeExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.notice, closure: closure) + } + + // MARK: * Warning + /// Execute some code only when at the Warning or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func warningExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.warning, closure: closure) + } + + /// Execute some code only when at the Warning or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func warningExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.warning, closure: closure) + } + + // MARK: * Error + /// Execute some code only when at the Error or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func errorExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.error, closure: closure) + } + + /// Execute some code only when at the Error or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func errorExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.error, closure: closure) + } + + // MARK: * Severe + /// Execute some code only when at the Severe log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func severeExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.severe, closure: closure) + } + + /// Execute some code only when at the Severe log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func severeExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.severe, closure: closure) + } + + // MARK: * Alert + /// Execute some code only when at the Alert or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func alertExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.alert, closure: closure) + } + + /// Execute some code only when at the Alert or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func alertExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.alert, closure: closure) + } + + // MARK: * Emergency + /// Execute some code only when at the Emergency or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open class func emergencyExec(_ closure: () -> () = {}) { + self.default.exec(XCGLogger.Level.emergency, closure: closure) + } + + /// Execute some code only when at the Emergency or lower log level. + /// + /// - Parameters: + /// - closure: The code closure to be executed. + /// + /// - Returns: Nothing. + /// + open func emergencyExec(_ closure: () -> () = {}) { + self.exec(XCGLogger.Level.emergency, closure: closure) + } + + // MARK: - Log destination methods + /// Get the destination with the specified identifier. + /// + /// - Parameters: + /// - identifier: Identifier of the destination to return. + /// + /// - Returns: The destination with the specified identifier, if one exists, nil otherwise. + /// + open func destination(withIdentifier identifier: String) -> DestinationProtocol? { + for destination in destinations { + if destination.identifier == identifier { + return destination + } + } + + return nil + } + + /// Add a new destination to the logger. + /// + /// - Parameters: + /// - destination: The destination to add. + /// + /// - Returns: + /// - true: Log destination was added successfully. + /// - false: Failed to add the destination. + /// + @discardableResult open func add(destination: DestinationProtocol) -> Bool { + var destination = destination + + let existingDestination: DestinationProtocol? = self.destination(withIdentifier: destination.identifier) + if existingDestination != nil { + return false + } + + if let previousOwner = destination.owner { + previousOwner.remove(destination: destination) + } + + destination.owner = self + destinations.append(destination) + return true + } + + /// Remove the destination from the logger. + /// + /// - Parameters: + /// - destination: The destination to remove. + /// + /// - Returns: + /// - true: Log destination was removed successfully. + /// - false: Failed to remove the destination. + /// + @discardableResult open func remove(destination: DestinationProtocol) -> Bool { + guard destination.owner === self else { return false } + + let existingDestination: DestinationProtocol? = self.destination(withIdentifier: destination.identifier) + guard existingDestination != nil else { return false } + + // Make our parameter mutable + var destination = destination + destination.owner = nil + + destinations = destinations.filter({$0.owner != nil}) + return true + } + + /// Remove the destination with the specified identifier from the logger. + /// + /// - Parameters: + /// - identifier: The identifier of the destination to remove. + /// + /// - Returns: + /// - true: Log destination was removed successfully. + /// - false: Failed to remove the destination. + /// + @discardableResult open func remove(destinationWithIdentifier identifier: String) -> Bool { + guard let destination = destination(withIdentifier: identifier) else { return false } + return remove(destination: destination) + } + + // MARK: - Misc methods + /// Check if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - level: The log level to check. + /// + /// - Returns: + /// - true: Logger is at the log level specified or lower. + /// - false: Logger is at a higher log levelss. + /// + open func isEnabledFor(level: XCGLogger.Level) -> Bool { + return level >= self.outputLevel + } + + // MARK: - Private methods + /// Log a message if the logger's log level is equal to or lower than the specified level. + /// + /// - Parameters: + /// - message: Message to log. + /// - level: Specified log level. + /// - source: The destination calling this method + /// + /// - Returns: Nothing + /// + internal func _logln(_ message: String, level: Level = .debug, source sourceDestination: DestinationProtocol? = nil) { + let logDetails: LogDetails = LogDetails(level: level, date: Date(), message: message, functionName: "", fileName: "", lineNumber: 0, userInfo: XCGLogger.Constants.internalUserInfo) + for destination in self.destinations { + if level >= .error && sourceDestination?.identifier == destination.identifier { continue } + if (destination.isEnabledFor(level: level)) { + destination.processInternal(logDetails: logDetails) + } + } + } + + // MARK: - DebugPrintable + open var debugDescription: String { + get { + var description: String = "\(extractTypeName(self)): \(identifier) - destinations: \r" + for destination in destinations { + description += "\t \(destination.debugDescription)\r" + } + + return description + } + } +} + +// Implement Comparable for XCGLogger.Level +public func < (lhs: XCGLogger.Level, rhs: XCGLogger.Level) -> Bool { + return lhs.rawValue < rhs.rawValue +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.pbxproj b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b300121 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.pbxproj @@ -0,0 +1,699 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 5168723350E59F85941E8B89 /* Pods_WCHBLEOTA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C578A462BE198D0F7F13A3C4 /* Pods_WCHBLEOTA.framework */; }; + 775410252800082200AC4053 /* AlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775410242800082200AC4053 /* AlertPresenter.swift */; }; + 77541027280008F900AC4053 /* QuickError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77541026280008F900AC4053 /* QuickError.swift */; }; + 7754104A2800105F00AC4053 /* DocumentFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775410442800105F00AC4053 /* DocumentFileManager.swift */; }; + 7754104B2800105F00AC4053 /* Directory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775410452800105F00AC4053 /* Directory.swift */; }; + 7754104C2800105F00AC4053 /* CH_FileTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775410482800105F00AC4053 /* CH_FileTableViewCell.swift */; }; + 7754104D2800105F00AC4053 /* CH_FileTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 775410492800105F00AC4053 /* CH_FileTableViewCell.xib */; }; + 775410512800109800AC4053 /* CH_FileSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7754104F2800109800AC4053 /* CH_FileSelectorViewController.swift */; }; + 775410522800109800AC4053 /* CH_FileSelectorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 775410502800109800AC4053 /* CH_FileSelectorViewController.xib */; }; + 77541054280010C000AC4053 /* FileDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77541053280010C000AC4053 /* FileDataSource.swift */; }; + 7754105A2800186800AC4053 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 775410592800186800AC4053 /* DocumentPicker.swift */; }; + 776E3BEC2803BF670024C54D /* CH_ActionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3BEB2803BF670024C54D /* CH_ActionTableViewCell.swift */; }; + 776E3C102803FC4F0024C54D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 776E3C0F2803FC4F0024C54D /* Images.xcassets */; }; + 776E3C19280422C50024C54D /* CH_HomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 776E3C15280422C50024C54D /* CH_HomeViewController.xib */; }; + 776E3C1A280422C50024C54D /* CH_HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3C16280422C50024C54D /* CH_HomeViewController.swift */; }; + 776E3C1C280426B90024C54D /* CH_PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3C1B280426B90024C54D /* CH_PeripheralModel.swift */; }; + 776E3C1E28042CE30024C54D /* CH_Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3C1D28042CE30024C54D /* CH_Preferences.swift */; }; + 776E3C21280516150024C54D /* CH_PeripheralTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3C1F280516150024C54D /* CH_PeripheralTableViewCell.swift */; }; + 776E3C22280516150024C54D /* CH_PeripheralTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 776E3C20280516150024C54D /* CH_PeripheralTableViewCell.xib */; }; + 776E3C2928051E7B0024C54D /* CH_PeripheralSerivceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776E3C2728051E7B0024C54D /* CH_PeripheralSerivceViewController.swift */; }; + 776E3C2A28051E7B0024C54D /* CH_PeripheralSerivceViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 776E3C2828051E7B0024C54D /* CH_PeripheralSerivceViewController.xib */; }; + 777D6DF128052A70003E2728 /* CH_FilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 777D6DEF28052A70003E2728 /* CH_FilterViewController.xib */; }; + 777D6DF228052A70003E2728 /* CH_FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777D6DF028052A70003E2728 /* CH_FilterViewController.swift */; }; + 777D6DF52805450F003E2728 /* CH_ServiceTableHeadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777D6DF32805450F003E2728 /* CH_ServiceTableHeadView.swift */; }; + 777D6DF62805450F003E2728 /* CH_ServiceTableHeadView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 777D6DF42805450F003E2728 /* CH_ServiceTableHeadView.xib */; }; + 777D6DF928054649003E2728 /* CH_CharacteristicsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777D6DF728054649003E2728 /* CH_CharacteristicsTableViewCell.swift */; }; + 777D6DFA28054649003E2728 /* CH_CharacteristicsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 777D6DF828054649003E2728 /* CH_CharacteristicsTableViewCell.xib */; }; + 7798C76128095BF0003033B5 /* XappKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7798C75F28095BCB003033B5 /* XappKit.framework */; platformFilter = ios; }; + 7798C76228095BF0003033B5 /* XappKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7798C75F28095BCB003033B5 /* XappKit.framework */; platformFilter = ios; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 77A6C4F62807B575009CA06B /* CH_UpdateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A6C4F42807B575009CA06B /* CH_UpdateViewController.swift */; }; + 77A6C4F72807B575009CA06B /* CH_UpdateViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77A6C4F52807B575009CA06B /* CH_UpdateViewController.xib */; }; + 77B81B8228056656001BFF9B /* BLEOTALibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77B81B8128056656001BFF9B /* BLEOTALibrary.framework */; }; + 77B81B8328056656001BFF9B /* BLEOTALibrary.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 77B81B8128056656001BFF9B /* BLEOTALibrary.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 77B81B8D2806A8EA001BFF9B /* IntelHexToBinCoverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B81B8C2806A8EA001BFF9B /* IntelHexToBinCoverter.swift */; }; + 77CBABDD28153E600088E07C /* CH_UpdateProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CBABDC28153E5F0088E07C /* CH_UpdateProgressView.swift */; }; + 77CBABDF28153EDF0088E07C /* CH_UpdateProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77CBABDE28153EDF0088E07C /* CH_UpdateProgressView.xib */; }; + 77CBABE1281545090088E07C /* ModernIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CBABE0281545090088E07C /* ModernIcon.swift */; }; + 77CBABE3281545100088E07C /* ImageWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CBABE2281545100088E07C /* ImageWrapper.swift */; }; + 77CBABE528164C040088E07C /* CH_UpdateCheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CBABE428164C040088E07C /* CH_UpdateCheckView.swift */; }; + 77CBABE728164C0F0088E07C /* CH_UpdateCheckView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77CBABE628164C0F0088E07C /* CH_UpdateCheckView.xib */; }; + 77CBABEA28168D460088E07C /* CH_LogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77CBABE828168D460088E07C /* CH_LogView.swift */; }; + 77CBABEB28168D460088E07C /* CH_LogView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77CBABE928168D460088E07C /* CH_LogView.xib */; }; + 77E19ED527FD279700FE6D8D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E19ED427FD279700FE6D8D /* AppDelegate.swift */; }; + 77E19EDE27FD279700FE6D8D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 77E19EDD27FD279700FE6D8D /* Assets.xcassets */; }; + 77E19EE127FD279700FE6D8D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 77E19EDF27FD279700FE6D8D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 77E19EF627FD931400FE6D8D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7798C76228095BF0003033B5 /* XappKit.framework in Embed Frameworks */, + 77B81B8328056656001BFF9B /* BLEOTALibrary.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 6382E55B3C92AD6B527CE092 /* Pods-WCHBLEOTA.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WCHBLEOTA.release.xcconfig"; path = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.release.xcconfig"; sourceTree = ""; }; + 7096B7B68D3598BD6BCB3104 /* Pods-WCHBLEOTA.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WCHBLEOTA.debug.xcconfig"; path = "Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA.debug.xcconfig"; sourceTree = ""; }; + 775410242800082200AC4053 /* AlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertPresenter.swift; sourceTree = ""; }; + 77541026280008F900AC4053 /* QuickError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickError.swift; sourceTree = ""; }; + 775410442800105F00AC4053 /* DocumentFileManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentFileManager.swift; sourceTree = ""; }; + 775410452800105F00AC4053 /* Directory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Directory.swift; sourceTree = ""; }; + 775410482800105F00AC4053 /* CH_FileTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_FileTableViewCell.swift; sourceTree = ""; }; + 775410492800105F00AC4053 /* CH_FileTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_FileTableViewCell.xib; sourceTree = ""; }; + 7754104F2800109800AC4053 /* CH_FileSelectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_FileSelectorViewController.swift; sourceTree = ""; }; + 775410502800109800AC4053 /* CH_FileSelectorViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_FileSelectorViewController.xib; sourceTree = ""; }; + 77541053280010C000AC4053 /* FileDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDataSource.swift; sourceTree = ""; }; + 775410592800186800AC4053 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; + 776E3BEB2803BF670024C54D /* CH_ActionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_ActionTableViewCell.swift; sourceTree = ""; }; + 776E3C0F2803FC4F0024C54D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 776E3C15280422C50024C54D /* CH_HomeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_HomeViewController.xib; sourceTree = ""; }; + 776E3C16280422C50024C54D /* CH_HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_HomeViewController.swift; sourceTree = ""; }; + 776E3C1B280426B90024C54D /* CH_PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_PeripheralModel.swift; sourceTree = ""; }; + 776E3C1D28042CE30024C54D /* CH_Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_Preferences.swift; sourceTree = ""; }; + 776E3C1F280516150024C54D /* CH_PeripheralTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_PeripheralTableViewCell.swift; sourceTree = ""; }; + 776E3C20280516150024C54D /* CH_PeripheralTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_PeripheralTableViewCell.xib; sourceTree = ""; }; + 776E3C2728051E7B0024C54D /* CH_PeripheralSerivceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_PeripheralSerivceViewController.swift; sourceTree = ""; }; + 776E3C2828051E7B0024C54D /* CH_PeripheralSerivceViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CH_PeripheralSerivceViewController.xib; sourceTree = ""; }; + 777D6DEF28052A70003E2728 /* CH_FilterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_FilterViewController.xib; sourceTree = ""; }; + 777D6DF028052A70003E2728 /* CH_FilterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_FilterViewController.swift; sourceTree = ""; }; + 777D6DF32805450F003E2728 /* CH_ServiceTableHeadView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_ServiceTableHeadView.swift; sourceTree = ""; }; + 777D6DF42805450F003E2728 /* CH_ServiceTableHeadView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_ServiceTableHeadView.xib; sourceTree = ""; }; + 777D6DF728054649003E2728 /* CH_CharacteristicsTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_CharacteristicsTableViewCell.swift; sourceTree = ""; }; + 777D6DF828054649003E2728 /* CH_CharacteristicsTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_CharacteristicsTableViewCell.xib; sourceTree = ""; }; + 7798C75F28095BCB003033B5 /* XappKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XappKit.framework; sourceTree = ""; }; + 77A6C4F42807B575009CA06B /* CH_UpdateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_UpdateViewController.swift; sourceTree = ""; }; + 77A6C4F52807B575009CA06B /* CH_UpdateViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CH_UpdateViewController.xib; sourceTree = ""; }; + 77B81B8128056656001BFF9B /* BLEOTALibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = BLEOTALibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 77B81B8C2806A8EA001BFF9B /* IntelHexToBinCoverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntelHexToBinCoverter.swift; sourceTree = ""; }; + 77CBABDC28153E5F0088E07C /* CH_UpdateProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_UpdateProgressView.swift; sourceTree = ""; }; + 77CBABDE28153EDF0088E07C /* CH_UpdateProgressView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_UpdateProgressView.xib; sourceTree = ""; }; + 77CBABE0281545090088E07C /* ModernIcon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModernIcon.swift; sourceTree = ""; }; + 77CBABE2281545100088E07C /* ImageWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageWrapper.swift; sourceTree = ""; }; + 77CBABE428164C040088E07C /* CH_UpdateCheckView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CH_UpdateCheckView.swift; sourceTree = ""; }; + 77CBABE628164C0F0088E07C /* CH_UpdateCheckView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CH_UpdateCheckView.xib; sourceTree = ""; }; + 77CBABE828168D460088E07C /* CH_LogView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CH_LogView.swift; sourceTree = ""; }; + 77CBABE928168D460088E07C /* CH_LogView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CH_LogView.xib; sourceTree = ""; }; + 77E19ED127FD279700FE6D8D /* WCHBLEOTA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WCHBLEOTA.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 77E19ED427FD279700FE6D8D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 77E19EDD27FD279700FE6D8D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 77E19EE027FD279700FE6D8D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 77E19EE227FD279700FE6D8D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C578A462BE198D0F7F13A3C4 /* Pods_WCHBLEOTA.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WCHBLEOTA.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 77E19ECE27FD279700FE6D8D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 77B81B8228056656001BFF9B /* BLEOTALibrary.framework in Frameworks */, + 7798C76128095BF0003033B5 /* XappKit.framework in Frameworks */, + 5168723350E59F85941E8B89 /* Pods_WCHBLEOTA.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 13B7F1B27102810971DB4A54 /* Pods */ = { + isa = PBXGroup; + children = ( + 7096B7B68D3598BD6BCB3104 /* Pods-WCHBLEOTA.debug.xcconfig */, + 6382E55B3C92AD6B527CE092 /* Pods-WCHBLEOTA.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 77541023280007DA00AC4053 /* Utilities */ = { + isa = PBXGroup; + children = ( + 77541026280008F900AC4053 /* QuickError.swift */, + 775410242800082200AC4053 /* AlertPresenter.swift */, + 77CBABE0281545090088E07C /* ModernIcon.swift */, + 77CBABE2281545100088E07C /* ImageWrapper.swift */, + ); + path = Utilities; + sourceTree = ""; + }; + 7754102C28000AFD00AC4053 /* OTAFileSelector */ = { + isa = PBXGroup; + children = ( + 775410432800105F00AC4053 /* OTAFileSelector */, + 7754103128000CB300AC4053 /* View */, + ); + path = OTAFileSelector; + sourceTree = ""; + }; + 7754103128000CB300AC4053 /* View */ = { + isa = PBXGroup; + children = ( + ); + path = View; + sourceTree = ""; + }; + 775410432800105F00AC4053 /* OTAFileSelector */ = { + isa = PBXGroup; + children = ( + 775410592800186800AC4053 /* DocumentPicker.swift */, + 775410442800105F00AC4053 /* DocumentFileManager.swift */, + 775410452800105F00AC4053 /* Directory.swift */, + 7754104E2800107600AC4053 /* ViewController */, + 775410462800105F00AC4053 /* Model */, + 775410472800105F00AC4053 /* View */, + ); + name = OTAFileSelector; + sourceTree = ""; + }; + 775410462800105F00AC4053 /* Model */ = { + isa = PBXGroup; + children = ( + 77541053280010C000AC4053 /* FileDataSource.swift */, + 77B81B8C2806A8EA001BFF9B /* IntelHexToBinCoverter.swift */, + ); + path = Model; + sourceTree = ""; + }; + 775410472800105F00AC4053 /* View */ = { + isa = PBXGroup; + children = ( + 775410482800105F00AC4053 /* CH_FileTableViewCell.swift */, + 775410492800105F00AC4053 /* CH_FileTableViewCell.xib */, + 776E3BEB2803BF670024C54D /* CH_ActionTableViewCell.swift */, + ); + path = View; + sourceTree = ""; + }; + 7754104E2800107600AC4053 /* ViewController */ = { + isa = PBXGroup; + children = ( + 7754104F2800109800AC4053 /* CH_FileSelectorViewController.swift */, + 775410502800109800AC4053 /* CH_FileSelectorViewController.xib */, + ); + path = ViewController; + sourceTree = ""; + }; + 776E3C13280422860024C54D /* OTABLE */ = { + isa = PBXGroup; + children = ( + 776E3C14280422C50024C54D /* Controller */, + 776E3C17280422C50024C54D /* Model */, + 776E3C18280422C50024C54D /* View */, + ); + path = OTABLE; + sourceTree = ""; + }; + 776E3C14280422C50024C54D /* Controller */ = { + isa = PBXGroup; + children = ( + 776E3C16280422C50024C54D /* CH_HomeViewController.swift */, + 776E3C15280422C50024C54D /* CH_HomeViewController.xib */, + 777D6DF028052A70003E2728 /* CH_FilterViewController.swift */, + 777D6DEF28052A70003E2728 /* CH_FilterViewController.xib */, + 776E3C2728051E7B0024C54D /* CH_PeripheralSerivceViewController.swift */, + 776E3C2828051E7B0024C54D /* CH_PeripheralSerivceViewController.xib */, + 77A6C4F42807B575009CA06B /* CH_UpdateViewController.swift */, + 77A6C4F52807B575009CA06B /* CH_UpdateViewController.xib */, + ); + path = Controller; + sourceTree = ""; + }; + 776E3C17280422C50024C54D /* Model */ = { + isa = PBXGroup; + children = ( + 776E3C1B280426B90024C54D /* CH_PeripheralModel.swift */, + 776E3C1D28042CE30024C54D /* CH_Preferences.swift */, + ); + path = Model; + sourceTree = ""; + }; + 776E3C18280422C50024C54D /* View */ = { + isa = PBXGroup; + children = ( + 777D6DF728054649003E2728 /* CH_CharacteristicsTableViewCell.swift */, + 777D6DF828054649003E2728 /* CH_CharacteristicsTableViewCell.xib */, + 777D6DF32805450F003E2728 /* CH_ServiceTableHeadView.swift */, + 777D6DF42805450F003E2728 /* CH_ServiceTableHeadView.xib */, + 776E3C1F280516150024C54D /* CH_PeripheralTableViewCell.swift */, + 776E3C20280516150024C54D /* CH_PeripheralTableViewCell.xib */, + 77CBABDC28153E5F0088E07C /* CH_UpdateProgressView.swift */, + 77CBABDE28153EDF0088E07C /* CH_UpdateProgressView.xib */, + 77CBABE428164C040088E07C /* CH_UpdateCheckView.swift */, + 77CBABE628164C0F0088E07C /* CH_UpdateCheckView.xib */, + 77CBABE828168D460088E07C /* CH_LogView.swift */, + 77CBABE928168D460088E07C /* CH_LogView.xib */, + ); + path = View; + sourceTree = ""; + }; + 77E19EC827FD279700FE6D8D = { + isa = PBXGroup; + children = ( + 77E19ED327FD279700FE6D8D /* WCHBLEOTA */, + 77E19ED227FD279700FE6D8D /* Products */, + 13B7F1B27102810971DB4A54 /* Pods */, + A7F29D6A1CB1BE2E5B4B51BD /* Frameworks */, + ); + sourceTree = ""; + }; + 77E19ED227FD279700FE6D8D /* Products */ = { + isa = PBXGroup; + children = ( + 77E19ED127FD279700FE6D8D /* WCHBLEOTA.app */, + ); + name = Products; + sourceTree = ""; + }; + 77E19ED327FD279700FE6D8D /* WCHBLEOTA */ = { + isa = PBXGroup; + children = ( + 7798C75F28095BCB003033B5 /* XappKit.framework */, + 77541023280007DA00AC4053 /* Utilities */, + 7754102C28000AFD00AC4053 /* OTAFileSelector */, + 776E3C13280422860024C54D /* OTABLE */, + 77E19ED427FD279700FE6D8D /* AppDelegate.swift */, + 77E19EDD27FD279700FE6D8D /* Assets.xcassets */, + 776E3C0F2803FC4F0024C54D /* Images.xcassets */, + 77E19EDF27FD279700FE6D8D /* LaunchScreen.storyboard */, + 77E19EE227FD279700FE6D8D /* Info.plist */, + ); + path = WCHBLEOTA; + sourceTree = ""; + }; + A7F29D6A1CB1BE2E5B4B51BD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 77B81B8128056656001BFF9B /* BLEOTALibrary.framework */, + C578A462BE198D0F7F13A3C4 /* Pods_WCHBLEOTA.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 77E19ED027FD279700FE6D8D /* WCHBLEOTA */ = { + isa = PBXNativeTarget; + buildConfigurationList = 77E19EE527FD279700FE6D8D /* Build configuration list for PBXNativeTarget "WCHBLEOTA" */; + buildPhases = ( + 9FC964EFD043048CD4A810DF /* [CP] Check Pods Manifest.lock */, + 77E19ECD27FD279700FE6D8D /* Sources */, + 77E19ECE27FD279700FE6D8D /* Frameworks */, + 77E19ECF27FD279700FE6D8D /* Resources */, + 77E19EF627FD931400FE6D8D /* Embed Frameworks */, + 74ED894A780894C6C85D5067 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = WCHBLEOTA; + productName = WCHBLEOTA; + productReference = 77E19ED127FD279700FE6D8D /* WCHBLEOTA.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 77E19EC927FD279700FE6D8D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1310; + LastUpgradeCheck = 1310; + TargetAttributes = { + 77E19ED027FD279700FE6D8D = { + CreatedOnToolsVersion = 13.1; + }; + }; + }; + buildConfigurationList = 77E19ECC27FD279700FE6D8D /* Build configuration list for PBXProject "WCHBLEOTA" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 77E19EC827FD279700FE6D8D; + productRefGroup = 77E19ED227FD279700FE6D8D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 77E19ED027FD279700FE6D8D /* WCHBLEOTA */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 77E19ECF27FD279700FE6D8D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 777D6DFA28054649003E2728 /* CH_CharacteristicsTableViewCell.xib in Resources */, + 777D6DF128052A70003E2728 /* CH_FilterViewController.xib in Resources */, + 77E19EE127FD279700FE6D8D /* LaunchScreen.storyboard in Resources */, + 776E3C19280422C50024C54D /* CH_HomeViewController.xib in Resources */, + 776E3C102803FC4F0024C54D /* Images.xcassets in Resources */, + 776E3C2A28051E7B0024C54D /* CH_PeripheralSerivceViewController.xib in Resources */, + 776E3C22280516150024C54D /* CH_PeripheralTableViewCell.xib in Resources */, + 77CBABE728164C0F0088E07C /* CH_UpdateCheckView.xib in Resources */, + 77CBABEB28168D460088E07C /* CH_LogView.xib in Resources */, + 777D6DF62805450F003E2728 /* CH_ServiceTableHeadView.xib in Resources */, + 77A6C4F72807B575009CA06B /* CH_UpdateViewController.xib in Resources */, + 7754104D2800105F00AC4053 /* CH_FileTableViewCell.xib in Resources */, + 775410522800109800AC4053 /* CH_FileSelectorViewController.xib in Resources */, + 77CBABDF28153EDF0088E07C /* CH_UpdateProgressView.xib in Resources */, + 77E19EDE27FD279700FE6D8D /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 74ED894A780894C6C85D5067 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-WCHBLEOTA/Pods-WCHBLEOTA-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9FC964EFD043048CD4A810DF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-WCHBLEOTA-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 77E19ECD27FD279700FE6D8D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 77CBABE3281545100088E07C /* ImageWrapper.swift in Sources */, + 775410512800109800AC4053 /* CH_FileSelectorViewController.swift in Sources */, + 77A6C4F62807B575009CA06B /* CH_UpdateViewController.swift in Sources */, + 7754104A2800105F00AC4053 /* DocumentFileManager.swift in Sources */, + 776E3C21280516150024C54D /* CH_PeripheralTableViewCell.swift in Sources */, + 77541054280010C000AC4053 /* FileDataSource.swift in Sources */, + 77CBABEA28168D460088E07C /* CH_LogView.swift in Sources */, + 77E19ED527FD279700FE6D8D /* AppDelegate.swift in Sources */, + 776E3C2928051E7B0024C54D /* CH_PeripheralSerivceViewController.swift in Sources */, + 776E3BEC2803BF670024C54D /* CH_ActionTableViewCell.swift in Sources */, + 776E3C1A280422C50024C54D /* CH_HomeViewController.swift in Sources */, + 777D6DF928054649003E2728 /* CH_CharacteristicsTableViewCell.swift in Sources */, + 776E3C1C280426B90024C54D /* CH_PeripheralModel.swift in Sources */, + 77CBABE1281545090088E07C /* ModernIcon.swift in Sources */, + 776E3C1E28042CE30024C54D /* CH_Preferences.swift in Sources */, + 77CBABDD28153E600088E07C /* CH_UpdateProgressView.swift in Sources */, + 777D6DF228052A70003E2728 /* CH_FilterViewController.swift in Sources */, + 7754104C2800105F00AC4053 /* CH_FileTableViewCell.swift in Sources */, + 77541027280008F900AC4053 /* QuickError.swift in Sources */, + 7754104B2800105F00AC4053 /* Directory.swift in Sources */, + 7754105A2800186800AC4053 /* DocumentPicker.swift in Sources */, + 77B81B8D2806A8EA001BFF9B /* IntelHexToBinCoverter.swift in Sources */, + 777D6DF52805450F003E2728 /* CH_ServiceTableHeadView.swift in Sources */, + 775410252800082200AC4053 /* AlertPresenter.swift in Sources */, + 77CBABE528164C040088E07C /* CH_UpdateCheckView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 77E19EDF27FD279700FE6D8D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 77E19EE027FD279700FE6D8D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 77E19EE327FD279700FE6D8D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 77E19EE427FD279700FE6D8D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 77E19EE627FD279700FE6D8D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7096B7B68D3598BD6BCB3104 /* Pods-WCHBLEOTA.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5JZGQTGU4W; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/WCHBLEOTA", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = WCHBLEOTA/Info.plist; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = NO; + INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "通信时需要使用您的蓝牙权限,以便更好的为您提供服务"; + INFOPLIST_KEY_NSBluetoothPeripheralUsageDescription = "通信时需要使用您的蓝牙权限,以便更好的为您提供服务"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = ""; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportsDocumentBrowser = NO; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cn.wch.WCHBLEOTA; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 77E19EE727FD279700FE6D8D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6382E55B3C92AD6B527CE092 /* Pods-WCHBLEOTA.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5JZGQTGU4W; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/WCHBLEOTA", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = WCHBLEOTA/Info.plist; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = NO; + INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "通信时需要使用您的蓝牙权限,以便更好的为您提供服务"; + INFOPLIST_KEY_NSBluetoothPeripheralUsageDescription = "通信时需要使用您的蓝牙权限,以便更好的为您提供服务"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = ""; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportsDocumentBrowser = NO; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cn.wch.WCHBLEOTA; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 77E19ECC27FD279700FE6D8D /* Build configuration list for PBXProject "WCHBLEOTA" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 77E19EE327FD279700FE6D8D /* Debug */, + 77E19EE427FD279700FE6D8D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 77E19EE527FD279700FE6D8D /* Build configuration list for PBXNativeTarget "WCHBLEOTA" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 77E19EE627FD279700FE6D8D /* Debug */, + 77E19EE727FD279700FE6D8D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 77E19EC927FD279700FE6D8D /* Project object */; +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..9421093 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/project.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..7cce04f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c0dc142 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcodeproj/xcuserdata/moyun.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + WCHBLEOTA.xcscheme_^#shared#^_ + + orderHint + 6 + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/contents.xcworkspacedata b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b6f91e8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..12e6182 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/WorkspaceSettings.xcsettings b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..379adbe --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,18 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + IssueFilterStyle + ShowActiveSchemeOnly + LiveSourceIssuesEnabled + + ShowSharedSchemesAutomaticallyEnabled + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..1395264 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA.xcworkspace/xcuserdata/moyun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/AppDelegate.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/AppDelegate.swift new file mode 100644 index 0000000..725ce03 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/AppDelegate.swift @@ -0,0 +1,71 @@ +// +// AppDelegate.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/6. +// + +import UIKit +import XappKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + var homeVC: CH_HomeViewController? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + self.window = UIWindow.init(frame: UIScreen.main.bounds) + AppDelegate.configNavigationBarStyle() + + self.homeVC = CH_HomeViewController.init(nibName: "CH_HomeViewController", bundle: nil) + let navHome = XAPP_BaseNavController.init(rootViewController: self.homeVC!) + self.window?.rootViewController = navHome + self.window?.makeKeyAndVisible() + + return true + } + + func application(_ app: UIApplication, open inputURL: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + // Ensure the URL is a file URL + guard inputURL.isFileURL else { return false } + + return true + } + + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + static func configNavigationBarStyle () { + //导航栏配置 + UINavigationBar.appearance().barTintColor = UIColor.init(r: 42, g: 140, b: 205) + UINavigationBar.appearance().tintColor = UIColor.white //UIColor.init(hexString: "f8652b") +// UINavigationBar.appearance().barStyle = UIBarStyle.black; // + UINavigationBar.appearance().isTranslucent = false + let titleColor = UIColor.white //UIColor.init(hexString: "fb652b") + UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor : titleColor, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 18.0)] + + UINavigationBar.appearance().setBackgroundImage(UIImage.init(named: "navgation_top_bg"), for: .default) + + } + +} + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AccentColor.colorset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AppIcon.appiconset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Base.lproj/LaunchScreen.storyboard b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHBlue.colorset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHBlue.colorset/Contents.json new file mode 100644 index 0000000..585e85f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHBlue.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.808", + "green" : "0.663", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHGreen.colorset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHGreen.colorset/Contents.json new file mode 100644 index 0000000..8957ab7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHGreen.colorset/Contents.json @@ -0,0 +1,68 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.322", + "green" : "0.816", + "red" : "0.243" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.294", + "green" : "0.843", + "red" : "0.196" + } + }, + "idiom" : "iphone" + }, + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.322", + "green" : "0.816", + "red" : "0.243" + } + }, + "idiom" : "ipad" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.294", + "green" : "0.843", + "red" : "0.196" + } + }, + "idiom" : "ipad" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHRed.colorset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHRed.colorset/Contents.json new file mode 100644 index 0000000..d61fbec --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/WCHRed.colorset/Contents.json @@ -0,0 +1,33 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.319", + "green" : "0.243", + "red" : "0.814" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "platform" : "ios", + "reference" : "systemRedColor" + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/Contents.json new file mode 100644 index 0000000..9e8e6e6 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "btn_common_back@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "btn_common_back@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@2x.png new file mode 100644 index 0000000..7a12af9 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@3x.png new file mode 100644 index 0000000..1efa2d3 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/btn_common_back.imageset/btn_common_back@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/Contents.json new file mode 100644 index 0000000..a01aee7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "folderEmpty.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "folderEmpty@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "folderEmpty@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty.png new file mode 100644 index 0000000..216fd22 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@2x.png new file mode 100644 index 0000000..8218ae4 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@3x.png new file mode 100644 index 0000000..d255e95 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/folderEmpty.imageset/folderEmpty@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/Contents.json new file mode 100644 index 0000000..4f4ee27 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "doc-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "doc-1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "doc.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-1.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-1.png new file mode 100644 index 0000000..ec0085a Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-1.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-2.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-2.png new file mode 100644 index 0000000..79f14fe Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc-2.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc.png new file mode 100644 index 0000000..1119484 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/ic_document.imageset/doc.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/Contents.json new file mode 100644 index 0000000..a6609aa --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "上 传.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/\344\270\212 \344\274\240.png" "b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/\344\270\212 \344\274\240.png" new file mode 100644 index 0000000..90b8298 Binary files /dev/null and "b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/receive.imageset/\344\270\212 \344\274\240.png" differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/Contents.json new file mode 100644 index 0000000..e155695 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "上 传 (1).png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/\344\270\212 \344\274\240 (1).png" "b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/\344\270\212 \344\274\240 (1).png" new file mode 100644 index 0000000..83fd2fc Binary files /dev/null and "b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/send.imageset/\344\270\212 \344\274\240 (1).png" differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/Contents.json new file mode 100644 index 0000000..71e4cb8 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_0.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_0@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_0@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0.png new file mode 100644 index 0000000..ed7a927 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@2x.png new file mode 100644 index 0000000..ef29786 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@3x.png new file mode 100644 index 0000000..3757d49 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_0.imageset/signal_strength_0@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/Contents.json new file mode 100644 index 0000000..1296ac9 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_1@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_1@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1.png new file mode 100644 index 0000000..c22fc1a Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@2x.png new file mode 100644 index 0000000..c22fc1a Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@3x.png new file mode 100644 index 0000000..fce055b Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_1.imageset/signal_strength_1@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/Contents.json new file mode 100644 index 0000000..f71804c --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2.png new file mode 100644 index 0000000..f0fe09b Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@2x.png new file mode 100644 index 0000000..f0fe09b Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@3x.png new file mode 100644 index 0000000..a0aea58 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_2.imageset/signal_strength_2@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/Contents.json new file mode 100644 index 0000000..5a51713 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_3.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_3@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_3@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3.png new file mode 100644 index 0000000..ec377fe Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@2x.png new file mode 100644 index 0000000..aa934e8 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@3x.png new file mode 100644 index 0000000..e226c69 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_3.imageset/signal_strength_3@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/Contents.json new file mode 100644 index 0000000..198a761 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_4@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_4@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4.png new file mode 100644 index 0000000..32d37da Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@2x.png new file mode 100644 index 0000000..9837404 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@3x.png new file mode 100644 index 0000000..6184b8d Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_4.imageset/signal_strength_4@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/Contents.json new file mode 100644 index 0000000..185efcf --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "signal_strength_5.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "signal_strength_5@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "signal_strength_5@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5.png new file mode 100644 index 0000000..cb0b4da Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@2x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@2x.png new file mode 100644 index 0000000..cb0b4da Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@2x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@3x.png b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@3x.png new file mode 100644 index 0000000..ecb67cf Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/signal_strength_5.imageset/signal_strength_5@3x.png differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/Contents.json b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/Contents.json new file mode 100644 index 0000000..4ee84ea --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "update_ic.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/update_ic.pdf b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/update_ic.pdf new file mode 100644 index 0000000..76da277 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Images.xcassets/update_ic.imageset/update_ic.pdf differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Info.plist new file mode 100644 index 0000000..65c881f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Info.plist @@ -0,0 +1,106 @@ + + + + + CFBundleDocumentTypes + + + CFBundleTypeIconFiles + + icon-hex + icon-hex@2x + + CFBundleTypeName + nRF5x Hex + CFBundleTypeRole + Viewer + LSHandlerRank + Owner + LSItemContentTypes + + com.intel.hex + + + + CFBundleTypeIconFiles + + icon-hex + icon-hex@2x + + CFBundleTypeName + Distribution Packet (ZIP) + CFBundleTypeRole + Viewer + LSHandlerRank + Default + LSItemContentTypes + + com.pkware.zip-archive + + + + CFBundleTypeIconFiles + + CFBundleTypeName + Application Binary (BIN) + CFBundleTypeRole + Editor + LSHandlerRank + Owner + LSItemContentTypes + + com.apple.macbinary-archive + + + + CFBundleTypeIconFiles + + CFBundleTypeName + Directory + LSHandlerRank + Owner + LSItemContentTypes + + public.directory + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UIBackgroundModes + + bluetooth-central + bluetooth-peripheral + + UIFileSharingEnabled + + UTImportedTypeDeclarations + + + UTTypeConformsTo + + public.data + public.archive + + UTTypeDescription + Intel Hex File + UTTypeIdentifier + com.intel.hex + UTTypeReferenceURL + http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf + UTTypeSize320IconFile + icon-dfu-320 + UTTypeSize64IconFile + icon-dfu-64 + UTTypeTagSpecification + + public.filename-extension + hex + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/.DS_Store b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/.DS_Store new file mode 100644 index 0000000..7db341a Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/.DS_Store differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.swift new file mode 100644 index 0000000..b96234a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.swift @@ -0,0 +1,125 @@ +// +// FilterViewController.swift +// WCHBLEApp +// +// Created by 娟华 胡 on 2021/4/2. +// + +import UIKit +import XappKit + +class CH_FilterViewController: MH_VC_BaseViewController { + + @IBOutlet var needFilterLayoutConstraints: [NSLayoutConstraint]! + @IBOutlet var notNeedFilterLayoutConstraints: [NSLayoutConstraint]! + @IBOutlet weak var needFilterSwitch: UISwitch! + @IBOutlet weak var filterValueSlider: UISlider! + @IBOutlet weak var minimumRSSILabel: UILabel! + + public var filterCallBack:(()->Void)? + public var sortedCallBack:(()->Void)? + + var needFilter: Bool { + get { + return CH_PreferencesStore.shared.preferences?.needFilter ?? false + } + set(newValue) { + guard let _ = CH_PreferencesStore.shared.preferences else { + CH_PreferencesStore.shared.preferences = CH_Preferences() + CH_PreferencesStore.shared.preferences!.needFilter = newValue + return + } + CH_PreferencesStore.shared.preferences!.needFilter = newValue + } + } + var filterValue: Int { + get { + return CH_PreferencesStore.shared.preferences?.filter ?? -90 + } + set(newValue) { + guard let _ = CH_PreferencesStore.shared.preferences else { + CH_PreferencesStore.shared.preferences = CH_Preferences() + CH_PreferencesStore.shared.preferences!.needFilter = true + CH_PreferencesStore.shared.preferences!.filter = newValue + return + } + CH_PreferencesStore.shared.preferences!.filter = newValue + } + } + + override func viewDidLoad() { + _=self.leftBarItem(with: UIImage.init(named: "btn_common_back"), selector: #selector(backAction)); + _=self.rightBarItem(with: "Sort", selector: #selector(sortAction)) + super.viewDidLoad() + initAll() + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + if needFilterSwitch.isOn { + NSLayoutConstraint.deactivate(self.notNeedFilterLayoutConstraints) + NSLayoutConstraint.activate(self.needFilterLayoutConstraints) + } else { + NSLayoutConstraint.deactivate(self.needFilterLayoutConstraints) + NSLayoutConstraint.activate(self.notNeedFilterLayoutConstraints) + } + } + + private func initAll() { + self.toolbarItems = self.navigationController?.toolbar.items + if needFilter { + needFilterSwitch.isOn = true + filterValueSlider.value = Float(filterValue) + } else { + needFilterSwitch.isOn = false + } + reloadViews() + } + + private func reloadViews() { + if needFilterSwitch.isOn { + NSLayoutConstraint.deactivate(self.notNeedFilterLayoutConstraints) + NSLayoutConstraint.activate(self.needFilterLayoutConstraints) + + let minimumValue = abs(Int(filterValue)) + minimumRSSILabel.text = "Minimum RSSI: -\(minimumValue) dB" +// var barValue = 0 +// switch labs(minimumValue) { +// case 0...40: +// barValue = 5 +// case 41...53: +// barValue = 4 +// case 54...65: +// barValue = 3 +// case 66...77: +// barValue = 2 +// case 77...89: +// barValue = 1 +// default: +// barValue = 0 +// } +// minimumRSSILabel.text = "Minimum RSSI: -\(minimumValue) dB (\(barValue) bar\(barValue <= 1 ? "" : "s"))" + } else { + NSLayoutConstraint.deactivate(self.needFilterLayoutConstraints) + NSLayoutConstraint.activate(self.notNeedFilterLayoutConstraints) + } + } + + @IBAction func didSwitchToggle(_ sw: UISwitch) { + needFilter = sw.isOn + reloadViews() + } + + @IBAction func didSliderChang(_ slider: UISlider) { + filterValue = Int(slider.value) + self.filterCallBack?() + reloadViews() + } + + @objc func sortAction() { + self.sortedCallBack?() + _=self.showSuccessMessage("排序成功") + } + + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.xib new file mode 100644 index 0000000..798f5d9 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_FilterViewController.xib @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.swift new file mode 100644 index 0000000..0c3ed32 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.swift @@ -0,0 +1,242 @@ +// +// CH_HomeViewController.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/6. +// + +import UIKit +import XappKit +import BLEOTALibrary + +class CH_HomeViewController: MH_VC_BaseViewController { + + @IBOutlet weak var tableView: MH_V_RefreshTableView! + + var preferences: CH_Preferences? { + return CH_PreferencesStore.shared.preferences + } + + private var OTAManager:BLEOTAManager? + private var connectPeripheral:CBPeripheral? + private var devicesArray:[CH_PeripheralModel] = [CH_PeripheralModel]() + + private var servicesArray:[CBService] = [CBService]() + private var serviceCharacter:[String:[CBCharacteristic]] = [String:[CBCharacteristic]]() + private weak var serviceVC:CH_PeripheralSerivceViewController? + private var writeCallBack:writeDataCallBack? + + override func viewDidLoad() { + super.viewDidLoad() + + self.navbarStatus = .Show + self.title = "Device List" + _=self.rightBarItem(with: "Filter", selector: #selector(filterAction)) + + // Do any additional setup after loading the view. + self.setupHome() + } + + func setupHome() { + self.OTAManager = BLEOTAManager.shareInstance() + self.OTAManager?.delegate = self + + self.tableView.tableFooterView = UIView() + self.tableView.setTableViewRefreshHeader() + self.tableView.refreshHeaderHandler = { [weak self] in + guard let wself = self else { return } + wself.devicesArray.removeAll() + wself.scanAllPeripheral() + } + } + + private func scanAllPeripheral() { + self.devicesArray.removeAll() + self.tableView.reloadData() + self.OTAManager?.stopScan() + self.OTAManager?.startScan(nil) + } + + private func stopScan() { + self.OTAManager?.stopScan() + } + + private func setConnectSuccess() { + let sVC = CH_PeripheralSerivceViewController.init(nibName: "CH_PeripheralSerivceViewController", bundle: Bundle.init(for: CH_PeripheralSerivceViewController.self)) + + sVC.services = self.servicesArray + + sVC.serviceBackAction = { [weak self] in + guard let wself = self else { return } + wself.OTAManager?.disconnect(wself.connectPeripheral) + wself.scanAllPeripheral() + } + + self.navigationController?.pushViewController(sVC, animated: true) + self.serviceVC = sVC + } + + @objc func filterAction() { + let filterVC = CH_FilterViewController.init(nibName: "CH_FilterViewController", bundle: Bundle.init(for: CH_FilterViewController.self)) + filterVC.filterCallBack = { [weak self] in + guard let wself = self else { return } + wself.scanAllPeripheral() + } + filterVC.sortedCallBack = { [weak self] in + guard let wself = self else { return } + wself.devicesArray = wself.devicesArray.sorted { + $0.RSSI.intValue > $1.RSSI.intValue + } + wself.tableView.reloadData() + } + self.navigationController?.pushViewController(filterVC, animated: true) + } + + @IBAction func scanFileAction(_ sender: Any) { + //获取目录下的文件 +// let documentPath = NSHomeDirectory() + "/Documents/all.hex" +// print(documentPath) +// +// //判断文件是否存在 +// if FileManager.default.fileExists(atPath: documentPath) { +// print("文件存在"); + // let fileUrl = URL.init(fileURLWithPath: documentPath) + // let data = try? Data(contentsOf: fileUrl) + // + // print(data); +// }else { +// +// } + let fileVC = CH_FileSelectorViewController.init(documentPicker: WCHDocumentPicker()) + self.navigationController?.pushViewController(fileVC, animated: true) + + } +} + +extension CH_HomeViewController:UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 100 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.devicesArray.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: "CH_PeripheralTableViewCell") as? CH_PeripheralTableViewCell + if (cell == nil) { + cell = CH_PeripheralTableViewCell.loadCell() + } + + cell?.selectionStyle = .none + cell?.peripheralConnect = {[weak self] (perpheral) in + guard let wself = self else { return } + if (perpheral == nil) { + _ = wself.showFailedMessage("为获取外设对象") + return + } + if (perpheral?.state == .connected) { + wself.OTAManager?.disconnect(perpheral) + }else { + wself.OTAManager?.connect(perpheral) + _ = wself.showLoadingWithText("正在连接...") + } + } + + if (self.devicesArray.count > indexPath.row) { + let model = self.devicesArray[indexPath.row] + cell?.updatePeripheralCell(model:model) + } + + return cell ?? UITableViewCell() + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + } + +} + +extension CH_HomeViewController:BLEOTADelegate { + + func bleManagerDidDiscover(_ peripheral: CBPeripheral!, advertisementData: [String : Any]!, rssi RSSI: NSNumber!) { + if (peripheral == nil || advertisementData == nil || RSSI == nil) { + return + } + self.tableView.endHeaderRefersh() + let peripheralInfo = CH_PeripheralModel.init(peripheral) + if (!self.devicesArray.contains(peripheralInfo)) { + let nowTimeInterval = Date().timeIntervalSince1970 + + if let preference = preferences, preference.needFilter { + if RSSI!.intValue != 127, RSSI!.intValue > preference.filter { + peripheralInfo.advertisementData = advertisementData! + peripheralInfo.RSSI = RSSI! + peripheralInfo.lastUpdatedTimeInterval = nowTimeInterval + self.devicesArray.append(peripheralInfo) + } + } else { + peripheralInfo.advertisementData = advertisementData! + peripheralInfo.RSSI = RSSI! + peripheralInfo.lastUpdatedTimeInterval = nowTimeInterval + self.devicesArray.append(peripheralInfo) + } + + }else { + guard let index = self.devicesArray.firstIndex(of: peripheralInfo) else { + return + } + let originPeripheralInfo = self.devicesArray[index] + let nowTimeInterval = Date().timeIntervalSince1970 + + originPeripheralInfo.lastUpdatedTimeInterval = nowTimeInterval + originPeripheralInfo.RSSI = RSSI! + originPeripheralInfo.advertisementData = advertisementData! + } + self.tableView.reloadData() + } + + func bleManagerDidUpdateState(_ error: Error?) { + let nsError = error as NSError? + let errorInfo = nsError?.userInfo + print(errorInfo?["NSUnderlyingError"] as? String ?? "未知错误") + _=self.showFailedMessage(errorInfo?["NSUnderlyingError"] as? String ?? "未知错误") + } + + func bleManagerDidPeripheralConnectUpateState(_ peripheral: CBPeripheral!, error: Error?) { + self.hideHud() + if (nil == error) { + _=self.showSuccessMessage("连接成功") + self.connectPeripheral = peripheral + + self.OTAManager?.readRSSI(peripheral, rssiCallBack: { (number) in + print("读取到了信号强度",Int(truncating: number ?? 0)) + }) + }else { + let nsError = error as NSError? + let errorInfo = nsError?.userInfo + _=self.showFailedMessage(errorInfo?["NSUnderlyingError"] as? String ?? "未知错误") + } + self.tableView.reloadData() + } + + func bleManagerPeriphearl(_ peripheral: CBPeripheral!, services: [CBService]?, error: Error?) { + if (nil == error) { + self.servicesArray.removeAll() + self.servicesArray = services ?? [CBService]() + self.setConnectSuccess() + } + } + + func bleManagerService(_ service: CBService!, characteristics: [CBCharacteristic]!, error: Error?) { + if (nil == error) { + self.serviceCharacter[service?.uuid.uuidString ?? ""] = characteristics + self.serviceVC?.servicesCharacterList(list: self.serviceCharacter) + } + } + + func bleManagerUpdateValue(forCharacteristic peripheral: CBPeripheral!, characteristic: CBCharacteristic!, error: Error?) { + + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.xib new file mode 100644 index 0000000..b342f51 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_HomeViewController.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.swift new file mode 100644 index 0000000..0571e67 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.swift @@ -0,0 +1,119 @@ +// +// CH_PeripheralSerivceViewController.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/12. +// + +import UIKit +import XappKit +import BLEOTALibrary +import CoreBluetooth + +class CH_PeripheralSerivceViewController: MH_VC_BaseViewController { + + public var serviceBackAction:(()->Void)? + public var services:[CBService] = [CBService]() + private var serviceCharacter:[String:[CBCharacteristic]] = [String:[CBCharacteristic]]() + + @IBOutlet weak var tableView: UITableView! + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Device Information" + _=self.leftBarItem(with: UIImage.init(named: "btn_common_back"), selector: #selector(backAction)); + _=self.rightBarItem(with: "Update", selector: #selector(updateAction)) + // Do any additional setup after loading the view. + self.setupViews() + + } + + override func backAction() { + self.serviceBackAction?() + super.backAction() + } + + func setupViews() { + self.tableView.tableFooterView = UIView() + self.tableView.estimatedRowHeight = 0 + self.tableView.estimatedSectionHeaderHeight = 0 + self.tableView.estimatedSectionFooterHeight = 0 + } + + public func servicesCharacterList(list:[String:[CBCharacteristic]]) { + self.serviceCharacter = list + self.tableView.reloadData() + } + + @objc + private func updateAction() { + + let object:CurrentImageObject? = BLEOTAManager.shareInstance().getCurrentImageInfo(); + if (object == nil) { + _ = self.showFailedMessage("未获取到固件信息,请重新连接") + }else { + let fileVC = CH_FileSelectorViewController.init(documentPicker: WCHDocumentPicker()) + self.navigationController?.pushViewController(fileVC, animated: true) + } + } +} + +extension CH_PeripheralSerivceViewController:UITableViewDelegate, UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return services.count + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return 70 + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let headView = CH_ServiceTableHeadView.instanceFromNib() + if (services.count > section) { + let service = services[section] + headView?.updateServiceHead(service: service) + } + + return headView + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 86 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if (services.count > section) { + let service = services[section] + let uuid = service.uuid.uuidString + let characters = self.serviceCharacter[uuid] + return characters?.count ?? 0 + } + return 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: "CH_CharacteristicsTableViewCell") as? CH_CharacteristicsTableViewCell + if (cell == nil) { + cell = CH_CharacteristicsTableViewCell.instanceFromNib() + } + cell?.selectionStyle = .none + if (self.services.count > indexPath.section) { + let service = self.services[indexPath.section] + let characters = self.serviceCharacter[service.uuid.uuidString] + if ((characters?.count ?? 0) > indexPath.row) { + cell?.updateCharactertics(character: characters![indexPath.row]) + } + + cell?.characterSend = {[weak self] in + guard let wself = self else { return } + } + + cell?.characterReceive = {[weak self] in + guard let wself = self else { return } + } + } + return cell ?? UITableViewCell() + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.xib new file mode 100644 index 0000000..a5db62d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_PeripheralSerivceViewController.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.swift new file mode 100644 index 0000000..2f284c4 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.swift @@ -0,0 +1,217 @@ +// +// CH_UpdateViewController.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/14. +// + +import UIKit +import XappKit +import SnapKit +import BLEOTALibrary + +class CH_UpdateViewController: MH_VC_BaseViewController { + + private var progressView: CH_UpdateProgressView? + private var checkView:CH_UpdateCheckView? + private var logView:CH_LogView? + + @IBOutlet weak var inputTextField: UITextField! + + @IBOutlet weak var progressContainView: UIView! + + @IBOutlet weak var logContainView: UIView! + + public var fname:String? + + public var fileData:Data? + + public var ishex:Bool? + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Update" + _ = self.leftBarItem(with: UIImage.init(named: "btn_common_back"), selector: #selector(backAction)) + _ = self.rightBarItem(with: "Check", selector: #selector(checkAction)) + // Do any additional setup after loading the view. + + if (nil == self.progressView) { + self.progressView = CH_UpdateProgressView.instanceFromNib() + } + self.progressContainView.addSubview(self.progressView!) + self.progressView!.snp.makeConstraints { make in + make.left.equalTo(0) + make.right.equalTo(0) + make.top.equalTo(0) + make.bottom.equalTo(0) + } + } + + @IBAction func cancleUpdateAction(_ sender: Any) { + + self.progressView?.stopAnimating() + self.progressView?.style = .error + self.progressView?.updateStatus(status: "升级已取消") + self.progressView?.updateProgress(progress: 0) + + BLEOTAManager.shareInstance().cancleOTAUpdate(); + } + + + @IBAction func startUpdateAction(_ sender: Any) { + + var inputStr = self.inputTextField.text ?? "0" + + if (!inputStr.isHexNumber) { + _ = self.showFailedMessage("Invalid Hex Number") + return; + } + + if (self.fileData == nil) { + return; + } + + let model = BLEOTAManager.shareInstance().getCurrentImageInfo() + if (model?.chipType == .UNKNOW) { + _ = self.showFailedMessage("Please Check Chip Type") + } + + + if inputStr.count == 0 { + inputStr = "0"; + } + + let addr = Int(inputStr, radix: 16)! + var startTime = Date.init(timeIntervalSinceNow: 0).timeIntervalSince1970 + var updateCount = 0; + + var sendData:Data? = self.fileData + + //根据数据格式,设定源数据文件是否需要进行偏移 + //hex格式已经转化bin后,已经对源数据文件进行了偏移,所以只需设置bin文件数据位置 + if (!self.ishex!) { + let data = sendData?.subdata(in: addr ..< sendData!.count) + print(data!) + sendData = data + } + + let totalLength:Int = sendData!.count * 2; + var receiveLength = 0; + + + self.progressView?.startAnimating() + self.progressView?.style = .update + + BLEOTAManager.shareInstance().startOTAUpdate(sendData!, eraseAddr: addr) {[weak self] (NSInteger) in + guard let sself = self else {return} + receiveLength += NSInteger + updateCount += NSInteger + + DispatchQueue.main.async { + let value = Float(receiveLength) / Float(totalLength) + sself.progressView?.updateProgress(progress: value) +// let currentTime = Date.init(timeIntervalSinceNow: 0).timeIntervalSince1970 +// let time = currentTime - (startTime ) +// if time > 0 { +// let speed = Double(updateCount) / time +// if (speed > 1000) { +// sself.progressView.text = String.init(format: "接收速度:%0.1f KB/S", speed / 1024) +// }else { +// sself.progressView.text = String.init(format: "接收速度:%0.1f B/S", speed) +// } +// } + } + } progressCallBack: {[weak self] (type) in + guard let sself = self else {return} + + var statusStr:String = "Connecting" + DispatchQueue.main.async { + switch type { + case .erase: + statusStr = "开始擦除" + break + case .eraseSuccess: + statusStr = "擦除成功" + break + case .eraseFailed: + statusStr = "擦除失败" + sself.progressView?.stopAnimating() + sself.progressView?.style = .error + break + case .program: + statusStr = "开始数据写入" + break + case .programWait: + statusStr = "等待数据发送结果" + break + case .programSuccess: + statusStr = "数据写入成功" + startTime = Date.init(timeIntervalSinceNow: 0).timeIntervalSince1970 + updateCount = 0; + break + case .programFailed: + statusStr = "数据写入失败" + sself.progressView?.stopAnimating() + sself.progressView?.style = .error + break + case .verify: + statusStr = "开始数据认证" + break + case .verifyWait: + statusStr = "等待数据认证" + break + case .verifySuccess: + statusStr = "数据认证成功" + break + case .verifyFailed: + statusStr = "数据认证失败" + sself.progressView?.stopAnimating() + sself.progressView?.style = .error + break + case .end: + statusStr = "升级成功" + sself.progressView?.style = .done + break + default: + break + } + + sself.progressView?.updateStatus(status: statusStr) + } + } + } + + + @IBAction func backGroundAction(_ sender: Any) { + self.inputTextField.resignFirstResponder() + } + + @objc func checkAction() { + if (nil == self.checkView) { + self.checkView = CH_UpdateCheckView.instanceFromNib() + } + + self.view.addSubview(self.checkView!) + self.checkView!.snp.makeConstraints { make in + make.left.equalTo(0) + make.right.equalTo(0) + make.top.equalTo(0) + make.bottom.equalTo(0) + } + + let model = BLEOTAManager.shareInstance().getCurrentImageInfo() + self.checkView!.updateCheckInfo(model:model!) + + self.checkView!.chipTypeSelect = { (index) in + var type:ChipType? + if (index == 0) { + type = .CH573 + }else if (index == 1) { + type = .CH583 + }else if (index == 2) { + type = .CH579 + } + BLEOTAManager.shareInstance().setChipType(type!) + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.xib new file mode 100644 index 0000000..abc9b5f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Controller/CH_UpdateViewController.xib @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_PeripheralModel.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_PeripheralModel.swift new file mode 100644 index 0000000..cc8c1d2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_PeripheralModel.swift @@ -0,0 +1,21 @@ +// +// CH_PeripheralModel.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/11. +// + +import UIKit +import CoreBluetooth + +class CH_PeripheralModel: NSObject { + let peripheral:CBPeripheral + var RSSI:NSNumber = 0 + var advertisementData:[String:Any] = [:] + var lastUpdatedTimeInterval: TimeInterval + + init(_ peripheral: CBPeripheral) { + self.peripheral = peripheral + self.lastUpdatedTimeInterval = Date().timeIntervalSince1970 + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_Preferences.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_Preferences.swift new file mode 100644 index 0000000..e0fd81d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/Model/CH_Preferences.swift @@ -0,0 +1,46 @@ +// +// CH_Preferences.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/11. +// + +import UIKit + +struct CH_Preferences: Codable { + var needFilter: Bool + var filter: Int + + init() { + self.needFilter = false + filter = -90 + } +} + + + +class CH_PreferencesStore: NSObject { + static let shared = CH_PreferencesStore() + private let preferencesKey = "preferencesKey" + + var preferences: CH_Preferences? { + didSet { + self.save() + } + } + + override init() { + if let data = UserDefaults.standard.object(forKey: preferencesKey) as? Data, let preferences = try? JSONDecoder().decode(CH_Preferences.self, from: data) { + self.preferences = preferences + } + } + + private func save() { + guard let encodedData = try? JSONEncoder().encode(preferences) else { + return + } + + UserDefaults.standard.set(encodedData, forKey: preferencesKey) + UserDefaults.standard.synchronize() + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.swift new file mode 100644 index 0000000..2638326 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.swift @@ -0,0 +1,85 @@ +// +// CharacteristicsTableViewCell.swift +// WCHBLEApp +// +// Created by 娟华 胡 on 2021/3/23. +// + +import UIKit +import CoreBluetooth + +class CH_CharacteristicsTableViewCell: UITableViewCell { + + @IBOutlet weak var nameLabel: UILabel! + @IBOutlet weak var uuidLabel: UILabel! + @IBOutlet weak var propertiesLabel: UILabel! + + @IBOutlet weak var receiveButton: UIButton! + @IBOutlet weak var sendButton: UIButton! + + @IBOutlet weak var sendImageView: UIImageView! + @IBOutlet weak var receiveImageView: UIImageView! + + public var characterSend:(()->Void)? + public var characterReceive:(()->Void)? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + self.receiveButton.isHidden = true + self.sendButton.isHidden = true + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + @IBAction func showSendView(_ sender: Any) { + self.characterSend?() + } + + @IBAction func showReadView(_ sender: Any) { + self.characterReceive?() + } + + public func updateCharactertics(character:CBCharacteristic) { + self.nameLabel.text = "\(character.uuid)" + self.uuidLabel.text = "UUID:\(character.uuid.uuidString)" + + var properties = "properties:" + if (character.properties.contains(.read)) { + properties += " Read" + } + + if (character.properties.contains(.write) || character.properties.contains(.writeWithoutResponse)) { + properties += " Write" + } + + if (character.properties.contains(.notify)) { + properties += " Notify" + } + + self.propertiesLabel.text = properties + + if (character.properties.contains(.read) || character.properties.contains(.notify)) { + self.receiveButton.isHidden = false + self.receiveImageView.isHidden = false + + }else { + self.receiveButton.isHidden = true + self.receiveImageView.isHidden = true + } + + if (character.properties.contains(.write)) { + self.sendButton.isHidden = false + self.sendImageView.isHidden = false + }else { + self.sendButton.isHidden = true + self.sendImageView.isHidden = true + } + + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.xib new file mode 100644 index 0000000..896a4bb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_CharacteristicsTableViewCell.xib @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.swift new file mode 100644 index 0000000..33bbd82 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.swift @@ -0,0 +1,55 @@ +// +// LogView.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/24. +// + +import UIKit + +class CH_LogView: UIView { + + @IBOutlet weak var tableView: UITableView! + + private var logArray:NSArray? + + override func awakeFromNib() { + self.tableView.delegate = self + self.tableView.dataSource = self + self.tableView.separatorStyle = .none + self.tableView.estimatedRowHeight = 44.0 + self.tableView.rowHeight = UITableView.automaticDimension + self.tableView.tableFooterView = UIView() + } + + public func setLog(log:NSArray?) { + if (log == nil) { + return + } + self.logArray = log + self.tableView.reloadData() + } + +} + +extension CH_LogView:UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.logArray?.count ?? 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier:"logCell") + if (cell == nil) { + cell = UITableViewCell.init(style: .default, reuseIdentifier: "logCell") + } + cell?.selectionStyle = .none + if ((self.logArray?.count ?? 0) > indexPath.row) { + let log = self.logArray?[indexPath.row] as? String ?? "" + cell?.textLabel?.numberOfLines = 0 + cell?.textLabel?.font = UIFont.systemFont(ofSize: 14.0) + cell?.textLabel?.text = log + } + return cell ?? UITableViewCell() + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.xib new file mode 100644 index 0000000..e4644f4 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_LogView.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.swift new file mode 100644 index 0000000..da6de0a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.swift @@ -0,0 +1,70 @@ +// +// PeripheralTableViewCell.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/6. +// + +import UIKit +import CoreBluetooth + +class CH_PeripheralTableViewCell: UITableViewCell { + + @IBOutlet weak var signalStrengthImg: UIImageView! + @IBOutlet weak var nameLabel: UILabel! + @IBOutlet weak var rssiLabel: UILabel! + @IBOutlet weak var stateLabel: UILabel! + @IBOutlet weak var identifierLabel: UILabel! + @IBOutlet weak var connectBtn: UIButton! + + public var peripheralConnect:((CBPeripheral?)->Void)? + private var peripheral:CBPeripheral? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + public class func loadCell() -> CH_PeripheralTableViewCell?{ + let bundle = Bundle.init(for: CH_PeripheralTableViewCell.self) + let nibs = bundle.loadNibNamed("CH_PeripheralTableViewCell", owner: self, options: nil) + return nibs?.first as? CH_PeripheralTableViewCell + } + + @IBAction func connectAction(_ sender: Any) { + self.peripheralConnect?(self.peripheral) + } + + public func updatePeripheralCell(model:CH_PeripheralModel) { + self.peripheral = model.peripheral + if ((model.peripheral.name?.isEmpty) != nil) { + self.nameLabel.text = (model.peripheral.name ?? "") + }else { + self.nameLabel.text = "Unnamed" + } + + self.rssiLabel.text = String.init(format: "%d", model.RSSI as? Int ?? 0) + self.identifierLabel.text = "UUID:\(model.peripheral.identifier)" + if let serviceUUIDs = model.advertisementData["kCBAdvDataServiceUUIDs"] as? NSArray, serviceUUIDs.count != 0 { + self.stateLabel.text = "\(serviceUUIDs.count) service" + (serviceUUIDs.count > 1 ? "s" : "") + } else { + self.stateLabel.text = "No service" + } + + switch labs(model.RSSI.intValue) { + case 0...40: + self.signalStrengthImg.image = UIImage(named: "signal_strength_5") + case 41...53: + self.signalStrengthImg.image = UIImage(named: "signal_strength_4") + case 54...65: + self.signalStrengthImg.image = UIImage(named: "signal_strength_3") + case 66...77: + self.signalStrengthImg.image = UIImage(named: "signal_strength_2") + case 77...89: + self.signalStrengthImg.image = UIImage(named: "signal_strength_1") + default: + self.signalStrengthImg.image = UIImage(named: "signal_strength_0") + } + } +} + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.xib new file mode 100644 index 0000000..1e4148a --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_PeripheralTableViewCell.xib @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.swift new file mode 100644 index 0000000..1e0197f --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.swift @@ -0,0 +1,24 @@ +// +// ServiceTableHeadView.swift +// WCHBLEApp +// +// Created by 娟华 胡 on 2021/3/23. +// + +import UIKit +import CoreBluetooth + + +class CH_ServiceTableHeadView: UIView { + + @IBOutlet weak var nameLabel: UILabel! + @IBOutlet weak var uuidLabel: UILabel! + @IBOutlet weak var privateLabel: UILabel! + + public func updateServiceHead(service:CBService) { + self.nameLabel.text = "\(service.uuid)" + self.uuidLabel.text = "UUID:" + service.uuid.uuidString + self.privateLabel.text = service.isPrimary ? "PRIMARY SERVICE" : "NO PRIMIARY" + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.xib new file mode 100644 index 0000000..878c474 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_ServiceTableHeadView.xib @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.swift new file mode 100644 index 0000000..84f969e --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.swift @@ -0,0 +1,78 @@ +// +// CH_UpdateCheckView.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/25. +// + +import UIKit +import BLEOTALibrary + +class CH_UpdateCheckView: UIView { + + @IBOutlet weak var chipTypeLabel: UILabel! + + @IBOutlet weak var imageTypeLabel: UILabel! + + @IBOutlet weak var blockSizeLabel: UILabel! + + @IBOutlet weak var offsetLabel: UILabel! + + @IBOutlet weak var containView: UIView! + + @IBOutlet weak var segmentView: UISegmentedControl! + + + var chipTypeSelect:((NSInteger)->Void)? + + override func awakeFromNib() { + super.awakeFromNib() + + self.containView.layer.cornerRadius = 15 + self.containView.layer.masksToBounds = true + } + + @IBAction func segMentSelect(_ sender: Any) { + + let seg:UISegmentedControl = sender as! UISegmentedControl + + self.chipTypeSelect?(seg.selectedSegmentIndex) + } + + public func updateCheckInfo(model:CurrentImageObject) { + + var chipType:String = "" + var imageType:String = "" + if (model.chipType == .CH573) { + chipType = "CH573" + }else if (model.chipType == .CH583) { + chipType = "CH583" + }else if (model.chipType == .CH579) { + chipType = "CH579" + }else { + chipType = "UNKNOW" + } + + if (model.type == .A) { + imageType = "ImageA" + }else if (model.type == .B) { + imageType = "ImageB" + }else { + imageType = "UNKNOW" + } + + self.chipTypeLabel.text = chipType + self.imageTypeLabel.text = imageType + self.blockSizeLabel.text = "\(model.blockSize)" + self.offsetLabel.text = "\(model.offset)" + + if (chipType != "UNKNOW") { + self.segmentView.isHidden = true + } + } + + @IBAction func backGroundAction(_ sender: Any) { + self.removeFromSuperview() + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.xib new file mode 100644 index 0000000..6b52595 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateCheckView.xib @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.swift new file mode 100644 index 0000000..da71f17 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.swift @@ -0,0 +1,74 @@ +// +// CH_UpdateProgressView.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/24. +// + +import UIKit + +class CH_UpdateProgressView: UIView { + + enum Style { + case update, error, done + } + + @IBOutlet var updateLogoImage: UIImageView! + @IBOutlet var progressView: UIProgressView! + @IBOutlet var statusLabel: UILabel! + + var style: Style = .update { + didSet { + let colorImage: (UIColor, ModernIcon, UIImage?) = { + let oldImage = UIImage(named: "update_ic")?.withRenderingMode(.alwaysTemplate) + switch style { + case .done: return (UIColor(named: "WCHGreen")!, ModernIcon.checkmark(.circle), oldImage) + case .error: return (UIColor(named: "WCHRed")!, ModernIcon.exclamationmark(.triangle), oldImage) + case .update: return (UIColor(named: "WCHBlue")!, ModernIcon.arrow(.init(digit: 2))(.circlePath), oldImage) + } + }() + + updateLogoImage.tintColor = colorImage.0 + if #available(iOS 13, *) { + updateLogoImage.image = colorImage.1.image + } else { + updateLogoImage.image = colorImage.2 + } + + progressView.tintColor = colorImage.0 + statusLabel.textColor = style == .error ? UIColor(named: "WCHRed")! : UIColor.black + + if style != .update { + stopAnimating() + } + } + } + + func startAnimating() { +// updateLogoImage.translatesAutoresizingMaskIntoConstraints = true + + UIView.animateKeyframes(withDuration: 1, delay: 0, options: [.repeat], animations: { + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1) { + self.updateLogoImage.transform = CGAffineTransform(rotationAngle: .pi) + } + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) { + self.updateLogoImage.transform = CGAffineTransform(scaleX: 1.2, y: 1.2) + } + UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) { + self.updateLogoImage.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) + } + }) + } + + func stopAnimating() { + updateLogoImage.layer.removeAllAnimations() + } + + public func updateStatus(status:String) { + self.statusLabel.text = status + } + + public func updateProgress(progress:Float) { + self.progressView.progress = progress + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.xib new file mode 100644 index 0000000..ccd4fb0 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTABLE/View/CH_UpdateProgressView.xib @@ -0,0 +1,78 @@ + + + + + + + + + + + + + GTEestiDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/.DS_Store b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/.DS_Store new file mode 100644 index 0000000..d836419 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/.DS_Store differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Directory.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Directory.swift new file mode 100644 index 0000000..2bb9e56 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Directory.swift @@ -0,0 +1,32 @@ +// +// Directory.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import Foundation + +protocol FileNode { + var url: URL { get } + var name: String { get } + var resourceModificationDate: Date? { get } +} + +extension FileNode { + var name: String { + return url.lastPathComponent + } +} + +struct File: FileNode { + let url: URL + let size: Int + var resourceModificationDate: Date? +} + +struct Directory: FileNode { + let url: URL + var nodes: [FileNode] + var resourceModificationDate: Date? +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentFileManager.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentFileManager.swift new file mode 100644 index 0000000..6339ab3 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentFileManager.swift @@ -0,0 +1,51 @@ +// +// DocumentFileManager.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import Foundation + +class DocumentFileManager: FileManager { + + func buildDocumentDir() throws -> Directory { + let docDir = try url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) + return try buildDir(url: docDir) + } + + func buildDir(url: URL) throws -> Directory { + let nodes = try buildTree(url: url) + return Directory(url: url, nodes: nodes) + } + + func buildTree(url: URL) throws -> [FileNode] { + do { + return try contentsOfDirectory(atPath: url.path).compactMap { itemName -> FileNode? in + let itemUrl = url.appendingPathComponent(itemName) + + var isDir: ObjCBool = false + let fileExist = self.fileExists(atPath: itemUrl.path, isDirectory: &isDir) + + guard fileExist else { return nil } + + let attr = try attributesOfItem(atPath: itemUrl.path) + let modificationDate = attr[.modificationDate] as? Date + + if isDir.boolValue { + let nestedNodes = try self.buildTree(url: itemUrl) + return Directory(url: itemUrl, nodes: nestedNodes, resourceModificationDate: modificationDate) + } else { + let size = attr[.size] as? Int ?? 0 + return File(url: itemUrl, size: size, resourceModificationDate: modificationDate) + } + } + } catch { + return [] + } + } + + func deleteNode(_ node: FileNode) throws { + try removeItem(at: node.url) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentPicker.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentPicker.swift new file mode 100644 index 0000000..29ea937 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/DocumentPicker.swift @@ -0,0 +1,81 @@ +// +// DocumentPicker.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit +import UniformTypeIdentifiers + +class DocumentPicker: NSObject, UIDocumentPickerDelegate { + typealias Callback = (Result) -> () + private (set) var callback: Callback! + let types: [String] + + init(documentTypes: [String]) { + types = documentTypes + super.init() + } + + func openDocumentPicker(presentOn controller: UIViewController, callback: @escaping Callback) { + let documentPickerVC: UIDocumentPickerViewController + if #available(iOS 14.0, *) { + //documentPickerVC = UIDocumentPickerViewController(forOpeningContentTypes: self.types.map { UTTypeReference(importedAs: $0) as UTType }) + + var contentType:[UTType] = [] + + for item in self.types { + let type = UTType.init(item) + if (type != nil) { + contentType.append(type!) + } + } + documentPickerVC = UIDocumentPickerViewController(forOpeningContentTypes:contentType) + + } else { + documentPickerVC = UIDocumentPickerViewController(documentTypes: types, in: .import) + } + documentPickerVC.delegate = self + controller.present(documentPickerVC, animated: true) + self.callback = callback + } + + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { + + + } +} + +class WCHDocumentPicker:DocumentPicker { + + init() { + super.init(documentTypes: ["public.data", "com.pkware.zip-archive"]) + } + + override func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { + + guard url.startAccessingSecurityScopedResource() else { + // Handle the failure here. + return + } + + defer { url.stopAccessingSecurityScopedResource() } + + var error: NSError? = nil + NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (url) in + + let ext = url.pathExtension + + if ext.caseInsensitiveCompare("bin") != .orderedSame && + ext.caseInsensitiveCompare("hex") != .orderedSame + { + callback(.failure(QuickError(message: "Invalid Firmware type please use hex and bin"))) + }else { + + let file = File.init(url: url, size: 0) + callback(.success(file)) + } + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/FileDataSource.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/FileDataSource.swift new file mode 100644 index 0000000..95f8d72 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/FileDataSource.swift @@ -0,0 +1,62 @@ +// +// FileDataSource.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import Foundation +import UIKit.UIImage + +struct FileNodeRepresentation { + var node: FileNode + + var level: Int + var name: String + var collapsed: Bool + var size: Int + var image: UIImage + + var modificationDate: Date? + var sizeInfo: String + var valid: Bool + var isDirectory: Bool +} + +struct FileDataSource { + var items: [FileNodeRepresentation] = [] + var fileExtensionFilter: String? + + mutating func updateItems(_ dir: Directory) { + items = items(dir, level: 0) + } + + func items(_ dir: Directory, level: Int = 0) -> [FileNodeRepresentation] { + dir.nodes.reduce([FileNodeRepresentation]()) { (result, node) in + let valid: Bool + if node is File, let ext = fileExtensionFilter, node.url.pathExtension != ext { + valid = false + } else { + valid = true + } + + var res = result + let image = (node is Directory) + ? ImageWrapper(icon: .folder, imageName: "folderEmpty").image + : UIImage.icon(forFileURL: node.url, preferredSize: .smallest) + + let infoText: String + if let dir = node as? Directory { + infoText = "\(dir.nodes.count) items" + } else { + infoText = ByteCountFormatter().string(fromByteCount: Int64((node as! File).size)) + } + + res.append(FileNodeRepresentation(node: node, level: level, name: node.name, collapsed: false, size: 0, image: image!, modificationDate: node.resourceModificationDate, sizeInfo: infoText, valid: valid, isDirectory: (node is Directory))) + if let dir = node as? Directory { + res.append(contentsOf: self.items(dir, level: level + 1)) + } + return res + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/IntelHexToBinCoverter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/IntelHexToBinCoverter.swift new file mode 100644 index 0000000..fb1c8b7 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/Model/IntelHexToBinCoverter.swift @@ -0,0 +1,161 @@ +// +// IntelHexToBinCoverter.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/13. +// + +import Foundation + +/// This converter converts Intel HEX file to BIN. +/// It is based on this specification: +/// http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf +/// +/// Not all Intel HEX features are supported! +/// The converter does not support gaps in the firmware. The returned +/// BIN contains data until the first found gap. +/// +/// Supported Record Types: +/// * 0x04 - Extended Linear Address Record +/// * 0x02 - Extended Segment Address Record +/// * 0x01 - End of File +/// * 0x00 - Data Record +/// +/// If MBR size is provided, the values from addresses 0.. Data? { + guard hex.count > 0 else { + return nil + } + + var bin = Data() + var offset = 0 + var currentAddress = Int64(0) + + while offset < hex.count { + // Each line must start with ':'. + guard hex[offset] == 0x3A else { + // Not a valid Intel HEX file. + return nil + } + offset += 1 + + // Each line must contain length (2 characters), offset (4 characters) and type (2 characters). + guard hex.count > offset + 8 else { + return nil + } + + let recordLength = Int(readByte(from: hex, at: &offset)) + let recordOffset = readAddress(form: hex, at: &offset) + let recordType = readByte(from: hex, at: &offset) + + // Each line must contain given number bytes (encoded as 2 ASCII characters) and a checksum (2 characters). + guard hex.count >= offset + recordLength * 2 + 2 else { + return nil + } + + switch recordType { + + case 0x04: // Extended Linear Address Record. + let ulba = readAddress(form: hex, at: &offset) << 16 // bits 16-31 + guard bin.count == 0 || ulba == currentAddress else { + // Gaps in addresses are not supported. + return bin + } + currentAddress = Int64(ulba) + // Skip checksum. + offset += 2 + + case 0x02: // Extended Segment Address Record. + let sba = readAddress(form: hex, at: &offset) << 4 // bits 4-19 + guard bin.count == 0 || sba == currentAddress else { + // Gaps in addresses are not supported. + return bin + } + currentAddress = Int64(sba) + // Skip checksum. + offset += 2 + + case 0x01: // End of file. + return bin + + case 0x00: // Data Record. + guard bin.count == 0 || currentAddress == (currentAddress & 0xFFFF0000) + Int64(recordOffset) else { + // A gap detected. + return bin + } + // Add record length if the address is higher than MBR size. + for i in 0..= mbrSize { + bin.append(readByte(from: hex, at: &offset)) + } else { + // Skip MBR byte. + offset += 2 + } + } + currentAddress = (currentAddress & 0xFFFF0000) + Int64(recordOffset + recordLength) + // Skip checksum. + offset += 2 + + default: + // Skip data and checksum. + offset += recordLength * 2 + 2 + } + if hex.count > offset && hex[offset] == 0x0D { offset += 1 } // Skip CR. + if hex.count > offset && hex[offset] == 0x0A { offset += 1 } // Skip LF. + + } + return bin + } + +} + +private extension IntelHexToBinConverter { + + /// Converts the byte written in ASCII to hexadecimal value. + /// + /// - parameter byte: The hex character in ASCII. + /// This must be in range "0-9A-F". + /// - returns: The hexadecimal value of the character. + static func ascii2hex(_ byte: UInt8) -> UInt8 { + if byte >= 0x41 { // 'A' + return byte - 0x37 + } + return byte - 0x30 + } + + /// Reads the full byte from ASCII characters at given offset. + /// + /// - parameter data: The source data. + /// - parameter offset: The offset from which to read the byte. + static func readByte(from data: Data, at offset: inout Int) -> UInt8 { + let first = ascii2hex(data[offset]) + let second = ascii2hex(data[offset + 1]) + offset += 2 + return (first << 4) | second + } + + /// Reads the 16-bit address from given address and returns as UInt32. + /// + /// - parameter data: The source data. + /// - parameter offset: The offset from which to read the address. + static func readAddress(form data: Data, at offset: inout Int) -> Int { + let msb = Int(readByte(from: data, at: &offset)) + let lsb = Int(readByte(from: data, at: &offset)) + return (msb << 8) | lsb + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_ActionTableViewCell.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_ActionTableViewCell.swift new file mode 100644 index 0000000..b0312da --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_ActionTableViewCell.swift @@ -0,0 +1,54 @@ +// +// CH_ActionTableViewCell.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/11. +// + +import UIKit + +class CH_ActionTableViewCell: UITableViewCell { + + + enum Style { + case `default`, destructive + } + + var style: Style = .default { + didSet { + switch style { + case .default: + textLabel?.textColor = UIColor.blue + case .destructive: + textLabel?.textColor = UIColor.red + } + } + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupAppearance() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func awakeFromNib() { + super.awakeFromNib() + setupAppearance() + } + + private func setupAppearance() { + let defaultSize = textLabel?.font.pointSize ?? 12 + textLabel?.font = UIFont.systemFont(ofSize: defaultSize) + + switch style { + case .default: + textLabel?.textColor = .blue + case .destructive: + textLabel?.textColor = .red + } + } + +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.swift new file mode 100644 index 0000000..14fa922 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.swift @@ -0,0 +1,46 @@ +// +// CH_FileTableViewCell.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit + +class CH_FileTableViewCell: UITableViewCell { + + @IBOutlet var nameLabel: UILabel! + @IBOutlet var fileImage: UIImageView! + @IBOutlet var infoLabel: UILabel! + @IBOutlet var dateLabel: UILabel! + @IBOutlet var leadingConstraint: NSLayoutConstraint! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + + func update(_ model: FileNodeRepresentation) { + nameLabel.text = model.name + fileImage.image = model.image + infoLabel.text = model.sizeInfo + + let dafeFormatter = DateFormatter() + dafeFormatter.timeStyle = .none + dafeFormatter.dateStyle = .short + dateLabel.text = model.modificationDate.flatMap { dafeFormatter.string(from: $0) } + + leadingConstraint.constant = CGFloat(model.level * 12) + layoutIfNeeded() + + if model.node is Directory { + selectionStyle = .none + } else { + selectionStyle = .default + } + + fileImage.alpha = model.valid ? 1 : 0.5 + + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.xib new file mode 100644 index 0000000..d6edfc2 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/View/CH_FileTableViewCell.xib @@ -0,0 +1,86 @@ + + + + + + + + + + + + + GTEestiDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.swift new file mode 100644 index 0000000..7040056 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.swift @@ -0,0 +1,258 @@ +// +// CH_FileSelectorViewController.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit +import XappKit +import BLEOTALibrary + +class CH_FileSelectorViewController: MH_VC_BaseViewController, AlertPresenter, UITableViewDataSource, UITableViewDelegate { + + + private let documentPicker: DocumentPicker + + private var documentFileManager = DocumentFileManager() + private (set) var dataSource = FileDataSource() + + + var filterExtension: String? = nil { + didSet { + dataSource.fileExtensionFilter = filterExtension + } + } + + @IBOutlet private var emptyView: UIView! + @IBOutlet private var tableView: UITableView! + @IBOutlet private var selectButton: UIButton! + @IBOutlet private var docImage: UIImageView! + + deinit { + NotificationCenter.default.removeObserver(self) + } + + init(documentPicker: DocumentPicker) { + self.documentPicker = documentPicker + super.init(nibName: "CH_FileSelectorViewController", bundle: .main) + navigationItem.title = "Select Package" + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + _=self.leftBarItem(with: UIImage.init(named: "btn_common_back"), selector: #selector(backAction)); + tableView.register(UINib(nibName: "CH_FileTableViewCell", bundle: .main), forCellReuseIdentifier: "CH_FileTableViewCell") + tableView.register( CH_ActionTableViewCell.self, forCellReuseIdentifier: "CH_ActionTableViewCell") + + + NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: UIApplication.willEnterForegroundNotification, object: nil) + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(reloadData)) + + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + reloadData() + } + + private func reloadItemList() { + do { + let directory = try documentFileManager.buildDocumentDir() + dataSource.updateItems(directory) + } catch let error { + displayErrorAlert(error: error) + return + } + } + + @objc + func reloadData() { + reloadItemList() + + if !dataSource.items.isEmpty { + view = tableView + tableView.reloadData() + tableView.backgroundColor = .white + } else { + view = emptyView + } + } + + func documentWasOpened(document: T) { + let file:File? = document as? File + self.OTAStartUpdate(file: file) + } + + + func fileWasSelected(file: File) { + self.OTAStartUpdate(file: file) + } + + func OTAStartUpdate(file:File?) { + + if (file == nil || file?.url == nil) { + _=self.showFailedMessage("文件不存在"); + } + + let ext = file?.url.pathExtension + let name = file?.url.lastPathComponent + + if ext?.caseInsensitiveCompare("bin") == .orderedSame { + guard let binData = try? Data.init(contentsOf: file!.url) else { + _=self.showFailedMessage("数据格式转换错误"); + return; + } + + let updateVC = CH_UpdateViewController.init(nibName: "CH_UpdateViewController", bundle: .main) + updateVC.fname = name + updateVC.fileData = binData + updateVC.ishex = false; + self.navigationController?.pushViewController(updateVC, animated: true); + + }else if ext?.caseInsensitiveCompare("hex") == .orderedSame { + guard let hexData = try? Data.init(contentsOf: file!.url) else { + _=self.showFailedMessage("数据格式转换错误"); + return; + } + + guard let binData = BLEOTAManager.shareInstance().hex2BinData(hexData) else {return}; + + let updateVC = CH_UpdateViewController.init(nibName: "CH_UpdateViewController", bundle: .main) + updateVC.fname = name + updateVC.fileData = binData + updateVC.ishex = true; + self.navigationController?.pushViewController(updateVC, animated: true); + }else { + _ = self.showFailedMessage("请使用hex或bin格式的文件") + } + + + + } + + + + @IBAction private func openDocumentPicker() { + documentPicker.openDocumentPicker(presentOn: self) { [unowned self] (result) in + switch result { + case .success(let result): + self.documentWasOpened(document: result) + case .failure(let error): + self.displayErrorAlert(error: error) + } + } + } + + func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + section == 0 ? dataSource.items.count : 1 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard indexPath.section == 0 else { + let cell = tableView.dequeueReusableCell(withIdentifier: "CH_ActionTableViewCell") + cell?.textLabel?.text = "Import Another" + return cell ?? UITableViewCell() + } + + let cell = tableView.dequeueReusableCell(withIdentifier: "CH_FileTableViewCell") as? CH_FileTableViewCell + let item = dataSource.items[indexPath.row] + cell?.update(item) + return cell ?? UITableViewCell() + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + indexPath.section == 0 + ? UIDevice.current.userInterfaceIdiom == .pad + ? 80 + : 66 + : 44 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.section == 1 { + openDocumentPicker() + } else if let file = dataSource.items[indexPath.row].node as? File, dataSource.items[indexPath.row].valid { + fileWasSelected(file: file) + } + + tableView.deselectRow(at: indexPath, animated: true) + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + section == 0 ? "Documents Directory" : "" + } + + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + indexPath.section == 0 + } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + guard editingStyle == .delete else { return } + let item = self.dataSource.items[indexPath.row] + + let deleteItem: (FileNode) -> (Error?) = { [weak self] node in + guard let `self` = self else { return QuickError(message: "Unknown Error") } + + do { + try self.documentFileManager.deleteNode(node) + } catch let error { + return error + } + return nil + } + + if let directory = item.node as? Directory { + let alert = UIAlertController(title: "Remove Directory", message: "Do you want to delete entire directory with all nested items?", preferredStyle: .alert) + let delete = UIAlertAction(title: "Delete", style: .destructive, handler: { _ in + self.removeDirectory(directory, rootItem: item, deleteAction: deleteItem) + }) + let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + + alert.addAction(delete) + alert.addAction(cancel) + + self.present(alert, animated: true, completion: nil) + } else { + deleteFile(item.node, deleteAction: deleteItem) + } + + } + + private func removeDirectory(_ dir: Directory, rootItem: FileNodeRepresentation, deleteAction: (FileNode) -> (Error?)) { + let indexPaths = ([rootItem] + dataSource.items(dir)) + .compactMap { item in + self.dataSource.items.firstIndex { item.node.url == $0.node.url } + } + .map { IndexPath(row: $0, section: 0)} + if let error = deleteAction(rootItem.node) { + displayErrorAlert(error: error) + return + } + self.reloadItemList() + tableView.deleteRows(at: indexPaths, with: .automatic) + } + + private func deleteFile(_ item: FileNode, deleteAction: (FileNode) -> (Error?)) { + guard let ip = self.dataSource.items + .firstIndex (where: { item.url == $0.node.url }) + .map ({ IndexPath(row: $0, section: 0) }) else { + return + } + + if let error = deleteAction(item) { + displayErrorAlert(error: error) + return + } + self.reloadItemList() + tableView.deleteRows(at: [ip], with: .automatic) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.xib b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.xib new file mode 100644 index 0000000..a68e908 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/OTAFileSelector/ViewController/CH_FileSelectorViewController.xib @@ -0,0 +1,90 @@ + + + + + + + + + + + + + GTEestiDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/AlertPresenter.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/AlertPresenter.swift new file mode 100644 index 0000000..14030bb --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/AlertPresenter.swift @@ -0,0 +1,31 @@ +// +// AlertPresenter.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit + +protocol AlertPresenter { + func displayErrorAlert(error: Error) +} + +extension AlertPresenter where Self:UIViewController { + func displayErrorAlert(error: Error) { + let msg = (error as? ReadableError)?.readableMessage ?? error.localizedDescription + let alertController = UIAlertController(title: "Error", message: msg, preferredStyle: .alert) + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + alertController.addAction(cancelAction) + present(alertController, animated: true, completion: nil) + } + + func displayOnError(_ expression: @autoclosure () throws -> T) throws -> T { + do { + return try expression() + } catch let error { + displayErrorAlert(error: error) + throw error + } + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ImageWrapper.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ImageWrapper.swift new file mode 100644 index 0000000..cb9418d --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ImageWrapper.swift @@ -0,0 +1,32 @@ +// +// ImageWrapper.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit.UIImage + + +struct ImageWrapper { + var modernIcon: ModernIcon + var legacyIcon: UIImage? + + var image: UIImage? { + if #available(iOS 13, *) { + return modernIcon.image + } else { + return legacyIcon + } + } + + init(icon: ModernIcon, image: UIImage?) { + modernIcon = icon + legacyIcon = image + } + + init(icon: ModernIcon, imageName: String) { + modernIcon = icon + legacyIcon = UIImage(named: imageName) + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ModernIcon.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ModernIcon.swift new file mode 100644 index 0000000..ccb0d18 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/ModernIcon.swift @@ -0,0 +1,71 @@ +// +// ModernIcon.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import UIKit.UIImage + +struct ModernIcon: Codable, Equatable { + private (set) var name: String + init(name: String) { + self.name = name + } + + init(digit: Int) { + name = "\(digit)" + } + + func add(_ icon: ModernIcon) -> ModernIcon { + return ModernIcon(name: "\(name).\(icon.name)") + } + + func callAsFunction(_ icon: ModernIcon) -> ModernIcon { + return ModernIcon(name: "\(name).\(icon.name)") + } + + @available(iOS 13.0, *) + var image: UIImage? { + return UIImage(systemName: name) + } +} + +extension ModernIcon { + static let circle = ModernIcon(name: "circle") + static let fill = ModernIcon(name: "fill") + static let end = ModernIcon(name: "end") + static let alt = ModernIcon(name: "alt") + static let grid = ModernIcon(name: "grid") + static let threeXthree = ModernIcon(name: "3x3") + static let trash = ModernIcon(name: "trash") + static let bolt = ModernIcon(name: "bolt") + static let list = ModernIcon(name: "list") + static let dash = ModernIcon(name: "dash") + + static let play = ModernIcon(name: "play") + static let pause = ModernIcon(name: "pause") + static let stop = ModernIcon(name: "stop") + static let backward = ModernIcon(name: "backward") + static let forward = ModernIcon(name: "forward") + static let `repeat` = ModernIcon(name: "repeat") + static let chevron = ModernIcon(name: "chevron") + static let record = ModernIcon(name: "recordingtape") + + static let up = ModernIcon(name: "up") + static let down = ModernIcon(name: "down") + static let left = ModernIcon(name: "left") + static let right = ModernIcon(name: "right") + + static let checkmark = ModernIcon(name: "checkmark") + static let line = ModernIcon(name: "line") + static let horizontal = ModernIcon(name: "horizontal") + static let decrease = ModernIcon(name: "decrease") + static let circlePath = ModernIcon(name: "circlepath") + static let arrow = ModernIcon(name: "arrow") + + static let exclamationmark = ModernIcon(name: "exclamationmark") + static let triangle = ModernIcon(name: "triangle") + + static let folder = ModernIcon(name: "folder") +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/QuickError.swift b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/QuickError.swift new file mode 100644 index 0000000..466f4be --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/Utilities/QuickError.swift @@ -0,0 +1,27 @@ +// +// QuickError.swift +// WCHBLEOTA +// +// Created by moyun on 2022/4/8. +// + +import Foundation + +protocol ReadableError: Error { + var title: String { get } + var readableMessage: String { get } +} + +extension ReadableError { + var title: String { + return "Error" + } +} + +struct QuickError: ReadableError { + let readableMessage: String + + init(message: String) { + readableMessage = message + } +} diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit-Swift.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit-Swift.h new file mode 100644 index 0000000..6327c22 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit-Swift.h @@ -0,0 +1,429 @@ +// Generated by Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6) +#ifndef XAPPKIT_SWIFT_H +#define XAPPKIT_SWIFT_H +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#include +#include +#include +#include + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif + +#if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +#else +# define SWIFT_RUNTIME_NAME(X) +#endif +#if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +#else +# define SWIFT_COMPILE_NAME(X) +#endif +#if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +#else +# define SWIFT_METHOD_FAMILY(X) +#endif +#if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +#else +# define SWIFT_NOESCAPE +#endif +#if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +#else +# define SWIFT_RELEASES_ARGUMENT +#endif +#if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define SWIFT_WARN_UNUSED_RESULT +#endif +#if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +#else +# define SWIFT_NORETURN +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif + +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif + +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif + +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if defined(__has_attribute) && __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +#else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +#endif +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#if __has_feature(modules) +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +@import CoreGraphics; +@import Foundation; +@import ObjectiveC; +@import UIKit; +@import WebKit; +#endif + +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="XappKit",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + + +@class NSCoder; + +SWIFT_CLASS("_TtC7XappKit20MHCircleProgressView") +@interface MHCircleProgressView : UIView +- (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)drawRect:(CGRect)rect; +@end + +@class UIColor; + +SWIFT_CLASS("_TtC7XappKit12MHShadowView") +@interface MHShadowView : UIView +@property (nonatomic, strong) UIColor * _Nullable backgroundColor; +- (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)layoutSubviews; +@end + +@class NSTextContainer; +@class NSString; +@class NSAttributedString; +@class UIFont; +@class UITouch; +@class UIEvent; + +SWIFT_CLASS("_TtC7XappKit10MHTextView") +@interface MHTextView : UITextView +- (nonnull instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer * _Nullable)textContainer OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)drawRect:(CGRect)rect; +@property (nonatomic, copy) NSString * _Null_unspecified text; +- (void)insertText:(NSString * _Nonnull)text; +@property (nonatomic, strong) NSAttributedString * _Null_unspecified attributedText; +@property (nonatomic) UIEdgeInsets contentInset; +@property (nonatomic, strong) UIFont * _Nullable font; +@property (nonatomic) NSTextAlignment textAlignment; +- (void)touchesBegan:(NSSet * _Nonnull)touches withEvent:(UIEvent * _Nullable)event; +- (void)touchesEnded:(NSSet * _Nonnull)touches withEvent:(UIEvent * _Nullable)event; +@end + +@class NSBundle; +@class NSNumber; + +SWIFT_CLASS("_TtC7XappKit24MH_VC_BaseViewController") +@interface MH_VC_BaseViewController : UIViewController +- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)viewDidLoad; +- (void)viewWillAppear:(BOOL)animated; +- (void)viewWillDisappear:(BOOL)animated; +- (void)backAction; +- (void)didReceiveMemoryWarning; +@end + +@class WKWebView; +@class WKNavigationAction; +@class WKNavigation; + +SWIFT_CLASS("_TtC7XappKit19MH_VC_WebController") +@interface MH_VC_WebController : MH_VC_BaseViewController +- (void)viewDidLoad; +- (void)viewDidAppear:(BOOL)animated; +- (void)backAction; +- (void)moreAction; +- (void)observeValueForKeyPath:(NSString * _Nullable)keyPath ofObject:(id _Nullable)object change:(NSDictionary * _Nullable)change context:(void * _Nullable)context; +- (void)webView:(WKWebView * _Nonnull)webView decidePolicyForNavigationAction:(WKNavigationAction * _Nonnull)navigationAction decisionHandler:(void (^ _Nonnull)(WKNavigationActionPolicy))decisionHandler; +- (void)webView:(WKWebView * _Nonnull)webView didStartProvisionalNavigation:(WKNavigation * _Null_unspecified)navigation; +- (void)webView:(WKWebView * _Nonnull)webView didFinishNavigation:(WKNavigation * _Null_unspecified)navigation; +- (void)webView:(WKWebView * _Nonnull)webView didFailNavigation:(WKNavigation * _Null_unspecified)navigation withError:(NSError * _Nonnull)error; +- (void)didReceiveMemoryWarning; +- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC7XappKit18MH_V_EmptyDataView") +@interface MH_V_EmptyDataView : UIView +- (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class UICollectionViewLayout; + +SWIFT_CLASS("_TtC7XappKit26MH_V_RefreshCollectionView") +@interface MH_V_RefreshCollectionView : UICollectionView +- (void)awakeFromNib; +- (nonnull instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout * _Nonnull)layout OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC7XappKit22MH_V_RefreshScrollView") +@interface MH_V_RefreshScrollView : UIScrollView +- (void)awakeFromNib; +- (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC7XappKit21MH_V_RefreshTableView") +@interface MH_V_RefreshTableView : UITableView +- (void)awakeFromNib; +- (nonnull instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + + + +SWIFT_CLASS("_TtC7XappKit9PopupMenu") +@interface PopupMenu : UIView +@property (nonatomic) CGRect frame; +- (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +- (void)drawRect:(CGRect)rect; +@end + + +@interface PopupMenu (SWIFT_EXTENSION(XappKit)) +- (void)scrollViewWillBeginDragging:(UIScrollView * _Nonnull)scrollView; +- (void)scrollViewDidEndDecelerating:(UIScrollView * _Nonnull)scrollView; +@end + +@class NSIndexPath; +@class UITableViewCell; + +@interface PopupMenu (SWIFT_EXTENSION(XappKit)) +- (NSInteger)tableView:(UITableView * _Nonnull)tableView numberOfRowsInSection:(NSInteger)section SWIFT_WARN_UNUSED_RESULT; +- (UITableViewCell * _Nonnull)tableView:(UITableView * _Nonnull)tableView cellForRowAtIndexPath:(NSIndexPath * _Nonnull)indexPath SWIFT_WARN_UNUSED_RESULT; +- (void)tableView:(UITableView * _Nonnull)tableView didSelectRowAtIndexPath:(NSIndexPath * _Nonnull)indexPath; +@end + + +SWIFT_PROTOCOL("_TtP7XappKit17PopupMenuDelegate_") +@protocol PopupMenuDelegate +/// block回调时 非可选 +- (void)popupMenuDidSelectedWithIndex:(NSInteger)index popupMenu:(PopupMenu * _Nonnull)popupMenu; +@optional +- (void)popupMenuBeganDismiss; +- (void)popupMenuDidDismiss; +- (void)popupMenuBeganShow; +- (void)popupMenudidShow; +@end + + + + + + + + + + + + + + + + + + +@protocol UINavigationControllerDelegate; + +SWIFT_CLASS("_TtC7XappKit22XAPP_BaseNavController") +@interface XAPP_BaseNavController : UINavigationController +@property (nonatomic, strong) id _Nullable delegate; +- (void)viewDidLoad; +- (nonnull instancetype)initWithNavigationBarClass:(Class _Nullable)navigationBarClass toolbarClass:(Class _Nullable)toolbarClass OBJC_DESIGNATED_INITIALIZER SWIFT_AVAILABILITY(ios,introduced=5.0); +- (nonnull instancetype)initWithRootViewController:(UIViewController * _Nonnull)rootViewController OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +@end + +@class UIGestureRecognizer; +@class UIPress; + +@interface XAPP_BaseNavController (SWIFT_EXTENSION(XappKit)) +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer * _Nonnull)gestureRecognizer SWIFT_WARN_UNUSED_RESULT; +- (BOOL)gestureRecognizer:(UIGestureRecognizer * _Nonnull)gestureRecognizer shouldReceiveTouch:(UITouch * _Nonnull)touch SWIFT_WARN_UNUSED_RESULT; +- (BOOL)gestureRecognizer:(UIGestureRecognizer * _Nonnull)gestureRecognizer shouldReceivePress:(UIPress * _Nonnull)press SWIFT_WARN_UNUSED_RESULT; +@end + +@protocol UIViewControllerAnimatedTransitioning; +@protocol UIViewControllerInteractiveTransitioning; + +@interface XAPP_BaseNavController (SWIFT_EXTENSION(XappKit)) +- (void)pushViewController:(UIViewController * _Nonnull)viewController animated:(BOOL)animated; +- (void)navigationController:(UINavigationController * _Nonnull)navigationController didShowViewController:(UIViewController * _Nonnull)viewController animated:(BOOL)animated; +- (void)navigationController:(UINavigationController * _Nonnull)navigationController willShowViewController:(UIViewController * _Nonnull)viewController animated:(BOOL)animated; +- (UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController * _Nonnull)navigationController SWIFT_WARN_UNUSED_RESULT; +- (UIInterfaceOrientation)navigationControllerPreferredInterfaceOrientationForPresentation:(UINavigationController * _Nonnull)navigationController SWIFT_WARN_UNUSED_RESULT; +- (id _Nullable)navigationController:(UINavigationController * _Nonnull)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController * _Nonnull)fromVC toViewController:(UIViewController * _Nonnull)toVC SWIFT_WARN_UNUSED_RESULT; +- (id _Nullable)navigationController:(UINavigationController * _Nonnull)navigationController interactionControllerForAnimationController:(id _Nonnull)animationController SWIFT_WARN_UNUSED_RESULT; +@end + + +SWIFT_CLASS("_TtC7XappKit14XTableViewCell") +@interface XTableViewCell : UITableViewCell +- (void)awakeFromNib; +- (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString * _Nullable)reuseIdentifier OBJC_DESIGNATED_INITIALIZER SWIFT_AVAILABILITY(ios,introduced=3.0); +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder OBJC_DESIGNATED_INITIALIZER; +@end + + +SWIFT_CLASS("_TtC7XappKit5XView") +@interface XView : UIView +- (void)awakeFromNib; +- (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder OBJC_DESIGNATED_INITIALIZER; +@end + +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#pragma clang diagnostic pop +#endif diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit.h b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit.h new file mode 100644 index 0000000..a4133b4 --- /dev/null +++ b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Headers/XappKit.h @@ -0,0 +1,19 @@ +// +// XappKit.h +// XappKit +// +// Created by jiangjing on 4/26/18. +// Copyright © 2018 imohoo.com. All rights reserved. +// + +#import + +//! Project version number for XappKit. +FOUNDATION_EXPORT double XappKitVersionNumber; + +//! Project version string for XappKit. +FOUNDATION_EXPORT const unsigned char XappKitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Info.plist b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Info.plist new file mode 100644 index 0000000..2d55dc6 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Info.plist differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo new file mode 100644 index 0000000..74ab24d Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64.swiftsourceinfo b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64.swiftsourceinfo new file mode 100644 index 0000000..74ab24d Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/Project/arm64.swiftsourceinfo differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftdoc b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftdoc new file mode 100644 index 0000000..d665730 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftdoc differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftmodule b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftmodule new file mode 100644 index 0000000..3674e4f Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64-apple-ios.swiftmodule differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftdoc b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftdoc new file mode 100644 index 0000000..d665730 Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftdoc differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftmodule b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftmodule new file mode 100644 index 0000000..3674e4f Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/Modules/XappKit.swiftmodule/arm64.swiftmodule differ diff --git a/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/XappKit b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/XappKit new file mode 100644 index 0000000..ded7e2e Binary files /dev/null and b/Tool/OTA_Tool/BLE_OTA_iOS/WCHBLEOTA/WCHBLEOTA/XappKit.framework/XappKit differ diff --git "a/Tool/OTA_Tool/BLE_OTA_iOS/iOS BLEOTA\345\272\224\347\224\250\350\275\257\344\273\266\344\275\277\347\224\250\350\257\264\346\230\216.pdf" "b/Tool/OTA_Tool/BLE_OTA_iOS/iOS BLEOTA\345\272\224\347\224\250\350\275\257\344\273\266\344\275\277\347\224\250\350\257\264\346\230\216.pdf" new file mode 100644 index 0000000..8da079a Binary files /dev/null and "b/Tool/OTA_Tool/BLE_OTA_iOS/iOS BLEOTA\345\272\224\347\224\250\350\275\257\344\273\266\344\275\277\347\224\250\350\257\264\346\230\216.pdf" differ diff --git "a/Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.PDF" "b/Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.PDF" new file mode 100644 index 0000000..d7a7b08 Binary files /dev/null and "b/Tool/WCH\350\223\235\347\211\231\347\251\272\344\270\255\345\215\207\347\272\247\357\274\210BLE OTA\357\274\211.PDF" differ