This commit is contained in:
DDIsFriend
2023-08-23 09:24:40 +08:00
parent 6bd037c5dd
commit 63ca919ed5
494 changed files with 35308 additions and 6623 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -37,6 +37,9 @@
794FBB162A8F1A3300D57BB8 /* RescuePhotoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB152A8F1A3300D57BB8 /* RescuePhotoController.swift */; };
794FBB192A8F4AF000D57BB8 /* MessageCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB182A8F4AF000D57BB8 /* MessageCount.swift */; };
794FBB1C2A8F4DE900D57BB8 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB1B2A8F4DE900D57BB8 /* MessageView.swift */; };
794FBB1F2A92F7C300D57BB8 /* WebViewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB1E2A92F7C300D57BB8 /* WebViewTool.swift */; };
794FBB212A934E0A00D57BB8 /* AppUpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB202A934E0A00D57BB8 /* AppUpdateView.swift */; };
794FBB232A93519800D57BB8 /* AppUpdateTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 794FBB222A93519800D57BB8 /* AppUpdateTool.swift */; };
79CECC122A89BD1A00B95D8B /* MessageCenterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC112A89BD1A00B95D8B /* MessageCenterController.swift */; };
79CECC192A89EE6A00B95D8B /* ReviewFailedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC182A89EE6A00B95D8B /* ReviewFailedController.swift */; };
79CECC1B2A89F83800B95D8B /* AdditionalPhotoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC1A2A89F83800B95D8B /* AdditionalPhotoController.swift */; };
@@ -44,6 +47,10 @@
79CECC242A8B16D400B95D8B /* VehicleMonitoringListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC232A8B16D400B95D8B /* VehicleMonitoringListController.swift */; };
79CECC262A8C749B00B95D8B /* VehicleMonitorVideoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC252A8C749B00B95D8B /* VehicleMonitorVideoController.swift */; };
79CECC282A8CADEA00B95D8B /* VehicleMonitoringVideoDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC272A8CADEA00B95D8B /* VehicleMonitoringVideoDetailController.swift */; };
79DD0DA82A9480D000768FE7 /* NotificationAuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79DD0DA72A9480D000768FE7 /* NotificationAuthView.swift */; };
79DD0DAA2A9481BC00768FE7 /* NotificationAuthTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79DD0DA92A9481BC00768FE7 /* NotificationAuthTool.swift */; };
79DD0DAD2A94A0EE00768FE7 /* LaunchImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 79DD0DAC2A94A0EE00768FE7 /* LaunchImage.png */; };
79DD0DB12A94B3DB00768FE7 /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79DD0DB02A94B3DB00768FE7 /* EmptyView.swift */; };
79EAD8142A7B86610036E093 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 79EAD8132A7B86610036E093 /* Assets.xcassets */; };
79EAD8172A7B86610036E093 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 79EAD8152A7B86610036E093 /* LaunchScreen.storyboard */; };
A64E95F00B82DC28C2B9306E /* libPods-OrderScheduling.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98784A61C325B3D6C408016C /* libPods-OrderScheduling.a */; };
@@ -80,6 +87,9 @@
794FBB152A8F1A3300D57BB8 /* RescuePhotoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RescuePhotoController.swift; sourceTree = "<group>"; };
794FBB182A8F4AF000D57BB8 /* MessageCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCount.swift; sourceTree = "<group>"; };
794FBB1B2A8F4DE900D57BB8 /* MessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = "<group>"; };
794FBB1E2A92F7C300D57BB8 /* WebViewTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewTool.swift; sourceTree = "<group>"; };
794FBB202A934E0A00D57BB8 /* AppUpdateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateView.swift; sourceTree = "<group>"; };
794FBB222A93519800D57BB8 /* AppUpdateTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdateTool.swift; sourceTree = "<group>"; };
79C638864A659A427FCD5391 /* Pods-OrderScheduling.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrderScheduling.debug.xcconfig"; path = "Target Support Files/Pods-OrderScheduling/Pods-OrderScheduling.debug.xcconfig"; sourceTree = "<group>"; };
79CECC112A89BD1A00B95D8B /* MessageCenterController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCenterController.swift; sourceTree = "<group>"; };
79CECC182A89EE6A00B95D8B /* ReviewFailedController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewFailedController.swift; sourceTree = "<group>"; };
@@ -88,7 +98,6 @@
79CECC232A8B16D400B95D8B /* VehicleMonitoringListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleMonitoringListController.swift; sourceTree = "<group>"; };
79CECC252A8C749B00B95D8B /* VehicleMonitorVideoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleMonitorVideoController.swift; sourceTree = "<group>"; };
79CECC272A8CADEA00B95D8B /* VehicleMonitoringVideoDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleMonitoringVideoDetailController.swift; sourceTree = "<group>"; };
79CECC2B2A8CBD0B00B95D8B /* OrderScheduling-Bridge-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OrderScheduling-Bridge-Header.h"; sourceTree = "<group>"; };
79CECC9D2A8E03C200B95D8B /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
79CECC9F2A8E03CF00B95D8B /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
79CECCA12A8E03D900B95D8B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@@ -104,6 +113,13 @@
79CECCB52A8E04EF00B95D8B /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
79CECCB62A8E04FA00B95D8B /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
79CECCB72A8E050200B95D8B /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
79DD0DA12A94501500768FE7 /* OrderScheduling-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OrderScheduling-Bridging-Header.h"; sourceTree = "<group>"; };
79DD0DA52A945D9E00768FE7 /* OrderSchedulingRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OrderSchedulingRelease.entitlements; sourceTree = "<group>"; };
79DD0DA62A946B2500768FE7 /* OrderSchedulingDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OrderSchedulingDebug.entitlements; sourceTree = "<group>"; };
79DD0DA72A9480D000768FE7 /* NotificationAuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationAuthView.swift; sourceTree = "<group>"; };
79DD0DA92A9481BC00768FE7 /* NotificationAuthTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationAuthTool.swift; sourceTree = "<group>"; };
79DD0DAC2A94A0EE00768FE7 /* LaunchImage.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = LaunchImage.png; sourceTree = "<group>"; };
79DD0DB02A94B3DB00768FE7 /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = "<group>"; };
79EAD8072A7B86600036E093 /* OrderScheduling.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OrderScheduling.app; sourceTree = BUILT_PRODUCTS_DIR; };
79EAD8132A7B86610036E093 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
79EAD8162A7B86610036E093 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
@@ -132,7 +148,7 @@
791887442A7CD05B007EA0C1 /* MainTabBarController.swift */,
7918877A2A7CDD1A007EA0C1 /* Initial.swift */,
7918878A2A7CE9E0007EA0C1 /* main.swift */,
79CECC2B2A8CBD0B00B95D8B /* OrderScheduling-Bridge-Header.h */,
79DD0DA12A94501500768FE7 /* OrderScheduling-Bridging-Header.h */,
);
path = Main;
sourceTree = "<group>";
@@ -239,18 +255,18 @@
isa = PBXGroup;
children = (
794FBB1A2A8F4DDD00D57BB8 /* View */,
794FBB172A8F4ADD00D57BB8 /* MessageCount */,
791887932A80C351007EA0C1 /* Controller */,
791887932A80C351007EA0C1 /* WebView */,
);
path = Common;
sourceTree = "<group>";
};
791887932A80C351007EA0C1 /* Controller */ = {
791887932A80C351007EA0C1 /* WebView */ = {
isa = PBXGroup;
children = (
791887942A80C361007EA0C1 /* WebViewController.swift */,
794FBB1E2A92F7C300D57BB8 /* WebViewTool.swift */,
);
path = Controller;
path = WebView;
sourceTree = "<group>";
};
7918879D2A80CA10007EA0C1 /* HttpRequestCenter */ = {
@@ -384,18 +400,16 @@
path = Reactor;
sourceTree = "<group>";
};
794FBB172A8F4ADD00D57BB8 /* MessageCount */ = {
isa = PBXGroup;
children = (
794FBB182A8F4AF000D57BB8 /* MessageCount.swift */,
);
path = MessageCount;
sourceTree = "<group>";
};
794FBB1A2A8F4DDD00D57BB8 /* View */ = {
isa = PBXGroup;
children = (
794FBB1B2A8F4DE900D57BB8 /* MessageView.swift */,
794FBB182A8F4AF000D57BB8 /* MessageCount.swift */,
794FBB202A934E0A00D57BB8 /* AppUpdateView.swift */,
794FBB222A93519800D57BB8 /* AppUpdateTool.swift */,
79DD0DA72A9480D000768FE7 /* NotificationAuthView.swift */,
79DD0DA92A9481BC00768FE7 /* NotificationAuthTool.swift */,
79DD0DB02A94B3DB00768FE7 /* EmptyView.swift */,
);
path = View;
sourceTree = "<group>";
@@ -524,6 +538,14 @@
path = Reactor;
sourceTree = "<group>";
};
79DD0DAB2A94A0EE00768FE7 /* Source */ = {
isa = PBXGroup;
children = (
79DD0DAC2A94A0EE00768FE7 /* LaunchImage.png */,
);
path = Source;
sourceTree = "<group>";
};
79EAD7FE2A7B86600036E093 = {
isa = PBXGroup;
children = (
@@ -545,6 +567,8 @@
79EAD8092A7B86600036E093 /* OrderScheduling */ = {
isa = PBXGroup;
children = (
79DD0DA62A946B2500768FE7 /* OrderSchedulingDebug.entitlements */,
79DD0DA52A945D9E00768FE7 /* OrderSchedulingRelease.entitlements */,
794FBB0E2A8F044F00D57BB8 /* Mine */,
794FBB072A8F03D200D57BB8 /* History */,
79CECC1C2A8A2A1600B95D8B /* VehicleMonitoring */,
@@ -559,6 +583,7 @@
7918877C2A7CE57D007EA0C1 /* Strings */,
791887732A7CD633007EA0C1 /* Rescue */,
7918873F2A7CCCCD007EA0C1 /* Main */,
79DD0DAB2A94A0EE00768FE7 /* Source */,
79EAD8132A7B86610036E093 /* Assets.xcassets */,
79EAD8152A7B86610036E093 /* LaunchScreen.storyboard */,
79EAD8182A7B86610036E093 /* Info.plist */,
@@ -632,6 +657,7 @@
TargetAttributes = {
79EAD8062A7B86600036E093 = {
CreatedOnToolsVersion = 14.3.1;
LastSwiftMigration = 1430;
};
};
};
@@ -660,6 +686,7 @@
files = (
79EAD8172A7B86610036E093 /* LaunchScreen.storyboard in Resources */,
79EAD8142A7B86610036E093 /* Assets.xcassets in Resources */,
79DD0DAD2A94A0EE00768FE7 /* LaunchImage.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -712,6 +739,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
794FBB232A93519800D57BB8 /* AppUpdateTool.swift in Sources */,
79CECC242A8B16D400B95D8B /* VehicleMonitoringListController.swift in Sources */,
791887BD2A83952D007EA0C1 /* Entry.swift in Sources */,
791887952A80C361007EA0C1 /* WebViewController.swift in Sources */,
@@ -724,7 +752,11 @@
7918878B2A7CE9E0007EA0C1 /* main.swift in Sources */,
791887A02A80CA10007EA0C1 /* RequestList.swift in Sources */,
79CECC262A8C749B00B95D8B /* VehicleMonitorVideoController.swift in Sources */,
79DD0DA82A9480D000768FE7 /* NotificationAuthView.swift in Sources */,
794FBB212A934E0A00D57BB8 /* AppUpdateView.swift in Sources */,
791887802A7CE6F1007EA0C1 /* UserDefaultStrings.swift in Sources */,
79DD0DB12A94B3DB00768FE7 /* EmptyView.swift in Sources */,
79DD0DAA2A9481BC00768FE7 /* NotificationAuthTool.swift in Sources */,
794FBB1C2A8F4DE900D57BB8 /* MessageView.swift in Sources */,
794FBB142A8F045F00D57BB8 /* MineController.swift in Sources */,
791887432A7CCCCD007EA0C1 /* SceneDelegate.swift in Sources */,
@@ -743,6 +775,7 @@
791887452A7CD05B007EA0C1 /* MainTabBarController.swift in Sources */,
791887792A7CD64C007EA0C1 /* RescueController.swift in Sources */,
79CECC122A89BD1A00B95D8B /* MessageCenterController.swift in Sources */,
794FBB1F2A92F7C300D57BB8 /* WebViewTool.swift in Sources */,
791887822A7CE71D007EA0C1 /* AppKeyStrings.swift in Sources */,
79CECC282A8CADEA00B95D8B /* VehicleMonitoringVideoDetailController.swift in Sources */,
791887A12A80CA10007EA0C1 /* ApiList.swift in Sources */,
@@ -886,9 +919,12 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = OrderScheduling/OrderSchedulingDebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = W4SG324NS4;
DEVELOPMENT_TEAM = X9WF5T89LV;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited)";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -911,12 +947,15 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.dezhong.boss;
PRODUCT_BUNDLE_IDENTIFIER = com.sino.supplier;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "OrderScheduling/Main/OrderScheduling-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
@@ -928,9 +967,11 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = OrderScheduling/OrderSchedulingRelease.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = W4SG324NS4;
DEVELOPMENT_TEAM = X9WF5T89LV;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/OrderScheduling/Player/Classes/ijkplayer",
@@ -952,12 +993,13 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.dezhong.boss;
PRODUCT_BUNDLE_IDENTIFIER = com.sino.supplier;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "OrderScheduling/Main/OrderScheduling-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};

View File

@@ -46,8 +46,8 @@
filePath = "OrderScheduling/Login/ViewController/LoginController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "222"
endingLineNumber = "222"
startingLineNumber = "229"
endingLineNumber = "229"
landmarkName = "textView(_:shouldInteractWith:in:interaction:)"
landmarkType = "7">
</BreakpointContent>
@@ -62,8 +62,8 @@
filePath = "OrderScheduling/Login/ViewController/LoginController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "226"
endingLineNumber = "226"
startingLineNumber = "233"
endingLineNumber = "233"
landmarkName = "textView(_:shouldInteractWith:in:interaction:)"
landmarkType = "7">
</BreakpointContent>
@@ -253,8 +253,8 @@
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "88"
endingLineNumber = "88"
startingLineNumber = "96"
endingLineNumber = "96"
landmarkName = "networkErrorHandler(response:)"
landmarkType = "7">
</BreakpointContent>
@@ -269,8 +269,8 @@
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "89"
endingLineNumber = "89"
startingLineNumber = "97"
endingLineNumber = "97"
landmarkName = "networkErrorHandler(response:)"
landmarkType = "7">
<Locations>
@@ -317,8 +317,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "469"
endingLineNumber = "469"
startingLineNumber = "481"
endingLineNumber = "481"
landmarkName = "tableView(_:cellForRowAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -333,8 +333,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "470"
endingLineNumber = "470"
startingLineNumber = "482"
endingLineNumber = "482"
landmarkName = "tableView(_:cellForRowAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -507,8 +507,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "551"
endingLineNumber = "551"
startingLineNumber = "563"
endingLineNumber = "563"
landmarkName = "tableView(_:cellForRowAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -523,8 +523,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "552"
endingLineNumber = "552"
startingLineNumber = "564"
endingLineNumber = "564"
landmarkName = "tableView(_:cellForRowAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -555,8 +555,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "672"
endingLineNumber = "672"
startingLineNumber = "701"
endingLineNumber = "701"
landmarkName = "collectionView(_:cellForItemAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -571,8 +571,8 @@
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "673"
endingLineNumber = "673"
startingLineNumber = "702"
endingLineNumber = "702"
landmarkName = "collectionView(_:cellForItemAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -714,8 +714,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "114"
endingLineNumber = "114"
startingLineNumber = "130"
endingLineNumber = "130"
landmarkName = "reloadCell(models:isPaiban:isAlarm:)"
landmarkType = "7">
</BreakpointContent>
@@ -746,8 +746,8 @@
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "105"
endingLineNumber = "105"
startingLineNumber = "113"
endingLineNumber = "113"
landmarkName = "errorCodeHandler(response:)"
landmarkType = "7">
</BreakpointContent>
@@ -762,28 +762,28 @@
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "108"
endingLineNumber = "108"
landmarkName = "errorCodeHandler(response:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "408F05CB-F217-4CEC-B810-196A4D68A42B"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "116"
endingLineNumber = "116"
landmarkName = "errorCodeHandler(response:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "408F05CB-F217-4CEC-B810-196A4D68A42B"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/Initial.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "124"
endingLineNumber = "124"
landmarkName = "errorCodeHandler(response:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@@ -794,8 +794,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "271"
endingLineNumber = "271"
startingLineNumber = "313"
endingLineNumber = "313"
landmarkName = "dd_mapView(_:viewFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -810,8 +810,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "249"
endingLineNumber = "249"
startingLineNumber = "291"
endingLineNumber = "291"
landmarkName = "dd_mapView(_:viewFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -826,8 +826,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "251"
endingLineNumber = "251"
startingLineNumber = "293"
endingLineNumber = "293"
landmarkName = "dd_mapView(_:viewFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -842,8 +842,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "397"
endingLineNumber = "397"
startingLineNumber = "439"
endingLineNumber = "439"
landmarkName = "categoryView(_:didScrollSelectedItemAt:)"
landmarkType = "7">
</BreakpointContent>
@@ -858,8 +858,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "277"
endingLineNumber = "277"
startingLineNumber = "319"
endingLineNumber = "319"
landmarkName = "dd_mapView(_:viewFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -874,8 +874,8 @@
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "276"
endingLineNumber = "276"
startingLineNumber = "318"
endingLineNumber = "318"
landmarkName = "dd_mapView(_:viewFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -938,8 +938,8 @@
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "20"
endingLineNumber = "20"
startingLineNumber = "37"
endingLineNumber = "37"
landmarkName = "application(_:supportedInterfaceOrientationsFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -954,8 +954,8 @@
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "21"
endingLineNumber = "21"
startingLineNumber = "38"
endingLineNumber = "38"
landmarkName = "application(_:supportedInterfaceOrientationsFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -970,8 +970,8 @@
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "23"
endingLineNumber = "23"
startingLineNumber = "40"
endingLineNumber = "40"
landmarkName = "application(_:supportedInterfaceOrientationsFor:)"
landmarkType = "7">
</BreakpointContent>
@@ -1200,5 +1200,675 @@
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "6A2DFD62-CA08-4B3A-BB54-D20A4C3D6469"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "66"
endingLineNumber = "66"
landmarkName = "addActions()"
landmarkType = "7">
<Locations>
<Location
uuid = "6A2DFD62-CA08-4B3A-BB54-D20A4C3D6469 - 34751609f5ed8897"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #4 (__C.UITapGestureRecognizer) -&gt; () in OrderScheduling.RescueController.addActions() -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "67"
endingLineNumber = "67"
offsetFromSymbolStart = "88">
</Location>
<Location
uuid = "6A2DFD62-CA08-4B3A-BB54-D20A4C3D6469 - 34751609f5ed88b6"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "closure #4 (__C.UITapGestureRecognizer) -&gt; () in OrderScheduling.RescueController.addActions() -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Rescue/ViewController/RescueController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "68"
endingLineNumber = "68"
offsetFromSymbolStart = "88">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "8C597888-D26F-4E1A-8EC0-DD9FE597EC25"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/WebView/WebViewTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "52"
endingLineNumber = "52"
landmarkName = "init()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DBF4CEA9-9E44-445D-8B2C-B35CD61D5AE1"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/View/AppUpdateTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "40"
endingLineNumber = "40"
landmarkName = "init()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "0702569E-F568-4FD2-9067-4E8D3CA96B0C"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/View/AppUpdateTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "107"
endingLineNumber = "107"
landmarkName = "shouldPresentEntry()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "1EAB411A-31C0-4363-B3F8-0250E09484C0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/View/AppUpdateTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "109"
endingLineNumber = "109"
landmarkName = "shouldPresentEntry()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "A86AA3E3-EF95-405C-896C-93A4C36C8E94"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/View/AppUpdateTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "32"
endingLineNumber = "32"
landmarkName = "setIgnoreFlag(ignoreFlag:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "84B06068-34C1-42A6-B483-140F25ABF3F7"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/View/AppUpdateTool.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "100"
endingLineNumber = "100"
landmarkName = "canUpdate(localVersion:onlineVersion:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "2C6B429B-5D9C-42AC-AF5D-B35905E69AF3"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/WebView/WebViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "92"
endingLineNumber = "92"
landmarkName = "userContentController(_:didReceive:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "51A09AA2-8E9F-4EDF-A31D-F456568C84A2"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Common/WebView/WebViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "96"
endingLineNumber = "96"
landmarkName = "userContentController(_:didReceive:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "6043A19F-FEA4-44B7-BAC8-98339955AF0A"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "62"
endingLineNumber = "62"
landmarkName = "application(_:didRegisterForRemoteNotificationsWithDeviceToken:)"
landmarkType = "7">
<Locations>
<Location
uuid = "6043A19F-FEA4-44B7-BAC8-98339955AF0A - e7c967a0298824cb"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.application(_: __C.UIApplication, didRegisterForRemoteNotificationsWithDeviceToken: Foundation.Data) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "50"
endingLineNumber = "50"
offsetFromSymbolStart = "1028">
</Location>
<Location
uuid = "6043A19F-FEA4-44B7-BAC8-98339955AF0A - e7c967a0298824cb"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.application(_: __C.UIApplication, didRegisterForRemoteNotificationsWithDeviceToken: Foundation.Data) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "50"
endingLineNumber = "50"
offsetFromSymbolStart = "1012">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3999ECF4-6836-4D27-99A3-7A8D5F9EF7CA"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Login/ViewController/LoginController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "147"
endingLineNumber = "147"
landmarkName = "addActions()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "A4AB261C-23A1-4E06-9DEF-C27FB6D7E55C"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "353"
endingLineNumber = "353"
landmarkName = "listContainerView(_:initListFor:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "E7562F84-F178-4518-B7E4-03C58B0C7A91"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "177"
endingLineNumber = "177"
landmarkName = "addAction()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "F8ECE186-F9F8-4A78-8C33-592365C104F0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "178"
endingLineNumber = "178"
landmarkName = "addAction()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "E2DCBA6D-6204-4F85-8ABF-A79302F049A2"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "68"
endingLineNumber = "68"
landmarkName = "tabBar(_:didSelect:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "D1708B2A-C5B4-4B40-9ECC-D648808E0F32"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "60"
endingLineNumber = "60"
landmarkName = "tabBar(_:didSelect:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "06C1367A-8041-4B21-981D-DAE1DB8A3EEE"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "62"
endingLineNumber = "62"
landmarkName = "tabBar(_:didSelect:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "36C549E3-0690-4ECF-9C0C-6D59D605762D"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "50"
endingLineNumber = "50"
landmarkName = "tabBarController(_:didSelect:)"
landmarkType = "7">
<Locations>
<Location
uuid = "36C549E3-0690-4ECF-9C0C-6D59D605762D - 240e3735f5c08bf7"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.MainTabBarController.tabBarController(_: __C.UITabBarController, didSelect: __C.UIViewController) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "49"
endingLineNumber = "49"
offsetFromSymbolStart = "524">
</Location>
<Location
uuid = "36C549E3-0690-4ECF-9C0C-6D59D605762D - 240e3735f5c08bf7"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.MainTabBarController.tabBarController(_: __C.UITabBarController, didSelect: __C.UIViewController) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "49"
endingLineNumber = "49"
offsetFromSymbolStart = "664">
</Location>
<Location
uuid = "36C549E3-0690-4ECF-9C0C-6D59D605762D - 240e3735f5c08b14"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.MainTabBarController.tabBarController(_: __C.UITabBarController, didSelect: __C.UIViewController) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "50"
endingLineNumber = "50"
offsetFromSymbolStart = "164">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "C81B7742-6AA9-45D7-A23A-CE72DDE13F26"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/MainTabBarController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "52"
endingLineNumber = "52"
landmarkName = "tabBarController(_:didSelect:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "2F438D4C-F5EF-4A0B-8B1C-1E84A0BF5854"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "127"
endingLineNumber = "127"
landmarkName = "reloadCell(models:isPaiban:isAlarm:)"
landmarkType = "7">
<Locations>
<Location
uuid = "2F438D4C-F5EF-4A0B-8B1C-1E84A0BF5854 - d1cd717f0f11f993"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.VehicleMonitoringListController.reloadCell(models: Swift.Optional&lt;Swift.Array&lt;OrderScheduling.VehicleMonitorListDataModel.ItemModel&gt;&gt;, isPaiban: Swift.Optional&lt;Swift.Bool&gt;, isAlarm: Swift.Optional&lt;Swift.Bool&gt;) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "127"
endingLineNumber = "127"
offsetFromSymbolStart = "564">
</Location>
<Location
uuid = "2F438D4C-F5EF-4A0B-8B1C-1E84A0BF5854 - d1cd717f0f11f993"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.VehicleMonitoringListController.reloadCell(models: Swift.Optional&lt;Swift.Array&lt;OrderScheduling.VehicleMonitorListDataModel.ItemModel&gt;&gt;, isPaiban: Swift.Optional&lt;Swift.Bool&gt;, isAlarm: Swift.Optional&lt;Swift.Bool&gt;) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "127"
endingLineNumber = "127"
offsetFromSymbolStart = "576">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "F36A8846-3BDC-4242-83B5-61E332C93611"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "125"
endingLineNumber = "125"
landmarkName = "reloadCell(models:isPaiban:isAlarm:)"
landmarkType = "7">
<Locations>
<Location
uuid = "F36A8846-3BDC-4242-83B5-61E332C93611 - d1cd717f0f11f95d"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.VehicleMonitoringListController.reloadCell(models: Swift.Optional&lt;Swift.Array&lt;OrderScheduling.VehicleMonitorListDataModel.ItemModel&gt;&gt;, isPaiban: Swift.Optional&lt;Swift.Bool&gt;, isAlarm: Swift.Optional&lt;Swift.Bool&gt;) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "125"
endingLineNumber = "125"
offsetFromSymbolStart = "400">
</Location>
<Location
uuid = "F36A8846-3BDC-4242-83B5-61E332C93611 - d1cd717f0f11f95d"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.VehicleMonitoringListController.reloadCell(models: Swift.Optional&lt;Swift.Array&lt;OrderScheduling.VehicleMonitorListDataModel.ItemModel&gt;&gt;, isPaiban: Swift.Optional&lt;Swift.Bool&gt;, isAlarm: Swift.Optional&lt;Swift.Bool&gt;) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "125"
endingLineNumber = "125"
offsetFromSymbolStart = "532">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "4D9B5DEE-D39F-46E6-A1EC-CEDB6C443D74"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringListController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "117"
endingLineNumber = "117"
landmarkName = "reloadCell(models:isPaiban:isAlarm:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "D7A2EF3A-2FB8-49BE-8A7C-A93AB3BCF461"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "112"
endingLineNumber = "112"
landmarkName = "jpushNotificationCenter(_:willPresent:withCompletionHandler:)"
landmarkType = "7">
<Locations>
<Location
uuid = "D7A2EF3A-2FB8-49BE-8A7C-A93AB3BCF461 - 80f31cf5eda31718"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.jpushNotificationCenter(_: __C.UNUserNotificationCenter, willPresent: __C.UNNotification, withCompletionHandler: (Swift.Int) -&gt; ()) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "100"
endingLineNumber = "100"
offsetFromSymbolStart = "612">
</Location>
<Location
uuid = "D7A2EF3A-2FB8-49BE-8A7C-A93AB3BCF461 - 80f31cf5eda31684"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.jpushNotificationCenter(_: __C.UNUserNotificationCenter, willPresent: __C.UNNotification, withCompletionHandler: (Swift.Int) -&gt; ()) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "112"
endingLineNumber = "112"
offsetFromSymbolStart = "624">
</Location>
<Location
uuid = "D7A2EF3A-2FB8-49BE-8A7C-A93AB3BCF461 - 80f31cf5eda31684"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.jpushNotificationCenter(_: __C.UNUserNotificationCenter, willPresent: __C.UNNotification, withCompletionHandler: (Swift.Int) -&gt; ()) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "112"
endingLineNumber = "112"
offsetFromSymbolStart = "716">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "0AB5E12D-53CA-429C-8322-7C8342D48DEC"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "110"
endingLineNumber = "110"
landmarkName = "jpushNotificationCenter(_:willPresent:withCompletionHandler:)"
landmarkType = "7">
<Locations>
<Location
uuid = "0AB5E12D-53CA-429C-8322-7C8342D48DEC - 80f31cf5eda314da"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.jpushNotificationCenter(_: __C.UNUserNotificationCenter, willPresent: __C.UNNotification, withCompletionHandler: (Swift.Int) -&gt; ()) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "98"
endingLineNumber = "98"
offsetFromSymbolStart = "276">
</Location>
<Location
uuid = "0AB5E12D-53CA-429C-8322-7C8342D48DEC - 80f31cf5eda31646"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "OrderScheduling.AppDelegate.jpushNotificationCenter(_: __C.UNUserNotificationCenter, willPresent: __C.UNNotification, withCompletionHandler: (Swift.Int) -&gt; ()) -&gt; ()"
moduleName = "OrderScheduling"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/zd/Desktop/%E4%B8%AD%E9%81%93%E6%95%91%E6%8F%B4/OrderScheduling/OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "110"
endingLineNumber = "110"
offsetFromSymbolStart = "268">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DC6A4772-1EB9-4787-98E6-B4D96EAFEFFA"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "132"
endingLineNumber = "132"
landmarkName = "jpushNotificationAuthorization(_:withInfo:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "CFCD4B6D-6F9B-4A1C-97F9-7EADFA549A6F"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OrderScheduling/Main/AppDelegate.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "120"
endingLineNumber = "120"
landmarkName = "jpushNotificationCenter(_:didReceive:withCompletionHandler:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

Binary file not shown.

View File

@@ -1,11 +0,0 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,6 +1,7 @@
{
"images" : [
{
"filename" : "icon-1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "noData_image.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "noData_image@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "noData_image@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,8 +1,10 @@
<?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">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -11,10 +13,21 @@
<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"/>
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LaunchImage.png" translatesAutoresizingMaskIntoConstraints="NO" id="afd-7Z-uCQ">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="afd-7Z-uCQ" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="9IV-E2-m37"/>
<constraint firstItem="afd-7Z-uCQ" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="Ife-bQ-hEA"/>
<constraint firstItem="afd-7Z-uCQ" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="Pkm-qE-C4y"/>
<constraint firstAttribute="trailing" secondItem="afd-7Z-uCQ" secondAttribute="trailing" id="Z7L-04-Q8L"/>
<constraint firstAttribute="bottom" secondItem="afd-7Z-uCQ" secondAttribute="bottom" id="yOv-fr-zul"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -22,4 +35,10 @@
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage.png" width="1290" height="2796"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

Binary file not shown.

View File

@@ -1,62 +0,0 @@
//
// WebViewController.swift
// OrderScheduling
//
// Created by on 2023/8/7.
//
import Foundation
import WebKit
import SnapKit
import DDLogKit_Private
import DDToastKit_Private
import DDControlsKit_Private
class WebViewController : DDViewController {
lazy var webView = WKWebView.init()
var vcTitle : String
var url : String?
public init(title:String,url:String) {
self.vcTitle = title
self.url = url
super.init(nibName: nil, bundle: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func viewDidLoad() {
super.viewDidLoad()
title = vcTitle
dd_navigationBarBackgroundColor = .hex("354683")
dd_navigationBarTitleTextAttributes = [.foregroundColor : UIColor.white(alpha: 0.7),.font:UIFont.mediumFont(17)]
webView.navigationDelegate = self
webView.uiDelegate = self
view.addSubview(webView)
let request = URLRequest(url: URL(string: url!)!)
webView.load(request)
webView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}
extension WebViewController : WKNavigationDelegate,WKUIDelegate {
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
DDLog(message: "finish--------------------------------")
}
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
DDLog(message: "didFail--------------------------------")
view.dd_makeToast(webViewLoadFailed) {[weak self] _ in
self?.navigationController?.popViewController(animated: true)
}
}
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
DDLog(message: "didFailProvisionalNavigation--------------------------------")
}
}

View File

@@ -0,0 +1,127 @@
//
// AppUpdateTool.swift
// OrderScheduling
//
// Created by on 2023/8/21.
//
import Foundation
import StoreKit
import RxSwift
import RxRelay
import RxCocoa
public let APPUPDATE = AppUpdateTool.default
open class AppUpdateTool : NSObject {
public static let `default` = AppUpdateTool()
public let requestAppUpdateRelay = ReplayRelay<FromTypeEnum>.create(bufferSize: 1)
private let disposeBag = DisposeBag()
public let appUpdateView = AppUpdateView()
public enum FromTypeEnum : Int {
case auto = 1
case manual
}
private var ignoreFlag : Bool? {
return UserDefaults.standard.object(forKey: appUpdateIgnore_key) as? Bool
}
func setIgnoreFlag(ignoreFlag:Bool) {
UserDefaults.standard.setValue(ignoreFlag, forKey: appUpdateIgnore_key)
}
public override init() {
super.init()
appUpdateView.updateButton.rx.tap
.subscribe(onNext: {[weak self] _ in
self?.openAppStore(by: UIApplication.shared.dd_keyWindow.rootViewController)
})
.disposed(by: disposeBag)
appUpdateView.ignoreButton.rx.tap
.subscribe(onNext: {[weak self] _ in
ENTRY.dismiss(name: appUpdateEntry) {[weak self] in
self?.setIgnoreFlag(ignoreFlag: true)
}
})
.disposed(by: disposeBag)
requestAppUpdateRelay
.observe(on: MainScheduler.instance)
.do(onNext: { _ in
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_showHUD()
})
.flatMapLatest { type in
return Observable.zip(RQ.versionCheck(parameters: VersionCheckParameters(version: TOOL.getVersion())).asObservable(), Observable.just(type))
}
.observe(on: MainScheduler.instance)
.do(onNext: { (_,_) in
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_hideHUD()
})
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] (response,type) in
if response?.success == true {
if self?.canUpdate(localVersion: TOOL.getVersion(), onlineVersion: response?.data?.appVersion ?? "0") == true {
if type == .auto {
if self?.shouldPresentEntry() == true {
if let appUpdateView = self?.appUpdateView {
appUpdateView.contentLabel.text = response?.data?.description
ENTRY.showAppUpdateEntry(view: appUpdateView,name: appUpdateEntry)
}
}
}else if type == .manual {
if let appUpdateView = self?.appUpdateView {
ENTRY.showAppUpdateEntry(view: appUpdateView,name: appUpdateEntry)
}
}
}else{
if type == .manual {
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_makeToast(isTheNewestVserion)
}
}
}else{
UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_makeToast(response?.msg)
}
})
.disposed(by: disposeBag)
}
func canUpdate(localVersion:String,onlineVersion:String) -> Bool {
let onlineIntVersion = Int(onlineVersion.replacingOccurrences(of: ".", with: "")) ?? 0
let localIntVersion = Int(localVersion.replacingOccurrences(of: ".", with: "")) ?? 0
if onlineIntVersion > localIntVersion {
return true
}
// app
setIgnoreFlag(ignoreFlag: false)
return false
}
func shouldPresentEntry() -> Bool {
if ignoreFlag == true {
return false
}
return true
}
func openAppStore(by from:UIViewController?) {
if ignoreFlag == true {
}else{
let vc = SKStoreProductViewController()
vc.delegate = self
vc.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier:AppItunesId])
from?.present(vc, animated: true)
}
}
}
extension AppUpdateTool : SKStoreProductViewControllerDelegate {
public func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) {
viewController.dismiss(animated: true)
}
}

View File

@@ -0,0 +1,87 @@
//
// AppUpdateView.swift
// OrderScheduling
//
// Created by on 2023/8/21.
//
import Foundation
import DDControlsKit_Private
import SnapKit
import DDAutoUIKit_Private
open class AppUpdateView : DDView {
private let radiusView : DDView
private let scrollView : DDScrollView
private let scrollContentView : DDView
public let contentLabel : DDLabel
public let ignoreButton : DDButton
public let updateButton : DDButton
public override init(frame: CGRect) {
radiusView = DDView.init()
scrollView = DDScrollView()
scrollContentView = DDView.init()
contentLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(14)), textColor: .black.alpha(0.5))
ignoreButton = DDButton.dd_initCustom()
updateButton = DDButton.dd_initCustom()
super.init(frame: frame)
addSubview(radiusView)
radiusView.addSubview(scrollView)
scrollView.addSubview(scrollContentView)
contentLabel.numberOfLines = 0
scrollContentView.addSubview(contentLabel)
ignoreButton.setTitle("忽略", for: .normal)
ignoreButton.titleLabel?.font = .mediumFont(auto(14))
ignoreButton.backgroundColor = .white
ignoreButton.setTitleColor(.black.alpha(0.3), for: .normal)
ignoreButton.layer.borderColor = UIColor.hex("000000").alpha(0.3).cgColor
ignoreButton.layer.borderWidth = 0.5
ignoreButton.layer.cornerRadius = auto(15)
radiusView.addSubview(ignoreButton)
updateButton.setTitle("更新", for: .normal)
updateButton.setTitleColor(.white, for: .normal)
updateButton.titleLabel?.font = .mediumFont(auto(14))
updateButton.backgroundColor = .hex("1C62D9")
updateButton.layer.cornerRadius = auto(15)
radiusView.addSubview(updateButton)
radiusView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
scrollView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.bottom.equalToSuperview().offset(-auto(70))
}
scrollContentView.snp.makeConstraints { make in
make.edges.equalToSuperview()
make.width.equalToSuperview()
}
contentLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(auto(20))
make.top.equalToSuperview().offset(auto(20))
make.right.equalTo(-auto(20))
make.bottom.equalTo(scrollContentView)
}
ignoreButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-auto(20))
make.width.equalTo(auto(80))
make.height.equalTo(auto(30))
make.centerX.equalToSuperview().offset(-auto(60))
}
updateButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-auto(20))
make.width.equalTo(auto(80))
make.height.equalTo(auto(30))
make.centerX.equalToSuperview().offset(auto(60))
}
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@@ -0,0 +1,28 @@
//
// EmptyView.swift
// OrderScheduling
//
// Created by on 2023/8/22.
//
import Foundation
import DDControlsKit_Private
import SnapKit
open class EmptyView : DDView {
public let imageView : DDImageView
public override init(frame: CGRect) {
imageView = DDImageView(image: UIImage(named: "noData_image"))
super.init(frame: frame)
addSubview(imageView)
imageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
isHidden = true
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@@ -0,0 +1,59 @@
//
// NotificationAuthTool.swift
// OrderScheduling
//
// Created by on 2023/8/22.
//
import Foundation
import RxSwift
import RxRelay
import RxCocoa
public let NOTIAUTHTOOL = NotificationAuthTool.default
open class NotificationAuthTool : NSObject {
public static let `default` = NotificationAuthTool()
public let requestNotiAuthRelay = ReplayRelay<Any?>.create(bufferSize: 1)
public let cancelNotiAuthRelay = ReplayRelay<Any?>.create(bufferSize: 1)
private let disposeBag = DisposeBag()
public let notificationAuthView = NotificationAuthView()
public override init() {
super.init()
requestNotiAuthRelay
.subscribe(onNext: {[weak self] _ in
if let notificationAuthView = self?.notificationAuthView {
ENTRY.showNotificationAuthEntry(view: notificationAuthView,name: notificationAuthViewEntry)
}
})
.disposed(by: disposeBag)
cancelNotiAuthRelay
.subscribe(onNext: { _ in
ENTRY.dismiss(name: notificationAuthViewEntry)
})
.disposed(by: disposeBag)
notificationAuthView.setButton.rx.tap
.subscribe(onNext: {[weak self] _ in
self?.openSetting()
})
.disposed(by: disposeBag)
notificationAuthView.ignoreButton.rx.tap
.subscribe(onNext: { _ in
ENTRY.dismiss(name: notificationAuthViewEntry)
})
.disposed(by: disposeBag)
}
public func openSetting() {
let url = URL(string: UIApplication.openSettingsURLString)!
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
}
}

View File

@@ -0,0 +1,91 @@
//
// NotificationAuthView.swift
// OrderScheduling
//
// Created by on 2023/8/22.
//
import Foundation
import DDControlsKit_Private
import DDAutoUIKit_Private
import DDColorKit_Private
import DDFontKit_Private
open class NotificationAuthView : DDView{
private let radiusView : DDView
private let scrollView : DDScrollView
private let scrollContentView : DDView
public let contentLabel : DDLabel
public let ignoreButton : DDButton
public let setButton : DDButton
public override init(frame: CGRect) {
radiusView = DDView.init()
scrollView = DDScrollView()
scrollContentView = DDView.init()
contentLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(17)), textColor: .black.alpha(0.5))
ignoreButton = DDButton.dd_initCustom()
setButton = DDButton.dd_initCustom()
super.init(frame: frame)
addSubview(radiusView)
radiusView.addSubview(scrollView)
scrollView.addSubview(scrollContentView)
contentLabel.numberOfLines = 0
contentLabel.textAlignment = .center
contentLabel.text = "当前应用未开启通知,建议开启"
scrollContentView.addSubview(contentLabel)
ignoreButton.setTitle("取消", for: .normal)
ignoreButton.titleLabel?.font = .mediumFont(auto(14))
ignoreButton.backgroundColor = .white
ignoreButton.setTitleColor(.black.alpha(0.3), for: .normal)
ignoreButton.layer.borderColor = UIColor.hex("000000").alpha(0.3).cgColor
ignoreButton.layer.borderWidth = 0.5
ignoreButton.layer.cornerRadius = auto(15)
radiusView.addSubview(ignoreButton)
setButton.setTitle("去设置", for: .normal)
setButton.setTitleColor(.white, for: .normal)
setButton.titleLabel?.font = .mediumFont(auto(14))
setButton.backgroundColor = .hex("1C62D9")
setButton.layer.cornerRadius = auto(15)
radiusView.addSubview(setButton)
radiusView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
scrollView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.bottom.equalToSuperview().offset(-auto(70))
}
scrollContentView.snp.makeConstraints { make in
make.edges.equalToSuperview()
make.width.equalToSuperview()
}
contentLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(auto(20))
make.top.equalToSuperview().offset(auto(20))
make.right.equalTo(-auto(20))
make.bottom.equalTo(scrollContentView)
}
ignoreButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-auto(20))
make.width.equalTo(auto(80))
make.height.equalTo(auto(30))
make.centerX.equalToSuperview().offset(-auto(60))
}
setButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-auto(20))
make.width.equalTo(auto(80))
make.height.equalTo(auto(30))
make.centerX.equalToSuperview().offset(auto(60))
}
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@@ -0,0 +1,115 @@
//
// WebViewController.swift
// OrderScheduling
//
// Created by on 2023/8/7.
//
import Foundation
import WebKit
import SnapKit
import DDLogKit_Private
import DDToastKit_Private
import DDControlsKit_Private
class WebViewController : DDViewController {
lazy var webView = WKWebView.init()
lazy var statusBarBackgroundView = DDView.init()
var showNavBar : Bool
var vcTitle : String
var url : String?
public init(showNavBar:Bool = true,title:String,url:String) {
self.showNavBar = showNavBar
self.vcTitle = title
self.url = url
super.init(nibName: nil, bundle: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func viewDidLoad() {
super.viewDidLoad()
webView.backgroundColor = .white
webView.navigationDelegate = self
webView.uiDelegate = self
view.addSubview(webView)
let request = URLRequest(url: URL(string: url!)!)
webView.load(request)
if showNavBar == false {
navigationItem.leftBarButtonItems = nil
dd_navigationBarBackgroundColor = .clear
view.addSubview(statusBarBackgroundView)
statusBarBackgroundView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.height.equalTo(CGRectGetHeight(UIApplication.shared.dd_statusBarFrame))
}
webView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(CGRectGetHeight(UIApplication.shared.dd_statusBarFrame))
make.bottom.equalTo(-view.safeAreaInsets.bottom)
}
}else{
title = vcTitle
dd_navigationBarBackgroundColor = .hex("354683")
dd_navigationBarTitleTextAttributes = [.foregroundColor : UIColor.white(alpha: 0.7),.font:UIFont.mediumFont(17)]
webView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(CGRectGetHeight(navigationController?.navigationBar.frame ?? .zero) + CGRectGetHeight(UIApplication.shared.dd_statusBarFrame))
make.bottom.equalTo(-view.safeAreaInsets.bottom)
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if showNavBar == false {
navigationController?.navigationBar.isHidden = true
}
webView.configuration.userContentController.add(self, name: "nativeObject")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if showNavBar == false {
navigationController?.navigationBar.isHidden = false
}
webView.configuration.userContentController.removeScriptMessageHandler(forName: "nativeObject")
}
}
extension WebViewController : WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let dict = message.body as? [String:String]
if dict?["action"] == "goBack" {
navigationController?.popViewController(animated: true)
}
}
}
extension WebViewController : WKNavigationDelegate,WKUIDelegate {
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
DDLog(message: "finish--------------------------------\(String(describing: webView.url?.absoluteString))")
if showNavBar == false {
statusBarBackgroundView.backgroundColor = .hex("2C395F")
}
}
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
DDLog(message: "didFail--------------------------------\(String(describing: webView.url?.absoluteString))")
view.dd_makeToast(webViewLoadFailed) {[weak self] _ in
self?.navigationController?.popViewController(animated: true)
}
}
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
DDLog(message: "didFailProvisionalNavigation--------------------------------\(String(describing: webView.url?.absoluteString))")
}
}

