Commit cf74440a777fcd4bb95f147453b723f57a56025a

Authored by 权海
1 parent 72cf904b

feat(ui):增加app路由跳转传递给flutter, 完善watch theme; 现在runner iOS工程可以直接调试了

Showing 43 changed files with 4307 additions and 315 deletions

Too many changes to show.

To preserve performance only 43 of 43+ files are displayed.

@@ -307,7 +307,7 @@ interface HealthKitHostApi { @@ -307,7 +307,7 @@ interface HealthKitHostApi {
307 fun getHealthServerAuthUrl(callback: (Result<String>) -> Unit) 307 fun getHealthServerAuthUrl(callback: (Result<String>) -> Unit)
308 fun cancelHealthAppAuthorization(): Boolean 308 fun cancelHealthAppAuthorization(): Boolean
309 /** Runs native health read and server upload pipeline. */ 309 /** Runs native health read and server upload pipeline. */
310 - fun performHealthUpload(): HealthUploadResult 310 + fun performHealthUpload(callback: (Result<HealthUploadResult>) -> Unit)
311 /** Opens Huawei Health client authorization UI. Returns whether user granted. */ 311 /** Opens Huawei Health client authorization UI. Returns whether user granted. */
312 fun checkHealthAppAuthorization(callback: (Result<HealthAuthorization>) -> Unit) 312 fun checkHealthAppAuthorization(callback: (Result<HealthAuthorization>) -> Unit)
313 fun requestHealthClientAuthorization(callback: (Result<Boolean>) -> Unit) 313 fun requestHealthClientAuthorization(callback: (Result<Boolean>) -> Unit)
@@ -373,12 +373,15 @@ interface HealthKitHostApi { @@ -373,12 +373,15 @@ interface HealthKitHostApi {
373 val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.performHealthUpload$separatedMessageChannelSuffix", codec) 373 val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.performHealthUpload$separatedMessageChannelSuffix", codec)
374 if (api != null) { 374 if (api != null) {
375 channel.setMessageHandler { _, reply -> 375 channel.setMessageHandler { _, reply ->
376 - val wrapped: List<Any?> = try {  
377 - listOf(api.performHealthUpload())  
378 - } catch (exception: Throwable) {  
379 - HealthKitApiPigeonUtils.wrapError(exception) 376 + api.performHealthUpload{ result: Result<HealthUploadResult> ->
  377 + val error = result.exceptionOrNull()
  378 + if (error != null) {
  379 + reply.reply(HealthKitApiPigeonUtils.wrapError(error))
  380 + } else {
  381 + val data = result.getOrNull()
  382 + reply.reply(HealthKitApiPigeonUtils.wrapResult(data))
  383 + }
380 } 384 }
381 - reply.reply(wrapped)  
382 } 385 }
383 } else { 386 } else {
384 channel.setMessageHandler(null) 387 channel.setMessageHandler(null)
@@ -359,6 +359,10 @@ interface PlatformHostApi { @@ -359,6 +359,10 @@ interface PlatformHostApi {
359 fun requestAppReview(callback: (Result<Boolean>) -> Unit) 359 fun requestAppReview(callback: (Result<Boolean>) -> Unit)
360 /** 跳app应用设置:通知、定位等权限 */ 360 /** 跳app应用设置:通知、定位等权限 */
361 fun jumpAppSetting(): Boolean 361 fun jumpAppSetting(): Boolean
  362 + /** 原生处理跳转url */
  363 + fun nativeHandleUrl(urlString: String): Boolean
  364 + /** 从原生拿需要处理的url, 主要场景是点击通知跳转 */
  365 + fun requestUnhandedUrl(): String?
362 /** 请求苹果登录 */ 366 /** 请求苹果登录 */
363 fun requestAppleSignIn(callback: (Result<AppleSignInModel?>) -> Unit) 367 fun requestAppleSignIn(callback: (Result<AppleSignInModel?>) -> Unit)
364 /** 368 /**
@@ -517,6 +521,38 @@ interface PlatformHostApi { @@ -517,6 +521,38 @@ interface PlatformHostApi {
517 } 521 }
518 } 522 }
519 run { 523 run {
  524 + val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.PlatformHostApi.nativeHandleUrl$separatedMessageChannelSuffix", codec)
  525 + if (api != null) {
  526 + channel.setMessageHandler { message, reply ->
  527 + val args = message as List<Any?>
  528 + val urlStringArg = args[0] as String
  529 + val wrapped: List<Any?> = try {
  530 + listOf(api.nativeHandleUrl(urlStringArg))
  531 + } catch (exception: Throwable) {
  532 + PlatformApiPigeonUtils.wrapError(exception)
  533 + }
  534 + reply.reply(wrapped)
  535 + }
  536 + } else {
  537 + channel.setMessageHandler(null)
  538 + }
  539 + }
  540 + run {
  541 + val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.PlatformHostApi.requestUnhandedUrl$separatedMessageChannelSuffix", codec)
  542 + if (api != null) {
  543 + channel.setMessageHandler { _, reply ->
  544 + val wrapped: List<Any?> = try {
  545 + listOf(api.requestUnhandedUrl())
  546 + } catch (exception: Throwable) {
  547 + PlatformApiPigeonUtils.wrapError(exception)
  548 + }
  549 + reply.reply(wrapped)
  550 + }
  551 + } else {
  552 + channel.setMessageHandler(null)
  553 + }
  554 + }
  555 + run {
520 val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.PlatformHostApi.requestAppleSignIn$separatedMessageChannelSuffix", codec) 556 val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.PlatformHostApi.requestAppleSignIn$separatedMessageChannelSuffix", codec)
521 if (api != null) { 557 if (api != null) {
522 channel.setMessageHandler { _, reply -> 558 channel.setMessageHandler { _, reply ->
@@ -28,6 +28,7 @@ flutter_ios_podfile_setup @@ -28,6 +28,7 @@ flutter_ios_podfile_setup
28 28
29 target 'Runner' do 29 target 'Runner' do
30 use_frameworks! 30 use_frameworks!
  31 + pod 'OBS', :path => './Runner/Library'
31 32
32 flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 33 flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
33 end 34 end
@@ -51,6 +52,7 @@ post_install do |installer| @@ -51,6 +52,7 @@ post_install do |installer|
51 52
52 target.build_configurations.each do |config| 53 target.build_configurations.each do |config|
53 config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO' 54 config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
  55 + config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
54 end 56 end
55 end 57 end
56 end 58 end
@@ -19,6 +19,7 @@ PODS: @@ -19,6 +19,7 @@ PODS:
19 - libwebp/sharpyuv (1.5.0) 19 - libwebp/sharpyuv (1.5.0)
20 - libwebp/webp (1.5.0): 20 - libwebp/webp (1.5.0):
21 - libwebp/sharpyuv 21 - libwebp/sharpyuv
  22 + - OBS (3.20.11.1)
22 - path_provider_foundation (0.0.1): 23 - path_provider_foundation (0.0.1):
23 - Flutter 24 - Flutter
24 - FlutterMacOS 25 - FlutterMacOS
@@ -45,6 +46,7 @@ DEPENDENCIES: @@ -45,6 +46,7 @@ DEPENDENCIES:
45 - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) 46 - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
46 - image_cropper (from `.symlinks/plugins/image_cropper/ios`) 47 - image_cropper (from `.symlinks/plugins/image_cropper/ios`)
47 - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) 48 - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
  49 + - OBS (from `./Runner/Library`)
48 - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) 50 - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
49 - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) 51 - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
50 - share_plus (from `.symlinks/plugins/share_plus/ios`) 52 - share_plus (from `.symlinks/plugins/share_plus/ios`)
@@ -67,6 +69,8 @@ EXTERNAL SOURCES: @@ -67,6 +69,8 @@ EXTERNAL SOURCES:
67 :path: ".symlinks/plugins/image_cropper/ios" 69 :path: ".symlinks/plugins/image_cropper/ios"
68 image_picker_ios: 70 image_picker_ios:
69 :path: ".symlinks/plugins/image_picker_ios/ios" 71 :path: ".symlinks/plugins/image_picker_ios/ios"
  72 + OBS:
  73 + :path: "./Runner/Library"
70 path_provider_foundation: 74 path_provider_foundation:
71 :path: ".symlinks/plugins/path_provider_foundation/darwin" 75 :path: ".symlinks/plugins/path_provider_foundation/darwin"
72 permission_handler_apple: 76 permission_handler_apple:
@@ -88,6 +92,7 @@ SPEC CHECKSUMS: @@ -88,6 +92,7 @@ SPEC CHECKSUMS:
88 image_cropper: c4326ea50132b1e1564499e5d32a84f01fb03537 92 image_cropper: c4326ea50132b1e1564499e5d32a84f01fb03537
89 image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a 93 image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
90 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 94 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
  95 + OBS: 4cf1e6db5515aefd6c3c6ae3e90e85ea5f028e83
91 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 96 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
92 permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d 97 permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
93 share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a 98 share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
@@ -97,6 +102,6 @@ SPEC CHECKSUMS: @@ -97,6 +102,6 @@ SPEC CHECKSUMS:
97 video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140 102 video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140
98 webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2 103 webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
99 104
100 -PODFILE CHECKSUM: b9265b4a06e32777ce541c63a22ad629b9ccc6ae 105 +PODFILE CHECKSUM: 9336dec050b93f0e3aeb7daef71d30ec0e2195f3
101 106
102 COCOAPODS: 1.16.2 107 COCOAPODS: 1.16.2
@@ -732,6 +732,11 @@ @@ -732,6 +732,11 @@
732 CURRENT_PROJECT_VERSION = 73; 732 CURRENT_PROJECT_VERSION = 73;
733 DEVELOPMENT_TEAM = ZRPLMC329K; 733 DEVELOPMENT_TEAM = ZRPLMC329K;
734 ENABLE_PREVIEWS = YES; 734 ENABLE_PREVIEWS = YES;
  735 + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
  736 + FRAMEWORK_SEARCH_PATHS = (
  737 + "$(inherited)",
  738 + "$(PROJECT_DIR)/Runner/Library",
  739 + );
735 "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( 740 "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = (
736 "$(inherited)", 741 "$(inherited)",
737 "$(BUILT_PRODUCTS_DIR)", 742 "$(BUILT_PRODUCTS_DIR)",
@@ -806,6 +811,11 @@ @@ -806,6 +811,11 @@
806 CURRENT_PROJECT_VERSION = 73; 811 CURRENT_PROJECT_VERSION = 73;
807 DEVELOPMENT_TEAM = ZRPLMC329K; 812 DEVELOPMENT_TEAM = ZRPLMC329K;
808 ENABLE_PREVIEWS = YES; 813 ENABLE_PREVIEWS = YES;
  814 + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
  815 + FRAMEWORK_SEARCH_PATHS = (
  816 + "$(inherited)",
  817 + "$(PROJECT_DIR)/Runner/Library",
  818 + );
809 "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( 819 "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = (
810 "$(inherited)", 820 "$(inherited)",
811 "$(BUILT_PRODUCTS_DIR)", 821 "$(BUILT_PRODUCTS_DIR)",
@@ -14,23 +14,19 @@ import AdSupport @@ -14,23 +14,19 @@ import AdSupport
14 14
15 typealias FlutterBridgeMethod = ((_ params: Any?, _ result: FlutterResult) -> Void) 15 typealias FlutterBridgeMethod = ((_ params: Any?, _ result: FlutterResult) -> Void)
16 16
17 -let kAppId = "6747254434"  
18 17
19 @Observable 18 @Observable
20 class AppDelegate: NSObject, UIApplicationDelegate { 19 class AppDelegate: NSObject, UIApplicationDelegate {
21 -  
22 - /// UIApplicationDelegate 要求声明 window,  
23 - /// image_cropper 等插件会通过 UIApplication.shared.delegate?.window 查找 keyWindow,  
24 - /// 缺少此属性会导致 "unrecognized selector" 崩溃。 20 +
25 var window: UIWindow? 21 var window: UIWindow?
26 - 22 +
27 private(set) var enginInitError: String? 23 private(set) var enginInitError: String?
28 - 24 +
29 enum FlutterBridgeMethodName: String{ 25 enum FlutterBridgeMethodName: String{
30 - case verifyPayment 26 + case handleFlutterUrl
31 } 27 }
32 private var methods: [String: FlutterBridgeMethod] = [:] 28 private var methods: [String: FlutterBridgeMethod] = [:]
33 - 29 +
34 var flutterEngine: FlutterEngine? 30 var flutterEngine: FlutterEngine?
35 var channel: FlutterMethodChannel? 31 var channel: FlutterMethodChannel?
36 private var isFlutterEngineReady = false 32 private var isFlutterEngineReady = false
@@ -42,7 +38,7 @@ class AppDelegate: NSObject, UIApplicationDelegate { @@ -42,7 +38,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
42 AppShared.shared.agent.genUA() 38 AppShared.shared.agent.genUA()
43 AppShared.shared.payment.delegate = self 39 AppShared.shared.payment.delegate = self
44 _ = AppShared.shared.payment.listenForTransactions() 40 _ = AppShared.shared.payment.listenForTransactions()
45 - 41 +
46 UIApplication.shared.registerForRemoteNotifications() 42 UIApplication.shared.registerForRemoteNotifications()
47 UNUserNotificationCenter.current().setBadgeCount(0) 43 UNUserNotificationCenter.current().setBadgeCount(0)
48 UNUserNotificationCenter.current().delegate = self 44 UNUserNotificationCenter.current().delegate = self
@@ -50,9 +46,32 @@ class AppDelegate: NSObject, UIApplicationDelegate { @@ -50,9 +46,32 @@ class AppDelegate: NSObject, UIApplicationDelegate {
50 46
51 WatchConnectivityService.shared.activate() 47 WatchConnectivityService.shared.activate()
52 HealthKitService.shared.startBackgroundObserversIfNeeded() 48 HealthKitService.shared.startBackgroundObserversIfNeeded()
  49 + cacheLaunchURLIfNeeded(launchOptions)
  50 + return true
  51 + }
  52 +
  53 + func application(
  54 + _ app: UIApplication,
  55 + open url: URL,
  56 + options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  57 + ) -> Bool {
  58 + handleFlutterUrl(url.absoluteString)
53 return true 59 return true
54 } 60 }
55 - 61 +
  62 + func application(
  63 + _ application: UIApplication,
  64 + continue userActivity: NSUserActivity,
  65 + restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
  66 + ) -> Bool {
  67 + guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
  68 + let urlString = userActivity.webpageURL?.absoluteString else {
  69 + return false
  70 + }
  71 + handleFlutterUrl(urlString)
  72 + return true
  73 + }
  74 +
56 func warmUpFlutterEngineIfNeeded() { 75 func warmUpFlutterEngineIfNeeded() {
57 guard !isFlutterEngineReady else { 76 guard !isFlutterEngineReady else {
58 enginInitError = nil 77 enginInitError = nil
@@ -69,16 +88,18 @@ class AppDelegate: NSObject, UIApplicationDelegate { @@ -69,16 +88,18 @@ class AppDelegate: NSObject, UIApplicationDelegate {
69 NativePigeonRegistrar.register(binaryMessenger: flutterEngine.binaryMessenger) 88 NativePigeonRegistrar.register(binaryMessenger: flutterEngine.binaryMessenger)
70 channel = FlutterMethodChannel(name: "doublefeel_flutter_main_channel", binaryMessenger: flutterEngine.binaryMessenger) 89 channel = FlutterMethodChannel(name: "doublefeel_flutter_main_channel", binaryMessenger: flutterEngine.binaryMessenger)
71 methods = defaultMethods() 90 methods = defaultMethods()
72 - 91 +
73 enginInitError = nil 92 enginInitError = nil
74 } 93 }
75 - 94 +
76 func application(_ application: UIApplication, 95 func application(_ application: UIApplication,
77 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 96 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
78 let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) } 97 let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
79 let token = tokenParts.joined() 98 let token = tokenParts.joined()
80 -  
81 - print("✅ Device Token: \(token)") 99 + AppGroupConstants.defaults?.set(token, forKey: AppGroupConstants.Key.appDeviceToken)
  100 + Task{
  101 + await AppShared.shared.reportDeviceInfo()
  102 + }
82 } 103 }
83 104
84 func application(_ application: UIApplication, 105 func application(_ application: UIApplication,
@@ -90,16 +111,73 @@ class AppDelegate: NSObject, UIApplicationDelegate { @@ -90,16 +111,73 @@ class AppDelegate: NSObject, UIApplicationDelegate {
90 extension AppDelegate{ 111 extension AppDelegate{
91 private func defaultMethods() -> [String: FlutterBridgeMethod]{ 112 private func defaultMethods() -> [String: FlutterBridgeMethod]{
92 var methods: [String: FlutterBridgeMethod] = [:] 113 var methods: [String: FlutterBridgeMethod] = [:]
93 - methods[FlutterBridgeMethodName.verifyPayment.rawValue] = { params, result in 114 + methods[FlutterBridgeMethodName.handleFlutterUrl.rawValue] = { params, result in
94 result(params) 115 result(params)
95 } 116 }
96 - 117 +
97 return methods 118 return methods
98 } 119 }
99 - 120 +
100 func invoke(method: FlutterBridgeMethodName, arguments: Any?, result: @escaping FlutterResult){ 121 func invoke(method: FlutterBridgeMethodName, arguments: Any?, result: @escaping FlutterResult){
101 channel?.invokeMethod(method.rawValue, arguments: arguments, result: result) 122 channel?.invokeMethod(method.rawValue, arguments: arguments, result: result)
102 } 123 }
  124 +
  125 + private func cacheLaunchURLIfNeeded(_ launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
  126 + if let url = launchOptions?[.url] as? URL {
  127 + AppShared.shared.unhandedUrl = url.absoluteString
  128 + return
  129 + }
  130 +
  131 + if let userActivityDictionary = launchOptions?[.userActivityDictionary] as? [AnyHashable: Any] {
  132 + for value in userActivityDictionary.values {
  133 + guard let userActivity = value as? NSUserActivity,
  134 + userActivity.activityType == NSUserActivityTypeBrowsingWeb,
  135 + let urlString = userActivity.webpageURL?.absoluteString else {
  136 + continue
  137 + }
  138 + AppShared.shared.unhandedUrl = urlString
  139 + return
  140 + }
  141 + }
  142 +
  143 + if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable: Any],
  144 + let urlString = Self.flutterURLString(from: userInfo) {
  145 + AppShared.shared.unhandedUrl = urlString
  146 + }
  147 + }
  148 +
  149 + func handleFlutterUrl(_ urlString: String) {
  150 + guard !urlString.isEmpty else {
  151 + return
  152 + }
  153 +
  154 + guard channel != nil else {
  155 + AppShared.shared.unhandedUrl = urlString
  156 + return
  157 + }
  158 +
  159 + invoke(method: .handleFlutterUrl, arguments: [
  160 + "url": urlString
  161 + ]) { result in
  162 + if let error = result as? FlutterError {
  163 + DebugLogger.log(desc: "handleFlutterUrl error: \(error.message ?? error.code)")
  164 + }
  165 + }
  166 + }
  167 +
  168 + private static func flutterURLString(from userInfo: [AnyHashable: Any]) -> String? {
  169 + if let urlString = userInfo["url"] as? String {
  170 + return urlString
  171 + }
  172 +
  173 + guard let payload = userInfo["payload"] as? String,
  174 + let data = payload.data(using: .utf8),
  175 + let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
  176 + return nil
  177 + }
  178 +
  179 + return dict["url"] as? String
  180 + }
103 } 181 }
104 182
105 extension AppDelegate: UNUserNotificationCenterDelegate{ 183 extension AppDelegate: UNUserNotificationCenterDelegate{
@@ -108,23 +186,13 @@ extension AppDelegate: UNUserNotificationCenterDelegate{ @@ -108,23 +186,13 @@ extension AppDelegate: UNUserNotificationCenterDelegate{
108 withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { 186 withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
109 completionHandler([.banner, .sound, .badge]) 187 completionHandler([.banner, .sound, .badge])
110 } 188 }
111 - 189 +
112 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 190 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
113 let userInfo = response.notification.request.content.userInfo 191 let userInfo = response.notification.request.content.userInfo
114 - 192 +
115 // 从通知中获取 URL 193 // 从通知中获取 URL
116 - if let payload = userInfo["payload"] as? String,  
117 - let data = payload.data(using: .utf8),  
118 - let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],  
119 - let urlString = dict["url"] as? String,  
120 - let url = URL(string: urlString) {  
121 -  
122 - // 通过 openURL 触发 onOpenURL 回调  
123 - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {  
124 - if UIApplication.shared.canOpenURL(url) {  
125 - UIApplication.shared.open(url)  
126 - }  
127 - } 194 + if let urlString = Self.flutterURLString(from: userInfo) {
  195 + handleFlutterUrl(urlString)
128 } 196 }
129 completionHandler() 197 completionHandler()
130 } 198 }
1 -//  
2 -// AppleHealthTestView.swift  
3 -// Runner  
4 -//  
5 -// Created by 权海 on 2026/6/15.  
6 -//  
7 -  
8 -import SwiftUI  
9 -  
10 -struct AppleHealthTestView: View {  
11 - @State private var logs: [String] = []  
12 - @State private var isRunning = false  
13 - @State private var runningTitle: String?  
14 -  
15 - private let api = HealthKitHostApiImpl()  
16 - private let logTimeFormatter: DateFormatter = {  
17 - let formatter = DateFormatter()  
18 - formatter.dateFormat = "HH:mm:ss.SSS"  
19 - return formatter  
20 - }()  
21 -  
22 - var body: some View {  
23 - NavigationStack {  
24 - VStack(spacing: 0) {  
25 - logPanel  
26 -  
27 - Divider()  
28 -  
29 - HStack(spacing: 12) {  
30 - actionButton(title: "AppleHealth 权限检查", systemImage: "checkmark.shield") {  
31 - await runPermissionCheck()  
32 - }  
33 -  
34 - actionButton(title: "获取数据接口", systemImage: "waveform.path.ecg") {  
35 - await runDataFetch()  
36 - }  
37 - }  
38 - .padding(16)  
39 - .background(.regularMaterial)  
40 - }  
41 - .navigationTitle("Apple Health Test")  
42 - .navigationBarTitleDisplayMode(.inline)  
43 - .toolbar {  
44 - ToolbarItem(placement: .topBarTrailing) {  
45 - Button("清空") {  
46 - logs.removeAll()  
47 - }  
48 - .disabled(isRunning || logs.isEmpty)  
49 - }  
50 - }  
51 - }  
52 - }  
53 -  
54 - private var logPanel: some View {  
55 - ScrollViewReader { proxy in  
56 - ScrollView {  
57 - LazyVStack(alignment: .leading, spacing: 8) {  
58 - if logs.isEmpty {  
59 - ContentUnavailableView(  
60 - "暂无日志",  
61 - systemImage: "list.bullet.rectangle",  
62 - description: Text("点击底部按钮开始测试 HealthKitHostApiImpl。")  
63 - )  
64 - .frame(maxWidth: .infinity, minHeight: 280)  
65 - } else {  
66 - ForEach(Array(logs.enumerated()), id: \.offset) { index, line in  
67 - Text(line)  
68 - .font(.system(.footnote, design: .monospaced))  
69 - .foregroundStyle(line.contains("❌") ? .red : .primary)  
70 - .textSelection(.enabled)  
71 - .frame(maxWidth: .infinity, alignment: .leading)  
72 - .id(index)  
73 - }  
74 - }  
75 - }  
76 - .padding(16)  
77 - }  
78 - .background(Color(.systemGroupedBackground))  
79 - .onChange(of: logs.count) { _, newValue in  
80 - guard newValue > 0 else { return }  
81 - withAnimation(.easeOut(duration: 0.2)) {  
82 - proxy.scrollTo(newValue - 1, anchor: .bottom)  
83 - }  
84 - }  
85 - }  
86 - }  
87 -  
88 - private func actionButton(  
89 - title: String,  
90 - systemImage: String,  
91 - action: @escaping () async -> Void  
92 - ) -> some View {  
93 - Button {  
94 - guard !isRunning else { return }  
95 - Task {  
96 - await runAction(title, action: action)  
97 - }  
98 - } label: {  
99 - Label(isRunning && runningTitle == title ? "执行中..." : title, systemImage: systemImage)  
100 - .font(.system(size: 15, weight: .semibold))  
101 - .frame(maxWidth: .infinity)  
102 - .frame(height: 48)  
103 - }  
104 - .buttonStyle(.borderedProminent)  
105 - .disabled(isRunning)  
106 - }  
107 -  
108 - @MainActor  
109 - private func runAction(_ title: String, action: @escaping () async -> Void) async {  
110 - isRunning = true  
111 - runningTitle = title  
112 - appendLog("▶️ \(title) 开始")  
113 - await action()  
114 - appendLog("✅ \(title) 完成")  
115 - isRunning = false  
116 - runningTitle = nil  
117 - }  
118 -  
119 - private func runPermissionCheck() async {  
120 - do {  
121 - let authorization = try await checkHealthAuthorization()  
122 - appendLog("checkHealthAppAuthorization status=\(authorization.status), hasData=\(authorization.hasData)")  
123 -  
124 - let authUrl = try await getHealthServerAuthUrl()  
125 - appendLog("getHealthServerAuthUrl = \(authUrl.isEmpty ? "<empty, iOS system managed>" : authUrl)")  
126 -  
127 - if authorization.status == 0 {  
128 - appendLog("当前需要请求授权,开始 requestHealthClientAuthorization")  
129 - let granted = try await requestHealthClientAuthorization()  
130 - appendLog("requestHealthClientAuthorization = \(granted)")  
131 - } else {  
132 - appendLog("当前不需要再次请求授权,跳过 requestHealthClientAuthorization")  
133 - }  
134 -  
135 - let cancelResult = try api.cancelHealthAppAuthorization()  
136 - appendLog("cancelHealthAppAuthorization = \(cancelResult) (iOS 不支持应用内撤销)")  
137 - } catch {  
138 - appendError("权限检查失败", error)  
139 - }  
140 - }  
141 -  
142 - private func runDataFetch() async {  
143 - let endTime = Int64(Date().timeIntervalSince1970)  
144 - let startTime = Int64(Calendar.current.date(byAdding: .day, value: -7, to: Date())?.timeIntervalSince1970 ?? Date().timeIntervalSince1970)  
145 - appendLog("数据范围: \(formatTimestamp(startTime)) -> \(formatTimestamp(endTime))")  
146 -  
147 - do {  
148 - let uploadResult = try api.performHealthUpload()  
149 - appendLog(  
150 - "performHealthUpload common=\(uploadResult.commonUploadSuccess), sleep=\(uploadResult.sleepUploadSuccess), error=\(uploadResult.errorMessage ?? "nil")"  
151 - )  
152 - } catch {  
153 - appendError("performHealthUpload 失败", error)  
154 - }  
155 -  
156 - await fetchCommon("HRV", startTime, endTime, api.fetchHrvData)  
157 - await fetchCommon("心率", startTime, endTime, api.fetchHeartRateData)  
158 - await fetchCommon("步行心率", startTime, endTime, api.fetchWalkingHeartRateData)  
159 - await fetchCommon("静息心率", startTime, endTime, api.fetchRestingHeartRateData)  
160 - await fetchCommon("睡眠心率", startTime, endTime, api.fetchSleepingHeartRateData)  
161 - await fetchCommon("血氧", startTime, endTime, api.fetchOxygenSaturationData)  
162 - await fetchCommon("活动能量", startTime, endTime, api.fetchActiveEnergyData)  
163 - await fetchCommon("锻炼", startTime, endTime, api.fetchExerciseData)  
164 - await fetchCommon("站立", startTime, endTime, api.fetchStandData)  
165 - await fetchCommon("步数", startTime, endTime, api.fetchStepCountData)  
166 - await fetchCommon("睡眠腕温", startTime, endTime, api.fetchSleepingWristTemperatureData)  
167 - await fetchCommon("呼吸频率", startTime, endTime, api.fetchRespiratoryRateData)  
168 - await fetchCommon("不规则心律", startTime, endTime, api.fetchIrregularHeartRhythmData)  
169 - await fetchSleep(startTime: startTime, endTime: endTime)  
170 - await fetchActivityTarget(startTime: startTime, endTime: endTime)  
171 - }  
172 -  
173 - private func fetchCommon(  
174 - _ title: String,  
175 - _ startTime: Int64,  
176 - _ endTime: Int64,  
177 - _ fetch: @escaping (Int64, Int64, @escaping (Result<[HealthUploadDataPoint], Error>) -> Void) -> Void  
178 - ) async {  
179 - do {  
180 - let points = try await withCheckedThrowingContinuation { continuation in  
181 - fetch(startTime, endTime) { result in  
182 - continuation.resume(with: result)  
183 - }  
184 - }  
185 - appendLog("\(title): \(points.count) 条")  
186 - appendSample(points)  
187 - } catch {  
188 - appendError("\(title) 获取失败", error)  
189 - }  
190 - }  
191 -  
192 - private func fetchSleep(startTime: Int64, endTime: Int64) async {  
193 - do {  
194 - let points = try await withCheckedThrowingContinuation { continuation in  
195 - api.fetchSleepData(startTime: startTime, endTime: endTime) { result in  
196 - continuation.resume(with: result)  
197 - }  
198 - }  
199 - appendLog("睡眠: \(points.count) 条")  
200 - for point in points.prefix(3) {  
201 - appendLog(" sample dataType=\(point.dataType), from=\(formatTimestamp(point.fromTime)), to=\(formatTimestamp(point.toTime))")  
202 - }  
203 - } catch {  
204 - appendError("睡眠获取失败", error)  
205 - }  
206 - }  
207 -  
208 - private func fetchActivityTarget(startTime: Int64, endTime: Int64) async {  
209 - do {  
210 - let target = try await withCheckedThrowingContinuation { continuation in  
211 - api.fetchActivityTargetData(startTime: startTime, endTime: endTime) { result in  
212 - continuation.resume(with: result)  
213 - }  
214 - }  
215 - if let target {  
216 - appendLog("活动目标: move=\(target.move.map(String.init) ?? "nil"), stand=\(target.stand.map(String.init) ?? "nil")")  
217 - } else {  
218 - appendLog("活动目标: nil")  
219 - }  
220 - } catch {  
221 - appendError("活动目标获取失败", error)  
222 - }  
223 - }  
224 -  
225 - private func checkHealthAuthorization() async throws -> HealthAuthorization {  
226 - try await withCheckedThrowingContinuation { continuation in  
227 - api.checkHealthAppAuthorization { result in  
228 - continuation.resume(with: result)  
229 - }  
230 - }  
231 - }  
232 -  
233 - private func requestHealthClientAuthorization() async throws -> Bool {  
234 - try await withCheckedThrowingContinuation { continuation in  
235 - api.requestHealthClientAuthorization { result in  
236 - continuation.resume(with: result)  
237 - }  
238 - }  
239 - }  
240 -  
241 - private func getHealthServerAuthUrl() async throws -> String {  
242 - try await withCheckedThrowingContinuation { continuation in  
243 - api.getHealthServerAuthUrl { result in  
244 - continuation.resume(with: result)  
245 - }  
246 - }  
247 - }  
248 -  
249 - @MainActor  
250 - private func appendLog(_ message: String) {  
251 - logs.append("[\(logTimeFormatter.string(from: Date()))] \(message)")  
252 - }  
253 -  
254 - @MainActor  
255 - private func appendError(_ prefix: String, _ error: Error) {  
256 - appendLog("❌ \(prefix): \(error.localizedDescription)")  
257 - }  
258 -  
259 - @MainActor  
260 - private func appendSample(_ points: [HealthUploadDataPoint]) {  
261 - for point in points.prefix(3) {  
262 - appendLog(" sample dataType=\(point.dataType), time=\(formatTimestamp(point.time)), value=\(point.value)")  
263 - }  
264 - }  
265 -  
266 - private func formatTimestamp(_ timestamp: Int64) -> String {  
267 - let date = Date(timeIntervalSince1970: TimeInterval(timestamp))  
268 - let formatter = DateFormatter()  
269 - formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"  
270 - return formatter.string(from: date)  
271 - }  
272 -}  
273 -  
274 -#Preview {  
275 - AppleHealthTestView()  
276 -}  
  1 +import Foundation
  2 +
  3 +struct NativeHealthUploadSummary {
  4 + let commonUploadSuccess: Bool
  5 + let sleepUploadSuccess: Bool
  6 + let errorMessage: String?
  7 + let commonCount: Int
  8 + let sleepCount: Int
  9 +}
  10 +
  11 +enum NativeHealthUploadError: LocalizedError {
  12 + case invalidServerURL
  13 + case missingAccessToken
  14 + case invalidResponse
  15 + case requestFailed(path: String, statusCode: Int, body: String?)
  16 +
  17 + var errorDescription: String? {
  18 + switch self {
  19 + case .invalidServerURL:
  20 + return "健康数据上传地址无效"
  21 + case .missingAccessToken:
  22 + return "缺少登录态,无法上传健康数据"
  23 + case .invalidResponse:
  24 + return "健康数据上传接口响应无效"
  25 + case .requestFailed(let path, let statusCode, let body):
  26 + return "健康数据接口请求失败:\(path), HTTP \(statusCode)\(body.map { ", \($0)" } ?? "")"
  27 + }
  28 + }
  29 +}
  30 +
  31 +/// Uploads Apple Health data to DoubleFeel.
  32 +///
  33 +/// Data reading stays in `HealthDataReader` / `HealthKitService`; this type only
  34 +/// owns upload requests and the per-user last-upload-time cache migrated from
  35 +/// the original SwiftUI app.
  36 +final class NativeHealthDataUploader {
  37 + static let shared = NativeHealthDataUploader()
  38 +
  39 + private let session: URLSession
  40 + private var uploadTimeRecorder: NativeHealthUploadTimeRecorder
  41 +
  42 + private let maxUploadTimeWeek = 4
  43 + private let defaultUploadTimeWeek = 1
  44 + private let firstUploadYear = 2
  45 +
  46 + init(
  47 + session: URLSession = .shared,
  48 + uploadTimeRecorder: NativeHealthUploadTimeRecorder = NativeHealthUploadTimeRecorder()
  49 + ) {
  50 + self.session = session
  51 + self.uploadTimeRecorder = uploadTimeRecorder
  52 + }
  53 +
  54 + func uploadAll(service: HealthKitService = .shared) async -> NativeHealthUploadSummary {
  55 + var commonCount = 0
  56 + var sleepCount = 0
  57 + var commonUploadSuccess = true
  58 + var sleepUploadSuccess = true
  59 + var errorMessages: [String] = []
  60 +
  61 + debugLog("uploadAll started, userId=\(AppShared.shared.userId ?? "<nil>")")
  62 + do {
  63 + let uploadTimeList = try await processLastUploadTime()
  64 +
  65 + for type in Self.commonUploadTypes {
  66 + let result = await upload(type: type, uploadTimeList: uploadTimeList, service: service)
  67 + commonCount += result.uploadedCount
  68 + if !result.success {
  69 + commonUploadSuccess = false
  70 + if let errorMessage = result.errorMessage {
  71 + errorMessages.append(errorMessage)
  72 + }
  73 + }
  74 + }
  75 +
  76 + let sleepResult = await upload(type: .sleep, uploadTimeList: uploadTimeList, service: service)
  77 + sleepCount = sleepResult.uploadedCount
  78 + sleepUploadSuccess = sleepResult.success
  79 + if let errorMessage = sleepResult.errorMessage {
  80 + errorMessages.append(errorMessage)
  81 + }
  82 +
  83 + let activityTargetUploaded = await uploadActivityTargetIfNeeded(
  84 + uploadTimeList: uploadTimeList,
  85 + service: service
  86 + )
  87 + if !activityTargetUploaded.success {
  88 + commonUploadSuccess = false
  89 + if let errorMessage = activityTargetUploaded.errorMessage {
  90 + errorMessages.append(errorMessage)
  91 + }
  92 + }
  93 + } catch {
  94 + commonUploadSuccess = false
  95 + sleepUploadSuccess = false
  96 + errorMessages.append(error.localizedDescription)
  97 + debugLog("uploadAll failed before per-type upload, error=\(error.localizedDescription)")
  98 + }
  99 +
  100 + debugLog("uploadAll finished, commonSuccess=\(commonUploadSuccess), sleepSuccess=\(sleepUploadSuccess), commonCount=\(commonCount), sleepCount=\(sleepCount), error=\(errorMessages.isEmpty ? "<nil>" : errorMessages.joined(separator: " | "))")
  101 +
  102 + return NativeHealthUploadSummary(
  103 + commonUploadSuccess: commonUploadSuccess,
  104 + sleepUploadSuccess: sleepUploadSuccess,
  105 + errorMessage: errorMessages.isEmpty ? nil : errorMessages.joined(separator: "\n"),
  106 + commonCount: commonCount,
  107 + sleepCount: sleepCount
  108 + )
  109 + }
  110 +
  111 + func upload(type: NativeHealthDataType, service: HealthKitService = .shared) async -> Bool {
  112 + do {
  113 + let uploadTimeList = try await processLastUploadTime()
  114 + return await upload(type: type, uploadTimeList: uploadTimeList, service: service).success
  115 + } catch {
  116 + debugLog("upload(\(type.debugName)) failed to process last upload time, error=\(error.localizedDescription)")
  117 + print("Health upload failed to process last upload time: \(error.localizedDescription)")
  118 + return false
  119 + }
  120 + }
  121 +}
  122 +
  123 +private extension NativeHealthDataUploader {
  124 + struct UploadTaskResult {
  125 + let success: Bool
  126 + let uploadedCount: Int
  127 + let errorMessage: String?
  128 + }
  129 +
  130 + static let commonUploadTypes: [NativeHealthDataType] = [
  131 + .hrv,
  132 + .heartRate,
  133 + .walkingHeartRate,
  134 + .restingHeartRate,
  135 + .sleepingHeartRate,
  136 + .oxygenSaturation,
  137 + .activeEnergy,
  138 + .exercise,
  139 + .stand,
  140 + .steps,
  141 + .sleepingWristTemperature,
  142 + .respiratoryRate,
  143 + .irregularHeartRhythm,
  144 + ]
  145 +
  146 + func upload(
  147 + type: NativeHealthDataType,
  148 + uploadTimeList: NativeHealthUploadTimeList,
  149 + service: HealthKitService
  150 + ) async -> UploadTaskResult {
  151 + guard type != .unknown,
  152 + let startUploadDate = uploadTimeList.latestDataTime(for: type) else {
  153 + debugLog("[\(type.debugName)] skipped, no upload start date")
  154 + return UploadTaskResult(success: true, uploadedCount: 0, errorMessage: nil)
  155 + }
  156 +
  157 + let endUploadDate = Date()
  158 + debugLog(
  159 + "[\(type.debugName)] upload started, range=\(Self.debugDateFormatter.string(from: startUploadDate)) -> \(Self.debugDateFormatter.string(from: endUploadDate))"
  160 + )
  161 + guard endUploadDate >= startUploadDate else {
  162 + debugLog("[\(type.debugName)] upload failed, start date is later than end date")
  163 + return UploadTaskResult(
  164 + success: false,
  165 + uploadedCount: 0,
  166 + errorMessage: "健康数据上传开始时间晚于结束时间:\(type)"
  167 + )
  168 + }
  169 +
  170 + do {
  171 + switch type {
  172 + case .sleep:
  173 + debugLog("[\(type.debugName)] reading sleep data")
  174 + let data = try await service.fetchSleepData(startDate: startUploadDate, endDate: endUploadDate)
  175 + debugLog("[\(type.debugName)] read finished, count=\(data.count)")
  176 + guard !data.isEmpty else {
  177 + uploadTimeRecorder.save(date: endUploadDate, for: type)
  178 + debugLog("[\(type.debugName)] no data, saved upload time=\(Self.debugDateFormatter.string(from: endUploadDate))")
  179 + return UploadTaskResult(success: true, uploadedCount: 0, errorMessage: nil)
  180 + }
  181 + debugLog("[\(type.debugName)] uploading, count=\(data.count)")
  182 + try await uploadSleep(data)
  183 + uploadTimeRecorder.save(date: endUploadDate, for: type)
  184 + debugLog("[\(type.debugName)] upload success, count=\(data.count), saved upload time=\(Self.debugDateFormatter.string(from: endUploadDate))")
  185 + return UploadTaskResult(success: true, uploadedCount: data.count, errorMessage: nil)
  186 + default:
  187 + debugLog("[\(type.debugName)] reading common data")
  188 + let data = try await fetchCommonData(
  189 + type: type,
  190 + startDate: startUploadDate,
  191 + endDate: endUploadDate,
  192 + service: service
  193 + )
  194 + debugLog("[\(type.debugName)] read finished, count=\(data.count)")
  195 + guard !data.isEmpty else {
  196 + uploadTimeRecorder.save(date: endUploadDate, for: type)
  197 + debugLog("[\(type.debugName)] no data, saved upload time=\(Self.debugDateFormatter.string(from: endUploadDate))")
  198 + return UploadTaskResult(success: true, uploadedCount: 0, errorMessage: nil)
  199 + }
  200 + debugLog("[\(type.debugName)] uploading, count=\(data.count)")
  201 + try await uploadCommon(data)
  202 + uploadTimeRecorder.save(date: endUploadDate, for: type)
  203 + debugLog("[\(type.debugName)] upload success, count=\(data.count), saved upload time=\(Self.debugDateFormatter.string(from: endUploadDate))")
  204 + return UploadTaskResult(success: true, uploadedCount: data.count, errorMessage: nil)
  205 + }
  206 + } catch {
  207 + debugLog("[\(type.debugName)] upload failed, error=\(error.localizedDescription)")
  208 + return UploadTaskResult(
  209 + success: false,
  210 + uploadedCount: 0,
  211 + errorMessage: "健康数据上传失败:\(type), \(error.localizedDescription)"
  212 + )
  213 + }
  214 + }
  215 +
  216 + func fetchCommonData(
  217 + type: NativeHealthDataType,
  218 + startDate: Date,
  219 + endDate: Date,
  220 + service: HealthKitService
  221 + ) async throws -> [NativeHealthDataPoint] {
  222 + switch type {
  223 + case .hrv:
  224 + return try await service.fetchHrvData(startDate: startDate, endDate: endDate)
  225 + case .heartRate:
  226 + return try await service.fetchHeartRateData(startDate: startDate, endDate: endDate)
  227 + case .walkingHeartRate:
  228 + return try await service.fetchWalkingHeartRateData(startDate: startDate, endDate: endDate)
  229 + case .restingHeartRate:
  230 + return try await service.fetchRestingHeartRateData(startDate: startDate, endDate: endDate)
  231 + case .sleepingHeartRate:
  232 + return try await service.fetchSleepingHeartRateData(startDate: startDate, endDate: endDate)
  233 + case .oxygenSaturation:
  234 + return try await service.fetchOxygenSaturationData(startDate: startDate, endDate: endDate)
  235 + case .activeEnergy:
  236 + return try await service.fetchActiveEnergyData(startDate: startDate, endDate: endDate)
  237 + case .exercise:
  238 + return try await service.fetchExerciseData(startDate: startDate, endDate: endDate)
  239 + case .stand:
  240 + return try await service.fetchStandData(startDate: startDate, endDate: endDate)
  241 + case .steps:
  242 + return try await service.fetchStepCountData(startDate: startDate, endDate: endDate)
  243 + case .sleepingWristTemperature:
  244 + return try await service.fetchSleepingWristTemperatureData(startDate: startDate, endDate: endDate)
  245 + case .respiratoryRate:
  246 + return try await service.fetchRespiratoryRateData(startDate: startDate, endDate: endDate)
  247 + case .irregularHeartRhythm:
  248 + return try await service.fetchIrregularHeartRhythmData(startDate: startDate, endDate: endDate)
  249 + case .unknown, .sleep:
  250 + return []
  251 + }
  252 + }
  253 +
  254 + func uploadActivityTargetIfNeeded(
  255 + uploadTimeList: NativeHealthUploadTimeList,
  256 + service: HealthKitService
  257 + ) async -> UploadTaskResult {
  258 + let startDate = uploadTimeList.latestDataTime(for: .activeEnergy)
  259 + ?? Calendar.current.date(byAdding: .weekOfYear, value: -defaultUploadTimeWeek, to: Date())
  260 + ?? Date(timeIntervalSinceNow: -7 * 24 * 60 * 60)
  261 + let endDate = Date()
  262 +
  263 + debugLog(
  264 + "[activityTarget] upload started, range=\(Self.debugDateFormatter.string(from: startDate)) -> \(Self.debugDateFormatter.string(from: endDate))"
  265 + )
  266 + do {
  267 + guard let target = try await service.fetchActivityTargetData(startDate: startDate, endDate: endDate),
  268 + target.move != nil || target.stand != nil else {
  269 + debugLog("[activityTarget] no target data")
  270 + return UploadTaskResult(success: true, uploadedCount: 0, errorMessage: nil)
  271 + }
  272 + debugLog("[activityTarget] uploading, move=\(target.move.map(String.init) ?? "<nil>"), stand=\(target.stand.map(String.init) ?? "<nil>")")
  273 + try await uploadActivityTarget(target)
  274 + debugLog("[activityTarget] upload success")
  275 + return UploadTaskResult(success: true, uploadedCount: 1, errorMessage: nil)
  276 + } catch {
  277 + debugLog("[activityTarget] upload failed, error=\(error.localizedDescription)")
  278 + return UploadTaskResult(
  279 + success: false,
  280 + uploadedCount: 0,
  281 + errorMessage: "活动目标上传失败:\(error.localizedDescription)"
  282 + )
  283 + }
  284 + }
  285 +
  286 + func processLastUploadTime() async throws -> NativeHealthUploadTimeList {
  287 + let localTimeList = uploadTimeRecorder.records
  288 + let serverTimeList = try? await fetchLastUploadTime()
  289 + var resultTimeList: [NativeHealthUploadTimeList.HealthUploadTime] = []
  290 + debugLog("processLastUploadTime started, hasServerTimeList=\(serverTimeList != nil)")
  291 +
  292 + let fourWeeksAgo = Calendar.current.date(byAdding: .weekOfYear, value: -maxUploadTimeWeek, to: Date())
  293 + ?? Date(timeIntervalSinceNow: -TimeInterval(maxUploadTimeWeek * 7 * 24 * 60 * 60))
  294 + let fourWeeksAgoMidnight = Calendar.current.startOfDay(for: fourWeeksAgo).timeIntervalSince1970
  295 +
  296 + let oneWeekAgo = Calendar.current.date(byAdding: .weekOfYear, value: -defaultUploadTimeWeek, to: Date())
  297 + ?? Date(timeIntervalSinceNow: -TimeInterval(defaultUploadTimeWeek * 7 * 24 * 60 * 60))
  298 + let oneWeekAgoMidnight = Calendar.current.startOfDay(for: oneWeekAgo).timeIntervalSince1970
  299 +
  300 + let twoYearsAgo = Calendar.current.date(byAdding: .year, value: -firstUploadYear, to: Date())
  301 + ?? Date(timeIntervalSinceNow: -TimeInterval(firstUploadYear * 365 * 24 * 60 * 60))
  302 + let twoYearsAgoMidnight = Calendar.current.startOfDay(for: twoYearsAgo).timeIntervalSince1970
  303 +
  304 + for type in NativeHealthDataType.allCases where type != .unknown {
  305 + let localTime = localTimeList.latestTimeInterval(for: type)
  306 + let serverTime = serverTimeList?.latestTimeInterval(for: type)
  307 +
  308 + let finalTime: TimeInterval
  309 + if let localTime, localTime > fourWeeksAgoMidnight {
  310 + finalTime = localTime
  311 + } else if let serverTime, serverTime > fourWeeksAgoMidnight {
  312 + finalTime = serverTime
  313 + } else if localTime != nil || serverTime != nil {
  314 + finalTime = oneWeekAgoMidnight
  315 + } else {
  316 + finalTime = twoYearsAgoMidnight
  317 + }
  318 +
  319 + debugLog(
  320 + "[\(type.debugName)] resolved start time=\(Self.debugDateFormatter.string(from: Date(timeIntervalSince1970: finalTime))), local=\(localTime.map { Self.debugDateFormatter.string(from: Date(timeIntervalSince1970: $0)) } ?? "<nil>"), server=\(serverTime.map { Self.debugDateFormatter.string(from: Date(timeIntervalSince1970: $0)) } ?? "<nil>")"
  321 + )
  322 + resultTimeList.append(
  323 + NativeHealthUploadTimeList.HealthUploadTime(
  324 + dataType: type,
  325 + latestDataTime: finalTime
  326 + )
  327 + )
  328 + }
  329 +
  330 + return NativeHealthUploadTimeList(latestDataTimeList: resultTimeList)
  331 + }
  332 +
  333 + func uploadCommon(_ data: [NativeHealthDataPoint]) async throws {
  334 + let list = data.map {
  335 + [
  336 + "data_type": $0.dataType.rawValue,
  337 + "time": $0.time,
  338 + "value": $0.value,
  339 + ] as [String: Any]
  340 + }
  341 + try await request(path: "/client/doublefeel/health/data_upload/common/", method: "POST", body: ["data_list": list])
  342 + }
  343 +
  344 + func uploadSleep(_ data: [NativeSleepInterval]) async throws {
  345 + let list = data.map {
  346 + [
  347 + "data_type": $0.dataType,
  348 + "from_time": $0.fromTime,
  349 + "to_time": $0.toTime,
  350 + ] as [String: Any]
  351 + }
  352 + try await request(path: "/client/doublefeel/health/data_upload/sleep/", method: "POST", body: ["data_list": list])
  353 + }
  354 +
  355 + func uploadActivityTarget(_ target: NativeActivityTarget) async throws {
  356 + var body: [String: Any] = [:]
  357 + body["move"] = target.move
  358 + body["stand"] = target.stand
  359 + try await request(path: "/client/doublefeel/health/activity_target/", method: "POST", body: body)
  360 + }
  361 +
  362 + func fetchLastUploadTime() async throws -> NativeHealthUploadTimeList {
  363 + let data = try await request(path: "/client/doublefeel/health/data_upload/common/", method: "GET")
  364 + return try NativeHealthUploadTimeList.decode(from: data)
  365 + }
  366 +
  367 + @discardableResult
  368 + func request(path: String, method: String, body: [String: Any]? = nil) async throws -> Data {
  369 + guard let baseURL = URL(string: AppShared.shared.baseUrl),
  370 + let url = URL(string: path, relativeTo: baseURL)?.absoluteURL else {
  371 + throw NativeHealthUploadError.invalidServerURL
  372 + }
  373 + guard let accessToken = AppShared.shared.token, !accessToken.isEmpty else {
  374 + throw NativeHealthUploadError.missingAccessToken
  375 + }
  376 +
  377 + var request = URLRequest(url: url)
  378 + request.httpMethod = method
  379 + request.timeoutInterval = 60
  380 + request.setValue("application/json", forHTTPHeaderField: "Accept")
  381 + request.setValue(accessToken, forHTTPHeaderField: "access_token")
  382 + request.setValue(AppShared.shared.agent.finalUA, forHTTPHeaderField: "User-Agent")
  383 +
  384 + if let body {
  385 + request.setValue("application/json", forHTTPHeaderField: "Content-Type")
  386 + request.httpBody = try JSONSerialization.data(withJSONObject: body)
  387 + }
  388 +
  389 + let (data, response) = try await session.data(for: request)
  390 + guard let httpResponse = response as? HTTPURLResponse else {
  391 + throw NativeHealthUploadError.invalidResponse
  392 + }
  393 + guard (200..<300).contains(httpResponse.statusCode) else {
  394 + throw NativeHealthUploadError.requestFailed(
  395 + path: path,
  396 + statusCode: httpResponse.statusCode,
  397 + body: String(data: data, encoding: .utf8)
  398 + )
  399 + }
  400 + return data
  401 + }
  402 +
  403 + static let debugDateFormatter: DateFormatter = {
  404 + let formatter = DateFormatter()
  405 + formatter.locale = Locale(identifier: "en_US_POSIX")
  406 + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  407 + return formatter
  408 + }()
  409 +
  410 + func debugLog(_ message: String) {
  411 + #if DEBUG || CI_ENV
  412 + print("[NativeHealthDataUploader] \(message)")
  413 + #endif
  414 + }
  415 +}
  416 +
  417 +struct NativeHealthUploadTimeList: Codable {
  418 + struct HealthUploadTime: Codable {
  419 + let dataType: NativeHealthDataType?
  420 + let latestDataTime: TimeInterval?
  421 +
  422 + enum CodingKeys: String, CodingKey {
  423 + case dataType = "data_type"
  424 + case latestDataTime = "latest_data_time"
  425 + }
  426 + }
  427 +
  428 + var latestDataTimeList: [HealthUploadTime]
  429 +
  430 + enum CodingKeys: String, CodingKey {
  431 + case latestDataTimeList = "latest_data_time_list"
  432 + }
  433 +
  434 + func latestDataTime(for type: NativeHealthDataType) -> Date? {
  435 + latestTimeInterval(for: type).map(Date.init(timeIntervalSince1970:))
  436 + }
  437 +
  438 + func latestTimeInterval(for type: NativeHealthDataType) -> TimeInterval? {
  439 + latestDataTimeList.first { $0.dataType == type }?.latestDataTime
  440 + }
  441 +
  442 + static func decode(from data: Data) throws -> NativeHealthUploadTimeList {
  443 + let decoder = JSONDecoder()
  444 +
  445 + if let direct = try? decoder.decode(NativeHealthUploadTimeList.self, from: data) {
  446 + return direct
  447 + }
  448 +
  449 + let wrapped = try decoder.decode(HealthUploadTimeListResponse.self, from: data)
  450 + if let data = wrapped.data {
  451 + return data
  452 + }
  453 + throw NativeHealthUploadError.invalidResponse
  454 + }
  455 +}
  456 +
  457 +private struct HealthUploadTimeListResponse: Decodable {
  458 + let data: NativeHealthUploadTimeList?
  459 +}
  460 +
  461 +struct NativeHealthUploadTimeRecorder {
  462 + private var cachedRecords: NativeHealthUploadTimeList?
  463 + private static let cacheKey = "HealthUploadlocalRecord_records"
  464 +
  465 + var records: NativeHealthUploadTimeList {
  466 + mutating get {
  467 + if let cachedRecords {
  468 + return cachedRecords
  469 + }
  470 + let records = Self.loadFromCache() ?? NativeHealthUploadTimeList(latestDataTimeList: [])
  471 + cachedRecords = records
  472 + return records
  473 + }
  474 + set {
  475 + cachedRecords = newValue
  476 + Self.saveToCache(newValue)
  477 + }
  478 + }
  479 +
  480 + init(records: NativeHealthUploadTimeList? = nil) {
  481 + cachedRecords = records
  482 + }
  483 +
  484 + mutating func save(date: Date, for type: NativeHealthDataType) {
  485 + var records = records
  486 + records.latestDataTimeList.removeAll { $0.dataType == type }
  487 + records.latestDataTimeList.append(
  488 + NativeHealthUploadTimeList.HealthUploadTime(
  489 + dataType: type,
  490 + latestDataTime: date.timeIntervalSince1970
  491 + )
  492 + )
  493 + self.records = records
  494 + }
  495 +
  496 + static func clearCache() {
  497 + UserDefaults.standard.removeObject(forKey: cacheKeyForCurrentUser())
  498 + }
  499 +
  500 + private static func loadFromCache() -> NativeHealthUploadTimeList? {
  501 + guard let data = UserDefaults.standard.data(forKey: cacheKeyForCurrentUser()) else {
  502 + return nil
  503 + }
  504 + return try? JSONDecoder().decode(NativeHealthUploadTimeList.self, from: data)
  505 + }
  506 +
  507 + private static func saveToCache(_ records: NativeHealthUploadTimeList) {
  508 + guard let data = try? JSONEncoder().encode(records) else {
  509 + return
  510 + }
  511 + UserDefaults.standard.set(data, forKey: cacheKeyForCurrentUser())
  512 + }
  513 +
  514 + private static func cacheKeyForCurrentUser() -> String {
  515 + let userId = AppShared.shared.userId
  516 + ?? AppShared.shared.userSummary?.meUserInfo?.id.map(String.init)
  517 + ?? AppGroupConstants.defaults?.string(forKey: AppGroupConstants.Key.userId)
  518 + ?? ""
  519 + return cacheKey + userId
  520 + }
  521 +}
  522 +
  523 +private extension NativeHealthDataType {
  524 + var debugName: String {
  525 + switch self {
  526 + case .unknown:
  527 + return "unknown"
  528 + case .hrv:
  529 + return "hrv"
  530 + case .heartRate:
  531 + return "heartRate"
  532 + case .oxygenSaturation:
  533 + return "oxygenSaturation"
  534 + case .activeEnergy:
  535 + return "activeEnergy"
  536 + case .exercise:
  537 + return "exercise"
  538 + case .stand:
  539 + return "stand"
  540 + case .steps:
  541 + return "steps"
  542 + case .walkingHeartRate:
  543 + return "walkingHeartRate"
  544 + case .restingHeartRate:
  545 + return "restingHeartRate"
  546 + case .sleepingHeartRate:
  547 + return "sleepingHeartRate"
  548 + case .sleepingWristTemperature:
  549 + return "sleepingWristTemperature"
  550 + case .respiratoryRate:
  551 + return "respiratoryRate"
  552 + case .irregularHeartRhythm:
  553 + return "irregularHeartRhythm"
  554 + case .sleep:
  555 + return "sleep"
  556 + }
  557 + }
  558 +}
  1 +//
  2 +// NSArray+OBSMTLManipulationAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Josh Abernathy on 9/19/12.
  6 +// Copyright (c) 2012 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSArray (OBSMTLManipulationAdditions)
  12 +
  13 +/// The first object in the array or nil if the array is empty.
  14 +/// Forwards to `firstObject` which has been first declared in iOS7, but works with iOS4/10.6.
  15 +@property (nonatomic, readonly, strong) id obs_mtl_firstObject;
  16 +
  17 +/// Returns a new array without all instances of the given object.
  18 +- (NSArray *)obs_mtl_arrayByRemovingObject:(id)object;
  19 +
  20 +/// Returns a new array without the first object. If the array is empty, it
  21 +/// returns the empty array.
  22 +- (NSArray *)obs_mtl_arrayByRemovingFirstObject;
  23 +
  24 +/// Returns a new array without the last object. If the array is empty, it
  25 +/// returns the empty array.
  26 +- (NSArray *)obs_mtl_arrayByRemovingLastObject;
  27 +
  28 +@end
  1 +//
  2 +// NSDictionary+OBSMTLJSONKeyPath.h
  3 +// Mantle
  4 +//
  5 +// Created by Robert Böhnke on 19/03/14.
  6 +// Copyright (c) 2014 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSDictionary (OBSMTLJSONKeyPath)
  12 +
  13 +/// Looks up the value of a key path in the receiver.
  14 +///
  15 +/// JSONKeyPath - The key path that should be resolved. Every element along this
  16 +/// key path needs to be an instance of NSDictionary for the
  17 +/// resolving to be successful.
  18 +/// success - If not NULL, this will be set to a boolean indicating whether
  19 +/// the key path was resolved successfully.
  20 +/// error - If not NULL, this may be set to an error that occurs during
  21 +/// resolving the value.
  22 +///
  23 +/// Returns the value for the key path which may be nil. Clients should inspect
  24 +/// the success parameter to decide how to proceed with the result.
  25 +- (id)obs_mtl_valueForJSONKeyPath:(NSString *)JSONKeyPath success:(BOOL *)success error:(NSError **)error;
  26 +
  27 +@end
  1 +//
  2 +// NSDictionary+OBSMTLManipulationAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Justin Spahr-Summers on 2012-09-24.
  6 +// Copyright (c) 2012 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSDictionary (OBSMTLManipulationAdditions)
  12 +
  13 +/// Merges the keys and values from the given dictionary into the receiver. If
  14 +/// both the receiver and `dictionary` have a given key, the value from
  15 +/// `dictionary` is used.
  16 +///
  17 +/// Returns a new dictionary containing the entries of the receiver combined with
  18 +/// those of `dictionary`.
  19 +- (NSDictionary *)obs_mtl_dictionaryByAddingEntriesFromDictionary:(NSDictionary *)dictionary;
  20 +
  21 +/// Creates a new dictionary with all the entries for the given keys removed from
  22 +/// the receiver.
  23 +- (NSDictionary *)obs_mtl_dictionaryByRemovingValuesForKeys:(NSArray *)keys;
  24 +
  25 +@end
  26 +
  27 +@interface NSDictionary (OBSMTLManipulationAdditions_Deprecated)
  28 +
  29 +- (NSDictionary *)obs_mtl_dictionaryByRemovingEntriesWithKeys:(NSSet *)keys __attribute__((deprecated("Replaced by -obs_mtl_dictionaryByRemovingValuesForKeys:")));
  30 +
  31 +@end
  1 +//
  2 +// NSDictionary+OBSMTLMappingAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Robert Böhnke on 10/31/13.
  6 +// Copyright (c) 2013 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSDictionary (OBSMTLMappingAdditions)
  12 +
  13 +/// Creates an identity mapping for serialization.
  14 +///
  15 +/// class - A subclass of OBSMTLModel.
  16 +///
  17 +/// Returns a dictionary that maps all properties of the given class to
  18 +/// themselves.
  19 ++ (NSDictionary *)obs_mtl_identityPropertyMapWithModel:(Class)modelClass;
  20 +
  21 +@end
  1 +//
  2 +// NSError+OBSMTLModelException.h
  3 +// Mantle
  4 +//
  5 +// Created by Robert Böhnke on 7/6/13.
  6 +// Copyright (c) 2013 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSError (OBSMTLModelException)
  12 +
  13 +/// Creates a new error for an exception that occurred during updating an
  14 +/// OBSMTLModel.
  15 +///
  16 +/// exception - The exception that was thrown while updating the model.
  17 +/// This argument must not be nil.
  18 +///
  19 +/// Returns an error that takes its localized description and failure reason
  20 +/// from the exception.
  21 ++ (instancetype)obs_mtl_modelErrorWithException:(NSException *)exception;
  22 +
  23 +@end
  1 +//
  2 +// NSObject+OBSMTLComparisonAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Josh Vera on 10/26/12.
  6 +// Copyright (c) 2012 GitHub. All rights reserved.
  7 +//
  8 +// Portions copyright (c) 2011 Bitswift. All rights reserved.
  9 +// See the LICENSE file for more information.
  10 +//
  11 +
  12 +#import <Foundation/Foundation.h>
  13 +
  14 +/// Returns whether both objects are identical or equal via -isEqual:
  15 +BOOL OBSMTLEqualObjects(id obj1, id obj2);
  1 +//
  2 +// NSValueTransformer+OBSMTLInversionAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Justin Spahr-Summers on 2013-05-18.
  6 +// Copyright (c) 2013 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface NSValueTransformer (OBSMTLInversionAdditions)
  12 +
  13 +/// Flips the direction of the receiver's transformation, such that
  14 +/// -transformedValue: will become -reverseTransformedValue:, and vice-versa.
  15 +///
  16 +/// The receiver must allow reverse transformation.
  17 +///
  18 +/// Returns an inverted transformer.
  19 +- (NSValueTransformer *)obs_mtl_invertedTransformer;
  20 +
  21 +@end
  1 +//
  2 +// NSValueTransformer+OBSMTLPredefinedTransformerAdditions.h
  3 +// Mantle
  4 +//
  5 +// Created by Justin Spahr-Summers on 2012-09-27.
  6 +// Copyright (c) 2012 GitHub. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +#import "OBSMTLTransformerErrorHandling.h"
  12 +
  13 +/// The name for a value transformer that converts strings into URLs and back.
  14 +extern NSString *const OBSMTLURLValueTransformerName;
  15 +
  16 +/// The name for a value transformer that converts strings into NSUUIDs and back.
  17 +extern NSString *const OBSMTLUUIDValueTransformerName;
  18 +
  19 +/// Ensure an NSNumber is backed by __NSCFBoolean/CFBooleanRef
  20 +///
  21 +/// NSJSONSerialization, and likely other serialization libraries, ordinarily
  22 +/// serialize NSNumbers as numbers, and thus booleans would be serialized as
  23 +/// 0/1. The exception is when the NSNumber is backed by __NSCFBoolean, which,
  24 +/// though very much an implementation detail, is detected and serialized as a
  25 +/// proper boolean.
  26 +extern NSString *const OBSMTLBooleanValueTransformerName;
  27 +
  28 +@interface NSValueTransformer (OBSMTLPredefinedTransformerAdditions)
  29 +
  30 +/// An optionally reversible transformer which applies the given transformer to
  31 +/// each element of an array.
  32 +///
  33 +/// transformer - The transformer to apply to each element. If the transformer
  34 +/// is reversible, the transformer returned by this method will be
  35 +/// reversible. This argument must not be nil.
  36 +///
  37 +/// Returns a transformer which applies a transformation to each element of an
  38 +/// array.
  39 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer;
  40 +
  41 +/// A reversible value transformer to transform between the keys and objects of a
  42 +/// dictionary.
  43 +///
  44 +/// dictionary - The dictionary whose keys and values should be
  45 +/// transformed between. This argument must not be nil.
  46 +/// defaultValue - The result to fall back to, in case no key matching the
  47 +/// input value was found during a forward transformation.
  48 +/// reverseDefaultValue - The result to fall back to, in case no value matching
  49 +/// the input value was found during a reverse
  50 +/// transformation.
  51 +///
  52 +/// Can for example be used for transforming between enum values and their string
  53 +/// representation.
  54 +///
  55 +/// NSValueTransformer *valueTransformer = [NSValueTransformer obs_mtl_valueMappingTransformerWithDictionary:@{
  56 +/// @"foo": @(EnumDataTypeFoo),
  57 +/// @"bar": @(EnumDataTypeBar),
  58 +/// } defaultValue: @(EnumDataTypeUndefined) reverseDefaultValue: @"undefined"];
  59 +///
  60 +/// Returns a transformer which will map from keys to objects for forward
  61 +/// transformations, and from objects to keys for reverse transformations.
  62 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary defaultValue:(id)defaultValue reverseDefaultValue:(id)reverseDefaultValue;
  63 +
  64 +/// Returns a value transformer created by calling
  65 +/// `+obs_mtl_valueMappingTransformerWithDictionary:defaultValue:reverseDefaultValue:`
  66 +/// with a default value of `nil` and a reverse default value of `nil`.
  67 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary;
  68 +
  69 +/// A reversible value transformer to transform between a date and its string
  70 +/// representation
  71 +///
  72 +/// dateFormat - The date format used by the date formatter (http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table)
  73 +/// calendar - The calendar used by the date formatter
  74 +/// locale - The locale used by the date formatter
  75 +/// timeZone - The time zone used by the date formatter
  76 +///
  77 +/// Returns a transformer which will map from strings to dates for forward
  78 +/// transformations, and from dates to strings for reverse transformations.
  79 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_dateTransformerWithDateFormat:(NSString *)dateFormat calendar:(NSCalendar *)calendar locale:(NSLocale *)locale timeZone:(NSTimeZone *)timeZone defaultDate:(NSDate *)defaultDate;
  80 +
  81 +/// Returns a value transformer created by calling
  82 +/// `+obs_mtl_dateTransformerWithDateFormat:calendar:locale:timeZone:defaultDate:`
  83 +/// with a calendar, locale, time zone and default date of `nil`.
  84 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_dateTransformerWithDateFormat:(NSString *)dateFormat locale:(NSLocale *)locale;
  85 +
  86 +/// A reversible value transformer to transform between a number and its string
  87 +/// representation
  88 +///
  89 +/// numberStyle - The number style used by the number formatter
  90 +///
  91 +/// Returns a transformer which will map from strings to numbers for forward
  92 +/// transformations, and from numbers to strings for reverse transformations.
  93 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_numberTransformerWithNumberStyle:(NSNumberFormatterStyle)numberStyle locale:(NSLocale *)locale;
  94 +
  95 +/// A reversible value transformer to transform between an object and its string
  96 +/// representation
  97 +///
  98 +/// formatter - The formatter used to perform the transformation
  99 +/// objectClass - The class of object that the formatter operates on
  100 +///
  101 +/// Returns a transformer which will map from strings to objects for forward
  102 +/// transformations, and from objects to strings for reverse transformations.
  103 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_transformerWithFormatter:(NSFormatter *)formatter forObjectClass:(Class)objectClass;
  104 +
  105 +/// A value transformer that errors if the transformed value are not of the given
  106 +/// class.
  107 +///
  108 +/// class - The expected class. This argument must not be nil.
  109 +///
  110 +/// Returns a transformer which will return an error if the transformed in value
  111 +/// is not a member of class. Otherwise, the value is simply passed through.
  112 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_validatingTransformerForClass:(Class)modelClass;
  113 +
  114 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_JSONDictionaryTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[OBSMTLJSONAdapter dictionaryTransformerWithModelClass:]")));
  115 +
  116 ++ (NSValueTransformer<OBSMTLTransformerErrorHandling> *)obs_mtl_JSONArrayTransformerWithModelClass:(Class)modelClass __attribute__((deprecated("Replaced by +[OBSMTLJSONAdapter arrayTransformerWithModelClass:]")));
  117 +
  118 +@end
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBS_h
  14 +#define OBS_h
  15 +#import <Foundation/Foundation.h>
  16 +
  17 +NS_ASSUME_NONNULL_BEGIN
  18 + //! Project version number for OBS.
  19 +FOUNDATION_EXPORT double OBSVersionNumber;
  20 +
  21 + //! Project version string for OBS.
  22 +FOUNDATION_EXPORT unsigned char OBSVersionString[];
  23 +NS_ASSUME_NONNULL_END
  24 +
  25 +#import "OBSBaseNetworking.h"
  26 +#import "OBSClient.h"
  27 +#import "OBSServiceBaseModel.h"
  28 +#import "OBSUtils.h"
  29 +#import "OBSBolts.h"
  30 +#import "OBSServiceCredentialProvider.h"
  31 +#import "OBSMantle.h"
  32 +#import "OBSLogging.h"
  33 +
  34 +#import "OBSServiceCommonEntities.h"
  35 +
  36 +
  37 +#pragma mark service models
  38 +#pragma mark presign
  39 +#import "OBSPreSignedURLModel.h"
  40 +
  41 +#pragma mark bucket
  42 +#import "OBSListBucketsModel.h"
  43 +#import "OBSCreateBucketModel.h"
  44 +
  45 +
  46 +#import "OBSGetBucketMetaDataModel.h"
  47 +#import "OBSGetBucketLocationModel.h"
  48 +#import "OBSGetBucketStorageInfoModel.h"
  49 +
  50 +#import "OBSSetBucketQuotaModel.h"
  51 +#import "OBSGetBucketQuotaModel.h"
  52 +
  53 +#import "OBSSetBucketACLModel.h"
  54 +#import "OBSGetBucketACLModel.h"
  55 +
  56 +#import "OBSSetBucketCORSModel.h"
  57 +#import "OBSGetBucketCORSModel.h"
  58 +#import "OBSDeleteBucketCORSModel.h"
  59 +
  60 +#import "OBSSetBucketStoragePolicyModel.h"
  61 +#import "OBSGetBucketStoragePolicyModel.h"
  62 +
  63 +#import "OBSSetBucketLoggingModel.h"
  64 +#import "OBSGetBucketLoggingModel.h"
  65 +
  66 +#import "OBSSetBucketPolicyModel.h"
  67 +#import "OBSGetBucketPolicyModel.h"
  68 +#import "OBSDeleteBucketPolicyModel.h"
  69 +
  70 +#import "OBSSetBucketLifecycleModel.h"
  71 +#import "OBSGetBucketLifecycleModel.h"
  72 +#import "OBSDeleteBucketLifecycleModel.h"
  73 +
  74 +#import "OBSSetBucketWebsiteModel.h"
  75 +#import "OBSGetBucketWebsiteModel.h"
  76 +#import "OBSDeleteBucketWebsiteModel.h"
  77 +
  78 +#import "OBSSetBucketVersioningModel.h"
  79 +#import "OBSGetBucketVersioningModel.h"
  80 +
  81 +#import "OBSSetBucketNotificationModel.h"
  82 +#import "OBSGetBucketNotificationModel.h"
  83 +
  84 +#import "OBSOptionsBucketModel.h"
  85 +
  86 +#import "OBSListMultipartUploadsModel.h"
  87 +
  88 +#import "OBSSetBucketTaggingModel.h"
  89 +#import "OBSGetBucketTaggingModel.h"
  90 +#import "OBSDeleteBucketTaggingModel.h"
  91 +
  92 +#import "OBSDeleteBucketModel.h"
  93 +#import "OBSReplicateBucketModel.h"
  94 +#import "OBSGetReplicateBucketModel.h"
  95 +#import "OBSDeleteReplicateBucketModel.h"
  96 +#import "OBSAppendObjectModel.h"
  97 +
  98 +#pragma mark object
  99 +#import "OBSPutObjectModel.h"
  100 +#import "OBSGetObjectModel.h"
  101 +#import "OBSCopyObjectModel.h"
  102 +
  103 +#import "OBSSetObjectACLModel.h"
  104 +#import "OBSGetObjectACLModel.h"
  105 +
  106 +#import "OBSListObjectsModel.h"
  107 +#import "OBSListObjectsVersionsModel.h"
  108 +
  109 +#import "OBSGetObjectMetaDataModel.h"
  110 +#import "OBSOptionsObjectModel.h"
  111 +#import "OBSRestoreObjectModel.h"
  112 +
  113 +#import "OBSInitiateMultipartUploadModel.h"
  114 +#import "OBSUploadPartModel.h"
  115 +#import "OBSCopyPartModel.h"
  116 +#import "OBSListPartsModel.h"
  117 +#import "OBSCompleteMultipartUploadModel.h"
  118 +#import "OBSAbortMultipartUploadModel.h"
  119 +
  120 +#import "OBSDeleteObjectModel.h"
  121 +#import "OBSDeleteObjectsModel.h"
  122 +
  123 +#pragma mark additional
  124 +#import "OBSDownloadFileModel.h"
  125 +#import "OBSUploadFileModel.h"
  126 +
  127 +#import "OBSUploadFileModel.h"
  128 +#import "OBSGetBucketLocationModel.h"
  129 +#import "OBSGetBucketStorageInfoModel.h"
  130 +#import "OBSSetBucketQuotaModel.h"
  131 +#import "OBSGetBucketStorageInfoModel.h"
  132 +#import "OBSServiceUtils.h"
  133 +#import "OBSListPartsModel.h"
  134 +#import "OBSAbortMultipartUploadModel.h"
  135 +#import "OBSCompleteMultipartUploadModel.h"
  136 +#import "OBSDownloadFileModel.h"
  137 +#import "OBSDeleteObjectModel.h"
  138 +#import "OBSDeleteObjectsModel.h"
  139 +#endif /* OBS_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSAbortMultipartUploadModel_h
  14 +#define OBSAbortMultipartUploadModel_h
  15 +
  16 +#import "OBSBaseNetworking.h"
  17 +#import "OBSClient.h"
  18 +#import "OBSServiceBaseModel.h"
  19 +#import "OBSServiceConstDefinition.h"
  20 +
  21 +@class OBSAbstractEncryption;
  22 + //request
  23 +#pragma mark - request
  24 +
  25 +/**
  26 + 取消多段上传任务
  27 + */
  28 +@protocol OBSAbortMultipartUploadProtocol<NSObject>
  29 +@required
  30 +
  31 +/**
  32 + 桶名
  33 + */
  34 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  35 +
  36 +/**
  37 + 对象名
  38 + */
  39 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  40 +
  41 +/**
  42 + 多段上传任务ID
  43 + */
  44 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  45 +@end
  46 +
  47 +
  48 +/**
  49 + 取消多段上传任务request
  50 + */
  51 +@interface OBSAbortMultipartUploadRequest : OBSBaseRequest<OBSAbortMultipartUploadProtocol>
  52 +
  53 +/**
  54 + 桶名
  55 + */
  56 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  57 +
  58 +/**
  59 + 对象key
  60 + */
  61 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  62 +
  63 +/**
  64 + 多段上传任务ID
  65 + */
  66 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  67 +
  68 +/**
  69 + 初始化取消多段上传任务request
  70 +
  71 + @param bucketName 桶名
  72 + @param objectKey 对象KEY
  73 + @param uploadID 多段上传任务ID
  74 + @return 取消多段上传request
  75 + */
  76 +-(instancetype)initWithBucketName:(NSString*) bucketName objectKey: (NSString*) objectKey uploadID:(NSString*) uploadID;
  77 +@end
  78 +
  79 +#pragma mark - networking request
  80 +@interface OBSNetworkingAbortMultipartUploadRequest : OBSServiceNetworkingCommandRequest
  81 +@end
  82 +
  83 + //response
  84 +#pragma mark - response
  85 +
  86 +/**
  87 + 取消多段上传response
  88 + */
  89 +@interface OBSAbortMultipartUploadResponse: OBSServiceResponse
  90 +@end
  91 +
  92 + //client method
  93 +#pragma mark - client method
  94 +@interface OBSClient(abortMultipartUpload)
  95 +
  96 +/**
  97 + 取消多段上传
  98 +
  99 + @param request 取消多段上传request
  100 + @param completionHandler 取消多段上传回调
  101 + @return OBSBFTask
  102 + */
  103 +- (OBSBFTask*)abortMultipartUpload:(__kindof OBSBaseRequest<OBSAbortMultipartUploadProtocol>*)request
  104 + completionHandler:(void (^)(OBSAbortMultipartUploadResponse * response, NSError * error))completionHandler;
  105 +@end
  106 +#endif /* OBSAbortMultipartUploadModel_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSAppendObjectRequest_h
  14 +#define OBSAppendObjectRequest_h
  15 +
  16 +#import "OBSBaseNetworking.h"
  17 +#import "OBSClient.h"
  18 +#import "OBSServiceBaseModel.h"
  19 +#import "OBSServiceConstDefinition.h"
  20 +
  21 + //request
  22 +@class OBSAbstractEncryption;
  23 +#pragma mark - request
  24 +
  25 +/**
  26 + 上传对象
  27 + */
  28 +@protocol OBSAppendObjectProtocol<NSObject>
  29 +@required
  30 +
  31 +/**
  32 + 桶名
  33 + */
  34 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  35 +
  36 +/**
  37 + 对象名
  38 + */
  39 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  40 +
  41 +/**
  42 + MD5值
  43 + */
  44 +@property (nonatomic, strong, nonnull) NSString *contentMD5;
  45 +
  46 +/**
  47 + 对象访问策略
  48 + */
  49 +@property (nonatomic, assign) OBSACLPolicy objectACLPolicy;
  50 +
  51 +/**
  52 + 对象存储类型
  53 + */
  54 +@property (nonatomic, assign) OBSStorageClass storageClass;
  55 +
  56 +/**
  57 + 元数据字典
  58 + */
  59 +@property (nonatomic, strong, nullable) NSDictionary *metaDataDict;
  60 +
  61 +/**
  62 + 重定向地址
  63 + */
  64 +@property (nonatomic, strong, nonnull) NSString *websiteRedirectLocation;
  65 +
  66 +/**
  67 + 加密方式
  68 + */
  69 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  70 +
  71 +/**
  72 + 上传进度
  73 + */
  74 +@property (nonatomic, copy, nonnull) OBSNetworkingUploadProgressBlock uploadProgressBlock;
  75 +@end
  76 +
  77 +
  78 +/**
  79 + 上传对象request父类
  80 + */
  81 +@interface OBSAbstractAppendObjectRequest : OBSBaseRequest<OBSAppendObjectProtocol>
  82 +
  83 +/**
  84 + 桶名
  85 + */
  86 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  87 +
  88 +/**
  89 + 对象描述标识
  90 + */
  91 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  92 +
  93 +/**
  94 + 对象的MD5
  95 + */
  96 +@property (nonatomic, strong, nonnull) NSString *contentMD5;
  97 +
  98 +/**
  99 + 对象的ACL
  100 + */
  101 +@property (nonatomic, assign) OBSACLPolicy objectACLPolicy;
  102 +
  103 +/**
  104 + 对象存储类型
  105 + */
  106 +@property (nonatomic, assign) OBSStorageClass storageClass;
  107 +
  108 +/**
  109 + 对象元数据字典
  110 + */
  111 +@property (nonatomic, strong, nullable) NSDictionary *metaDataDict;
  112 +
  113 +/**
  114 + 对象重定向地址
  115 + */
  116 +@property (nonatomic, strong, nonnull) NSString *websiteRedirectLocation;
  117 +
  118 +/**
  119 + 创建对象时,使用此头域授权domain下所有用户有读对象和获取对象元数据的权限
  120 + */
  121 +@property (nonatomic, strong, nonnull) NSString *granteRead;
  122 +
  123 +/**
  124 +创建对象时,使用此头域授权domain下所有用户有读对象和获取对象元数据的权限
  125 +*/
  126 +@property (nonatomic, strong, nonnull) NSString *granteReadAcp;
  127 +
  128 +/**
  129 + 创建对象时,使用此头域授权domain下所有用户有获取对象ACL的权限
  130 + */
  131 +@property (nonatomic, strong, nonnull) NSString *granteWriteAcp;
  132 +
  133 +/**
  134 + 创建对象时,使用此头域授权domain下所有用户有读对象、获取对象元数据、获取对象ACL、写对象ACL的权限
  135 + */
  136 +@property (nonatomic, strong, nonnull) NSString *granteFullControl;
  137 +
  138 +/**
  139 + 此参数的值是一个URL,用于指定当此次请求操作成功响应后的重定向的地址
  140 + 如果此参数值有效且操作成功,响应码为303,location头域由此参数以及桶名、对象名、对象的ETag组成
  141 + 如果此参数值无效,忽略此参数的作用,响应码为204,location头域为对象地址
  142 + */
  143 +@property (nonatomic, strong, nonnull) NSString *actionRedirect;
  144 +
  145 +/**
  146 + 表示上传对象的过期时间,单位是天
  147 + */
  148 +@property (nonatomic, strong, nonnull) NSNumber *expires;
  149 +
  150 +/**
  151 + 追加写位置
  152 + */
  153 +@property (nonatomic, strong, nonnull) NSNumber *position;
  154 +
  155 +
  156 +
  157 +/**
  158 + 加密方式
  159 + */
  160 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  161 +
  162 +/**
  163 + 上传对象时的回调
  164 + */
  165 +@property (nonatomic, copy, nonnull) OBSNetworkingUploadProgressBlock uploadProgressBlock;
  166 +
  167 +/**
  168 + 自定义MIME类型
  169 + */
  170 +@property (nonatomic, strong, nonnull) NSString *customContentType;
  171 +@end
  172 +
  173 +
  174 +/**
  175 + 流式上传对象request
  176 + */
  177 +@interface OBSAppendObjectWithDataRequest: OBSAbstractAppendObjectRequest
  178 +
  179 +/**
  180 + 上传的数据
  181 + */
  182 +@property (nonatomic, strong, nonnull) NSData *uploadData;
  183 +
  184 +/**
  185 + 初始化流式上传对象request
  186 +
  187 + @param bucketName 桶名
  188 + @param objectKey 对象名
  189 + @param data 需要上传的对象数据
  190 + @return 流式上传对象request
  191 + */
  192 +-(instancetype)initWithBucketName:(NSString*) bucketName objectKey: (NSString*) objectKey uploadData:(NSData*) data;
  193 +
  194 +/**
  195 + 初始上传网络流对象request
  196 +
  197 + @param bucketName 桶名
  198 + @param objectKey 对象名
  199 + @param dataURL 需要上传的网络流地址
  200 + @return 上传网络流对象request
  201 + */
  202 +-(instancetype)initWithBucketName:(NSString*) bucketName objectKey: (NSString*) objectKey uploadDataURL:(NSURL*) dataURL;
  203 +@end
  204 +
  205 +/**
  206 + 通过文件上传对象request
  207 + */
  208 +@interface OBSAppendObjectWithFileRequest: OBSAbstractAppendObjectRequest
  209 +
  210 +/**
  211 + 文件路径
  212 + */
  213 +@property (nonatomic, strong, nonnull) NSString *uploadFilePath;
  214 +@property (nonatomic, assign) BOOL background;
  215 +
  216 +/**
  217 + 初始化通过文件上传对象request
  218 +
  219 + @param bucketName 桶名
  220 + @param objectKey 对象描述标识
  221 + @param uploadFilePath 文件路径
  222 + @return 通过文件上传对象request
  223 + */
  224 +-(instancetype)initWithBucketName:(NSString*) bucketName objectKey: (NSString*) objectKey uploadFilePath:(NSString*) uploadFilePath;
  225 +@end
  226 +
  227 +#pragma mark - networking request
  228 +@interface OBSNetworkingAppendObjectWithDataRequest : OBSServiceNetworkingUploadDataRequest
  229 +@end
  230 +@interface OBSNetworkingAppendObjectWithFileRequest : OBSServiceNetworkingUploadFileRequest
  231 +@end
  232 +
  233 + //response
  234 +#pragma mark - response
  235 +
  236 +/**
  237 + 上传对象响应
  238 + */
  239 +@interface OBSAppendObjectResponse: OBSServiceResponse
  240 +
  241 +/**
  242 + 对象etag值
  243 + */
  244 +@property (nonatomic, strong, nonnull) NSString *etag;
  245 +
  246 +/**
  247 + 如果桶开启了多版本状态 则返回版本号
  248 + */
  249 +@property (nonatomic, strong, nonnull) NSString *versionID;
  250 +
  251 +/**
  252 + 对象存储类型
  253 + */
  254 +@property (nonatomic, assign) OBSStorageClass storageClass;
  255 +
  256 +/**
  257 + 对象加密方式
  258 + */
  259 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  260 +@end
  261 +
  262 + //client method
  263 +#pragma mark - client method
  264 +@interface OBSClient(appendObject)
  265 +
  266 +/**
  267 + 上传对象
  268 +
  269 + @param request 上传对象request
  270 + @param completionHandler 上传对象回调
  271 + @return OBSBFTask
  272 + */
  273 +- (OBSBFTask*)appendObject:(__kindof OBSBaseRequest<OBSAppendObjectProtocol>*)request
  274 + completionHandler:(void (^)(OBSAppendObjectResponse * response, NSError * error))completionHandler;
  275 +@end
  276 +#endif /* OBSAppendObjectRequest_h */
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +#import "OBSBFCancellationTokenRegistration.h"
  14 +
  15 +NS_ASSUME_NONNULL_BEGIN
  16 +
  17 +/*!
  18 + A block that will be called when a token is cancelled.
  19 + */
  20 +typedef void(^OBSBFCancellationBlock)(void);
  21 +
  22 +/*!
  23 + The consumer view of a CancellationToken.
  24 + Propagates notification that operations should be canceled.
  25 + A OBSBFCancellationToken has methods to inspect whether the token has been cancelled.
  26 + */
  27 +@interface OBSBFCancellationToken : NSObject
  28 +
  29 +/*!
  30 + Whether cancellation has been requested for this token source.
  31 + */
  32 +@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
  33 +
  34 +/*!
  35 + Register a block to be notified when the token is cancelled.
  36 + If the token is already cancelled the delegate will be notified immediately.
  37 + */
  38 +- (OBSBFCancellationTokenRegistration *)registerCancellationObserverWithBlock:(OBSBFCancellationBlock)block;
  39 +
  40 +@end
  41 +
  42 +NS_ASSUME_NONNULL_END
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +NS_ASSUME_NONNULL_BEGIN
  14 +
  15 +/*!
  16 + Represents the registration of a cancellation observer with a cancellation token.
  17 + Can be used to unregister the observer at a later time.
  18 + */
  19 +@interface OBSBFCancellationTokenRegistration : NSObject
  20 +
  21 +/*!
  22 + Removes the cancellation observer registered with the token
  23 + and releases all resources associated with this registration.
  24 + */
  25 +- (void)dispose;
  26 +
  27 +@end
  28 +
  29 +NS_ASSUME_NONNULL_END
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +NS_ASSUME_NONNULL_BEGIN
  14 +
  15 +@class OBSBFCancellationToken;
  16 +
  17 +/*!
  18 + OBSBFCancellationTokenSource represents the producer side of a CancellationToken.
  19 + Signals to a CancellationToken that it should be canceled.
  20 + It is a cancellation token that also has methods
  21 + for changing the state of a token by cancelling it.
  22 + */
  23 +@interface OBSBFCancellationTokenSource : NSObject
  24 +
  25 +/*!
  26 + Creates a new cancellation token source.
  27 + */
  28 ++ (instancetype)cancellationTokenSource;
  29 +
  30 +/*!
  31 + The cancellation token associated with this CancellationTokenSource.
  32 + */
  33 +@property (nonatomic, strong, readonly) OBSBFCancellationToken *token;
  34 +
  35 +/*!
  36 + Whether cancellation has been requested for this token source.
  37 + */
  38 +@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
  39 +
  40 +/*!
  41 + Cancels the token if it has not already been cancelled.
  42 + */
  43 +- (void)cancel;
  44 +
  45 +/*!
  46 + Schedules a cancel operation on this CancellationTokenSource after the specified number of milliseconds.
  47 + @param millis The number of milliseconds to wait before completing the returned task.
  48 + If delay is `0` the cancel is executed immediately. If delay is `-1` any scheduled cancellation is stopped.
  49 + */
  50 +- (void)cancelAfterDelay:(int)millis;
  51 +
  52 +/*!
  53 + Releases all resources associated with this token source,
  54 + including disposing of all registrations.
  55 + */
  56 +- (void)dispose;
  57 +
  58 +@end
  59 +
  60 +NS_ASSUME_NONNULL_END
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +NS_ASSUME_NONNULL_BEGIN
  14 +
  15 +/*!
  16 + An object that can run a given block.
  17 + */
  18 +@interface OBSBFExecutor : NSObject
  19 +
  20 +/*!
  21 + Returns a default executor, which runs continuations immediately until the call stack gets too
  22 + deep, then dispatches to a new GCD queue.
  23 + */
  24 ++ (instancetype)defaultExecutor;
  25 +
  26 +/*!
  27 + Returns an executor that runs continuations on the thread where the previous task was completed.
  28 + */
  29 ++ (instancetype)immediateExecutor;
  30 +
  31 +/*!
  32 + Returns an executor that runs continuations on the main thread.
  33 + */
  34 ++ (instancetype)mainThreadExecutor;
  35 +
  36 +/*!
  37 + Returns a new executor that uses the given block to execute continuations.
  38 + @param block The block to use.
  39 + */
  40 ++ (instancetype)executorWithBlock:(void(^)(void(^block)(void)))block;
  41 +
  42 +/*!
  43 + Returns a new executor that runs continuations on the given queue.
  44 + @param queue The instance of `dispatch_queue_t` to dispatch all continuations onto.
  45 + */
  46 ++ (instancetype)executorWithDispatchQueue:(dispatch_queue_t)queue;
  47 +
  48 +/*!
  49 + Returns a new executor that runs continuations on the given queue.
  50 + @param queue The instance of `NSOperationQueue` to run all continuations on.
  51 + */
  52 ++ (instancetype)executorWithOperationQueue:(NSOperationQueue *)queue;
  53 +
  54 +/*!
  55 + Runs the given block using this executor's particular strategy.
  56 + @param block The block to execute.
  57 + */
  58 +- (void)execute:(void(^)(void))block;
  59 +
  60 +@end
  61 +
  62 +NS_ASSUME_NONNULL_END
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +#pragma once
  14 +
  15 +/**
  16 + This exists to use along with `OBSBFTask` and `OBSBFTaskCompletionSource`.
  17 +
  18 + Instead of returning a `OBSBFTask` with no generic type, or a generic type of 'NSNull'
  19 + when there is no usable result from a task, we use the type 'OBSBFVoid', which will always have a value of `nil`.
  20 +
  21 + This allows you to provide a more enforced API contract to the caller,
  22 + as sending any message to `OBSBFVoid` will result in a compile time error.
  23 + */
  24 +@class _OBSBFVoid_Nonexistant;
  25 +typedef _OBSBFVoid_Nonexistant *OBSBFVoid;
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +#import "OBSBFCancellationToken.h"
  14 +#import "OBSBFGeneric.h"
  15 +
  16 +NS_ASSUME_NONNULL_BEGIN
  17 +
  18 +/*!
  19 + Error domain used if there was multiple errors on <OBSBFTask taskForCompletionOfAllTasks:>.
  20 + */
  21 +extern NSString *const OBSBFTaskErrorDomain;
  22 +
  23 +/*!
  24 + An error code used for <OBSBFTask taskForCompletionOfAllTasks:>, if there were multiple errors.
  25 + */
  26 +extern NSInteger const kOBSBFMultipleErrorsError;
  27 +
  28 +/*!
  29 + An error userInfo key used if there were multiple errors on <OBSBFTask taskForCompletionOfAllTasks:>.
  30 + Value type is `NSArray<NSError *> *`.
  31 + */
  32 +extern NSString *const OBSBFTaskMultipleErrorsUserInfoKey;
  33 +
  34 +@class OBSBFExecutor;
  35 +@class OBSBFTask;
  36 +
  37 +/*!
  38 + The consumer view of a Task. A OBSBFTask has methods to
  39 + inspect the state of the task, and to add continuations to
  40 + be run once the task is complete.
  41 + */
  42 +@interface OBSBFTask<__covariant ResultType> : NSObject
  43 +
  44 +/*!
  45 + A block that can act as a continuation for a task.
  46 + */
  47 +typedef __nullable id(^OBSBFContinuationBlock)(OBSBFTask<ResultType> *t);
  48 +
  49 +/*!
  50 + Creates a task that is already completed with the given result.
  51 + @param result The result for the task.
  52 + */
  53 ++ (instancetype)taskWithResult:(nullable ResultType)result;
  54 +
  55 +/*!
  56 + Creates a task that is already completed with the given error.
  57 + @param error The error for the task.
  58 + */
  59 ++ (instancetype)taskWithError:(NSError *)error;
  60 +
  61 +/*!
  62 + Creates a task that is already cancelled.
  63 + */
  64 ++ (instancetype)cancelledTask;
  65 +
  66 +/*!
  67 + Returns a task that will be completed (with result == nil) once
  68 + all of the input tasks have completed.
  69 + @param tasks An `NSArray` of the tasks to use as an input.
  70 + */
  71 ++ (instancetype)taskForCompletionOfAllTasks:(nullable NSArray<OBSBFTask *> *)tasks;
  72 +
  73 +/*!
  74 + Returns a task that will be completed once all of the input tasks have completed.
  75 + If all tasks complete successfully without being faulted or cancelled the result will be
  76 + an `NSArray` of all task results in the order they were provided.
  77 + @param tasks An `NSArray` of the tasks to use as an input.
  78 + */
  79 ++ (instancetype)taskForCompletionOfAllTasksWithResults:(nullable NSArray<OBSBFTask *> *)tasks;
  80 +
  81 +/*!
  82 + Returns a task that will be completed once there is at least one successful task.
  83 + The first task to successuly complete will set the result, all other tasks results are
  84 + ignored.
  85 + @param tasks An `NSArray` of the tasks to use as an input.
  86 + */
  87 ++ (instancetype)taskForCompletionOfAnyTask:(nullable NSArray<OBSBFTask *> *)tasks;
  88 +
  89 +/*!
  90 + Returns a task that will be completed a certain amount of time in the future.
  91 + @param millis The approximate number of milliseconds to wait before the
  92 + task will be finished (with result == nil).
  93 + */
  94 ++ (OBSBFTask<OBSBFVoid> *)taskWithDelay:(int)millis;
  95 +
  96 +/*!
  97 + Returns a task that will be completed a certain amount of time in the future.
  98 + @param millis The approximate number of milliseconds to wait before the
  99 + task will be finished (with result == nil).
  100 + @param token The cancellation token (optional).
  101 + */
  102 ++ (OBSBFTask<OBSBFVoid> *)taskWithDelay:(int)millis cancellationToken:(nullable OBSBFCancellationToken *)token;
  103 +
  104 +/*!
  105 + Returns a task that will be completed after the given block completes with
  106 + the specified executor.
  107 + @param executor A OBSBFExecutor responsible for determining how the
  108 + continuation block will be run.
  109 + @param block The block to immediately schedule to run with the given executor.
  110 + @returns A task that will be completed after block has run.
  111 + If block returns a OBSBFTask, then the task returned from
  112 + this method will not be completed until that task is completed.
  113 + */
  114 ++ (instancetype)taskFromExecutor:(OBSBFExecutor *)executor withBlock:(nullable id (^)(void))block;
  115 +
  116 +// Properties that will be set on the task once it is completed.
  117 +
  118 +/*!
  119 + The result of a successful task.
  120 + */
  121 +@property (nullable, nonatomic, strong, readonly) ResultType result;
  122 +
  123 +/*!
  124 + The error of a failed task.
  125 + */
  126 +@property (nullable, nonatomic, strong, readonly) NSError *error;
  127 +
  128 +/*!
  129 + Whether this task has been cancelled.
  130 + */
  131 +@property (nonatomic, assign, readonly, getter=isCancelled) BOOL cancelled;
  132 +
  133 +/*!
  134 + Whether this task has completed due to an error.
  135 + */
  136 +@property (nonatomic, assign, readonly, getter=isFaulted) BOOL faulted;
  137 +
  138 +/*!
  139 + Whether this task has completed.
  140 + */
  141 +@property (nonatomic, assign, readonly, getter=isCompleted) BOOL completed;
  142 +
  143 +/*!
  144 + Enqueues the given block to be run once this task is complete.
  145 + This method uses a default execution strategy. The block will be
  146 + run on the thread where the previous task completes, unless the
  147 + the stack depth is too deep, in which case it will be run on a
  148 + dispatch queue with default priority.
  149 + @param block The block to be run once this task is complete.
  150 + @returns A task that will be completed after block has run.
  151 + If block returns a OBSBFTask, then the task returned from
  152 + this method will not be completed until that task is completed.
  153 + */
  154 +- (OBSBFTask *)continueWithBlock:(OBSBFContinuationBlock)block NS_SWIFT_NAME(continueWith(block:));
  155 +
  156 +/*!
  157 + Enqueues the given block to be run once this task is complete.
  158 + This method uses a default execution strategy. The block will be
  159 + run on the thread where the previous task completes, unless the
  160 + the stack depth is too deep, in which case it will be run on a
  161 + dispatch queue with default priority.
  162 + @param block The block to be run once this task is complete.
  163 + @param cancellationToken The cancellation token (optional).
  164 + @returns A task that will be completed after block has run.
  165 + If block returns a OBSBFTask, then the task returned from
  166 + this method will not be completed until that task is completed.
  167 + */
  168 +- (OBSBFTask *)continueWithBlock:(OBSBFContinuationBlock)block
  169 + cancellationToken:(nullable OBSBFCancellationToken *)cancellationToken NS_SWIFT_NAME(continueWith(block:cancellationToken:));
  170 +
  171 +/*!
  172 + Enqueues the given block to be run once this task is complete.
  173 + @param executor A OBSBFExecutor responsible for determining how the
  174 + continuation block will be run.
  175 + @param block The block to be run once this task is complete.
  176 + @returns A task that will be completed after block has run.
  177 + If block returns a OBSBFTask, then the task returned from
  178 + this method will not be completed until that task is completed.
  179 + */
  180 +- (OBSBFTask *)continueWithExecutor:(OBSBFExecutor *)executor
  181 + withBlock:(OBSBFContinuationBlock)block NS_SWIFT_NAME(continueWith(executor:block:));
  182 +
  183 +/*!
  184 + Enqueues the given block to be run once this task is complete.
  185 + @param executor A OBSBFExecutor responsible for determining how the
  186 + continuation block will be run.
  187 + @param block The block to be run once this task is complete.
  188 + @param cancellationToken The cancellation token (optional).
  189 + @returns A task that will be completed after block has run.
  190 + If block returns a OBSBFTask, then the task returned from
  191 + his method will not be completed until that task is completed.
  192 + */
  193 +- (OBSBFTask *)continueWithExecutor:(OBSBFExecutor *)executor
  194 + block:(OBSBFContinuationBlock)block
  195 + cancellationToken:(nullable OBSBFCancellationToken *)cancellationToken
  196 +NS_SWIFT_NAME(continueWith(executor:block:cancellationToken:));
  197 +
  198 +/*!
  199 + Identical to continueWithBlock:, except that the block is only run
  200 + if this task did not produce a cancellation or an error.
  201 + If it did, then the failure will be propagated to the returned
  202 + task.
  203 + @param block The block to be run once this task is complete.
  204 + @returns A task that will be completed after block has run.
  205 + If block returns a OBSBFTask, then the task returned from
  206 + this method will not be completed until that task is completed.
  207 + */
  208 +- (OBSBFTask *)continueWithSuccessBlock:(OBSBFContinuationBlock)block NS_SWIFT_NAME(continueOnSuccessWith(block:));
  209 +
  210 +/*!
  211 + Identical to continueWithBlock:, except that the block is only run
  212 + if this task did not produce a cancellation or an error.
  213 + If it did, then the failure will be propagated to the returned
  214 + task.
  215 + @param block The block to be run once this task is complete.
  216 + @param cancellationToken The cancellation token (optional).
  217 + @returns A task that will be completed after block has run.
  218 + If block returns a OBSBFTask, then the task returned from
  219 + this method will not be completed until that task is completed.
  220 + */
  221 +- (OBSBFTask *)continueWithSuccessBlock:(OBSBFContinuationBlock)block
  222 + cancellationToken:(nullable OBSBFCancellationToken *)cancellationToken
  223 +NS_SWIFT_NAME(continueOnSuccessWith(block:cancellationToken:));
  224 +
  225 +/*!
  226 + Identical to continueWithExecutor:withBlock:, except that the block
  227 + is only run if this task did not produce a cancellation, error, or an error.
  228 + If it did, then the failure will be propagated to the returned task.
  229 + @param executor A OBSBFExecutor responsible for determining how the
  230 + continuation block will be run.
  231 + @param block The block to be run once this task is complete.
  232 + @returns A task that will be completed after block has run.
  233 + If block returns a OBSBFTask, then the task returned from
  234 + this method will not be completed until that task is completed.
  235 + */
  236 +- (OBSBFTask *)continueWithExecutor:(OBSBFExecutor *)executor
  237 + withSuccessBlock:(OBSBFContinuationBlock)block NS_SWIFT_NAME(continueOnSuccessWith(executor:block:));
  238 +
  239 +/*!
  240 + Identical to continueWithExecutor:withBlock:, except that the block
  241 + is only run if this task did not produce a cancellation or an error.
  242 + If it did, then the failure will be propagated to the returned task.
  243 + @param executor A OBSBFExecutor responsible for determining how the
  244 + continuation block will be run.
  245 + @param block The block to be run once this task is complete.
  246 + @param cancellationToken The cancellation token (optional).
  247 + @returns A task that will be completed after block has run.
  248 + If block returns a OBSBFTask, then the task returned from
  249 + this method will not be completed until that task is completed.
  250 + */
  251 +- (OBSBFTask *)continueWithExecutor:(OBSBFExecutor *)executor
  252 + successBlock:(OBSBFContinuationBlock)block
  253 + cancellationToken:(nullable OBSBFCancellationToken *)cancellationToken
  254 +NS_SWIFT_NAME(continueOnSuccessWith(executor:block:cancellationToken:));
  255 +
  256 +/*!
  257 + Waits until this operation is completed.
  258 + This method is inefficient and consumes a thread resource while
  259 + it's running. It should be avoided. This method logs a warning
  260 + message if it is used on the main thread.
  261 + */
  262 +- (void)waitUntilFinished;
  263 +
  264 +@end
  265 +
  266 +NS_ASSUME_NONNULL_END
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import <Foundation/Foundation.h>
  12 +
  13 +NS_ASSUME_NONNULL_BEGIN
  14 +
  15 +@class OBSBFTask<__covariant ResultType>;
  16 +
  17 +/*!
  18 + A OBSBFTaskCompletionSource represents the producer side of tasks.
  19 + It is a task that also has methods for changing the state of the
  20 + task by settings its completion values.
  21 + */
  22 +@interface OBSBFTaskCompletionSource<__covariant ResultType> : NSObject
  23 +
  24 +/*!
  25 + Creates a new unfinished task.
  26 + */
  27 ++ (instancetype)taskCompletionSource;
  28 +
  29 +/*!
  30 + The task associated with this TaskCompletionSource.
  31 + */
  32 +@property (nonatomic, strong, readonly) OBSBFTask<ResultType> *task;
  33 +
  34 +/*!
  35 + Completes the task by setting the result.
  36 + Attempting to set this for a completed task will raise an exception.
  37 + @param result The result of the task.
  38 + */
  39 +- (void)setResult:(nullable ResultType)result NS_SWIFT_NAME(set(result:));
  40 +
  41 +/*!
  42 + Completes the task by setting the error.
  43 + Attempting to set this for a completed task will raise an exception.
  44 + @param error The error for the task.
  45 + */
  46 +- (void)setError:(NSError *)error NS_SWIFT_NAME(set(error:));
  47 +
  48 +/*!
  49 + Completes the task by marking it as cancelled.
  50 + Attempting to set this for a completed task will raise an exception.
  51 + */
  52 +- (void)cancel;
  53 +
  54 +/*!
  55 + Sets the result of the task if it wasn't already completed.
  56 + @returns whether the new value was set.
  57 + */
  58 +- (BOOL)trySetResult:(nullable ResultType)result NS_SWIFT_NAME(trySet(result:));
  59 +
  60 +/*!
  61 + Sets the error of the task if it wasn't already completed.
  62 + @param error The error for the task.
  63 + @returns whether the new value was set.
  64 + */
  65 +- (BOOL)trySetError:(NSError *)error NS_SWIFT_NAME(trySet(error:));
  66 +
  67 +/*!
  68 + Sets the cancellation state of the task if it wasn't already completed.
  69 + @returns whether the new value was set.
  70 + */
  71 +- (BOOL)trySetCancelled;
  72 +
  73 +@end
  74 +
  75 +NS_ASSUME_NONNULL_END
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSBaseCategory_h
  14 +#define OBSBaseCategory_h
  15 +#import "OBSBaseConstDefinition.h"
  16 +#import "OBSMTLJSONAdapter.h"
  17 +#import "OBSMTLValueTransformer.h"
  18 +@class OBSBaseNetworkingRequest;
  19 +@class OBSBFTaskCompletionSource;
  20 +
  21 +
  22 +
  23 +@interface NSString (OBS)
  24 + //data to NSString with utf8 encoding
  25 ++ (nullable instancetype)obs_initWithDataUTF8:(NSData *)data;
  26 + //OBSHTTPMethod enum to string
  27 ++ (nullable instancetype)obs_initWithOBSHTTPMethod:(OBSHTTPMethod) HTTPMethod;
  28 + //url string remove tailing slash
  29 +- (nullable NSString*)obs_removeTailSlash;
  30 + //url string append query string
  31 +//- (nullable NSString*)obs_stringByAppendingQueryStringForURL:(NSDictionary *)queryDict;
  32 + //trim spaces
  33 +- (nullable NSString*)obs_trim;
  34 +
  35 +-(nullable NSString*)stringWithRepeatTimes:(NSInteger) times;
  36 +
  37 + //bool with string
  38 +//-(BOOL) obs_boolWithString;
  39 + //OBSHTTPMethod string to enum
  40 +//- (OBSHTTPMethod)obs_OBSHTTPMethodWithString;
  41 + //OBSBodyType string to enum
  42 +//-(OBSBodyType)obs_OBSBodyTypeWithString;
  43 + //URL encoding
  44 +-(nullable NSString*)obs_stringWithURLEncodingAllowedSet;
  45 +//-(nullable NSString*)obs_stringWithURLEncodingAll;
  46 +//-(nullable NSString*)obs_stringWithURLEncodingAllowedAlphanumeric;
  47 + //string substitue
  48 +-(nullable NSString*)obs_stringSubstituteWithDict:(NSDictionary*) dict;
  49 + //xml encoding
  50 +//-(nullable NSString*)obs_XMLEncodeString;
  51 +@end
  52 +
  53 +@interface NSDictionary(OBS)
  54 +//-(NSString*)obs_convertDictionaryToXMLWithStartNode:(NSString*)startNode;
  55 +-(NSString*)obs_XMLString;
  56 +- (NSString *)obs_innerXML:(NSInteger) ident;
  57 +- (nullable NSDictionary *)obs_childNodes;
  58 +- (nullable NSDictionary<NSString *, NSString *> *)obs_attributes;
  59 +@end
  60 +
  61 +@interface NSMutableArray(OBS)
  62 +-(id)pop;
  63 +-(void)push:(id)obj;
  64 +@end
  65 +
  66 +@interface NSURLSessionTask(OBS)
  67 +-(OBSBaseNetworkingRequest*)obsNetworkingRequest;
  68 +-(void)setObsNetworkingRequest:(OBSBaseNetworkingRequest*) networkingRequest;
  69 +@end
  70 +
  71 +@interface OBSMTLJSONAdapter(OBS)
  72 ++ (NSDictionary *)valueTransformersForModelClass:(Class)modelClass;
  73 +@end
  74 +
  75 +@interface OBSMTLValueTransformer(OBS)
  76 +//+(NSValueTransformer*)obs_mtl_nsnumberIntegerTransformer;
  77 ++(NSValueTransformer*)obs_mtl_nsnumberLongLongTransformer;
  78 ++(NSValueTransformer*)obs_mtl_nsnumberUIntegerTransformer;
  79 ++(NSValueTransformer*)obs_mtl_nsdateRFC1123Transformer;
  80 ++(NSValueTransformer*)obs_mtl_nsdateIOS8601Format3Transformer;
  81 +//+(NSValueTransformer*)obs_mtl_filterNullStringTransformer;
  82 +@end
  83 +#endif /* OBSBaseCategory_h */
  1 +//
  2 +// OBSBaseConstDefinition.h
  3 +// OBS
  4 +//
  5 +// Created by MaxZhang on 10/10/2017.
  6 +// Copyright © 2017 obs. All rights reserved.
  7 +//
  8 +
  9 +#ifndef OBSBaseDefinition_h
  10 +#define OBSBaseDefinition_h
  11 +
  12 +
  13 +static NSString *const OBSSDKVersion =@"3.24.4";
  14 +
  15 +static NSUInteger const maxConcurrentRequestCountDefault =3;
  16 +
  17 +static NSString *const OBSURLReservedCharacters =@"-_.~!*'();:=@&=+$,/?#[]%";
  18 +static NSString *const OBSURLAllowedSpecialCharacters =@"-_.";
  19 +
  20 +static NSString *const OBSAbstractClassPrefix =@"OBSAbstract";
  21 +#pragma mark - Errors messages;
  22 +static NSString *const OBSClientErrorDomain =@"com.obs.clientError";
  23 +static NSString *const OBSServerErrorDomain =@"com.obs.serverError";
  24 +static NSString *const OBSErrorMessageTOKEN =@"ErrorMessage";
  25 +static NSString *const OBSClientErrorHTTPRequestIDKey =@"RequestID";
  26 +static NSString *const OBSClientErrorHTTPCodeKey =@"HTTPErrorCode";
  27 +static NSString *const OBSClientErrorHTTPBodyKey =@"HTTPErrorBody";
  28 +static NSString *const OBSClientErrorInvalidParameter =@"InvalidParameter";
  29 +
  30 +static char *const OBSProcessorsQueueName ="com.obs.sdk.processors";
  31 +static NSString *const OBSMaxConcurrentCommandRequestCountKey =@"maxConcurrentCommandRequestCount";
  32 +static NSString *const OBSMaxConcurrentUploadRequestCountKey =@"maxConcurrentUploadRequestCount";
  33 +static NSString *const OBSMaxConcurrentDownloadRequestCountKey =@"maxConcurrentDownloadRequestCount";
  34 +
  35 +static NSString *const OBSUploadBackgroundIdentifierDefault =@"com.obs.sdk.upload";
  36 +static NSString *const OBSDownloadBackgroundIdentifierDefault =@"com.obs.sdk.download";
  37 +
  38 + //networking request definition dict keys;
  39 + //common fields;
  40 +static NSString *const OBSRequestTypeKey =@"requestType";
  41 +static NSString *const OBSRequestIDKey =@"requestID";
  42 +static NSString *const OBSRequestHTTPMethodKey =@"requestMethod";
  43 +static NSString *const OBSRequestResourceStringKey =@"requestResourceString";
  44 +static NSString *const OBSRequestResourceParametersKey =@"requestResourceParameters";
  45 +static NSString *const OBSRequestQueryParametersKey =@"requestQueryParameters";
  46 +static NSString *const OBSRequestHeaderParametersKey =@"requestHeadersParameters";
  47 +
  48 +static NSString *const OBSRequestBodyParameterKey =@"requestBodyParameters";
  49 +static NSString *const OBSRequestAddonRequestPostProcessorsKey =@"addonRequestPostProcessorsParameters";
  50 +static NSString *const OBSRequestAddonResponsePreProcessorsKey =@"addonResponsePreProcessorsParameters";
  51 +static NSString *const OBSRequestAuthRequiredKey =@"authenticationRequired";
  52 + //upload data fields;
  53 +static NSString *const OBSRequestUploadDataKey =@"uploadData";
  54 +static NSString *const OBSRequestUploadProgressBlockKey =@"uploadProgressBlock";
  55 + //download data fields;
  56 +static NSString *const OBSRequestOnReceiveDataBlockKey =@"onReceiveDataBlock";
  57 +static NSString *const OBSRequestDownloadProgressBlockKey =@"downloadProgressBlock";
  58 + //upload and download fields;
  59 +static NSString *const OBSRequestUploadFilePathKey =@"uploadFilePath";
  60 +static NSString *const OBSRequestDownloadFilePathKey =@"downloadFilePath";
  61 +static NSString *const OBSRequestBackgroundKey =@"background";
  62 + // headesr key;
  63 +static NSString *const OBSHeadersUAKey =@"User-Agent";
  64 +
  65 +static NSString *const OBSHeadersHostKey =@"Host";
  66 +static NSString *const OBSHeadersContentTypeKey =@"Content-Type";
  67 +static NSString *const OBSHeadersContentLengthKey =@"Content-Length";
  68 +static NSString *const OBSHeadersAuthorizationKey =@"Authorization";
  69 +static NSString *const OBSDefaultContentType =@"binary/octet-stream";
  70 + //date format;
  71 +static NSString *const OBSDateShortFormat =@"yyyyMMdd";
  72 +static NSString *const OBSDateRFC1123Format =@"E, dd MMM yyyy HH:mm:ss z";
  73 +static NSString *const OBSDateISO8601Format1 =@"yyyy-MM-dd'T'HH:mm:ss'Z'";
  74 +static NSString *const OBSDateISO8601Format2 =@"yyyyMMdd'T'HHmmss'Z'" ;
  75 +static NSString *const OBSDateISO8601Format3 =@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
  76 + //output keys and download temp file extention;
  77 +static NSString *const OBSOutputCodeKey =@"statusCode";
  78 +static NSString *const OBSOutputHeadersKey =@"headers";
  79 +static NSString *const OBSOutputBodyKey =@"body";
  80 +
  81 +
  82 +static NSString *const OBSXMLDefaultNS =@" xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"";
  83 +static NSString *const OBSXMLDefaultNS_OBS =@" xmlns=\"http://myhwclouds.com/doc/2015-06-30/\"";
  84 +
  85 +static NSString *const OBSXMLDictionaryNodeOrderKey =@"__order";
  86 +
  87 +#pragma mark -Enum
  88 +/**
  89 + * OBS鉴权版本枚举
  90 + */
  91 +
  92 +typedef NS_ENUM(NSInteger, OBSContentType) {
  93 + /**
  94 + * 默认类型
  95 + */
  96 + OBSContentTypeNULL0,
  97 + /**
  98 + * mp4
  99 + */
  100 + OBSContentTypeMP4,
  101 + /**
  102 + * 二进制流
  103 + */
  104 + OBSContentTypeBinary,
  105 + /**
  106 + * JPEG
  107 + */
  108 + OBSContentTypeJPEG,
  109 + /**
  110 + * PNG
  111 + */
  112 + OBSContentTypePNG,
  113 + /**
  114 + * HTML
  115 + */
  116 + OBSContentTypeHTML,
  117 + /**
  118 + * GIF
  119 + */
  120 + OBSContentTypeGIF,
  121 + /**
  122 + * PDF
  123 + */
  124 + OBSContentTypePDF,
  125 + /**
  126 + * MP3
  127 + */
  128 + OBSContentTypeMP3,
  129 + /**
  130 + * WAV
  131 + */
  132 + OBSContentTypeWAV,
  133 + /**
  134 + * MOV
  135 + */
  136 + OBSContentTypeMOV,
  137 + /**
  138 + * m3u8
  139 + */
  140 + OBSContentTypeM3U8,
  141 +};
  142 +
  143 +typedef NS_ENUM(NSInteger, OBSAuthVersion) {
  144 + /**
  145 + * 默认鉴权
  146 + */
  147 + OBSAuthVersionNULL0,
  148 + /**
  149 + * V2鉴权
  150 + */
  151 + OBSAuthVersionV2,
  152 + /**
  153 + * V4鉴权
  154 + */
  155 + OBSAuthVersionV4,
  156 +};
  157 +
  158 +/**
  159 + * OBS协议种类
  160 + */
  161 +typedef NS_ENUM(NSInteger, OBSProtocolType) {
  162 +
  163 + /**
  164 + * 旧版本协议
  165 + */
  166 + OBSProtocolTypeOld,
  167 + /**
  168 + * 自研协议
  169 + */
  170 + OBSProtocolTypeOBS,
  171 +};
  172 +
  173 +/**
  174 + * OBS错误码枚举
  175 + */
  176 +typedef NS_ENUM(NSInteger, OBSErrorCode) {
  177 + /**
  178 + * 默认
  179 + */
  180 + OBSErrorCodeNoErrorCode0,
  181 + /**
  182 + * 服务器错误
  183 + */
  184 + OBSErrorCodeServerErrorStatus,
  185 + /**
  186 + * 客户端错误
  187 + */
  188 + OBSErrorCodeClientErrorStatus,
  189 +};
  190 +
  191 +/**
  192 + * OBS客户端错误码枚举
  193 + */
  194 +typedef NS_ENUM(NSInteger, OBSClientErrorCODE) {
  195 + /**
  196 + * 默认
  197 + */
  198 + OBSRequestNoErrorCode0,
  199 + /**
  200 + * 定义未找到
  201 + */
  202 + OBSClientErrorRequestDefinitionNotFoundCode,
  203 + /**
  204 + * 响应错误码
  205 + */
  206 + OBSClientErrorHTTPResponseCodeError,
  207 + /**
  208 + * 签名错误
  209 + */
  210 + OBSClientErrorCodeSignFailed,
  211 +// OBSClientErrorCodeNetworkingFailWithResponseCode0,
  212 +// OBSClientErrorCodeFileCantWrite,
  213 +// OBSClientErrorCodeInvalidArgument,
  214 +// OBSClientErrorCodeNilUploadid,
  215 +// OBSClientErrorCodeTaskCancelled,
  216 +// OBSClientErrorCodeNetworkError,
  217 +// OBSClientErrorCodeCannotResumeUpload,
  218 +// OBSClientErrorCodeExcpetionCatched,
  219 +// OBSClientErrorCodeNotKnown
  220 +};
  221 +
  222 +/**
  223 + * OBS请求代理类型
  224 + */
  225 +typedef NS_ENUM(NSInteger, OBSHTTPProxyType) {
  226 + /**
  227 + * 默认
  228 + */
  229 + OBSHTTPRroxyTypeNull0,
  230 + /**
  231 + * HTTP
  232 + */
  233 + OBSHTTPRroxyTypeHTTP,
  234 + /**
  235 + * HTTPS
  236 + */
  237 + OBSHTTPRroxyTypeHTTPS,
  238 + /**
  239 + * HTTP & HTTPS
  240 + */
  241 + OBSHTTPRroxyTypeHTTPAndHTTPS,
  242 +};
  243 +
  244 +/**
  245 + * 请求类型
  246 + */
  247 +typedef NS_ENUM(NSInteger, OBSRequestType){
  248 + /**
  249 + * 默认
  250 + */
  251 + OBSRequestTypeNull0,
  252 + /**
  253 + * 命令
  254 + */
  255 + OBSRequestTypeCommandRequest,
  256 + /**
  257 + * 上传数据
  258 + */
  259 + OBSRequestTypeUploadDataRequest,
  260 + /**
  261 + * 上传文件
  262 + */
  263 + OBSRequestTypeUploadFileRequest,
  264 + /**
  265 + * 下载数据
  266 + */
  267 + OBSRequestTypeDownloadDataRequest,
  268 + /**
  269 + * 下载文件
  270 + */
  271 + OBSRequestTypeDownloadFileRequest,
  272 +};
  273 +
  274 +/**
  275 + * 请求体内容
  276 + */
  277 +typedef NS_ENUM(NSInteger, OBSBodyType){
  278 + /**
  279 + * 默认
  280 + */
  281 + OBSBodyTypeNull0,
  282 + /**
  283 + * JSON
  284 + */
  285 + OBSBodyTypeJSON,
  286 + /**
  287 + * XML
  288 + */
  289 + OBSBodyTypeXML,
  290 + /**
  291 + * 字符串
  292 + */
  293 + OBSBodyTypeStringData,
  294 +};
  295 +/**
  296 + * 请求方法类型枚举
  297 + */
  298 +typedef NS_ENUM(NSInteger, OBSHTTPMethod){
  299 + OBSHTTPMethodNull0,
  300 + OBSHTTPMethodGET,
  301 + OBSHTTPMethodHEAD,
  302 + OBSHTTPMethodPUT,
  303 + OBSHTTPMethodPOST,
  304 + OBSHTTPMethodTRACE,
  305 + OBSHTTPMethodOPTIONS,
  306 + OBSHTTPMethodDELETE,
  307 + OBSHTTPMethodLOCK,
  308 + OBSHTTPMethodMKCOL,
  309 + OBSHTTPMethodMOVE,
  310 +};
  311 +
  312 +
  313 +#pragma mark - ignore warn
  314 +#define SuppressPerformSelectorLeakWarning(code) \
  315 + _Pragma("clang diagnostic push") \
  316 + _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
  317 + code\
  318 + _Pragma("clang diagnostic pop") \
  319 +
  320 +#define SuppressMethodDefinitionNotFoundWarning(code) \
  321 + _Pragma("clang diagnostic push") \
  322 + _Pragma("clang diagnostic ignored \"-Wincomplete-implementation\"") \
  323 + code\
  324 + _Pragma("clang diagnostic pop") \
  325 +
  326 +#define MakeDispatchOnceDictBEGIN \
  327 + static NSDictionary *dict; \
  328 + static dispatch_once_t onceToken; \
  329 + dispatch_once(&onceToken, ^{
  330 +
  331 +#define MakeDispatchOnceDictEND\
  332 + }); \
  333 +
  334 +
  335 +#define MakeDispatchOnceArrayBEGIN \
  336 + static NSArray *array; \
  337 + static dispatch_once_t onceToken; \
  338 + dispatch_once(&onceToken, ^{
  339 +
  340 +#define MakeDispatchOnceArrayEND\
  341 + }); \
  342 +
  343 +#define MakeDispatchOnceTransformerBEGIN \
  344 +static NSValueTransformer *transformer; \
  345 +static dispatch_once_t onceToken; \
  346 +dispatch_once(&onceToken, ^{
  347 +
  348 +#define MakeDispatchOnceTransformerEND \
  349 +}); \
  350 +
  351 +
  352 +#define metamacro_concat(A,B) A ## B
  353 +#define weakify(VAR) \
  354 +autoreleasepool {} \
  355 +__weak __typeof__(VAR) weak##VAR = VAR
  356 + // __weak __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR)
  357 +
  358 +#define strongify(VAR) \
  359 +autoreleasepool {} \
  360 +_Pragma("clang diagnostic push") \
  361 +_Pragma("clang diagnostic ignored \"-Wshadow\"") \
  362 +__strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_)\
  363 +_Pragma("clang diagnostic pop") \
  364 +
  365 +#pragma mark - Progress block
  366 +typedef void (^OBSNetworkingUploadProgressBlock) (int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
  367 +typedef void (^OBSNetworkingDownloadProgressBlock) (int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
  368 +typedef void (^OBSNetworkingOnReceiveDataBlock)(NSData *data);
  369 +#endif /* OBSConstDefinition_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSBaseModel_h
  14 +#define OBSBaseModel_h
  15 +
  16 +#import "OBSBaseCategory.h"
  17 +#import "OBSBaseConstDefinition.h"
  18 +#import "OBSMantle.h"
  19 +#import "OBSXMLDictionary.h"
  20 +
  21 +@class OBSRequestConverter;
  22 +@protocol OBSNetworkingRequestPostProcessor;
  23 +
  24 +//#pragma mark - OBSSafeMutableDictionary
  25 +//@interface OBSSafeMutableDictionary<KeyType, ObjectType>:NSMutableDictionary
  26 +//- (id) objectForKey:(id)aKey;
  27 +//- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>) aKey;
  28 +//- (void)removeObjectForKey:(KeyType)aKey;
  29 +//@end
  30 +//#pragma mark - OBSOrderedMutableDictionary
  31 +//@interface OBSOrderedMutableDictionary<KeyType, ObjectType>:NSMutableDictionary
  32 +//- (id) objectForKey:(id)aKey;
  33 +//- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>) aKey;
  34 +//- (void)removeObjectForKey:(KeyType)aKey;
  35 +//- (NSEnumerator*)keyEnumerator;
  36 +//- (NSUInteger)count;
  37 +//@end
  38 +
  39 +#pragma mark - OBSWeakMutableArray
  40 +@interface OBSWeakMutableArray<ObjectType>:NSMutableArray
  41 +-(instancetype)initWithCapacity:(NSUInteger)numItems;
  42 +-(NSUInteger)count;
  43 +-(void)addObject:(id)anObject;
  44 +-(void)removeObject:(id)anObject;
  45 +-(void)removeObjectAtIndex:(NSUInteger)index;
  46 +-(id)objectAtIndex:(NSUInteger)index;
  47 +@end
  48 +
  49 +@protocol OBSGetBodyTypeProtocol<NSObject>
  50 ++(OBSBodyType)GetBodyType;
  51 +@end
  52 +
  53 +#pragma mark configuration
  54 +@interface OBSHTTPProxyConfiguration : NSObject
  55 +@property (nonatomic, assign) OBSHTTPProxyType proxyType;
  56 +@property (nonatomic, strong, nonnull) NSString *proxyHost;
  57 +@property (nonatomic, strong, nonnull) NSNumber *proxyPort;
  58 +@property (nonatomic, strong, nonnull) NSString *username;
  59 +@property (nonatomic, strong, nonnull) NSString *password;
  60 +
  61 +/**
  62 + 端口代理初始化
  63 +
  64 + @param proxyType 请求类型(OBSHTTPRroxyTypeNull0 OBSHTTPRroxyTypeHTTP OBSHTTPRroxyTypeHTTPS OBSHTTPRroxyTypeHTTPAndHTTPS)
  65 + @param host host
  66 + @param port port
  67 + @return 代理对象
  68 + */
  69 +-(instancetype)initWithType:(OBSHTTPProxyType) proxyType proxyHost:(NSString*) host proxyPort:(NSUInteger) port;
  70 +-(NSDictionary*) getProxyDict;
  71 +@end
  72 +
  73 +@interface OBSBaseConfiguration : NSObject
  74 +@property (nonatomic, strong, readonly, nonnull) NSURL *url;
  75 +@property (nonatomic, strong) NSString *lastUploadPath;
  76 +@property (nonatomic, strong) NSData *uploadAllData;
  77 +@property (nonatomic, assign) BOOL trustUnsafeCert;
  78 +@property (nonatomic, assign) uint32_t maxConcurrentCommandRequestCount;
  79 +@property (nonatomic, assign) uint32_t maxConcurrentUploadRequestCount;
  80 +@property (nonatomic, assign) uint32_t maxConcurrentDownloadRequestCount;
  81 +
  82 +@property (nonatomic, strong) NSURLSessionConfiguration * commandSessionConfiguration;
  83 +@property (nonatomic, strong) NSURLSessionConfiguration * uploadSessionConfiguration;
  84 +@property (nonatomic, strong) NSURLSessionConfiguration * downloadSessionConfiguration;
  85 +@property (nonatomic, strong) NSURLSessionConfiguration * backgroundUploadSessionConfiguration;
  86 +@property (nonatomic, strong) NSURLSessionConfiguration * backgroundDownloadSessionConfiguration;
  87 +
  88 +@property (nonatomic, strong) OBSHTTPProxyConfiguration * proxyConfig;
  89 +@property (nonatomic, strong) NSMutableArray<id<OBSNetworkingRequestPostProcessor>> * customProcessors;
  90 +@property (nonatomic, assign) BOOL enableURLEncoding;
  91 +-(instancetype) initWithURL:(NSURL*) url;
  92 +-(NSArray*)getDefaultPostProcessors;
  93 +@end
  94 +
  95 +#pragma mark MTLJSONAdaptor and XML Parser
  96 +
  97 +@protocol OBSMTLDictionaryItemOrderProtocol <NSObject>
  98 +@required
  99 ++(NSArray*)DictionaryOrderList;
  100 +@end
  101 +
  102 +@interface OBSMTLJSONAdapterCustomized: OBSMTLJSONAdapter
  103 +
  104 +-(void)setModelClass:(Class)clazz;
  105 +-(Class)modelClass;
  106 +
  107 +-(void)setJSONKeyPathsByPropertyKey:(NSDictionary*)dict;
  108 +-(NSDictionary*)JSONKeyPathsByPropertyKey;
  109 +
  110 +-(void)setValueTransformersByPropertyKey:(NSDictionary*)dict;
  111 +-(NSDictionary*)valueTransformersByPropertyKey;
  112 +
  113 +-(void)setJSONAdaptersByModelClass:(NSMapTable*)dict;
  114 +-(NSMapTable*)JSONAdaptersByModelClass;
  115 +
  116 +- (OBSMTLJSONAdapter *)JSONAdapterForModelClass:(Class)modelClass error:(NSError **)error;
  117 +@end
  118 +
  119 +@interface OBSXMLDictionaryParserWithFormat: OBSXMLDictionaryParser
  120 ++ (NSString *)OBSXMLStringForNode:(id)node withNodeName:(NSString *)nodeName ident:(NSInteger) ident;
  121 +- (void)endText;
  122 +-(void)setRoot:(NSMutableDictionary<NSString *, id>*) root;
  123 +-(NSMutableDictionary<NSString *, id>*)root;
  124 +-(void)setStack:(NSMutableArray*) stack;
  125 +-(NSMutableArray*)stack;
  126 +@end
  127 +
  128 +#pragma mark - Base Model
  129 +
  130 +
  131 +@protocol OBSRequestConvert
  132 +@required
  133 +-(OBSBaseNetworkingRequest*)convertToNetworkingRequest:(OBSBaseConfiguration*) configuration error:(NSError**) error;
  134 +@end
  135 +
  136 +@interface OBSAbstractModel : OBSMTLModel<OBSMTLJSONSerializing>
  137 +@end
  138 +
  139 +@interface OBSBaseEntity: OBSAbstractModel
  140 +@end
  141 +
  142 +@interface OBSResponseHeaderEntity: OBSBaseEntity
  143 +@end
  144 +
  145 +@interface OBSResponseURLEntity: OBSBaseEntity
  146 +@end
  147 +
  148 +@interface OBSResponseBodyEntity: OBSBaseEntity
  149 +@end
  150 +
  151 +#pragma mark - Base Requests
  152 +
  153 +
  154 +/**
  155 + OBS网络请求基类
  156 + */
  157 +@interface OBSBaseRequest: OBSAbstractModel<OBSRequestConvert>
  158 +
  159 +/**
  160 + 请求ID
  161 + */
  162 +@property (nonatomic, strong, nonnull) NSString *requestID;
  163 +
  164 +/**
  165 + 是否取消
  166 + */
  167 +@property (readonly, nonatomic, assign) BOOL isCancelled;
  168 +
  169 +/**
  170 + 请求类型
  171 + */
  172 +@property (nonatomic, assign) OBSProtocolType protocolType;
  173 +
  174 +
  175 +/**
  176 + 取消请求
  177 + */
  178 +-(void)cancel;
  179 +
  180 +/**
  181 + 判断是否是一个合法的请求
  182 +
  183 + @param error 抛出的错误
  184 + @return 返回是否为合法请求
  185 + */
  186 +-(BOOL)validateRequest:(NSError**)error;
  187 +@end
  188 +
  189 +#pragma mark - Base Response
  190 +
  191 +/**
  192 + OBS网络响应基类
  193 + */
  194 +@interface OBSBaseResponse: OBSAbstractModel<OBSGetBodyTypeProtocol>
  195 +
  196 +/**
  197 + 响应状态码
  198 + */
  199 +@property (nonatomic, strong, nonnull) NSString *statusCode;
  200 +
  201 +/**
  202 + 响应头部
  203 + */
  204 +@property (nonatomic, strong, nullable) NSDictionary *headers;
  205 +
  206 +/**
  207 + 请求ID
  208 + */
  209 +@property (nonatomic, strong, nullable) NSString *requestID;
  210 +@end
  211 +
  212 +
  213 +#endif /* OBSBaseModel_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSBaseNetworking_h
  14 +#define OBSBaseNetworking_h
  15 +#import "OBSBaseConstDefinition.h"
  16 +#import "OBSBaseModel.h"
  17 +@class OBSBFTaskCompletionSource;
  18 +@class OBSBFTask;
  19 +@class OBSBaseRequest;
  20 +@class OBSEndpoint;
  21 +@class OBSBaseNetworkingRequest;
  22 +@class OBSBaseConfiguration;
  23 +@class OBSAbstractCredentailProvider;
  24 +@protocol NSURLSessionDelegate;
  25 +@protocol NSURLSessionDataDelegate;
  26 +@protocol OBSServiceCredentialProvider;
  27 +
  28 +#pragma mark - Networking classes
  29 +
  30 +@protocol OBSNetworkingRequestPostProcessor<NSObject>
  31 +@required
  32 ++(void)processRequest:(OBSBaseNetworkingRequest*) request configuration:(__kindof OBSBaseConfiguration *const) configuration error:(NSError**) error;
  33 +@end
  34 +
  35 +@protocol OBSNetworkingResponsePreProcessor<NSObject>
  36 +@required
  37 ++(void)processResponse:(NSMutableDictionary*) responseDict configuration:(__kindof OBSBaseConfiguration *const) configuration error:(NSError**) error;
  38 +@end
  39 +
  40 +@interface OBSRequestURLStringPostProcessor: NSObject<OBSNetworkingRequestPostProcessor>
  41 +@end
  42 +
  43 +@interface OBSResouceParameterPostProcessor: NSObject<OBSNetworkingRequestPostProcessor>
  44 +@end
  45 +
  46 +@interface OBSHeaderUAPostProcessor: NSObject <OBSNetworkingRequestPostProcessor>
  47 +@end
  48 +
  49 +@interface OBSHeaderContentLengthPostProcessor: NSObject <OBSNetworkingRequestPostProcessor>
  50 +@end
  51 +
  52 +@interface OBSHeaderContentTypePostProcessor: NSObject <OBSNetworkingRequestPostProcessor>
  53 +@end
  54 +
  55 +@interface OBSHeaderHostPostProcessor: NSObject <OBSNetworkingRequestPostProcessor>
  56 +@end
  57 +
  58 +@interface OBSURLEncodingPostProcessor: NSObject <OBSNetworkingRequestPostProcessor>
  59 +@end
  60 +
  61 +@protocol OBSNetworkingRequestJSONDataProtocol<NSObject>
  62 +@required
  63 ++(NSDictionary*) AdditionalJSONData;
  64 ++(NSDictionary*) getAdditionalJSONDataIncludeParents;
  65 +@end
  66 +
  67 +#pragma mark - Networking Manager
  68 +@interface OBSNetworkingManager :NSObject<NSURLSessionDelegate, NSURLSessionTaskDelegate,NSURLSessionDataDelegate,NSURLSessionDownloadDelegate>
  69 +@property (nonatomic, readonly, nonnull) OBSBaseConfiguration *configuration;
  70 +-(instancetype) initWithConfiguration:(OBSBaseConfiguration*) configuration;
  71 +-(OBSBFTask*) sendRequest: (OBSBaseNetworkingRequest*) request;
  72 +-(void)releaseSessions;
  73 +@end
  74 +
  75 +#pragma mark - networking base requests
  76 +
  77 +@protocol OBSNetworkingGetResponseClazz
  78 +@optional
  79 +-(Class)getResponseClazz;
  80 +@end
  81 +
  82 +@interface OBSBaseNetworkingRequest : OBSAbstractModel<OBSNetworkingGetResponseClazz>
  83 + //config
  84 +@property (nonatomic, assign) OBSRequestType requestType;
  85 +@property (nonatomic, copy, nonnull) NSString *requestID;
  86 +@property (nonatomic, assign) OBSHTTPMethod requestMethod;
  87 +@property (nonatomic, strong, nullable) NSString *requestBaseURLString;
  88 +@property (nonatomic, strong, nullable) NSString *requestResourceString;
  89 +@property (nonatomic, strong, nullable) NSString *requestOriginalResourceString;
  90 +@property (nonatomic, strong, nullable) NSMutableDictionary *requestResourceParameters;
  91 +@property (nonatomic, strong, nullable) NSMutableDictionary *requestQueryParameters;
  92 +@property (nonatomic, strong, nullable) NSMutableDictionary *requestHeadersParameters;
  93 +@property (nonatomic, strong, nullable) NSMutableArray *addonRequestPostProcessorsParameters;
  94 +@property (nonatomic, strong, nullable) NSMutableArray *addonResponsePreProcessorsParameters;
  95 +
  96 + //processing attribute
  97 +@property (nonatomic, strong, nullable) NSData *requestBodyData;
  98 +@property (nonatomic, strong, nullable) NSMutableData *responseData;
  99 +@property (nonatomic, strong) NSMutableArray<Class<OBSNetworkingRequestPostProcessor>> *postProcessors;
  100 +@property (nonatomic, strong) NSMutableArray<Class<OBSNetworkingResponsePreProcessor>> *preProcessors;
  101 +@property (nonatomic, strong, nullable) OBSWeakMutableArray<NSURLSessionTask*> *sessionTaskList;
  102 +@property (nonatomic, strong) OBSBFTaskCompletionSource *completionSource;
  103 +@property (nonatomic, weak, nullable) OBSBaseRequest *obsRequest;
  104 +@property (readonly, nonatomic, assign) BOOL isCancelled;
  105 +-(void)cancel;
  106 +@end
  107 +
  108 +@interface OBSNetworkingCommandRequest : OBSBaseNetworkingRequest<OBSNetworkingRequestJSONDataProtocol, OBSGetBodyTypeProtocol>
  109 +@property (nonatomic, strong, nullable) NSMutableDictionary *requestBodyParameters;
  110 +@end
  111 +
  112 +@interface OBSNetworkingUploadDataRequest : OBSBaseNetworkingRequest<OBSNetworkingRequestJSONDataProtocol>
  113 +@property (nonatomic, strong, nonnull) NSData *uploadData;
  114 +@property (nonatomic, copy, nullable) OBSNetworkingUploadProgressBlock uploadProgressBlock;
  115 +@end
  116 +
  117 +@interface OBSNetworkingUploadFileRequest : OBSBaseNetworkingRequest<OBSNetworkingRequestJSONDataProtocol>
  118 +@property (nonatomic, strong, nonnull) NSString *uploadFilePath;
  119 +@property (nonatomic, assign) BOOL background;
  120 +@property (nonatomic, copy, nullable) OBSNetworkingUploadProgressBlock uploadProgressBlock;
  121 +@end
  122 +
  123 +@interface OBSNetworkingDownloadDataRequest : OBSBaseNetworkingRequest<OBSNetworkingRequestJSONDataProtocol>
  124 +@property (nonatomic, copy, nonnull) OBSNetworkingOnReceiveDataBlock onReceiveDataBlock;
  125 +@property (nonatomic, copy) OBSNetworkingDownloadProgressBlock downloadProgressBlock;
  126 +@property (nonatomic, assign) int64_t bytes_totalGot;
  127 +
  128 +@end
  129 +
  130 +@interface OBSNetworkingDownloadFileRequest : OBSBaseNetworkingRequest<OBSNetworkingRequestJSONDataProtocol>
  131 +@property (nonatomic, assign) BOOL background;
  132 +@property (nonatomic, strong, nonnull) NSString * downloadFilePath;
  133 +@property (nonatomic, copy) OBSNetworkingDownloadProgressBlock downloadProgressBlock;
  134 +@end
  135 +
  136 +
  137 +
  138 +
  139 +
  140 +#endif /* OBSBaseNetworking_h */
  1 +/*
  2 + * Copyright (c) 2014, Facebook, Inc.
  3 + * All rights reserved.
  4 + *
  5 + * This source code is licensed under the BSD-style license found in the
  6 + * LICENSE file in the root directory of this source tree. An additional grant
  7 + * of patent rights can be found in the PATENTS file in the same directory.
  8 + *
  9 + */
  10 +
  11 +#import "OBSBFCancellationToken.h"
  12 +#import "OBSBFCancellationTokenRegistration.h"
  13 +#import "OBSBFCancellationTokenSource.h"
  14 +#import "OBSBFExecutor.h"
  15 +#import "OBSBFGeneric.h"
  16 +#import "OBSBFTask.h"
  17 +#import "OBSBFTaskCompletionSource.h"
  18 +
  19 +#if __has_include("OBSBFAppLink.h") && TARGET_OS_IPHONE && !TARGET_OS_WATCH && !TARGET_OS_TV
  20 +#import "OBSBFAppLink.h"
  21 +#import "OBSBFAppLinkNavigation.h"
  22 +#import "OBSBFAppLinkResolving.h"
  23 +#import "OBSBFAppLinkReturnToRefererController.h"
  24 +#import "OBSBFAppLinkReturnToRefererView.h"
  25 +#import "OBSBFAppLinkTarget.h"
  26 +#import "OBSBFMeasurementEvent.h"
  27 +#import "OBSBFURL.h"
  28 +#import "OBSBFWebViewAppLinkResolver.h"
  29 +#endif
  30 +
  31 +
  32 +NS_ASSUME_NONNULL_BEGIN
  33 +
  34 +/**
  35 + A string containing the version of the Bolts Framework used by the current application.
  36 + */
  37 +FOUNDATION_EXPORT NSString *const OBSBoltsFrameworkVersionString;
  38 +
  39 +NS_ASSUME_NONNULL_END
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +#import <Foundation/Foundation.h>
  17 +#import <QuartzCore/QuartzCore.h>
  18 +
  19 +/**
  20 + *This class represents an NSColor replacement for CLI projects that don't link with AppKit
  21 + **/
  22 +@interface OBSCLIColor : NSObject
  23 +
  24 +/**
  25 + * Convenience method for creating a `OBSCLIColor` instance from RGBA params
  26 + *
  27 + * @param red red channel, between 0 and 1
  28 + * @param green green channel, between 0 and 1
  29 + * @param blue blue channel, between 0 and 1
  30 + * @param alpha alpha channel, between 0 and 1
  31 + */
  32 ++ (OBSCLIColor *)colorWithCalibratedRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
  33 +
  34 +/**
  35 + * Get the RGBA components from a `OBSCLIColor`
  36 + *
  37 + * @param red red channel, between 0 and 1
  38 + * @param green green channel, between 0 and 1
  39 + * @param blue blue channel, between 0 and 1
  40 + * @param alpha alpha channel, between 0 and 1
  41 + */
  42 +- (void)getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha NS_SWIFT_NAME(get(red:green:blue:alpha:));
  43 +
  44 +@end
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSClient_h
  14 +#define OBSClient_h
  15 +#import "OBSLogging.h"
  16 +
  17 +@class OBSBaseRequest;
  18 +@class OBSBFTask;
  19 +@class OBSBaseConfiguration;
  20 +@class OBSRequestConverter;
  21 +
  22 +
  23 +@interface OBSClient:NSObject
  24 +@property (nonatomic, strong, nonnull) OBSBaseConfiguration *configuration;
  25 +
  26 +
  27 +#pragma mark - init
  28 +
  29 +/**
  30 + client初始化
  31 +
  32 + @param configuration 配置参数
  33 + @return client对象
  34 + */
  35 +-(instancetype) initWithConfiguration: (__kindof OBSBaseConfiguration*) configuration;
  36 +
  37 +#pragma mark - set logger
  38 +/* *Set log level, default level is info.
  39 + log levels are:
  40 + OBSDDLogLevelOff
  41 + OBSDDLogLevelError
  42 + OBSDDLogLevelWarning
  43 + OBSDDLogLevelInfo
  44 + OBSDDLogLevelDebug
  45 + OBSDDLogLevelVerbose
  46 +*/
  47 +
  48 +/**
  49 + 设置日志等级
  50 +
  51 + @param logLevel 日志种类
  52 + OBSDDLogLevelOff
  53 + OBSDDLogLevelError
  54 + OBSDDLogLevelWarning
  55 + OBSDDLogLevelInfo
  56 + OBSDDLogLevelDebug
  57 + OBSDDLogLevelVerbose
  58 + */
  59 +-(void) setLogLevel:(OBSDDLogLevel) logLevel;
  60 +
  61 +/**
  62 + *Add custom logger, such as file logger
  63 + */
  64 +
  65 +
  66 +/**
  67 + 添加日志logger
  68 +
  69 + @param logger 日志logger类型
  70 + */
  71 +-(void) addLogger: (id <OBSDDLogger>) logger;
  72 +
  73 +
  74 +/**
  75 + *Set Apple System Logger on, after turnning on this log could be seeing in the system's console app.
  76 + */
  77 +
  78 +/**
  79 + 开启窗口日志打印
  80 + */
  81 +-(void) setASLogOn;
  82 +
  83 +- (OBSBFTask*)invokeRequest:(OBSBaseRequest *) request;
  84 +-(BOOL)getOBSProtocol:(OBSBaseRequest *)request;
  85 +@end
  86 +
  87 +#endif /* OBSClient_h */
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +/**
  17 + *Welcome to CocoaLumberjack!
  18 + *
  19 + *The project page has a wealth of documentation if you have any questions.
  20 + *https://github.com/CocoaLumberjack/CocoaLumberjack
  21 + *
  22 + *If you're new to the project you may wish to read "Getting Started" at:
  23 + *Documentation/GettingStarted.md
  24 + *
  25 + *Otherwise, here is a quick refresher.
  26 + *There are three steps to using the macros:
  27 + *
  28 + *Step 1:
  29 + *Import the header in your implementation or prefix file:
  30 + *
  31 + *#import <CocoaLumberjack/CocoaLumberjack.h>
  32 + *
  33 + *Step 2:
  34 + *Define your logging level in your implementation file:
  35 + *
  36 + // Log levels: off, error, warn, info, verbose
  37 + *static const OBSDDLogLevel obsddLogLevel = OBSDDLogLevelVerbose;
  38 + *
  39 + *Step 2 [3rd party frameworks]:
  40 + *
  41 + *Define your OBSLOG_LEVEL_DEF to a different variable/function than obsddLogLevel:
  42 + *
  43 + // #undef OBSLOG_LEVEL_DEF // Undefine first only if needed
  44 + *#define OBSLOG_LEVEL_DEF myLibLogLevel
  45 + *
  46 + *Define your logging level in your implementation file:
  47 + *
  48 + // Log levels: off, error, warn, info, verbose
  49 + *static const OBSDDLogLevel myLibLogLevel = OBSDDLogLevelVerbose;
  50 + *
  51 + *Step 3:
  52 + *Replace your NSLog statements with OBSDDLog statements according to the severity of the message.
  53 + *
  54 + *NSLog(@"Fatal error, no dohickey found!"); -> OBSDDLogError(@"Fatal error, no dohickey found!");
  55 + *
  56 + *OBSDDLog works exactly the same as NSLog.
  57 + *This means you can pass it multiple variables just like NSLog.
  58 + **/
  59 +
  60 +#import <Foundation/Foundation.h>
  61 +
  62 +NS_ASSUME_NONNULL_BEGIN
  63 +
  64 +
  65 +NS_ASSUME_NONNULL_END
  66 +
  67 +FOUNDATION_EXPORT NSString *const OBSCocoaLumberjackFrameworkVersionString;
  68 +// Disable legacy macros
  69 +#ifndef OBSDD_LEGACY_MACROS
  70 + #define OBSDD_LEGACY_MACROS 0
  71 +#endif
  72 +
  73 +// Core
  74 +#import "OBSDDLog.h"
  75 +
  76 +// Main macros
  77 +#import "OBSDDLogMacros.h"
  78 +#import "OBSDDAssertMacros.h"
  79 +
  80 +// Capture ASL
  81 +#import "OBSDDASLLogCapture.h"
  82 +
  83 +// Loggers
  84 +#import "OBSDDTTYLogger.h"
  85 +#import "OBSDDASLLogger.h"
  86 +#import "OBSDDFileLogger.h"
  87 +#import "OBSDDOSLogger.h"
  88 +
  89 +// CLI
  90 +#if __has_include("OBSCLIColor.h") && TARGET_OS_OSX
  91 +#import "OBSCLIColor.h"
  92 +#endif
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSCompleteMultipartUploadModel_h
  14 +#define OBSCompleteMultipartUploadModel_h
  15 +#import "OBSBaseNetworking.h"
  16 +#import "OBSClient.h"
  17 +#import "OBSServiceBaseModel.h"
  18 +#import "OBSServiceConstDefinition.h"
  19 +#import "OBSServiceCommonEntities.h"
  20 +
  21 +@class OBSAbstractEncryption;
  22 + //request
  23 +
  24 +
  25 +#pragma mark - request
  26 +
  27 +/**
  28 + 合并段
  29 + */
  30 +@protocol OBSCompleteMultipartUploadProtocol<NSObject>
  31 +@required
  32 +
  33 +/**
  34 + 桶名
  35 + */
  36 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  37 +
  38 +/**
  39 + 对象名
  40 + */
  41 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  42 +
  43 +/**
  44 + 多段上传任务ID
  45 + */
  46 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  47 +
  48 +/**
  49 + 多段任务列表
  50 + */
  51 +@property (nonatomic, strong, nonnull) NSMutableArray<OBSPart*> *partsList;
  52 +@end
  53 +
  54 +
  55 +/**
  56 + 合并段request
  57 + */
  58 +@interface OBSCompleteMultipartUploadRequest : OBSBaseRequest<OBSCompleteMultipartUploadProtocol>
  59 +
  60 +/**
  61 + 桶名
  62 + */
  63 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  64 +
  65 +/**
  66 + 对象名
  67 + */
  68 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  69 +
  70 +/**
  71 + 多段上传任务ID
  72 + */
  73 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  74 +
  75 +/**
  76 + 多段上传对象列表
  77 + */
  78 +@property (nonatomic, strong, nonnull) NSMutableArray<OBSPart*> *partsList;
  79 +
  80 +/**
  81 + 初始化合并段request
  82 +
  83 + @param bucketName 桶名
  84 + @param objectKey 对象名
  85 + @param uploadID 多段上传任务ID
  86 + @return 合并段request
  87 + */
  88 +-(instancetype)initWithBucketName:(NSString*) bucketName objectKey: (NSString*) objectKey uploadID:(NSString*) uploadID;
  89 +@end
  90 +
  91 +#pragma mark - networking request
  92 +@interface OBSNetworkingCompleteMultipartUploadRequest : OBSServiceNetworkingCommandRequest
  93 +@end
  94 +
  95 + //response
  96 +#pragma mark - response
  97 +
  98 +/**
  99 + 合并段response
  100 + */
  101 +@interface OBSCompleteMultipartUploadResponse: OBSServiceResponse
  102 +
  103 +/**
  104 + 桶名
  105 + */
  106 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  107 +
  108 +/**
  109 + 对象名
  110 + */
  111 +@property (nonatomic, strong, nonnull) NSString *objectKey;
  112 +
  113 +/**
  114 + 区域位置
  115 + */
  116 +@property (nonatomic, strong, nonnull) NSString *location;
  117 +
  118 +/**
  119 + 对象etag
  120 + */
  121 +@property (nonatomic, strong, nonnull) NSString *etag;
  122 +
  123 +/**
  124 + 多版本ID
  125 + */
  126 +@property (nonatomic, strong, nonnull) NSString *versionID;
  127 +
  128 +/**
  129 + 加密方式
  130 + */
  131 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  132 +@end
  133 +
  134 + //client method
  135 +#pragma mark - client method
  136 +@interface OBSClient(completeMultipartUpload)
  137 +
  138 +/**
  139 + 合并段
  140 +
  141 + @param request 合并段request
  142 + @param completionHandler 合并段回调
  143 + @return OBSBFTask
  144 + */
  145 +- (OBSBFTask*)completeMultipartUpload:(__kindof OBSBaseRequest<OBSCompleteMultipartUploadProtocol>*)request
  146 + completionHandler:(void (^)(OBSCompleteMultipartUploadResponse * response, NSError * error))completionHandler;
  147 +@end
  148 +
  149 +#endif /* OBSCompleteMultipartUploadModel_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSCopyObjectModel_h
  14 +#define OBSCopyObjectModel_h
  15 +
  16 +#import "OBSBaseNetworking.h"
  17 +#import "OBSClient.h"
  18 +#import "OBSServiceBaseModel.h"
  19 +#import "OBSServiceConstDefinition.h"
  20 +
  21 +
  22 +@class OBSEncryptionTypeCustomer;
  23 +@class OBSAbstractEncryption;
  24 + //request
  25 +
  26 +#pragma mark - request
  27 +
  28 +/**
  29 + 复制对象
  30 + */
  31 +@protocol OBSCopyObjectProtocol<NSObject>
  32 +@required
  33 +
  34 +/**
  35 + 被复制桶名
  36 + */
  37 +@property (nonatomic, strong, nonnull) NSString *srcBucketName;
  38 +
  39 +/**
  40 + 被复制对象名
  41 + */
  42 +@property (nonatomic, strong, nonnull) NSString *srcObjectKey;
  43 +
  44 +/**
  45 + 被复制对版本ID
  46 + */
  47 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  48 +
  49 +/**
  50 + 复制后的桶名
  51 + */
  52 +@property (nonatomic, strong, nonnull) NSString *dstBucketName;
  53 +
  54 +/**
  55 + 复制后的对象名
  56 + */
  57 +@property (nonatomic, strong, nonnull) NSString *dstObjectKey;
  58 +
  59 +/**
  60 + 复制后对象访问策略
  61 + */
  62 +@property (nonatomic, assign) OBSACLPolicy dstObjectACLPolicy;
  63 +
  64 +/**
  65 + 复制后对象元数据
  66 + */
  67 +@property (nonatomic, assign) OBSMetaDirective dstObjectMetaDirective;
  68 +
  69 +/**
  70 + 如果etag匹配则复制
  71 + */
  72 +@property (nonatomic, strong, nonnull) NSString *cpSrcIfETagMatch;
  73 +
  74 +/**
  75 + 如果etag不匹配则复制
  76 + */
  77 +@property (nonatomic, strong, nonnull) NSString *cpSrcIfETagNoneMatch;
  78 +
  79 +/**
  80 + 只有当源对象在此参数指定的时间之后修改过才进行复制对象操作
  81 + */
  82 +@property (nonatomic, strong, nonnull) NSDate *cpSrcIfModifiedSince;
  83 +
  84 +/**
  85 + 只有当源对象不在此参数指定的时间之后修改过才进行复制对象操作
  86 + */
  87 +@property (nonatomic, strong, nonnull) NSDate *cpSrcIfUnmodifiedSince;
  88 +
  89 +/**
  90 + 复制后对象存储类型
  91 + */
  92 +@property (nonatomic, assign) OBSStorageClass dstObjectStorageClass;
  93 +
  94 +/**
  95 + 复制后对象网站重定向
  96 + */
  97 +@property (nonatomic, strong, nonnull) NSString *dstObjectWebsiteRedirectLocation;
  98 +
  99 +/**
  100 + 复制后对象加密方式
  101 + */
  102 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *dstObjectEncryption;
  103 +
  104 +/**
  105 + 被复制对象加密方式
  106 + */
  107 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *srcObjectEncryption;
  108 +
  109 +/**
  110 + 自定义元数据
  111 + */
  112 +@property (nonatomic, strong, nullable) NSDictionary *metaDataDict;
  113 +@end
  114 +
  115 +
  116 +/**
  117 + 复制对象request
  118 + */
  119 +@interface OBSCopyObjectRequest: OBSBaseRequest<OBSCopyObjectProtocol>
  120 +
  121 +/**
  122 + 被复制桶名
  123 + */
  124 +@property (nonatomic, strong, nonnull) NSString *srcBucketName;
  125 +
  126 +/**
  127 + 被复制的对象key
  128 + */
  129 +@property (nonatomic, strong, nonnull) NSString *srcObjectKey;
  130 +
  131 +/**
  132 + 被复制对象多版本ID
  133 + */
  134 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  135 +
  136 +/**
  137 + 复制后的桶名
  138 + */
  139 +@property (nonatomic, strong, nonnull) NSString *dstBucketName;
  140 +
  141 +/**
  142 + 复制后的对象key
  143 + */
  144 +@property (nonatomic, strong, nonnull) NSString *dstObjectKey;
  145 +
  146 +
  147 +/**
  148 + 复制后对象的ACL
  149 + */
  150 +@property (nonatomic, assign) OBSACLPolicy dstObjectACLPolicy;
  151 +
  152 +/**
  153 + 复制后对象的元数据
  154 + */
  155 +@property (nonatomic, assign) OBSMetaDirective dstObjectMetaDirective;
  156 +
  157 +
  158 +/**
  159 + 只有当源对象的Etag与此参数指定的值相等时才进行复制对象操作
  160 + */
  161 +@property (nonatomic, strong, nonnull) NSString *cpSrcIfETagMatch;
  162 +
  163 +/**
  164 + 只有当源对象的Etag与此参数指定的值不相等时才进行复制对象操作
  165 + */
  166 +@property (nonatomic, strong, nonnull) NSString *cpSrcIfETagNoneMatch;
  167 +
  168 +
  169 +/**
  170 + 只有当源对象在此参数指定的时间之后修改过才进行复制对象操作
  171 + */
  172 +@property (nonatomic, strong, nonnull) NSDate *cpSrcIfModifiedSince;
  173 +
  174 +/**
  175 + 只有当源对象在此参数指定的时间之后没有修改过才进行复制对象操作
  176 + */
  177 +@property (nonatomic, strong, nonnull) NSDate *cpSrcIfUnmodifiedSince;
  178 +
  179 +/**
  180 + 对象存储类型
  181 + */
  182 +@property (nonatomic, assign) OBSStorageClass dstObjectStorageClass;
  183 +
  184 +/**
  185 + 对象重定向
  186 + */
  187 +@property (nonatomic, strong, nonnull) NSString *dstObjectWebsiteRedirectLocation;
  188 +
  189 +/**
  190 + 复制后的对象加密方式
  191 + */
  192 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *dstObjectEncryption;
  193 +
  194 +/**
  195 + 被复制对象加密方式
  196 + */
  197 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *srcObjectEncryption;
  198 +
  199 +/**
  200 + 自定义元数据
  201 + */
  202 +@property (nonatomic, strong, nullable) NSDictionary *metaDataDict;
  203 +
  204 +/**
  205 + 自定义MIME类型
  206 + */
  207 +@property (nonatomic, strong, nonnull) NSString *customContentType;
  208 +
  209 +/**
  210 + 初始化复制对象request
  211 +
  212 + @param srcBucketName 被复制桶名
  213 + @param srcObjectKey 被复制对象的key
  214 + @param dstBucketName 复制后的桶名
  215 + @param dstObjectKey 复制后对象的key
  216 + @return 复制对象request
  217 + */
  218 +-(instancetype)initWithSrcBucketName:(NSString*) srcBucketName
  219 + srcObjectKey:(NSString*) srcObjectKey
  220 + dstBucketName:(NSString*) dstBucketName
  221 + dstObjectKey:(NSString*) dstObjectKey;
  222 +@end
  223 +
  224 +#pragma mark - networking request
  225 +@interface OBSNetworkingCopyObjectRequest : OBSServiceNetworkingCommandRequest
  226 +@end
  227 +
  228 + //response
  229 +#pragma mark - response
  230 +
  231 +/**
  232 + 复制对象response
  233 + */
  234 +@interface OBSCopyObjectResponse: OBSServiceResponse
  235 +
  236 +/**
  237 + 复制后对象etag值
  238 + */
  239 +@property (nonatomic, strong, nonnull) NSString *etag;
  240 +
  241 +/**
  242 + 对象最后修改时间
  243 + */
  244 +@property (nonatomic, strong, nonnull) NSDate *lastModified;
  245 +
  246 +/**
  247 + 如果桶多版本开启,则返回被复制对象的版本号
  248 + */
  249 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  250 +
  251 +/**
  252 + 如果桶多版本开启,则返回新对象的版本号
  253 + */
  254 +@property (nonatomic, strong, nonnull) NSString *dstObjectVersionID;
  255 +
  256 +
  257 +/**
  258 + 新对象加密方式
  259 + */
  260 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  261 +
  262 +@end
  263 +
  264 + //client method
  265 +#pragma mark - client method
  266 +@interface OBSClient(copyObject)
  267 +
  268 +/**
  269 + 复制对象
  270 +
  271 + @param request 复制对象request
  272 + @param completionHandler 复制对象回调
  273 + @return OBSBFTask
  274 + */
  275 +- (OBSBFTask*)copyObject:(__kindof OBSBaseRequest<OBSCopyObjectProtocol>*)request
  276 + completionHandler:(void (^)(OBSCopyObjectResponse * response, NSError * error))completionHandler;
  277 +@end
  278 +#endif /* OBSCopyObjectModel_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSCopyPartModel_h
  14 +#define OBSCopyPartModel_h
  15 +
  16 +#import "OBSBaseNetworking.h"
  17 +#import "OBSClient.h"
  18 +#import "OBSServiceBaseModel.h"
  19 +#import "OBSServiceConstDefinition.h"
  20 +
  21 +
  22 +@class OBSEncryptionTypeCustomer;
  23 +@class OBSAbstractEncryption;
  24 + //request
  25 +
  26 +#pragma mark - request
  27 +
  28 +/**
  29 + 拷贝段
  30 + */
  31 +@protocol OBSCopyPartProtocol<NSObject>
  32 +@required
  33 +
  34 +/**
  35 + 被复制桶名
  36 + */
  37 +@property (nonatomic, strong, nonnull) NSString *srcBucketName;
  38 +
  39 +/**
  40 + 被复制对象名
  41 + */
  42 +@property (nonatomic, strong, nonnull) NSString *srcObjectKey;
  43 +
  44 +/**
  45 + 被复制多版本ID
  46 + */
  47 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  48 +
  49 +/**
  50 + 被复制范围
  51 + */
  52 +@property (nonatomic, strong, nonnull) NSString *range;
  53 +
  54 +
  55 +/**
  56 + 上传段的桶名
  57 + */
  58 +@property (nonatomic, strong, nonnull) NSString *uploadBucketName;
  59 +
  60 +/**
  61 + 上传段对象名
  62 + */
  63 +@property (nonatomic, strong, nonnull) NSString *uploadObjectKey;
  64 +
  65 +/**
  66 + 上传段段号
  67 + */
  68 +@property (nonatomic, strong, nonnull) NSNumber *uploadPartNumber;
  69 +
  70 +/**
  71 + 多段上传任务ID
  72 + */
  73 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  74 +
  75 +/**
  76 + 被复制对象加密方式
  77 + */
  78 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *srcObjectEncryption;
  79 +
  80 +/**
  81 + 复制后对象加密方式
  82 + */
  83 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *uploadEncryption;
  84 +@end
  85 +
  86 +
  87 +/**
  88 + 拷贝段
  89 + */
  90 +@interface OBSCopyPartRequest: OBSBaseRequest<OBSCopyPartProtocol>
  91 +
  92 +/**
  93 + 被拷贝桶名
  94 + */
  95 +@property (nonatomic, strong, nonnull) NSString *srcBucketName;
  96 +
  97 +/**
  98 + 被拷贝的对象KEY
  99 + */
  100 +@property (nonatomic, strong, nonnull) NSString *srcObjectKey;
  101 +
  102 +/**
  103 + 被拷贝的对象多版本ID
  104 + */
  105 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  106 +
  107 +/**
  108 + 被拷贝的字节范围
  109 + */
  110 +@property (nonatomic, strong, nonnull) NSString *range;
  111 +
  112 +
  113 +/**
  114 + 拷贝后桶名
  115 + */
  116 +@property (nonatomic, strong, nonnull) NSString *uploadBucketName;
  117 +
  118 +/**
  119 + 拷贝后对象KEY
  120 + */
  121 +@property (nonatomic, strong, nonnull) NSString *uploadObjectKey;
  122 +
  123 +/**
  124 + 被拷贝的段号
  125 + */
  126 +@property (nonatomic, strong, nonnull) NSNumber *uploadPartNumber;
  127 +
  128 +/**
  129 + 多段上传任务ID
  130 + */
  131 +@property (nonatomic, strong, nonnull) NSString *uploadID;
  132 +
  133 +/**
  134 + 被拷贝加密方式
  135 + */
  136 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *srcObjectEncryption;
  137 +
  138 +/**
  139 + 拷贝后加密方式
  140 + */
  141 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *uploadEncryption;
  142 +
  143 +/**
  144 + 初始化拷贝段request
  145 +
  146 + @param srcBucketName 原始桶名
  147 + @param srcObjectKey 原始对象KEY
  148 + @param uploadBucketName 拷贝后桶名
  149 + @param uploadObjectKey 拷贝后对象KEY
  150 + @param uploadPartNumber 拷贝段段号
  151 + @param uploadID 多段上传任务ID
  152 + @return 拷贝段request
  153 + */
  154 +-(instancetype)initWithSrcBucketName:(NSString*) srcBucketName
  155 + srcObjectKey:(NSString*) srcObjectKey
  156 + uploadBucketName:(NSString*) uploadBucketName
  157 + uploadObjectKey:(NSString*) uploadObjectKey
  158 + uploadPartNumber:(NSNumber*) uploadPartNumber
  159 + uploadID:(NSString*) uploadID;
  160 +@end
  161 +
  162 +#pragma mark - networking request
  163 +@interface OBSNetworkingCopyPartRequest : OBSServiceNetworkingCommandRequest
  164 +@end
  165 +
  166 + //response
  167 +#pragma mark - response
  168 +
  169 +/**
  170 + 拷贝段response
  171 + */
  172 +@interface OBSCopyPartResponse: OBSServiceResponse
  173 +
  174 +/**
  175 + 新段的etag
  176 + */
  177 +@property (nonatomic, strong, nonnull) NSString *etag;
  178 +
  179 +/**
  180 + 最后修改时间
  181 + */
  182 +@property (nonatomic, strong, nonnull) NSDate *lastModified;
  183 +
  184 +/**
  185 + 被拷贝对象的多版本ID
  186 + */
  187 +@property (nonatomic, strong, nonnull) NSString *srcObjectVersionID;
  188 +
  189 +/**
  190 + 加密方式
  191 + */
  192 +@property (nonatomic, strong, nonnull) __kindof OBSAbstractEncryption *encryption;
  193 +
  194 +@end
  195 +
  196 + //client method
  197 +#pragma mark - client method
  198 +@interface OBSClient(copyPart)
  199 +
  200 +/**
  201 + 拷贝段
  202 +
  203 + @param request 拷贝段request
  204 + @param completionHandler 拷贝段回调
  205 + @return OBSBFTask
  206 + */
  207 +- (OBSBFTask*)copyPart:(__kindof OBSBaseRequest<OBSCopyPartProtocol>*)request
  208 + completionHandler:(void (^)(OBSCopyPartResponse * response, NSError * error))completionHandler;
  209 +@end
  210 +#endif /* OBSCopyPartModel_h */
  1 +// Copyright 2019 Huawei Technologies Co.,Ltd.
  2 +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3 +// this file except in compliance with the License. You may obtain a copy of the
  4 +// License at
  5 +//
  6 +// http://www.apache.org/licenses/LICENSE-2.0
  7 +//
  8 +// Unless required by applicable law or agreed to in writing, software distributed
  9 +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10 +// CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11 +// specific language governing permissions and limitations under the License.
  12 +
  13 +#ifndef OBSCreateBucketModel_h
  14 +#define OBSCreateBucketModel_h
  15 +#import "OBSBaseModel.h"
  16 +#import "OBSBaseNetworking.h"
  17 +#import "OBSClient.h"
  18 +#import "OBSServiceBaseModel.h"
  19 +#import "OBSServiceConstDefinition.h"
  20 +#import "OBSServiceCommonEntities.h"
  21 +#import "OBSServiceCredentialProvider.h"
  22 +
  23 + //request
  24 +#pragma mark - request entity
  25 +
  26 +
  27 +#pragma mark - request
  28 +
  29 +
  30 +
  31 +/**
  32 + 创建桶的
  33 + */
  34 +@protocol OBSCreateBucketProtocol
  35 +@required
  36 +
  37 +/**
  38 + 桶名
  39 + */
  40 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  41 +@end
  42 +
  43 +
  44 +/**
  45 + 创建桶request
  46 + */
  47 +@interface OBSCreateBucketRequest: OBSBaseRequest<OBSCreateBucketProtocol>
  48 +
  49 +/**
  50 + //区域配置
  51 + */
  52 +@property (nonatomic, strong, nullable) OBSBucketConfiguration *configuration;
  53 +
  54 +/**
  55 + ACL设置
  56 +
  57 + OBSACLPolicyNULL0,
  58 + OBSACLPolicyPrivate,
  59 + OBSACLPolicyPublicRead,
  60 + OBSACLPolicyPublicReadWrite,
  61 + OBSACLPolicyAuthenticatedRead,
  62 + OBSACLPolicyBucketOwnerRead,
  63 + OBSACLPolicyBucketOwnerFullControl,
  64 + OBSACLPolicyLogDeliveryWrite,
  65 + */
  66 +@property (nonatomic, assign) OBSACLPolicy bucketACLPolicy;
  67 +
  68 +/**
  69 + 桶存储类型
  70 +
  71 + OBSStorageClassNULL0,
  72 + OBSStorageClassStandard,
  73 + OBSStorageClassStandardIA,
  74 + OBSStorageClassGlacier,
  75 + */
  76 +@property (nonatomic, assign) OBSStorageClass defaultStorageClass;
  77 +@property (nonatomic, strong, nonnull) NSString *bucketName;
  78 +
  79 +//**********************自研协议*******************************
  80 +/**
  81 + 授权给指定domain下的所有用户有READ权限。
  82 + */
  83 +@property (nonatomic, strong, nonnull) NSString *grantRead;
  84 +/**
  85 + 授权给指定domain下的所有用户有WRITE权限。
  86 + */
  87 +@property (nonatomic, strong, nonnull) NSString *grantWrite;
  88 +/**
  89 + 授权给指定domain下的所有用户有READ_ACP权限。
  90 + */
  91 +@property (nonatomic, strong, nonnull) NSString *grantReadAcp;
  92 +/**
  93 + 授权给指定domain下的所有用户有WRITE_ACP权限,允许修改桶的ACL信息。
  94 + */
  95 +@property (nonatomic, strong, nonnull) NSString *grantWriteAcp;
  96 +/**
  97 + 授权给指定domain下的所有用户有FULL_CONTROL权限。
  98 + */
  99 +@property (nonatomic, strong, nonnull) NSString *grantfullControl;
  100 +/**
  101 + 授权给指定domain下的所有用户有READ权限,并且在默认情况下,该READ权限将传递给桶内所有对象。
  102 + */
  103 +@property (nonatomic, strong, nonnull) NSString *grantreadDelivered;
  104 +/**
  105 + 授权给指定domain下的所有用户有FULL_CONTROL权限,并且在默认情况下,该FULL_CONTROL权限将传递给桶内所有对象。
  106 + */
  107 +@property (nonatomic, strong, nonnull) NSString *grantfullControlDelivered;
  108 +
  109 +
  110 +/**
  111 + 初始化创建桶的request对象
  112 +
  113 + @param bucketName 桶名
  114 + @return request实例
  115 + */
  116 +-(instancetype)initWithBucketName:(NSString*) bucketName;
  117 +@end
  118 +
  119 +#pragma mark - networking request
  120 +@interface OBSCreateBucketRequestNetworking : OBSServiceNetworkingCommandRequest
  121 +@end
  122 +
  123 + //response
  124 +#pragma mark - response
  125 +
  126 +/**
  127 + 创建桶response
  128 + */
  129 +@interface OBSCreateBucketResponse: OBSServiceResponse
  130 +
  131 +/**
  132 + 桶区域位置
  133 + */
  134 +@property (nonatomic, strong, nullable) NSString *location;
  135 +@end
  136 +
  137 +
  138 +#pragma mark - client method
  139 +@interface OBSClient(createBucket)
  140 +
  141 +/**
  142 + 创建桶
  143 +
  144 + @param request 创建桶的request对象
  145 + @param completionHandler 创建桶的回调
  146 + @return task对象
  147 + */
  148 +- (OBSBFTask*)createBucket:(__kindof OBSBaseRequest<OBSCreateBucketProtocol>*)request
  149 + completionHandler:(void (^)(OBSCreateBucketResponse * response, NSError * error))completionHandler;
  150 +@end
  151 +
  152 +
  153 +#endif /* OBSServiceBaseModel_h */
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +#import "OBSDDASLLogger.h"
  17 +
  18 +@protocol OBSDDLogger;
  19 +
  20 +/**
  21 + * This class provides the ability to capture the ASL (Apple System Logs)
  22 + */
  23 +@interface OBSDDASLLogCapture : NSObject
  24 +
  25 +/**
  26 + * Start capturing logs
  27 + */
  28 ++ (void)start;
  29 +
  30 +/**
  31 + * Stop capturing logs
  32 + */
  33 ++ (void)stop;
  34 +
  35 +/**
  36 + * The current capture level.
  37 + * @note Default log level: OBSDDLogLevelVerbose (i.e. capture all ASL messages).
  38 + */
  39 +@property (class) OBSDDLogLevel captureLevel;
  40 +
  41 +@end
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +#import <Foundation/Foundation.h>
  17 +
  18 +// Disable legacy macros
  19 +#ifndef OBSDD_LEGACY_MACROS
  20 + #define OBSDD_LEGACY_MACROS 0
  21 +#endif
  22 +
  23 +#import "OBSDDLog.h"
  24 +
  25 +// Custom key set on messages sent to ASL
  26 +extern const char *const kOBSDDASLKeyOBSDDLog;
  27 +
  28 +// Value set for kOBSDDASLKeyOBSDDLog
  29 +extern const char *const kOBSDDASLOBSDDLogValue;
  30 +
  31 +/**
  32 + *This class provides a logger for the Apple System Log facility.
  33 + *
  34 + *As described in the "Getting Started" page,
  35 + *the traditional NSLog() function directs its output to two places:
  36 + *
  37 + *- Apple System Log
  38 + *- StdErr (if stderr is a TTY) so log statements show up in Xcode console
  39 + *
  40 + *To duplicate NSLog() functionality you can simply add this logger and a tty logger.
  41 + *However, if you instead choose to use file logging (for faster performance),
  42 + *you may choose to use a file logger and a tty logger.
  43 + **/
  44 +@interface OBSDDASLLogger : OBSDDAbstractLogger <OBSDDLogger>
  45 +
  46 +/**
  47 + * Singleton method
  48 + *
  49 + * @return the shared instance
  50 + */
  51 +@property (class, readonly, strong) OBSDDASLLogger *sharedInstance;
  52 +
  53 +// Inherited from OBSDDAbstractLogger
  54 +
  55 +// - (id <OBSDDLogFormatter>)logFormatter;
  56 +// - (void)setLogFormatter:(id <OBSDDLogFormatter>)formatter;
  57 +
  58 +@end
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +// Disable legacy macros
  17 +#ifndef OBSDD_LEGACY_MACROS
  18 + #define OBSDD_LEGACY_MACROS 0
  19 +#endif
  20 +
  21 +#import "OBSDDLog.h"
  22 +
  23 +/**
  24 + *This class provides an abstract implementation of a database logger.
  25 + *
  26 + *That is, it provides the base implementation for a database logger to build atop of.
  27 + *All that is needed for a concrete database logger is to extend this class
  28 + *and override the methods in the implementation file that are prefixed with "db_".
  29 + **/
  30 +@interface OBSDDAbstractDatabaseLogger : OBSDDAbstractLogger {
  31 +
  32 +@protected
  33 + NSUInteger _saveThreshold;
  34 + NSTimeInterval _saveInterval;
  35 + NSTimeInterval _maxAge;
  36 + NSTimeInterval _deleteInterval;
  37 + BOOL _deleteOnEverySave;
  38 +
  39 + BOOL _saveTimerSuspended;
  40 + NSUInteger _unsavedCount;
  41 + dispatch_time_t _unsavedTime;
  42 + dispatch_source_t _saveTimer;
  43 + dispatch_time_t _lastDeleteTime;
  44 + dispatch_source_t _deleteTimer;
  45 +}
  46 +
  47 +/**
  48 + *Specifies how often to save the data to disk.
  49 + *Since saving is an expensive operation (disk io) it is not done after every log statement.
  50 + *These properties allow you to configure how/when the logger saves to disk.
  51 + *
  52 + *A save is done when either (whichever happens first):
  53 + *
  54 + *- The number of unsaved log entries reaches saveThreshold
  55 + *- The amount of time since the oldest unsaved log entry was created reaches saveInterval
  56 + *
  57 + *You can optionally disable the saveThreshold by setting it to zero.
  58 + *If you disable the saveThreshold you are entirely dependent on the saveInterval.
  59 + *
  60 + *You can optionally disable the saveInterval by setting it to zero (or a negative value).
  61 + *If you disable the saveInterval you are entirely dependent on the saveThreshold.
  62 + *
  63 + *It's not wise to disable both saveThreshold and saveInterval.
  64 + *
  65 + *The default saveThreshold is 500.
  66 + *The default saveInterval is 60 seconds.
  67 + **/
  68 +@property (assign, readwrite) NSUInteger saveThreshold;
  69 +
  70 +/**
  71 + * See the description for the `saveThreshold` property
  72 + */
  73 +@property (assign, readwrite) NSTimeInterval saveInterval;
  74 +
  75 +/**
  76 + *It is likely you don't want the log entries to persist forever.
  77 + *Doing so would allow the database to grow infinitely large over time.
  78 + *
  79 + *The maxAge property provides a way to specify how old a log statement can get
  80 + *before it should get deleted from the database.
  81 + *
  82 + *The deleteInterval specifies how often to sweep for old log entries.
  83 + *Since deleting is an expensive operation (disk io) is is done on a fixed interval.
  84 + *
  85 + *An alternative to the deleteInterval is the deleteOnEverySave option.
  86 + *This specifies that old log entries should be deleted during every save operation.
  87 + *
  88 + *You can optionally disable the maxAge by setting it to zero (or a negative value).
  89 + *If you disable the maxAge then old log statements are not deleted.
  90 + *
  91 + *You can optionally disable the deleteInterval by setting it to zero (or a negative value).
  92 + *
  93 + *If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted.
  94 + *
  95 + *It's not wise to enable both deleteInterval and deleteOnEverySave.
  96 + *
  97 + *The default maxAge is 7 days.
  98 + *The default deleteInterval is 5 minutes.
  99 + *The default deleteOnEverySave is NO.
  100 + **/
  101 +@property (assign, readwrite) NSTimeInterval maxAge;
  102 +
  103 +/**
  104 + * See the description for the `maxAge` property
  105 + */
  106 +@property (assign, readwrite) NSTimeInterval deleteInterval;
  107 +
  108 +/**
  109 + * See the description for the `maxAge` property
  110 + */
  111 +@property (assign, readwrite) BOOL deleteOnEverySave;
  112 +
  113 +/**
  114 + *Forces a save of any pending log entries (flushes log entries to disk).
  115 + **/
  116 +- (void)savePendingLogEntries;
  117 +
  118 +/**
  119 + *Removes any log entries that are older than maxAge.
  120 + **/
  121 +- (void)deleteOldLogEntries;
  122 +
  123 +@end
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +/**
  17 + *NSAsset replacement that will output a log message even when assertions are disabled.
  18 + **/
  19 +#define OBSDDAssert(condition, frmt, ...) \
  20 + if (!(condition)) { \
  21 + NSString *description = [NSString stringWithFormat:frmt, ## __VA_ARGS__]; \
  22 + OBSDDLogError(@"%@", description); \
  23 + NSAssert(NO, description); \
  24 + }
  25 +#define OBSDDAssertCondition(condition) OBSDDAssert(condition, @"Condition not satisfied: %s", #condition)
  26 +
  1 +// Software License Agreement (BSD License)
  2 +//
  3 +// Copyright (c) 2010-2016, Deusty, LLC
  4 +// All rights reserved.
  5 +//
  6 +// Redistribution and use of this software in source and binary forms,
  7 +// with or without modification, are permitted provided that the following conditions are met:
  8 +//
  9 +// *Redistributions of source code must retain the above copyright notice,
  10 +// this list of conditions and the following disclaimer.
  11 +//
  12 +// *Neither the name of Deusty nor the names of its contributors may be used
  13 +// to endorse or promote products derived from this software without specific
  14 +// prior written permission of Deusty, LLC.
  15 +
  16 +#import <Foundation/Foundation.h>
  17 +
  18 +// Disable legacy macros
  19 +#ifndef OBSDD_LEGACY_MACROS
  20 + #define OBSDD_LEGACY_MACROS 0
  21 +#endif
  22 +
  23 +#import "OBSDDLog.h"
  24 +
  25 +/**
  26 + *This class provides a log formatter that filters log statements from a logging context not on the whitelist.
  27 + *
  28 + *A log formatter can be added to any logger to format and/or filter its output.
  29 + *You can learn more about log formatters here:
  30 + *Documentation/CustomFormatters.md
  31 + *
  32 + *You can learn more about logging context's here:
  33 + *Documentation/CustomContext.md
  34 + *
  35 + *But here's a quick overview / refresher:
  36 + *
  37 + *Every log statement has a logging context.
  38 + *These come from the underlying logging macros defined in OBSDDLog.h.
  39 + *The default logging context is zero.
  40 + *You can define multiple logging context's for use in your application.
  41 + *For example, logically separate parts of your app each have a different logging context.
  42 + *Also 3rd party frameworks that make use of Lumberjack generally use their own dedicated logging context.
  43 + **/
  44 +@interface OBSDDContextWhitelistFilterLogFormatter : NSObject <OBSDDLogFormatter>
  45 +
  46 +/**
  47 + * Designated default initializer
  48 + */
  49 +- (instancetype)init NS_DESIGNATED_INITIALIZER;
  50 +
  51 +/**
  52 + * Add a context to the whitelist
  53 + *
  54 + * @param loggingContext the context
  55 + */
  56 +- (void)addToWhitelist:(NSUInteger)loggingContext;
  57 +
  58 +/**
  59 + * Remove context from whitelist
  60 + *
  61 + * @param loggingContext the context
  62 + */
  63 +- (void)removeFromWhitelist:(NSUInteger)loggingContext;
  64 +
  65 +/**
  66 + * Return the whitelist
  67 + */
  68 +@property (readonly, copy) NSArray<NSNumber *> *whitelist;
  69 +
  70 +/**
  71 + * Check if a context is on the whitelist
  72 + *
  73 + * @param loggingContext the context
  74 + */
  75 +- (BOOL)isOnWhitelist:(NSUInteger)loggingContext;
  76 +
  77 +@end
  78 +
  79 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  80 +#pragma mark -
  81 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  82 +
  83 +/**
  84 + *This class provides a log formatter that filters log statements from a logging context on the blacklist.
  85 + **/
  86 +@interface OBSDDContextBlacklistFilterLogFormatter : NSObject <OBSDDLogFormatter>
  87 +
  88 +- (instancetype)init NS_DESIGNATED_INITIALIZER;
  89 +
  90 +/**
  91 + * Add a context to the blacklist
  92 + *
  93 + * @param loggingContext the context
  94 + */
  95 +- (void)addToBlacklist:(NSUInteger)loggingContext;
  96 +
  97 +/**
  98 + * Remove context from blacklist
  99 + *
  100 + * @param loggingContext the context
  101 + */
  102 +- (void)removeFromBlacklist:(NSUInteger)loggingContext;
  103 +
  104 +/**
  105 + * Return the blacklist
  106 + */
  107 +@property (readonly, copy) NSArray<NSNumber *> *blacklist;
  108 +
  109 +
  110 +/**
  111 + * Check if a context is on the blacklist
  112 + *
  113 + * @param loggingContext the context
  114 + */
  115 +- (BOOL)isOnBlacklist:(NSUInteger)loggingContext;
  116 +
  117 +@end