我来自 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
如果您需要抽象类之类的东西,可以使用协议。
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 { ... }