View File

@@ -0,0 +1,108 @@
//
// WebViewTool.swift
// OrderScheduling
//
// Created by on 2023/8/21.
//
import Foundation
import RxSwift
import RxRelay
public let WEBTOOL = WebViewTool.default
open class WebViewTool : NSObject {
public static let `default` = WebViewTool()
private var requestModelRelay = ReplayRelay<WebViewNameEnum>.create(bufferSize: 1)
private var appendingRelay = ReplayRelay<String?>.create(bufferSize: 1)
private var disposeBag = DisposeBag()
public var h5Models : DispatchAppH5UrlDataModel?
enum WebViewNameEnum : String {
case todoList = "待办事项"
case workOrderReconciliation = "工单记账"
case vehicleManage = "车辆管理"
case driverManage = "司机管理"
case invoicingNotify = "开票通知"
case reporting = "报备"
case supplySettlement = "补结算单"
case workOrderDetail = "工单详情页"
}
public override init() {
super.init()
Observable.zip(requestModelRelay, appendingRelay)
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] (name,appending) in
if let _ = self?.h5Models {
self?.openWebView(name: name,appending: appending)
}else{
let tabBarVc = UIApplication.shared.dd_keyWindow.rootViewController as? UITabBarController
let nav = tabBarVc?.selectedViewController as? UINavigationController
nav?.topViewController?.view.dd_showHUD()
}
})
.filter({[weak self] (name,appending) in
return self?.h5Models == nil
})
.throttle(RxTimeInterval.seconds(20), scheduler: ConcurrentMainScheduler.instance)
.flatMapLatest { (name,appending) in
return Observable.zip(RQ.dispatchAppH5Urls().asObservable(), Observable.just(name),Observable.just(appending))
}
.retry(5)
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] (response,name,appending) in
let tabBarVc = UIApplication.shared.dd_keyWindow.rootViewController as? UITabBarController
let nav = tabBarVc?.selectedViewController as? UINavigationController
nav?.topViewController?.view.dd_hideHUD()
self?.h5Models = response?.data
self?.openWebView(name: name,appending: appending)
})
.disposed(by: disposeBag)
}
private func openWebView(name:WebViewNameEnum,appending:String?) {
var vc : WebViewController?
switch name {
case .todoList:
vc = WebViewController(title: WebViewNameEnum.todoList.rawValue, url: "\((h5Models?.todoList)!)?token=\((USER.token)!)")
break
case .workOrderReconciliation:
vc = WebViewController(showNavBar:false, title: WebViewNameEnum.workOrderReconciliation.rawValue, url: "\((h5Models?.workOrderReconciliation)!)?token=\((USER.token)!)")
break
case .vehicleManage:
vc = WebViewController(showNavBar:false, title: WebViewNameEnum.vehicleManage.rawValue, url: "\((h5Models?.vehicleManage)!)?token=\((USER.token)!)")
break
case .driverManage:
vc = WebViewController(showNavBar:false, title: WebViewNameEnum.driverManage.rawValue, url: "\((h5Models?.driverManage)!)?token=\((USER.token)!)")
break
case .invoicingNotify:
vc = WebViewController(showNavBar:false, title: WebViewNameEnum.invoicingNotify.rawValue, url: "\((h5Models?.invoicingNotify)!)?token=\((USER.token)!)")
break
case .reporting:
vc = WebViewController(title: WebViewNameEnum.reporting.rawValue, url: "\((h5Models?.reporting)!)?token=\((USER.token)!)"+(appending ?? ""))
break
case .supplySettlement:
vc = WebViewController(title: WebViewNameEnum.supplySettlement.rawValue, url: "\((h5Models?.supplySettlement)!)?token=\((USER.token)!)"+(appending ?? ""))
break
case .workOrderDetail:
vc = WebViewController(title: WebViewNameEnum.workOrderDetail.rawValue, url: "\((h5Models?.workOrderDetail)!)?token=\((USER.token)!)"+(appending ?? ""))
break
}
if let vc {
let tabVc = UIApplication.shared.dd_keyWindow.rootViewController as? MainTabBarController
let nav = tabVc?.selectedViewController as? UINavigationController
nav?.pushViewController(vc, animated: true)
}
}
func open(name:WebViewNameEnum,appending:String?) {
requestModelRelay.accept(name)
appendingRelay.accept(appending)
}
}

View File

@@ -57,6 +57,92 @@ open class Entry {
SwiftEntryKit.display(entry: view, using: attributes)
}
func showAppUpdateEntry(view:UIView,name:String? = nil) {
var attributes = EKAttributes()
attributes = .centerFloat
attributes.name = name
attributes.precedence = .override(priority: .high, dropEnqueuedEntries: false)
attributes.displayMode = .inferred
attributes.displayDuration = .infinity
attributes.screenBackground = .color(color: .clear)
attributes.entryBackground = .color(color: .white)
attributes.screenInteraction = .absorbTouches
attributes.entryInteraction = .absorbTouches
attributes.scroll = .disabled
attributes.entranceAnimation = .init(
translate: .init(
duration: 0.25,
spring: .init(damping: 1, initialVelocity: 0)
)
)
attributes.exitAnimation = .init(
translate: .init(duration: 0.25)
)
attributes.popBehavior = .animated(
animation: .init(
translate: .init(duration: 0.25)
)
)
attributes.shadow = .active(
with: .init(
color: .black,
opacity: 0.3,
radius: 6
)
)
attributes.positionConstraints.size = .init(
width: .constant(value: auto(326)),
height: .constant(value: auto(285))
)
attributes.positionConstraints.verticalOffset = 0
attributes.positionConstraints.safeArea = .overridden
attributes.statusBar = .light
SwiftEntryKit.display(entry: view, using: attributes)
}
func showNotificationAuthEntry(view:UIView,name:String? = nil) {
var attributes = EKAttributes()
attributes = .centerFloat
attributes.name = name
attributes.precedence = .override(priority: .low, dropEnqueuedEntries: false)
attributes.displayMode = .inferred
attributes.displayDuration = .infinity
attributes.screenBackground = .color(color: .clear)
attributes.entryBackground = .color(color: .white)
attributes.screenInteraction = .absorbTouches
attributes.entryInteraction = .absorbTouches
attributes.scroll = .disabled
attributes.entranceAnimation = .init(
translate: .init(
duration: 0.25,
spring: .init(damping: 1, initialVelocity: 0)
)
)
attributes.exitAnimation = .init(
translate: .init(duration: 0.25)
)
attributes.popBehavior = .animated(
animation: .init(
translate: .init(duration: 0.25)
)
)
attributes.shadow = .active(
with: .init(
color: .black,
opacity: 0.3,
radius: 6
)
)
attributes.positionConstraints.size = .init(
width: .constant(value: auto(280)),
height: .constant(value: auto(130))
)
attributes.positionConstraints.verticalOffset = 0
attributes.positionConstraints.safeArea = .overridden
attributes.statusBar = .light
SwiftEntryKit.display(entry: view, using: attributes)
}
public func isCurrentlyDisplaying(entryNamed name: String? = nil) -> Bool {
return SwiftEntryKit.isCurrentlyDisplaying(entryNamed: name)
}

View File

@@ -81,4 +81,55 @@ open class Tool {
}
return dateString
}
public func getVersion() -> String {
return (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "1.0.0"
}
public func getIPhoneCode() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let versionCode: String = String(validatingUTF8: NSString(bytes: &systemInfo.machine, length: Int(_SYS_NAMELEN), encoding: String.Encoding.ascii.rawValue)!.utf8String!)!
switch versionCode {
/*** iPhone ***/
case "iPhone5,1", "iPhone5,2": return "iPhone5"
case "iPhone5,3", "iPhone5,4": return "iPhone5C"
case "iPhone6,1", "iPhone6,2": return "iPhone5S"
case "iPhone7,2": return "iPhone6"
case "iPhone7,1": return "iPhone6Plus"
case "iPhone8,1": return "iPhone6S"
case "iPhone8,2": return "iPhone6SPlus"
case "iPhone8,3", "iPhone8,4": return "iPhoneSE"
case "iPhone9,1", "iPhone9,3": return "iPhone7"
case "iPhone9,2", "iPhone9,4": return "iPhone7Plus"
case "iPhone10,1", "iPhone10,4": return "iPhone8"
case "iPhone10,2", "iPhone10,5": return "iPhone8Plus"
case "iPhone10,3", "iPhone10,6": return "iPhoneX"
case "iPhone11,2": return "iPhoneXS"
case "iPhone11,4", "iPhone11,6": return "iPhoneXS_Max"
case "iPhone11,8": return "iPhoneXR"
case "iPhone12,1": return "iPhone11"
case "iPhone12,3": return "iPhone11Pro"
case "iPhone12,5": return "iPhone11Pro_Max"
case "iPhone12,8": return "iPhoneSE2"
case "iPhone13,1": return "iPhone12Mini"
case "iPhone13,2": return "iPhone12"
case "iPhone13,3": return "iPhone12Pro"
case "iPhone13,4": return "iPhone12Pro_Max"
case "iPhone14,4": return "iPhone13Mini"
case "iPhone14,5": return "iPhone13"
case "iPhone14,2": return "iPhone13Pro"
case "iPhone14,3": return "iPhone13Pro_Max"
case "iPhone14,7": return "iPhone14"
case "iPhone14,8": return "iPhone14Plus"
case "iPhone15,2": return "iPhone14Pro"
case "iPhone15,3": return "iPhone14Pro_Max"
default:
break
}
return "未知"
}
}

View File

@@ -28,6 +28,10 @@ open class UserData {
UserDefaults.standard.set(supplierType, forKey: supplierType_key)
}
public var deviceToken : String?
public var regId : String?
func clear() {
setToken(token: nil)
setSupplierType(supplierType: nil)

View File

@@ -51,6 +51,16 @@ extension HistoryController {
})
.disposed(by: disposeBag)
pendingTapGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .todoList,appending: nil)
})
.disposed(by: disposeBag)
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
}
}
@@ -76,10 +86,8 @@ extension HistoryItemController {
.subscribe(onNext: {[weak self] (response, pageNum) in
if response?.success == true {
if pageNum == 1 {
if response?.data?.isEmpty == false {
self?.resultArr.removeAll()
self?.historyItemView.tableView.mj_footer?.resetNoMoreData()
}
self?.historyItemView.tableView.mj_header?.endRefreshing()
}else{
if response?.data?.isEmpty == false {
@@ -91,8 +99,15 @@ extension HistoryItemController {
if let array = response?.data {
self?.resultArr.append(contentsOf: array)
self?.historyItemView.tableView.reloadData()
}
if self?.resultArr.isEmpty == false {
self?.emptyView.isHidden = true
}else{
self?.emptyView.isHidden = false
}
self?.historyItemView.tableView.reloadData()
}else{
if pageNum == 1 {
self?.historyItemView.tableView.mj_header?.endRefreshing()
@@ -177,9 +192,26 @@ extension HistoryItemController : UITableViewDelegate, UITableViewDataSource {
})
}
cell?.reportButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .reporting, appending: "&queryType=\(OrderTypeEnum.UNCLOSED_ORDER.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)")
})
.disposed(by: cell!.disposeBag)
cell?.additionalButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .supplySettlement, appending: "&queryType=\(OrderTypeEnum.UNCLOSED_ORDER.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)&taskOrderId=\(model.taskOrderId)")
})
.disposed(by: cell!.disposeBag)
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let model = resultArr[indexPath.item]
WEBTOOL.open(name: .workOrderDetail, appending: "&queryType=\(type.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)&taskOrderId=\(model.taskOrderId)")
}
}
// MARK: JXCategoryViewDelegate,JXCategoryListContainerViewDelegate
@@ -273,6 +305,8 @@ class HistoryItemController : DDViewController {
private var refreshRelay = ReplayRelay<Int>.create(bufferSize: 1)
private var pageNum : Int = 1
private var type : OrderTypeEnum
private var emptyView = EmptyView()
public init(type:OrderTypeEnum) {
self.type = type
super.init(nibName: nil, bundle: nil)
@@ -296,6 +330,13 @@ class HistoryItemController : DDViewController {
make.edges.equalToSuperview()
}
historyItemView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
historyItemView.tableView.delegate = self
historyItemView.tableView.dataSource = self
}

View File

@@ -43,4 +43,6 @@ open class ApiList {
public let generalInfo = "/supplierAppV2/dispatchApp/user/generalInfo"
public let dispatchAppH5Urls = "/supplierAppV2/open/dispatchAppH5Urls"
public let versionCheck = "/supplierAppV2/dispatchApp/user/versionCheck"
}

View File

@@ -99,13 +99,13 @@ public struct RtspChannelParameters : Encodable {
var external : Int = 1
}
public struct OrderPhotoList : Encodable {
public struct OrderPhotoListParameters : Encodable {
var userOrderId : Int
var orderCode : String
var taskOrderId : Int
}
public struct SupplementOrderPhoto : Encodable {
public struct SupplementOrderPhotoParameters : Encodable {
var userOrderId : Int
var orderCode : String
var taskOrderId : Int
@@ -114,3 +114,8 @@ public struct SupplementOrderPhoto : Encodable {
var tag : String
var file : Data
}
public struct VersionCheckParameters : Encodable {
var version : String
var platForm : Int = 2
}

View File

@@ -80,7 +80,11 @@ open class RequestList {
return DDAF.post(urlString: HOST+API.generalInfo,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<GeneralInfoDataModel>.self)
}
func dispatchAppH5Urls() -> Single<ResponseModel<DispatchAppH5Urls>?> {
return DDAF.post(urlString: HOST+API.dispatchAppH5Urls,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<DispatchAppH5Urls>.self)
func dispatchAppH5Urls() -> Single<ResponseModel<DispatchAppH5UrlDataModel>?> {
return DDAF.post(urlString: HOST+API.dispatchAppH5Urls,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<DispatchAppH5UrlDataModel>.self)
}
func versionCheck(parameters:Encodable) -> Single<ResponseModel<VersionCheckDataModel>?> {
return DDAF.post(urlString: HOST+API.versionCheck,parameters: parameters,encoding: JSONParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<VersionCheckDataModel>.self)
}
}

View File

@@ -62,7 +62,7 @@ class OrderListDataModel: Decodable {
var orderCode : String
var createTime : String
var driverName : String?
var drivePhone : String?
var driverPhone : String?
var environmentPic : String?
var userOrderId : Int
var taskOrderId : Int
@@ -215,10 +215,8 @@ public class GeneralInfoDataModel : Decodable {
var driverCount : Int
}
public class DispatchAppH5Urls : Decodable {
var data : DataModel?
class DataModel : Decodable {
var todoList : String
public class DispatchAppH5UrlDataModel : Decodable {
var todoList : String?
var workOrderReconciliation : String
var vehicleManage : String
var driverManage : String
@@ -226,5 +224,25 @@ public class DispatchAppH5Urls : Decodable {
var reporting : String
var supplySettlement : String
var workOrderDetail : String
}
}
public class VersionCheckDataModel : Decodable {
var id : Int
var appVersion : String
var update : UpdateEnum
var appType : AppTypeEnum
enum UpdateEnum : Int,Decodable {
case NO = 0
case YES = 1
}
enum AppTypeEnum : Int,Decodable {
case app_type_1 = 1
case app_type_2 = 2
case app_type_3 = 3
case app_type_4 = 4
case app_type_5 = 5
}
var updateTime : String?
var createTime : String?
var description : String?
}

View File

@@ -136,8 +136,15 @@ extension LoginController {
let code = self?.loginView.codeView.textfield.text ?? ""
let clientType = "rescueApp"
let supplierLoginCode = self?.loginView.serviceProviderView.textfield.text ?? ""
let appVsersion = TOOL.getVersion()
let brand = "iPhone"
let model = TOOL.getIPhoneCode()
let sdkRelease = UIDevice.current.systemVersion
let platform = "iOS"
let deviceId = USER.deviceToken ?? ""
let regId = USER.regId ?? ""
let str = "{\"phone\":\"\(phone)\",\"code\":\"\(code)\",\"clientType\":\"\(clientType)\",\"supplierLoginCode\":\"\(supplierLoginCode)\"}"
let str = "{\"phone\":\"\(phone)\",\"code\":\"\(code)\",\"clientType\":\"\(clientType)\",\"supplierLoginCode\":\"\(supplierLoginCode)\",\"appVersion\":\"\(appVsersion)\",\"brand\":\"\(brand)\",\"model\":\"\(model)\",\"sdkRelease\":\"\(sdkRelease)\",\"platform\":\"\(platform)\",\"deviceId\":\"\(deviceId)\",\"regId\":\"\(regId)\"}"
return str
})
.flatMapLatest({ app_login_json in

View File

@@ -6,6 +6,7 @@
//
import UIKit
import CocoaDebug
class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -13,6 +14,22 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
//
JGInforCollectionAuth.jCollectionAuth({ authInfo in
authInfo.isAuth = true
})
let entity = JPUSHRegisterEntity()
entity.types = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 5
JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
#if DEBUG
JPUSHService.setup(withOption: launchOptions, appKey: JPushKey, channel: "App Store", apsForProduction: false)
#else
JPUSHService.setup(withOption: launchOptions, appKey: JPushKey, channel: "App Store", apsForProduction: true)
#endif
JPUSHService.resetBadge()
UIApplication.shared.applicationIconBadgeNumber = 0
return true
}
@@ -23,6 +40,42 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return .allButUpsideDown
}
func applicationDidBecomeActive(_ application: UIApplication) {
// JPUSHService.requestNotificationAuthorization({ status in
// print("\(status)")
// if status != .statusAuthorized {
// NOTIAUTHTOOL.requestNotiAuthRelay.accept(nil)
// }else{
// NOTIAUTHTOOL.cancelNotiAuthRelay.accept(nil)
// }
// })
}
//
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("deviceToken:\(tokenString)")
JPUSHService.registerDeviceToken(deviceToken)
USER.deviceToken = tokenString
print("registrationID:\(JPUSHService.registrationID())")
USER.regId = JPUSHService.registrationID()
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("did fail to register for remote notification with error ", error)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
JPUSHService.handleRemoteNotification(userInfo)
print("收到通知", userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
JPUSHService.handleRemoteNotification(userInfo)
completionHandler(.newData)
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
@@ -36,7 +89,50 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// 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.
}
}
extension AppDelegate : JPUSHRegisterDelegate {
@available(iOS 12.0, *)
func jpushNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification) {
if notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self) == true {
//
print("ios12从通知页面进入应用")
}else{
//
print("ios12从通知设置进入应用")
}
}
@available(iOS 10.0, *)
func jpushNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification,
withCompletionHandler completionHandler: ((Int) -> Void)) {
let userInfo = notification.request.content.userInfo
if notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self) == true {
JPUSHService.handleRemoteNotification(userInfo)
print("ios10 前台")
}
completionHandler(0)
}
@available(iOS 10.0, *)
func jpushNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: (() -> Void)) {
let userInfo = response.notification.request.content.userInfo
if response.notification.request.trigger?.isKind(of: UNPushNotificationTrigger.self) == true {
JPUSHService.resetBadge()
UIApplication.shared.applicationIconBadgeNumber = 0
JPUSHService.handleRemoteNotification(userInfo)
print("ios10 后台")
}
completionHandler()
}
func jpushNotificationAuthorization(_ status: JPAuthorizationStatus, withInfo info: [AnyHashable : Any]?) {
print("通知授权状态\(status)")
if status != .statusAuthorized {
NOTIAUTHTOOL.requestNotiAuthRelay.accept(nil)
}else{
NOTIAUTHTOOL.cancelNotiAuthRelay.accept(nil)
}
}
}

