From e8d59495a415489bdfce1ce51d4adfa4226a2e7a Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Fri, 10 Oct 2025 17:22:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20EPMomentViewCo?= =?UTF-8?q?ntroller=EF=BC=8C=E6=9B=BF=E6=8D=A2=20UITableView=20=E4=B8=BA?= =?UTF-8?q?=20EPMomentListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主要变更: 1. 移除 UITableView,改为使用 EPMomentListView 以简化数据展示和交互。 2. 添加顶部固定文案 UILabel,提升用户体验。 3. 通过 EPMomentAPIHelper 统一管理 Moments 列表 API 请求,优化数据加载逻辑。 4. 更新 UI 约束,确保布局适配不同屏幕。 此重构旨在提升代码可维护性和用户界面的一致性。 --- YuMi.xcodeproj/project.pbxproj | 20 + .../Controllers/EPMomentViewController.m | 220 +++-------- .../NewMoments/Services/EPMomentAPIHelper.h | 36 ++ .../NewMoments/Services/EPMomentAPIHelper.m | 58 +++ YuMi/E-P/NewMoments/Views/EPMomentListView.h | 34 ++ YuMi/E-P/NewMoments/Views/EPMomentListView.m | 143 +++++++ YuMi/E-P/NewTabBar/EPTabBarController.swift | 93 +++-- .../NewTabBar/EPTabBarController.swift | 374 ------------------ YuMi/Modules/YMMonents/Api/Api+Moments.m | 6 +- 9 files changed, 396 insertions(+), 588 deletions(-) create mode 100644 YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h create mode 100644 YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m create mode 100644 YuMi/E-P/NewMoments/Views/EPMomentListView.h create mode 100644 YuMi/E-P/NewMoments/Views/EPMomentListView.m delete mode 100644 YuMi/Modules/NewTabBar/EPTabBarController.swift diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 607a842..6c39312 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -425,6 +425,8 @@ 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 */; }; 4C0A5B842E02675300955219 /* MedalsCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */; }; 4C0A5B872E02BB1100955219 /* MedalsLevelIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B862E02BB1100955219 /* MedalsLevelIndicatorView.m */; }; 4C0A5B8A2E02BC3900955219 /* MedalsDetailView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A5B892E02BC3900955219 /* MedalsDetailView.m */; }; @@ -2475,6 +2477,10 @@ 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 = ""; }; 4C0A5B822E02675300955219 /* MedalsCollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MedalsCollectionViewCell.h; sourceTree = ""; }; 4C0A5B832E02675300955219 /* MedalsCollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MedalsCollectionViewCell.m; sourceTree = ""; }; 4C0A5B852E02BB1100955219 /* MedalsLevelIndicatorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MedalsLevelIndicatorView.h; sourceTree = ""; }; @@ -6532,6 +6538,8 @@ 4C06427B2E97BD6D00BAF413 /* Views */ = { isa = PBXGroup; children = ( + 4C0642972E98F77900BAF413 /* EPMomentListView.h */, + 4C0642982E98F77900BAF413 /* EPMomentListView.m */, 4C0642792E97BD6D00BAF413 /* EPMomentCell.h */, 4C06427A2E97BD6D00BAF413 /* EPMomentCell.m */, ); @@ -6541,6 +6549,7 @@ 4C06427C2E97BD6D00BAF413 /* NewMoments */ = { isa = PBXGroup; children = ( + 4C0642952E98F76F00BAF413 /* Services */, 4C0642782E97BD6D00BAF413 /* Controllers */, 4C06427B2E97BD6D00BAF413 /* Views */, ); @@ -6565,6 +6574,15 @@ path = "E-P"; sourceTree = ""; }; + 4C0642952E98F76F00BAF413 /* Services */ = { + isa = PBXGroup; + children = ( + 4C0642932E98F76F00BAF413 /* EPMomentAPIHelper.h */, + 4C0642942E98F76F00BAF413 /* EPMomentAPIHelper.m */, + ); + path = Services; + sourceTree = ""; + }; 4C45C1A82E6837BF00E73A44 /* Manager */ = { isa = PBXGroup; children = ( @@ -12232,6 +12250,7 @@ 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 */, @@ -13189,6 +13208,7 @@ 189DD58F26DF97E700AB55B1 /* LoginPresenter.m in Sources */, E88863C9278EBA43004BCFAB /* XPAcrossRoomPKForceEndResultView.m in Sources */, E8F63CB7298B566D00B338BA /* XPSessionSayHelloPresenter.m in Sources */, + 4C0642992E98F77900BAF413 /* EPMomentListView.m in Sources */, E88C72952828F1AD0047FB2B /* XPRoomMusicLibraryViewController.m in Sources */, 233423D32AAF0F4F00B1253F /* XPIAPRechargeHeadCell.m in Sources */, E85E7BA62A4EC99300B6D00A /* XPMineGiveDiamondSearchView.m in Sources */, diff --git a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m index 6fe702e..7b44823 100644 --- a/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m +++ b/YuMi/E-P/NewMoments/Controllers/EPMomentViewController.m @@ -7,34 +7,20 @@ // #import "EPMomentViewController.h" +#import +#import #import "EPMomentCell.h" -#import "Api+Moments.h" -#import "AccountInfoStorage.h" -#import "MomentsInfoModel.h" +#import "EPMomentListView.h" -@interface EPMomentViewController () +@interface EPMomentViewController () // MARK: - UI Components -/// 主列表(卡片式布局) -@property (nonatomic, strong) UITableView *tableView; +/// 列表视图(MVVM:View) +@property (nonatomic, strong) EPMomentListView *listView; -/// 刷新控件 -@property (nonatomic, strong) UIRefreshControl *refreshControl; - -/// 发布按钮 -@property (nonatomic, strong) UIButton *publishButton; - -// MARK: - Data - -/// 动态数据源(MomentsInfoModel 数组) -@property (nonatomic, strong) NSMutableArray *dataSource; - -/// 当前页码 -@property (nonatomic, assign) NSInteger currentPage; - -/// 是否正在加载 -@property (nonatomic, assign) BOOL isLoading; +/// 顶部固定文案 +@property (nonatomic, strong) UILabel *topTipLabel; @end @@ -48,7 +34,7 @@ self.title = @"动态"; [self setupUI]; - [self loadData]; + [self.listView reloadFirstPage]; NSLog(@"[EPMomentViewController] 页面加载完成"); } @@ -74,70 +60,29 @@ make.edges.mas_equalTo(self.view); }]; - // TableView - [self.view addSubview:self.tableView]; - [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.equalTo(self.view); + // 顶部固定文案 + [self.view addSubview:self.topTipLabel]; + [self.topTipLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(8); + make.left.equalTo(self.view).offset(20); + make.right.equalTo(self.view).offset(-20); }]; - // TODO: 调整为右上角 - [self.view addSubview:self.publishButton]; - [self.publishButton mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.view).offset(-20); - make.bottom.equalTo(self.view).offset(-100); // 避开 TabBar - make.size.mas_equalTo(CGSizeMake(56, 56)); + // 列表视图 + [self.view addSubview:self.listView]; + [self.listView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self.view); + make.top.equalTo(self.topTipLabel.mas_bottom).offset(8); }]; + // 右上角发布按钮 + UIBarButtonItem *publishItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(onPublishButtonTapped)]; + self.navigationItem.rightBarButtonItem = publishItem; + NSLog(@"[EPMomentViewController] UI 设置完成"); } -// MARK: - Data Loading - -- (void)loadData { - if (self.isLoading) return; - - self.isLoading = YES; - NSLog(@"[EPMomentViewController] 开始加载数据,页码: %ld", (long)self.currentPage); - - // 调用真实 API 加载动态列表 - NSString *page = [NSString stringWithFormat:@"%ld", (long)self.currentPage]; - NSString *pageSize = @"10"; - NSString *types = @"0,2"; // 类型:0=图片,2=文字 - - @kWeakify(self); - [Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { - @kStrongify(self); - self.isLoading = NO; - [self.refreshControl endRefreshing]; - - if (code == 200 && data.data) { - // 解析数据 - NSArray *list = [MomentsInfoModel mj_objectArrayWithKeyValuesArray:data.data]; - - if (list.count > 0) { - [self.dataSource addObjectsFromArray:list]; - self.currentPage++; - [self.tableView reloadData]; - NSLog(@"[EPMomentViewController] 加载成功,新增 %lu 条动态", (unsigned long)list.count); - } else { - NSLog(@"[EPMomentViewController] 没有更多数据"); - } - } else { - NSLog(@"[EPMomentViewController] 加载失败: code=%ld, msg=%@", (long)code, msg); - // 如果 API 失败,显示提示 - if (self.dataSource.count == 0) { - // 首次加载失败,显示空状态 - [self showAlertWithMessage:msg ?: @"加载失败"]; - } - } - } page:page pageSize:pageSize types:types]; -} - -- (void)onRefresh { - self.currentPage = 0; - [self.dataSource removeAllObjects]; - [self loadData]; -} +// 不再在 VC 内部直接发请求/维护分页 // MARK: - Actions @@ -155,108 +100,35 @@ [self presentViewController:alert animated:YES completion:nil]; } -// MARK: - UITableViewDataSource - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.dataSource.count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - EPMomentCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewMomentCell" forIndexPath:indexPath]; - - if (indexPath.row < self.dataSource.count) { - MomentsInfoModel *model = self.dataSource[indexPath.row]; - [cell configureWithModel:model]; - } - - return cell; -} - -// MARK: - UITableViewDelegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - NSLog(@"[EPMomentViewController] 点击动态: %ld", (long)indexPath.row); - // TODO: 跳转到详情页 - [self showAlertWithMessage:[NSString stringWithFormat:@"点击了第 %ld 条动态", (long)indexPath.row]]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return UITableViewAutomaticDimension; -} - -- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { - return 200; -} - -// 滚动到底部时加载更多 -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - CGFloat offsetY = scrollView.contentOffset.y; - CGFloat contentHeight = scrollView.contentSize.height; - CGFloat screenHeight = scrollView.frame.size.height; - - if (offsetY > contentHeight - screenHeight - 100 && !self.isLoading) { - [self loadData]; - } -} +// 列表点击回调由 listView 暴露 // MARK: - Lazy Loading -- (UITableView *)tableView { - if (!_tableView) { - _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; - _tableView.delegate = self; - _tableView.dataSource = self; - _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _tableView.backgroundColor = [UIColor clearColor]; // 透明背景,显示下层背景图 - _tableView.estimatedRowHeight = 200; - _tableView.rowHeight = UITableViewAutomaticDimension; - _tableView.showsVerticalScrollIndicator = NO; - _tableView.contentInset = UIEdgeInsetsMake(10, 0, 10, 0); - - // 注册 Cell - [_tableView registerClass:[EPMomentCell class] forCellReuseIdentifier:@"NewMomentCell"]; - - // 添加下拉刷新 - _tableView.refreshControl = self.refreshControl; +// Lazy + +- (EPMomentListView *)listView { + if (!_listView) { + _listView = [[EPMomentListView alloc] initWithFrame:CGRectZero]; + __weak typeof(self) weakSelf = self; + _listView.onSelectMoment = ^(NSInteger index) { + __strong typeof(weakSelf) self = weakSelf; + [self showAlertWithMessage:[NSString stringWithFormat:@"点击了第 %ld 条动态", (long)index]]; + }; } - return _tableView; + return _listView; } -- (UIRefreshControl *)refreshControl { - if (!_refreshControl) { - _refreshControl = [[UIRefreshControl alloc] init]; - [_refreshControl addTarget:self action:@selector(onRefresh) forControlEvents:UIControlEventValueChanged]; +- (UILabel *)topTipLabel { + if (!_topTipLabel) { + _topTipLabel = [UILabel new]; + _topTipLabel.numberOfLines = 0; + _topTipLabel.textColor = [UIColor whiteColor]; + _topTipLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightRegular]; + _topTipLabel.text = @"The disease is like a cruel ruler, measuring the true length of my life, but it is also like a lamp, illuminating the present that I have always ignored. Now I feel a strange freedom: since the end is clear, I can take every step with my whole heart."; } - return _refreshControl; + return _topTipLabel; } -- (UIButton *)publishButton { - if (!_publishButton) { - _publishButton = [UIButton buttonWithType:UIButtonTypeCustom]; - _publishButton.backgroundColor = [UIColor colorWithRed:0.2 green:0.6 blue:0.86 alpha:1.0]; // 主色调 - _publishButton.layer.cornerRadius = 28; - _publishButton.layer.shadowColor = [UIColor blackColor].CGColor; - _publishButton.layer.shadowOffset = CGSizeMake(0, 2); - _publishButton.layer.shadowOpacity = 0.3; - _publishButton.layer.shadowRadius = 4; - - // 设置图标(暂时使用文字) - [_publishButton setTitle:@"+" forState:UIControlStateNormal]; - _publishButton.titleLabel.font = [UIFont systemFontOfSize:32 weight:UIFontWeightLight]; - [_publishButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [_publishButton addTarget:self action:@selector(onPublishButtonTapped) forControlEvents:UIControlEventTouchUpInside]; - } - return _publishButton; -} - -- (NSMutableArray *)dataSource { - if (!_dataSource) { - _dataSource = [NSMutableArray array]; - } - return _dataSource; -} +// 无数据源属性 @end diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h new file mode 100644 index 0000000..7125fdc --- /dev/null +++ b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.h @@ -0,0 +1,36 @@ +// +// EPMomentAPIHelper.h +// YuMi +// +// Created by AI on 2025-10-10. +// + +#import +#import "BaseMvpPresenter.h" +#import "MomentsInfoModel.h" +#import "MomentsListInfoModel.h" + +NS_ASSUME_NONNULL_BEGIN + +/// 推荐/我的动态列表数据源类型 +typedef NS_ENUM(NSInteger, EPMomentListSourceType) { + EPMomentListSourceTypeRecommend = 0, + EPMomentListSourceTypeMine = 1 +}; + +/// 统一封装 Moments 列表 API +@interface EPMomentAPIHelper : BaseMvpPresenter + +/// 拉取动态列表(默认 types:"0,2" 图片+文字) +/// page 从 0 开始,pageSize > 0 +/// completion 返回 data 数组(字典数组) 或错误 +- (void)fetchMomentsWithType:(EPMomentListSourceType)sourceType + page:(NSInteger)page + pageSize:(NSInteger)pageSize + completion:(void (^)(NSArray * _Nullable list, NSInteger code, NSString * _Nullable msg))completion; + +@end + +NS_ASSUME_NONNULL_END + + diff --git a/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m new file mode 100644 index 0000000..3976008 --- /dev/null +++ b/YuMi/E-P/NewMoments/Services/EPMomentAPIHelper.m @@ -0,0 +1,58 @@ +// +// EPMomentAPIHelper.m +// YuMi +// +// Created by AI on 2025-10-10. +// + +#import +#import "EPMomentAPIHelper.h" +#import "Api+Moments.h" +#import "AccountInfoStorage.h" +#import "BaseModel.h" + + +@implementation EPMomentAPIHelper + +- (void)fetchMomentsWithType:(EPMomentListSourceType)sourceType + page:(NSInteger)page + pageSize:(NSInteger)pageSize + completion:(void (^)(NSArray * _Nullable list, NSInteger code, NSString * _Nullable msg))completion { + // 兼容后端从 1 开始分页:若收到 0 则转成 1 + NSInteger requestPage = page <= 0 ? 1 : page; + NSString *pageStr = [NSString stringWithFormat:@"%ld", (long)requestPage]; + NSString *pageSizeStr = [NSString stringWithFormat:@"%ld", (long)pageSize]; + NSString *types = @"0,2"; // 图片+文字 + + if (sourceType == EPMomentListSourceTypeRecommend) { +// [Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { +// if (code == 200 && data.data) { +// NSArray *array = [MomentsInfoModel modelsWithArray:data.data]; +// if (completion) completion(array ?: @[], 200, @"success"); +// } else { +// if (completion) completion(@[], code, msg); +// } +// } page:pageStr pageSize:pageSizeStr types:types]; + [Api momentsLatestList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + MomentsListInfoModel *listInfo = [MomentsListInfoModel modelWithDictionary:data.data]; + if (completion) completion(listInfo.dynamicList ?: @[], 200, @"success"); + } fail:^(NSInteger code, NSString * _Nullable msg) { + if (completion) completion(@[], code, msg); + }] dynamicId:@"" pageSize:pageSizeStr types:types]; + + } else { + // 预留:我的动态列表(暂时复用推荐接口,后续替换为真正的“我的动态”API) + [Api momentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200 && data.data) { + NSArray *array = [MomentsInfoModel modelsWithArray:data.data]; + if (completion) completion(array ?: @[], 200, @"success"); + } else { + if (completion) completion(@[], code, msg); + } + } page:pageStr pageSize:pageSizeStr types:types]; + } +} + +@end + + diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.h b/YuMi/E-P/NewMoments/Views/EPMomentListView.h new file mode 100644 index 0000000..ae4a1b1 --- /dev/null +++ b/YuMi/E-P/NewMoments/Views/EPMomentListView.h @@ -0,0 +1,34 @@ +// +// EPMomentListView.h +// YuMi +// +// Created by AI on 2025-10-10. +// + +#import +#import "EPMomentAPIHelper.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MomentsInfoModel; + +/// 承载 Moments 列表与分页刷新的视图 +@interface EPMomentListView : UIView + +/// 当前数据源(外部可读) +@property (nonatomic, strong, readonly) NSArray *rawList; + +/// 列表类型:推荐 / 我的 +@property (nonatomic, assign) EPMomentListSourceType sourceType; + +/// 外部可设置:当某一项被点击 +@property (nonatomic, copy) void (^onSelectMoment)(NSInteger index); + +/// 重新加载(刷新到第一页) +- (void)reloadFirstPage; + +@end + +NS_ASSUME_NONNULL_END + + diff --git a/YuMi/E-P/NewMoments/Views/EPMomentListView.m b/YuMi/E-P/NewMoments/Views/EPMomentListView.m new file mode 100644 index 0000000..0dc385a --- /dev/null +++ b/YuMi/E-P/NewMoments/Views/EPMomentListView.m @@ -0,0 +1,143 @@ +// +// EPMomentListView.m +// YuMi +// +// Created by AI on 2025-10-10. +// + +#import +#import "EPMomentListView.h" +#import "EPMomentCell.h" + + +@interface EPMomentListView () + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) UIRefreshControl *refreshControl; +@property (nonatomic, strong) NSMutableArray *mutableRawList; +@property (nonatomic, strong) EPMomentAPIHelper *api; +@property (nonatomic, assign) NSInteger currentPage; +@property (nonatomic, assign) BOOL isLoading; + +@end + +@implementation EPMomentListView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + _api = [[EPMomentAPIHelper alloc] init]; + _mutableRawList = [NSMutableArray array]; + _currentPage = 0; // 若后端从1开始,这里会在首次请求时自增到1 + _sourceType = EPMomentListSourceTypeRecommend; + + [self addSubview:self.tableView]; + [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + } + return self; +} + +- (NSArray *)rawList { + return [self.mutableRawList copy]; +} + +- (void)reloadFirstPage { + self.currentPage = 0; + [self.mutableRawList removeAllObjects]; + [self.tableView reloadData]; + [self requestNextPage]; +} + +- (void)requestNextPage { + if (self.isLoading) return; + self.isLoading = YES; + + NSLog(@"[EPMomentListView] 请求页码: %ld", (long)self.currentPage); + @kWeakify(self); + [self.api fetchMomentsWithType:self.sourceType page:self.currentPage pageSize:20 completion:^(NSArray * _Nullable list, NSInteger code, NSString * _Nullable msg) { + @kStrongify(self); + self.isLoading = NO; + [self.refreshControl endRefreshing]; + NSLog(@"[EPMomentListView] 返回 code=%ld, count=%lu", (long)code, (unsigned long)list.count); + if (code == 200 && list.count > 0) { + [self.mutableRawList addObjectsFromArray:list]; + self.currentPage++; + [self.tableView reloadData]; + } else if (code == 200 && list.count == 0 && self.currentPage == 0) { + // 如果第一页就为空,尝试从1开始(兼容某些后端从1计数) + self.currentPage = 1; + [self requestNextPage]; + } + }]; +} + +#pragma mark - UITableView + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.mutableRawList.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + EPMomentCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewMomentCell" forIndexPath:indexPath]; + if (indexPath.row < self.mutableRawList.count) { + MomentsInfoModel *model = [self.mutableRawList xpSafeObjectAtIndex:indexPath.row]; + [cell configureWithModel:model]; + } + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 200; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (self.onSelectMoment) self.onSelectMoment(indexPath.row); +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + CGFloat offsetY = scrollView.contentOffset.y; + CGFloat contentHeight = scrollView.contentSize.height; + CGFloat screenHeight = scrollView.frame.size.height; + if (offsetY > contentHeight - screenHeight - 100 && !self.isLoading) { + [self requestNextPage]; + } +} + +#pragma mark - Lazy + +- (UITableView *)tableView { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _tableView.backgroundColor = [UIColor clearColor]; + _tableView.estimatedRowHeight = 200; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.showsVerticalScrollIndicator = NO; + _tableView.contentInset = UIEdgeInsetsMake(10, 0, 10, 0); + [_tableView registerClass:[EPMomentCell class] forCellReuseIdentifier:@"NewMomentCell"]; + _tableView.refreshControl = self.refreshControl; + } + return _tableView; +} + +- (UIRefreshControl *)refreshControl { + if (!_refreshControl) { + _refreshControl = [[UIRefreshControl alloc] init]; + [_refreshControl addTarget:self action:@selector(reloadFirstPage) forControlEvents:UIControlEventValueChanged]; + } + return _refreshControl; +} + +@end + + diff --git a/YuMi/E-P/NewTabBar/EPTabBarController.swift b/YuMi/E-P/NewTabBar/EPTabBarController.swift index 7d5824a..ef0568b 100644 --- a/YuMi/E-P/NewTabBar/EPTabBarController.swift +++ b/YuMi/E-P/NewTabBar/EPTabBarController.swift @@ -43,6 +43,9 @@ import SnapKit // 隐藏原生 TabBar self.tabBar.isHidden = true + // 设置 delegate 以完全控制切换行为 + self.delegate = self + setupCustomFloatingTabBar() setupGlobalManagers() setupInitialViewControllers() @@ -111,14 +114,12 @@ import SnapKit selectedImage: "tab_moment_on", tag: 0 ) - momentButton.isSelected = true let mineButton = createTabButton( normalImage: "tab_mine_off", selectedImage: "tab_mine_on", tag: 1 ) - mineButton.isSelected = true tabButtons = [momentButton, mineButton] @@ -144,35 +145,35 @@ import SnapKit private func createTabButton(normalImage: String, selectedImage: String, tag: Int) -> UIButton { let button = UIButton(type: .custom) button.tag = tag - - // 存储图片名称到 button,方便后续切换 - button.accessibilityLabel = normalImage - button.accessibilityHint = selectedImage + button.adjustsImageWhenHighlighted = false // 禁用高亮效果,避免闪烁 // 尝试设置自定义图片,如果不存在则使用 SF Symbols - if let normalImg = UIImage(named: normalImage), let _ = UIImage(named: selectedImage) { - // 使用自定义图片(初始显示 off 图片) + if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { + // 正确设置:分别为 normal 和 selected 状态设置图片 button.setImage(normalImg, for: .normal) + button.setImage(selectedImg, for: .selected) } else { // 使用 SF Symbols 作为备用 let fallbackIcons = ["sparkles", "person.circle"] let iconName = fallbackIcons[tag] let imageConfig = UIImage.SymbolConfiguration(pointSize: 24, weight: .medium) + let normalIcon = UIImage(systemName: iconName, withConfiguration: imageConfig) - button.setImage(UIImage(systemName: iconName, withConfiguration: imageConfig), for: .normal) + button.setImage(normalIcon, for: .normal) + button.setImage(normalIcon, for: .selected) button.tintColor = .white.withAlphaComponent(0.6) } // 图片渲染模式 button.imageView?.contentMode = .scaleAspectFit - // 移除标题,只使用图片 + // 移除标题 button.setTitle(nil, for: .normal) button.setTitle(nil, for: .selected) // 设置图片大小约束 button.imageView?.snp.makeConstraints { make in - make.size.equalTo(28) // 图标大小 + make.size.equalTo(28) } button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) @@ -191,8 +192,10 @@ import SnapKit // 先更新按钮状态 updateTabButtonStates(selectedIndex: newIndex) - // 再切换 ViewController(使用动画) - selectedIndex = newIndex + // 禁用 UITabBarController 的默认切换动画,避免闪烁 + UIView.performWithoutAnimation { + selectedIndex = newIndex + } let tabNames = ["动态", "我的"] NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") @@ -205,32 +208,23 @@ import SnapKit for (index, button) in tabButtons.enumerated() { let isSelected = (index == selectedIndex) + + // 直接设置 isSelected 属性即可,图片会自动切换 button.isSelected = isSelected - // 更新图片状态 - if let normalImageName = button.accessibilityLabel, - let selectedImageName = button.accessibilityHint { - // 使用自定义图片 - let imageName = isSelected ? selectedImageName : normalImageName - if let image = UIImage(named: imageName) { - button.setImage(image, for: .normal) - } else { - // 如果自定义图片不存在,使用 SF Symbols - button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) - } - } else { - // 使用 SF Symbols(备用方案) + // SF Symbols 的情况需要手动更新 tintColor + if button.currentImage?.isSymbolImage == true { button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) } - // 选中状态动画 - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseInOut], animations: { + // 选中状态缩放动画 + UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseOut], animations: { button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity - }, completion: nil) + }) } - // 延迟恢复按钮交互,避免动画期间的重复点击 - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + // 延迟恢复按钮交互 + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { self.tabButtons.forEach { $0.isUserInteractionEnabled = true } } } @@ -317,22 +311,34 @@ import SnapKit !(viewControllers?[0] is EPMomentViewController) || !(viewControllers?[1] is EPMineViewController) { - // 创建真实的 ViewController(OC 类) + // 创建真实的 ViewController(OC 类),并使用导航控制器包裹以显示标题/右上按钮 let momentVC = EPMomentViewController() - momentVC.tabBarItem = createTabBarItem( + momentVC.title = "动态" + let momentNav = UINavigationController(rootViewController: momentVC) + momentNav.navigationBar.isTranslucent = true + momentNav.navigationBar.setBackgroundImage(UIImage(), for: .default) + momentNav.navigationBar.shadowImage = UIImage() + momentNav.view.backgroundColor = .clear + momentNav.tabBarItem = createTabBarItem( title: "动态", normalImage: "tab_moment_normal", selectedImage: "tab_moment_selected" ) - + let mineVC = EPMineViewController() - mineVC.tabBarItem = createTabBarItem( + mineVC.title = "我的" + let mineNav = UINavigationController(rootViewController: mineVC) + mineNav.navigationBar.isTranslucent = true + mineNav.navigationBar.setBackgroundImage(UIImage(), for: .default) + mineNav.navigationBar.shadowImage = UIImage() + mineNav.view.backgroundColor = .clear + mineNav.tabBarItem = createTabBarItem( title: "我的", normalImage: "tab_mine_normal", selectedImage: "tab_mine_selected" ) - viewControllers = [momentVC, mineVC] + viewControllers = [momentNav, mineNav] NSLog("[EPTabBarController] 登录后 ViewControllers 创建完成 - Moment & Mine") } @@ -347,6 +353,21 @@ extension EPTabBarController: UITabBarControllerDelegate { override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { NSLog("[EPTabBarController] 选中 Tab: \(item.title ?? "Unknown")") } + + /// 禁用系统默认的切换动画 + func tabBarController(_ tabBarController: UITabBarController, + animationControllerForTransitionFrom fromVC: UIViewController, + to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + // 返回 nil 表示不使用动画 + return nil + } + + /// 完全控制是否允许切换 + func tabBarController(_ tabBarController: UITabBarController, + shouldSelect viewController: UIViewController) -> Bool { + // 允许切换,但通过返回 nil 的 animationController 来禁用动画 + return true + } } // MARK: - OC Compatibility diff --git a/YuMi/Modules/NewTabBar/EPTabBarController.swift b/YuMi/Modules/NewTabBar/EPTabBarController.swift deleted file mode 100644 index b4b784f..0000000 --- a/YuMi/Modules/NewTabBar/EPTabBarController.swift +++ /dev/null @@ -1,374 +0,0 @@ -// -// EPTabBarController.swift -// YuMi -// -// Created by AI on 2025-10-09. -// Copyright © 2025 YuMi. All rights reserved. -// - -import UIKit -import SnapKit - -/// EP 系列 TabBar 控制器 -/// 悬浮设计 + 液态玻璃效果,只包含 Moment 和 Mine 两个 Tab -@objc class EPTabBarController: UITabBarController { - - // MARK: - Properties - - /// 全局事件管理器 - private var globalEventManager: GlobalEventManager? - - /// 是否已登录 - private var isLoggedIn: Bool = false - - /// 自定义悬浮 TabBar 容器 - private var customTabBarView: UIView! - - /// 毛玻璃背景视图 - private var tabBarBackgroundView: UIVisualEffectView! - - /// Tab 按钮数组 - private var tabButtons: [UIButton] = [] - - // MARK: - Lifecycle - - override func viewDidLoad() { - super.viewDidLoad() - - // 测试域名配置 - #if DEBUG - APIConfig.testEncryption() - #endif - - // 隐藏原生 TabBar - self.tabBar.isHidden = true - - // 设置 delegate 以完全控制切换行为 - self.delegate = self - - setupCustomFloatingTabBar() - setupGlobalManagers() - setupInitialViewControllers() - - NSLog("[EPTabBarController] 悬浮 TabBar 初始化完成") - } - - deinit { - globalEventManager?.removeAllDelegates() - NSLog("[EPTabBarController] 已释放") - } - - // MARK: - Setup - - /// 设置自定义悬浮 TabBar - private func setupCustomFloatingTabBar() { - // 创建悬浮容器 - customTabBarView = UIView() - customTabBarView.translatesAutoresizingMaskIntoConstraints = false - customTabBarView.backgroundColor = .clear - view.addSubview(customTabBarView) - - // 液态玻璃/毛玻璃效果 - let effect: UIVisualEffect - if #available(iOS 26.0, *) { - // iOS 26+ 使用液态玻璃(Material) - effect = UIGlassEffect() - } else { - // iOS 13-17 使用毛玻璃 - effect = UIBlurEffect(style: .systemMaterial) - } - - tabBarBackgroundView = UIVisualEffectView(effect: effect) - tabBarBackgroundView.translatesAutoresizingMaskIntoConstraints = false - tabBarBackgroundView.layer.cornerRadius = 28 - tabBarBackgroundView.layer.masksToBounds = true - - // 添加边框 - tabBarBackgroundView.layer.borderWidth = 0.5 - tabBarBackgroundView.layer.borderColor = UIColor.white.withAlphaComponent(0.2).cgColor - - customTabBarView.addSubview(tabBarBackgroundView) - - // 简化的布局约束(类似 Masonry 风格) - customTabBarView.snp.makeConstraints { make in - make.leading.equalTo(view).offset(16) - make.trailing.equalTo(view).offset(-16) - make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-12) - make.height.equalTo(64) - } - - tabBarBackgroundView.snp.makeConstraints { make in - make.edges.equalTo(customTabBarView) - } - - // 添加 Tab 按钮 - setupTabButtons() - - NSLog("[EPTabBarController] 悬浮 TabBar 设置完成") - } - - /// 设置 Tab 按钮 - private func setupTabButtons() { - let momentButton = createTabButton( - normalImage: "tab_moment_off", - selectedImage: "tab_moment_on", - tag: 0 - ) - - let mineButton = createTabButton( - normalImage: "tab_mine_off", - selectedImage: "tab_mine_on", - tag: 1 - ) - - tabButtons = [momentButton, mineButton] - - let stackView = UIStackView(arrangedSubviews: tabButtons) - stackView.axis = .horizontal - stackView.distribution = .fillEqually - stackView.spacing = 20 - stackView.translatesAutoresizingMaskIntoConstraints = false - tabBarBackgroundView.contentView.addSubview(stackView) - - stackView.snp.makeConstraints { make in - make.top.equalTo(tabBarBackgroundView).offset(8) - make.leading.equalTo(tabBarBackgroundView).offset(20) - make.trailing.equalTo(tabBarBackgroundView).offset(-20) - make.bottom.equalTo(tabBarBackgroundView).offset(-8) - } - - // 默认选中第一个 - updateTabButtonStates(selectedIndex: 0) - } - - /// 创建 Tab 按钮 - private func createTabButton(normalImage: String, selectedImage: String, tag: Int) -> UIButton { - let button = UIButton(type: .custom) - button.tag = tag - button.adjustsImageWhenHighlighted = false // 禁用高亮效果,避免闪烁 - - // 尝试设置自定义图片,如果不存在则使用 SF Symbols - if let normalImg = UIImage(named: normalImage), let selectedImg = UIImage(named: selectedImage) { - // 正确设置:分别为 normal 和 selected 状态设置图片 - button.setImage(normalImg, for: .normal) - button.setImage(selectedImg, for: .selected) - } else { - // 使用 SF Symbols 作为备用 - let fallbackIcons = ["sparkles", "person.circle"] - let iconName = fallbackIcons[tag] - let imageConfig = UIImage.SymbolConfiguration(pointSize: 24, weight: .medium) - let normalIcon = UIImage(systemName: iconName, withConfiguration: imageConfig) - - button.setImage(normalIcon, for: .normal) - button.setImage(normalIcon, for: .selected) - button.tintColor = .white.withAlphaComponent(0.6) - } - - // 图片渲染模式 - button.imageView?.contentMode = .scaleAspectFit - - // 移除标题 - button.setTitle(nil, for: .normal) - button.setTitle(nil, for: .selected) - - // 设置图片大小约束 - button.imageView?.snp.makeConstraints { make in - make.size.equalTo(28) - } - - button.addTarget(self, action: #selector(tabButtonTapped(_:)), for: .touchUpInside) - return button - } - - /// Tab 按钮点击事件 - @objc private func tabButtonTapped(_ sender: UIButton) { - let newIndex = sender.tag - - // 如果点击的是当前已选中的 tab,不做任何操作 - if newIndex == selectedIndex { - return - } - - // 先更新按钮状态 - updateTabButtonStates(selectedIndex: newIndex) - - // 禁用 UITabBarController 的默认切换动画,避免闪烁 - UIView.performWithoutAnimation { - selectedIndex = newIndex - } - - let tabNames = ["动态", "我的"] - NSLog("[EPTabBarController] 选中 Tab: \(tabNames[newIndex])") - } - - /// 更新 Tab 按钮状态 - private func updateTabButtonStates(selectedIndex: Int) { - // 禁用按钮交互,避免快速点击 - tabButtons.forEach { $0.isUserInteractionEnabled = false } - - for (index, button) in tabButtons.enumerated() { - let isSelected = (index == selectedIndex) - - // 直接设置 isSelected 属性即可,图片会自动切换 - button.isSelected = isSelected - - // SF Symbols 的情况需要手动更新 tintColor - if button.currentImage?.isSymbolImage == true { - button.tintColor = isSelected ? .white : .white.withAlphaComponent(0.6) - } - - // 选中状态缩放动画 - UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseOut], animations: { - button.transform = isSelected ? CGAffineTransform(scaleX: 1.1, y: 1.1) : .identity - }) - } - - // 延迟恢复按钮交互 - DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { - self.tabButtons.forEach { $0.isUserInteractionEnabled = true } - } - } - - /// 设置全局管理器 - private func setupGlobalManagers() { - globalEventManager = GlobalEventManager.shared() - globalEventManager?.setupSDKDelegates() - - // TODO: v0.2 版本暂时禁用房间最小化视图(无房间功能) - // 后续版本可通过 Build Configuration 或版本号判断是否启用 - /* - if let containerView = view { - globalEventManager?.setupRoomMiniView(on: containerView) - } - */ - - // 注册社交分享回调 - globalEventManager?.registerSocialShareCallback() - - NSLog("[EPTabBarController] 全局管理器设置完成(v0.2 - 无 MiniRoom)") - } - - /// 设置初始 ViewController(未登录状态) - private func setupInitialViewControllers() { - // TODO: 暂时使用空白页面占位 - let blankVC1 = UIViewController() - blankVC1.view.backgroundColor = .white - blankVC1.tabBarItem = createTabBarItem( - title: "动态", - normalImage: "tab_moment_normal", - selectedImage: "tab_moment_selected" - ) - - let blankVC2 = UIViewController() - blankVC2.view.backgroundColor = .white - blankVC2.tabBarItem = createTabBarItem( - title: "我的", - normalImage: "tab_mine_normal", - selectedImage: "tab_mine_selected" - ) - - viewControllers = [blankVC1, blankVC2] - selectedIndex = 0 - - NSLog("[EPTabBarController] 初始 ViewControllers 设置完成") - } - - /// 创建 TabBarItem - /// - Parameters: - /// - title: 标题 - /// - normalImage: 未选中图标名称 - /// - selectedImage: 选中图标名称 - /// - Returns: UITabBarItem - private func createTabBarItem(title: String, normalImage: String, selectedImage: String) -> UITabBarItem { - let item = UITabBarItem( - title: title, - image: UIImage(named: normalImage)?.withRenderingMode(.alwaysOriginal), - selectedImage: UIImage(named: selectedImage)?.withRenderingMode(.alwaysOriginal) - ) - return item - } - - // MARK: - Public Methods - - /// 登录成功后刷新 TabBar - /// - Parameter isLogin: 是否已登录 - func refreshTabBar(isLogin: Bool) { - isLoggedIn = isLogin - - if isLogin { - setupLoggedInViewControllers() - } else { - setupInitialViewControllers() - } - - NSLog("[EPTabBarController] TabBar 已刷新,登录状态: \(isLogin)") - } - - /// 设置登录后的 ViewControllers - private func setupLoggedInViewControllers() { - // 只在 viewControllers 为空或不是正确类型时才创建 - if viewControllers?.count != 2 || - !(viewControllers?[0] is EPMomentViewController) || - !(viewControllers?[1] is EPMineViewController) { - - // 创建真实的 ViewController(OC 类) - let momentVC = EPMomentViewController() - momentVC.tabBarItem = createTabBarItem( - title: "动态", - normalImage: "tab_moment_normal", - selectedImage: "tab_moment_selected" - ) - - let mineVC = EPMineViewController() - mineVC.tabBarItem = createTabBarItem( - title: "我的", - normalImage: "tab_mine_normal", - selectedImage: "tab_mine_selected" - ) - - viewControllers = [momentVC, mineVC] - NSLog("[EPTabBarController] 登录后 ViewControllers 创建完成 - Moment & Mine") - } - - selectedIndex = 0 - } -} - -// MARK: - UITabBarControllerDelegate - -extension EPTabBarController: UITabBarControllerDelegate { - - override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { - NSLog("[EPTabBarController] 选中 Tab: \(item.title ?? "Unknown")") - } - - /// 禁用系统默认的切换动画 - func tabBarController(_ tabBarController: UITabBarController, - animationControllerForTransitionFrom fromVC: UIViewController, - to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { - // 返回 nil 表示不使用动画 - return nil - } - - /// 完全控制是否允许切换 - func tabBarController(_ tabBarController: UITabBarController, - shouldSelect viewController: UIViewController) -> Bool { - // 允许切换,但通过返回 nil 的 animationController 来禁用动画 - return true - } -} - -// MARK: - OC Compatibility - -extension EPTabBarController { - - /// OC 兼容:创建实例的工厂方法 - @objc static func create() -> EPTabBarController { - return EPTabBarController() - } - - /// OC 兼容:刷新 TabBar 方法 - @objc func refreshTabBarWithIsLogin(_ isLogin: Bool) { - refreshTabBar(isLogin: isLogin) - } -} diff --git a/YuMi/Modules/YMMonents/Api/Api+Moments.m b/YuMi/Modules/YMMonents/Api/Api+Moments.m index e1c9cc4..4b1165c 100644 --- a/YuMi/Modules/YMMonents/Api/Api+Moments.m +++ b/YuMi/Modules/YMMonents/Api/Api+Moments.m @@ -17,8 +17,7 @@ /// @param pageSize 一页的个数 /// @param types 类型 0,2 + (void)momentsRecommendList:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize types:(NSString *)types { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvcmVjb21tZW5kRHluYW1pY3M="];///dynamic/square/recommendDynamics - [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, types, nil]; + [self makeRequest:@"dynamic/square/recommendDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, types, nil]; } /// 朋友圈动态最新列表 @@ -27,8 +26,7 @@ /// @param pageSize 一页的个数 /// @param types 类型 0,2 + (void)momentsLatestList:(HttpRequestHelperCompletion)completion dynamicId:(NSString *)dynamicId pageSize:(NSString *)pageSize types:(NSString *)types { - NSString * fang = [NSString stringFromBase64String:@"ZHluYW1pYy9zcXVhcmUvbGF0ZXN0RHluYW1pY3M="];///dynamic/square/latestDynamics - [self makeRequest:fang method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; + [self makeRequest:@"dynamic/square/latestDynamics" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dynamicId, pageSize, types, nil]; } /// 朋友圈动态关注列表