
- 在Package.swift中注释掉旧的swift-composable-architecture依赖,并添加swift-case-paths依赖。 - 在Podfile中将iOS平台版本更新至16.0,并移除QCloudCOSXML/Transfer依赖,改为使用QCloudCOSXML。 - 更新Podfile.lock以反映依赖变更,确保项目依赖的准确性。 - 新增架构分析需求文档,明确项目架构评估和改进建议。 - 在多个文件中实现async/await语法,提升异步操作的可读性和性能。 - 更新日志输出方法,确保在调试模式下提供一致的调试信息。 - 优化多个视图组件,提升用户体验和代码可维护性。
176 lines
6.7 KiB
Swift
176 lines
6.7 KiB
Swift
import Foundation
|
||
import ComposableArchitecture
|
||
|
||
@Reducer
|
||
struct FeedFeature {
|
||
@ObservableState
|
||
struct State: Equatable {
|
||
var moments: [MomentsInfo] = []
|
||
var isLoading = false
|
||
var hasMoreData = true
|
||
var error: String?
|
||
var nextDynamicId: Int = 0
|
||
|
||
// 是否已初始化
|
||
var isInitialized = false
|
||
|
||
// CreateFeedView 相关状态
|
||
var isShowingCreateFeed = false
|
||
var createFeedState: CreateFeedFeature.State? = nil
|
||
}
|
||
|
||
enum Action {
|
||
case onAppear
|
||
case loadLatestMoments
|
||
case loadMoreMoments
|
||
case momentsResponse(TaskResult<MomentsLatestResponse>)
|
||
case clearError
|
||
case retryLoad
|
||
|
||
// CreateFeedView 相关 Action
|
||
case showCreateFeed
|
||
case dismissCreateFeed
|
||
case createFeedCompleted
|
||
indirect case createFeed(CreateFeedFeature.Action)
|
||
}
|
||
|
||
@Dependency(\.apiService) var apiService
|
||
|
||
var body: some ReducerOf<Self> {
|
||
Reduce { state, action in
|
||
switch action {
|
||
case .onAppear:
|
||
#if DEBUG
|
||
return .none
|
||
#endif
|
||
|
||
// 只在首次出现时触发加载
|
||
guard !state.isInitialized else { return .none }
|
||
state.isInitialized = true
|
||
return .send(.loadLatestMoments)
|
||
|
||
case .loadLatestMoments:
|
||
// 加载最新数据(下拉刷新)
|
||
state.isLoading = true
|
||
state.error = nil
|
||
|
||
let request = LatestDynamicsRequest(
|
||
dynamicId: "", // 首次加载传空字符串
|
||
pageSize: 20,
|
||
types: [.text, .picture]
|
||
)
|
||
|
||
return .run { send in
|
||
await send(.momentsResponse(TaskResult {
|
||
try await apiService.request(request)
|
||
}))
|
||
}
|
||
|
||
case .loadMoreMoments:
|
||
// 加载更多数据(分页加载)
|
||
guard !state.isLoading && state.hasMoreData else { return .none }
|
||
|
||
state.isLoading = true
|
||
state.error = nil
|
||
|
||
let request = LatestDynamicsRequest(
|
||
dynamicId: state.nextDynamicId == 0 ? "" : String(state.nextDynamicId),
|
||
pageSize: 20,
|
||
types: [.text, .picture]
|
||
)
|
||
|
||
return .run { send in
|
||
await send(.momentsResponse(TaskResult {
|
||
try await apiService.request(request)
|
||
}))
|
||
}
|
||
|
||
case let .momentsResponse(.success(response)):
|
||
state.isLoading = false
|
||
|
||
// 添加调试日志
|
||
debugInfoSync("📱 FeedFeature: API 响应成功")
|
||
debugInfoSync("📱 FeedFeature: response.code = \(response.code)")
|
||
debugInfoSync("📱 FeedFeature: response.message = \(response.message)")
|
||
debugInfoSync("📱 FeedFeature: response.data = \(response.data != nil ? "有数据" : "无数据")")
|
||
|
||
// 检查响应状态
|
||
guard response.code == 200, let data = response.data else {
|
||
let errorMsg = response.message.isEmpty ? "获取动态失败" : response.message
|
||
state.error = errorMsg
|
||
debugErrorSync("❌ FeedFeature: API 响应失败 - code: \(response.code), message: \(errorMsg)")
|
||
return .none
|
||
}
|
||
|
||
// 添加数据调试日志
|
||
debugInfoSync("📱 FeedFeature: data.dynamicList.count = \(data.dynamicList.count)")
|
||
debugInfoSync("📱 FeedFeature: data.nextDynamicId = \(data.nextDynamicId)")
|
||
|
||
// 判断是刷新还是加载更多
|
||
let isRefresh = state.nextDynamicId == 0
|
||
debugInfoSync("📱 FeedFeature: isRefresh = \(isRefresh)")
|
||
|
||
if isRefresh {
|
||
// 刷新:替换所有数据
|
||
state.moments = data.dynamicList
|
||
debugInfoSync(" FeedFeature: 刷新数据,moments.count = \(state.moments.count)")
|
||
} else {
|
||
// 加载更多:追加到现有数据
|
||
let oldCount = state.moments.count
|
||
state.moments.append(contentsOf: data.dynamicList)
|
||
debugInfoSync(" FeedFeature: 加载更多,moments.count: \(oldCount) -> \(state.moments.count)")
|
||
}
|
||
|
||
// 更新分页状态
|
||
state.nextDynamicId = data.nextDynamicId
|
||
state.hasMoreData = !data.dynamicList.isEmpty
|
||
|
||
debugInfoSync("📱 FeedFeature: 更新完成 - nextDynamicId: \(state.nextDynamicId), hasMoreData: \(state.hasMoreData)")
|
||
return .none
|
||
|
||
case let .momentsResponse(.failure(error)):
|
||
state.isLoading = false
|
||
state.error = error.localizedDescription
|
||
debugErrorSync("❌ FeedFeature: API 请求失败 - \(error.localizedDescription)")
|
||
return .none
|
||
|
||
case .clearError:
|
||
state.error = nil
|
||
return .none
|
||
|
||
case .retryLoad:
|
||
// 重试加载
|
||
if state.moments.isEmpty {
|
||
return .send(.loadLatestMoments)
|
||
} else {
|
||
return .send(.loadMoreMoments)
|
||
}
|
||
|
||
case .showCreateFeed:
|
||
state.isShowingCreateFeed = true
|
||
// 初始化 createFeedState
|
||
state.createFeedState = CreateFeedFeature.State()
|
||
return .none
|
||
|
||
case .dismissCreateFeed:
|
||
state.isShowingCreateFeed = false
|
||
state.createFeedState = nil
|
||
return .none
|
||
|
||
case .createFeedCompleted:
|
||
state.isShowingCreateFeed = false
|
||
state.createFeedState = nil
|
||
// 发布完成后刷新动态列表
|
||
return .send(.loadLatestMoments)
|
||
case .createFeed:
|
||
// 子模块 Action 由作用域 reducer 处理
|
||
return .none
|
||
}
|
||
}
|
||
// 子模块作用域 reducer
|
||
ifLet(\State.createFeedState, action: /Action.createFeed) {
|
||
CreateFeedFeature()
|
||
}
|
||
}
|
||
}
|