View File

@@ -31,6 +31,9 @@ class Initial : NSObject {
// af
initAF()
//
}
func initIQKeyboard(){
@@ -50,6 +53,10 @@ class Initial : NSObject {
DDAF.delegate = self
}
func initAppUpdate() {
APPUPDATE.requestAppUpdateRelay.accept(.auto)
}
// MARK: <RootViewController>
func initRootViewController(){
if USER.token != nil {
@@ -76,8 +83,9 @@ class Initial : NSObject {
window?.rootViewController = nav
}
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: Notification_loginSuccessToRescueController), object: nil, queue: .main) { note in
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: Notification_loginSuccessToRescueController), object: nil, queue: .main) {[weak self] note in
window?.rootViewController = MainTabBarController.init()
self?.initAppUpdate()
}
}

View File

@@ -12,7 +12,7 @@ import DDColorKit_Private
import DDFontKit_Private
import DDControlsKit_Private
open class MainTabBarController : ESTabBarController {
open class MainTabBarController : ESTabBarController,UITabBarControllerDelegate {
open override func viewDidLoad() {
super.viewDidLoad()
@@ -36,12 +36,38 @@ open class MainTabBarController : ESTabBarController {
tabBar.shadowImage = UIImage()
tabBar.backgroundImage = UIImage()
}
delegate = self
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
public func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let nav = viewController as? UINavigationController
if nav?.topViewController?.isMember(of: VehicleMonitoringController.self) == true {
let vc = nav?.topViewController as? VehicleMonitoringController
vc?.refreshData()
}
}
open override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
super.tabBar(tabBar, didSelect: item)
if item.title != "车辆监控" || item.title != "点击刷新" {
for tabBarItem in (tabBar.items ?? []) {
if tabBarItem.title == "点击刷新" {
tabBarItem.title = "车辆监控"
}
}
}
if item.title == "车辆监控" {
item.title = "点击刷新"
}
}
}
class MainTabBarItemContentView : ESTabBarItemContentView{

View File

@@ -1,15 +0,0 @@
//
// OrderScheduling-Bridge-Header.h
// OrderScheduling
//
// Created by 中道 on 2023/8/16.
//
#ifndef OrderScheduling_Bridge_Header_h
#define OrderScheduling_Bridge_Header_h
//#import <ZFPlayer/ZFPlayerController.h>
//#import <ZFPlayer/ZFPlayerControlView.h>
//#import <ZFPlayer/ZFIJKPlayerManager.h>
#endif /* OrderScheduling_Bridge_Header_h */

View File

@@ -0,0 +1,11 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// 引入 JPush 功能所需头文件
# import "JPUSHService.h"
# import "JGInforCollectionAuth.h"
// iOS10 注册 APNs 所需头文件
# ifdef NSFoundationVersionNumber_iOS_9_x_Max
# import <UserNotifications/UserNotifications.h>
# endif

View File

@@ -36,6 +36,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
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.
// JPUSHService.requestNotificationAuthorization({ status in
// print("\(status)")
// if status != .statusAuthorized {
// NOTIAUTHTOOL.requestNotiAuthRelay.accept(nil)
// }else{
// NOTIAUTHTOOL.cancelNotiAuthRelay.accept(nil)
// }
// })
}
func sceneWillResignActive(_ scene: UIScene) {

View File

@@ -47,6 +47,8 @@ extension MessageCenterController : UITableViewDelegate,UITableViewDataSource {
open class MessageCenterController : DDViewController {
private let messageCenterView = MessageCenterView()
private var emptyView = EmptyView()
open override func viewDidLoad() {
super.viewDidLoad()
dd_navigationItemTitle = "消息提醒"
@@ -65,6 +67,13 @@ open class MessageCenterController : DDViewController {
make.bottom.equalTo(-view.safeAreaInsets.bottom)
}
messageCenterView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
messageCenterView.tableView.delegate = self
messageCenterView.tableView.dataSource = self
}

View File

@@ -14,9 +14,14 @@ import RxRelay
import RxCocoa
import DDToastKit_Private
import DDProgressHUDKit_Private
import MJRefresh
extension MineController {
func addActions() {
mineView.scrollView.mj_header = MJRefreshNormalHeader(refreshingBlock: {[weak self] in
self?.refreshRelay.accept(nil)
})
mineView.logoutButton.rx.tap
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
@@ -29,6 +34,7 @@ extension MineController {
.do(onNext: {[weak self] _ in
self?.view.dd_hideHUD()
})
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response in
if response?.success == true {
USER.clear()
@@ -46,6 +52,7 @@ extension MineController {
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response in
if response?.success == true {
self?.mineView.scrollView.mj_header?.endRefreshing()
self?.mineView.carInfoView.descLabel.text = String(response?.data?.vehicleCount ?? 0)+""
self?.mineView.driverInfoView.descLabel.text = String(response?.data?.driverCount ?? 0)+""
if let icon = response?.data?.icon {
@@ -65,13 +72,60 @@ extension MineController {
refreshRelay.accept(nil)
mineView.carInfoGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .vehicleManage, appending: nil)
})
.disposed(by: disposeBag)
mineView.driverInfoGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .driverManage, appending: nil)
})
.disposed(by: disposeBag)
mineView.gongdanduizhangGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .workOrderReconciliation, appending: nil)
})
.disposed(by: disposeBag)
mineView.kaipiaotongzhiGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .invoicingNotify, appending: nil)
})
.disposed(by: disposeBag)
mineView.wendangziliaoGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
})
.disposed(by: disposeBag)
mineView.peixunwendangGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
})
.disposed(by: disposeBag)
mineView.banbenjianceGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
APPUPDATE.requestAppUpdateRelay.accept(.manual)
})
.disposed(by: disposeBag)
mineView.tongzhitixingGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
let url = URL(string: UIApplication.openSettingsURLString)!
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
}
NOTIAUTHTOOL.openSetting()
})
.disposed(by: disposeBag)
}
@@ -113,23 +167,30 @@ open class MineController : DDViewController {
}
open class MineView : DDView {
private let scrollView : DDScrollView
public let scrollView : DDScrollView
private let scrollContentView : DDView
private let topBackgroundImageView : DDImageView
public let avatar : DDImageView
public let accountLabel : DDLabel
public let companyLabel : DDLabel
public let carInfoGes : UITapGestureRecognizer
public let carInfoView : MineInfoView
public let driverInfoGes : UITapGestureRecognizer
public let driverInfoView : MineInfoView
public let infoRadiusView : DDView
public let infoRadiusSeparate : DDImageView
public let orderRadiusView : DDView
public let materialRadiusView : DDView
public let settingsRadiusView : DDView
public let gongdanduizhangGes : UITapGestureRecognizer
public let gongdanduizhang : MineCell
public let kaipiaotongzhiGes : UITapGestureRecognizer
public let kaipiaotongzhi : MineCell
public let peixunwendangGes : UITapGestureRecognizer
public let peixunwendang : MineCell
public let wendangziliaoGes : UITapGestureRecognizer
public let wendangziliao : MineCell
public let banbenjianceGes : UITapGestureRecognizer
public let banbenjiance : MineCell
public let tongzhitixingGes : UITapGestureRecognizer
public let tongzhitixing : MineCell
@@ -143,16 +204,23 @@ open class MineView : DDView {
accountLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(15)), textColor: .hex("FFFFFF").alpha(0.8))
companyLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(12)), textColor: .hex("FFFFFF").alpha(0.5))
carInfoView = MineInfoView()
carInfoGes = UITapGestureRecognizer()
driverInfoView = MineInfoView()
driverInfoGes = UITapGestureRecognizer()
infoRadiusView = DDView()
infoRadiusSeparate = DDImageView(image: UIImage(named: "mine_info_separate"))
orderRadiusView = DDView()
materialRadiusView = DDView()
settingsRadiusView = DDView()
gongdanduizhangGes = UITapGestureRecognizer()
gongdanduizhang = MineCell()
kaipiaotongzhiGes = UITapGestureRecognizer()
kaipiaotongzhi = MineCell()
peixunwendangGes = UITapGestureRecognizer()
peixunwendang = MineCell()
wendangziliaoGes = UITapGestureRecognizer()
wendangziliao = MineCell()
banbenjianceGes = UITapGestureRecognizer()
banbenjiance = MineCell()
tongzhitixingGes = UITapGestureRecognizer()
tongzhitixing = MineCell()
@@ -174,7 +242,9 @@ open class MineView : DDView {
infoRadiusView.backgroundColor = .hex("FFFFFF")
infoRadiusView.layer.cornerRadius = auto(12)
scrollContentView.addSubview(infoRadiusView)
carInfoView.addGestureRecognizer(carInfoGes)
infoRadiusView.addSubview(carInfoView)
driverInfoView.addGestureRecognizer(driverInfoGes)
infoRadiusView.addSubview(driverInfoView)
scrollContentView.addSubview(infoRadiusSeparate)
orderRadiusView.backgroundColor = .hex("FFFFFF")
@@ -186,12 +256,17 @@ open class MineView : DDView {
settingsRadiusView.backgroundColor = .hex("FFFFFF")
settingsRadiusView.layer.cornerRadius = auto(6)
scrollContentView.addSubview(settingsRadiusView)
gongdanduizhang.addGestureRecognizer(gongdanduizhangGes)
orderRadiusView.addSubview(gongdanduizhang)
kaipiaotongzhi.line.isHidden = true
kaipiaotongzhi.addGestureRecognizer(kaipiaotongzhiGes)
orderRadiusView.addSubview(kaipiaotongzhi)
peixunwendang.addGestureRecognizer(peixunwendangGes)
materialRadiusView.addSubview(peixunwendang)
wendangziliao.line.isHidden = true
wendangziliao.addGestureRecognizer(wendangziliaoGes)
materialRadiusView.addSubview(wendangziliao)
banbenjiance.addGestureRecognizer(banbenjianceGes)
settingsRadiusView.addSubview(banbenjiance)
tongzhitixing.line.isHidden = true
settingsRadiusView.addSubview(tongzhitixing)

View File

@@ -0,0 +1,8 @@
<?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>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?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>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@@ -383,6 +383,7 @@ open class DispatchOrderPannelCell : DDTableViewCell {
// stateLabel.lineBreakMode = .byTruncatingMiddle
stateLabel.numberOfLines = 0
contentView.addSubview(stateLabel)
name.numberOfLines = 0
contentView.addSubview(name)
contentView.addSubview(phone)
distance.lineBreakMode = .byTruncatingMiddle

View File

@@ -53,8 +53,6 @@ extension RescueController {
})
.disposed(by: disposeBag)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
messageTapGes.rx.event
.subscribe(onNext: {[weak self] _ in
let vc = MessageCenterController()
@@ -63,23 +61,17 @@ extension RescueController {
.disposed(by: disposeBag)
pendingTapGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .todoList,appending: nil)
})
.disposed(by: disposeBag)
h5Relay
.flatMapLatest { _ in
return RQ.dispatchAppH5Urls()
}
.subscribe(onNext: { response in
})
.disposed(by: disposeBag)
h5Relay.accept(nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
}
}
extension RescuePendingOrderController {
@@ -102,10 +94,8 @@ extension RescuePendingOrderController {
.subscribe(onNext: {[weak self] (response, pageNum) in
if response?.success == true {
if pageNum == 1 {
if response?.data?.isEmpty == false {
self?.resultArr.removeAll()
self?.pendingOrderView.tableView.mj_footer?.resetNoMoreData()
}
self?.pendingOrderView.tableView.mj_header?.endRefreshing()
}else{
if response?.data?.isEmpty == false {
@@ -117,8 +107,15 @@ extension RescuePendingOrderController {
if let array = response?.data {
self?.resultArr.append(contentsOf: array)
self?.pendingOrderView.tableView.reloadData()
}
if self?.resultArr.isEmpty == false {
self?.emptyView.isHidden = true
}else{
self?.emptyView.isHidden = false
}
self?.pendingOrderView.tableView.reloadData()
}else{
if pageNum == 1 {
self?.pendingOrderView.tableView.mj_header?.endRefreshing()
@@ -241,10 +238,8 @@ extension RescuePendingDispatchController {
.subscribe(onNext: {[weak self] (response, pageNum) in
if response?.success == true {
if pageNum == 1 {
if response?.data?.isEmpty == false {
self?.resultArr.removeAll()
self?.pendingDispatchView.tableView.mj_footer?.resetNoMoreData()
}
self?.pendingDispatchView.tableView.mj_header?.endRefreshing()
}else{
if response?.data?.isEmpty == false {
@@ -256,8 +251,15 @@ extension RescuePendingDispatchController {
if let array = response?.data {
self?.resultArr.append(contentsOf: array)
self?.pendingDispatchView.tableView.reloadData()
}
if self?.resultArr.isEmpty == false {
self?.emptyView.isHidden = true
}else{
self?.emptyView.isHidden = false
}
self?.pendingDispatchView.tableView.reloadData()
}else{
if pageNum == 1 {
self?.pendingDispatchView.tableView.mj_header?.endRefreshing()
@@ -293,10 +295,8 @@ extension RescueIsIngController {
.subscribe(onNext: {[weak self] (response, pageNum) in
if response?.success == true {
if pageNum == 1 {
if response?.data?.isEmpty == false {
self?.resultArr.removeAll()
self?.pendingIsIngView.tableView.mj_footer?.resetNoMoreData()
}
self?.pendingIsIngView.tableView.mj_header?.endRefreshing()
}else{
if response?.data?.isEmpty == false {
@@ -308,8 +308,15 @@ extension RescueIsIngController {
if let array = response?.data {
self?.resultArr.append(contentsOf: array)
self?.pendingIsIngView.tableView.reloadData()
}
if self?.resultArr.isEmpty == false {
self?.emptyView.isHidden = true
}else{
self?.emptyView.isHidden = false
}
self?.pendingIsIngView.tableView.reloadData()
}else{
if pageNum == 1 {
self?.pendingIsIngView.tableView.mj_header?.endRefreshing()
@@ -421,6 +428,11 @@ extension RescuePendingOrderController : UITableViewDelegate,UITableViewDataSour
.disposed(by: disposeBag)
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let model = resultArr[indexPath.item]
WEBTOOL.open(name: .workOrderDetail, appending: "&queryType=\(OrderTypeEnum.TO_ACCEPT_DISPATCH.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)&taskOrderId=\(model.taskOrderId)")
}
}
extension RescuePendingDispatchController : UITableViewDelegate,UITableViewDataSource {
@@ -583,6 +595,11 @@ extension RescuePendingDispatchController : UITableViewDelegate,UITableViewDataS
.disposed(by: cell!.disposeBag)
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let model = resultArr[indexPath.item]
WEBTOOL.open(name: .workOrderDetail, appending: "&queryType=\(OrderTypeEnum.TO_DISPATCH_VEHICLE.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)&taskOrderId=\(model.taskOrderId)")
}
}
extension RescueIsIngController : UITableViewDelegate,UITableViewDataSource {
@@ -610,12 +627,12 @@ extension RescueIsIngController : UITableViewDelegate,UITableViewDataSource {
cell?.orderNumLabel.text = model.orderCode
cell?.orderDateLabel.text = model.createTime
if model.driverName?.isEmpty == false && model.drivePhone?.isEmpty == false {
cell?.driverLabel.text = "\(model.driverName!)/\(model.drivePhone!)"
if model.driverName?.isEmpty == false && model.driverPhone?.isEmpty == false {
cell?.driverLabel.text = "\(model.driverName!)/\(model.driverPhone!)"
}else if model.driverName?.isEmpty == false {
cell?.driverLabel.text = model.driverName!
}else if model.drivePhone?.isEmpty == false {
cell?.driverLabel.text = model.drivePhone!
}else if model.driverPhone?.isEmpty == false {
cell?.driverLabel.text = model.driverPhone!
}else{
cell?.driverLabel.text = nil
}
@@ -649,8 +666,20 @@ extension RescueIsIngController : UITableViewDelegate,UITableViewDataSource {
self?.navigationController?.pushViewController(vc, animated: true)
})
.disposed(by: cell!.disposeBag)
cell?.reportButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .reporting,appending: "&queryType=\(OrderTypeEnum.TO_RESCUE.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)")
})
.disposed(by: disposeBag)
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let model = resultArr[indexPath.item]
WEBTOOL.open(name: .workOrderDetail, appending: "&queryType=\(OrderTypeEnum.TO_RESCUE.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)&taskOrderId=\(model.taskOrderId)")
}
}
// MARK: UICollectionViewDelegate, UICollectionViewDataSource
@@ -761,6 +790,7 @@ class RescuePendingOrderController : DDViewController {
private var refuseRemarkIdRelay = ReplayRelay<OrderListDataModel>.create(bufferSize: 1)
private var refuseSubmitRelay = ReplayRelay<Any?>.create(bufferSize: 1)
private var acceptOrderRelay = ReplayRelay<OrderListDataModel>.create(bufferSize: 1)
private var emptyView = EmptyView()
override func viewDidLoad() {
super.viewDidLoad()
@@ -776,6 +806,13 @@ class RescuePendingOrderController : DDViewController {
make.edges.equalToSuperview()
}
pendingOrderView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
pendingOrderView.tableView.delegate = self
pendingOrderView.tableView.dataSource = self
}
@@ -789,6 +826,7 @@ class RescuePendingDispatchController : DDViewController {
private var environmentPics : [String] = []
private var refreshRelay = ReplayRelay<Int>.create(bufferSize: 1)
private var pageNum : Int = 1
private var emptyView = EmptyView()
override func viewDidLoad() {
super.viewDidLoad()
@@ -804,6 +842,13 @@ class RescuePendingDispatchController : DDViewController {
make.edges.equalToSuperview()
}
pendingDispatchView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
pendingDispatchView.tableView.delegate = self
pendingDispatchView.tableView.dataSource = self
}
@@ -816,6 +861,7 @@ class RescueIsIngController : DDViewController {
private var resultArr : [OrderListDataModel] = []
private var refreshRelay = ReplayRelay<Int>.create(bufferSize: 1)
private var pageNum : Int = 1
private var emptyView = EmptyView()
override func viewDidLoad() {
super.viewDidLoad()
@@ -831,6 +877,13 @@ class RescueIsIngController : DDViewController {
make.edges.equalToSuperview()
}
pendingIsIngView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
pendingIsIngView.tableView.delegate = self
pendingIsIngView.tableView.dataSource = self
}

View File

@@ -17,7 +17,7 @@ extension AdditionalPhotoController{
func addActions() {
refreshRelay
.flatMapLatest {[weak self] _ in
return RQ.orderPhotoList(prameters: OrderPhotoList(userOrderId: (self?.userOrderId)!, orderCode: (self?.orderCode)!, taskOrderId: (self?.taskOrderId)!))
return RQ.orderPhotoList(prameters: OrderPhotoListParameters(userOrderId: (self?.userOrderId)!, orderCode: (self?.orderCode)!, taskOrderId: (self?.taskOrderId)!))
}
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response in
@@ -44,7 +44,7 @@ extension AdditionalPhotoController{
uploadImageRelay
.flatMapLatest {[weak self] itemModel in
return RQ.supplementOrderPhoto(prameters: SupplementOrderPhoto(userOrderId: (self?.userOrderId)!, orderCode: (self?.orderCode)!, taskOrderId: (self?.taskOrderId)!, taskStatus: (itemModel.taskStatus)!, tag: itemModel.tag, file: (itemModel.uploadImage)!)) { multipartFormData in
return RQ.supplementOrderPhoto(prameters: SupplementOrderPhotoParameters(userOrderId: (self?.userOrderId)!, orderCode: (self?.orderCode)!, taskOrderId: (self?.taskOrderId)!, taskStatus: (itemModel.taskStatus)!, tag: itemModel.tag, file: (itemModel.uploadImage)!)) { multipartFormData in
multipartFormData.append((itemModel.uploadImage)!, withName: "file",fileName: "\(String(Date.init().timeIntervalSince1970*1000))",mimeType: "text/plain")
if let data = itemModel.tag.data(using: .utf8) {
multipartFormData.append(data, withName: "tag")

View File

@@ -50,14 +50,12 @@ extension ReviewFailedController {
})
.disposed(by: disposeBag)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
messageCenterView.tableView.mj_header = MJRefreshNormalHeader(refreshingBlock: {[weak self] in
reviewFailedView.tableView.mj_header = MJRefreshNormalHeader(refreshingBlock: {[weak self] in
self?.pageNum = 1
self?.refreshRelay.accept(self?.pageNum ?? 1)
})
messageCenterView.tableView.mj_footer = MJRefreshBackNormalFooter(refreshingBlock: {[weak self] in
reviewFailedView.tableView.mj_footer = MJRefreshBackNormalFooter(refreshingBlock: {[weak self] in
self?.pageNum+=1
self?.refreshRelay.accept(self?.pageNum ?? 1)
})
@@ -70,35 +68,52 @@ extension ReviewFailedController {
.subscribe(onNext: {[weak self] (response, pageNum) in
if response?.success == true {
if pageNum == 1 {
if response?.data?.isEmpty == false {
self?.resultArr.removeAll()
self?.messageCenterView.tableView.mj_footer?.resetNoMoreData()
}
self?.messageCenterView.tableView.mj_header?.endRefreshing()
self?.reviewFailedView.tableView.mj_footer?.resetNoMoreData()
self?.reviewFailedView.tableView.mj_header?.endRefreshing()
}else{
if response?.data?.isEmpty == false {
self?.messageCenterView.tableView.mj_footer?.endRefreshing()
self?.reviewFailedView.tableView.mj_footer?.endRefreshing()
}else{
self?.messageCenterView.tableView.mj_footer?.endRefreshingWithNoMoreData()
self?.reviewFailedView.tableView.mj_footer?.endRefreshingWithNoMoreData()
}
}
if let array = response?.data {
self?.resultArr.append(contentsOf: array)
self?.messageCenterView.tableView.reloadData()
}
if self?.resultArr.isEmpty == false {
self?.emptyView.isHidden = true
}else{
self?.emptyView.isHidden = false
}
self?.reviewFailedView.tableView.reloadData()
}else{
if pageNum == 1 {
self?.messageCenterView.tableView.mj_header?.endRefreshing()
self?.reviewFailedView.tableView.mj_header?.endRefreshing()
}else{
self?.messageCenterView.tableView.mj_footer?.endRefreshing()
self?.reviewFailedView.tableView.mj_footer?.endRefreshing()
}
self?.view.dd_makeToast(response?.msg)
}
})
.disposed(by: disposeBag)
messageCenterView.tableView.mj_header?.beginRefreshing()
reviewFailedView.tableView.mj_header?.beginRefreshing()
pendingTapGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .todoList,appending: nil)
})
.disposed(by: disposeBag)
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
}
}
@@ -136,7 +151,7 @@ extension ReviewFailedController : UITableViewDelegate,UITableViewDataSource {
}
open class ReviewFailedController : DDViewController {
private let messageCenterView = ReviewFailedView()
private let reviewFailedView = ReviewFailedView()
private var pageNum : Int = 1
private var refreshRelay = ReplayRelay<Int>.create(bufferSize: 1)
private let disposeBag = DisposeBag()
@@ -145,6 +160,7 @@ open class ReviewFailedController : DDViewController {
private let messageView = MessageView()
private let pendingTapGes = UITapGestureRecognizer()
private let pendingView = MessageView()
private var emptyView = EmptyView()
open override func viewDidLoad() {
super.viewDidLoad()
@@ -159,14 +175,21 @@ open class ReviewFailedController : DDViewController {
func addSubviews() {
view.backgroundColor = .hex("F4F5F7")
view.addSubview(messageCenterView)
messageCenterView.snp.makeConstraints { make in
view.addSubview(reviewFailedView)
reviewFailedView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.bottom.equalTo(-view.safeAreaInsets.bottom)
}
messageCenterView.tableView.delegate = self
messageCenterView.tableView.dataSource = self
reviewFailedView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
reviewFailedView.tableView.delegate = self
reviewFailedView.tableView.dataSource = self
messageView.titleLabel.text = "消息"
messageView.addGestureRecognizer(messageTapGes)

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@@ -8,3 +8,7 @@
import Foundation
public let MAAppKey = "6e13671d1444633f9fd5a407a309555a"
public let JPushKey = "259b546bb2aaf5f02ffa2547"
public let AppItunesId = "1616776985"

View File

@@ -8,3 +8,7 @@
import Foundation
public let refuseOrderEntry = "refuseOrderEntry"
public let appUpdateEntry = "appUpdateEntry"
public let notificationAuthViewEntry = "notificationAuthViewEntry"

View File

@@ -22,3 +22,5 @@ public let dispatchOrderInputPhone = "请输入技师电话"
public let dispatchOrderInputLicense = "请输入救援车车牌"
public let dispatchOrderSuccess = "派单成功"
public let isTheNewestVserion = "已是最新版本"

View File

@@ -8,3 +8,5 @@
import Foundation
public let login_code_timer_key = "login_code_timer_key"
public let refresh_vehicle_monitoring_key = "refresh_vehicle_monitoring_key"

View File

@@ -10,3 +10,9 @@ import Foundation
public let token_key = "token_key"
public let supplierType_key = "supplierType_key"
public let appUpdateIgnore_key = "appUpdateIgnore_key"
public let deviceToken_key = "deviceToken_key"
public let regId_key = "regId_key"

View File

@@ -14,6 +14,7 @@ import RxCocoa
import RxRelay
import JXCategoryView
import SnapKit
import DDTimerKit_Private
fileprivate let vehicleMonitoringPannelViewHeight = auto(300)
fileprivate let vehicleMonitoringPannelViewTopInset = auto(90)
@@ -62,10 +63,18 @@ extension VehicleMonitoringController {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
reloadRelay
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
self?.view.dd_showHUD()
})
.flatMapLatest { _ in
return RQ.vehicleMonitorList()
}
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
self?.view.dd_hideHUD()
})
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response in
if response?.success == true {
self?.dataModel = response?.data
@@ -76,12 +85,13 @@ extension VehicleMonitoringController {
let busyCount = String(response?.data?.vehicleMonitorCount.busyCount ?? 0)+"\n"+"忙碌"
let alarmCount = String(response?.data?.vehicleMonitorCount.alarmCount ?? 0)+"\n"+"报警"
if USER.supplierType == 2 {
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [roster,onLineCount,lostConnectionCount,leisureCount,busyCount,alarmCount]
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [roster,onLineCount,lostConnectionCount,leisureCount,busyCount]
}else{
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [onLineCount,lostConnectionCount,leisureCount,busyCount,alarmCount]
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [onLineCount,lostConnectionCount,leisureCount,busyCount]
}
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.reloadData()
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.selectItem(at: 0)
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.reloadDataWithoutListContainer()
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.listContainer.reloadData()
self?.categoryView(self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView, didSelectedItemAt: self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.selectedIndex ?? 0)
}else{
self?.view.dd_makeToast(response?.msg)
}
@@ -144,8 +154,40 @@ extension VehicleMonitoringController {
})
.disposed(by: disposeBag)
pendingTapGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
WEBTOOL.open(name: .todoList,appending: nil)
})
.disposed(by: disposeBag)
// vehicleMonitoringView.refreshButton.rx.tap
// .subscribe(onNext: {[weak self] _ in
// self?.reloadRelay.accept(nil)
// })
// .disposed(by: disposeBag)
// vehicleMonitoringView.refreshButton.sendActions(for: .touchUpInside)
// var duration = 0
// DDTimerManager.dd_share().dd_addTimer(withName: refresh_vehicle_monitoring_key, timeInterval: 1, repeatCount: 0, delay: 0) {[weak self] (manager, obj, index) in
// if duration == 0 {
// duration = 60
// self?.reloadRelay.accept(nil)
// }
// duration-=1
// DispatchQueue.main.async {[weak self] in
// self?.vehicleMonitoringView.refreshButton.setTitle(":"+"\(duration)s", for: .normal)
// }
// }
}
public func refreshData() {
reloadRelay.accept(nil)
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: Notification_reloadRescusControolerToDoMessageCount), object: nil)
}
}
extension VehicleMonitoringController : DDMAMapViewDelegate {
@@ -505,10 +547,6 @@ open class VehicleMonitoringController : DDViewController {
}
}
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
}
// MARK: UI
@@ -518,12 +556,14 @@ open class VehicleMonitoringView : DDView {
public let coverView : DDView
public let tapGes : UITapGestureRecognizer
public let panGes : UIPanGestureRecognizer
public let refreshButton : DDButton
public init(titles:[String]) {
vehicleMonitoringPannelView = VehicleMonitoringPannelView(titles:titles)
maMapView = DDMAMapView()
coverView = DDView()
tapGes = UITapGestureRecognizer()
panGes = UIPanGestureRecognizer()
refreshButton = DDButton.dd_initCustom()
super.init(frame: .zero)
maMapView.maMapView.logoCenter = CGPoint(x: 100, y: 100)
@@ -534,6 +574,11 @@ open class VehicleMonitoringView : DDView {
addSubview(coverView)
vehicleMonitoringPannelView.layer.cornerRadius = auto(16)
addSubview(vehicleMonitoringPannelView)
refreshButton.setTitle("手动刷新", for: .normal)
refreshButton.setTitleColor(.hex("000000"), for: .normal)
refreshButton.titleLabel?.font = .mediumFont(auto(14))
refreshButton.isHidden = true
addSubview(refreshButton)
maMapView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
@@ -549,6 +594,12 @@ open class VehicleMonitoringView : DDView {
make.left.right.equalToSuperview()
make.height.equalTo(vehicleMonitoringPannelViewHeight)
}
refreshButton.snp.makeConstraints { make in
make.bottom.equalTo(vehicleMonitoringPannelView.snp.top).offset(-auto(0))
make.right.equalTo(-auto(20))
make.height.equalTo(auto(30))
}
}
required public init?(coder: NSCoder) {

View File

@@ -88,6 +88,8 @@ open class VehicleMonitoringListController : DDViewController {
public var selectCellBlock: ((VehicleMonitorListDataModel.ItemModel) -> Void)?
private var isPaiban : Bool?
private var isAlarm : Bool?
private var emptyView = EmptyView()
open override func viewDidLoad() {
super.viewDidLoad()
@@ -99,6 +101,13 @@ open class VehicleMonitoringListController : DDViewController {
make.edges.equalToSuperview()
}
vehicleMonitoringListView.tableView.addSubview(emptyView)
emptyView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(auto(303))
make.height.equalTo(auto(94))
}
vehicleMonitoringListView.tableView.delegate = self
vehicleMonitoringListView.tableView.dataSource = self
}
@@ -111,6 +120,13 @@ open class VehicleMonitoringListController : DDViewController {
if let models {
self.models.append(contentsOf: models)
}
if self.models.isEmpty == false {
emptyView.isHidden = true
}else{
emptyView.isHidden = false
}
vehicleMonitoringListView.tableView.reloadData()
}
}
@@ -175,6 +191,7 @@ open class VehicleMonitoringListCell : DDTableViewCell {
dateLabel.numberOfLines = 0
dateLabel.textAlignment = .center
radiusView.addSubview(dateLabel)
nameLabel.numberOfLines = 0
radiusView.addSubview(nameLabel)
radiusView.addSubview(phoneLabel)
callButton.layer.cornerRadius = auto(4)
@@ -208,7 +225,7 @@ open class VehicleMonitoringListCell : DDTableViewCell {
}
nameLabel.snp.makeConstraints { make in
make.left.equalTo(dateLabel.snp.right).offset(auto(5))
make.left.equalTo(dateLabel.snp.right).offset(auto(10))
make.width.equalTo(auto(60))
make.centerY.equalToSuperview()
}

View File

@@ -8,7 +8,7 @@ target 'OrderScheduling' do
use_modular_headers!
# pod 'CocoaDebug', :configurations => ['Debug']
pod 'CocoaDebug'
pod 'ESTabBarController-swift'
pod 'DDCategoryKit_Private'
pod 'DDBasicControlsKit_Private'
@@ -24,7 +24,7 @@ target 'OrderScheduling' do
pod 'DDTimerKit_Private'
pod 'DDToastKit_Private'
pod 'DDNetworkingOfAlamofireKit_Private'
pod 'DDProgressHUDKit_Private'
pod 'DDProgressHUDKit_Private', :path=> '/Users/zd/Desktop/PodRepository/DDProgressHUDKit_Private'
pod 'JXCategoryView'
pod 'DDControlsKit_Private'
pod 'SwiftEntryKit'
@@ -34,6 +34,7 @@ target 'OrderScheduling' do
pod 'ZFPlayer',:path=> '/Users/zd/Downloads/iOS相关/ZFPlayer-master'
pod 'ZFPlayer/ControlView',:path=> '/Users/zd/Downloads/iOS相关/ZFPlayer-master'
pod 'ZFPlayer/ijkplayer',:path=> '/Users/zd/Downloads/iOS相关/ZFPlayer-master'
pod 'JPush'
# pod 'ZFPlayer', '~> 4.0'
# pod 'ZFPlayer/ControlView'

View File

@@ -10,6 +10,7 @@ PODS:
- AMapTrack-NO-IDFA (1.4.2):
- AMapFoundation-NO-IDFA (>= 1.6.4)
- AMapLocation-NO-IDFA (>= 2.6.7)
- CocoaDebug (1.7.7)
- DDAutoUIKit_Private (0.1.2)
- DDBasicControlsKit_Private (0.3.1):
- DDBasicControlsKit_Private/DDBaseAnimation (= 0.3.1)
@@ -254,7 +255,10 @@ PODS:
- Alamofire
- DDLogKit_Private
- RxSwift
- DDProgressHUDKit_Private (0.1.1)
- DDProgressHUDKit_Private (0.1.1):
- "DDCategoryKit_Private/UIImage+DDCategory"
- SnapKit
- YYImage
- DDTimerKit_Private (0.1.0):
- DDTimerKit_Private/GCDTimer (= 0.1.0)
- DDTimerKit_Private/GCDTimer (0.1.0)
@@ -272,6 +276,9 @@ PODS:
- DDWebImageKit_Private/SDWebImage/Core
- ESTabBarController-swift (2.8.0)
- IQKeyboardManagerSwift (6.5.12)
- JCore (4.2.1)
- JPush (5.0.1):
- JCore (>= 2.0.0)
- JXCategoryView (1.6.1)
- MJRefresh (3.7.5)
- RxCocoa (6.5.0):
@@ -282,6 +289,9 @@ PODS:
- RxSwift (6.5.0)
- SnapKit (5.6.0)
- SwiftEntryKit (2.0.0)
- YYImage (1.0.4):
- YYImage/Core (= 1.0.4)
- YYImage/Core (1.0.4)
- ZFPlayer (4.0.5):
- ZFPlayer/Core (= 4.0.5)
- ZFPlayer/ControlView (4.0.5):
@@ -294,6 +304,7 @@ PODS:
- ZLPhotoBrowser/Core (4.4.3.2)
DEPENDENCIES:
- CocoaDebug
- DDAutoUIKit_Private
- DDBasicControlsKit_Private
- DDCategoryKit_Private
@@ -302,12 +313,13 @@ DEPENDENCIES:
- DDFontKit_Private
- DDMAMapKit_Private
- DDNetworkingOfAlamofireKit_Private
- DDProgressHUDKit_Private
- DDProgressHUDKit_Private (from `/Users/zd/Desktop/PodRepository/DDProgressHUDKit_Private`)
- DDTimerKit_Private
- DDToastKit_Private
- DDWebImageKit_Private
- ESTabBarController-swift
- IQKeyboardManagerSwift
- JPush
- JXCategoryView
- MJRefresh
- RxCocoa
@@ -331,7 +343,6 @@ SPEC REPOS:
- DDLogKit_Private
- DDMAMapKit_Private
- DDNetworkingOfAlamofireKit_Private
- DDProgressHUDKit_Private
- DDTimerKit_Private
- DDToastKit_Private
- DDWebImageKit_Private
@@ -342,8 +353,11 @@ SPEC REPOS:
- AMapNavi-NO-IDFA
- AMapSearch-NO-IDFA
- AMapTrack-NO-IDFA
- CocoaDebug
- ESTabBarController-swift
- IQKeyboardManagerSwift
- JCore
- JPush
- JXCategoryView
- MJRefresh
- RxCocoa
@@ -351,9 +365,12 @@ SPEC REPOS:
- RxSwift
- SnapKit
- SwiftEntryKit
- YYImage
- ZLPhotoBrowser
EXTERNAL SOURCES:
DDProgressHUDKit_Private:
:path: "/Users/zd/Desktop/PodRepository/DDProgressHUDKit_Private"
ZFPlayer:
:path: "/Users/zd/Downloads/iOS相关/ZFPlayer-master"
@@ -364,6 +381,7 @@ SPEC CHECKSUMS:
AMapNavi-NO-IDFA: 70c724400376bfadcb8ec08b9761f526096cfdb6
AMapSearch-NO-IDFA: 10cbd3ad7d122045a0c1f5760f6d46ff576ca918
AMapTrack-NO-IDFA: 7109cf1867f5d6c407c8191492b1f73101e1682e
CocoaDebug: b38d31464b91a9775928f8667d114db07b136565
DDAutoUIKit_Private: 4d031662fdd86c46b1dc4b88271f2303661225fd
DDBasicControlsKit_Private: 04e64a24551a24e76555835fc14002415db80f94
DDCategoryKit_Private: db12e3f6923e2309dd1894fc36c967d6bce94605
@@ -373,12 +391,14 @@ SPEC CHECKSUMS:
DDLogKit_Private: 1ed442cc7be004bd05f27bfda9b525e113df54e0
DDMAMapKit_Private: 8e70d3f58cb70ce30705a2f10d696e42878ce52d
DDNetworkingOfAlamofireKit_Private: d65c96f99bc59311d374e7b7a7e8a9e042d9b5ea
DDProgressHUDKit_Private: 2046b3cc10a6fe4c7bd454b7431fe80efdd58923
DDProgressHUDKit_Private: 2523d52ac5566bfde304456abfe2aac3cbf75c59
DDTimerKit_Private: 3713d029a72710f42a5dd5a32083d6aad8f51eb0
DDToastKit_Private: b6ae3709d110cadca503a037419f3709d1755256
DDWebImageKit_Private: b905111547e44626773b729bae9030403a9a0c76
ESTabBarController-swift: 05593a6ad64700b03c0eb60ff625916370aa4136
IQKeyboardManagerSwift: 371b08cb39664fb56030f5345c815a4ffc74bbc0
JCore: d994e32edb50add8a33135473acca799d882c5fa
JPush: bf8d6011eb80c776aa40a0c4f5c25fd10335af9c
JXCategoryView: 7b1ee69ede4843c581688afe84d0f047723262f2
MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
RxCocoa: 94f817b71c07517321eb4f9ad299112ca8af743b
@@ -386,9 +406,10 @@ SPEC CHECKSUMS:
RxSwift: 5710a9e6b17f3c3d6e40d6e559b9fa1e813b2ef8
SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25
SwiftEntryKit: 61b5fa36f34a97dd8013e48a7345bc4c4720be9a
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
ZFPlayer: ba6410f1043fc8a3b7769749f860cf237016df09
ZLPhotoBrowser: 0563c2bfc7b247b65d023d646012f46cba94101b
PODFILE CHECKSUM: 35f200a29520ee2712b22639b1f230ab047e1457
PODFILE CHECKSUM: bcbd7bb02cdf74bee6af46549ebabe072e53ecf7
COCOAPODS: 1.11.3

BIN
Pods/.DS_Store generated vendored Normal file

Binary file not shown.

104
Pods/CocoaDebug/README.md generated Normal file
View File

@@ -0,0 +1,104 @@
| <img alt="logo" src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/logo.png" width="250"/> | <ul align="left"><li><a href="#introduction">Introduction</a><li><a href="#installation">Installation</a><li><a href="#usage">Usage</a><li><a href="#parameters">Parameters</a></ul> |
| -------------- | -------------- |
| Version | [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/CocoaDebug.svg)](https://img.shields.io/cocoapods/v/CocoaDebug.svg) |
| Platform | ![Platform](https://img.shields.io/badge/platforms-iOS%2012.0+-blue.svg) |
| Languages | ![Languages](https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-blue.svg) |
<span style="float:none" />
## Screenshot
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a1.png" width="250">
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a2.png" width="250">
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a3.png" width="250">
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a4.png" width="250">
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a5.png" width="250">
<img src="https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/pic/a6.png" width="250">
## Introduction
- [x] Shake to hide or show the black bubble. (Support iPhone device and simulator)
- [x] Share network details via email or copy to clipboard when you are in the *Network Details* page.
- [x] Copy logs. (Long press the text, then select all or select copy)
- [x] Search logs by keyword.
- [x] Long press the black bubble to clean all network logs.
- [x] Detect *UI Blocking*.
- [x] List crash errors.
- [x] List application and device informations, including: *version*, *build*, *bundle name*, *bundle id*, *screen resolution*, *device*, *iOS version*
- [x] List all network requests sent by the application. (Support *JSON* and Google's *Protocol buffers*)
- [x] List all sandbox folders and files, supporting to preview and edit.
- [x] List all *WKWebView* consoles.
- [x] List all *React Native* JavaScript consoles and Native logs.
- [x] List all *print()* and *NSLog()* messages which have been written by developer in Xcode.
## Installation
### *CocoaPods* *(Preferred)*
```ruby
target 'YourTargetName' do
use_frameworks!
pod 'CocoaDebug', :configurations => ['Debug']
end
```
### *Carthage*
```ruby
github "CocoaDebug/CocoaDebug"
```
### *Framework*
*[CocoaDebug.framework](https://raw.githubusercontent.com/CocoaDebug/CocoaDebug/master/CocoaDebug.framework.zip) (Version 1.7.2)*
> WARNING: Never ship a product which has been linked with the CocoaDebug framework. The [Integration Guide](https://github.com/CocoaDebug/CocoaDebug/wiki/Integration-Guide) outline a way to use build configurations to isolate linking the framework to Debug builds.
## Usage
- Don't need to do anything. CocoaDebug will start automatically.
- To capture logs from Xcode with codes: (You can also set this in *CocoaDebug->App->Monitor->Applogs* without any codes.)
```swift
CocoaDebugSettings.shared.enableLogMonitoring = true //The default value is false
```
- Check [AppDelegate.m](https://github.com/CocoaDebug/CocoaDebug/blob/master/Example_Objc/Example_Objc/AppDelegate.m) OR [AppDelegate.swift](https://github.com/CocoaDebug/CocoaDebug/blob/master/Example_Swift/Example_Swift/AppDelegate.swift) for more advanced usage.
## Parameters
When you initialize CocoaDebug, you can customize the following parameter values before `CocoaDebug.enable()`.
- `serverURL` - If the captured URLs contain server URL, CocoaDebug set server URL bold font to be marked. Not mark when this value is nil. Default value is **nil**.
- `ignoredURLs` - Set the URLs which should not been captured, CocoaDebug capture all URLs when the value is nil. Default value is **nil**.
- `onlyURLs` - Set the URLs which are only been captured, CocoaDebug capture all URLs when the value is nil. Default value is **nil**.
- `ignoredPrefixLogs` - Set the prefix Logs which should not been captured, CocoaDebug capture all Logs when the value is nil. Default value is **nil**.
- `onlyPrefixLogs` - Set the prefix Logs which are only been captured, CocoaDebug capture all Logs when the value is nil. Default value is **nil**.
- `additionalViewController` - Add an additional UIViewController as child controller of CocoaDebug's main UITabBarController. Default value is **nil**.
- `emailToRecipients` - Set the initial recipients to include in the emails “To” field when share via email. Default value is **nil**.
- `emailCcRecipients` - Set the initial recipients to include in the emails “Cc” field when share via email. Default value is **nil**.
- `mainColor` - Set CocoaDebug's main color with hexadecimal format. Default value is **#42d459**.
- `protobufTransferMap` - Protobuf data transfer to JSON map. Default value is **nil**.
## Reference
[https://developer.apple.com/library/archive/samplecode/CustomHTTPProtocol/Introduction/Intro.html](https://developer.apple.com/library/archive/samplecode/CustomHTTPProtocol/Introduction/Intro.html)

View File

@@ -0,0 +1,37 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
import UIKit
class AboutViewController: UITableViewController {
@IBOutlet weak var versionLabel: UILabel!
@IBOutlet weak var naviItem: UINavigationItem!
var naviItemTitleLabel: UILabel?
//MARK: - init
override func viewDidLoad() {
super.viewDidLoad()
naviItemTitleLabel = UILabel.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40))
naviItemTitleLabel?.textAlignment = .center
naviItemTitleLabel?.textColor = Color.mainGreen
naviItemTitleLabel?.font = .boldSystemFont(ofSize: 20)
naviItemTitleLabel?.text = "About"
naviItem.titleView = naviItemTitleLabel
// let version = "1.7.2"
//
// self.versionLabel.text = "CocoaDebug Version ".appending(version)
tableView.tableFooterView = UIView()
}
}

View File

@@ -0,0 +1,217 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
class AppInfoViewController: UITableViewController {
@IBOutlet weak var labelVersionNumber: UILabel!
@IBOutlet weak var labelBuildNumber: UILabel!
@IBOutlet weak var labelBundleName: UILabel!
@IBOutlet weak var labelScreenResolution: UILabel!
@IBOutlet weak var labelDeviceModel: UILabel!
@IBOutlet weak var labelCrashCount: UILabel!
@IBOutlet weak var labelBundleID: UILabel!
@IBOutlet weak var labelserverURL: UILabel!
@IBOutlet weak var labelIOSVersion: UILabel!
@IBOutlet weak var labelHtml: UILabel!
@IBOutlet weak var crashSwitch: UISwitch!
@IBOutlet weak var logSwitch: UISwitch!
@IBOutlet weak var networkSwitch: UISwitch!
@IBOutlet weak var webViewSwitch: UISwitch!
@IBOutlet weak var slowAnimationsSwitch: UISwitch!
@IBOutlet weak var naviItem: UINavigationItem!
@IBOutlet weak var rnSwitch: UISwitch!
@IBOutlet weak var uiBlockingSwitch: UISwitch!
var naviItemTitleLabel: UILabel?
//MARK: - init
override func viewDidLoad() {
super.viewDidLoad()
naviItemTitleLabel = UILabel.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40))
naviItemTitleLabel?.textAlignment = .center
naviItemTitleLabel?.textColor = Color.mainGreen
naviItemTitleLabel?.font = .boldSystemFont(ofSize: 20)
naviItemTitleLabel?.text = "App"
naviItem.titleView = naviItemTitleLabel
labelCrashCount.frame.size = CGSize(width: 30, height: 20)
labelVersionNumber.text = CocoaDebugDeviceInfo.sharedInstance().appVersion
labelBuildNumber.text = CocoaDebugDeviceInfo.sharedInstance().appBuiltVersion
labelBundleName.text = CocoaDebugDeviceInfo.sharedInstance().appBundleName
labelScreenResolution.text = "\(Int(CocoaDebugDeviceInfo.sharedInstance().resolution.width))" + "*" + "\(Int(CocoaDebugDeviceInfo.sharedInstance().resolution.height))"
labelDeviceModel.text = "\(CocoaDebugDeviceInfo.sharedInstance().getPlatformString)"
labelBundleID.text = CocoaDebugDeviceInfo.sharedInstance().appBundleID
labelserverURL.text = CocoaDebugSettings.shared.serverURL
labelIOSVersion.text = UIDevice.current.systemVersion
if UIScreen.main.bounds.size.width == 320 {
labelHtml.font = UIFont.systemFont(ofSize: 15)
}
logSwitch.isOn = CocoaDebugSettings.shared.enableLogMonitoring
networkSwitch.isOn = !CocoaDebugSettings.shared.disableNetworkMonitoring
rnSwitch.isOn = CocoaDebugSettings.shared.enableRNMonitoring
webViewSwitch.isOn = CocoaDebugSettings.shared.enableWKWebViewMonitoring
slowAnimationsSwitch.isOn = CocoaDebugSettings.shared.slowAnimations
crashSwitch.isOn = CocoaDebugSettings.shared.enableCrashRecording
uiBlockingSwitch.isOn = CocoaDebugSettings.shared.enableUIBlockingMonitoring
logSwitch.addTarget(self, action: #selector(logSwitchChanged), for: UIControl.Event.valueChanged)
networkSwitch.addTarget(self, action: #selector(networkSwitchChanged), for: UIControl.Event.valueChanged)
rnSwitch.addTarget(self, action: #selector(rnSwitchChanged), for: UIControl.Event.valueChanged)
webViewSwitch.addTarget(self, action: #selector(webViewSwitchChanged), for: UIControl.Event.valueChanged)
slowAnimationsSwitch.addTarget(self, action: #selector(slowAnimationsSwitchChanged), for: UIControl.Event.valueChanged)
crashSwitch.addTarget(self, action: #selector(crashSwitchChanged), for: UIControl.Event.valueChanged)
uiBlockingSwitch.addTarget(self, action: #selector(uiBlockingSwitchChanged), for: UIControl.Event.valueChanged)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let count = UserDefaults.standard.integer(forKey: "crashCount_CocoaDebug")
labelCrashCount.text = "\(count)"
labelCrashCount.textColor = count > 0 ? .red : .white
}
//MARK: - alert
func showAlert() {
let alert = UIAlertController.init(title: nil, message: "You must restart APP to ensure the changes take effect", preferredStyle: .alert)
let cancelAction = UIAlertAction.init(title: "Restart later", style: .cancel, handler: nil)
let okAction = UIAlertAction.init(title: "Restart now", style: .destructive) { _ in
exit(0)
}
alert.addAction(cancelAction)
alert.addAction(okAction)
alert.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
alert.popoverPresentationController?.sourceView = self.view
alert.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(alert, animated: true, completion: nil)
}
//MARK: - target action
@objc func slowAnimationsSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.slowAnimations = slowAnimationsSwitch.isOn
// self.showAlert()
}
@objc func uiBlockingSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.enableUIBlockingMonitoring = uiBlockingSwitch.isOn
if uiBlockingSwitch.isOn == true {
WindowHelper.shared.startUIBlockingMonitoring()
} else {
WindowHelper.shared.stopUIBlockingMonitoring()
}
}
@objc func crashSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.enableCrashRecording = crashSwitch.isOn
self.showAlert()
}
@objc func networkSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.disableNetworkMonitoring = !networkSwitch.isOn
self.showAlert()
}
@objc func logSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.enableLogMonitoring = logSwitch.isOn
self.showAlert()
}
@objc func rnSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.enableRNMonitoring = rnSwitch.isOn
self.showAlert()
}
@objc func webViewSwitchChanged(sender: UISwitch) {
CocoaDebugSettings.shared.enableWKWebViewMonitoring = webViewSwitch.isOn
self.showAlert()
}
}
//MARK: - UITableViewDelegate
extension AppInfoViewController {
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
if section == 0 {
return 56
}
return 38
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.section == 1 && indexPath.row == 4 {
if labelserverURL.text == nil || labelserverURL.text == "" {
return 0
}
}
return 44
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
tableView.deselectRow(at: indexPath, animated: true)
if indexPath.section == 1 && indexPath.row == 2 {
UIPasteboard.general.string = CocoaDebugDeviceInfo.sharedInstance().appBundleName
let alert = UIAlertController.init(title: "copied bundle name to clipboard", message: nil, preferredStyle: .alert)
let action = UIAlertAction.init(title: "OK", style: .cancel, handler: nil)
alert.addAction(action)
alert.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
alert.popoverPresentationController?.sourceView = self.view
alert.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(alert, animated: true, completion: nil)
}
if indexPath.section == 1 && indexPath.row == 3 {
UIPasteboard.general.string = CocoaDebugDeviceInfo.sharedInstance().appBundleID
let alert = UIAlertController.init(title: "copied bundle id to clipboard", message: nil, preferredStyle: .alert)
let action = UIAlertAction.init(title: "OK", style: .cancel, handler: nil)
alert.addAction(action)
alert.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
alert.popoverPresentationController?.sourceView = self.view
alert.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(alert, animated: true, completion: nil)
}
if indexPath.section == 1 && indexPath.row == 4 {
if labelserverURL.text == nil || labelserverURL.text == "" {return}
UIPasteboard.general.string = CocoaDebugSettings.shared.serverURL
let alert = UIAlertController.init(title: "copied server to clipboard", message: nil, preferredStyle: .alert)
let action = UIAlertAction.init(title: "OK", style: .cancel, handler: nil)
alert.addAction(action)
alert.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
alert.popoverPresentationController?.sourceView = self.view
alert.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(alert, animated: true, completion: nil)
}
}
}

View File

@@ -0,0 +1,41 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
class CrashCell: UITableViewCell {
@IBOutlet weak var textview: CustomTextView!
override func awakeFromNib() {
super.awakeFromNib()
textview.isUserInteractionEnabled = false
}
var crash: _CrashModel? {
didSet {
guard let crash = crash else {return}
if let formatDate = _OCLoggerFormat.formatDate(crash.date) {
let content = "\("\(String(describing: formatDate))\n")\(crash.name ?? "unknown crash")"
textview.text = content
let attstr = NSMutableAttributedString(string: content)
attstr.addAttribute(.foregroundColor,
value: UIColor.white, range: NSMakeRange(0, content.count))
let range = NSMakeRange(0, formatDate.count)
attstr.addAttribute(.foregroundColor, value: Color.mainGreen, range: range)
attstr.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 12), range: range)
textview.attributedText = attstr
}
}
}
}

View File

@@ -0,0 +1,62 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
class CrashDetailViewController: UITableViewController {
@IBOutlet weak var textviewName: CustomTextView!
@IBOutlet weak var textviewReason: CustomTextView!
@IBOutlet weak var textviewStackTraces: CustomTextView!
@IBOutlet weak var naviItem: UINavigationItem!
var naviItemTitleLabel: UILabel?
var crash: _CrashModel?
static func instanceFromStoryBoard() -> CrashDetailViewController {
let storyboard = UIStoryboard(name: "App", bundle: Bundle(for: CocoaDebug.self))
return storyboard.instantiateViewController(withIdentifier: "CrashDetailViewController") as! CrashDetailViewController
}
//MARK - init
override func viewDidLoad() {
super.viewDidLoad()
naviItemTitleLabel = UILabel.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40))
naviItemTitleLabel?.textAlignment = .center
naviItemTitleLabel?.textColor = Color.mainGreen
naviItemTitleLabel?.font = .boldSystemFont(ofSize: 20)
naviItemTitleLabel?.text = "Details"
naviItem.titleView = naviItemTitleLabel
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 50
tableView.delegate = self
textviewName.text = "\(crash?.name ?? "N/A")"
textviewReason.text = "\(crash?.reason ?? "N/A")"
let contentStack = crash?.callStacks?.reduce("", {
$0 == "" ? $1 : $0 + "\n" + $1
})
textviewStackTraces.text = contentStack
}
}
//MARK: - UITableViewDelegate
extension CrashDetailViewController {
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
}

View File

@@ -0,0 +1,115 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
class CrashListViewController: UITableViewController {
var models: [_CrashModel] = [_CrashModel]()
@IBOutlet weak var naviItem: UINavigationItem!
var naviItemTitleLabel: UILabel?
//MARK: - init
override func viewDidLoad() {
super.viewDidLoad()
naviItemTitleLabel = UILabel.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40))
naviItemTitleLabel?.textAlignment = .center
naviItemTitleLabel?.textColor = Color.mainGreen
naviItemTitleLabel?.font = .boldSystemFont(ofSize: 20)
naviItemTitleLabel?.text = "Crash"
naviItem.titleView = naviItemTitleLabel
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action:#selector(CrashListViewController.deleteCrashes))
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
models = CrashStoreManager.shared.crashArray
tableView.reloadData()
}
//MARK: - target action
@objc func deleteCrashes() {
models = []
CrashStoreManager.shared.resetCrashs()
// dispatch_main_async_safe { [weak self] in
tableView.reloadData()
// }
}
}
//MARK: - UITableViewDataSource
extension CrashListViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CrashCell", for: indexPath)
as! CrashCell
cell.crash = models[indexPath.row]
cell.accessoryType = .none
return cell
}
}
//MARK: - UITableViewDelegate
extension CrashListViewController {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let vc = CrashDetailViewController.instanceFromStoryBoard()
vc.crash = models[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
@available(iOS 11.0, *)
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .destructive, title: "Delete") { [weak self] (action, sourceView, completionHandler) in
guard let models = self?.models else {return}
CrashStoreManager.shared.removeCrash(models[indexPath.row])
self?.models.remove(at: indexPath.row)
// self?.dispatch_main_async_safe { [weak self] in
self?.tableView.deleteRows(at: [indexPath], with: .automatic)
// }
completionHandler(true)
}
return UISwipeActionsConfiguration(actions: [delete])
}
//MARK: - only for ios8/ios9/ios10, not ios11
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "Delete"
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if (editingStyle == .delete) {
CrashStoreManager.shared.removeCrash(models[indexPath.row])
self.models.remove(at: indexPath.row)
// self.dispatch_main_async_safe { [weak self] in
self.tableView.deleteRows(at: [indexPath], with: .automatic)
// }
}
}
}

View File

@@ -0,0 +1,98 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
import Darwin
func exceptionHandler(exception: NSException) {
if CrashLogger.shared.crashed {
return
}
CrashLogger.shared.crashed = true
CrashLogger.addCrash(name: exception.name.rawValue, reason: exception.reason)
}
func handleSignal(signal: Int32) {
if CrashLogger.shared.crashed {
return
}
CrashLogger.shared.crashed = true
switch signal {
case SIGILL:
CrashLogger.addCrash(name: "SIGILL", reason: nil)
case SIGABRT:
CrashLogger.addCrash(name: "SIGABRT", reason: nil)
case SIGFPE:
CrashLogger.addCrash(name: "SIGFPE", reason: nil)
case SIGBUS:
CrashLogger.addCrash(name: "SIGBUS", reason: nil)
case SIGSEGV:
CrashLogger.addCrash(name: "SIGSEGV", reason: nil)
case SIGSYS:
CrashLogger.addCrash(name: "SIGSYS", reason: nil)
case SIGPIPE:
CrashLogger.addCrash(name: "SIGPIPE", reason: nil)
case SIGTRAP:
CrashLogger.addCrash(name: "SIGTRAP", reason: nil)
default: break
}
}
class CrashLogger {
static let shared = CrashLogger()
private init() {}
var hasBeenRegistered = false
var crashed = false
var enable: Bool = false {
didSet {
if enable {
CrashLogger.shared.register()
}
else {
CrashLogger.shared.unregister()
}
}
}
func register() {
if hasBeenRegistered == false {
hasBeenRegistered = true
NSSetUncaughtExceptionHandler(exceptionHandler)
signal(SIGILL, handleSignal)
signal(SIGABRT, handleSignal)
signal(SIGFPE, handleSignal)
signal(SIGBUS, handleSignal)
signal(SIGSEGV, handleSignal)
signal(SIGSYS, handleSignal)
signal(SIGPIPE, handleSignal)
signal(SIGTRAP, handleSignal)
}
}
func unregister() {
if hasBeenRegistered == true {
hasBeenRegistered = false
NSSetUncaughtExceptionHandler(nil)
signal(SIGILL, SIG_DFL)
signal(SIGABRT, SIG_DFL)
signal(SIGFPE, SIG_DFL)
signal(SIGBUS, SIG_DFL)
signal(SIGSEGV, SIG_DFL)
signal(SIGSYS, SIG_DFL)
signal(SIGPIPE, SIG_DFL)
signal(SIGTRAP, SIG_DFL)
}
}
static func addCrash(name: String, reason: String?) {
let newCrash = _CrashModel(name: name, reason: reason)
CrashStoreManager.shared.addCrash(newCrash)
}
}

View File

@@ -0,0 +1,79 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
class CrashStoreManager {
var crashArray: [_CrashModel] = [_CrashModel]()
static let shared = CrashStoreManager()
private init() {
crashArray = self.getCrashs()
}
//MARK: - public
func addCrash(_ crash: _CrashModel) {
if self.crashArray.count >= 1000 {
if self.crashArray.count > 0 {
self.crashArray.remove(at: 0)
}
}
self.crashArray.append(crash)
archiveCrashs(self.crashArray)
}
func removeCrash(_ model: _CrashModel) {
if let index = self.crashArray.firstIndex(where: { (crash) -> Bool in
return crash.id == model.id
}) {
self.crashArray.remove(at: index)
}
archiveCrashs(self.crashArray)
}
func resetCrashs() {
if self.crashArray.count > 0 {
self.crashArray.removeAll()
UserDefaults.standard.removeObject(forKey: "crashArchive_CocoaDebug")
UserDefaults.standard.removeObject(forKey: "crashCount_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
//MARK: - private
private func archiveCrashs(_ crashs: [_CrashModel]) {
do {
var dataArchive: Data
if #available(iOS 11.0, *) {
dataArchive = try NSKeyedArchiver.archivedData(withRootObject: crashs, requiringSecureCoding: false)
} else {
// Fallback on earlier versions
dataArchive = NSKeyedArchiver.archivedData(withRootObject: crashs)
}
UserDefaults.standard.set(dataArchive, forKey: "crashArchive_CocoaDebug")
UserDefaults.standard.set(crashs.count, forKey: "crashCount_CocoaDebug")
UserDefaults.standard.synchronize()
} catch {}
}
private func getCrashs() -> [_CrashModel] {
guard let data = UserDefaults.standard.object(forKey: "crashArchive_CocoaDebug") as? Data else {return []}
do {
if #available(iOS 9.0, *) {
let dataArchive = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
return dataArchive as! [_CrashModel]
} else {
// Fallback on earlier versions
return []
}
} catch {
return []
}
}
}

View File

@@ -0,0 +1,119 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
import UIKit
class IgnoredURLsViewController: UITableViewController {
var ignoredURLs: Array<String>?
var onlyURLs: Array<String>?
var ignoredPrefixLogs: Array<String>?
var onlyPrefixLogs: Array<String>?
@IBOutlet weak var naviItem: UINavigationItem!
var naviItemTitleLabel: UILabel?
//MARK: - init
override func viewDidLoad() {
super.viewDidLoad()
naviItemTitleLabel = UILabel.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40))
naviItemTitleLabel?.textAlignment = .center
naviItemTitleLabel?.textColor = Color.mainGreen
naviItemTitleLabel?.font = .boldSystemFont(ofSize: 20)
naviItemTitleLabel?.text = "Settings"
naviItem.titleView = naviItemTitleLabel
tableView.tableFooterView = UIView()
ignoredURLs = CocoaDebugSettings.shared.ignoredURLs
onlyURLs = CocoaDebugSettings.shared.onlyURLs
ignoredPrefixLogs = CocoaDebugSettings.shared.ignoredPrefixLogs
onlyPrefixLogs = CocoaDebugSettings.shared.onlyPrefixLogs
}
}
//MARK: - UITableViewDataSource
extension IgnoredURLsViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return 4
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return ignoredURLs?.count ?? 0
case 1:
return onlyURLs?.count ?? 0
case 2:
return ignoredPrefixLogs?.count ?? 0
case 3:
return onlyPrefixLogs?.count ?? 0
default:
break
}
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell.init(style: .default, reuseIdentifier: "CocoaDebugSettingsCell")
cell.textLabel?.textColor = .white
cell.contentView.backgroundColor = .black
cell.selectionStyle = .none
switch indexPath.section {
case 0:
cell.textLabel?.text = ignoredURLs?[indexPath.row]
case 1:
cell.textLabel?.text = onlyURLs?[indexPath.row]
case 2:
cell.textLabel?.text = ignoredPrefixLogs?[indexPath.row]
case 3:
cell.textLabel?.text = onlyPrefixLogs?[indexPath.row]
default:
break
}
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "ignored URLs"
case 1:
return "only URLs"
case 2:
return "ignored Prefix Logs"
case 3:
return "only Prefix Logs"
default:
break
}
return ""
}
}
//MARK: - UITableViewDelegate
extension IgnoredURLsViewController {
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 20
}
}

View File

@@ -0,0 +1,57 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import UIKit
class _CrashModel: NSObject, NSCoding {
var id: String
var date: Date
var reason: String?
var name: String?
var callStacks: [String]?
init(name: String, reason: String?) {
id = UUID().uuidString
date = Date()
self.reason = reason
self.name = name
callStacks = Thread.callStackSymbols
}
func encode(with aCoder: NSCoder) {
aCoder.encode(id, forKey: "id")
aCoder.encode(date, forKey: "date")
aCoder.encode(reason, forKey: "reason")
aCoder.encode(name, forKey: "name")
aCoder.encode(callStacks, forKey: "callstacks")
}
required init?(coder aDecoder: NSCoder) {
id = aDecoder.decodeObject(forKey: "id") as? String ?? ""
date = aDecoder.decodeObject(forKey: "date") as? Date ?? Date()
reason = aDecoder.decodeObject(forKey: "reason") as? String
name = aDecoder.decodeObject(forKey: "name") as? String
callStacks = aDecoder.decodeObject(forKey: "callstacks") as? [String]
}
func toString() -> String {
let stringContent = NSMutableString()
stringContent.append("Date: \(String(describing: _OCLoggerFormat.formatDate(date)))\n")
stringContent.append("Name: \(name ?? "N/A")\n")
stringContent.append("Reason: \(reason ?? "N/A")\n")
let stacks = (callStacks ?? []).reduce("", {
return "\($0)\($1)\n"
})
stringContent.append(stacks)
return stringContent as String
}
}

View File

@@ -0,0 +1,20 @@
////
//// Example
//// man.li
////
//// Created by man 11/11/2018.
//// Copyright © 2020 man. All rights reserved.
////
//
//#import <Protobuf/GPBMessage.h>
//
//@interface GPBMessage (CocoaDebug)
//
//- (id _Nullable)initWithDictionary:(NSDictionary *_Nullable)dict;
//
//- (NSDictionary *_Nullable)containerType;
//- (NSDictionary *_Nullable)nameMap;
//- (NSString *_Nullable)_JSONStringWithIgnoreFields:(NSArray * _Nullable)ignoreFields;
//- (NSDictionary *_Nullable)dictionaryWithIgnoreFields:(NSArray * _Nullable)ignoreFields;
//
//@end

View File

@@ -0,0 +1,411 @@
////
//// Example
//// man.li
////
//// Created by man 11/11/2018.
//// Copyright © 2020 man. All rights reserved.
////
//
//#import "GPBMessage+CocoaDebug.h"
//#import "NSObject+CocoaDebug.h"
//#import <objc/runtime.h>
//#import <objc/message.h>
//#import "GPBArray.h"
//
//@implementation GPBMessage (CocoaDebug)
//
//#pragma mark - Public Methods
//- (id)initWithDictionary:(NSDictionary *)dict {
// self = [self init];
// if (dict && [dict isKindOfClass:[NSDictionary class]]) {
// NSMutableDictionary<NSString *, NSString *> *keyMap = [NSMutableDictionary<NSString *, NSString *> dictionary];
// NSDictionary *nameMap = [self nameMap];
// for (NSString *keyName in nameMap) {
// id keyNameObject = [nameMap objectForKey:keyName];
// if ([keyNameObject isKindOfClass:[NSString class]]) {
// [keyMap setObject:keyName forKey:keyNameObject];
// }
// if ([keyNameObject isKindOfClass:[NSArray class]]) {
// for (id keyPath in (NSArray *)keyNameObject) {
// [keyMap setObject:keyName forKey:keyPath];
// }
// }
// }
// for (NSString *keyName in dict) {
// NSString *keyPath = [keyMap _stringForKey:keyName default:keyName];
// [self setKeyPath:keyPath value:[dict objectForKey:keyName]];
// }
// }
// return self;
//}
//
//- (NSDictionary *)containerType {
// return @{};
//}
//
//- (NSDictionary *)nameMap {
// return @{};
//}
//
//- (NSString *)_JSONStringWithIgnoreFields:(NSArray * _Nullable)ignoreFields {
// NSData *data = [NSJSONSerialization dataWithJSONObject:[self dictionaryWithIgnoreFields:ignoreFields] options:kNilOptions error:nil];
// return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//}
//
//#pragma mark - Private Methods
//- (NSDictionary *)dictionaryWithIgnoreFields:(NSArray * _Nullable)ignoreFields {
// NSMutableDictionary *dict = [NSMutableDictionary dictionary];
//
// unsigned int count;
// objc_property_t *properties = class_copyPropertyList([self class], &count);
// for (unsigned int i = 0; i < count; i++) {
// const char *propertyName = property_getName(properties[i]);
// NSString *keyPath = [NSString stringWithUTF8String:propertyName];
//
// id serializeObject = [self serializeValueForKey:keyPath];
// if (nil == serializeObject) {
// continue;
// }
// id keyNameObject = [[self nameMap] objectForKey:keyPath];
//
// if (keyNameObject == nil && ![ignoreFields containsObject:keyPath]) {
// [dict setObject:serializeObject forKey:keyPath];
// }
// if ([keyNameObject isKindOfClass:[NSString class]] && ![ignoreFields containsObject:keyNameObject]) {
// [dict setObject:serializeObject forKey:keyNameObject];
// }
// if ([keyNameObject isKindOfClass:[NSArray class]] && ![ignoreFields containsObject:keyNameObject]) {
// NSString *keyName = [keyNameObject objectAtIndex:0]; // Serialize only the first value
// [dict setObject:serializeObject forKey:keyName];
// }
// }
// free(properties);
// return dict;
//}
//
//- (NSDictionary *)dictionary {
// return [self dictionaryWithIgnoreFields:nil];
//}
//
//- (id)serializeValueForKey:(NSString *)keyPath {
// id item = [self valueForKey:keyPath];
// if ([item isKindOfClass:[NSNumber class]] || [item isKindOfClass:[NSString class]]) {
// return item;
// }
// if ([item isKindOfClass:[GPBMessage class]]) {
// return [item dictionary];
// }
// if ([item isKindOfClass:[GPBInt32Array class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBInt32Array *itemArray = (GPBInt32Array *)item;
// [itemArray enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBUInt32Array class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBUInt32Array *itemArray = (GPBUInt32Array *)item;
// [itemArray enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBInt64Array class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBInt64Array *itemArray = (GPBInt64Array *)item;
// [itemArray enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBUInt64Array class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBUInt64Array *itemArray = (GPBUInt64Array *)item;
// [itemArray enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBFloatArray class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBFloatArray *itemArray = (GPBFloatArray *)item;
// [itemArray enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBDoubleArray class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBDoubleArray *itemArray = (GPBDoubleArray *)item;
// [itemArray enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBBoolArray class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBBoolArray *itemArray = (GPBBoolArray *)item;
// [itemArray enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[GPBEnumArray class]]) {
// NSMutableArray *array = [NSMutableArray array];
// GPBEnumArray *itemArray = (GPBEnumArray *)item;
// [itemArray enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL * _Nonnull stop) {
// [array addObject:@(value)];
// }];
// return array;
// }
// if ([item isKindOfClass:[NSArray class]]) {
// NSMutableArray *array = [NSMutableArray array];
// for (id arrayItem in item) {
// if ([arrayItem isKindOfClass:[NSNumber class]] || [arrayItem isKindOfClass:[NSString class]]) {
// [array addObject:arrayItem];
// continue;
// }
// if ([arrayItem isKindOfClass:[GPBMessage class]]) {
// [array addObject:[arrayItem dictionary]];
// }
// }
// return array;
// }
// return nil;
//}
//
//- (void)setKeyPath:(NSString *)keyPath value:(id)value {
// NSMutableArray *propertiesNameArray = [NSMutableArray<NSString *> array];
// NSMutableDictionary *propertiesTypeDic = [NSMutableDictionary<NSString *, NSString *> dictionary];
// unsigned int count;
// objc_property_t *properties = class_copyPropertyList([self class], &count);
// for (NSUInteger i = 0; i < count; i++) {
// objc_property_t property = properties[i];
// NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
// [propertiesNameArray addObject:propertyName];
//
// NSString *attr = [NSString stringWithUTF8String:&(property_getAttributes(property)[1])];
// NSString *type = [[attr componentsSeparatedByString:@","] objectAtIndex:0];
// [propertiesTypeDic setObject:type forKey:propertyName];
// }
// free(properties);
//
// NSString *type = [propertiesTypeDic _stringForKey:keyPath default:@""];
// SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [keyPath substringToIndex:1].uppercaseString, [keyPath substringFromIndex:1]]);
//
// if ([value isKindOfClass:[NSString class]] == YES) {
// NSString *str = (NSString *)value;
// if ([type isEqualToString:@"@\"NSString\""]) {
// ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)self, setter, str);
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(bool)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require bool but string", self, keyPath);
// ((void (*)(id, SEL, bool))(void *) objc_msgSend)(self, setter, str.boolValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(BOOL)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require BOOL but string", self, keyPath);
// ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)(self, setter, str.boolValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(int32_t)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require int32_t but string", self, keyPath);
// ((void (*)(id, SEL, int32_t))(void *) objc_msgSend)(self, setter, (int32_t)str.intValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(uint32_t)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require uint32_t but string", self, keyPath);
// NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
// [numberFormatter setNumberStyle:NSNumberFormatterNoStyle];
// NSNumber *num = [numberFormatter numberFromString:str];
// ((void (*)(id, SEL, uint32_t))(void *) objc_msgSend)(self, setter, (uint32_t)num.unsignedIntValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(int64_t)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require int64_t but string", self, keyPath);
// ((void (*)(id, SEL, int64_t))(void *) objc_msgSend)(self, setter, (int64_t)str.longLongValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(uint64_t)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require uint64_t but string", self, keyPath);
// NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
// [numberFormatter setNumberStyle:NSNumberFormatterNoStyle];
// NSNumber *num = [numberFormatter numberFromString:str];
// ((void (*)(id, SEL, uint64_t))(void *) objc_msgSend)(self, setter, (uint64_t)num.unsignedLongLongValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(float)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require float but string", self, keyPath);
// float f = str.floatValue;
// if (isnan(f) == NO && isinf(f) == NO) {
// ((void (*)(id, SEL, float))(void *) objc_msgSend)(self, setter, f);
// return;
// }
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(double)]]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require double but string", self, keyPath);
// double d = str.doubleValue;
// if (isnan(d) == NO && isinf(d) == NO) {
// ((void (*)(id, SEL, double))(void *) objc_msgSend)(self, setter, d);
// return;
// }
// }
// }
// if ([value isKindOfClass:[NSNumber class]] == YES) {
// NSNumber *number = (NSNumber *)value;
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(bool)]]) {
// ((void (*)(id, SEL, bool))(void *) objc_msgSend)(self, setter, number.boolValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(BOOL)]]) {
// ((void (*)(id, SEL, BOOL))(void *) objc_msgSend)(self, setter, number.boolValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(int32_t)]]) {
// ((void (*)(id, SEL, int32_t))(void *) objc_msgSend)(self, setter, (int32_t)number.intValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(uint32_t)]]) {
// ((void (*)(id, SEL, uint32_t))(void *) objc_msgSend)(self, setter, (uint32_t)number.unsignedIntValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(int64_t)]]) {
// ((void (*)(id, SEL, int64_t))(void *) objc_msgSend)(self, setter, (int64_t)number.longLongValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(uint64_t)]]) {
// ((void (*)(id, SEL, uint64_t))(void *) objc_msgSend)(self, setter, (uint64_t)number.longLongValue);
// return;
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(float)]]) {
// float f = number.floatValue;
// if (isnan(f) == NO && isinf(f) == NO) {
// ((void (*)(id, SEL, float))(void *) objc_msgSend)(self, setter, f);
// return;
// }
// }
// if ([type isEqualToString:[NSString stringWithUTF8String:@encode(double)]]) {
// double d = number.doubleValue;
// if (isnan(d) == NO && isinf(d) == NO) {
// ((void (*)(id, SEL, double))(void *) objc_msgSend)(self, setter, d);
// return;
// }
// }
// if ([type isEqualToString:@"@\"NSString\""]) {
// NSAssert([value isKindOfClass:[NSString class]], @"%@: property (%@) type mismatch, require string but number", self, keyPath);
// ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)self, setter, [number stringValue]);
// return;
// }
// }
// if (([type isEqualToString:@"@\"NSMutableArray\""] || [type isEqualToString:@"@\"NSArray\""]) && [value isKindOfClass:[NSArray class]] == YES) {
// NSMutableArray *array = [NSMutableArray array];
// for (id arrayValue in value) {
// if ([arrayValue isKindOfClass:[NSNumber class]] == YES || [arrayValue isKindOfClass:[NSString class]] == YES) {
// [array addObject:arrayValue];
// continue;
// }
// if ([arrayValue isKindOfClass:[NSDictionary class]] == YES) {
// NSString *arrayItemType = [[self containerType] _stringForKey:keyPath default:nil];
// if (arrayItemType == nil) {
// [array addObject:arrayValue];
// break;
// }
// Class itemClass = NSClassFromString(arrayItemType);
// if (!itemClass) {
// //SSPWarning(@"Can't find class of %@", arrayItemType);
// return;
// }
// Class parentClass = class_getSuperclass(itemClass);
// if ([parentClass isEqual:[GPBMessage class]] == NO) {
// //SSPWarning(@"%@ is not GPBMessage", arrayItemType);
// return;
// }
// [array addObject:[[itemClass alloc] initWithDictionary:arrayValue]];
// }
// if ([arrayValue isKindOfClass:[NSArray class]] == YES) {
// //SSPError(@"Not support NSArray in NSArray");
// return;
// }
// }
// ((void (*)(id, SEL, id))(void *) objc_msgSend)(self, setter, array);
// return;
// }
// if ([type hasPrefix:@"@\""] && [value isKindOfClass:[NSDictionary class]] == YES) {
// if ([type isEqualToString:@"@\"NSDictionary\""] || [type isEqualToString:@"@\"NSMutableDictionary\""]) {
// NSMutableDictionary *dictValue = [NSMutableDictionary dictionary];
// NSArray *dictTypes = [[self containerType] _arrayForKey:keyPath default:nil];
// if (dictTypes && [dictTypes count] == 2) {
// for (id dictKey in value) {
// Class itemClass = NSClassFromString(dictTypes[1]);
// if (!itemClass) {
// //SSPWarning(@"Can't find class of %@", dictTypes[1]);
// return;
// }
// if ([itemClass isEqual:[NSString class]]||[itemClass isEqual:[NSNumber class]]) {
// [dictValue setObject:value[dictKey] forKey:dictKey];
// continue;
// }
// Class parentClass = class_getSuperclass(itemClass);
// if ([parentClass isEqual:[GPBMessage class]] == NO) {
// //SSPWarning(@"%@ is not GPBMessage", dictTypes[1]);
// return;
// }
// [dictValue setObject:[[itemClass alloc] initWithDictionary:value[dictKey]] forKey:dictKey];
// }
// } else if (dictTypes && [dictTypes count] == 3){
// for (id dictKey in value) {
// Class itemClass = NSClassFromString(dictTypes[1]);
// if (!itemClass || ![itemClass isEqual:[NSArray class]] || ![value[dictKey] isKindOfClass:[NSArray class]]) {
// //SSPWarning(@"Map<obj, Array> parse error!");
// return;
// }
// NSMutableArray *array = [NSMutableArray array];
// for (id arrayValue in value[dictKey]) {
// if ([arrayValue isKindOfClass:[NSNumber class]] == YES || [arrayValue isKindOfClass:[NSString class]] == YES) {
// [array addObject:arrayValue];
// continue;
// }
// if ([arrayValue isKindOfClass:[NSDictionary class]] == YES) {
// Class inItemClass = NSClassFromString(dictTypes[2]);
// if (!inItemClass) {
// //SSPWarning(@"Can't find class of %@", dictTypes[2]);
// return;
// }
// Class parentClass = class_getSuperclass(inItemClass);
// if ([parentClass isEqual:[GPBMessage class]] == NO) {
// //SSPWarning(@"%@ is not GPBMessage", dictTypes[2]);
// return;
// }
// [array addObject:[[inItemClass alloc] initWithDictionary:arrayValue]];
// }
// if ([arrayValue isKindOfClass:[NSArray class]] == YES) {
// //SSPError(@"Not support NSArray in NSArray");
// return;
// }
// }
// [dictValue setObject:array forKey:dictKey];
// }
// }
// ((void (*)(id, SEL, id))(void *) objc_msgSend)(self, setter, dictValue);
// return;
// }
//
// NSString *itemType = [type substringWithRange:NSMakeRange(2, [type length]-3)];
// Class itemClass = NSClassFromString(itemType);
// if (!itemClass) {
// //SSPWarning(@"Can't find class of %@", itemType);
// return;
// }
// Class parentClass = class_getSuperclass(itemClass);
// if ([parentClass isEqual:[GPBMessage class]] == NO) {
// //SSPWarning(@"%@ is not GPBMessage", itemType);
// return;
// }
// id item = [[itemClass alloc] initWithDictionary:value];
// ((void (*)(id, SEL, id))(void *) objc_msgSend)(self, setter, item);
// return;
// }
//}
//
//@end

View File

@@ -0,0 +1,84 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/*************************************************/
@interface NSData (CocoaDebug)
+ (NSData *_Nullable)dataWithInputStream:(NSInputStream *_Nullable)stream;
@end
/*************************************************/
@interface NSString (CocoaDebug)
- (CGFloat)heightWithFont:(UIFont *_Nullable)font constraintToWidth:(CGFloat)width;
@end
/*************************************************/
@interface NSURLRequest (CocoaDebug)
- (NSString *_Nullable)requestId;
- (void)setRequestId:(NSString *_Nullable)requestId;
- (NSNumber*_Nullable)startTime;
- (void)setStartTime:(NSNumber*_Nullable)startTime;
@end
/*************************************************/
@interface UIColor (CocoaDebug)
+ (UIColor *_Nullable)colorFromHexString:(NSString *_Nullable)hexString;
@end
/*************************************************/
@interface NSDictionary (CocoaDebug)
- (NSString *_Nullable)_stringForKey:(id<NSCopying>_Nullable)key;
- (NSArray *_Nullable)_arrayForKey:(id<NSCopying>_Nullable)key;
- (NSDictionary *_Nullable)_dictionaryForKey:(id<NSCopying>_Nullable)key;
- (NSInteger)_integerForKey:(id<NSCopying>_Nullable)key;
- (int64_t)_int64ForKey:(id<NSCopying>_Nullable)key;
- (int32_t)_int32ForKey:(id<NSCopying>_Nullable)key;
- (float)_floatForKey:(id<NSCopying>_Nullable)key;
- (double)_doubleForKey:(id<NSCopying>_Nullable)key;
- (BOOL)_boolForKey:(id<NSCopying>_Nullable)key;
- (NSString *_Nullable)_stringForKey:(id<NSCopying>_Nullable)key default:(NSString * _Nullable)defaultValue;
- (bool)_boolForKey:(id<NSCopying>_Nullable)key default:(bool)defaultValue;
- (NSInteger)_integerForKey:(id<NSCopying>_Nullable)key default:(NSInteger)defaultValue;
- (float)_floatForKey:(id<NSCopying>_Nullable)key default:(float)defaultValue;
- (NSArray *_Nullable)_arrayForKey:(id<NSCopying>_Nullable)key default:(NSArray * _Nullable)defaultValue;
- (NSDictionary *_Nullable)_dictionaryForKey:(id<NSCopying>_Nullable)key default:(NSDictionary * _Nullable)defaultValue;
@end
/*************************************************/
@interface UIImage (CocoaDebug)
//Obtain the GIF image object according to the data data of a GIF image
+ (UIImage *_Nullable)imageWithGIFData:(NSData *_Nullable)data;
//Obtain the GIF image object according to the name of the local GIF image
+ (UIImage *_Nullable)imageWithGIFNamed:(NSString *_Nullable)name;
//Obtain the GIF image object according to the URL of a GIF image
+ (void)imageWithGIFUrl:(NSString *_Nullable)url gifImageBlock:(void(^_Nullable)(UIImage *_Nullable gifImage))gifImageBlock;
@end

View File

@@ -0,0 +1,367 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
#import "NSObject+CocoaDebug.h"
#import <objc/runtime.h>
#import <ImageIO/ImageIO.h>
/*************************************************/
@implementation NSData (CocoaDebug)
+ (NSData *)dataWithInputStream:(NSInputStream *)stream
{
NSMutableData * data = [NSMutableData data];
[stream open];
NSInteger result;
uint8_t buffer[1024]; // BUFFER_LEN can be any positive integer
while((result = [stream read:buffer maxLength:1024]) != 0) {
if (result > 0) {
// buffer contains result bytes of data to be handled
[data appendBytes:buffer length:result];
} else {
// The stream had an error. You can get an NSError object using [iStream streamError]
if (result < 0) {
// [NSException raise:@"STREAM_ERROR" format:@"%@", [stream streamError]];
return nil;//liman
}
}
}
return data;
}
@end
/*************************************************/
@implementation NSString (CocoaDebug)
- (CGFloat)heightWithFont:(UIFont *)font constraintToWidth:(CGFloat)width
{
CGRect rect = [self boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
return rect.size.height;
}
@end
/*************************************************/
@implementation NSURLRequest (CocoaDebug)
- (NSString *)requestId {
return objc_getAssociatedObject(self, @"requestId");
}
- (void)setRequestId:(NSString *)requestId {
objc_setAssociatedObject(self, @"requestId", requestId, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSNumber*)startTime {
return objc_getAssociatedObject(self, @"startTime");
}
- (void)setStartTime:(NSNumber*)startTime {
objc_setAssociatedObject(self, @"startTime", startTime, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/*************************************************/
@implementation UIColor (CocoaDebug)
+ (UIColor *)colorFromHexString:(NSString *)hexString
{
unsigned rgbValue = 0;
NSScanner *scanner = [NSScanner scannerWithString:hexString];
[scanner setScanLocation:1];
[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}
@end
/*************************************************/
@implementation NSDictionary (CocoaDebug)
- (NSString *)_stringForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if (![obj isKindOfClass:[NSString class]]) {
return nil;
}
return obj;
}
- (NSArray *)_arrayForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if (![obj isKindOfClass:[NSArray class]]) {
return nil;
}
return obj;
}
- (NSDictionary *)_dictionaryForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if (![obj isKindOfClass:[NSDictionary class]]) {
return nil;
}
return obj;
}
- (NSInteger)_integerForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) integerValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) integerValue];
}
return 0;
}
- (int64_t)_int64ForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) longLongValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) longLongValue];
}
return 0;
}
- (int32_t)_int32ForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) intValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) intValue];
}
return 0;
}
- (float)_floatForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) floatValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) floatValue];
}
return 0;
}
- (double)_doubleForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) doubleValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) doubleValue];
}
return 0;
}
- (BOOL)_boolForKey:(id<NSCopying>)key {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]]) {
return [((NSNumber *)obj) boolValue];
}
if ([obj isKindOfClass:[NSString class]]) {
return [((NSString *)obj) boolValue];
}
return NO;
}
- (NSString *)_stringForKey:(id<NSCopying>)key default:(NSString * _Nullable)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSString class]]) {
return obj;
}
return defaultValue;
}
- (bool)_boolForKey:(id<NSCopying>)key default:(bool)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSString class]]) {
return [obj boolValue];
}
return defaultValue;
}
- (NSInteger)_integerForKey:(id<NSCopying>)key default:(NSInteger)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSString class]]) {
return [obj integerValue];
}
return defaultValue;
}
- (float)_floatForKey:(id<NSCopying>)key default:(float)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSString class]]) {
return [obj floatValue];
}
return defaultValue;
}
- (NSArray *)_arrayForKey:(id<NSCopying>)key default:(NSArray * _Nullable)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSArray class]]) {
return obj;
}
return defaultValue;
}
- (NSDictionary *)_dictionaryForKey:(id<NSCopying>)key default:(NSDictionary * _Nullable)defaultValue {
id obj = [self objectForKey:key];
if ([obj isKindOfClass:[NSDictionary class]]) {
return obj;
}
return defaultValue;
}
@end
/*************************************************/
@implementation UIImage (CocoaDebug)
//Obtain the GIF image object according to the data data of a GIF image
+ (UIImage *_Nullable)imageWithGIFData:(NSData *_Nullable)data {
if (!data) return nil;
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
UIImage *animatedImage;
if (count <= 1) {
animatedImage = [[UIImage alloc] initWithData:data];
} else {
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval duration = 0.0f;
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
NSTimeInterval frameDuration = [UIImage ssz_frameDurationAtIndex:i source:source];
duration += frameDuration;
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CFRelease(image);
}
if (!duration) {
duration = (1.0f / 10.0f) * count;
}
animatedImage = [UIImage animatedImageWithImages:images duration:duration];
}
CFRelease(source);
return animatedImage;
}
//Obtain the GIF image object according to the name of the local GIF image
+ (UIImage *_Nullable)imageWithGIFNamed:(NSString *_Nullable)name {
NSUInteger scale = (NSUInteger)[UIScreen mainScreen].scale;
return [self GIFName:name scale:scale];
}
+ (UIImage *)GIFName:(NSString *)name scale:(NSUInteger)scale {
NSString *imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"];
if (!imagePath) {
(scale + 1 > 3) ? (scale -= 1) : (scale += 1);
imagePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@@%zdx", name, scale] ofType:@"gif"];
}
if (imagePath) {
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
return [UIImage imageWithGIFData:imageData];
} else {
imagePath = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
if (imagePath) {
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
return [UIImage imageWithGIFData:imageData];
} else {
return [UIImage imageNamed:name];
}
}
}
//Obtain the GIF image object according to the URL of a GIF image
+ (void)imageWithGIFUrl:(NSString *_Nullable)url gifImageBlock:(void(^_Nullable)(UIImage *_Nullable gifImage))gifImageBlock {
NSURL *GIFUrl = [NSURL URLWithString:url];
if (!GIFUrl) return;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSData *CIFData = [NSData dataWithContentsOfURL:GIFUrl];
dispatch_async(dispatch_get_main_queue(), ^{
gifImageBlock([UIImage imageWithGIFData:CIFData]);
});
});
}
+ (float)ssz_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
float frameDuration = 0.1f;
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
if (delayTimeUnclampedProp) {
frameDuration = [delayTimeUnclampedProp floatValue];
} else {
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
if (delayTimeProp) {
frameDuration = [delayTimeProp floatValue];
}
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See and
// for more information.
if (frameDuration < 0.011f) {
frameDuration = 0.100f;
}
CFRelease(cfFrameProperties);
return frameDuration;
}
@end

