Delegate

1. 前言

以前只知道怎么用 Delegate,能够传值和回传值。最近写代码封装一个 UIPickerView+UIButton,时候需要传值,就想到了 Delegate。但是自己写一个却把我难住了。最后看了还是看了一个 Demo, 单步调试才算真正理解的Delegate 整个流程和原理。

简单来说就是声明 Protocol,添加触发 调用Protocol 方法的条件,被委托者设置 Delegate = self,就会在触发条件下调用 Protocol 方法(参数和返回值可实现双向传值)。

主要看了这个教程:
CREATE CUSTOM DELEGATE AND PROTOCOL IOS | SWIFT & OBJECTIVE-C,下面是作者提供的源码Objective-C  ProjectSwift Project

教材中MyTimer是Custom ViewController,我实际工作中是 UIView,也是参考了另外一篇 Apple 的教程:Implement a Custom Control。发现开发真的离不开 Google,但是前提是要有思路,或者对一个项目或者难题,要有整体的框架和可用的知识点熟悉。

2. 源码

下面是UIPickerView+UIButton封装后的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//  GenderPickerView.swift

import UIKit

protocol GenderPickerViewDelegate: NSObjectProtocol {
func genderPickerDidSelectItem(row: Int)
}

class GenderPickerView: UIView, UIPickerViewDataSource, UIPickerViewDelegate {
var delegate: GenderPickerViewDelegate!
var toolbar: UIToolbar!
var picker: UIPickerView!
var genderPickerViewData = ["不告诉你", "男", "女"]
var genderSelectedRow = 0

override init(frame: CGRect) {
super.init(frame: frame)
toolbar = UIToolbar.init(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, 20))
toolbar.barStyle = .Default
toolbar.sizeToFit()

let cancelButton = UIBarButtonItem.init(title: "取消", style: UIBarButtonItemStyle.Done, target: self, action: "genderPickerDidCancel")
let flexibleButton = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
let doneButton = UIBarButtonItem.init(title: "确定", style: UIBarButtonItemStyle.Done, target: self, action: "genderPickerDidSelect")
toolbar.setItems([cancelButton, flexibleButton, doneButton], animated: true)

picker = UIPickerView.init(frame: CGRectMake(0, 44, UIScreen.mainScreen().bounds.width, 120))
picker.dataSource = self
picker.delegate = self

addSubview(toolbar)
addSubview(picker)
}

convenience init() {
self.init(frame: CGRectMake(0, UIScreen.mainScreen().bounds.height - 164, UIScreen.mainScreen().bounds.width, 164))
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}


//MARK: - 性别选择视图
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 3
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return genderPickerViewData[row]
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
genderSelectedRow = row
}

func genderPickerDidSelect() {
delegate?.genderPickerDidSelectItem(genderSelectedRow)
removeFromSuperview()
}

func genderPickerDidCancel() {
removeFromSuperview()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//  PersonalInfoViewController.swift

import UIKit

class ViewController: UIViewController, GenderPickerViewDelegate {
var genderPicker: GenderPickerView!
override func viewDidLoad() {
super.viewDidLoad()
genderPicker = GenderPickerView.init()
genderPicker.delegate = self
self.view.addSubview(genderPicker)}

//MARK: - GenderPickerViewDelegate
func genderPickerDidSelectItem(row: Int) {
// Do something
}
}