[英]Using protocol with generic data type to pass data between screens
I am Android Developer that started learning iOS. I am trying to pass data between the master-detail style app.我是 Android 开始学习 iOS 的开发人员。我正在尝试在主从样式应用程序之间传递数据。 I got
controller1
that has a list of ToDo
items, and controller2
that allows to create a new ToDo
item and add it to the list on controller1
.我得到了包含
ToDo
项目列表的controller1
,以及允许创建新的ToDo
项目并将其添加到controller2
上的列表的controller1
。
I have created a protocol:我创建了一个协议:
protocol ListDataHolder {
associatedtype T
func addItem(item: T)
func reloadData()
}
Assigned self
in prepare
of controller1
:在
controller1
的prepare
中分配self
:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let controller2 = segue.destination as? Controller2{
controller2.toDoDataHolder = self
}
}
Declared delegate in controller2
在
controller2
中声明委托
// how do I tell to use ToDo class for generic type here
var toDoDataHolder: ListDataHolder? = nil
And use it like this:并像这样使用它:
@IBAction func onAddClicked(_ sender: Any) {
let toDo = ToDo()
...
toDoDataHolder?.addItem(item: toDo)
toDoDataHolder?.reloadData()
navigationController?.popViewController(animated: true)
}
I got a few errors when going this way:这样做时我遇到了一些错误:
For delegate declaration:对于委托声明:
Protocol 'ListDataHolder' can only be used as a generic constraint because it has Self or associated type requirements
When using addItem()
:使用
addItem()
时:
Cannot convert value of type 'ToDo' to expected argument type 'ListDataHolder.T'
Insert ' as! ListDataHolder.T'
Member 'addItem' cannot be used on value of protocol type 'ListDataHolder'; use a generic constraint instead
When I remove generic from protocol and just have addItem(item: ToDo)
, everything works fine.当我从协议中删除 generic 并且只有
addItem(item: ToDo)
时,一切正常。 But I want to be able to use ListDataHolder
with any data type.但我希望能够将
ListDataHolder
与任何数据类型一起使用。
This is just experimentation for me, I am not looking for a correct way to pass data between controllers.这对我来说只是实验,我不是在寻找在控制器之间传递数据的正确方法。
EDIT: you can find complete code in this GitHub repo: github.com/Sermilion/ios_learning编辑:您可以在此 GitHub 存储库中找到完整代码: github.com/Sermilion/ios_learning
What you need to do is to make the second view controller generic using the protocol and limit the type of objects being used (or held) by the class conforming to ListDataHolder
您需要做的是使用协议使第二个视图 controller 通用,并限制符合
ListDataHolder
的 class 使用(或持有)的对象类型
This can be done in the declaration of the view controller这可以在视图 controller 的声明中完成
class SecondViewController<Holder: ListDataHolder>: UIViewController where Holder.T == ToDo
then your method onAddClicked
will work as is.那么您的方法
onAddClicked
将按原样工作。
Instead of using associated type in ListDataHolder
protocol use ToDo
if your are always passing ToDo
instance to the addItem
method.如果您总是将
ToDo
实例传递给addItem
方法,则不要在ListDataHolder
协议中使用关联类型,而是使用ToDo
。
If you want this protocol addItem
method will work with any genericType use following code.如果您希望此协议
addItem
方法适用于任何 genericType,请使用以下代码。
protocol ListDataHolder {
func addItem<T:Decodable>(item: T)
func reloadData()
}
struct ToDo: Decodable {
}
class A: ListDataHolder {
func addItem<T:Decodable>(item: T) {
print("Add Item called")
}
func reloadData(){
}
}
Here you need to implement Delegation design pattern.这里需要实现委托设计模式。 Please check Delegation design pattern in detail.
请详细检查委托设计模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.