View File

@@ -0,0 +1,393 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
extension Dictionary {
///JSON/Form format conversion
func dictionaryToFormString() -> String? {
var array = [String]()
for (key, value) in self {
array.append(String(describing: key) + "=" + String(describing: value))
}
if array.count > 0 {
return array.joined(separator: "&")
}
return nil
}
}
extension String {
///JSON/Form format conversion
func formStringToDictionary() -> [String: Any]? {
var dictionary = [String: Any]()
let array = self.components(separatedBy: "&")
for str in array {
let arr = str.components(separatedBy: "=")
if arr.count == 2 {
dictionary.updateValue(arr[1], forKey: arr[0])
} else {
return nil
}
}
if dictionary.count > 0 {
return dictionary
}
return nil
}
}
//MARK: - *********************************************************************
extension Data {
func dataToDictionary() -> [String: Any]? {
do {
return try JSONSerialization.jsonObject(with: self, options: []) as? [String : Any]
} catch {
}
return nil
}
}
extension Dictionary {
func dictionaryToData() -> Data? {
do {
return try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
} catch {
}
return nil
}
}
extension Data {
func dataToString() -> String? {
return String(bytes: self, encoding: .utf8)
}
}
extension String {
func stringToData() -> Data? {
return self.data(using: .utf8)
}
}
//MARK: - *********************************************************************
extension String {
func stringToDictionary() -> [String: Any]? {
return self.stringToData()?.dataToDictionary()
}
}
extension Dictionary {
func dictionaryToString() -> String? {
return self.dictionaryToData()?.dataToString()
}
}
extension String {
func jsonStringToPrettyJsonString() -> String? {
return self.stringToDictionary()?.dictionaryToString()
}
}
extension String {
func isValidURL() -> Bool {
if let url = URL(string: self) {
return UIApplication.shared.canOpenURL(url)
}
return false
}
}
extension String {
func isValidJsonString() -> Bool {
if let _ = self.stringToDictionary() {
return true
}
return false
}
}
extension String {
func isValidFormString() -> Bool {
if let _ = self.formStringToDictionary() {
return true
}
return false
}
}
extension String {
func jsonStringToFormString() -> String? {
return self.stringToDictionary()?.dictionaryToFormString()
}
}
extension String {
func formStringToJsonString() -> String? {
return self.formStringToDictionary()?.dictionaryToString()
}
}
extension String {
func formStringToData() -> Data? {
return self.formStringToDictionary()?.dictionaryToData()
}
}
extension Data {
func formDataToDictionary() -> [String: Any]? {
return self.dataToString()?.formStringToDictionary()
}
}
extension Data {
func dataToPrettyPrintString() -> String? {
//1.pretty json
if let str = self.dataToDictionary()?.dictionaryToString() {
return str
} else {
//2.protobuf
// if let message = try? GPBMessage.parse(from: self) {
// if message.serializedSize() > 0 {
// return message.description
// } else {
// //3.utf-8 string
// return String(data: self, encoding: .utf8)
// }
// } else {
//3.utf-8 string
return String(data: self, encoding: .utf8)
// }
}
}
}
//MARK: - *********************************************************************
//https://gist.github.com/arshad/de147c42d7b3063ef7bc
///Color
extension String {
var hexColor: UIColor {
let hex = trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int = UInt32()
Scanner(string: hex).scanHexInt32(&int)
var a, r, g, b: UInt32
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
return .clear
}
return UIColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
}
}
extension UIView {
func addCorner(roundingCorners: UIRectCorner, cornerSize: CGSize) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: roundingCorners, cornerRadii: cornerSize)
let cornerLayer = CAShapeLayer()
cornerLayer.frame = bounds
cornerLayer.path = path.cgPath
self.layer.mask = cornerLayer
}
}
//extension NSObject {
// func dispatch_main_async_safe(callback: @escaping ()->Void ) {
// if Thread.isMainThread {
// callback()
// } else {
// DispatchQueue.main.async( execute: {
// callback()
// })
// }
// }
//}
//https://stackoverflow.com/questions/26244293/scrolltorowatindexpath-with-uitableview-does-not-work
///tableView
extension UITableView {
func tableViewScrollToBottom(animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
let numberOfSections = self.numberOfSections
let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.scrollToRow(at: indexPath, at: .bottom, animated: animated)
}
}
}
func tableViewScrollToIndex(index: Int, animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
self.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: animated)
}
}
func tableViewScrollToHeader(animated: Bool) {
self.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: animated)
}
func reloadData(completion: @escaping () -> ()) {
UIView.animate(withDuration: 0, animations: { self.reloadData()})
{_ in completion() }
}
}
///shake
extension UIWindow {
private static var _cocoadebugShakeProperty = [String:Bool]()
var cocoadebugShakeProperty:Bool {
get {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
return UIWindow._cocoadebugShakeProperty[tmpAddress] ?? false
}
set(newValue) {
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
UIWindow._cocoadebugShakeProperty[tmpAddress] = newValue
}
}
open override var canBecomeFirstResponder: Bool {
return true
}
open override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
super.motionBegan(motion, with: event)
self.cocoadebugShakeProperty = true
if CocoaDebugSettings.shared.responseShake == false {return}
if motion == .motionShake {
if CocoaDebugSettings.shared.visible == true { return }
CocoaDebugSettings.shared.showBubbleAndWindow = !CocoaDebugSettings.shared.showBubbleAndWindow
}
}
open override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
super.motionEnded(motion, with: event)
if self.cocoadebugShakeProperty == true {
self.cocoadebugShakeProperty = false
return
}
if CocoaDebugSettings.shared.responseShake == false {return}
if motion == .motionShake {
if CocoaDebugSettings.shared.visible == true { return }
CocoaDebugSettings.shared.showBubbleAndWindow = !CocoaDebugSettings.shared.showBubbleAndWindow
}
}
}
///CocoaDebug
extension CocoaDebug {
///init
static func initializationMethod(serverURL: String? = nil, ignoredURLs: [String]? = nil, onlyURLs: [String]? = nil, ignoredPrefixLogs: [String]? = nil, onlyPrefixLogs: [String]? = nil, additionalViewController: UIViewController? = nil, emailToRecipients: [String]? = nil, emailCcRecipients: [String]? = nil, mainColor: String? = nil, protobufTransferMap: [String: [String]]? = nil)
{
if serverURL == nil {
CocoaDebugSettings.shared.serverURL = ""
} else {
CocoaDebugSettings.shared.serverURL = serverURL
}
if ignoredURLs == nil {
CocoaDebugSettings.shared.ignoredURLs = []
} else {
CocoaDebugSettings.shared.ignoredURLs = ignoredURLs
}
if onlyURLs == nil {
CocoaDebugSettings.shared.onlyURLs = []
} else {
CocoaDebugSettings.shared.onlyURLs = onlyURLs
}
if ignoredPrefixLogs == nil {
CocoaDebugSettings.shared.ignoredPrefixLogs = []
} else {
CocoaDebugSettings.shared.ignoredPrefixLogs = ignoredPrefixLogs
}
if onlyPrefixLogs == nil {
CocoaDebugSettings.shared.onlyPrefixLogs = []
} else {
CocoaDebugSettings.shared.onlyPrefixLogs = onlyPrefixLogs
}
if CocoaDebugSettings.shared.firstIn == nil {//first launch
CocoaDebugSettings.shared.firstIn = ""
CocoaDebugSettings.shared.showBubbleAndWindow = true
} else {//not first launch
CocoaDebugSettings.shared.showBubbleAndWindow = CocoaDebugSettings.shared.showBubbleAndWindow
}
CocoaDebugSettings.shared.visible = false
CocoaDebugSettings.shared.logSearchWordNormal = nil
CocoaDebugSettings.shared.logSearchWordRN = nil
CocoaDebugSettings.shared.logSearchWordWeb = nil
CocoaDebugSettings.shared.networkSearchWord = nil
CocoaDebugSettings.shared.protobufTransferMap = protobufTransferMap
CocoaDebugSettings.shared.additionalViewController = additionalViewController
var _ = _OCLogStoreManager.shared()
CocoaDebugSettings.shared.responseShake = true
//share via email
CocoaDebugSettings.shared.emailToRecipients = emailToRecipients
CocoaDebugSettings.shared.emailCcRecipients = emailCcRecipients
//color
CocoaDebugSettings.shared.mainColor = mainColor ?? "#42d459"
//slow animations
CocoaDebugSettings.shared.slowAnimations = false
//log
let enableLogMonitoring = UserDefaults.standard.bool(forKey: "enableLogMonitoring_CocoaDebug")
if enableLogMonitoring == false {
_SwiftLogHelper.shared.enable = false
// _OCLogHelper.shared()?.enable = false
} else {
_SwiftLogHelper.shared.enable = true
// _OCLogHelper.shared()?.enable = true
}
//network
let disableNetworkMonitoring = UserDefaults.standard.bool(forKey: "disableNetworkMonitoring_CocoaDebug")
if disableNetworkMonitoring == true {
_NetworkHelper.shared().disable()
} else {
_NetworkHelper.shared().enable()
}
}
///deinit
static func deinitializationMethod() {
WindowHelper.shared.disable()
_NetworkHelper.shared().disable()
_SwiftLogHelper.shared.enable = false
// _OCLogHelper.shared()?.enable = false
CrashLogger.shared.enable = false
CocoaDebugSettings.shared.responseShake = false
}
}

