iOS 子类化

示例

子类化UIControl使我们可以访问以下方法:

  • beginTrackingWithTouch 当手指首次在控件范围内触碰时调用。

  • continueTrackingWithTouch 手指在控件上滑动甚至在控件范围之外时,都会反复调用。

  • endTrackingWithTouch 手指离开屏幕时被调用。

MyCustomControl.swift

import UIKit

// 这些是我们如何与其他班级交流的自定义规则
protocol ViewControllerCommunicationDelegate: class {
    func myTrackingBegan()
    func myTrackingContinuing(location: CGPoint)
    func myTrackingEnded()
}

class MyCustomControl: UIControl {

    // 希望将触摸事件通知给哪个类,必须将委托设置为其自身
    weak var delegate: ViewControllerCommunicationDelegate?
    
    override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        
        // 通知委托(即视图控制器)
        delegate?.myTrackingBegan()
        
        // 返回true表示将来的事件(例如continueTrackingWithTouch和endTrackingWithTouch)将继续被触发
        return true
    }
    
    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        
        // 在我们的自定义控件自己的坐标系中获取触摸位置
        let point = touch.locationInView(self)
        
        // 用新的坐标点更新委托(即视图控制器)
        delegate?.myTrackingContinuing(point)
        
        // 返回true表示将来的事件将继续被触发
        return true
    }
    
    override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
        
        // 通知委托(即视图控制器)
        delegate?.myTrackingEnded()
    }
}

ViewController.swift

这就是将视图控制器设置为委托并响应来自自定义控件的触摸事件的方式。

import UIKit
class ViewController: UIViewController, ViewControllerCommunicationDelegate {
    
    @IBOutlet weak var myCustomControl: MyCustomControl!
    @IBOutlet weak var trackingBeganLabel: UILabel!
    @IBOutlet weak var trackingEndedLabel: UILabel!
    @IBOutlet weak var xLabel: UILabel!
    @IBOutlet weak var yLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       myCustomControl.delegate= self
    }

    func myTrackingBegan() {
       trackingBeganLabel.text= "Tracking began"
    }
    
    func myTrackingContinuing(location: CGPoint) {
       xLabel.text= "x: \(location.x)"
       yLabel.text= "y: \(location.y)"
    }
    
    func myTrackingEnded() {
       trackingEndedLabel.text= "Tracking ended"
    }
}

笔记

  • 无需子类即可获得相同结果的替代方法包括添加目标或使用手势识别器。

  • 如果仅在自定义控件本身中使用这些方法,则不必将委托与这些方法一起使用。我们本来可以添加一条print语句来显示事件如何被调用。在这种情况下,代码将简化为

      import UIKit
     class MyCustomControl: UIControl {
         override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
             print("Began tracking")
             return true
         }
     
         override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
             let point = touch.locationInView(self)
             print("x: \(point.x), y: \(point.y)")
             return true
         }
     
         override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
             print("Ended tracking")
         }
     }