我正在尝试创建一个提要,但现在使用 JSON 中的模拟数据。但是,速度非常慢。
以下是我对 Feed 的看法
struct FeedView: View {
@StateObject private var viewModel = FeedViewModel()
@State private var isFeedSelected: Bool = true
var body: some View {
NavigationView {
ScrollView {
LazyVStack {
if(isFeedSelected) {
ForEach(viewModel.feed) { post in
PostItemView(item: post)
}
} else {
ForEach(viewModel.classFeed) { classItem in
Text(classItem.userName)
}
}
}
}
.padding([.top], 10)
.task {
if(isFeedSelected) {
await viewModel.getFeed()
} else {
await viewModel.getClasses()
}
}
ViewModel如下:
final class FeedViewModel: ObservableObject {
var feedUseCase: FeedUseCase
@Published var feed: [FeedItemEntity] = []
@Published var classFeed: [ClassItemEntity] = []
@Published var state: FeedState = .na
@Published var hasError: Bool = false
init() {
self.feedUseCase = FeedUseCase.shared
setupErrorSubscription()
}
func getFeed() async {
Task.detached {
let result = await self.feedUseCase.getFeed()
switch(result) {
case .success(let feed):
self.feed = feed
case .failure(let error):
self.feed = []
self.hasError = true
}
}
}
func getClasses() async {
Task.detached {
let result = await self.feedUseCase.getClasses()
switch(result) {
case .success(let classes):
self.classFeed = classes
case .failure(let error):
self.classFeed = []
self.hasError = true
}
}
}
}
用例正在这样做:
enum UseCaseError: Error{
case networkError, decodingError
}
final class FeedUseCase {
static let shared = FeedUseCase()
let repository: FeedRepositoryProtocol
init() {
self.repository = FeedRepository.shared
}
func getFeed() async -> Result<[FeedItemEntity], UseCaseError> {
do {
let feed = try await repository.getFeed()
return .success(feed)
} catch (let error) {
switch(error){
case APIServiceError.decodingError:
return .failure(.decodingError)
default:
return .failure(.networkError)
}
}
}
最后,存储库只是这样做:
func getFeed() async throws -> [FeedItemEntity] {
return try await service.getFeed()
}
然后服务如下:
func getFeed() async throws -> [FeedItemEntity] {
guard let url = Bundle(for: MockedFeedService.self).url(forResource: "basic-test-feed-response",withExtension: "json"),
let data = try? Data(contentsOf: url) else {
throw APIServiceError.badUrl
}
guard let result = try? JSONDecoder().decode([FeedItemEntity].self, from: data) else {
throw APIServiceError.decodingError
}
return result
}
据我观察,
ForEach
循环似乎不断被调用,我认为这可能会影响性能。该应用程序非常非常慢。
我习惯在Android上开发,协程机制通常在后台运行,但似乎在iOS上,那些调用更复杂,或者我只是错过了一些东西。
知道如何让应用程序高效流畅吗?
谢谢
由于您正在使用 async/await ,加快速度的一种方法是删除旧的合并
ObservableObject
,例如
struct FeedView: View {
@Environment(\.feedController) var controller // renamed from feedUseCase
@State private var feed: [FeedItem] = []
var body: some View {
...
.task { // normally there is an id param for the feed you want to fetch
do {
feed = await controller.getFeed()
catch {
// it's good practice to set an error message in a state and show it
}
}
...
如果你让你的控制器不是主要角色,它在后台线程上会更快。使用
EnvironmentKey
作为控制器的原因是这样您可以在预览时将其切换为模拟。