swift的protocol

Swift与Objective-C中的Protocol

利用Protocol,我们可以在Objc和Swift实现多继承。实现方式有区别,但是道理是一样的

可以这样声明Protocol:

Objective-C

1
2
3
4
5
@protocol SomeProtocol <NSObject>

- (void)someMethod;

@end

Swift

1
2
3
4
protocol SomeProtocol 
{
func someMethod()
}

实现Protocol:

Objective-C

1
2
3
@interface MyClass : NSObject<SomeProtocol>

@end

Swift

1
2
3
4
5
6
class MyClass: NSObject, SomeProtocol 
{
// Conforming to SomeProtocol
func someMethod() {
}
}

利用Protocol实现代理模式

通过代理模式可以实现方法的回调
一个例子模拟计算机启动并检测计算机的启动状态,先定义一个Protocol,

如果要定义像oc中的可选(Optional)的方法,必须在定义的时候在protocol前面加上@objc属性

1
2
3
@objc protocol ComupterDelegate {
optional func computerDidStart()
}

下面是个Computer类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Computer {

weak var delegate: ComupterDelegate? //可能为空所以定义为可选类型

func configureComputer(){
//计算机初始化的操作
}

func startUp(){
configureComputer()

//完成初始化,执行回调
if let delegateUW = delegate {
delegateUW.computerDidStart?()
}
}
}

然后在我们的ViewController就可以用了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ViewController: UIViewController,ComupterDelegate {

var computer : Computer!

override func viewDidLoad() {
super.viewDidLoad()
computer = Computer()
computer.delegate = self
computer.startUp()
}

func computerDidStart() {
//此处进行计算机完成初始化后的操作
}
}

protocol实现tablecell对不同Model的适配

  • 原理:protocol是一种类型,可以被用作参数,返回值,变量常量等,也可以被存放与Dictionary和Array里
    因为protocol是一种类型,所以可以用 is 操作符来确认是否被实现,也可以用as!,as?来类型转换

官方文档对protocol类型的表述:
Protocols do not actually implement any functionality themselves. Nonetheless, any protocol you create will become a fully-fledged type for use in your code.
Because it is a type, you can use a protocol in many places where other types are allowed, including:

  • As a parameter type or return type in a function, method, or initializer
  • As the type of a constant, variable, or property
  • As the type of items in an array, dictionary, or other container
  • 一个例子,2个数据Model类(存放原始数据),一个CustomCell类(用于table的数据展示,假设需要展示名字和年龄)。例子中protocol作为一个类型,充当了一个适配器

定义protocal:

1
2
3
protocol ModelForCustomCell {
func dataForCustomCell()->(name:String,age:String)
}

2个数据Model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class ModelA : ModelForCustomCell{
var name: String!
var age: String!

func dataForCustomCell() -> (name:String,age:String) {
//实际应用中这里应该是写数据处理逻辑,组装成元组返回给调用的VC,避免在VC中写复杂的逻辑
self.name = "modelA"
self.age = "25"
return (self.name,self.age)
}

}

class ModelB : ModelForCustomCell{
var name: String!
var age: String!

func dataForCustomCell() -> (name:String,age:String) {
//实际应用中这里应该是写数据处理逻辑,组装成元组返回给调用的VC,避免在VC中写复杂的逻辑
self.name = "modelB"
self.age = "35"
return (self.name,self.age)
}
}

Note:
protocol中的方法返回的是元组。在MVVM模式下,Model类可以在extension中写一个方法写数据处理逻辑,返回一个View需要的数据元组。这里数据元组起到了ViewModel的作用

然后是我们的自定义tablelCell,要显示name,age两个数据

1
2
3
4
5
6
7
8
9
10
class CustomCell:UITableViewCell{
var nameLabel = UILabel()
var ageLabel = UILabel()

func configureCell(dataModel:ModelForCustomCell){

self.nameLabel.text = dataModel.dataForCustomCell().name
self.ageLabel.text = dataModel.dataForCustomCell().age
}
}

有2个table,分别显示ModelA和ModelB的名字和年龄,都可以用到CustomCell,在各自的table的dataSourece回调中可以这样写:

1
2
3
4
5
6
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell = self.tableView.dequeueReusableCellWithIdentifier(commentCellID) as! CustomCell
var model = ModelA()//或者是ModelB()
cell.configureCell(model)
return cell
}

这样就可以对同一个cell适配显示不同的数据Model了

参考资料