1、實例說明及實現(xiàn)
使用委托模式實現(xiàn)。
協(xié)議最常見的用法莫過于進(jìn)行代理傳值。常用的場景有:controller中自定義了一個view,view中添加了一個button。點(diǎn)擊自定義中的button去改變在controller上label的值。代碼如下:
自定義ClickView.swift:
//
// ClickView.swift
// Demo
//
// Created by 王樹軍 on 2018/7/30.
// Copyright ? 2018 王樹軍. All rights reserved.
//
import UIKit
/* 屏幕的寬 */
public let kSCREEN_WIDTH = UIScreen.main.bounds.size.width
/* 屏幕的高 */
public let kSCREEN_HEIGHT = UIScreen.main.bounds.size.height
@objc protocol ClickViewDelegate {
func changeLabel(_ str: String)
}
class ClickView: UIView {
var keywords: [String]?
var buttons: [UIButton]?
weak public var delegate: ClickViewDelegate?
init(frame: CGRect, keywords: [String]) {
super.init(frame: frame)
self.keywords = keywords
renderVier()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
private func renderVier() {
buttons = keywords?.enumerated().map({ (index, key) -> UIButton in
let buttonWidth = kSCREEN_WIDTH/CGFloat((keywords?.count)!)
let button = UIButton.init(frame: CGRect.init(x: CGFloat(index)*buttonWidth, y: 0, width: buttonWidth, height: 50))
button.setTitle(key, for: .normal)
button.setTitleColor(UIColor.blue, for: .normal)
button.backgroundColor = UIColor.gray
button.tag = index
button.addTarget(self, action: #selector(tapButton(sender:)), for: .touchUpInside)
addSubview(button)
return button
})
}
@objc func tapButton(sender: UIButton) {
delegate?.changeLabel(keywords![sender.tag])
}
}
ViewController.swift
//
// ViewController.swift
// Demo
//
// Created by 王樹軍 on 2018/7/30.
// Copyright ? 2018 王樹軍. All rights reserved.
//
import UIKit
class ViewController: UIViewController ,ClickViewDelegate{
lazy var label: UILabel = {
var label = UILabel(frame: CGRect.init(x: 50, y: 200, width: 100, height: 30))
label.text = labelStr
label.backgroundColor = UIColor.red
return label
}()
var labelStr: String? {
didSet {
label.text = labelStr
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(label)
setupClickView()
}
func setupClickView() {
let clickView = ClickView(frame: CGRect.init(x: 0, y: 88, width: kSCREEN_WIDTH, height: 50), keywords: ["aa", "bb"])
clickView.delegate = self
view.addSubview(clickView)
}
func changeLabel(_ str: String) {
labelStr = str
}
}
2、注意事項
1、在 ARC 中,對于一般的 delegate,我們會在聲明中將其指定為 weak,在這個 delegate 實際的對象被釋放的時候,會被重置回 nil。
2、 Swift 的 protocol 是可以被除了 class 以外的其他類型遵守的,而對于像 struct 或是 enum 這樣的類型,本身就不通過引用計數(shù)來管理內(nèi)存,所以也不可能用 weak 這樣的 ARC 的概念來進(jìn)行修飾。
兩種解決方法:
①、使用@objc
②、聲明類類型專屬協(xié)議。通過添加 class 關(guān)鍵字來限制協(xié)議只能被類類型遵循,
而結(jié)構(gòu)體或枚舉不能遵循該協(xié)議。class 關(guān)鍵字必須第一個出現(xiàn)在協(xié)議的繼承列表中,在其他繼承的協(xié)議之前
protocol ClickViewDelegate : class