Browse Source

开发了 AF 的流式响应网络请求

100Years 2 months ago
parent
commit
4fa0007d29

+ 3 - 3
AIEmoji.xcodeproj/project.pbxproj

@@ -481,7 +481,6 @@
 		A89EA6782D59D238000EB181 /* ViewModel */ = {
 			isa = PBXGroup;
 			children = (
-				A89EA67C2D59F1AC000EB181 /* StreamPostRequest.swift */,
 				A89EA6792D59D248000EB181 /* TSAIChatVM.swift */,
 			);
 			path = ViewModel;
@@ -736,6 +735,7 @@
 				A8F775372D390C3C00AA6E93 /* TSNetworkManager.swift */,
 				A8F7753C2D3918E200AA6E93 /* TSNetWork+Business.swift */,
 				A8F7753A2D3918D700AA6E93 /* TSNetworkManager+Loading.swift */,
+				A89EA67C2D59F1AC000EB181 /* StreamPostRequest.swift */,
 			);
 			path = TSNetWork;
 			sourceTree = "<group>";
@@ -1181,7 +1181,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -1220,7 +1220,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;

+ 15 - 1
AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSAIChatVM.swift

@@ -46,8 +46,22 @@ extension TSAIChatVM {
             "message": message
         ]
         
+//        AiMDString = ""
+//        streamRequest = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
+//            guard let self = self else { return }
+//            AiMDString = AiMDString + string
+//            streamHandler(string)
+//        } completion: { result in
+//            switch result {
+//            case .success(let data):
+//                completion(data,nil)
+//            case .failure(let error):
+//                completion(nil,error)
+//            }
+//        }
+        
         AiMDString = ""
-        streamRequest = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
+        _ = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
             guard let self = self else { return }
             AiMDString = AiMDString + string
             streamHandler(string)

+ 1 - 1
AIEmoji/Business/TSEmojisVC/TSEmojisChildVC/TSEmojisChildVC.swift

@@ -77,7 +77,7 @@ class TSEmojisChildVC: TSBaseVC {
 
     override func viewDidLayoutSubviews() {
         super.viewDidLayoutSubviews()
-        print("View did layout subviews")
+//        print("View did layout subviews")
         self.collectionComponent.collectionView.frame = self.view.bounds
     }
 }

+ 0 - 0
AIEmoji/Business/AIChat/TSChatViewController/ViewModel/StreamPostRequest.swift → AIEmoji/Common/NetworkManager/TSNetWork/StreamPostRequest.swift


+ 37 - 19
AIEmoji/Common/NetworkManager/TSNetWork/TSNetWork+Business.swift

@@ -7,7 +7,7 @@
 
 /// 基础 URL(根据需求修改)
 private let baseURL = "http://ai.100yearslater.com"
-
+import Alamofire
 enum TSNeURLType:String {
     
     case imageEmoji = "/api/image/emoji"
@@ -54,6 +54,40 @@ extension TSNetworkManager {
         }
     }
     
+//    /// 通用 POST Stream 请求
+//    /// - Parameters:
+//    ///   - endpoint: 接口路径
+//    ///   - parameters: 请求参数
+//    ///   - responseType: 响应数据模型(可选)
+//    ///   - completion: 请求完成的回调
+//    func postStream<T: TSBaseModel>(
+//        urlType: TSNeURLType,
+//        parameters: [String: Any]? = nil,
+//        responseType: T.Type? = nil,
+//        streamHandler:@escaping (String) -> Void,
+//        completion: @escaping (Result<Any, Error>) -> Void
+//    ) -> StreamPostRequest{
+//        let urlString = urlType.getUrlString()
+//        
+//        let streamRequest = StreamPostRequest(url: URL(string: urlString)!, parameters: parameters) { data in
+//            if let string = String(data: data, encoding: .utf8) {
+//                print("Received chunk: \(string)")
+//                streamHandler(string)
+//            }
+//        } completionHandler: { error in
+//            if let error = error {
+//                print("Request failed with error: \(error)")
+//                completion(.failure(error))
+//            } else {
+//                print("Request completed successfully.")
+//                completion(.success("success"))
+//            }
+//        }
+//        streamRequest.startRequest()
+//        return streamRequest
+//    }
+    
+    
     /// 通用 POST Stream 请求
     /// - Parameters:
     ///   - endpoint: 接口路径
@@ -66,25 +100,9 @@ extension TSNetworkManager {
         responseType: T.Type? = nil,
         streamHandler:@escaping (String) -> Void,
         completion: @escaping (Result<Any, Error>) -> Void
-    ) -> StreamPostRequest{
+    ) -> DataStreamRequest?{
         let urlString = urlType.getUrlString()
-        
-        let streamRequest = StreamPostRequest(url: URL(string: urlString)!, parameters: parameters) { data in
-            if let string = String(data: data, encoding: .utf8) {
-                print("Received chunk: \(string)")
-                streamHandler(string)
-            }
-        } completionHandler: { error in
-            if let error = error {
-                print("Request failed with error: \(error)")
-                completion(.failure(error))
-            } else {
-                print("Request completed successfully.")
-                completion(.success("success"))
-            }
-        }
-        streamRequest.startRequest()
-        
+        let streamRequest = postStreamRequest(urlString: urlString, parameters: parameters, streamHandler: streamHandler, completion: completion)
         return streamRequest
     }
 

+ 53 - 0
AIEmoji/Common/NetworkManager/TSNetWork/TSNetworkManager.swift

@@ -25,6 +25,59 @@ class TSNetworkManager {
         ]
     }
     
+    
+    
+    func postStreamRequest(
+        urlString: String,
+        parameters: [String: Any]? = nil,
+        streamHandler:@escaping (String) -> Void,
+        completion: @escaping (Result<Any, Error>) -> Void
+    )-> DataStreamRequest? {
+        
+        guard let url = URL(string: urlString) else {
+            completion(.failure(NSError(domain: "url nil", code: 0)))
+            return nil
+        }
+        
+        // 1. 创建 URLRequest
+        var urlRequest = URLRequest(url:URL(string: urlString)!)
+        urlRequest.httpMethod = "POST"
+        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+        
+        // 2. 将字典参数转换为 JSON 数据并设置为请求体
+        do {
+            let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])
+            urlRequest.httpBody = jsonData
+        } catch {
+            print("Failed to encode parameters: \(error)")
+            completion(.failure(error))
+            return nil
+        }
+        
+        // 3. 使用 AF.streamRequest 发起流式请求
+        let request = AF.streamRequest(urlRequest)
+        request.responseStreamString{ stream in
+            switch stream.event {
+            case .stream(let result):
+                switch result {
+                case .success(let string):
+//                    print("Received string: \(string)")
+                    streamHandler(string)
+                case .failure(let error):
+                    print("Stream error: \(error)")
+                    completion(.failure(error))
+                }
+            case .complete(let cpl):
+                if let error = cpl.error {
+                    print("Request failed with error: \(error)")
+                    completion(.failure(error))
+                } else {
+                    completion(.success("success"))
+                }
+            }
+        }
+        return request
+    }
 
     func request(
         method:HTTPMethod,

+ 3 - 3
AIEmoji/Common/Purchase/TSPurchaseManager.swift

@@ -138,9 +138,9 @@ public class PurchaseManager: NSObject {
     }
 
     @objc public var isVip: Bool {
-//        #if DEBUG
-//        return true
-//        #endif
+        #if DEBUG
+        return true
+        #endif
         guard let expiresDate = expiredDate else {
             return false
         }