BaseViewModel 在 iOS 中使用 Swift 遵循 DRY 原则

问题描述 投票:0回答:1

我来自 Android 世界,那里有抽象类。我正在尝试使用 Swift 改进 iOS。我创建一个基类如下:

class BaseViewModel<T>: ObservableObject {
    typealias GHError = APIService.GHError
    
    @Published var result = Resource.loading
    
    let apiService = APIService()
    
    init() {
        refresh()
    }
    
    func getSuccessResult() async throws -> T? {
        return nil
    }
    
    func refresh() {
        result = Resource.loading
        Task { @MainActor in
            do {
                if let successResult = try await getSuccessResult() {
                    result = Resource.success(successResult)
                }
            } catch GHError.invalidURL {
                result = Resource.error("Invalid URL")
            } catch GHError.invalidResponse {
                result = Resource.error("Invalid response")
            } catch GHError.invalidData {
                result = Resource.error("Invalid data")
            } catch {
                result = Resource.error("Unexpected error")
            }
        }
    }
    
    enum Resource {
        case loading
        case success(T)
        case error(String)
    }
}

我试图避免在我创建的每个 ViewModel 中编写刷新方法,这就是我创建基类的原因,并且由于我们在 Swift 中没有抽象,所以我添加了这个在基类中返回 nil 的方法:

func getSuccessResult() async throws -> T? {
     return nil
}

这是子 viewModel 的示例:

class GithubViewModel : BaseViewModel<[UserWrapper]> {
    
    override func getSuccessResult() async throws -> [UserWrapper] {
        async let following = apiService.getUsers(endPoint: Constants.followingEndPoint)
        async let followers = apiService.getUsers(endPoint: Constants.followersEndPoint)
        return try await UserWrapper.createUsers(following: following, followers: followers)
    }
    
    private struct Constants {
        private static let endPoint = "https://api.github.com/users/alirezaeiii/"
        static let followingEndPoint = endPoint + "following"
        static let followersEndPoint = endPoint + "followers"
    }
}

它工作正常,但我不确定我是否遵循 DRY(不要重复自己)原则的好方法。

如果有任何改进,请帮我提出意见。

源代码在这里:https://github.com/alirezaeiii/Github-Users-Assignment/tree/main

ios swift generics
1个回答
0
投票

如果您需要抽象类之类的东西,可以使用协议。

protocol IBaseViewModel {
func getSuccessResult() async throws -> [BaseWrapper]? // You can also create BaseWrapper protocol for this. 

}

如果您想设置函数的默认行为,您可以为协议创建扩展。

extension IBaseViewModel {
    func getSuccessResult() async throws -> [BaseWrapper]? {
    return nil
  }
}

最后是UserWrapper和BaseWrapper的例子:

protocol BaseWrapper { ... }
protocol UserWrapper: BaseWrapper { ... }
© www.soinside.com 2019 - 2024. All rights reserved.