--- /dev/null
+// !$*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 = "<group>"; };
+ 18204BD52C193F9A00F94E69 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
+ 18204BD72C193F9A00F94E69 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+ 18204BDA2C193F9A00F94E69 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+ 18204BDC2C193F9D00F94E69 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+ 18204BDF2C193F9D00F94E69 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+ 18204BE12C193F9D00F94E69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 18204BE72C19417000F94E69 /* MixSdk.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = MixSdk.xcodeproj; path = ../MixSdk/MixSdk.xcodeproj; sourceTree = "<group>"; };
+/* 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 = "<group>";
+ };
+ 18204BD12C193F9A00F94E69 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 18204BD02C193F9A00F94E69 /* Example.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
+ 18204BE82C19417000F94E69 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 18204BEC2C19417000F94E69 /* MixSdk.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 18204BED2C19428100F94E69 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* 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 = "<group>";
+ };
+ 18204BDE2C193F9D00F94E69 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 18204BDF2C193F9D00F94E69 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "<group>";
+ };
+/* 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 */;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>SchemeUserState</key>
+ <dict>
+ <key>Example.xcscheme_^#shared#^_</key>
+ <dict>
+ <key>orderHint</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+</dict>
+</plist>
--- /dev/null
+//
+// 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<UISceneSession>) {
+ // 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.
+ }
+
+
+}
+
--- /dev/null
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
--- /dev/null
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
--- /dev/null
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="EHf-IW-A2E">
+ <objects>
+ <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="53" y="375"/>
+ </scene>
+ </scenes>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+ <device id="retina6_12" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="System colors in document resources" minToolsVersion="11.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="tne-QT-ifu">
+ <objects>
+ <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+ <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZOn-PK-K8d">
+ <rect key="frame" x="49" y="95" width="100" height="54"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <state key="normal" title="Button"/>
+ <buttonConfiguration key="configuration" style="gray" title="register">
+ <backgroundConfiguration key="background"/>
+ </buttonConfiguration>
+ <connections>
+ <action selector="registerAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="MjA-mA-eXX"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Iwj-0L-6nd">
+ <rect key="frame" x="259" y="170" width="100" height="54"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <state key="normal" title="Button"/>
+ <buttonConfiguration key="configuration" style="gray" title="通用翻译">
+ <backgroundConfiguration key="background"/>
+ </buttonConfiguration>
+ <connections>
+ <action selector="tranlateAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="r2v-DR-gSa"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="McA-22-96t">
+ <rect key="frame" x="206" y="95" width="100" height="54"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <state key="normal" title="Button"/>
+ <buttonConfiguration key="configuration" style="gray" title="login">
+ <backgroundConfiguration key="background"/>
+ </buttonConfiguration>
+ <connections>
+ <action selector="loginAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="kRm-ly-flg"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6wR-pv-u1r">
+ <rect key="frame" x="26" y="170" width="198" height="54"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <state key="normal" title="Button"/>
+ <buttonConfiguration key="configuration" style="gray" title="获取翻译支持语言列表">
+ <backgroundConfiguration key="background"/>
+ </buttonConfiguration>
+ <connections>
+ <action selector="getSupportLanguagesAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="s8U-yk-Edk"/>
+ </connections>
+ </button>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="119.84732824427481" y="3.5211267605633805"/>
+ </scene>
+ </scenes>
+ <resources>
+ <systemColor name="systemBackgroundColor">
+ <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
+ </resources>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>UIApplicationSceneManifest</key>
+ <dict>
+ <key>UIApplicationSupportsMultipleScenes</key>
+ <false/>
+ <key>UISceneConfigurations</key>
+ <dict>
+ <key>UIWindowSceneSessionRoleApplication</key>
+ <array>
+ <dict>
+ <key>UISceneConfigurationName</key>
+ <string>Default Configuration</string>
+ <key>UISceneDelegateClassName</key>
+ <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
+ <key>UISceneStoryboardFile</key>
+ <string>Main</string>
+ </dict>
+ </array>
+ </dict>
+ </dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+</dict>
+</plist>
--- /dev/null
+//
+// 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.
+ }
+
+
+}
+
--- /dev/null
+//
+// 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 ?? "")
+ }
+ }
+ }
+}
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "group:Example/Example.xcodeproj">
+ </FileRef>
+</Workspace>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+ uuid = "CEE9026F-0B36-4450-AB09-5A796FB97D62"
+ type = "0"
+ version = "2.0">
+</Bucket>
--- /dev/null
+// !$*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 = "<group>"; };
+ 181188312C1A8B5200C23FAB /* Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
+ 181188322C1A8B5200C23FAB /* Any.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Any.swift; sourceTree = "<group>"; };
+ 181188332C1A8B5200C23FAB /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
+ 181188342C1A8B5200C23FAB /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
+ 181188362C1A8B5200C23FAB /* UTF8.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UTF8.swift; sourceTree = "<group>"; };
+ 181188372C1A8B5200C23FAB /* CRC16.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CRC16.swift; sourceTree = "<group>"; };
+ 181188382C1A8B5200C23FAB /* LRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LRC.swift; sourceTree = "<group>"; };
+ 181188442C1AC35F00C23FAB /* MSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSError.swift; sourceTree = "<group>"; };
+ 181188462C1ACA6100C23FAB /* String+MD5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+MD5.swift"; sourceTree = "<group>"; };
+ 1811884D2C1AEF0F00C23FAB /* MSTranslate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSTranslate.swift; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 18204BC52C193E4B00F94E69 /* MSAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSAuth.swift; sourceTree = "<group>"; };
+ 18204BEF2C19457600F94E69 /* IBHttpManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IBHttpManager.swift; sourceTree = "<group>"; };
+ 18204BF22C19488800F94E69 /* StatusCode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = "<group>"; };
+ 18204BF32C19488800F94E69 /* SwiftHTTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwiftHTTP.h; sourceTree = "<group>"; };
+ 18204BF42C19488800F94E69 /* Request.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
+ 18204BF52C19488800F94E69 /* Upload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Upload.swift; sourceTree = "<group>"; };
+ 18204BF62C19488800F94E69 /* HTTPSecurity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPSecurity.swift; sourceTree = "<group>"; };
+ 18204BF72C19488800F94E69 /* Operation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operation.swift; sourceTree = "<group>"; };
+/* 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 = "<group>";
+ };
+ 18204BB12C193E3D00F94E69 = {
+ isa = PBXGroup;
+ children = (
+ 18204BBD2C193E3D00F94E69 /* MixSdk */,
+ 18204BBC2C193E3D00F94E69 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 18204BBC2C193E3D00F94E69 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 18204BBB2C193E3D00F94E69 /* MixSdk.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
+ 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 = "<group>";
+ };
+/* 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 */;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:">
+ </FileRef>
+</Workspace>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1500"
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "18204BBA2C193E3D00F94E69"
+ BuildableName = "MixSdk.framework"
+ BlueprintName = "MixSdk"
+ ReferencedContainer = "container:MixSdk.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Release"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "18204BBA2C193E3D00F94E69"
+ BuildableName = "MixSdk.framework"
+ BlueprintName = "MixSdk"
+ ReferencedContainer = "container:MixSdk.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>SchemeUserState</key>
+ <dict>
+ <key>MixSdk.xcscheme_^#shared#^_</key>
+ <dict>
+ <key>orderHint</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <key>SuppressBuildableAutocreation</key>
+ <dict>
+ <key>18204BBA2C193E3D00F94E69</key>
+ <dict>
+ <key>primary</key>
+ <true/>
+ </dict>
+ </dict>
+</dict>
+</plist>
--- /dev/null
+//
+// 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()
+ }
+
+
+}
+
+
--- /dev/null
+//
+// 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 ?? ""))
+ }
+ }
+ }
+}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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()
+}
--- /dev/null
+//
+// 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,"获取失败"))
+ }
+ }
+ }
+}
--- /dev/null
+//
+// MixSdk.h
+// MixSdk
+//
+// Created by incar on 2024/6/12.
+//
+
+#import <Foundation/Foundation.h>
+
+//! 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 <MixSdk/PublicHeader.h>
+
+
--- /dev/null
+//
+// 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<SSLCert>()
+ 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<SecKey>()
+ 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<Data>()
+ 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<SecCertificate>()
+ 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<Data> {
+ var collect = Array<Data>()
+ 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<SecKey> {
+ var collect = Array<SecKey>()
+ 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
+ }
+
+
+}
--- /dev/null
+//
+// 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<String,String>?
+ /// 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<Int,Response>()
+ //"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<String,String>
+ 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
+ }
+}
--- /dev/null
+//
+// 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<HTTPPair> {
+ var collect = Array<HTTPPair>()
+ 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
+ }
+}
--- /dev/null
+//
+// 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"
+ }
+ }
+ }
+}
--- /dev/null
+//
+// SwiftHTTP.h
+// SwiftHTTP
+//
+// Created by Austin Cherry on 9/16/14.
+// Copyright (c) 2014 Vluxe. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+//! 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 <SwiftHTTP/PublicHeader.h>
+
+
--- /dev/null
+//
+// 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
+ }
+}
--- /dev/null
+//
+// 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) }
+}
--- /dev/null
+//
+// 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..<length {
+ crcSum ^= Int(bytes[index])
+ for _ in 0..<8 {
+ if((crcSum & 0x0001) != 0) {
+ crcSum >>= 1
+ crcSum ^= polynomial
+ }else{
+ crcSum >>= 1
+ }
+ }
+ }
+ return crcSum
+ }
+}
--- /dev/null
+//
+// 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)
+ }
+}
--- /dev/null
+//
+// 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<T: Decodable>(_ 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<T: Decodable>(_ 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
+ }
+}
--- /dev/null
+//
+// 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
+ }
+}
+
+
--- /dev/null
+//
+// 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)
+ }
+}
--- /dev/null
+//
+// 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()
+
+ }
+}
--- /dev/null
+//
+// 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) }
+}
--- /dev/null
+# Poly-SDK接口文档\r
+\r
+## 修改记录:\r
+\r
+| 修改记录 | 修改人 | 时间 |\r
+| -------- | ------ | ---------- |\r
+| 初始版本 | 谢威 | 2024-06-08 |\r
+| | | |\r
+| | | |\r
+| | | |\r
+\r
+\r
+\r
+## 引入依赖库\r
+\r
+添加依赖项和配置:\r
+\r
+(1) 将Poly-SDK-xxx.aar包放入Module的libs中(如App中的libs)。\r
+\r
+(2) 在需要依赖的Module中的build.gradle文件中添加:\r
+\r
+```java\r
+dependencies {\r
+ implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs') \r
+ implementation 'com.google.code.gson:gson:2.10'\r
+ implementation "org.java-websocket:Java-WebSocket:1.5.1"\r
+}\r
+```\r
+\r
+(3) 以上添加完后点击右上角的“Sync Now”进行构建即可\r
+\r
+## 相关权限配置\r
+\r
+//TODO:使用到的相关权限\r
+\r
+```java\r
+ <uses-permission android:name="android.permission.INTERNET" />\r
+```\r
+\r
+## 混淆\r
+\r
+```java\r
+-keep class com.zhixun.android.sdk.polysdk.callback.*{*;}\r
+-keep class com.zhixun.android.sdk.polysdk.entity.*{*;}\r
+-keep class com.zhixun.android.sdk.polysdk.PolymerizeAgent{*;}\r
+```\r
+\r
+\r
+\r
+## 初始化 SDK\r
+\r
+- 初始化SDK\r
+\r
+ ```java\r
+ public class xxx extends Application {\r
+ @Override\r
+ public void onCreate() {\r
+ super.onCreate();\r
+ PolymerizeAgent.getInstance().init(this,true,true);//contxt、isdebug(是否打印日志)、issavelog(是否存储日志)\r
+ }\r
+ }\r
+ ```\r
+\r
+\r
+\r
+## 鉴权(AuthenAPI)\r
+\r
+### 注意:需要鉴权成功才能进行AI 相关操作\r
+\r
+\r
+\r
+### PolymerizeAgent.getInstance().getAuthenAPI()\r
+\r
+```java\r
+\r
+\r
+//鉴权注册,authCallback \r
+ /**\r
+ * \r
+ * 注册时所需要的三元组信息:\r
+ productKey 产品Key(在物连网云平台里是bid)\r
+ secretKey 产品秘钥(在物连网云平台里是secret_key)\r
+ deviceId 设备ID(在物连网云平台里是设备ID)\r
+ * @param sn 设备sn号\r
+ * @param authCallback onSuccess会返回鉴权所需deviceSecret,\r
+ */\r
+ void regiest(String productKey,\r
+ String deviceId,\r
+ String sn,String secretKey,AuthCallback authCallback);\r
+\r
+ /**\r
+ * \r
+ * productKey 产品Key(在物连网云平台里是bid)\r
+ secretKey 产品秘钥(在物连网云平台里是secret_key)\r
+ deviceId 设备ID(在物连网云平台里是设备ID)\r
+ * @param deviceSecret 注册返回的密码\r
+ * @param authCallback onSuccess成功 onfail 失败\r
+ */\r
+ void authentication(String productKey,String deviceId\r
+ ,String deviceSecret,String secretKey,AuthCallback authCallback);\r
+\r
+ //authCallback\r
+ public interface AuthCallback {\r
+ void onSuccess(String result);\r
+ void onFail(String msg);\r
+ }\r
+```\r
+\r
+\r
+\r
+## 翻译\r
+\r
+### PolymerizeAgent.getInstance().getAiAPI()\r
+\r
+```java\r
+ /**\r
+ * 翻译\r
+ * @param lang 需要翻译成的语言 code 例如en\r
+ * @param text 需要翻译的内容\r
+ * @param aiRequestCallback onSuccess 返回翻译后的内容 String text = (String) result;\r
+ */\r
+ void translate(String lang,String text,AIRequestCallback aiRequestCallback);\r
+\r
+ /**\r
+ * 获取支持的语言\r
+ * @param aiRequestCallback onSuccess 返回 List<SupportLanguage> languages = (List<SupportLanguage>) result;\r
+ */\r
+ void getSupportLan(AIRequestCallback aiRequestCallback);\r
+\r
+ \r
+```\r
+\r
+\r
+\r
+## AIGC\r
+\r
+### PolymerizeAgent.getInstance().getAiAPI()\r
+\r
+```java\r
+ /**\r
+ *获取aigc算法类型\r
+ * @param type 0:⽂字⽣图,1: ⽂+图⽣图 5:图⽣图(⻛格变换)\r
+ * @param aiRequestCallback List<AigcStyle> aigcStyles = (List<AigcStyle>) result;\r
+ */\r
+ void getAigcModeList(int type,AIRequestCallback aiRequestCallback);\r
+\r
+ /**\r
+ *创建任务\r
+ * @param aigcTask\r
+ * @param aiRequestCallback 返回String taskId = (String) result;\r
+ */\r
+ void creatAigcImg(AigcTask aigcTask,AIRequestCallback aiRequestCallback);\r
+\r
+ /**\r
+ *查询任务\r
+ * @param type 0:⽂字⽣图,1: ⽂+图⽣图 5:图⽣图(⻛格变换)\r
+ * @param aiRequestCallback 返回String jsonStr = (String) result;\r
+ {\r
+ "status": "SUCCEEDED",//RUNNING FAIL\r
+ "task_id": "1706fbfd-8053-41d6-957f-0465b95e51e6",\r
+ "results": [\r
+ {\r
+ "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"\r
+ }\r
+ \r
+ */\r
+ void queryTaskState(String taskId,AIRequestCallback aiRequestCallback);\r
+```\r
+\r
+\r
+\r
+## 大模型对话\r
+\r
+### PolymerizeAgent.getInstance().getAiAPI()\r
+\r
+```java\r
+ /**\r
+ * 发送文本信息\r
+ * @param text\r
+ */\r
+ void sendChatMsg(String text);\r
+\r
+ /**\r
+ * 回复信息\r
+ * @param text\r
+ */\r
+ void setOnChatMsgListener(OnChatMsgListener onChatMsgListener);\r
+```\r
+\r
+\r
+\r
+## 实时转写\r
+\r
+\r
+\r
+### PolymerizeAgent.getInstance().getAiAPI()\r
+\r
+```java\r
+ \r
+ /**\r
+ * 开始实时转写 format pcm,采样率16000\r
+ * @param text\r
+ */\r
+ void startTrans();\r
+ \r
+ /**\r
+ * 结束实时转写\r
+ * @param text\r
+ */\r
+ void stopTrans();\r
+\r
+ /**\r
+ * 发送音频流 需startTrans以后 再调用\r
+ * @param text\r
+ */\r
+ void sendTransByte(byte[] data);\r
+\r
+ /**\r
+ * onChange(String msg) 实时返回识别的内容\r
+ * @param text\r
+ */\r
+ void setOnTranscriptionDataChange(OnTranscriptionDataChange onTranscriptionDataChange);\r
+\r
+ PolymerizeAgent.getInstance().getAiAPI().setOnTranscriptionDataChange(new OnTranscriptionDataChange() {\r
+ @Override\r
+ public void onChange(String msg) {\r
+ speedSb.append(msg);\r
+ Log.i(TAG,"onChange--"+msg);\r
+ \r
+ }\r
+ });\r
+```\r
+\r
+\r
+\r
+## 语音合成\r
+\r
+\r
+\r
+### PolymerizeAgent.getInstance().getAiAPI()\r
+\r
+```java\r
+ \r
+ /**\r
+ * 开始实时语音合成 format mp3,采样率8000\r
+ */\r
+ void startSynthesis();\r
+\r
+ /**\r
+ * 实时发送 需合成的内容\r
+ * @param text\r
+ */\r
+ void runSynthesis(String text);\r
+ /**\r
+ * 结束实时语音合成\r
+ * \r
+ */\r
+ void stopSynthesis();\r
+ \r
+ /**\r
+ * 发送一次性长内容 语音合成,注意实时合成和一次性只能同时运行一个\r
+ * @param text\r
+ */\r
+ void sendLongTextStream(String text);\r
+ /**\r
+ * 合成语音回调\r
+ * @param onTTSDataChange\r
+ */\r
+ void setOnTTSDataChange(OnTTSDataChange onTTSDataChange);\r
+ PolymerizeAgent.getInstance().getAiAPI().setOnTTSDataChange(new OnTTSDataChange() {\r
+ @Override\r
+ public void onSynthesisChange(byte[] msg) {\r
+ Log.e(TAG,"实时语音合成--返回的音频流--");\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void onLongTextStreamChange(byte[] msg) {\r
+ Log.e(TAG,"发送一次性长内容--返回的音频流--");\r
+ }\r
+ });\r
+```\r
+\r
+\r
+\r
+## AigcStyle类\r
+\r
+```java\r
+ private String code;//类型code\r
+ private String name;//类型名称\r
+ private String url;\r
+```\r
+\r
+\r
+\r
+## AigcTask类\r
+\r
+```java\r
+ /*{\r
+ "subject": "一只奔跑的猫", // type=5 参数不生效\r
+ "url": "https://public-vigen-video.oss-cn-shanghai.aliyuncs.com/public/dashscope/test.png", // type=0 不需要提交url type=5 必须提交\r
+ "type": 5, //0:⽂字⽣图,1: ⽂+图⽣图 5: 图⽣图(⻛格变换)\r
+ "amount": 2, //生成图片数量\r
+ "height": 1024, \r
+ "width": 1024, \r
+ "algorithm": "" //算法id可⽤值⻅getstyle\r
+ }*/\r
+\r
+ private String subject;//需要的图片藐视 例如"一只奔跑的猫",type=5 参数不生效\r
+ private String url;// type=0 不需要提交url type=5 必须提交\r
+ private int type;//0:⽂字⽣图,1: ⽂+图⽣图 5: 图⽣图(⻛格变换)\r
+ private int amount;//⽣成的图⽚数量 type=5 参数不生效\r
+ private int height;//⽣成的图⽚⾼度,type=1时需要是32的倍数。 type=5 参数不生效\r
+ private int width;//⽣成的图⽚宽度,type=1时需要是32的倍数。 type=5 参数不生效\r
+ private String algorithm;//算法code可⽤值⻅getstyle\r
+```\r
+\r
+\r
+\r
+## SupportLanguage类\r
+\r
+```java\r
+ private String cn;//中文名称\r
+ private String en;//英文名称\r
+ private String code;//语言code\r
+```\r
+\r
+\r
+\r
+## AIRequestCallback类\r
+\r
+```java\r
+public interface AIRequestCallback {\r
+ //成功返回数据 根据具体请求返回result\r
+ void onSuccess(Object result);\r
+ //请求失败\r
+ void onFail(String msg);\r
+}\r
+```\r
+\r