Swift 通用类型
Swift Generic types
您好,我是 swift 的新手,正在编写 iOS 应用程序。
我想知道如何更好地使用泛型来传递我的结果数据。
我有一个代表,它提供来自服务器的人的数据
protocol PersonDataProvider {
func dataReceived(_ result: PersonResult)
}
结果可以通过枚举有成功和失败状态。
enum PersonResult {
case success
case networkFailed
}
下面class调用服务器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" 如何定义他期望从 "success" 块获得的结果类型?
使用关联值作为 .success
案例的一部分。
假设您有一个适合您的人类型的超类 Person。然后像这样定义你的枚举:
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
}
}
您必须摆脱委派模式才能实现您想要的目标。相反,您将需要 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")
}
}
您好,我是 swift 的新手,正在编写 iOS 应用程序。 我想知道如何更好地使用泛型来传递我的结果数据。
我有一个代表,它提供来自服务器的人的数据
protocol PersonDataProvider {
func dataReceived(_ result: PersonResult)
}
结果可以通过枚举有成功和失败状态。
enum PersonResult {
case success
case networkFailed
}
下面class调用服务器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" 如何定义他期望从 "success" 块获得的结果类型?
使用关联值作为 .success
案例的一部分。
假设您有一个适合您的人类型的超类 Person。然后像这样定义你的枚举:
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
}
}
您必须摆脱委派模式才能实现您想要的目标。相反,您将需要 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")
}
}