View File

@@ -0,0 +1,40 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
#import "CocoaDebug.h"
#import "CocoaDebugTool.h"
#import "CocoaDebugDeviceInfo.h"
#import "NSObject+CocoaDebug.h"
#import "_fishhook.h"
#import "_FileInfo.h"
#import "_Swizzling.h"
#import "_ObjcLog.h"
#import "_Sandboxer.h"
#import "_HttpModel.h"
#import "_OCLogModel.h"
#import "_OCLogHelper.h"
#import "_NetworkHelper.h"
#import "_HttpDatasource.h"
#import "_ImageResources.h"
#import "_OCLoggerFormat.h"
#import "_RunloopMonitor.h"
#import "_BacktraceLogger.h"
#import "_ImageController.h"
#import "_SandboxerHelper.h"
#import "_CanonicalRequest.h"
#import "_Sandboxer-Header.h"
#import "_FileTableViewCell.h"
#import "_OCLogStoreManager.h"
#import "_DebugConsoleLabel.h"
#import "_CustomHTTPProtocol.h"
#import "_CacheStoragePolicy.h"
#import "_QNSURLSessionDemux.h"
#import "GPBMessage+CocoaDebug.h"
#import "_FilePreviewController.h"
#import "_DirectoryContentsTableViewController.h"

