From: liangzhenying <867174124@qq.com> Date: Thu, 13 Jun 2024 11:39:11 +0000 (+0800) Subject: init X-Git-Tag: deepseek~33 X-Git-Url: http://git.snicker.com.cn/sitemap.xml?a=commitdiff_plain;h=5b6ea59c7d282a9f329e6aa6367e69a56522eb9c;p=mirrors%2FMixSdk-iOS.git init --- 5b6ea59c7d282a9f329e6aa6367e69a56522eb9c diff --git a/MixSdk/Example/Example.xcodeproj/project.pbxproj b/MixSdk/Example/Example.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e382633 --- /dev/null +++ b/MixSdk/Example/Example.xcodeproj/project.pbxproj @@ -0,0 +1,416 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 18204BD42C193F9A00F94E69 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BD32C193F9A00F94E69 /* AppDelegate.swift */; }; + 18204BD62C193F9A00F94E69 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BD52C193F9A00F94E69 /* SceneDelegate.swift */; }; + 18204BD82C193F9A00F94E69 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BD72C193F9A00F94E69 /* ViewController.swift */; }; + 18204BDB2C193F9A00F94E69 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18204BD92C193F9A00F94E69 /* Main.storyboard */; }; + 18204BDD2C193F9D00F94E69 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18204BDC2C193F9D00F94E69 /* Assets.xcassets */; }; + 18204BE02C193F9D00F94E69 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18204BDE2C193F9D00F94E69 /* LaunchScreen.storyboard */; }; + 18204BEE2C19428100F94E69 /* MixSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18204BEC2C19417000F94E69 /* MixSdk.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 18204BEB2C19417000F94E69 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18204BE72C19417000F94E69 /* MixSdk.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 18204BBB2C193E3D00F94E69; + remoteInfo = MixSdk; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 18204BD02C193F9A00F94E69 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 18204BD32C193F9A00F94E69 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 18204BD52C193F9A00F94E69 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 18204BD72C193F9A00F94E69 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 18204BDA2C193F9A00F94E69 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 18204BDC2C193F9D00F94E69 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 18204BDF2C193F9D00F94E69 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 18204BE12C193F9D00F94E69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 18204BE72C19417000F94E69 /* MixSdk.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MixSdk.xcodeproj; path = ../MixSdk/MixSdk.xcodeproj; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 18204BCD2C193F9A00F94E69 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 18204BEE2C19428100F94E69 /* MixSdk.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18204BC72C193F9A00F94E69 = { + isa = PBXGroup; + children = ( + 18204BE72C19417000F94E69 /* MixSdk.xcodeproj */, + 18204BD22C193F9A00F94E69 /* Example */, + 18204BD12C193F9A00F94E69 /* Products */, + 18204BED2C19428100F94E69 /* Frameworks */, + ); + sourceTree = ""; + }; + 18204BD12C193F9A00F94E69 /* Products */ = { + isa = PBXGroup; + children = ( + 18204BD02C193F9A00F94E69 /* Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 18204BD22C193F9A00F94E69 /* Example */ = { + isa = PBXGroup; + children = ( + 18204BD32C193F9A00F94E69 /* AppDelegate.swift */, + 18204BD52C193F9A00F94E69 /* SceneDelegate.swift */, + 18204BD72C193F9A00F94E69 /* ViewController.swift */, + 18204BD92C193F9A00F94E69 /* Main.storyboard */, + 18204BDC2C193F9D00F94E69 /* Assets.xcassets */, + 18204BDE2C193F9D00F94E69 /* LaunchScreen.storyboard */, + 18204BE12C193F9D00F94E69 /* Info.plist */, + ); + path = Example; + sourceTree = ""; + }; + 18204BE82C19417000F94E69 /* Products */ = { + isa = PBXGroup; + children = ( + 18204BEC2C19417000F94E69 /* MixSdk.framework */, + ); + name = Products; + sourceTree = ""; + }; + 18204BED2C19428100F94E69 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 18204BCF2C193F9A00F94E69 /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18204BE42C193F9D00F94E69 /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + 18204BCC2C193F9A00F94E69 /* Sources */, + 18204BCD2C193F9A00F94E69 /* Frameworks */, + 18204BCE2C193F9A00F94E69 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Example; + productName = Example; + productReference = 18204BD02C193F9A00F94E69 /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 18204BC82C193F9A00F94E69 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 18204BCF2C193F9A00F94E69 = { + CreatedOnToolsVersion = 15.0.1; + }; + }; + }; + buildConfigurationList = 18204BCB2C193F9A00F94E69 /* Build configuration list for PBXProject "Example" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 18204BC72C193F9A00F94E69; + productRefGroup = 18204BD12C193F9A00F94E69 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 18204BE82C19417000F94E69 /* Products */; + ProjectRef = 18204BE72C19417000F94E69 /* MixSdk.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 18204BCF2C193F9A00F94E69 /* Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 18204BEC2C19417000F94E69 /* MixSdk.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = MixSdk.framework; + remoteRef = 18204BEB2C19417000F94E69 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 18204BCE2C193F9A00F94E69 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18204BE02C193F9D00F94E69 /* LaunchScreen.storyboard in Resources */, + 18204BDD2C193F9D00F94E69 /* Assets.xcassets in Resources */, + 18204BDB2C193F9A00F94E69 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 18204BCC2C193F9A00F94E69 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18204BD82C193F9A00F94E69 /* ViewController.swift in Sources */, + 18204BD42C193F9A00F94E69 /* AppDelegate.swift in Sources */, + 18204BD62C193F9A00F94E69 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 18204BD92C193F9A00F94E69 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 18204BDA2C193F9A00F94E69 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 18204BDE2C193F9D00F94E69 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 18204BDF2C193F9D00F94E69 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 18204BE22C193F9D00F94E69 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 18204BE32C193F9D00F94E69 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 18204BE52C193F9D00F94E69 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = M33X987285; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Example/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ZhiHui.Example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 18204BE62C193F9D00F94E69 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = M33X987285; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Example/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = ZhiHui.Example; + 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 */ + 18204BCB2C193F9A00F94E69 /* Build configuration list for PBXProject "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18204BE22C193F9D00F94E69 /* Debug */, + 18204BE32C193F9D00F94E69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18204BE42C193F9D00F94E69 /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18204BE52C193F9D00F94E69 /* Debug */, + 18204BE62C193F9D00F94E69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 18204BC82C193F9A00F94E69 /* Project object */; +} diff --git a/MixSdk/Example/Example.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist b/MixSdk/Example/Example.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c1cbfb0 --- /dev/null +++ b/MixSdk/Example/Example.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Example.xcscheme_^#shared#^_ + + orderHint + 1 + + + + diff --git a/MixSdk/Example/Example/AppDelegate.swift b/MixSdk/Example/Example/AppDelegate.swift new file mode 100644 index 0000000..4c7d99f --- /dev/null +++ b/MixSdk/Example/Example/AppDelegate.swift @@ -0,0 +1,38 @@ +// +// AppDelegate.swift +// Example +// +// Created by incar on 2024/6/12. +// + +import UIKit +import MixSdk +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + MSManager.shared.initSDK() + MSManager.shared.isDebug = true + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/MixSdk/Example/Example/Assets.xcassets/AccentColor.colorset/Contents.json b/MixSdk/Example/Example/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/MixSdk/Example/Example/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MixSdk/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/MixSdk/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/MixSdk/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MixSdk/Example/Example/Assets.xcassets/Contents.json b/MixSdk/Example/Example/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/MixSdk/Example/Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MixSdk/Example/Example/Base.lproj/LaunchScreen.storyboard b/MixSdk/Example/Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/MixSdk/Example/Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MixSdk/Example/Example/Base.lproj/Main.storyboard b/MixSdk/Example/Example/Base.lproj/Main.storyboard new file mode 100644 index 0000000..497e2a4 --- /dev/null +++ b/MixSdk/Example/Example/Base.lproj/Main.storyboard @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MixSdk/Example/Example/Info.plist b/MixSdk/Example/Example/Info.plist new file mode 100644 index 0000000..735e27a --- /dev/null +++ b/MixSdk/Example/Example/Info.plist @@ -0,0 +1,30 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + diff --git a/MixSdk/Example/Example/SceneDelegate.swift b/MixSdk/Example/Example/SceneDelegate.swift new file mode 100644 index 0000000..e6404e0 --- /dev/null +++ b/MixSdk/Example/Example/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// Example +// +// Created by incar on 2024/6/12. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/MixSdk/Example/Example/ViewController.swift b/MixSdk/Example/Example/ViewController.swift new file mode 100644 index 0000000..be71f45 --- /dev/null +++ b/MixSdk/Example/Example/ViewController.swift @@ -0,0 +1,68 @@ +// +// ViewController.swift +// Example +// +// Created by incar on 2024/6/12. +// + +import UIKit +import MixSdk + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + + } + + @IBAction func registerAction(_ sender: Any) { + let sn = "MSCL1BKZ12105000042363" + let deviceId = "C0310000A57B" + let productKey = "ccvUoJOLbXn" + let secretKey = "nNRjkRpKTxvprGaW" + MSManager.shared.auth.register(productKey: productKey, secretKey: secretKey, deviceId: deviceId,sn:sn){ deviceSecret,error in + if let err = error{ + print("\(err)") + } + else{ + print(deviceSecret ?? "") + } + } + } + @IBAction func loginAction(_ sender: Any) { + let deviceId = "C0310000A57B" + let productKey = "ccvUoJOLbXn" + let secretKey = "nNRjkRpKTxvprGaW" + let deviceSecret = "ZqqFHYeXf4xuv5jEfuHUE2hdMnoaegGi" + MSManager.shared.auth.login(productKey: productKey, secretKey: secretKey, deviceId: deviceId, deviceSecrect: deviceSecret){ isSuccess,error in + if let err = error{ + print("\(err)") + } + else{ + print("Login Success") + } + } + } + @IBAction func tranlateAction(_ sender: Any) { + MSManager.shared.translate.translate(lang: "zh", text: "Translate General"){text,error in + if let err = error{ + print("\(err)") + } + else{ + print(text ?? "") + } + } + } + @IBAction func getSupportLanguagesAction(_ sender: Any) { + MSManager.shared.translate.getSupportLanguages { list, error in + if let err = error{ + print("\(err)") + } + else{ + print(list ?? "") + } + } + } +} + diff --git a/MixSdk/MixSdk.xcworkspace/contents.xcworkspacedata b/MixSdk/MixSdk.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b30795b --- /dev/null +++ b/MixSdk/MixSdk.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/MixSdk/MixSdk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MixSdk/MixSdk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MixSdk/MixSdk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate b/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..b4fd6a7 Binary files /dev/null and b/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..56e205c --- /dev/null +++ b/MixSdk/MixSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/project.pbxproj b/MixSdk/MixSdk/MixSdk.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0ff107c --- /dev/null +++ b/MixSdk/MixSdk/MixSdk.xcodeproj/project.pbxproj @@ -0,0 +1,449 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 1811882F2C1A89E600C23FAB /* MSManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1811882E2C1A89E600C23FAB /* MSManager.swift */; }; + 181188392C1A8B5200C23FAB /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188312C1A8B5200C23FAB /* Date.swift */; }; + 1811883A2C1A8B5200C23FAB /* Any.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188322C1A8B5200C23FAB /* Any.swift */; }; + 1811883B2C1A8B5200C23FAB /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188332C1A8B5200C23FAB /* Logger.swift */; }; + 1811883C2C1A8B5200C23FAB /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188342C1A8B5200C23FAB /* JSON.swift */; }; + 1811883E2C1A8B5200C23FAB /* UTF8.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188362C1A8B5200C23FAB /* UTF8.swift */; }; + 1811883F2C1A8B5200C23FAB /* CRC16.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188372C1A8B5200C23FAB /* CRC16.swift */; }; + 181188402C1A8B5200C23FAB /* LRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188382C1A8B5200C23FAB /* LRC.swift */; }; + 181188452C1AC35F00C23FAB /* MSError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188442C1AC35F00C23FAB /* MSError.swift */; }; + 181188472C1ACA6100C23FAB /* String+MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181188462C1ACA6100C23FAB /* String+MD5.swift */; }; + 1811884E2C1AEF0F00C23FAB /* MSTranslate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1811884D2C1AEF0F00C23FAB /* MSTranslate.swift */; }; + 18204BBF2C193E3D00F94E69 /* MixSdk.h in Headers */ = {isa = PBXBuildFile; fileRef = 18204BBE2C193E3D00F94E69 /* MixSdk.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18204BC62C193E4B00F94E69 /* MSAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BC52C193E4B00F94E69 /* MSAuth.swift */; }; + 18204BF02C19457600F94E69 /* IBHttpManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BEF2C19457600F94E69 /* IBHttpManager.swift */; }; + 18204BF82C19488800F94E69 /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BF22C19488800F94E69 /* StatusCode.swift */; }; + 18204BF92C19488900F94E69 /* SwiftHTTP.h in Headers */ = {isa = PBXBuildFile; fileRef = 18204BF32C19488800F94E69 /* SwiftHTTP.h */; }; + 18204BFA2C19488900F94E69 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BF42C19488800F94E69 /* Request.swift */; }; + 18204BFB2C19488900F94E69 /* Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BF52C19488800F94E69 /* Upload.swift */; }; + 18204BFC2C19488900F94E69 /* HTTPSecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BF62C19488800F94E69 /* HTTPSecurity.swift */; }; + 18204BFD2C19488900F94E69 /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18204BF72C19488800F94E69 /* Operation.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1811882E2C1A89E600C23FAB /* MSManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSManager.swift; sourceTree = ""; }; + 181188312C1A8B5200C23FAB /* Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = ""; }; + 181188322C1A8B5200C23FAB /* Any.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Any.swift; sourceTree = ""; }; + 181188332C1A8B5200C23FAB /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; + 181188342C1A8B5200C23FAB /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; + 181188362C1A8B5200C23FAB /* UTF8.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UTF8.swift; sourceTree = ""; }; + 181188372C1A8B5200C23FAB /* CRC16.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CRC16.swift; sourceTree = ""; }; + 181188382C1A8B5200C23FAB /* LRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LRC.swift; sourceTree = ""; }; + 181188442C1AC35F00C23FAB /* MSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSError.swift; sourceTree = ""; }; + 181188462C1ACA6100C23FAB /* String+MD5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+MD5.swift"; sourceTree = ""; }; + 1811884D2C1AEF0F00C23FAB /* MSTranslate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTranslate.swift; sourceTree = ""; }; + 18204BBB2C193E3D00F94E69 /* MixSdk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MixSdk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 18204BBE2C193E3D00F94E69 /* MixSdk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MixSdk.h; sourceTree = ""; }; + 18204BC52C193E4B00F94E69 /* MSAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSAuth.swift; sourceTree = ""; }; + 18204BEF2C19457600F94E69 /* IBHttpManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IBHttpManager.swift; sourceTree = ""; }; + 18204BF22C19488800F94E69 /* StatusCode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; + 18204BF32C19488800F94E69 /* SwiftHTTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwiftHTTP.h; sourceTree = ""; }; + 18204BF42C19488800F94E69 /* Request.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + 18204BF52C19488800F94E69 /* Upload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Upload.swift; sourceTree = ""; }; + 18204BF62C19488800F94E69 /* HTTPSecurity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPSecurity.swift; sourceTree = ""; }; + 18204BF72C19488800F94E69 /* Operation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operation.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 18204BB82C193E3D00F94E69 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 181188302C1A8B5200C23FAB /* Tools */ = { + isa = PBXGroup; + children = ( + 181188312C1A8B5200C23FAB /* Date.swift */, + 181188322C1A8B5200C23FAB /* Any.swift */, + 181188332C1A8B5200C23FAB /* Logger.swift */, + 181188342C1A8B5200C23FAB /* JSON.swift */, + 181188362C1A8B5200C23FAB /* UTF8.swift */, + 181188372C1A8B5200C23FAB /* CRC16.swift */, + 181188382C1A8B5200C23FAB /* LRC.swift */, + 181188462C1ACA6100C23FAB /* String+MD5.swift */, + ); + path = Tools; + sourceTree = ""; + }; + 18204BB12C193E3D00F94E69 = { + isa = PBXGroup; + children = ( + 18204BBD2C193E3D00F94E69 /* MixSdk */, + 18204BBC2C193E3D00F94E69 /* Products */, + ); + sourceTree = ""; + }; + 18204BBC2C193E3D00F94E69 /* Products */ = { + isa = PBXGroup; + children = ( + 18204BBB2C193E3D00F94E69 /* MixSdk.framework */, + ); + name = Products; + sourceTree = ""; + }; + 18204BBD2C193E3D00F94E69 /* MixSdk */ = { + isa = PBXGroup; + children = ( + 181188302C1A8B5200C23FAB /* Tools */, + 18204BF12C19488800F94E69 /* SwiftHTTP */, + 18204BBE2C193E3D00F94E69 /* MixSdk.h */, + 18204BEF2C19457600F94E69 /* IBHttpManager.swift */, + 1811882E2C1A89E600C23FAB /* MSManager.swift */, + 18204BC52C193E4B00F94E69 /* MSAuth.swift */, + 1811884D2C1AEF0F00C23FAB /* MSTranslate.swift */, + 181188442C1AC35F00C23FAB /* MSError.swift */, + ); + path = MixSdk; + sourceTree = ""; + }; + 18204BF12C19488800F94E69 /* SwiftHTTP */ = { + isa = PBXGroup; + children = ( + 18204BF22C19488800F94E69 /* StatusCode.swift */, + 18204BF32C19488800F94E69 /* SwiftHTTP.h */, + 18204BF42C19488800F94E69 /* Request.swift */, + 18204BF52C19488800F94E69 /* Upload.swift */, + 18204BF62C19488800F94E69 /* HTTPSecurity.swift */, + 18204BF72C19488800F94E69 /* Operation.swift */, + ); + path = SwiftHTTP; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 18204BB62C193E3D00F94E69 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 18204BF92C19488900F94E69 /* SwiftHTTP.h in Headers */, + 18204BBF2C193E3D00F94E69 /* MixSdk.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 18204BBA2C193E3D00F94E69 /* MixSdk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 18204BC22C193E3D00F94E69 /* Build configuration list for PBXNativeTarget "MixSdk" */; + buildPhases = ( + 18204BB62C193E3D00F94E69 /* Headers */, + 18204BB72C193E3D00F94E69 /* Sources */, + 18204BB82C193E3D00F94E69 /* Frameworks */, + 18204BB92C193E3D00F94E69 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MixSdk; + productName = MixSdk; + productReference = 18204BBB2C193E3D00F94E69 /* MixSdk.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 18204BB22C193E3D00F94E69 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1500; + TargetAttributes = { + 18204BBA2C193E3D00F94E69 = { + CreatedOnToolsVersion = 15.0.1; + LastSwiftMigration = 1500; + }; + }; + }; + buildConfigurationList = 18204BB52C193E3D00F94E69 /* Build configuration list for PBXProject "MixSdk" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 18204BB12C193E3D00F94E69; + productRefGroup = 18204BB12C193E3D00F94E69; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 18204BBA2C193E3D00F94E69 /* MixSdk */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 18204BB92C193E3D00F94E69 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 18204BB72C193E3D00F94E69 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 18204BC62C193E4B00F94E69 /* MSAuth.swift in Sources */, + 181188472C1ACA6100C23FAB /* String+MD5.swift in Sources */, + 1811883F2C1A8B5200C23FAB /* CRC16.swift in Sources */, + 181188452C1AC35F00C23FAB /* MSError.swift in Sources */, + 1811883B2C1A8B5200C23FAB /* Logger.swift in Sources */, + 18204BFD2C19488900F94E69 /* Operation.swift in Sources */, + 1811883C2C1A8B5200C23FAB /* JSON.swift in Sources */, + 181188402C1A8B5200C23FAB /* LRC.swift in Sources */, + 18204BFC2C19488900F94E69 /* HTTPSecurity.swift in Sources */, + 18204BFB2C19488900F94E69 /* Upload.swift in Sources */, + 18204BFA2C19488900F94E69 /* Request.swift in Sources */, + 1811882F2C1A89E600C23FAB /* MSManager.swift in Sources */, + 18204BF02C19457600F94E69 /* IBHttpManager.swift in Sources */, + 181188392C1A8B5200C23FAB /* Date.swift in Sources */, + 1811883A2C1A8B5200C23FAB /* Any.swift in Sources */, + 1811883E2C1A8B5200C23FAB /* UTF8.swift in Sources */, + 1811884E2C1AEF0F00C23FAB /* MSTranslate.swift in Sources */, + 18204BF82C19488800F94E69 /* StatusCode.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 18204BC02C193E3D00F94E69 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 18204BC12C193E3D00F94E69 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 18204BC32C193E3D00F94E69 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = M33X987285; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + 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; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = ZhiHui.MixSdk; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 18204BC42C193E3D00F94E69 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = M33X987285; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + 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; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = ZhiHui.MixSdk; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 18204BB52C193E3D00F94E69 /* Build configuration list for PBXProject "MixSdk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18204BC02C193E3D00F94E69 /* Debug */, + 18204BC12C193E3D00F94E69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 18204BC22C193E3D00F94E69 /* Build configuration list for PBXNativeTarget "MixSdk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 18204BC32C193E3D00F94E69 /* Debug */, + 18204BC42C193E3D00F94E69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 18204BB22C193E3D00F94E69 /* Project object */; +} diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..88f2403 Binary files /dev/null and b/MixSdk/MixSdk/MixSdk.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/xcshareddata/xcschemes/MixSdk.xcscheme b/MixSdk/MixSdk/MixSdk.xcodeproj/xcshareddata/xcschemes/MixSdk.xcscheme new file mode 100644 index 0000000..362dcb3 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk.xcodeproj/xcshareddata/xcschemes/MixSdk.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MixSdk/MixSdk/MixSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist b/MixSdk/MixSdk/MixSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c65c30d --- /dev/null +++ b/MixSdk/MixSdk/MixSdk.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + MixSdk.xcscheme_^#shared#^_ + + orderHint + 0 + + + SuppressBuildableAutocreation + + 18204BBA2C193E3D00F94E69 + + primary + + + + + diff --git a/MixSdk/MixSdk/MixSdk/IBHttpManager.swift b/MixSdk/MixSdk/MixSdk/IBHttpManager.swift new file mode 100644 index 0000000..33448e9 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/IBHttpManager.swift @@ -0,0 +1,63 @@ +// +// HttpManager.swift +// MixSdk +// +// Created by incar on 2024/6/12. +// + +import Foundation + +class IBHttpManager{ + + func request(_ url:URL){ + // 创建URL对象 + + // 创建URLSessionDataTask来发送请求 + let task = URLSession.shared.dataTask(with: url) { (data, response, error) in + // 确保没有错误发生 + if let error = error { + print("Error: \(error)") + return + } + + // 确保我们得到了数据 + guard let data = data else { + print("未收到数据") + return + } + + // 尝试解析数据为JSON(如果服务器返回的是JSON) + if let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) { + print(jsonObject) + } else { + print("JSON解析失败") + } + } + + // 启动任务 + task.resume() + } + + + func post(_ url:URL){ + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + // 创建POST的数据(例如JSON) + let postData = "{\"key\":\"value\"}".data(using: .utf8) + request.httpBody = postData + + // 创建URLSessionDataTask来发送请求 + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + // 处理响应类似于GET请求 + } + + // 启动任务 + task.resume() + } + + +} + + diff --git a/MixSdk/MixSdk/MixSdk/MSAuth.swift b/MixSdk/MixSdk/MixSdk/MSAuth.swift new file mode 100644 index 0000000..89cc855 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/MSAuth.swift @@ -0,0 +1,112 @@ +// +// TestDemo.swift +// MixSdk +// +// Created by incar on 2024/6/12. +// + +import Foundation +import CommonCrypto + +//class AuthResultModel:Codable{ +// var success = false +// var msg = "" +// var code = 0 +// var data:String? = "" +//} + +public typealias MSRegisterCompleteHandler = (_ deviceSecret: String?,_ error:MSError?) -> Void +public typealias MSLoginCompleteHandler = (_ isSuccess: Bool,_ error:MSError?) -> Void + +public class MSAuth { + public var isAuth = false + + func getUrl(_ api:String)->String{ + return "https://app.api.thisiot.com/da/auth/" + api + } + + /// 注册 + /// - Parameters: + /// - productKey: 产品Key + /// - secretKey: 产品秘钥 + /// - deviceId: 设备ID + /// - sn: SN号 + /// - completeHandler: 结果回调 + public func register(productKey:String,secretKey:String,deviceId:String,sn:String,completeHandler: @escaping MSRegisterCompleteHandler){ + let timeStamp = "\(Int(Date().timeIntervalSince1970)*1000)" + let value = deviceId + sn + timeStamp + secretKey + let signValue = value.md5 + let params = [ + "bid":productKey, + "deviceId":deviceId, + "signMethod":"MD5", + "sign":signValue, + "timeStamp":timeStamp, + "sn":sn + ] + let url = getUrl("active") + Logger.log(url,params) + + HTTP.PUT(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + if let _ = response.error { + Logger.log(response.description) + completeHandler(nil,MSError.invalidRequest) + return + } + Logger.log(response.data.string ?? "") + guard let dict = response.data.jsonObject() as? NSDictionary else{ + completeHandler(nil,MSError.parsingError) + return + } + if let result = dict["success"] as? Bool,result == true,let data = dict["data"] as? [String:Any], let deviceSecret = data["deviceSecret"] as? String{ + completeHandler(deviceSecret,nil) + } + else{ + completeHandler(nil,MSError.reponseError(dict["code"] as? Int ?? 0,dict["msg"] as? String ?? "")) + } + } + } + + /// 登录 + /// - Parameters: + /// - productKey:产品Key + /// - secretKey: 产品秘钥 + /// - deviceId: 设备ID + /// - deviceSecrect: 注册返回的密码 + /// - completeHandler: 结果回调 + public func login(productKey:String,secretKey:String,deviceId:String,deviceSecrect:String,completeHandler: @escaping MSLoginCompleteHandler){ + let timeStamp = "\(Int(Date().timeIntervalSince1970*1000))" + let value = deviceId + deviceSecrect + timeStamp + secretKey + let signValue = value.md5 + let params = [ + "bid":productKey, + "deviceId":deviceId, + "deviceSecret":deviceSecrect, + "timestamp":timeStamp, + "signMethod":"MD5", + "sign":signValue + ] + let url = getUrl("login") + Logger.log(url,params) + + HTTP.POST(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + if let _ = response.error { + Logger.log(response.description) + completeHandler(false,MSError.invalidRequest) + return + } + Logger.log(response.data.string ?? "") + guard let dict = response.data.jsonObject() as? NSDictionary else{ + completeHandler(false,MSError.parsingError) + return + } + if let result = dict["success"] as? Bool,result == true{ + self.isAuth = true + completeHandler(true,nil) + } + else{ + completeHandler(false,MSError.reponseError(dict["code"] as? Int ?? 0,dict["msg"] as? String ?? "")) + } + } + } +} diff --git a/MixSdk/MixSdk/MixSdk/MSError.swift b/MixSdk/MixSdk/MixSdk/MSError.swift new file mode 100644 index 0000000..32e1a7a --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/MSError.swift @@ -0,0 +1,20 @@ +// +// MSError.swift +// MixSdk +// +// Created by incar on 2024/6/13. +// + +import Foundation + +/// 错误类型 +public enum MSError: Error { + /// 无效的请求 + case invalidRequest + /// 解析出错 + case parsingError + /// 响应出错 + case reponseError(Int,String) + /// 未鉴权 + case unauthorised +} diff --git a/MixSdk/MixSdk/MixSdk/MSManager.swift b/MixSdk/MixSdk/MixSdk/MSManager.swift new file mode 100644 index 0000000..50c51dc --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/MSManager.swift @@ -0,0 +1,37 @@ +// +// MSManager.swift +// MixSdk +// +// Created by incar on 2024/6/13. +// + +import Foundation + +/// SDK 管理类 +public class MSManager:NSObject { + public static let shared = MSManager() + + private override init() { + super.init() + } + + /// 初始化工作 + public func initSDK() { + Logger.log("sdk version:",MSManager.version) + } + + + /// 日志 + public var logs: [String] { Logger.logs } + + /// SDK 版本号 + public let version: String = "1.0.0" + /// 默认为 false + public var isDebug: Bool = false { + didSet { Logger.isDebug = isDebug } + } + + public var auth = MSAuth() + + public var translate = MSTranslate() +} diff --git a/MixSdk/MixSdk/MixSdk/MSTranslate.swift b/MixSdk/MixSdk/MixSdk/MSTranslate.swift new file mode 100644 index 0000000..0cb54f4 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/MSTranslate.swift @@ -0,0 +1,97 @@ +// +// MSTranslate.swift +// MixSdk +// +// Created by incar on 2024/6/13. +// + +import Foundation + +class MSSupportLanModel:Codable{ + var status:Int = 0 + var data:[MSSupportLanguage] = [] +} + +public class MSSupportLanguage:Codable{ + /// 中文名称 + var cn = "" + /// 英文名称 + var en = "" + /// 代码 + var code = "" +} + + +public typealias MSTranslateCompleteHandler = (_ text: String?,_ error:MSError?) -> Void +public typealias MSLanuageCompleteHandler = (_ list: [MSSupportLanguage]?,_ error:MSError?) -> Void + +public class MSTranslate { + + private func getUrl(_ api:String)->String{ + return "http://121.40.67.151:9099/translate/" + api + } +} + +public extension MSTranslate{ + + /// 通用翻译 + /// - Parameters: + /// - lang: 语言 + /// - text: 需要翻译的文字 + /// - completeHandler: 结果回调 + func translate(lang:String,text:String,completeHandler: @escaping MSTranslateCompleteHandler){ + let url = getUrl("general") + let params = [ + "sl":"auto", + "tl":lang, + "text":text + ] + Logger.log(url,params) + + HTTP.POST(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + if let _ = response.error { + Logger.log(response.description) + completeHandler(nil,MSError.invalidRequest) + return + } + Logger.log(response.data.string ?? "") + guard let dict = response.data.jsonObject() as? NSDictionary else{ + completeHandler(nil,MSError.parsingError) + return + } + if let data = dict["data"] as? [String:Any], let translated = data["translated"] as? String{ + completeHandler(translated,nil) + } + else{ + completeHandler(nil,MSError.reponseError(dict["status"] as? Int ?? 0,"翻译失败")) + } + } + } + + + /// 获取支持的语言 + /// - Parameter completeHandler: 结果回调 + func getSupportLanguages(completeHandler: @escaping MSLanuageCompleteHandler){ + let url = getUrl("languages") + Logger.log(url) + + HTTP.POST(url,requestSerializer: JSONParameterSerializer()){ response in + if let _ = response.error { + Logger.log(response.description) + completeHandler(nil,MSError.invalidRequest) + return + } + Logger.log(response.data.string ?? "") + guard let model = JSON.decode(MSSupportLanModel.self, from: response.data) else{ + completeHandler(nil,MSError.parsingError) + return + } + if model.data.count > 0 { + completeHandler(model.data,nil) + } + else{ + completeHandler(nil,MSError.reponseError(model.status,"获取失败")) + } + } + } +} diff --git a/MixSdk/MixSdk/MixSdk/MixSdk.h b/MixSdk/MixSdk/MixSdk/MixSdk.h new file mode 100644 index 0000000..19e1df6 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/MixSdk.h @@ -0,0 +1,18 @@ +// +// MixSdk.h +// MixSdk +// +// Created by incar on 2024/6/12. +// + +#import + +//! Project version number for MixSdk. +FOUNDATION_EXPORT double MixSdkVersionNumber; + +//! Project version string for MixSdk. +FOUNDATION_EXPORT const unsigned char MixSdkVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/HTTPSecurity.swift b/MixSdk/MixSdk/MixSdk/SwiftHTTP/HTTPSecurity.swift new file mode 100644 index 0000000..fb4d9e3 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/HTTPSecurity.swift @@ -0,0 +1,239 @@ +// +// HTTPSecurity.swift +// SwiftHTTP +// +// Created by Dalton Cherry on 5/16/15. +// Copyright (c) 2015 Vluxe. All rights reserved. +// + +import Foundation +import Security + +open class SSLCert { + var certData: Data? + var key: SecKey? + + /** + Designated init for certificates + + - parameter data: is the binary data of the certificate + + - returns: a representation security object to be used with + */ + public init(data: Data) { + self.certData = data + } + + /** + Designated init for public keys + + - parameter key: is the public key to be used + + - returns: a representation security object to be used with + */ + public init(key: SecKey) { + self.key = key + } +} + +open class HTTPSecurity { + open var validatedDN = true //should the domain name be validated? + + var isReady = false //is the key processing done? + var certificates: [Data]? //the certificates + var pubKeys: [SecKey]? //the public keys + var usePublicKeys = false //use public keys or certificate validation? + + /** + Use certs from main app bundle + + - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation + + - returns: a representation security object to be used with + */ + public convenience init(usePublicKeys: Bool = false) { + let paths = Bundle.main.paths(forResourcesOfType: "cer", inDirectory: ".") + var collect = Array() + for path in paths { + if let d = try? Data(contentsOf: URL(fileURLWithPath: path as String)) { + collect.append(SSLCert(data: d)) + } + } + self.init(certs:collect, usePublicKeys: usePublicKeys) + } + + /** + Designated init + + - parameter keys: is the certificates or public keys to use + - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation + + - returns: a representation security object to be used with + */ + public init(certs: [SSLCert], usePublicKeys: Bool) { + self.usePublicKeys = usePublicKeys + + if self.usePublicKeys { + DispatchQueue.global().async { + var collect = Array() + for cert in certs { + if let data = cert.certData , cert.key == nil { + cert.key = self.extractPublicKey(data) + } + if let k = cert.key { + collect.append(k) + } + } + self.pubKeys = collect + self.isReady = true + } + } else { + var collect = Array() + for cert in certs { + if let d = cert.certData { + collect.append(d) + } + } + self.certificates = collect + self.isReady = true + } + } + + /** + Valid the trust and domain name. + + - parameter trust: is the serverTrust to validate + - parameter domain: is the CN domain to validate + + - returns: if the key was successfully validated + */ + open func isValid(_ trust: SecTrust, domain: String?) -> Bool { + + var tries = 0 + while(!self.isReady) { + usleep(1000) + tries += 1 + if tries > 5 { + return false //doesn't appear it is going to ever be ready... + } + } + var policy: SecPolicy + if self.validatedDN { + policy = SecPolicyCreateSSL(true, domain as CFString?) + } else { + policy = SecPolicyCreateBasicX509() + } + SecTrustSetPolicies(trust,policy) + if self.usePublicKeys { + if let keys = self.pubKeys { + var trustedCount = 0 + let serverPubKeys = publicKeyChainForTrust(trust) + for serverKey in serverPubKeys as [AnyObject] { + for key in keys as [AnyObject] { + if serverKey.isEqual(key) { + trustedCount += 1 + break + } + } + } + if trustedCount == serverPubKeys.count { + return true + } + } + } else if let certs = self.certificates { + let serverCerts = certificateChainForTrust(trust) + var collect = Array() + for cert in certs { + collect.append(SecCertificateCreateWithData(nil,cert as CFData)!) + } + SecTrustSetAnchorCertificates(trust,collect as CFArray) + var result: SecTrustResultType = SecTrustResultType(rawValue: UInt32(0))! + SecTrustEvaluate(trust,&result) + if result == SecTrustResultType.unspecified || result == SecTrustResultType.proceed { + var trustedCount = 0 + for serverCert in serverCerts { + for cert in certs { + if cert == serverCert { + trustedCount += 1 + break + } + } + } + if trustedCount == serverCerts.count { + return true + } + } + } + return false + } + + /** + Get the public key from a certificate data + + - parameter data: is the certificate to pull the public key from + + - returns: a public key + */ + func extractPublicKey(_ data: Data) -> SecKey? { + let possibleCert = SecCertificateCreateWithData(nil,data as CFData) + if let cert = possibleCert { + return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509()) + } + return nil + } + + /** + Get the public key from a certificate + + - parameter data: is the certificate to pull the public key from + + - returns: a public key + */ + func extractPublicKeyFromCert(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? { + var possibleTrust: SecTrust? + SecTrustCreateWithCertificates(cert, policy, &possibleTrust) + if let trust = possibleTrust { + var result: SecTrustResultType = SecTrustResultType(rawValue: UInt32(0))! + SecTrustEvaluate(trust, &result) + return SecTrustCopyPublicKey(trust) + } + return nil + } + + /** + Get the certificate chain for the trust + + - parameter trust: is the trust to lookup the certificate chain for + + - returns: the certificate chain for the trust + */ + func certificateChainForTrust(_ trust: SecTrust) -> Array { + var collect = Array() + for i in 0 ..< SecTrustGetCertificateCount(trust) { + let cert = SecTrustGetCertificateAtIndex(trust,i) + collect.append(SecCertificateCopyData(cert!) as Data) + } + return collect + } + + /** + Get the public key chain for the trust + + - parameter trust: is the trust to lookup the certificate chain and extract the public keys + + - returns: the public keys from the certifcate chain for the trust + */ + func publicKeyChainForTrust(_ trust: SecTrust) -> Array { + var collect = Array() + let policy = SecPolicyCreateBasicX509() + for i in 0 ..< SecTrustGetCertificateCount(trust) { + let cert = SecTrustGetCertificateAtIndex(trust,i) + if let key = extractPublicKeyFromCert(cert!, policy: policy) { + collect.append(key) + } + } + return collect + } + + +} diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/Operation.swift b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Operation.swift new file mode 100644 index 0000000..90e2b41 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Operation.swift @@ -0,0 +1,556 @@ +// +// Operation.swift +// SwiftHTTP +// +// Created by Dalton Cherry on 8/2/15. +// Copyright © 2015 vluxe. All rights reserved. +// + +import Foundation + +enum HTTPOptError: Error { + case invalidRequest +} + +/** +This protocol exist to allow easy and customizable swapping of a serializing format within an class methods of HTTP. +*/ +public protocol HTTPSerializeProtocol { + + /** + implement this protocol to support serializing parameters to the proper HTTP body or URL + -parameter request: The URLRequest object you will modify to add the parameters to + -parameter parameters: The container (array or dictionary) to convert and append to the URL or Body + */ + func serialize(_ request: inout URLRequest, parameters: HTTPParameterProtocol) -> Error? +} + +/** +Standard HTTP encoding +*/ +public struct HTTPParameterSerializer: HTTPSerializeProtocol { + public init() { } + public func serialize(_ request: inout URLRequest, parameters: HTTPParameterProtocol) -> Error? { + return request.appendParameters(parameters) + } +} + +/** +Send the data as a JSON body +*/ +public struct JSONParameterSerializer: HTTPSerializeProtocol { + public init() { } + public func serialize(_ request: inout URLRequest, parameters: HTTPParameterProtocol) -> Error? { + return request.appendParametersAsJSON(parameters) + } +} + +/** +All the things of an HTTP response +*/ +open class Response { + /// The header values in HTTP response. + open var headers: Dictionary? + /// The mime type of the HTTP response. + open var mimeType: String? + /// The suggested filename for a downloaded file. + open var suggestedFilename: String? + /// The body data of the HTTP response. + open var data: Data { + return collectData as Data + } + /// The status code of the HTTP response. + open var statusCode: Int? + /// The URL of the HTTP response. + open var URL: Foundation.URL? + /// The Error of the HTTP response (if there was one). + open var error: Error? + ///Returns the response as a string + open var text: String? { + return String(data: data, encoding: .utf8) + } + ///get the description of the response + open var description: String { + var buffer = "" + if let u = URL { + buffer += "URL:\n\(u)\n\n" + } + if let code = self.statusCode { + buffer += "Status Code:\n\(code)\n\n" + } + if let heads = headers { + buffer += "Headers:\n" + for (key, value) in heads { + buffer += "\(key): \(value)\n" + } + buffer += "\n" + } + if let t = text { + buffer += "Payload:\n\(t)\n" + } + return buffer + } + ///private things + + ///holds the collected data + var collectData = NSMutableData() + ///finish closure + var completionHandler:((Response) -> Void)? + + //progress closure. Progress is between 0 and 1. + var progressHandler:((Float) -> Void)? + + //download closure. the URL is the file URL where the temp file has been download. + //This closure will be called so you can move the file where you desire. + var downloadHandler:((Response, URL) -> Void)? + + ///This gets called on auth challenges. If nil, default handling is use. + ///Returning nil from this method will cause the request to be rejected and cancelled + var auth:((URLAuthenticationChallenge) -> URLCredential?)? + + ///This is for doing SSL pinning + var security: HTTPSecurity? +} + +/** +The class that does the magic. Is a subclass of NSOperation so you can use it with operation queues or just a good ole HTTP request. +*/ +open class HTTP { + /** + Get notified with a request finishes. + */ + open var onFinish:((Response) -> Void)? { + didSet { + if let handler = onFinish { + DelegateManager.sharedInstance.addTask(task, completionHandler: { (response: Response) in + handler(response) + }) + } + } + } + ///This is for handling authenication + open var auth:((URLAuthenticationChallenge) -> URLCredential?)? { + set { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return } + resp.auth = newValue + } + get { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return nil } + return resp.auth + } + } + + ///This is for doing SSL pinning + open var security: HTTPSecurity? { + set { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return } + resp.security = newValue + } + get { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return nil } + return resp.security + } + } + + ///This is for monitoring progress + open var progress: ((Float) -> Void)? { + set { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return } + resp.progressHandler = newValue + } + get { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return nil } + return resp.progressHandler + } + } + + ///This is for handling downloads + open var downloadHandler: ((Response, URL) -> Void)? { + set { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return } + resp.downloadHandler = newValue + } + get { + guard let resp = DelegateManager.sharedInstance.responseForTask(task) else { return nil } + return resp.downloadHandler + } + } + + ///the actual task + var task: URLSessionTask! + + /** + creates a new HTTP request. + */ + public init(_ req: URLRequest, session: URLSession = SharedSession.defaultSession, isDownload: Bool = false) { + if isDownload { + task = session.downloadTask(with: req) + } else { + task = session.dataTask(with: req) + } + DelegateManager.sharedInstance.addResponseForTask(task) + } + + /** + start/sends the HTTP task with a completionHandler. Use this when *NOT* using an NSOperationQueue. + */ + open func run(_ completionHandler: ((Response) -> Void)? = nil) { + if let handler = completionHandler { + onFinish = handler + } + task.resume() + } + + /** + Cancel the running task + */ + open func cancel() { + task.cancel() + } + + /** + Class method to run a GET request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func GET(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, + requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .GET, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + /** + Class method to run a HEAD request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func HEAD(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .HEAD, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + /** + Class method to run a DELETE request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func DELETE(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .DELETE, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + /** + Class method to run a POST request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func POST(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .POST, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + /** + Class method to run a PUT request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func PUT(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, + requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .PUT, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + /** + Class method to run a PUT request that handles the URLRequest and parameter encoding for you. + */ + @discardableResult open class func PATCH(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + return Run(url, method: .PATCH, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) + } + + @discardableResult class func Run(_ url: String, method: HTTPVerb, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + guard let task = HTTP.New(url, method: method, parameters: parameters, headers: headers, requestSerializer: requestSerializer, completionHandler: completionHandler) else {return nil} + task.run() + return task + } + + /** + Class method to create a Download request that handles the URLRequest and parameter encoding for you. + */ + open class func Download(_ url: String, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, + requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completion:@escaping ((Response, URL) -> Void)) { + guard let task = HTTP.New(url, method: .GET, parameters: parameters, headers: headers, requestSerializer: requestSerializer) else {return} + task.downloadHandler = completion + task.run() + } + + /** + Class method to create a HTTP request that handles the URLRequest and parameter encoding for you. + */ + open class func New(_ url: String, method: HTTPVerb, parameters: HTTPParameterProtocol? = nil, headers: [String:String]? = nil, requestSerializer: HTTPSerializeProtocol = HTTPParameterSerializer(), completionHandler: ((Response) -> Void)? = nil) -> HTTP? { + guard var req = URLRequest(urlString: url, headers: headers) else { + guard let handler = completionHandler else { return nil } + let resp = Response() + resp.error = HTTPOptError.invalidRequest + handler(resp) + return nil + } + if let handler = DelegateManager.sharedInstance.requestHandler { + handler(&req) + } + req.verb = method + if let params = parameters { + if let error = requestSerializer.serialize(&req, parameters: params) { + guard let handler = completionHandler else { return nil } + let resp = Response() + resp.error = error + handler(resp) + return nil + } + } + let httpReq = HTTP(req) + httpReq.onFinish = completionHandler + return httpReq + } + + /** + Set the global auth handler + */ + open class func globalAuth(_ handler: ((URLAuthenticationChallenge) -> URLCredential?)?) { + DelegateManager.sharedInstance.auth = handler + } + + /** + Set the global security handler + */ + open class func globalSecurity(_ security: HTTPSecurity?) { + DelegateManager.sharedInstance.security = security + } + + /** + Set the global request handler + */ + open class func globalRequest(_ handler: ((inout URLRequest) -> Void)?) { + DelegateManager.sharedInstance.requestHandler = handler + } +} + +extension HTTP { + static func == (left: HTTP, right: HTTP) -> Bool { + return left.task.taskIdentifier == right.task.taskIdentifier + } + + static func != (left: HTTP, right: HTTP) -> Bool { + return !(left == right) + } +} + +/** +Absorb all the delegates methods of NSURLSession and forwards them to pretty closures. +This is basically the sin eater for NSURLSession. +*/ +public class DelegateManager: NSObject, URLSessionDataDelegate, URLSessionDownloadDelegate { + //the singleton to handle delegate needs of NSURLSession + static let sharedInstance = DelegateManager() + + /// this is for global authenication handling + var auth:((URLAuthenticationChallenge) -> URLCredential?)? + + ///This is for global SSL pinning + var security: HTTPSecurity? + + /// this is for global request handling + var requestHandler:((inout URLRequest) -> Void)? + + var taskMap = Dictionary() + //"install" a task by adding the task to the map and setting the completion handler + func addTask(_ task: URLSessionTask, completionHandler:@escaping ((Response) -> Void)) { + addResponseForTask(task) + if let resp = responseForTask(task) { + resp.completionHandler = completionHandler + } + } + + //"remove" a task by removing the task from the map + func removeTask(_ task: URLSessionTask) { + taskMap.removeValue(forKey: task.taskIdentifier) + } + + //add the response task + func addResponseForTask(_ task: URLSessionTask) { + if taskMap[task.taskIdentifier] == nil { + taskMap[task.taskIdentifier] = Response() + } + } + //get the response object for the task + func responseForTask(_ task: URLSessionTask) -> Response? { + return taskMap[task.taskIdentifier] + } + + //handle getting data + public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + addResponseForTask(dataTask) + guard let resp = responseForTask(dataTask) else { return } + resp.collectData.append(data) + if resp.progressHandler != nil { //don't want the extra cycles for no reason + guard let taskResp = dataTask.response else { return } + progressHandler(resp, expectedLength: taskResp.expectedContentLength, currentLength: Int64(resp.collectData.length)) + } + } + + //handle task finishing + public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + guard let resp = responseForTask(task) else { return } + resp.error = error as NSError? + if let hresponse = task.response as? HTTPURLResponse { + resp.headers = hresponse.allHeaderFields as? Dictionary + resp.mimeType = hresponse.mimeType + resp.suggestedFilename = hresponse.suggestedFilename + resp.statusCode = hresponse.statusCode + resp.URL = hresponse.url + } + if let code = resp.statusCode, code > 299 { + resp.error = createError(code) + } + if let handler = resp.completionHandler { + handler(resp) + } + removeTask(task) + } + + //handle authenication + public func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + var sec = security + var au = auth + if let resp = responseForTask(task) { + if let s = resp.security { + sec = s + } + if let a = resp.auth { + au = a + } + } + if let sec = sec , challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { + let space = challenge.protectionSpace + if let trust = space.serverTrust { + if sec.isValid(trust, domain: space.host) { + completionHandler(.useCredential, URLCredential(trust: trust)) + return + } + } + completionHandler(.cancelAuthenticationChallenge, nil) + return + + } else if let a = au { + let cred = a(challenge) + if let c = cred { + completionHandler(.useCredential, c) + return + } + completionHandler(.rejectProtectionSpace, nil) + return + } + completionHandler(.performDefaultHandling, nil) + } + + //upload progress + public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { + guard let resp = responseForTask(task) else { return } + progressHandler(resp, expectedLength: totalBytesExpectedToSend, currentLength: totalBytesSent) + } + + //download progress + public func urlSession(_ session: Foundation.URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { + guard let resp = responseForTask(downloadTask) else { return } + progressHandler(resp, expectedLength: totalBytesExpectedToWrite, currentLength: totalBytesWritten) + } + + //handle download task + public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { + guard let resp = responseForTask(downloadTask) else { return } + guard let handler = resp.downloadHandler else { return } + handler(resp, location) + } + + //handle progress + public func progressHandler(_ response: Response, expectedLength: Int64, currentLength: Int64) { + guard let handler = response.progressHandler else { return } + let slice = Float(1.0)/Float(expectedLength) + handler(slice*Float(currentLength)) + } + + /** + Create an error for response you probably don't want (400-500 HTTP responses for example). + + -parameter code: Code for error. + + -returns An NSError. + */ + fileprivate func createError(_ code: Int) -> NSError { + let text = HTTPStatusCode(statusCode: code).statusDescription + return NSError(domain: "HTTP", code: code, userInfo: [NSLocalizedDescriptionKey: text]) + } +} + +/** +Handles providing singletons of NSURLSession. +*/ +public class SharedSession { + public static let defaultSession = URLSession(configuration: URLSessionConfiguration.default, + delegate: DelegateManager.sharedInstance, delegateQueue: nil) + static let ephemeralSession = URLSession(configuration: URLSessionConfiguration.ephemeral, + delegate: DelegateManager.sharedInstance, delegateQueue: nil) +} + + +/** + Bare bones queue to manage HTTP Requests + */ +open class HTTPQueue { + public var maxSimultaneousRequest = 5 + var queue = [HTTP]() + let mutex = NSLock() + var activeReq = [Int: HTTP]() + var finishedHandler: (() -> Void)? + + public init(maxSimultaneousRequest: Int) { + self.maxSimultaneousRequest = maxSimultaneousRequest + } + + open func add(request: URLRequest) { + add(http: HTTP(request)) + } + + open func add(http: HTTP) { + var doWork = false + mutex.lock() + queue.append(http) + if activeReq.count < maxSimultaneousRequest { + doWork = true + } + mutex.unlock() + if doWork { + run() + } + } + + open func finished(queue: DispatchQueue = DispatchQueue.main, completionHandler: @escaping (() -> Void)) { + finishedHandler = completionHandler + } + + func run() { + guard let http = nextItem() else { + mutex.lock() + let count = activeReq.count + mutex.unlock() + if count == 0 { + finishedHandler?() + } + return + } + let handler = http.onFinish + http.run {[weak self] (response) in + handler?(response) + self?.mutex.lock() + self?.activeReq.removeValue(forKey: http.task.taskIdentifier) + self?.mutex.unlock() + self?.run() + } + } + + func nextItem() -> HTTP? { + mutex.lock() + if queue.count == 0 { + mutex.unlock() + return nil + } + let next = queue.removeFirst() + activeReq[next.task.taskIdentifier] = next + mutex.unlock() + return next + } +} diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/Request.swift b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Request.swift new file mode 100644 index 0000000..6767352 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Request.swift @@ -0,0 +1,361 @@ +// +// Request.swift +// SwiftHTTP +// +// Created by Dalton Cherry on 8/16/15. +// Copyright © 2015 vluxe. All rights reserved. +// + +import Foundation + + +extension String { + /** + A simple extension to the String object to encode it for web request. + + :returns: Encoded version of of string it was called as. + */ + var escaped: String? { + var set = CharacterSet() + set.formUnion(CharacterSet.urlQueryAllowed) + set.remove(charactersIn: "[].:/?&=;+!@#$()',*\"") // remove the HTTP ones from the set. + return self.addingPercentEncoding(withAllowedCharacters: set) + } + + /** + A simple extension to the String object to url encode quotes only. + + :returns: string with . + */ + var quoteEscaped: String { + return self.replacingOccurrences(of: "\"", with: "%22").replacingOccurrences(of: "'", with: "%27") + } +} + +/** +The standard HTTP Verbs +*/ +public enum HTTPVerb: String { + case GET = "GET" + case POST = "POST" + case PUT = "PUT" + case HEAD = "HEAD" + case DELETE = "DELETE" + case PATCH = "PATCH" + case OPTIONS = "OPTIONS" + case TRACE = "TRACE" + case CONNECT = "CONNECT" + case UNKNOWN = "UNKNOWN" +} + +/** +This is used to create key/value pairs of the parameters +*/ +public struct HTTPPair { + var key: String? + let storeVal: AnyObject + /** + Create the object with a possible key and a value + */ + init(key: String?, value: AnyObject) { + self.key = key + self.storeVal = value + } + /** + Computed property of the string representation of the storedVal + */ + var upload: Upload? { + return storeVal as? Upload + } + /** + Computed property of the string representation of the storedVal + */ + var value: String { + if storeVal is NSNull { + return "" + } else if let v = storeVal as? String { + return v + } else { + return storeVal.description ?? "" + } + } + /** + Computed property of the string representation of the storedVal escaped for URLs + */ + var escapedValue: String { + let v = value.escaped ?? "" + if let k = key { + if let escapedKey = k.escaped { + return "\(escapedKey)=\(v)" + } + } + return "" + } +} + +/** + This is super gross, but it is just an edge case, I'm willing to live with it + versus trying to handle such an rare need with more code and confusion + */ +public class HTTPParameterProtocolSettings { + public static var sendEmptyArray = false +} + +/** +This protocol is used to make the dictionary and array serializable into key/value pairs. +*/ +public protocol HTTPParameterProtocol { + func createPairs(_ key: String?) -> [HTTPPair] +} + +/** +Support for the Dictionary type as an HTTPParameter. +*/ +extension Dictionary: HTTPParameterProtocol { + public func createPairs(_ key: String?) -> [HTTPPair] { + var collect = [HTTPPair]() + for (k, v) in self { + if let nestedKey = k as? String { + let useKey = key != nil ? "\(key!)[\(nestedKey)]" : nestedKey + if let subParam = v as? HTTPParameterProtocol { + collect.append(contentsOf: subParam.createPairs(useKey)) + } else { + collect.append(HTTPPair(key: useKey, value: v as AnyObject)) + } + } + } + return collect + } +} + +/** +Support for the Array type as an HTTPParameter. +*/ +extension Array: HTTPParameterProtocol { + + public func createPairs(_ key: String?) -> [HTTPPair] { + var collect = [HTTPPair]() + for v in self { + let useKey = key != nil ? "\(key!)[]" : key + if let subParam = v as? HTTPParameterProtocol { + collect.append(contentsOf: subParam.createPairs(useKey)) + } else { + collect.append(HTTPPair(key: useKey, value: v as AnyObject)) + } + } + if HTTPParameterProtocolSettings.sendEmptyArray && collect.count == 0 { + collect.append(HTTPPair(key: key, value: "[]" as AnyObject)) + } + return collect + } +} + +/** +Support for the Upload type as an HTTPParameter. +*/ +extension Upload: HTTPParameterProtocol { + public func createPairs(_ key: String?) -> Array { + var collect = Array() + collect.append(HTTPPair(key: key, value: self)) + return collect + } +} + +/** +Adds convenience methods to URLRequest to make using it with HTTP much simpler. +*/ +extension URLRequest { + /** + Convenience init to allow init with a string. + -parameter urlString: The string representation of a URL to init with. + */ + public init?(urlString: String, parameters: HTTPParameterProtocol? = nil, headers: [String: String]? = nil, cachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, timeoutInterval: TimeInterval = 60) { + if let url = URL(string: urlString) { + self.init(url: url) + } else { + return nil + } + if let params = parameters { + let _ = appendParameters(params) + } + if let heads = headers { + for (key,value) in heads { + addValue(value, forHTTPHeaderField: key) + } + } + } + + /** + Convenience method to avoid having to use strings and allow using an enum + */ + public var verb: HTTPVerb { + set { + httpMethod = newValue.rawValue + } + get { + if let verb = httpMethod, let v = HTTPVerb(rawValue: verb) { + return v + } + return .UNKNOWN + } + } + + /** + Used to update the content type in the HTTP header as needed + */ + var contentTypeKey: String { + return "Content-Type" + } + + /** + append the parameters using the standard HTTP Query model. + This is parameters in the query string of the url (e.g. ?first=one&second=two for GET, HEAD, DELETE. + It uses 'application/x-www-form-urlencoded' for the content type of POST/PUT requests that don't contains files. + If it contains a file it uses `multipart/form-data` for the content type. + -parameter parameters: The container (array or dictionary) to convert and append to the URL or Body + */ + public mutating func appendParameters(_ parameters: HTTPParameterProtocol) -> Error? { + if isURIParam() { + appendParametersAsQueryString(parameters) + } else if containsFile(parameters) { + return appendParametersAsMultiPartFormData(parameters) + } else { + appendParametersAsUrlEncoding(parameters) + } + return nil + } + + /** + append the parameters as a HTTP Query string. (e.g. domain.com?first=one&second=two) + -parameter parameters: The container (array or dictionary) to convert and append to the URL + */ + public mutating func appendParametersAsQueryString(_ parameters: HTTPParameterProtocol) { + let queryString = parameters.createPairs(nil).map({ (pair) in + return pair.escapedValue + }).joined(separator: "&") + if let u = self.url , queryString.count > 0 { + let para = u.query != nil ? "&" : "?" + self.url = URL(string: "\(u.absoluteString)\(para)\(queryString)") + } + } + + /** + append the parameters as a url encoded string. (e.g. in the body of the request as: first=one&second=two) + -parameter parameters: The container (array or dictionary) to convert and append to the HTTP body + */ + public mutating func appendParametersAsUrlEncoding(_ parameters: HTTPParameterProtocol) { + if value(forHTTPHeaderField: contentTypeKey) == nil { + var contentStr = "application/x-www-form-urlencoded" + if let charset = CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(String.Encoding.utf8.rawValue)) { + contentStr += "; charset=\(charset)" + } + setValue(contentStr, forHTTPHeaderField:contentTypeKey) + } + let queryString = parameters.createPairs(nil).map({ (pair) in + return pair.escapedValue + }).joined(separator: "&") + httpBody = queryString.data(using: .utf8) + } + + /** + append the parameters as a multpart form body. This is the type normally used for file uploads. + -parameter parameters: The container (array or dictionary) to convert and append to the HTTP body + */ + public mutating func appendParametersAsMultiPartFormData(_ parameters: HTTPParameterProtocol) -> Error? { + let boundary = "Boundary+\(arc4random())\(arc4random())" + if value(forHTTPHeaderField: contentTypeKey) == nil { + setValue("multipart/form-data; boundary=\(boundary)", + forHTTPHeaderField:contentTypeKey) + } + let mutData = NSMutableData() + let multiCRLF = "\r\n" + mutData.append("--\(boundary)".data(using: .utf8)!) + for pair in parameters.createPairs(nil) { + guard let key = pair.key else { continue } //this won't happen, but just to properly unwrap + if let upload = pair.upload { + let resp = upload.getData() + if let error = resp.error { + return error + } + mutData.append("\(multiCRLF)".data(using: .utf8)!) + if let data = resp.data { + mutData.append(multiFormHeader(key, fileName: upload.fileName, + type: upload.mimeType, multiCRLF: multiCRLF).data(using: .utf8)!) + mutData.append(data) + } else { + return HTTPUploadError.noData + } + } else { + mutData.append("\(multiCRLF)".data(using: .utf8)!) + let str = "\(multiFormHeader(key, fileName: nil, type: nil, multiCRLF: multiCRLF))\(pair.value)" + mutData.append(str.data(using: .utf8)!) + } + mutData.append("\(multiCRLF)--\(boundary)".data(using: .utf8)!) + } + mutData.append("--\(multiCRLF)".data(using: .utf8)!) + httpBody = mutData as Data + return nil + } + + /** + Helper method to create the multipart form data + */ + func multiFormHeader(_ name: String, fileName: String?, type: String?, multiCRLF: String) -> String { + var str = "Content-Disposition: form-data; name=\"\(name.quoteEscaped)\"" + if let n = fileName { + str += "; filename=\"\(n.quoteEscaped)\"" + } + str += multiCRLF + if let t = type { + str += "Content-Type: \(t)\(multiCRLF)" + } + str += multiCRLF + return str + } + + + /** + send the parameters as a body of JSON + -parameter parameters: The container (array or dictionary) to convert and append to the URL or Body + */ + public mutating func appendParametersAsJSON(_ parameters: HTTPParameterProtocol) -> Error? { + if isURIParam() { + appendParametersAsQueryString(parameters) + } else { + do { + httpBody = try JSONSerialization.data(withJSONObject: parameters as AnyObject, options: JSONSerialization.WritingOptions()) + } catch let error { + return error + } + var contentStr = "application/json" + if let charset = CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(String.Encoding.utf8.rawValue)) { + contentStr += "; charset=\(charset)" + } + setValue(contentStr, forHTTPHeaderField: contentTypeKey) + } + return nil + } + + /** + Check if the request requires the parameters to be appended to the URL + */ + public func isURIParam() -> Bool { + if verb == .GET || verb == .HEAD || verb == .DELETE { + return true + } + return false + } + + /** + check if the parameters contain a file object within them + -parameter parameters: The parameters to search through for an upload object + */ + public func containsFile(_ parameters: HTTPParameterProtocol) -> Bool { + for pair in parameters.createPairs(nil) { + if let _ = pair.upload { + return true + } + } + return false + } +} diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/StatusCode.swift b/MixSdk/MixSdk/MixSdk/SwiftHTTP/StatusCode.swift new file mode 100644 index 0000000..71bdf93 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/StatusCode.swift @@ -0,0 +1,159 @@ +// +// HTTPStatusCode.swift +// SwiftHTTP +// +// Created by Yu Kadowaki on 7/12/15. +// Copyright (c) 2015 Vluxe. All rights reserved. +// + +import Foundation + +/// HTTP Status Code (RFC 2616) +public enum HTTPStatusCode: Int { + case `continue` = 100, + switchingProtocols = 101 + + case ok = 200, + created = 201, + accepted = 202, + nonAuthoritativeInformation = 203, + noContent = 204, + resetContent = 205, + partialContent = 206 + + case multipleChoices = 300, + movedPermanently = 301, + found = 302, + seeOther = 303, + notModified = 304, + useProxy = 305, + unused = 306, + temporaryRedirect = 307 + + case badRequest = 400, + unauthorized = 401, + paymentRequired = 402, + forbidden = 403, + notFound = 404, + methodNotAllowed = 405, + notAcceptable = 406, + proxyAuthenticationRequired = 407, + requestTimeout = 408, + conflict = 409, + gone = 410, + lengthRequired = 411, + preconditionFailed = 412, + requestEntityTooLarge = 413, + requestUriTooLong = 414, + unsupportedMediaType = 415, + requestedRangeNotSatisfiable = 416, + expectationFailed = 417 + + case internalServerError = 500, + notImplemented = 501, + badGateway = 502, + serviceUnavailable = 503, + gatewayTimeout = 504, + httpVersionNotSupported = 505 + + case invalidUrl = -1001 + + case unknownStatus = 0 + + init(statusCode: Int) { + self = HTTPStatusCode(rawValue: statusCode) ?? .unknownStatus + } + + public var statusDescription: String { + get { + switch self { + case .continue: + return "Continue" + case .switchingProtocols: + return "Switching protocols" + case .ok: + return "OK" + case .created: + return "Created" + case .accepted: + return "Accepted" + case .nonAuthoritativeInformation: + return "Non authoritative information" + case .noContent: + return "No content" + case .resetContent: + return "Reset content" + case .partialContent: + return "Partial Content" + case .multipleChoices: + return "Multiple choices" + case .movedPermanently: + return "Moved Permanently" + case .found: + return "Found" + case .seeOther: + return "See other Uri" + case .notModified: + return "Not modified" + case .useProxy: + return "Use proxy" + case .unused: + return "Unused" + case .temporaryRedirect: + return "Temporary redirect" + case .badRequest: + return "Bad request" + case .unauthorized: + return "Access denied" + case .paymentRequired: + return "Payment required" + case .forbidden: + return "Forbidden" + case .notFound: + return "Page not found" + case .methodNotAllowed: + return "Method not allowed" + case .notAcceptable: + return "Not acceptable" + case .proxyAuthenticationRequired: + return "Proxy authentication required" + case .requestTimeout: + return "Request timeout" + case .conflict: + return "Conflict request" + case .gone: + return "Page is gone" + case .lengthRequired: + return "Lack content length" + case .preconditionFailed: + return "Precondition failed" + case .requestEntityTooLarge: + return "Request entity is too large" + case .requestUriTooLong: + return "Request uri is too long" + case .unsupportedMediaType: + return "Unsupported media type" + case .requestedRangeNotSatisfiable: + return "Request range is not satisfiable" + case .expectationFailed: + return "Expected request is failed" + case .internalServerError: + return "Internal server error" + case .notImplemented: + return "Server does not implement a feature for request" + case .badGateway: + return "Bad gateway" + case .serviceUnavailable: + return "Service unavailable" + case .gatewayTimeout: + return "Gateway timeout" + case .httpVersionNotSupported: + return "Http version not supported" + case .invalidUrl: + return "Invalid url" + default: + return "Unknown status code" + } + } + } +} diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/SwiftHTTP.h b/MixSdk/MixSdk/MixSdk/SwiftHTTP/SwiftHTTP.h new file mode 100644 index 0000000..f1b72ec --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/SwiftHTTP.h @@ -0,0 +1,19 @@ +// +// SwiftHTTP.h +// SwiftHTTP +// +// Created by Austin Cherry on 9/16/14. +// Copyright (c) 2014 Vluxe. All rights reserved. +// + +#import + +//! Project version number for SwiftHTTP. +FOUNDATION_EXPORT double SwiftHTTPVersionNumber; + +//! Project version string for SwiftHTTP. +FOUNDATION_EXPORT const unsigned char SwiftHTTPVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/MixSdk/MixSdk/MixSdk/SwiftHTTP/Upload.swift b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Upload.swift new file mode 100644 index 0000000..160c668 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/SwiftHTTP/Upload.swift @@ -0,0 +1,117 @@ +// +// Upload.swift +// SwiftHTTP +// +// Created by Dalton Cherry on 6/5/14. +// Copyright (c) 2014 Vluxe. All rights reserved. +// + +import Foundation + +#if os(iOS) + import MobileCoreServices +#endif + +/** + Upload errors + */ +enum HTTPUploadError: Error { + case noFileUrl + case noData +} + +/** +This is how to upload files in SwiftHTTP. The upload object represents a file to upload by either a data blob or a url (which it reads off disk). +*/ +open class Upload: NSObject, NSCoding { + var fileUrl: URL? { + didSet { + getMimeType() + } + } + var mimeType: String? + var data: Data? + var fileName: String? + + /** + Tries to determine the mime type from the fileUrl extension. + */ + func getMimeType() { + mimeType = "application/octet-stream" + guard let url = fileUrl else { return } + #if os(iOS) || os(OSX) //for watchOS support + guard let UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, url.pathExtension as CFString, nil) else { return } + guard let str = UTTypeCopyPreferredTagWithClass(UTI.takeRetainedValue(), kUTTagClassMIMEType) else { return } + mimeType = str.takeRetainedValue() as String + #endif + } + + /** + Reads the data from disk or from memory. Throws an error if no data or file is found. + */ + open func getData() -> (data: Data?, error: Error?) { + if let d = data { + return (d, nil) + } + guard let url = fileUrl else { return (nil, HTTPUploadError.noFileUrl) } + fileName = url.lastPathComponent + do { + let d = try Data(contentsOf: url, options: .mappedIfSafe) + data = d + getMimeType() + return (d, nil) + } catch let error { + return (nil, error) + } + } + + /** + Standard NSCoder support + */ + open func encode(with aCoder: NSCoder) { + aCoder.encode(self.fileUrl, forKey: "fileUrl") + aCoder.encode(self.mimeType, forKey: "mimeType") + aCoder.encode(self.fileName, forKey: "fileName") + aCoder.encode(self.data, forKey: "data") + } + + /** + Required for NSObject support (because of NSCoder, it would be a struct otherwise!) + */ + public override init() { + super.init() + } + + required public convenience init(coder aDecoder: NSCoder) { + self.init() + fileUrl = aDecoder.decodeObject(forKey: "fileUrl") as? URL + mimeType = aDecoder.decodeObject(forKey: "mimeType") as? String + fileName = aDecoder.decodeObject(forKey: "fileName") as? String + data = aDecoder.decodeObject(forKey: "data") as? Data + } + + /** + Initializes a new Upload object with a fileUrl. The fileName and mimeType will be infered. + + -parameter fileUrl: The fileUrl is a standard url path to a file. + */ + public convenience init(fileUrl: URL) { + self.init() + self.fileUrl = fileUrl + } + + /** + Initializes a new Upload object with a data blob. + + -parameter data: The data is a NSData representation of a file's data. + -parameter fileName: The fileName is just that. The file's name. + -parameter mimeType: The mimeType is just that. The mime type you would like the file to uploaded as. + */ + ///upload a file from a a data blob. Must add a filename and mimeType as that can't be infered from the data + public convenience init(data: Data, fileName: String, mimeType: String) { + self.init() + self.data = data + self.fileName = fileName + self.mimeType = mimeType + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/Any.swift b/MixSdk/MixSdk/MixSdk/Tools/Any.swift new file mode 100644 index 0000000..d164046 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/Any.swift @@ -0,0 +1,180 @@ +// +// Any.swift +// MyBase +// +// Created by Harvey on 2021/6/2. +// + +import Foundation + +/// 判断可选类型是否为 nil +func isNil(_ any: Any?) -> Bool { + switch any { + case .none: return true + case .some: return false + } +} + +/// 判断可选类型是否有值 +func isValue(_ any: Any?) -> Bool { + return isNil(any) == false +} + +/// for Array +func isEmpty(_ value: [Any]?) -> Bool { + return isNil(value) || value!.count == 0 +} + +/// for Array +func isNotEmpty(_ value: [Any]?) -> Bool { + return isEmpty(value) == false +} + +/// for Dictionary +func isEmpty(_ value: [AnyHashable: Any]?) -> Bool { + return isNil(value) || value!.count == 0 +} + +/// for Dictionary +func isNotEmpty(_ value: [AnyHashable: Any]?) -> Bool { + return isEmpty(value) == false +} + +/// for String +func isEmpty(_ value: String?) -> Bool { + return isNil(value) || value!.count == 0 +} + +/// for String +func isNotEmpty(_ value: String?) -> Bool { + return isEmpty(value) == false +} + + extension String { + + /// 补足8位(长度为8的整数倍) + var binary: String { + let bytes = (Double(count) / 8.0).upInt + let offset = bytes * 8 - count + let prefix = Array(repeating: "0", count: offset).joined() + return prefix + self + } +} + +extension Double { + var upInt: Int { Int(ceil(self)) } +} + extension Int { + private static let binaryPack = 0b11111111 + + /// convert to data with byte (max is 4294967295) + /// + /// 低位 --> 高位 + var bytes: [UInt8] { + var mutatingSelf = self + var bytes = [UInt8(mutatingSelf & Self.binaryPack)] + + var count = 1 + mutatingSelf = mutatingSelf >> (count * 8) + while mutatingSelf > 0 { + bytes.append(UInt8(mutatingSelf & Self.binaryPack)) + mutatingSelf = mutatingSelf >> (count * 8) + count = count + 1 + } + return bytes + } + + /// convert to data with 1 byte + var byte: UInt8 { + UInt8(self & Self.binaryPack) + } + + /// convert to data with 2 byte + /// + /// 低位 --> 高位 + var byte2: [UInt8] { + [ + UInt8(self & Self.binaryPack), + UInt8(self >> 8 & Self.binaryPack) + ] + } + + /// convert to data with 3 byte + /// + /// 低位 --> 高位 + var byte3: [UInt8] { + [ + UInt8(self & Self.binaryPack), + UInt8(self >> 8 & Self.binaryPack), + UInt8(self >> 16 & Self.binaryPack) + ] + } + + /// convert to data with 4 byte + /// + /// 低位 --> 高位 + var byte4: [UInt8] { + [ + UInt8(self & Self.binaryPack), + UInt8(self >> 8 & Self.binaryPack), + UInt8(self >> 16 & Self.binaryPack), + UInt8(self >> 24 & Self.binaryPack) + ] + } +} + + extension BinaryInteger { + + /// e.g. 0000100110010101 + var binaryString: String { + .init(self, radix: 2).binary + } +} + + extension Array where Element == UInt8 { + + var int: Int { + self + .map { Int($0) } + .enumerated() + .map { $1 << ($0 * 8) } + .reduce(0, { partialResult, value in + partialResult | value + }) + } + + var data: Data { Data(self) } +} + + extension Data { + var bytes: [UInt8] { map { $0 } } + + func joined(format: String = "%02x", _ separator: String = "") -> String { + self + .map { String(format: format, $0) } + .joined(separator: separator) + } + + func reversedJoined(format: String = "%02x", _ separator: String = "") -> String { + self + .map { String(format: format, $0) } + .reversed() + .joined(separator: separator) + } + + var int: Int { + self + .map { Int($0) } + .enumerated() + .map { $1 << ($0 * 8) } + .reduce(0, { partialResult, value in + partialResult | value + }) + } + + var lrc: UInt8 { LRC.calculateLRC(bytes) } +} + + extension UInt8 { + var int: Int { Int(self) } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/CRC16.swift b/MixSdk/MixSdk/MixSdk/Tools/CRC16.swift new file mode 100644 index 0000000..d454510 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/CRC16.swift @@ -0,0 +1,44 @@ +// +// CRC16.swift +// MSManager +// +// Created by yaozuopan on 2024/3/12. +// + +import Foundation + +/// CRC-16/MODBUS +class CRC16 { + static let shared = CRC16() + private init() { } + + func result(_ bytes: [UInt8]) -> [UInt8] { + var crcValue = crc(bytes) + var crcBytes: [UInt8] = [0, 0] + for index in (0..<2).reversed() { + crcBytes[index] = UInt8(crcValue % 256) + crcValue >>= 8 + } + return crcBytes + } + + private func crc(_ bytes: [UInt8]) -> Int { + + var crcSum: Int = 0xffff + let polynomial: Int = 0xa001 + let length = bytes.count + + for index in 0..>= 1 + crcSum ^= polynomial + }else{ + crcSum >>= 1 + } + } + } + return crcSum + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/Date.swift b/MixSdk/MixSdk/MixSdk/Tools/Date.swift new file mode 100644 index 0000000..9fc933d --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/Date.swift @@ -0,0 +1,145 @@ +// +// Date.swift +// MyBase +// +// Created by Harvey on 2021/5/18. +// + +import Foundation + +// MARK: - Extension Date +extension Date { + + static let formatter = DateFormatter() + + struct Format { + + let rawValue: String + init(_ rawValue: String) { + self.rawValue = rawValue + } + + /// e.g. 01:01:01 + static let time: Format = .init("HH:mm:ss") + + /// e.g. 01:01 + static let shortTime: Format = .init("HH:mm") + + /// e.g. 01-01 + static let date: Format = .init("MM-dd") + + /// e.g. 01月01日 + static let date1: Format = .init("MM月dd日") + + /// e.g. 2020-01-01 + static let short: Format = .init("yyyy-MM-dd") + + /// e.g. 2020年01月01日 + static let short1: Format = .init("yyy年MM月dd日") + + /// e.g. 2020-01-01 01:01 + static let middle: Format = .init("yyyy-MM-dd HH:mm") + + /// e.g. 2020年01月01日 01:01 + static let middle1: Format = .init("yyy年MM月dd日 HH:mm") + + /// e.g. 2020-01-01 01:01:01 + static let long: Format = .init("yyyy-MM-dd HH:mm:ss") + + /// e.g. 2020年01月01日 01:01:01 + static let long1: Format = .init("yyyy年MM月dd日 HH:mm:ss") + + /// e.g. 2020-01-01 01:01:01.088 + static let full: Format = .init("yyyy-MM-dd HH:mm:ss.SSS") + + /// e.g. 2020年01月01日 01:01:01.088 + static let full1: Format = .init("yyyy年MM月dd日 HH:mm:ss.SSS") + } + + /// 格式化成本地时间 + func format(_ format: Date.Format = .middle) -> String { + Self.formatter.dateFormat = format.rawValue + return Self.formatter.string(from: self) + } + + enum Unit { + case minute(Int) + case hour(Int) + case day(Int) + + /// 转换成秒 + var second: TimeInterval { + switch self { + case .minute(let minute): return 60.0 * Double(minute) + case .hour(let hour): return 60.0 * 60.0 * Double(hour) + case .day(let day): return 60.0 * 60.0 * 24.0 * Double(day) + } + } + } +} + +let today: Date = .init() + +/// 本地化 +extension Date { + /// 星期几 + enum Week: Int { + /// 星期日 + case sun = 1 + /// 星期一 + case mon + /// 星期二 + case tue + /// 星期三 + case wed + /// 星期四 + case thur + /// 星期五 + case fri + /// 星期六 + case sat + } + +// /// 当天的第一秒 +// var fromTimeInterval: TimeInterval { +// let today = format(.short) +// return today.timeIntervalSince1970(.short) +// } +// +// /// 当天最后一秒 +// var toTimeInterval: TimeInterval { fromTimeInterval + Unit.day(1).second } + + /// 哪一年 + var year: Int { component(.year) } + + /// 哪个月 + var month: Int { component(.month) } + + /// 当月的第几天 + var day: Int { component(.day) } + + /// 当月的第几天 + var hour: Int { component(.hour)} + + /// 当月的第几天 + var minute: Int { component(.minute)} + + /// 当月的第几天 + var second: Int { component(.second)} + + /// 当月的第几周 + var weekOfMonth: Int { component(.weekOfMonth) } + + /// 今年的第几周 + var weekOfYear: Int { component(.weekOfYear) } + + /// 星期几 + var weekDay: Week { Week(rawValue: component(.weekday))! } + + /// 假设当天是周五,表示本月的第几个周五 + var weekdayOrdinal: Int { component(.weekdayOrdinal) } + + private func component(_ component: Calendar.Component) -> Int { + return Calendar.autoupdatingCurrent.component(component, from: self) + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/JSON.swift b/MixSdk/MixSdk/MixSdk/Tools/JSON.swift new file mode 100644 index 0000000..9c94ed9 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/JSON.swift @@ -0,0 +1,115 @@ +// +// JSON.swift +// MyBase +// +// Created by Harvey on 2024/1/7. +// + +import Foundation + + struct JSON { } + + extension Dictionary { + + func jsonString(options: JSONSerialization.WritingOptions = [.fragmentsAllowed]) -> String? { + guard JSONSerialization.isValidJSONObject(self) else { + Logger.log("无效的 JSONObject") + return nil + } + guard let data = try? JSONSerialization.data(withJSONObject: self, options: options) else { return nil } + return data.string + } +} + + extension Array { + + func jsonString(options: JSONSerialization.WritingOptions = [.fragmentsAllowed]) -> String? { + guard JSONSerialization.isValidJSONObject(self) else { + Logger.log("无效的 JSONObject") + return nil + } + guard let data = try? JSONSerialization.data(withJSONObject: self, options: options) else { return nil } + return data.string + } +} + + extension String { + + func jsonObject(options: JSONSerialization.ReadingOptions = [.mutableContainers]) -> Any? { + guard let data = self.data else { return nil } + return data.jsonObject(options: options) + } +} + + extension Data { + + func jsonObject(options: JSONSerialization.ReadingOptions = [.mutableContainers]) -> Any? { + do { return try JSONSerialization.jsonObject(with: self, options: options) } + catch { Logger.log(error) } + return nil + } +} + +// MARK: - Extension Codable + + extension Encodable { + + /// JSON encode + var encode: Data? { + do { + return try JSONEncoder().encode(self) + } catch { Logger.log(error) } + return nil + } + + var jsonString: String? { + encode?.string + } +} + + extension Decodable { + + /// JSON decode + static func decode(_ from: Data) -> Self? { + do { + return try JSONDecoder().decode(Self.self, from: from) + } catch { Logger.log(error) } + return nil + } + + /// JSON decode + static func decode(_ from: String) -> Self? { + guard let data = from.data else { return nil } + return decode(data) + } +} + + extension JSON { + /// JSON decode + static func decode(_ decodable: T.Type, from data: Data) -> T? { + do { + return try JSONDecoder().decode(decodable.self, from: data) + } catch { Logger.log(error) } + return nil + } + + /// JSON decode + static func decode(_ decodable: T.Type, from jsonString: String) -> T? { + guard let data = jsonString.data else { return nil } + return decode(decodable, from: data) + } +} + + extension Array where Element: Encodable { + /// JSON encode + var jsonData: Data? { + do { + return try JSONEncoder().encode(self) + } catch { Logger.log(error) } + return nil + } + + var jsonString: String? { + encode?.string + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/LRC.swift b/MixSdk/MixSdk/MixSdk/Tools/LRC.swift new file mode 100644 index 0000000..e3f04f7 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/LRC.swift @@ -0,0 +1,29 @@ +// +// LRC.swift +// MSManager +// +// Created by yaozuopan on 2024/3/13. +// + +import Foundation + +public struct LRC { + + static func calculateLRC(_ bytes: [UInt8]) -> UInt8 { + let sum = bytes.map({ Int($0) }).reduce(0) { partialResult, value in + partialResult + value + } + + let lrc = sum % 256 + return UInt8(lrc == 0 ? 0 : 256 - lrc) + } + + static func calculate(_ bytes: [UInt8]) -> UInt8 { + let sum = bytes.map({ Int($0) }).reduce(into: 0) { partialResult, value in + partialResult ^= value + } + return sum.byte + } +} + + diff --git a/MixSdk/MixSdk/MixSdk/Tools/Logger.swift b/MixSdk/MixSdk/MixSdk/Tools/Logger.swift new file mode 100644 index 0000000..86f74e1 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/Logger.swift @@ -0,0 +1,33 @@ +// +// Logger.swift +// +// +// Created by Harvey on 2021/4/27. +// + +import Foundation + +/// 日记管理 +class Logger { + static var isDebug: Bool = false + + fileprivate static let shared = Logger() + private init() { } + + fileprivate var dateString: String { Date().format(.full) } + + static var logs: [String] = [] +} + +extension Logger { + static func log(_ logs: Any..., line: Int = #line, separator: String = " ", terminator: String = "\n") { + objc_sync_enter(Logger.shared) + if Logger.isDebug { + print(Logger.shared.dateString, terminator: " [MSManager-\(String(format: "%03d", line))]: ") + print(logs, separator: separator, terminator: terminator) + let logString = Logger.shared.dateString + " [MSManager-\(String(format: "%03d", line))]: " + logs.map({ "\($0)" }).joined(separator: separator) + terminator + Self.logs.append(logString) + } + objc_sync_exit(Logger.shared) + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/String+MD5.swift b/MixSdk/MixSdk/MixSdk/Tools/String+MD5.swift new file mode 100644 index 0000000..0a651a5 --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/String+MD5.swift @@ -0,0 +1,35 @@ +// +// String+MD5.swift +// MixSdk +// +// Created by incar on 2024/6/13. +// + +import Foundation +import CommonCrypto +extension String { + /// 原生md5 + public var md5: String { + guard let data = data(using: .utf8) else { + return self + } + var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH)) + + #if swift(>=5.0) + + _ = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in + return CC_MD5(bytes.baseAddress, CC_LONG(data.count), &digest) + } + + #else + + _ = data.withUnsafeBytes { bytes in + return CC_MD5(bytes, CC_LONG(data.count), &digest) + } + + #endif + + return digest.map { String(format: "%02X", $0) }.joined() + + } +} diff --git a/MixSdk/MixSdk/MixSdk/Tools/UTF8.swift b/MixSdk/MixSdk/MixSdk/Tools/UTF8.swift new file mode 100644 index 0000000..e52689c --- /dev/null +++ b/MixSdk/MixSdk/MixSdk/Tools/UTF8.swift @@ -0,0 +1,16 @@ +// +// UTF8.swift +// MSManager +// +// Created by yaozuopan on 2024/3/6. +// + +import Foundation + + extension Data { + var string: String? { String(data: self, encoding: .utf8) } +} + + extension String { + var data: Data? { self.data(using: .utf8) } +} diff --git "a/document/Poly-SDK\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/document/Poly-SDK\346\216\245\345\217\243\346\226\207\346\241\243.md" new file mode 100644 index 0000000..f81c4d5 --- /dev/null +++ "b/document/Poly-SDK\346\216\245\345\217\243\346\226\207\346\241\243.md" @@ -0,0 +1,340 @@ +# Poly-SDK接口文档 + +## 修改记录: + +| 修改记录 | 修改人 | 时间 | +| -------- | ------ | ---------- | +| 初始版本 | 谢威 | 2024-06-08 | +| | | | +| | | | +| | | | + + + +## 引入依赖库 + +添加依赖项和配置: + +(1) 将Poly-SDK-xxx.aar包放入Module的libs中(如App中的libs)。 + +(2) 在需要依赖的Module中的build.gradle文件中添加: + +```java +dependencies { + implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs') + implementation 'com.google.code.gson:gson:2.10' + implementation "org.java-websocket:Java-WebSocket:1.5.1" +} +``` + +(3) 以上添加完后点击右上角的“Sync Now”进行构建即可 + +## 相关权限配置 + +//TODO:使用到的相关权限 + +```java + +``` + +## 混淆 + +```java +-keep class com.zhixun.android.sdk.polysdk.callback.*{*;} +-keep class com.zhixun.android.sdk.polysdk.entity.*{*;} +-keep class com.zhixun.android.sdk.polysdk.PolymerizeAgent{*;} +``` + + + +## 初始化 SDK + +- 初始化SDK + + ```java + public class xxx extends Application { + @Override + public void onCreate() { + super.onCreate(); + PolymerizeAgent.getInstance().init(this,true,true);//contxt、isdebug(是否打印日志)、issavelog(是否存储日志) + } + } + ``` + + + +## 鉴权(AuthenAPI) + +### 注意:需要鉴权成功才能进行AI 相关操作 + +![image-20240611172353324](C:\Users\89233\AppData\Roaming\Typora\typora-user-images\image-20240611172353324.png) + +### PolymerizeAgent.getInstance().getAuthenAPI() + +```java + + +//鉴权注册,authCallback + /** + * + * 注册时所需要的三元组信息: + productKey 产品Key(在物连网云平台里是bid) + secretKey 产品秘钥(在物连网云平台里是secret_key) + deviceId 设备ID(在物连网云平台里是设备ID) + * @param sn 设备sn号 + * @param authCallback onSuccess会返回鉴权所需deviceSecret, + */ + void regiest(String productKey, + String deviceId, + String sn,String secretKey,AuthCallback authCallback); + + /** + * + * productKey 产品Key(在物连网云平台里是bid) + secretKey 产品秘钥(在物连网云平台里是secret_key) + deviceId 设备ID(在物连网云平台里是设备ID) + * @param deviceSecret 注册返回的密码 + * @param authCallback onSuccess成功 onfail 失败 + */ + void authentication(String productKey,String deviceId + ,String deviceSecret,String secretKey,AuthCallback authCallback); + + //authCallback + public interface AuthCallback { + void onSuccess(String result); + void onFail(String msg); + } +``` + + + +## 翻译 + +### PolymerizeAgent.getInstance().getAiAPI() + +```java + /** + * 翻译 + * @param lang 需要翻译成的语言 code 例如en + * @param text 需要翻译的内容 + * @param aiRequestCallback onSuccess 返回翻译后的内容 String text = (String) result; + */ + void translate(String lang,String text,AIRequestCallback aiRequestCallback); + + /** + * 获取支持的语言 + * @param aiRequestCallback onSuccess 返回 List languages = (List) result; + */ + void getSupportLan(AIRequestCallback aiRequestCallback); + + +``` + + + +## AIGC + +### PolymerizeAgent.getInstance().getAiAPI() + +```java + /** + *获取aigc算法类型 + * @param type 0:⽂字⽣图,1: ⽂+图⽣图 5:图⽣图(⻛格变换) + * @param aiRequestCallback List aigcStyles = (List) result; + */ + void getAigcModeList(int type,AIRequestCallback aiRequestCallback); + + /** + *创建任务 + * @param aigcTask + * @param aiRequestCallback 返回String taskId = (String) result; + */ + void creatAigcImg(AigcTask aigcTask,AIRequestCallback aiRequestCallback); + + /** + *查询任务 + * @param type 0:⽂字⽣图,1: ⽂+图⽣图 5:图⽣图(⻛格变换) + * @param aiRequestCallback 返回String jsonStr = (String) result; + { + "status": "SUCCEEDED",//RUNNING FAIL + "task_id": "1706fbfd-8053-41d6-957f-0465b95e51e6", + "results": [ + { + "url": "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-06-03/0d2d5854-483d-4ea3-b888-bc497fcfddb7/20240603104723357435_style4_j9m54htwox.jpg?Expires=1717469251&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=xYIxXdXv1%2FGP6S%2F3kHfk%2F0dzs8E%3D" + } + + */ + void queryTaskState(String taskId,AIRequestCallback aiRequestCallback); +``` + + + +## 大模型对话 + +### PolymerizeAgent.getInstance().getAiAPI() + +```java + /** + * 发送文本信息 + * @param text + */ + void sendChatMsg(String text); + + /** + * 回复信息 + * @param text + */ + void setOnChatMsgListener(OnChatMsgListener onChatMsgListener); +``` + + + +## 实时转写 + +![image-20240611164347888](C:\Users\89233\AppData\Roaming\Typora\typora-user-images\image-20240611164347888.png) + +### PolymerizeAgent.getInstance().getAiAPI() + +```java + + /** + * 开始实时转写 format pcm,采样率16000 + * @param text + */ + void startTrans(); + + /** + * 结束实时转写 + * @param text + */ + void stopTrans(); + + /** + * 发送音频流 需startTrans以后 再调用 + * @param text + */ + void sendTransByte(byte[] data); + + /** + * onChange(String msg) 实时返回识别的内容 + * @param text + */ + void setOnTranscriptionDataChange(OnTranscriptionDataChange onTranscriptionDataChange); + + PolymerizeAgent.getInstance().getAiAPI().setOnTranscriptionDataChange(new OnTranscriptionDataChange() { + @Override + public void onChange(String msg) { + speedSb.append(msg); + Log.i(TAG,"onChange--"+msg); + + } + }); +``` + + + +## 语音合成 + +![image-20240611165613054](C:\Users\89233\AppData\Roaming\Typora\typora-user-images\image-20240611165613054.png) + +### PolymerizeAgent.getInstance().getAiAPI() + +```java + + /** + * 开始实时语音合成 format mp3,采样率8000 + */ + void startSynthesis(); + + /** + * 实时发送 需合成的内容 + * @param text + */ + void runSynthesis(String text); + /** + * 结束实时语音合成 + * + */ + void stopSynthesis(); + + /** + * 发送一次性长内容 语音合成,注意实时合成和一次性只能同时运行一个 + * @param text + */ + void sendLongTextStream(String text); + /** + * 合成语音回调 + * @param onTTSDataChange + */ + void setOnTTSDataChange(OnTTSDataChange onTTSDataChange); + PolymerizeAgent.getInstance().getAiAPI().setOnTTSDataChange(new OnTTSDataChange() { + @Override + public void onSynthesisChange(byte[] msg) { + Log.e(TAG,"实时语音合成--返回的音频流--"); + + } + + @Override + public void onLongTextStreamChange(byte[] msg) { + Log.e(TAG,"发送一次性长内容--返回的音频流--"); + } + }); +``` + + + +## AigcStyle类 + +```java + private String code;//类型code + private String name;//类型名称 + private String url; +``` + + + +## AigcTask类 + +```java + /*{ + "subject": "一只奔跑的猫", // type=5 参数不生效 + "url": "https://public-vigen-video.oss-cn-shanghai.aliyuncs.com/public/dashscope/test.png", // type=0 不需要提交url type=5 必须提交 + "type": 5, //0:⽂字⽣图,1: ⽂+图⽣图 5: 图⽣图(⻛格变换) + "amount": 2, //生成图片数量 + "height": 1024, + "width": 1024, + "algorithm": "" //算法id可⽤值⻅getstyle + }*/ + + private String subject;//需要的图片藐视 例如"一只奔跑的猫",type=5 参数不生效 + private String url;// type=0 不需要提交url type=5 必须提交 + private int type;//0:⽂字⽣图,1: ⽂+图⽣图 5: 图⽣图(⻛格变换) + private int amount;//⽣成的图⽚数量 type=5 参数不生效 + private int height;//⽣成的图⽚⾼度,type=1时需要是32的倍数。 type=5 参数不生效 + private int width;//⽣成的图⽚宽度,type=1时需要是32的倍数。 type=5 参数不生效 + private String algorithm;//算法code可⽤值⻅getstyle +``` + + + +## SupportLanguage类 + +```java + private String cn;//中文名称 + private String en;//英文名称 + private String code;//语言code +``` + + + +## AIRequestCallback类 + +```java +public interface AIRequestCallback { + //成功返回数据 根据具体请求返回result + void onSuccess(Object result); + //请求失败 + void onFail(String msg); +} +``` +