From e318aaeee4c73fd6544a35b0caf06d9dcea56b64 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Sat, 11 Oct 2025 18:43:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20EPMomentAPIHelper?= =?UTF-8?q?=5FDeprecated=20=E4=BB=A5=E6=94=AF=E6=8C=81=E6=97=A7=E7=89=88?= =?UTF-8?q?=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主要变更: 1. 新增 EPMomentAPIHelper_Deprecated.h 和 EPMomentAPIHelper_Deprecated.m 文件,提供与旧版 Objective-C API 的兼容性。 2. 该文件已被 EPMomentAPISwiftHelper.swift 替代,保留仅供参考,后续可删除。 3. 更新 EPMomentListView 以使用新的 Swift 版本 API,提升代码的现代化和类型安全。 此更新旨在确保旧版 API 的平滑过渡,同时鼓励使用新的 Swift 实现。 --- YuMi.xcodeproj/project.pbxproj | 12 +++--- ...elper.h => EPMomentAPIHelper_Deprecated.h} | 9 +++- ...elper.m => EPMomentAPIHelper_Deprecated.m} | 6 ++- .../Services/EPMomentAPISwiftHelper.swift | 41 ++++++++++++++++++- YuMi/E-P/NewMoments/Views/EPMomentListView.h | 8 +++- YuMi/E-P/NewMoments/Views/EPMomentListView.m | 9 ++-- 6 files changed, 70 insertions(+), 15 deletions(-) rename YuMi/E-P/NewMoments/Services/{EPMomentAPIHelper.h => EPMomentAPIHelper_Deprecated.h} (71%) rename YuMi/E-P/NewMoments/Services/{EPMomentAPIHelper.m => EPMomentAPIHelper_Deprecated.m} (88%) diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index e03bb81..a76e4d0 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -425,7 +425,6 @@ 4C06428B2E98DC5F00BAF413 /* EPTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06428A2E98DC5F00BAF413 /* EPTabBarController.swift */; }; 4C06428E2E98DC7E00BAF413 /* EPMineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C06428D2E98DC7E00BAF413 /* EPMineViewController.m */; }; 4C0642912E98DC8700BAF413 /* EPMomentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0642902E98DC8700BAF413 /* EPMomentViewController.m */; }; - 4C0642962E98F76F00BAF413 /* EPMomentAPIHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0642942E98F76F00BAF413 /* EPMomentAPIHelper.m */; }; 4C0642992E98F77900BAF413 /* EPMomentListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0642982E98F77900BAF413 /* EPMomentListView.m */; }; 4C06429C2E99120600BAF413 /* EPMomentPublishViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C06429B2E99120600BAF413 /* EPMomentPublishViewController.m */; }; 4C0A5B842E02675300955219 /* MedalsCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */; }; @@ -455,6 +454,7 @@ 4C1E98C62E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */; }; 4C1E98C92E9A4DFD0031AE79 /* EPQCloudConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C72E9A4DFD0031AE79 /* EPQCloudConfig.swift */; }; 4C1E98CA2E9A4DFD0031AE79 /* EPSDKManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98C82E9A4DFD0031AE79 /* EPSDKManager.swift */; }; + 4C1E98CD2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */; }; 4C3475C42DD1FE590099B984 /* CreateEventSelectRoomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3475C32DD1FE590099B984 /* CreateEventSelectRoomViewController.m */; }; 4C3851992DD5F4D50089CFCC /* EventConfigModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3851982DD5F4D50089CFCC /* EventConfigModel.m */; }; 4C38C2AD2D84064400CFA4A8 /* LoginInputItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C38C2AC2D84064300CFA4A8 /* LoginInputItemView.m */; }; @@ -2484,8 +2484,6 @@ 4C06428D2E98DC7E00BAF413 /* EPMineViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMineViewController.m; sourceTree = ""; }; 4C06428F2E98DC8700BAF413 /* EPMomentViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentViewController.h; sourceTree = ""; }; 4C0642902E98DC8700BAF413 /* EPMomentViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMomentViewController.m; sourceTree = ""; }; - 4C0642932E98F76F00BAF413 /* EPMomentAPIHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentAPIHelper.h; sourceTree = ""; }; - 4C0642942E98F76F00BAF413 /* EPMomentAPIHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMomentAPIHelper.m; sourceTree = ""; }; 4C0642972E98F77900BAF413 /* EPMomentListView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentListView.h; sourceTree = ""; }; 4C0642982E98F77900BAF413 /* EPMomentListView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMomentListView.m; sourceTree = ""; }; 4C06429A2E99120600BAF413 /* EPMomentPublishViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentPublishViewController.h; sourceTree = ""; }; @@ -2537,6 +2535,8 @@ 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPMomentAPISwiftHelper.swift; sourceTree = ""; }; 4C1E98C72E9A4DFD0031AE79 /* EPQCloudConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPQCloudConfig.swift; sourceTree = ""; }; 4C1E98C82E9A4DFD0031AE79 /* EPSDKManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EPSDKManager.swift; sourceTree = ""; }; + 4C1E98CB2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EPMomentAPIHelper_Deprecated.h; sourceTree = ""; }; + 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPMomentAPIHelper_Deprecated.m; sourceTree = ""; }; 4C3475C22DD1FE590099B984 /* CreateEventSelectRoomViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreateEventSelectRoomViewController.h; sourceTree = ""; }; 4C3475C32DD1FE590099B984 /* CreateEventSelectRoomViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CreateEventSelectRoomViewController.m; sourceTree = ""; }; 4C3851972DD5F4D50089CFCC /* EventConfigModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EventConfigModel.h; sourceTree = ""; }; @@ -6597,9 +6597,9 @@ 4C0642952E98F76F00BAF413 /* Services */ = { isa = PBXGroup; children = ( + 4C1E98CB2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.h */, + 4C1E98CC2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m */, 4C1E98C52E9A45BC0031AE79 /* EPMomentAPISwiftHelper.swift */, - 4C0642932E98F76F00BAF413 /* EPMomentAPIHelper.h */, - 4C0642942E98F76F00BAF413 /* EPMomentAPIHelper.m */, ); path = Services; sourceTree = ""; @@ -12293,7 +12293,6 @@ E83ABF03280EC90C00322EE4 /* ContentApplicationShareModel.m in Sources */, 4C7153952E0942F700C9F940 /* MedalsCyclePagerCell.m in Sources */, 9BA812E028BF6ABB00783EA7 /* Api+RedPacket.m in Sources */, - 4C0642962E98F76F00BAF413 /* EPMomentAPIHelper.m in Sources */, 9BA3B40F293DD2F90071DF1C /* XPUpgradeView.m in Sources */, E81A654928351B9500F55894 /* XPMomentsRecommendHeaderView.m in Sources */, E84B0E3F2727EDF6008818C6 /* XPRoomMessageTableViewCell.m in Sources */, @@ -12671,6 +12670,7 @@ E8751E5F28A62A970056EF44 /* XPSailingPresenter.m in Sources */, E84A2E962A5280F900D6AF8A /* XPExchangeDiamondsView.m in Sources */, 23F9636A2BB6919D00F440A6 /* PINobleRebateModel.m in Sources */, + 4C1E98CD2E9A69B20031AE79 /* EPMomentAPIHelper_Deprecated.m in Sources */, E8DAC5AC2858305A00012CFD /* XPRoomMessageBubbleView.m in Sources */, 1427218929A75F6F00C7C423 /* HTTPDataResponse.m in Sources */, E8B9843028AB90200022D026 /* XPMoentsTopicListView.m in Sources */, diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h similarity index 71% rename from YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h rename to YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h index 98ca7d2..bebb1c8 100644 --- a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h +++ b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.h @@ -1,9 +1,16 @@ // -// EPMomentAPIHelper.h +// EPMomentAPIHelper_Deprecated.h // YuMi // // Created by AI on 2025-10-10. // +// ⚠️ DEPRECATED: 已被 EPMomentAPISwiftHelper.swift 替代 +// 原因: +// 1. 继承 BaseMvpPresenter 会引起 Bridging Header 依赖链问题 +// 2. Swift 版本更简洁、类型安全 +// 3. 功能已完整迁移到 Swift 版本 +// +// 保留此文件仅供参考,后续可删除 #import #import "BaseMvpPresenter.h" diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m similarity index 88% rename from YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m rename to YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m index 07082f8..b55af98 100644 --- a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m +++ b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper_Deprecated.m @@ -1,12 +1,14 @@ // -// EPMomentAPIHelper.m +// EPMomentAPIHelper_Deprecated.m // YuMi // // Created by AI on 2025-10-10. // +// ⚠️ DEPRECATED: 已被 EPMomentAPISwiftHelper.swift 替代 +// 保留此文件仅供参考,后续可删除 #import -#import "EPMomentAPIHelper.h" +#import "EPMomentAPIHelper_Deprecated.h" #import "Api+Moments.h" #import "AccountInfoStorage.h" #import "BaseModel.h" diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift b/YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift index e638a43..170e6d6 100644 --- a/YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift +++ b/YuMi/E-P/NewMoments/Services/EPMomentAPISwiftHelper.swift @@ -8,9 +8,48 @@ import Foundation /// 动态 API 封装(Swift 现代化版本) -/// 与现有 OC 版本 EPMomentAPIHelper 并存,供对比评估 +/// 统一封装列表获取和发布功能,完全替代 OC 版本 @objc class EPMomentAPISwiftHelper: NSObject { + /// 拉取最新动态列表 + /// - Parameters: + /// - nextID: 下一页 ID,首次传空字符串 + /// - completion: 成功回调 (动态列表, 下一页ID) + /// - failure: 失败回调 (错误码, 错误信息) + @objc func fetchLatestMomentsWithNextID( + _ nextID: String, + completion: @escaping (NSArray, String) -> Void, + failure: @escaping (Int, String) -> Void + ) { + let pageSize = "20" + let types = "0,2" // 图片+文字 + + Api.momentsLatestList({ (data, code, msg) in + if code == 200 { + // 使用运行时动态调用解析 Model,避免类型依赖 + if let modelClass = NSClassFromString("MomentsListInfoModel") as? NSObject.Type, + let selector = NSSelectorFromString("modelWithDictionary:") as Selector?, + modelClass.responds(to: selector) { + + let modelObj = modelClass.perform(selector, with: data?.data)?.takeUnretainedValue() + + // 使用 KVC 获取属性,避免直接访问类型 + if let model = modelObj as? NSObject { + let dynamicList = model.value(forKey: "dynamicList") as? NSArray ?? NSArray() + let nextID = model.value(forKey: "nextDynamicId") as? String ?? "" + completion(dynamicList, nextID) + return + } + } + + // 解析失败,返回空 + completion(NSArray(), "") + } else { + failure(Int(code), msg ?? "请求失败") + } + }, dynamicId: nextID, pageSize: pageSize, types: types) + } + /// 发布动态 /// - Parameters: /// - type: "0"=纯文本, "2"=图片 diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.h b/YuMi/E-P/NewMoments/Views/EPMomentListView.h index 68be966..5376032 100644 --- a/YuMi/E-P/NewMoments/Views/EPMomentListView.h +++ b/YuMi/E-P/NewMoments/Views/EPMomentListView.h @@ -6,12 +6,18 @@ // #import -#import "EPMomentAPIHelper.h" NS_ASSUME_NONNULL_BEGIN +@class EPMomentAPISwiftHelper; @class MomentsInfoModel; +/// 推荐/我的动态列表数据源类型 +typedef NS_ENUM(NSInteger, EPMomentListSourceType) { + EPMomentListSourceTypeRecommend = 0, + EPMomentListSourceTypeMine = 1 +}; + /// 承载 Moments 列表与分页刷新的视图 @interface EPMomentListView : UIView diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.m b/YuMi/E-P/NewMoments/Views/EPMomentListView.m index f472de3..51392a6 100644 --- a/YuMi/E-P/NewMoments/Views/EPMomentListView.m +++ b/YuMi/E-P/NewMoments/Views/EPMomentListView.m @@ -9,6 +9,7 @@ #import "EPMomentListView.h" #import "EPMomentCell.h" #import +#import "YuMi-Swift.h" @interface EPMomentListView () @@ -16,7 +17,7 @@ @property (nonatomic, strong) UITableView *tableView; @property (nonatomic, strong) UIRefreshControl *refreshControl; @property (nonatomic, strong) NSMutableArray *mutableRawList; -@property (nonatomic, strong) EPMomentAPIHelper *api; +@property (nonatomic, strong) EPMomentAPISwiftHelper *api; @property (nonatomic, assign) BOOL isLoading; @property (nonatomic, copy) NSString *nextID; @property (nonatomic, assign) BOOL isLocalMode; @@ -29,7 +30,7 @@ self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor clearColor]; - _api = [[EPMomentAPIHelper alloc] init]; + _api = [[EPMomentAPISwiftHelper alloc] init]; _mutableRawList = [NSMutableArray array]; _sourceType = EPMomentListSourceTypeRecommend; @@ -86,7 +87,7 @@ @kWeakify(self); [self.api fetchLatestMomentsWithNextID:self.nextID - completion:^(NSArray * _Nullable list, NSString * _Nonnull nextMomentID) { + completion:^(NSArray *list, NSString *nextMomentID) { @kStrongify(self); [self endLoading]; if (list.count > 0) { @@ -106,7 +107,7 @@ [self.tableView.mj_footer endRefreshing]; } } - } failure:^(NSInteger code, NSString * _Nullable msg) { + } failure:^(NSInteger code, NSString *msg) { @kStrongify(self); [self endLoading]; // TODO: 完全没有数据情况下,后续补充数据异常页面