View File

@@ -0,0 +1,65 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
import UIKit
@objc public class CocoaDebug : NSObject {
///if the captured URLs contain server URL, CocoaDebug set server URL bold font to be marked. Not mark when this value is nil. Default value is `nil`.
@objc public static var serverURL: String? = nil
///set the URLs which should not been captured, CocoaDebug capture all URLs when the value is nil. Default value is `nil`.
@objc public static var ignoredURLs: [String]? = nil
///set the URLs which are only been captured, CocoaDebug capture all URLs when the value is nil. Default value is `nil`.
@objc public static var onlyURLs: [String]? = nil
///set the prefix Logs which should not been captured, CocoaDebug capture all Logs when the value is nil. Default value is `nil`.
@objc public static var ignoredPrefixLogs: [String]? = nil
///set the prefix Logs which are only been captured, CocoaDebug capture all Logs when the value is nil. Default value is `nil`.
@objc public static var onlyPrefixLogs: [String]? = nil
///add an additional UIViewController as child controller of CocoaDebug's main UITabBarController. Default value is `nil`.
@objc public static var additionalViewController: UIViewController? = nil
///set the initial recipients to include in the emails To field when share via email. Default value is `nil`.
@objc public static var emailToRecipients: [String]? = nil
///set the initial recipients to include in the emails Cc field when share via email. Default value is `nil`.
@objc public static var emailCcRecipients: [String]? = nil
///set CocoaDebug's main color with hexadecimal format. Default value is `#42d459`.
@objc public static var mainColor: String = "#42d459"
///protobuf url and response class transfer map. Default value is `nil`.
@objc public static var protobufTransferMap: [String: [String]]? = nil
//MARK: - CocoaDebug enable
@objc public static func enable() {
initializationMethod(serverURL: serverURL, ignoredURLs: ignoredURLs, onlyURLs: onlyURLs, ignoredPrefixLogs: ignoredPrefixLogs, onlyPrefixLogs: onlyPrefixLogs, additionalViewController: additionalViewController, emailToRecipients: emailToRecipients, emailCcRecipients: emailCcRecipients, mainColor: mainColor, protobufTransferMap: protobufTransferMap)
}
//MARK: - CocoaDebug disable
@objc public static func disable() {
deinitializationMethod()
}
//MARK: - hide Bubble
@objc public static func hideBubble() {
CocoaDebugSettings.shared.showBubbleAndWindow = false
}
//MARK: - show Bubble
@objc public static func showBubble() {
CocoaDebugSettings.shared.showBubbleAndWindow = true
}
}
//MARK: - override Swift `print` method
public func print<T>(file: String = #file, function: String = #function, line: Int = #line, _ message: T, color: UIColor = .white) {
Swift.print(message)
_SwiftLogHelper.shared.handleLog(file: file, function: function, line: line, message: message, color: color)
}

View File

