嗨,我是迅速编写iOS应用程序的新手。 我想知道如何更好地使用泛型传递结果数据。
我有一个委托人,负责提供服务器中的人的数据
protocol PersonDataProvider {
func dataReceived(_ result: PersonResult)
}
结果可以通过枚举获得成功和失败状态。
enum PersonResult {
case success
case networkFailed
}
下面的类调用服务器api并获取数据,然后传回
class MyNetworkClass {
var personDataProvider: PersonDataProvider
func getDataFromServer() {
personDataProvider.dataReceived(.success)
}
}
下面是我订阅提供程序的Viewcontroller
class MyViewController: PersonDataProvider {
func dataReceived(_ result: PersonResult) {
switch result {
case .success:
print("success")
case .networkFailed:
print("no network")
}
}
}
现在,我想发送带有成功块的额外信息,该信息可以是下面的数据模型。它可以是任何类型。
class Employer:Person {
let id
let salary
}
class Student:Person {
let id
let rollNumber
}
我该如何实现?我可以在协议中定义关联类型并实现吗?
我如何订阅“ PersonDataProvider”的“ MyViewController”可以定义他期望的“成功”块的结果类型?
答案 0 :(得分:1)
将关联值用作.success
案例的一部分。
比方说,对于您这类的人,您有一个超类人。然后像这样定义您的枚举:
enum PersonResult {
case success(Person)
case networkFailed
}
现在,当您交出.success
值时,必须提供一个Person来配合它:
func getDataFromServer() {
let person = Student.init(...) // initialize, or fetch, or whatever
personDataProvider.dataReceived(.success(person))
}
这里是一个完整的伪造示例,它模拟了整个过程;您必须更改详细信息,但要注意的是,它将编译:
enum PersonResult {
case success(Person)
case networkFailed
}
protocol PersonDataProvider {
func dataReceived(_ result: PersonResult)
}
class MyNetworkClass {
var personDataProvider: PersonDataProvider!
func getDataFromServer() {
let person = Student.init(id: 3, rollNumber: 10)
personDataProvider.dataReceived(.success(person))
}
}
class Person {}
class Employer:Person {
let id : Int
let salary : Int
init(id:Int, salary:Int) {
self.id = id; self.salary = salary
}
}
class Student:Person {
let id : Int
let rollNumber : Int
init(id:Int, rollNumber:Int) {
self.id = id; self.rollNumber = rollNumber
}
}
答案 1 :(得分:0)
您必须摆脱委派模式才能实现所需的功能。取而代之的是,您将需要 Result 类型的通用enum
和您的数据模型类型通用的网络class
。
enum Result<T> {
case success(T)
case networkFailed
}
class MyNetworkClass<T: Person> {
func getDataFromServer(completion: @escaping (Result<T>)-> Void) {
// here goes your implementation (data fetching)
// for demonstration purpose I just initialized object
if let student = Student(id: 112233, rollNumber: 25) as? T {
completion(Result.success(student))
} else if let employer = Employer(id: 445566, salary: 5200) as? T {
completion(Result.success(employer))
} else {
completion(Result.networkFailed)
}
}
}
那么您的用法将是:
MyNetworkClass().getDataFromServer { (result: Result<Student>) in // you can also use Employer type
switch result {
case .success(let student):
print(student.id)
case .networkFailed:
print("Error")
}
}