@@ -0,0 +1,37 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
// https://github.com/maybeliu/MBDeviceTool_OC
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CocoaDebugDeviceInfo : NSObject
@property (nonatomic, assign, readonly) CGSize resolution;
@property (nonatomic, copy, readonly) NSString *systemType;
@property (nonatomic, copy, readonly) NSString *userName;
@property (nonatomic, copy, readonly) NSString *systemVersion;
@property (nonatomic, copy, readonly) NSString *deviceModel;
@property (nonatomic, copy, readonly) NSString *deviceUUID;
@property (nonatomic, copy, readonly) NSString *userPhoneName;
@property (nonatomic, copy, readonly) NSString *deviceName;
@property (nonatomic, copy, readonly) NSString *getPlatformString;
@property (nonatomic, copy, readonly) NSString *localizedModel;
@property (nonatomic, copy, readonly) NSString *appVersion;
@property (nonatomic, copy, readonly) NSString *appBuiltVersion;
@property (nonatomic, copy, readonly) NSString *appBundleID ;
@property (nonatomic, copy, readonly) NSString *appBundleName ;
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,89 @@
//
// CocoaDebug
// liman
//
// Created by liman 02/02/2023.
// Copyright © 2023 liman. All rights reserved.
//
#import "CocoaDebugDeviceInfo.h"
#import "sys/utsname.h"
#import "_DeviceUtil.h"
@implementation CocoaDebugDeviceInfo
+ (instancetype)sharedInstance {
static CocoaDebugDeviceInfo *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[CocoaDebugDeviceInfo alloc] init];
});
return sharedInstance;
}
- (NSString *)systemType {
return [[UIDevice currentDevice] systemName];
}
- (NSString *)userName {
return [[UIDevice currentDevice] name];
}
- (NSString *)systemVersion {
return [[UIDevice currentDevice] systemVersion];
}
- (NSString *)deviceModel {
return [[UIDevice currentDevice] model];
}
- (NSString *)deviceUUID {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
- (NSString *)deviceName {
struct utsname systemInfo;
uname(&systemInfo);
NSString *code = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
return code;
}
- (NSString *)getPlatformString {
return [[_DeviceUtil new] hardwareSimpleDescription];
}
- (NSString *)localizedModel {
return [[UIDevice currentDevice] localizedModel];
}
- (NSString *)appVersion {
return [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"];
}
- (NSString *)appBuiltVersion {
return [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
}
- (NSString *)appBundleID {
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
return bundleID;
}
- (NSString *)appBundleName {
NSString *bundleName = [[NSBundle mainBundle] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleNameKey];
return bundleName;
}
- (CGSize)resolution {
return CGSizeMake([UIScreen mainScreen].bounds.size.width * [[UIScreen mainScreen] scale], [UIScreen mainScreen].bounds.size.height * [[UIScreen mainScreen] scale]);
}
@end

View File

@@ -0,0 +1,277 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
import Foundation
@objc public class CocoaDebugSettings: NSObject {
@objc public static let shared = CocoaDebugSettings()
@objc public var slowAnimations: Bool = false {
didSet {
if slowAnimations == false {
UIApplication.shared.windows.first?.layer.speed = 1;
} else {
UIApplication.shared.windows.first?.layer.speed = 0.1;
}
}
}
@objc public var responseShake: Bool = false {
didSet {
UserDefaults.standard.set(responseShake, forKey: "responseShake_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var firstIn: String? = nil {
didSet {
UserDefaults.standard.set(firstIn, forKey: "firstIn_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableCrashRecording: Bool = false {
didSet {
UserDefaults.standard.set(enableCrashRecording, forKey: "enableCrashRecording_CocoaDebug")
UserDefaults.standard.synchronize()
if enableCrashRecording == true {
CrashLogger.shared.enable = true
} else {
CrashLogger.shared.enable = false
CrashStoreManager.shared.resetCrashs()
}
}
}
@objc public var enableUIBlockingMonitoring: Bool = false {
didSet {
UserDefaults.standard.set(enableUIBlockingMonitoring, forKey: "enableUIBlockingMonitoring_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableWKWebViewMonitoring: Bool = false {
didSet {
UserDefaults.standard.set(enableWKWebViewMonitoring, forKey: "enableWKWebViewMonitoring_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableLogMonitoring: Bool = false {
didSet {
UserDefaults.standard.set(enableLogMonitoring, forKey: "enableLogMonitoring_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var disableNetworkMonitoring: Bool = false {
didSet {
UserDefaults.standard.set(disableNetworkMonitoring, forKey: "disableNetworkMonitoring_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableRNMonitoring: Bool = false {
didSet {
UserDefaults.standard.set(enableRNMonitoring, forKey: "enableRNMonitoring_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableMemoryLeaksMonitoring_ViewController: Bool = false {
didSet {
UserDefaults.standard.set(enableMemoryLeaksMonitoring_ViewController, forKey: "enableMemoryLeaksMonitoring_UIViewController_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableMemoryLeaksMonitoring_View: Bool = false {
didSet {
UserDefaults.standard.set(enableMemoryLeaksMonitoring_View, forKey: "enableMemoryLeaksMonitoring_UIView_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var enableMemoryLeaksMonitoring_MemberVariables: Bool = false {
didSet {
UserDefaults.standard.set(enableMemoryLeaksMonitoring_MemberVariables, forKey: "enableMemoryLeaksMonitoring_MemberVariables_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var visible: Bool = false {
didSet {
UserDefaults.standard.set(visible, forKey: "visible_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var showBubbleAndWindow: Bool = false {
didSet {
UserDefaults.standard.set(showBubbleAndWindow, forKey: "showBubbleAndWindow_CocoaDebug")
UserDefaults.standard.synchronize()
let x = WindowHelper.shared.vc.bubble.frame.origin.x
let width = WindowHelper.shared.vc.bubble.frame.size.width
if showBubbleAndWindow == true
{
if x > UIScreen.main.bounds.size.width/2 {
WindowHelper.shared.vc.bubble.frame.origin.x = UIScreen.main.bounds.size.width - width/8*8.25
} else {
WindowHelper.shared.vc.bubble.frame.origin.x = -width + width/8*8.25
}
WindowHelper.shared.enable()
}
else
{
if x > UIScreen.main.bounds.size.width/2 {
WindowHelper.shared.vc.bubble.frame.origin.x = UIScreen.main.bounds.size.width
} else {
WindowHelper.shared.vc.bubble.frame.origin.x = -width
}
WindowHelper.shared.disable()
}
}
}
@objc public var serverURL: String? = nil {
didSet {
UserDefaults.standard.set(serverURL, forKey: "serverURL_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var tabBarSelectItem: Int {
didSet {
UserDefaults.standard.set(tabBarSelectItem, forKey: "tabBarSelectItem_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var logSelectIndex: Int {
didSet {
UserDefaults.standard.set(logSelectIndex, forKey: "logSelectIndex_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var networkLastIndex: Int {
didSet {
UserDefaults.standard.set(networkLastIndex, forKey: "networkLastIndex_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var bubbleFrameX: Float {
didSet {
UserDefaults.standard.set(bubbleFrameX, forKey: "bubbleFrameX_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var bubbleFrameY: Float {
didSet {
UserDefaults.standard.set(bubbleFrameY, forKey: "bubbleFrameY_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var logSearchWordNormal: String? = nil {
didSet {
UserDefaults.standard.set(logSearchWordNormal, forKey: "logSearchWordNormal_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var logSearchWordRN: String? = nil {
didSet {
UserDefaults.standard.set(logSearchWordRN, forKey: "logSearchWordRN_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var logSearchWordWeb: String? = nil {
didSet {
UserDefaults.standard.set(logSearchWordWeb, forKey: "logSearchWordWeb_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var networkSearchWord: String? = nil {
didSet {
UserDefaults.standard.set(networkSearchWord, forKey: "networkSearchWord_CocoaDebug")
UserDefaults.standard.synchronize()
}
}
@objc public var mainColor: String {
didSet {
UserDefaults.standard.set(mainColor, forKey: "mainColor_CocoaDebug")
UserDefaults.standard.synchronize()
_NetworkHelper.shared().mainColor = mainColor.hexColor
}
}
@objc public var additionalViewController: UIViewController? = nil
//share via email
@objc public var emailToRecipients: [String]? = nil
@objc public var emailCcRecipients: [String]? = nil
//objc
@objc public var ignoredURLs: [String]? = nil {
didSet {
_NetworkHelper.shared().ignoredURLs = ignoredURLs
}
}
@objc public var onlyURLs: [String]? = nil {
didSet {
_NetworkHelper.shared().onlyURLs = onlyURLs
}
}
@objc public var ignoredPrefixLogs: [String]? = nil {
didSet {
_NetworkHelper.shared().ignoredPrefixLogs = ignoredPrefixLogs
}
}
@objc public var onlyPrefixLogs: [String]? = nil {
didSet {
_NetworkHelper.shared().onlyPrefixLogs = onlyPrefixLogs
}
}
//protobuf
@objc public var protobufTransferMap: [String: [String]]? = nil {
didSet {
_NetworkHelper.shared().protobufTransferMap = protobufTransferMap
}
}
private override init() {
responseShake = UserDefaults.standard.bool(forKey: "responseShake_CocoaDebug")
firstIn = UserDefaults.standard.string(forKey: "firstIn_CocoaDebug")
serverURL = UserDefaults.standard.string(forKey: "serverURL_CocoaDebug")
visible = UserDefaults.standard.bool(forKey: "visible_CocoaDebug")
showBubbleAndWindow = UserDefaults.standard.bool(forKey: "showBubbleAndWindow_CocoaDebug")
enableCrashRecording = UserDefaults.standard.bool(forKey: "enableCrashRecording_CocoaDebug")
enableUIBlockingMonitoring = UserDefaults.standard.bool(forKey: "enableUIBlockingMonitoring_CocoaDebug")
enableWKWebViewMonitoring = UserDefaults.standard.bool(forKey: "enableWKWebViewMonitoring_CocoaDebug")
enableLogMonitoring = UserDefaults.standard.bool(forKey: "enableLogMonitoring_CocoaDebug")
disableNetworkMonitoring = UserDefaults.standard.bool(forKey: "disableNetworkMonitoring_CocoaDebug")
enableRNMonitoring = UserDefaults.standard.bool(forKey: "enableRNMonitoring_CocoaDebug")
tabBarSelectItem = UserDefaults.standard.integer(forKey: "tabBarSelectItem_CocoaDebug")
logSelectIndex = UserDefaults.standard.integer(forKey: "logSelectIndex_CocoaDebug")
networkLastIndex = UserDefaults.standard.integer(forKey: "networkLastIndex_CocoaDebug")
bubbleFrameX = UserDefaults.standard.float(forKey: "bubbleFrameX_CocoaDebug")
bubbleFrameY = UserDefaults.standard.float(forKey: "bubbleFrameY_CocoaDebug")
logSearchWordNormal = UserDefaults.standard.string(forKey: "logSearchWordNormal_CocoaDebug")
logSearchWordRN = UserDefaults.standard.string(forKey: "logSearchWordRN_CocoaDebug")
logSearchWordWeb = UserDefaults.standard.string(forKey: "logSearchWordWeb_CocoaDebug")
networkSearchWord = UserDefaults.standard.string(forKey: "networkSearchWord_CocoaDebug")
mainColor = UserDefaults.standard.string(forKey: "mainColor_CocoaDebug") ?? "#42d459"
//objc
ignoredURLs = _NetworkHelper.shared().ignoredURLs
onlyURLs = _NetworkHelper.shared().onlyURLs
ignoredPrefixLogs = _NetworkHelper.shared().ignoredPrefixLogs
onlyPrefixLogs = _NetworkHelper.shared().onlyPrefixLogs
//protobuf
protobufTransferMap = _NetworkHelper.shared().protobufTransferMap
//Memory
enableMemoryLeaksMonitoring_ViewController = UserDefaults.standard.bool(forKey: "enableMemoryLeaksMonitoring_UIViewController_CocoaDebug")
enableMemoryLeaksMonitoring_View = UserDefaults.standard.bool(forKey: "enableMemoryLeaksMonitoring_UIView_CocoaDebug")
enableMemoryLeaksMonitoring_MemberVariables = UserDefaults.standard.bool(forKey: "enableMemoryLeaksMonitoring_MemberVariables_CocoaDebug")
}
}

View File

@@ -0,0 +1,51 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
static const char *kPropertyKey = "kApplicationDidFinishLaunching_CocoaDebug_Key";
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "_NetworkHelper.h"
@interface NSObject (CocoaDebugAutoLaunch)
@property (nonatomic, assign) BOOL cocoadebug_applicationDidFinishLaunching;
@end
@implementation NSObject (CocoaDebugAutoLaunch)
#pragma mark - load
+ (void)load {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cocoadebug_applicationDidFinishLaunchingNotification:) name:UIApplicationDidFinishLaunchingNotification object:nil];
}
#pragma mark - notification
- (void)cocoadebug_applicationDidFinishLaunchingNotification:(NSNotification *)notification {
if (self.cocoadebug_applicationDidFinishLaunching) {return;}
self.cocoadebug_applicationDidFinishLaunching = YES;
Class CocoaDebug = NSClassFromString(@"_TtC10CocoaDebug10CocoaDebug");
if (CocoaDebug) {
[[CocoaDebug class] performSelector:@selector(enable)];
}
}
#pragma mark - getter setter
- (BOOL)cocoadebug_applicationDidFinishLaunching {
NSNumber *number = objc_getAssociatedObject(self, kPropertyKey);
return [number boolValue];
}
- (void)setCocoadebug_applicationDidFinishLaunching:(BOOL)applicationDidFinishLaunching {
NSNumber *number = [NSNumber numberWithBool:applicationDidFinishLaunching];
objc_setAssociatedObject(self, kPropertyKey, number, OBJC_ASSOCIATION_RETAIN);
}
@end

View File

@@ -0,0 +1,325 @@
//
// CocoaDebug
// liman
//
// Created by liman 02/02/2023.
// Copyright © 2023 liman. All rights reserved.
//
typedef NS_ENUM(NSUInteger, Hardware) {
IPHONE_2G,
IPHONE_3G,
IPHONE_3GS,
IPHONE_4,
IPHONE_4_CDMA,
IPHONE_4S,
IPHONE_5,
IPHONE_5_CDMA_GSM,
IPHONE_5C,
IPHONE_5C_CDMA_GSM,
IPHONE_5S,
IPHONE_5S_CDMA_GSM,
IPHONE_6_PLUS,
IPHONE_6,
IPHONE_6S,
IPHONE_6S_PLUS,
IPHONE_SE,
IPHONE_7,
IPHONE_7_PLUS,
IPHONE_7_GSM,
IPHONE_7_PLUS_GSM,
IPHONE_8_CN,
IPHONE_8_PLUS_CN,
IPHONE_X_CN,
IPHONE_8,
IPHONE_8_PLUS,
IPHONE_X,
IPHONE_XS,
IPHONE_XS_MAX,
IPHONE_XS_MAX_CN,
IPHONE_XR,
IPHONE_11,
IPHONE_11_PRO,
IPHONE_11_PRO_MAX,
IPHONE_SE_2G,
IPHONE_12_MINI,
IPHONE_12,
IPHONE_12_PRO,
IPHONE_12_PRO_MAX,
IPHONE_13_PRO,
IPHONE_13_PRO_MAX,
IPHONE_13_MINI,
IPHONE_13,
IPHONE_SE_3G,
IPHONE_14,
IPHONE_14_PLUS,
IPHONE_14_PRO,
IPHONE_14_PRO_MAX,
IPOD_TOUCH_1G,
IPOD_TOUCH_2G,
IPOD_TOUCH_3G,
IPOD_TOUCH_4G,
IPOD_TOUCH_5G,
IPOD_TOUCH_6G,
IPOD_TOUCH_7G,
IPAD,
IPAD_3G,
IPAD_2_WIFI,
IPAD_2,
IPAD_2_CDMA,
IPAD_MINI_WIFI,
IPAD_MINI,
IPAD_MINI_WIFI_CDMA,
IPAD_3_WIFI,
IPAD_3_WIFI_CDMA,
IPAD_3,
IPAD_4_WIFI,
IPAD_4,
IPAD_4_GSM_CDMA,
IPAD_AIR_WIFI,
IPAD_AIR_WIFI_GSM,
IPAD_AIR_WIFI_CDMA,
IPAD_MINI_RETINA_WIFI,
IPAD_MINI_RETINA_WIFI_CDMA,
IPAD_MINI_RETINA_WIFI_CELLULAR_CN,
IPAD_MINI_3_WIFI,
IPAD_MINI_3_WIFI_CELLULAR,
IPAD_MINI_3_WIFI_CELLULAR_CN,
IPAD_MINI_4_WIFI,
IPAD_MINI_4_WIFI_CELLULAR,
IPAD_AIR_2_WIFI,
IPAD_AIR_2_WIFI_CELLULAR,
IPAD_5_WIFI,
IPAD_5_WIFI_CELLULAR,
IPAD_PRO_97_WIFI,
IPAD_PRO_97_WIFI_CELLULAR,
IPAD_PRO_WIFI,
IPAD_PRO_WIFI_CELLULAR,
IPAD_PRO_2G_WIFI,
IPAD_7_WIFI,
IPAD_7_WIFI_CELLULAR,
IPAD_PRO_2G_WIFI_CELLULAR,
IPAD_PRO_105_WIFI,
IPAD_PRO_105_WIFI_CELLULAR,
IPAD_6_WIFI,
IPAD_6_WIFI_CELLULAR,
IPAD_PRO_11_2G_WIFI_CELLULAR,
IPAD_PRO_11_WIFI,
IPAD_PRO_4G_WIFI,
IPAD_PRO_11_1TB_WIFI,
IPAD_PRO_11_WIFI_CELLULAR,
IPAD_PRO_11_1TB_WIFI_CELLULAR,
IPAD_PRO_3G_WIFI,
IPAD_PRO_3G_1TB_WIFI,
IPAD_PRO_3G_WIFI_CELLULAR,
IPAD_PRO_4G_WIFI_CELLULAR,
IPAD_PRO_3G_1TB_WIFI_CELLULAR,
IPAD_PRO_11_2G_WIFI,
IPAD_MINI_5_WIFI,
IPAD_MINI_5_WIFI_CELLULAR,
IPAD_AIR_3_WIFI,
IPAD_AIR_3_WIFI_CELLULAR,
IPAD_9_WIFI,
IPAD_9_WIFI_CELLULAR,
IPAD_PRO_5_WIFI_CELLULAR,
IPAD_AIR_4_WIFI,
IPAD_AIR_5_WIFI,
IPAD_AIR_5_WIFI_CELLULAR,
IPAD_AIR_4_WIFI_CELLULAR,
IPAD_PRO_11_3_WIFI,
IPAD_PRO_11_3_WIFI_CELLULAR,
IPAD_PRO_5_WIFI,
IPAD_MINI_6_WIFI,
IPAD_MINI_6_WIFI_CELLULAR,
APPLE_WATCH_38,
APPLE_WATCH_42,
APPLE_WATCH_SERIES_2_38,
APPLE_WATCH_SERIES_2_42,
APPLE_WATCH_SERIES_1_38,
APPLE_WATCH_SERIES_1_42,
APPLE_WATCH_SERIES_3_38_CELLULAR,
APPLE_WATCH_SERIES_3_42_CELLULAR,
APPLE_WATCH_SERIES_3_38,
APPLE_WATCH_SERIES_3_42,
APPLE_WATCH_SERIES_4_40,
APPLE_WATCH_SERIES_4_44,
APPLE_WATCH_SERIES_4_40_CELLULAR,
APPLE_WATCH_SERIES_4_44_CELLULAR,
APPLE_WATCH_SERIES_5_40,
APPLE_WATCH_SERIES_5_44,
APPLE_WATCH_SERIES_5_40_CELLULAR,
APPLE_WATCH_SERIES_5_44_CELLULAR,
APPLE_TV_1G,
APPLE_TV_2G,
APPLE_TV_3G,
APPLE_TV_3_2G,
APPLE_TV_4G,
APPLE_TV_4K,
SIMULATOR,
UNKNOWN
};
extern NSString* const AppleTV1_1;
extern NSString* const AppleTV2_1;
extern NSString* const AppleTV3_1;
extern NSString* const AppleTV3_2;
extern NSString* const AppleTV5_3;
extern NSString* const AppleTV6_2;
extern NSString* const Watch1_1;
extern NSString* const Watch1_2;
extern NSString* const Watch2_3;
extern NSString* const Watch2_4;
extern NSString* const Watch2_6;
extern NSString* const Watch2_7;
extern NSString* const Watch3_1;
extern NSString* const Watch3_2;
extern NSString* const Watch3_3;
extern NSString* const Watch3_4;
extern NSString* const Watch4_1;
extern NSString* const Watch4_2;
extern NSString* const Watch4_3;
extern NSString* const Watch4_4;
extern NSString* const Watch5_1;
extern NSString* const Watch5_2;
extern NSString* const Watch5_3;
extern NSString* const Watch5_4;
extern NSString* const i386_Simulator;
extern NSString* const iPad1_1;
extern NSString* const iPad1_2;
extern NSString* const iPad11_1;
extern NSString* const iPad11_2;
extern NSString* const iPad11_3;
extern NSString* const iPad11_4;
extern NSString* const iPad12_1;
extern NSString* const iPad12_2;
extern NSString* const iPad13_1;
extern NSString* const iPad13_10;
extern NSString* const iPad13_11;
extern NSString* const iPad13_16;
extern NSString* const iPad13_17;
extern NSString* const iPad13_2;
extern NSString* const iPad13_4;
extern NSString* const iPad13_5;
extern NSString* const iPad13_6;
extern NSString* const iPad13_7;
extern NSString* const iPad13_8;
extern NSString* const iPad13_9;
extern NSString* const iPad14_1;
extern NSString* const iPad14_2;
extern NSString* const iPad2_1;
extern NSString* const iPad2_2;
extern NSString* const iPad2_3;
extern NSString* const iPad2_4;
extern NSString* const iPad2_5;
extern NSString* const iPad2_6;
extern NSString* const iPad2_7;
extern NSString* const iPad3_1;
extern NSString* const iPad3_2;
extern NSString* const iPad3_3;
extern NSString* const iPad3_4;
extern NSString* const iPad3_5;
extern NSString* const iPad3_6;
extern NSString* const iPad4_1;
extern NSString* const iPad4_2;
extern NSString* const iPad4_3;
extern NSString* const iPad4_4;
extern NSString* const iPad4_5;
extern NSString* const iPad4_6;
extern NSString* const iPad4_7;
extern NSString* const iPad4_8;
extern NSString* const iPad4_9;
extern NSString* const iPad5_1;
extern NSString* const iPad5_2;
extern NSString* const iPad5_3;
extern NSString* const iPad5_4;
extern NSString* const iPad6_11;
extern NSString* const iPad6_12;
extern NSString* const iPad6_3;
extern NSString* const iPad6_4;
extern NSString* const iPad6_7;
extern NSString* const iPad6_8;
extern NSString* const iPad7_1;
extern NSString* const iPad7_11;
extern NSString* const iPad7_12;
extern NSString* const iPad7_2;
extern NSString* const iPad7_3;
extern NSString* const iPad7_4;
extern NSString* const iPad7_5;
extern NSString* const iPad7_6;
extern NSString* const iPad8_1;
extern NSString* const iPad8_10;
extern NSString* const iPad8_11;
extern NSString* const iPad8_12;
extern NSString* const iPad8_2;
extern NSString* const iPad8_3;
extern NSString* const iPad8_4;
extern NSString* const iPad8_5;
extern NSString* const iPad8_6;
extern NSString* const iPad8_7;
extern NSString* const iPad8_8;
extern NSString* const iPad8_9;
extern NSString* const iPhone1_1;
extern NSString* const iPhone1_2;
extern NSString* const iPhone10_1;
extern NSString* const iPhone10_2;
extern NSString* const iPhone10_3;
extern NSString* const iPhone10_4;
extern NSString* const iPhone10_5;
extern NSString* const iPhone10_6;
extern NSString* const iPhone11_2;
extern NSString* const iPhone11_4;
extern NSString* const iPhone11_6;
extern NSString* const iPhone11_8;
extern NSString* const iPhone12_1;
extern NSString* const iPhone12_3;
extern NSString* const iPhone12_5;
extern NSString* const iPhone12_8;
extern NSString* const iPhone13_1;
extern NSString* const iPhone13_2;
extern NSString* const iPhone13_3;
extern NSString* const iPhone13_4;
extern NSString* const iPhone14_2;
extern NSString* const iPhone14_3;
extern NSString* const iPhone14_4;
extern NSString* const iPhone14_5;
extern NSString* const iPhone14_6;
extern NSString* const iPhone14_7;
extern NSString* const iPhone14_8;
extern NSString* const iPhone15_2;
extern NSString* const iPhone15_3;
extern NSString* const iPhone2_1;
extern NSString* const iPhone3_1;
extern NSString* const iPhone3_2;
extern NSString* const iPhone3_3;
extern NSString* const iPhone4_1;
extern NSString* const iPhone5_1;
extern NSString* const iPhone5_2;
extern NSString* const iPhone5_3;
extern NSString* const iPhone5_4;
extern NSString* const iPhone6_1;
extern NSString* const iPhone6_2;
extern NSString* const iPhone7_1;
extern NSString* const iPhone7_2;
extern NSString* const iPhone8_1;
extern NSString* const iPhone8_2;
extern NSString* const iPhone8_4;
extern NSString* const iPhone9_1;
extern NSString* const iPhone9_2;
extern NSString* const iPhone9_3;
extern NSString* const iPhone9_4;
extern NSString* const iPod1_1;
extern NSString* const iPod2_1;
extern NSString* const iPod3_1;
extern NSString* const iPod4_1;
extern NSString* const iPod5_1;
extern NSString* const iPod7_1;
extern NSString* const iPod9_1;
extern NSString* const x86_64_Simulator;

View File

@@ -0,0 +1,334 @@
//
// CocoaDebug
// liman
//
// Created by liman 02/02/2023.
// Copyright © 2023 liman. All rights reserved.
//
#import "_DeviceUtil.h"
NSString* const AppleTV1_1 = @"AppleTV1,1";
NSString* const AppleTV2_1 = @"AppleTV2,1";
NSString* const AppleTV3_1 = @"AppleTV3,1";
NSString* const AppleTV3_2 = @"AppleTV3,2";
NSString* const AppleTV5_3 = @"AppleTV5,3";
NSString* const AppleTV6_2 = @"AppleTV6,2";
NSString* const Watch1_1 = @"Watch1,1";
NSString* const Watch1_2 = @"Watch1,2";
NSString* const Watch2_3 = @"Watch2,3";
NSString* const Watch2_4 = @"Watch2,4";
NSString* const Watch2_6 = @"Watch2,6";
NSString* const Watch2_7 = @"Watch2,7";
NSString* const Watch3_1 = @"Watch3,1";
NSString* const Watch3_2 = @"Watch3,2";
NSString* const Watch3_3 = @"Watch3,3";
NSString* const Watch3_4 = @"Watch3,4";
NSString* const Watch4_1 = @"Watch4,1";
NSString* const Watch4_2 = @"Watch4,2";
NSString* const Watch4_3 = @"Watch4,3";
NSString* const Watch4_4 = @"Watch4,4";
NSString* const Watch5_1 = @"Watch5,1";
NSString* const Watch5_2 = @"Watch5,2";
NSString* const Watch5_3 = @"Watch5,3";
NSString* const Watch5_4 = @"Watch5,4";
NSString* const i386_Simulator = @"i386";
NSString* const iPad1_1 = @"iPad1,1";
NSString* const iPad1_2 = @"iPad1,2";
NSString* const iPad11_1 = @"iPad11,1";
NSString* const iPad11_2 = @"iPad11,2";
NSString* const iPad11_3 = @"iPad11,3";
NSString* const iPad11_4 = @"iPad11,4";
NSString* const iPad12_1 = @"iPad12,1";
NSString* const iPad12_2 = @"iPad12,2";
NSString* const iPad13_1 = @"iPad13,1";
NSString* const iPad13_10 = @"iPad13,10";
NSString* const iPad13_11 = @"iPad13,11";
NSString* const iPad13_16 = @"iPad13,16";
NSString* const iPad13_17 = @"iPad13,17";
NSString* const iPad13_2 = @"iPad13,2";
NSString* const iPad13_4 = @"iPad13,4";
NSString* const iPad13_5 = @"iPad13,5";
NSString* const iPad13_6 = @"iPad13,6";
NSString* const iPad13_7 = @"iPad13,7";
NSString* const iPad13_8 = @"iPad13,8";
NSString* const iPad13_9 = @"iPad13,9";
NSString* const iPad14_1 = @"iPad14,1";
NSString* const iPad14_2 = @"iPad14,2";
NSString* const iPad2_1 = @"iPad2,1";
NSString* const iPad2_2 = @"iPad2,2";
NSString* const iPad2_3 = @"iPad2,3";
NSString* const iPad2_4 = @"iPad2,4";
NSString* const iPad2_5 = @"iPad2,5";
NSString* const iPad2_6 = @"iPad2,6";
NSString* const iPad2_7 = @"iPad2,7";
NSString* const iPad3_1 = @"iPad3,1";
NSString* const iPad3_2 = @"iPad3,2";
NSString* const iPad3_3 = @"iPad3,3";
NSString* const iPad3_4 = @"iPad3,4";
NSString* const iPad3_5 = @"iPad3,5";
NSString* const iPad3_6 = @"iPad3,6";
NSString* const iPad4_1 = @"iPad4,1";
NSString* const iPad4_2 = @"iPad4,2";
NSString* const iPad4_3 = @"iPad4,3";
NSString* const iPad4_4 = @"iPad4,4";
NSString* const iPad4_5 = @"iPad4,5";
NSString* const iPad4_6 = @"iPad4,6";
NSString* const iPad4_7 = @"iPad4,7";
NSString* const iPad4_8 = @"iPad4,8";
NSString* const iPad4_9 = @"iPad4,9";
NSString* const iPad5_1 = @"iPad5,1";
NSString* const iPad5_2 = @"iPad5,2";
NSString* const iPad5_3 = @"iPad5,3";
NSString* const iPad5_4 = @"iPad5,4";
NSString* const iPad6_11 = @"iPad6,11";
NSString* const iPad6_12 = @"iPad6,12";
NSString* const iPad6_3 = @"iPad6,3";
NSString* const iPad6_4 = @"iPad6,4";
NSString* const iPad6_7 = @"iPad6,7";
NSString* const iPad6_8 = @"iPad6,8";
NSString* const iPad7_1 = @"iPad7,1";
NSString* const iPad7_11 = @"iPad7,11";
NSString* const iPad7_12 = @"iPad7,12";
NSString* const iPad7_2 = @"iPad7,2";
NSString* const iPad7_3 = @"iPad7,3";
NSString* const iPad7_4 = @"iPad7,4";
NSString* const iPad7_5 = @"iPad7,5";
NSString* const iPad7_6 = @"iPad7,6";
NSString* const iPad8_1 = @"iPad8,1";
NSString* const iPad8_10 = @"iPad8,10";
NSString* const iPad8_11 = @"iPad8,11";
NSString* const iPad8_12 = @"iPad8,12";
NSString* const iPad8_2 = @"iPad8,2";
NSString* const iPad8_3 = @"iPad8,3";
NSString* const iPad8_4 = @"iPad8,4";
NSString* const iPad8_5 = @"iPad8,5";
NSString* const iPad8_6 = @"iPad8,6";
NSString* const iPad8_7 = @"iPad8,7";
NSString* const iPad8_8 = @"iPad8,8";
NSString* const iPad8_9 = @"iPad8,9";
NSString* const iPhone1_1 = @"iPhone1,1";
NSString* const iPhone1_2 = @"iPhone1,2";
NSString* const iPhone10_1 = @"iPhone10,1";
NSString* const iPhone10_2 = @"iPhone10,2";
NSString* const iPhone10_3 = @"iPhone10,3";
NSString* const iPhone10_4 = @"iPhone10,4";
NSString* const iPhone10_5 = @"iPhone10,5";
NSString* const iPhone10_6 = @"iPhone10,6";
NSString* const iPhone11_2 = @"iPhone11,2";
NSString* const iPhone11_4 = @"iPhone11,4";
NSString* const iPhone11_6 = @"iPhone11,6";
NSString* const iPhone11_8 = @"iPhone11,8";
NSString* const iPhone12_1 = @"iPhone12,1";
NSString* const iPhone12_3 = @"iPhone12,3";
NSString* const iPhone12_5 = @"iPhone12,5";
NSString* const iPhone12_8 = @"iPhone12,8";
NSString* const iPhone13_1 = @"iPhone13,1";
NSString* const iPhone13_2 = @"iPhone13,2";
NSString* const iPhone13_3 = @"iPhone13,3";
NSString* const iPhone13_4 = @"iPhone13,4";
NSString* const iPhone14_2 = @"iPhone14,2";
NSString* const iPhone14_3 = @"iPhone14,3";
NSString* const iPhone14_4 = @"iPhone14,4";
NSString* const iPhone14_5 = @"iPhone14,5";
NSString* const iPhone14_6 = @"iPhone14,6";
NSString* const iPhone14_7 = @"iPhone14,7";
NSString* const iPhone14_8 = @"iPhone14,8";
NSString* const iPhone15_2 = @"iPhone15,2";
NSString* const iPhone15_3 = @"iPhone15,3";
NSString* const iPhone2_1 = @"iPhone2,1";
NSString* const iPhone3_1 = @"iPhone3,1";
NSString* const iPhone3_2 = @"iPhone3,2";
NSString* const iPhone3_3 = @"iPhone3,3";
NSString* const iPhone4_1 = @"iPhone4,1";
NSString* const iPhone5_1 = @"iPhone5,1";
NSString* const iPhone5_2 = @"iPhone5,2";
NSString* const iPhone5_3 = @"iPhone5,3";
NSString* const iPhone5_4 = @"iPhone5,4";
NSString* const iPhone6_1 = @"iPhone6,1";
NSString* const iPhone6_2 = @"iPhone6,2";
NSString* const iPhone7_1 = @"iPhone7,1";
NSString* const iPhone7_2 = @"iPhone7,2";
NSString* const iPhone8_1 = @"iPhone8,1";
NSString* const iPhone8_2 = @"iPhone8,2";
NSString* const iPhone8_4 = @"iPhone8,4";
NSString* const iPhone9_1 = @"iPhone9,1";
NSString* const iPhone9_2 = @"iPhone9,2";
NSString* const iPhone9_3 = @"iPhone9,3";
NSString* const iPhone9_4 = @"iPhone9,4";
NSString* const iPod1_1 = @"iPod1,1";
NSString* const iPod2_1 = @"iPod2,1";
NSString* const iPod3_1 = @"iPod3,1";
NSString* const iPod4_1 = @"iPod4,1";
NSString* const iPod5_1 = @"iPod5,1";
NSString* const iPod7_1 = @"iPod7,1";
NSString* const iPod9_1 = @"iPod9,1";
NSString* const x86_64_Simulator = @"x86_64";
@implementation _DeviceUtil (Constant)
- (Hardware)hardware {
NSString *hardware = [self hardwareString];
if ([hardware isEqualToString:AppleTV1_1]) return APPLE_TV_1G;
if ([hardware isEqualToString:AppleTV2_1]) return APPLE_TV_2G;
if ([hardware isEqualToString:AppleTV3_1]) return APPLE_TV_3G;
if ([hardware isEqualToString:AppleTV3_2]) return APPLE_TV_3_2G;
if ([hardware isEqualToString:AppleTV5_3]) return APPLE_TV_4G;
if ([hardware isEqualToString:AppleTV6_2]) return APPLE_TV_4K;
if ([hardware isEqualToString:Watch1_1]) return APPLE_WATCH_38;
if ([hardware isEqualToString:Watch1_2]) return APPLE_WATCH_42;
if ([hardware isEqualToString:Watch2_3]) return APPLE_WATCH_SERIES_2_38;
if ([hardware isEqualToString:Watch2_4]) return APPLE_WATCH_SERIES_2_42;
if ([hardware isEqualToString:Watch2_6]) return APPLE_WATCH_SERIES_1_38;
if ([hardware isEqualToString:Watch2_7]) return APPLE_WATCH_SERIES_1_42;
if ([hardware isEqualToString:Watch3_1]) return APPLE_WATCH_SERIES_3_38_CELLULAR;
if ([hardware isEqualToString:Watch3_2]) return APPLE_WATCH_SERIES_3_42_CELLULAR;
if ([hardware isEqualToString:Watch3_3]) return APPLE_WATCH_SERIES_3_38;
if ([hardware isEqualToString:Watch3_4]) return APPLE_WATCH_SERIES_3_42;
if ([hardware isEqualToString:Watch4_1]) return APPLE_WATCH_SERIES_4_40;
if ([hardware isEqualToString:Watch4_2]) return APPLE_WATCH_SERIES_4_44;
if ([hardware isEqualToString:Watch4_3]) return APPLE_WATCH_SERIES_4_40_CELLULAR;
if ([hardware isEqualToString:Watch4_4]) return APPLE_WATCH_SERIES_4_44_CELLULAR;
if ([hardware isEqualToString:Watch5_1]) return APPLE_WATCH_SERIES_5_40;
if ([hardware isEqualToString:Watch5_2]) return APPLE_WATCH_SERIES_5_44;
if ([hardware isEqualToString:Watch5_3]) return APPLE_WATCH_SERIES_5_40_CELLULAR;
if ([hardware isEqualToString:Watch5_4]) return APPLE_WATCH_SERIES_5_44_CELLULAR;
if ([hardware isEqualToString:i386_Simulator]) return SIMULATOR;
if ([hardware isEqualToString:iPad1_1]) return IPAD;
if ([hardware isEqualToString:iPad1_2]) return IPAD_3G;
if ([hardware isEqualToString:iPad11_1]) return IPAD_MINI_5_WIFI;
if ([hardware isEqualToString:iPad11_2]) return IPAD_MINI_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad11_3]) return IPAD_AIR_3_WIFI;
if ([hardware isEqualToString:iPad11_4]) return IPAD_AIR_3_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad12_1]) return IPAD_9_WIFI;
if ([hardware isEqualToString:iPad12_2]) return IPAD_9_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_1]) return IPAD_AIR_4_WIFI;
if ([hardware isEqualToString:iPad13_10]) return IPAD_PRO_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_11]) return IPAD_PRO_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_16]) return IPAD_AIR_5_WIFI;
if ([hardware isEqualToString:iPad13_17]) return IPAD_AIR_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_2]) return IPAD_AIR_4_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_4]) return IPAD_PRO_11_3_WIFI;
if ([hardware isEqualToString:iPad13_5]) return IPAD_AIR_4_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_6]) return IPAD_PRO_11_3_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_7]) return IPAD_PRO_11_3_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad13_8]) return IPAD_PRO_5_WIFI;
if ([hardware isEqualToString:iPad13_9]) return IPAD_PRO_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad14_1]) return IPAD_MINI_6_WIFI;
if ([hardware isEqualToString:iPad14_2]) return IPAD_MINI_6_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad2_1]) return IPAD_2_WIFI;
if ([hardware isEqualToString:iPad2_2]) return IPAD_2;
if ([hardware isEqualToString:iPad2_3]) return IPAD_2_CDMA;
if ([hardware isEqualToString:iPad2_4]) return IPAD_2;
if ([hardware isEqualToString:iPad2_5]) return IPAD_MINI_WIFI;
if ([hardware isEqualToString:iPad2_6]) return IPAD_MINI;
if ([hardware isEqualToString:iPad2_7]) return IPAD_MINI_WIFI_CDMA;
if ([hardware isEqualToString:iPad3_1]) return IPAD_3_WIFI;
if ([hardware isEqualToString:iPad3_2]) return IPAD_3_WIFI_CDMA;
if ([hardware isEqualToString:iPad3_3]) return IPAD_3;
if ([hardware isEqualToString:iPad3_4]) return IPAD_4_WIFI;
if ([hardware isEqualToString:iPad3_5]) return IPAD_4;
if ([hardware isEqualToString:iPad3_6]) return IPAD_4_GSM_CDMA;
if ([hardware isEqualToString:iPad4_1]) return IPAD_AIR_WIFI;
if ([hardware isEqualToString:iPad4_2]) return IPAD_AIR_WIFI_GSM;
if ([hardware isEqualToString:iPad4_3]) return IPAD_AIR_WIFI_CDMA;
if ([hardware isEqualToString:iPad4_4]) return IPAD_MINI_RETINA_WIFI;
if ([hardware isEqualToString:iPad4_5]) return IPAD_MINI_RETINA_WIFI_CDMA;
if ([hardware isEqualToString:iPad4_6]) return IPAD_MINI_RETINA_WIFI_CELLULAR_CN;
if ([hardware isEqualToString:iPad4_7]) return IPAD_MINI_3_WIFI;
if ([hardware isEqualToString:iPad4_8]) return IPAD_MINI_3_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad4_9]) return IPAD_MINI_3_WIFI_CELLULAR_CN;
if ([hardware isEqualToString:iPad5_1]) return IPAD_MINI_4_WIFI;
if ([hardware isEqualToString:iPad5_2]) return IPAD_MINI_4_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad5_3]) return IPAD_AIR_2_WIFI;
if ([hardware isEqualToString:iPad5_4]) return IPAD_AIR_2_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad6_11]) return IPAD_5_WIFI;
if ([hardware isEqualToString:iPad6_12]) return IPAD_5_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad6_3]) return IPAD_PRO_97_WIFI;
if ([hardware isEqualToString:iPad6_4]) return IPAD_PRO_97_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad6_7]) return IPAD_PRO_WIFI;
if ([hardware isEqualToString:iPad6_8]) return IPAD_PRO_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad7_1]) return IPAD_PRO_2G_WIFI;
if ([hardware isEqualToString:iPad7_11]) return IPAD_7_WIFI;
if ([hardware isEqualToString:iPad7_12]) return IPAD_7_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad7_2]) return IPAD_PRO_2G_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad7_3]) return IPAD_PRO_105_WIFI;
if ([hardware isEqualToString:iPad7_4]) return IPAD_PRO_105_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad7_5]) return IPAD_6_WIFI;
if ([hardware isEqualToString:iPad7_6]) return IPAD_6_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_1]) return IPAD_PRO_11_WIFI;
if ([hardware isEqualToString:iPad8_10]) return IPAD_PRO_11_2G_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_11]) return IPAD_PRO_4G_WIFI;
if ([hardware isEqualToString:iPad8_12]) return IPAD_PRO_4G_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_2]) return IPAD_PRO_11_1TB_WIFI;
if ([hardware isEqualToString:iPad8_3]) return IPAD_PRO_11_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_4]) return IPAD_PRO_11_1TB_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_5]) return IPAD_PRO_3G_WIFI;
if ([hardware isEqualToString:iPad8_6]) return IPAD_PRO_3G_1TB_WIFI;
if ([hardware isEqualToString:iPad8_7]) return IPAD_PRO_3G_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_8]) return IPAD_PRO_3G_1TB_WIFI_CELLULAR;
if ([hardware isEqualToString:iPad8_9]) return IPAD_PRO_11_2G_WIFI;
if ([hardware isEqualToString:iPhone1_1]) return IPHONE_2G;
if ([hardware isEqualToString:iPhone1_2]) return IPHONE_3G;
if ([hardware isEqualToString:iPhone10_1]) return IPHONE_8_CN;
if ([hardware isEqualToString:iPhone10_2]) return IPHONE_8_PLUS_CN;
if ([hardware isEqualToString:iPhone10_3]) return IPHONE_X_CN;
if ([hardware isEqualToString:iPhone10_4]) return IPHONE_8;
if ([hardware isEqualToString:iPhone10_5]) return IPHONE_8_PLUS;
if ([hardware isEqualToString:iPhone10_6]) return IPHONE_X;
if ([hardware isEqualToString:iPhone11_2]) return IPHONE_XS;
if ([hardware isEqualToString:iPhone11_4]) return IPHONE_XS_MAX;
if ([hardware isEqualToString:iPhone11_6]) return IPHONE_XS_MAX_CN;
if ([hardware isEqualToString:iPhone11_8]) return IPHONE_XR;
if ([hardware isEqualToString:iPhone12_1]) return IPHONE_11;
if ([hardware isEqualToString:iPhone12_3]) return IPHONE_11_PRO;
if ([hardware isEqualToString:iPhone12_5]) return IPHONE_11_PRO_MAX;
if ([hardware isEqualToString:iPhone12_8]) return IPHONE_SE_2G;
if ([hardware isEqualToString:iPhone13_1]) return IPHONE_12_MINI;
if ([hardware isEqualToString:iPhone13_2]) return IPHONE_12;
if ([hardware isEqualToString:iPhone13_3]) return IPHONE_12_PRO;
if ([hardware isEqualToString:iPhone13_4]) return IPHONE_12_PRO_MAX;
if ([hardware isEqualToString:iPhone14_2]) return IPHONE_13_PRO;
if ([hardware isEqualToString:iPhone14_3]) return IPHONE_13_PRO_MAX;
if ([hardware isEqualToString:iPhone14_4]) return IPHONE_13_MINI;
if ([hardware isEqualToString:iPhone14_5]) return IPHONE_13;
if ([hardware isEqualToString:iPhone14_6]) return IPHONE_SE_3G;
if ([hardware isEqualToString:iPhone14_7]) return IPHONE_14;
if ([hardware isEqualToString:iPhone14_8]) return IPHONE_14_PLUS;
if ([hardware isEqualToString:iPhone15_2]) return IPHONE_14_PRO;
if ([hardware isEqualToString:iPhone15_3]) return IPHONE_14_PRO_MAX;
if ([hardware isEqualToString:iPhone2_1]) return IPHONE_3GS;
if ([hardware isEqualToString:iPhone3_1]) return IPHONE_4;
if ([hardware isEqualToString:iPhone3_2]) return IPHONE_4;
if ([hardware isEqualToString:iPhone3_3]) return IPHONE_4_CDMA;
if ([hardware isEqualToString:iPhone4_1]) return IPHONE_4S;
if ([hardware isEqualToString:iPhone5_1]) return IPHONE_5;
if ([hardware isEqualToString:iPhone5_2]) return IPHONE_5_CDMA_GSM;
if ([hardware isEqualToString:iPhone5_3]) return IPHONE_5C;
if ([hardware isEqualToString:iPhone5_4]) return IPHONE_5C_CDMA_GSM;
if ([hardware isEqualToString:iPhone6_1]) return IPHONE_5S;
if ([hardware isEqualToString:iPhone6_2]) return IPHONE_5S_CDMA_GSM;
if ([hardware isEqualToString:iPhone7_1]) return IPHONE_6_PLUS;
if ([hardware isEqualToString:iPhone7_2]) return IPHONE_6;
if ([hardware isEqualToString:iPhone8_1]) return IPHONE_6S;
if ([hardware isEqualToString:iPhone8_2]) return IPHONE_6S_PLUS;
if ([hardware isEqualToString:iPhone8_4]) return IPHONE_SE;
if ([hardware isEqualToString:iPhone9_1]) return IPHONE_7;
if ([hardware isEqualToString:iPhone9_2]) return IPHONE_7_PLUS;
if ([hardware isEqualToString:iPhone9_3]) return IPHONE_7_GSM;
if ([hardware isEqualToString:iPhone9_4]) return IPHONE_7_PLUS_GSM;
if ([hardware isEqualToString:iPod1_1]) return IPOD_TOUCH_1G;
if ([hardware isEqualToString:iPod2_1]) return IPOD_TOUCH_2G;
if ([hardware isEqualToString:iPod3_1]) return IPOD_TOUCH_3G;
if ([hardware isEqualToString:iPod4_1]) return IPOD_TOUCH_4G;
if ([hardware isEqualToString:iPod5_1]) return IPOD_TOUCH_5G;
if ([hardware isEqualToString:iPod7_1]) return IPOD_TOUCH_6G;
if ([hardware isEqualToString:iPod9_1]) return IPOD_TOUCH_7G;
if ([hardware isEqualToString:x86_64_Simulator]) return SIMULATOR;
NSLog(@"This is a device which is not listed in this category. Please visit https://github.com/InderKumarRathore/DeviceUtil and add a comment there.");
NSLog(@"Your device hardware string is: %@", hardware);
return UNKNOWN;
}
@end

View File

@@ -0,0 +1,55 @@
//
// CocoaDebug
// liman
//
// Created by liman 02/02/2023.
// Copyright © 2023 liman. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "_DeviceUtil+Constant.h"
/// Enum of the different Apple's device platforms
typedef NS_ENUM(NSUInteger, Platform) {
iPhone,
iPodTouch,
iPad,
AppleTV,
AppleWatch,
Unknown
};
@interface _DeviceUtil : NSObject
/// This method returns the hardware type
- (NSString*)hardwareString;
/// This method returns the Platform enum depending upon hardware string
- (Platform)platform;
/// This method returns the readable description of hardware string
- (NSString*)hardwareDescription;
/// This method returns the readable simple description of hardware string
- (NSString*)hardwareSimpleDescription;
/// This method returns the hardware number not actual but logically. e.g. if the hardware string is 5,1 then hardware number would be 5.1
- (float)hardwareNumber;
/// This method returns if we are running in the simulator
- (BOOL)isSimulator;
/// This method returns the resolution for still image that can be received from back camera of the current device. Resolution returned for image oriented landscape right.
- (CGSize)backCameraStillImageResolutionInPixels;
@end
@interface _DeviceUtil (Constant)
/// This method returns the Hardware enum depending upon hardware string
- (Hardware)hardware;
@end

849
Pods/CocoaDebug/Sources/Core/_DeviceUtil.m generated Normal file
View File

@@ -0,0 +1,849 @@
//
// CocoaDebug
// liman
//
// Created by liman 02/02/2023.
// Copyright © 2023 liman. All rights reserved.
//
#import "_DeviceUtil.h"
#import "_DeviceUtil+Constant.h"
#include <sys/sysctl.h>
@implementation _DeviceUtil {
NSDictionary *deviceList;
}
- (instancetype)init
{
self = [super init];
if (self) {
deviceList = @{
@"AppleTV1,1" : @{
@"name": @"Apple TV 1G",
@"version": @"1.1",
},
@"AppleTV2,1" : @{
@"name": @"Apple TV 2G",
@"version": @"2.1",
},
@"AppleTV3,1" : @{
@"name": @"Apple TV 2012",
@"version": @"3.1",
},
@"AppleTV3,2" : @{
@"name": @"Apple TV 2013",
@"version": @"3.2",
},
@"AppleTV5,3" : @{
@"name": @"Apple TV 4G",
@"version": @"5.3",
},
@"AppleTV6,2" : @{
@"name": @"Apple TV 4K",
@"version": @"6.2",
},
@"Watch1,1" : @{
@"name": @"Apple Watch (38 mm)",
@"version": @"1.1",
},
@"Watch1,2" : @{
@"name": @"Apple Watch (42 mm)",
@"version": @"1.2",
},
@"Watch2,3" : @{
@"name": @"Apple Watch Series 2 (38 mm)",
@"version": @"2.3",
},
@"Watch2,4" : @{
@"name": @"Apple Watch Series 2 (42 mm)",
@"version": @"2.4",
},
@"Watch2,6" : @{
@"name": @"Apple Watch Series 1 (38 mm)",
@"version": @"2.6",
},
@"Watch2,7" : @{
@"name": @"Apple Watch Series 1 (42 mm)",
@"version": @"2.7",
},
@"Watch3,1" : @{
@"name": @"Apple Watch Series 3 (38 mm/Cellular)",
@"version": @"3.1",
},
@"Watch3,2" : @{
@"name": @"Apple Watch Series 3 (42 mm/Cellular)",
@"version": @"3.2",
},
@"Watch3,3" : @{
@"name": @"Apple Watch Series 3 (38 mm)",
@"version": @"3.3",
},
@"Watch3,4" : @{
@"name": @"Apple Watch Series 3 (42 mm)",
@"version": @"3.4",
},
@"Watch4,1" : @{
@"name": @"Apple Watch Series 4 (40 mm)",
@"version": @"4.1",
},
@"Watch4,2" : @{
@"name": @"Apple Watch Series 4 (44 mm)",
@"version": @"4.2",
},
@"Watch4,3" : @{
@"name": @"Apple Watch Series 4 (40 mm/Cellular)",
@"version": @"4.3",
},
@"Watch4,4" : @{
@"name": @"Apple Watch Series 4 (44 mm/Cellular)",
@"version": @"4.4",
},
@"Watch5,1" : @{
@"name": @"Apple Watch Series 5 (40 mm)",
@"version": @"5.1",
},
@"Watch5,2" : @{
@"name": @"Apple Watch Series 5 (44 mm)",
@"version": @"5.2",
},
@"Watch5,3" : @{
@"name": @"Apple Watch Series 5 (40 mm/Cellular)",
@"version": @"5.3",
},
@"Watch5,4" : @{
@"name": @"Apple Watch Series 5 (44 mm/Cellular)",
@"version": @"5.4",
},
@"i386" : @{
@"name": @"Simulator",
@"version": @"-1",
},
@"iPad1,1" : @{
@"name": @"iPad (WiFi)",
@"version": @"1.1",
},
@"iPad1,2" : @{
@"name": @"iPad 3G",
@"version": @"1.2",
},
@"iPad11,1" : @{
@"name": @"iPad mini 5 (Wi-Fi Only)",
@"version": @"11.1",
},
@"iPad11,2" : @{
@"name": @"iPad mini 5 (Wi-Fi/Cellular)",
@"version": @"11.2",
},
@"iPad11,3" : @{
@"name": @"iPad Air 3 (Wi-Fi)",
@"version": @"11.3",
},
@"iPad11,4" : @{
@"name": @"iPad Air 3 (Wi-Fi + Cellular)",
@"version": @"11.4",
},
@"iPad12,1" : @{
@"name": @"iPad 9 (Wi-Fi)",
@"version": @"12.1",
},
@"iPad12,2" : @{
@"name": @"iPad 9 (Wi-Fi + Cellular)",
@"version": @"12.2",
},
@"iPad13,1" : @{
@"name": @"iPad Air 4 (Wi-Fi)",
@"version": @"13.1",
},
@"iPad13,10" : @{
@"name": @"iPad Pro 12.9\" 5th Gen (Wi-Fi + Cellular)",
@"version": @"13.1",
},
@"iPad13,11" : @{
@"name": @"iPad Pro 12.9\" 5th Gen (Wi-Fi + Cellular)",
@"version": @"13.11",
},
@"iPad13,16" : @{
@"name": @"iPad Air 5th Gen (Wi-Fi)",
@"version": @"13.16",
},
@"iPad13,17" : @{
@"name": @"iPad Air 5th Gen (Wi-Fi + Cellular)",
@"version": @"13.17",
},
@"iPad13,2" : @{
@"name": @"iPad Air 4 (Wi-Fi + Cellular)",
@"version": @"13.2",
},
@"iPad13,4" : @{
@"name": @"iPad Pro 11\" 3rd Gen (Wi-Fi)",
@"version": @"13.4",
},
@"iPad13,5" : @{
@"name": @"iPad Pro 11\" 3rd Gen (Wi-Fi + Cellular)",
@"version": @"13.5",
},
@"iPad13,6" : @{
@"name": @"iPad Pro 11\" 3rd Gen (Wi-Fi + Cellular)",
@"version": @"13.6",
},
@"iPad13,7" : @{
@"name": @"iPad Pro 11\" 3rd Gen (Wi-Fi + Cellular)",
@"version": @"13.7",
},
@"iPad13,8" : @{
@"name": @"iPad Pro 12.9\" 5th Gen (Wi-Fi)",
@"version": @"13.8",
},
@"iPad13,9" : @{
@"name": @"iPad Pro 12.9\" 5th Gen (Wi-Fi + Cellular)",
@"version": @"13.9",
},
@"iPad14,1" : @{
@"name": @"iPad Mini 6 (Wi-Fi)",
@"version": @"14.1",
},
@"iPad14,2" : @{
@"name": @"iPad Mini 6 (Wi-Fi + Cellular)",
@"version": @"14.2",
},
@"iPad2,1" : @{
@"name": @"iPad 2 (WiFi)",
@"version": @"2.1",
},
@"iPad2,2" : @{
@"name": @"iPad 2 (GSM)",
@"version": @"2.2",
},
@"iPad2,3" : @{
@"name": @"iPad 2 (CDMA)",
@"version": @"2.3",
},
@"iPad2,4" : @{
@"name": @"iPad 2 (WiFi Rev. A)",
@"version": @"2.4",
},
@"iPad2,5" : @{
@"name": @"iPad Mini (WiFi)",
@"version": @"2.5",
},
@"iPad2,6" : @{
@"name": @"iPad Mini (GSM)",
@"version": @"2.6",
},
@"iPad2,7" : @{
@"name": @"iPad Mini (CDMA)",
@"version": @"2.7",
},
@"iPad3,1" : @{
@"name": @"iPad 3 (WiFi)",
@"version": @"3.1",
},
@"iPad3,2" : @{
@"name": @"iPad 3 (CDMA)",
@"version": @"3.2",
},
@"iPad3,3" : @{
@"name": @"iPad 3 (Global)",
@"version": @"3.3",
},
@"iPad3,4" : @{
@"name": @"iPad 4 (WiFi)",
@"version": @"3.4",
},
@"iPad3,5" : @{
@"name": @"iPad 4 (CDMA)",
@"version": @"3.5",
},
@"iPad3,6" : @{
@"name": @"iPad 4 (Global)",
@"version": @"3.6",
},
@"iPad4,1" : @{
@"name": @"iPad Air (WiFi)",
@"version": @"4.1",
},
@"iPad4,2" : @{
@"name": @"iPad Air (WiFi+GSM)",
@"version": @"4.2",
},
@"iPad4,3" : @{
@"name": @"iPad Air (WiFi+CDMA)",
@"version": @"4.3",
},
@"iPad4,4" : @{
@"name": @"iPad Mini Retina (WiFi)",
@"version": @"4.4",
},
@"iPad4,5" : @{
@"name": @"iPad Mini Retina (WiFi+CDMA)",
@"version": @"4.5",
},
@"iPad4,6" : @{
@"name": @"iPad Mini Retina (Wi-Fi + Cellular CN)",
@"version": @"4.6",
},
@"iPad4,7" : @{
@"name": @"iPad Mini 3 (Wi-Fi)",
@"version": @"4.7",
},
@"iPad4,8" : @{
@"name": @"iPad Mini 3 (Wi-Fi + Cellular)",
@"version": @"4.8",
},
@"iPad4,9" : @{
@"name": @"iPad mini 3 (Wi-Fi/Cellular, China)",
@"version": @"4.9",
},
@"iPad5,1" : @{
@"name": @"iPad mini 4 (Wi-Fi Only)",
@"version": @"5.1",
},
@"iPad5,2" : @{
@"name": @"iPad mini 4 (Wi-Fi/Cellular)",
@"version": @"5.2",
},
@"iPad5,3" : @{
@"name": @"iPad Air 2 (Wi-Fi)",
@"version": @"5.3",
},
@"iPad5,4" : @{
@"name": @"iPad Air 2 (Wi-Fi + Cellular)",
@"version": @"5.4",
},
@"iPad6,11" : @{
@"name": @"9.7-inch iPad (Wi-Fi)",
@"version": @"6.11",
},
@"iPad6,12" : @{
@"name": @"9.7-inch iPad (Wi-Fi + Cellular)",
@"version": @"6.12",
},
@"iPad6,3" : @{
@"name": @"iPad Pro 9.7-inch (Wi-Fi Only)",
@"version": @"6.3",
},
@"iPad6,4" : @{
@"name": @"iPad Pro 9.7-inch (Wi-Fi + Cellular)",
@"version": @"6.4",
},
@"iPad6,7" : @{
@"name": @"iPad Pro (Wi-Fi Only)",
@"version": @"6.7",
},
@"iPad6,8" : @{
@"name": @"iPad Pro (Wi-Fi/Cellular)",
@"version": @"6.8",
},
@"iPad7,1" : @{
@"name": @"iPad Pro 12.9-Inch (Wi-Fi Only - 2nd Gen)",
@"version": @"7.1",
},
@"iPad7,11" : @{
@"name": @"iPad 10.2-Inch 7th Gen (Wi-Fi Only)",
@"version": @"7.11",
},
@"iPad7,12" : @{
@"name": @"iPad 10.2-Inch 7th Gen (Wi-Fi/Cellular Only)",
@"version": @"7.12",
},
@"iPad7,2" : @{
@"name": @"iPad Pro 12.9-Inch (Wi-Fi/Cell - 2nd Gen)",
@"version": @"7.2",
},
@"iPad7,3" : @{
@"name": @"iPad Pro 10.5-Inch (Wi-Fi Only)",
@"version": @"7.3",
},
@"iPad7,4" : @{
@"name": @"iPad Pro 10.5-Inch (Wi-Fi/Cellular)",
@"version": @"7.4",
},
@"iPad7,5" : @{
@"name": @"iPad 9.7-Inch 6th Gen (Wi-Fi Only)",
@"version": @"7.5",
},
@"iPad7,6" : @{
@"name": @"iPad 9.7-Inch 6th Gen (Wi-Fi/Cellular)",
@"version": @"7.6",
},
@"iPad8,1" : @{
@"name": @"iPad Pro 11-Inch (Wi-Fi Only)",
@"version": @"8.1",
},
@"iPad8,10" : @{
@"name": @"iPad Pro 11-Inch (Wi-Fi/Cellular - 2nd Gen)",
@"version": @"8.1",
},
@"iPad8,11" : @{
@"name": @"iPad Pro 12.9-Inch 1TB (Wi-Fi Only - 4th Gen)",
@"version": @"8.109999999999999",
},
@"iPad8,12" : @{
@"name": @"iPad Pro 12.9-Inch (Wi-Fi/Cell - 4th Gen)",
@"version": @"8.800000000000001",
},
@"iPad8,2" : @{
@"name": @"iPad Pro 11-Inch 1TB (Wi-Fi Only)",
@"version": @"8.199999999999999",
},
@"iPad8,3" : @{
@"name": @"iPad Pro 11-Inch (Wi-Fi/Cellular)",
@"version": @"8.300000000000001",
},
@"iPad8,4" : @{
@"name": @"iPad Pro 11-Inch 1TB (Wi-Fi/Cellular)",
@"version": @"8.4",
},
@"iPad8,5" : @{
@"name": @"iPad Pro 12.9-Inch (Wi-Fi Only - 3rd Gen)",
@"version": @"8.5",
},
@"iPad8,6" : @{
@"name": @"iPad Pro 12.9-Inch 1TB (Wi-Fi Only - 3rd Gen)",
@"version": @"8.6",
},
@"iPad8,7" : @{
@"name": @"iPad Pro 12.9-Inch (Wi-Fi/Cell - 3rd Gen)",
@"version": @"8.699999999999999",
},
@"iPad8,8" : @{
@"name": @"iPad Pro 12.9-Inch 1TB (Wi-Fi/Cell - 3rd Gen)",
@"version": @"8.800000000000001",
},
@"iPad8,9" : @{
@"name": @"iPad Pro 11-Inch (Wi-Fi Only - 2nd Gen)",
@"version": @"8.9",
},
@"iPhone1,1" : @{
@"name": @"iPhone 2G",
@"version": @"1.1",
},
@"iPhone1,2" : @{
@"name": @"iPhone 3G",
@"version": @"1.2",
},
@"iPhone10,1" : @{
@"name": @"iPhone 8",
@"version": @"10.1",
},
@"iPhone10,2" : @{
@"name": @"iPhone 8 Plus",
@"version": @"10.2",
},
@"iPhone10,3" : @{
@"name": @"iPhone X",
@"version": @"10.3",
},
@"iPhone10,4" : @{
@"name": @"iPhone 8",
@"version": @"10.4",
},
@"iPhone10,5" : @{
@"name": @"iPhone 8 Plus",
@"version": @"10.5",
},
@"iPhone10,6" : @{
@"name": @"iPhone X",
@"version": @"10.6",
},
@"iPhone11,2" : @{
@"name": @"iPhone XS",
@"version": @"11.2",
},
@"iPhone11,4" : @{
@"name": @"iPhone XS Max",
@"version": @"11.4",
},
@"iPhone11,6" : @{
@"name": @"iPhone XS Max China",
@"version": @"11.6",
},
@"iPhone11,8" : @{
@"name": @"iPhone XR",
@"version": @"11.8",
},
@"iPhone12,1" : @{
@"name": @"iPhone 11",
@"version": @"12.1",
},
@"iPhone12,3" : @{
@"name": @"iPhone 11 Pro",
@"version": @"12.3",
},
@"iPhone12,5" : @{
@"name": @"iPhone 11 Pro Max",
@"version": @"12.5",
},
@"iPhone12,8" : @{
@"name": @"iPhone SE (2 Gen)",
@"version": @"12.8",
},
@"iPhone13,1" : @{
@"name": @"iPhone 12 mini",
@"version": @"13.1",
},
@"iPhone13,2" : @{
@"name": @"iPhone 12",
@"version": @"13.2",
},
@"iPhone13,3" : @{
@"name": @"iPhone 12 Pro",
@"version": @"13.3",
},
@"iPhone13,4" : @{
@"name": @"iPhone 12 Pro Max",
@"version": @"13.4",
},
@"iPhone14,2" : @{
@"name": @"iPhone 13 Pro",
@"version": @"14.2",
},
@"iPhone14,3" : @{
@"name": @"iPhone 13 Pro Max",
@"version": @"14.3",
},
@"iPhone14,4" : @{
@"name": @"iPhone 13 mini",
@"version": @"14.4",
},
@"iPhone14,5" : @{
@"name": @"iPhone 13",
@"version": @"14.5",
},
@"iPhone14,6" : @{
@"name": @"iPhone SE (3 Gen)",
@"version": @"14.6",
},
@"iPhone14,7" : @{
@"name": @"iPhone 14",
@"version": @"14.7",
},
@"iPhone14,8" : @{
@"name": @"iPhone 14 Plus",
@"version": @"14.8",
},
@"iPhone15,2" : @{
@"name": @"iPhone 14 Pro",
@"version": @"15.2",
},
@"iPhone15,3" : @{
@"name": @"iPhone 14 Pro Max",
@"version": @"15.3",
},
@"iPhone2,1" : @{
@"name": @"iPhone 3GS",
@"version": @"2.1",
},
@"iPhone3,1" : @{
@"name": @"iPhone 4 (GSM)",
@"version": @"3.1",
},
@"iPhone3,2" : @{
@"name": @"iPhone 4 (GSM Rev. A)",
@"version": @"3.2",
},
@"iPhone3,3" : @{
@"name": @"iPhone 4 (CDMA)",
@"version": @"3.3",
},
@"iPhone4,1" : @{
@"name": @"iPhone 4S",
@"version": @"4.1",
},
@"iPhone5,1" : @{
@"name": @"iPhone 5 (GSM)",
@"version": @"5.1",
},
@"iPhone5,2" : @{
@"name": @"iPhone 5 (Global)",
@"version": @"5.2",
},
@"iPhone5,3" : @{
@"name": @"iPhone 5c (GSM)",
@"version": @"5.3",
},
@"iPhone5,4" : @{
@"name": @"iPhone 5c (Global)",
@"version": @"5.4",
},
@"iPhone6,1" : @{
@"name": @"iPhone 5s (GSM)",
@"version": @"6.1",
},
@"iPhone6,2" : @{
@"name": @"iPhone 5s (Global)",
@"version": @"6.2",
},
@"iPhone7,1" : @{
@"name": @"iPhone 6 Plus",
@"version": @"7.1",
},
@"iPhone7,2" : @{
@"name": @"iPhone 6",
@"version": @"7.2",
},
@"iPhone8,1" : @{
@"name": @"iPhone 6s",
@"version": @"8.1",
},
@"iPhone8,2" : @{
@"name": @"iPhone 6s Plus",
@"version": @"8.199999999999999",
},
@"iPhone8,4" : @{
@"name": @"iPhone SE",
@"version": @"8.4",
},
@"iPhone9,1" : @{
@"name": @"iPhone 7",
@"version": @"9.1",
},
@"iPhone9,2" : @{
@"name": @"iPhone 7 Plus",
@"version": @"9.199999999999999",
},
@"iPhone9,3" : @{
@"name": @"iPhone 7",
@"version": @"9.300000000000001",
},
@"iPhone9,4" : @{
@"name": @"iPhone 7 Plus",
@"version": @"9.4",
},
@"iPod1,1" : @{
@"name": @"iPod Touch (1 Gen)",
@"version": @"1.1",
},
@"iPod2,1" : @{
@"name": @"iPod Touch (2 Gen)",
@"version": @"2.1",
},
@"iPod3,1" : @{
@"name": @"iPod Touch (3 Gen)",
@"version": @"3.1",
},
@"iPod4,1" : @{
@"name": @"iPod Touch (4 Gen)",
@"version": @"4.1",
},
@"iPod5,1" : @{
@"name": @"iPod Touch (5 Gen)",
@"version": @"5.1",
},
@"iPod7,1" : @{
@"name": @"iPod Touch (6 Gen)",
@"version": @"7.1",
},
@"iPod9,1" : @{
@"name": @"iPod Touch (7 Gen)",
@"version": @"9.1",
},
@"x86_64" : @{
@"name": @"Simulator",
@"version": @"-1",
},
};
}
return self;
}
- (NSString*)nativeHardwareString {
int name[] = {CTL_HW,HW_MACHINE};
size_t size = 100;
sysctl(name, 2, NULL, &size, NULL, 0); // getting size of answer
char *hw_machine = malloc(size);
sysctl(name, 2, hw_machine, &size, NULL, 0);
NSString *hardware = [NSString stringWithUTF8String:hw_machine];
free(hw_machine);
return hardware;
}
- (NSString*)hardwareString {
NSString *hardware = [self nativeHardwareString];
// Check if the hardware is simulator
if ([hardware isEqualToString:i386_Simulator] || [hardware isEqualToString:x86_64_Simulator]) {
NSString *deviceID = [[[NSProcessInfo processInfo] environment] objectForKey:@"SIMULATOR_MODEL_IDENTIFIER"];
if (deviceID != nil) {
hardware = deviceID;
}
}
return hardware;
}
/* This is another way of gtting the system info
* For this you have to #import <sys/utsname.h>
*/
/*
NSString* machineName
{
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
*/
/// This method returns the Platform enum depending upon hardware string
///
///
/// - returns: `Platform` type of the device
///
- (Platform)platform {
NSString *hardware = [self hardwareString];
if ([hardware hasPrefix:@"iPhone"]) return iPhone;
if ([hardware hasPrefix:@"iPod"]) return iPodTouch;
if ([hardware hasPrefix:@"iPad"]) return iPad;
if ([hardware hasPrefix:@"Watch"]) return AppleWatch;
if ([hardware hasPrefix:@"AppleTV"]) return AppleTV;
return Unknown;
}
- (Hardware)nativeHardware {
NSString *hardware = [self nativeHardwareString];
if ([hardware isEqualToString:i386_Simulator]) return SIMULATOR;
if ([hardware isEqualToString:x86_64_Simulator]) return SIMULATOR;
return [self hardware];
}
- (NSString*)hardwareDescription {
NSString *hardware = [self hardwareString];
NSString *hardwareDescription = [[deviceList objectForKey:hardware] objectForKey:@"name"];
if (hardwareDescription) {
return hardwareDescription;
}
else {
//log message that your device is not present in the list
[self logMessage:hardware];
return nil;
}
}
- (NSString*)hardwareSimpleDescription {
NSString *hardwareDescription = [self hardwareDescription];
if (hardwareDescription == nil) {
return nil;
}
NSError *error = nil;
// this expression matches all strings between round brackets (e.g (Wifi), (GSM)) except the pattern "[0-9]+ Gen"
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\((?![0-9]+ Gen).*\\)" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *hardwareSimpleDescription = [regex stringByReplacingMatchesInString:hardwareDescription options:0 range:NSMakeRange(0, [hardwareDescription length]) withTemplate:@""];
if (error) {
return nil;
} else {
return hardwareSimpleDescription;
}
}
- (float)hardwareNumber {
NSString *hardware = [self hardwareString];
float version = [[[deviceList objectForKey:hardware] objectForKey:@"version"] floatValue];
if (version != 0.0f) {
return version;
}
else {
//log message that your device is not present in the list
[self logMessage:hardware];
return 200.0f; //device might be new one of missing one so returning 200.0f
}
}
- (BOOL)isSimulator {
return [self nativeHardware] == SIMULATOR;
}
- (CGSize)backCameraStillImageResolutionInPixels {
switch ([self hardware]) {
case IPHONE_2G:
case IPHONE_3G:
return CGSizeMake(1600, 1200);
case IPHONE_3GS:
return CGSizeMake(2048, 1536);
case IPHONE_4:
case IPHONE_4_CDMA:
case IPAD_3_WIFI:
case IPAD_3_WIFI_CDMA:
case IPAD_3:
case IPAD_4_WIFI:
case IPAD_4:
case IPAD_4_GSM_CDMA:
return CGSizeMake(2592, 1936);
case IPHONE_4S:
case IPHONE_5:
case IPHONE_5_CDMA_GSM:
case IPHONE_5C:
case IPHONE_5C_CDMA_GSM:
case IPHONE_6:
case IPHONE_6_PLUS:
case IPOD_TOUCH_6G:
case IPAD_AIR_2_WIFI:
case IPAD_AIR_2_WIFI_CELLULAR:
case IPHONE_6S:
case IPHONE_6S_PLUS:
case IPAD_MINI_4_WIFI:
case IPAD_MINI_4_WIFI_CELLULAR:
case IPAD_MINI_5_WIFI:
case IPAD_MINI_5_WIFI_CELLULAR:
case IPAD_AIR_3_WIFI:
case IPAD_AIR_3_WIFI_CELLULAR:
return CGSizeMake(3264, 2448);
case IPHONE_7:
case IPHONE_7_GSM:
case IPHONE_7_PLUS:
case IPHONE_7_PLUS_GSM:
case IPHONE_8:
case IPHONE_8_CN:
case IPHONE_8_PLUS:
case IPHONE_8_PLUS_CN:
case IPHONE_X:
case IPHONE_X_CN:
return CGSizeMake(4032, 3024);
case IPOD_TOUCH_4G:
return CGSizeMake(960, 720);
case IPOD_TOUCH_5G:
return CGSizeMake(2440, 1605);
case IPAD_2_WIFI:
case IPAD_2:
case IPAD_2_CDMA:
return CGSizeMake(872, 720);
case IPAD_MINI_WIFI:
case IPAD_MINI:
case IPAD_MINI_WIFI_CDMA:
return CGSizeMake(1820, 1304);
case IPAD_PRO_97_WIFI:
case IPAD_PRO_97_WIFI_CELLULAR:
return CGSizeMake(4032, 3024);
default:
NSLog(@"We have no resolution for your device's camera listed in this category. Please, make photo with back camera of your device, get its resolution in pixels (via Preview Cmd+I for example) and add a comment to this repository (https://github.com/InderKumarRathore/DeviceUtil) on GitHub.com in format Device = Hpx x Wpx.");
NSLog(@"Your device is: %@", [self hardwareDescription]);
break;
}
return CGSizeZero;
}
- (void)logMessage:(NSString *)hardware {
NSLog(@"This is a device which is not listed in this category. Please visit https://github.com/InderKumarRathore/DeviceUtil and add a comment there.");
NSLog(@"Your device hardware string is: %@", hardware);
}
@end

View File

@@ -0,0 +1,22 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
@import Foundation;
/*! Determines the cache storage policy for a response.
* \details When we provide a response up to the client we need to tell the client whether
* the response is cacheable or not. The default HTTP/HTTPS protocol has a reasonable
* complex chunk of code to determine this, but we can't get at it. Thus, we have to
* reimplement it ourselves. This is split off into a separate file to emphasise that
* this is standard boilerplate that you probably don't need to look at.
* \param request The request that generated the response; must not be nil.
* \param response The response itself; must not be nil.
* \returns A cache storage policy to use.
*/
extern NSURLCacheStoragePolicy CacheStoragePolicyForRequestAndResponse(NSURLRequest * request, NSHTTPURLResponse * response);

View File

@@ -0,0 +1,85 @@
//
// Example
// man
//
// Created by man 11/11/2018.
// Copyright © 2020 man. All rights reserved.
//
#import "_CacheStoragePolicy.h"
extern NSURLCacheStoragePolicy CacheStoragePolicyForRequestAndResponse(NSURLRequest * request, NSHTTPURLResponse * response)
// See comment in header.
{
BOOL cacheable;
NSURLCacheStoragePolicy result;
//assert(request != NULL);
//assert(response != NULL);
// First determine if the request is cacheable based on its status code.
switch ([response statusCode]) {
case 200:
case 203:
case 206:
case 301:
case 304:
case 404:
case 410: {
cacheable = YES;
} break;
default: {
cacheable = NO;
} break;
}
// If the response might be cacheable, look at the "Cache-Control" header in
// the response.
// IMPORTANT: We can't rely on -rangeOfString: returning valid results if the target
// string is nil, so we have to explicitly test for nil in the following two cases.
if (cacheable) {
NSString * responseHeader;
responseHeader = [[response allHeaderFields][@"Cache-Control"] lowercaseString];
if ( (responseHeader != nil) && [responseHeader rangeOfString:@"no-store"].location != NSNotFound) {
cacheable = NO;
}
}
// If we still think it might be cacheable, look at the "Cache-Control" header in
// the request.
if (cacheable) {
NSString * requestHeader;
requestHeader = [[request allHTTPHeaderFields][@"Cache-Control"] lowercaseString];
if ( (requestHeader != nil)
&& ([requestHeader rangeOfString:@"no-store"].location != NSNotFound)
&& ([requestHeader rangeOfString:@"no-cache"].location != NSNotFound) ) {
cacheable = NO;
}
}
// Use the cacheable flag to determine the result.
if (cacheable) {
// This code only caches HTTPS data in memory. This is inline with earlier versions of
// iOS. Modern versions of iOS use file protection to protect the cache, and thus are
// happy to cache HTTPS on disk. I've not made the correspondencing change because
// it's nice to see all three cache policies in action.
if ([[[[request URL] scheme] lowercaseString] isEqual:@"https"]) {
result = NSURLCacheStorageAllowedInMemoryOnly;
} else {
result = NSURLCacheStorageAllowed;
}
} else {
result = NSURLCacheStorageNotAllowed;
}
return result;
}

Some files were not shown because too many files have changed in this diff Show More