子類

子類化 UIControl 使我們能夠訪問以下方法:

  • 當手指首次觸及控制範圍內時,會呼叫 beginTrackingWithTouch
  • 當手指滑過控制元件甚至在控制元件的邊界之外時,會反覆呼叫 continueTrackingWithTouch
  • 當手指擡離螢幕時,會呼叫 endTrackingWithTouch

MyCustomControl.swift

import UIKit

// These are out self-defined rules for how we will communicate with other classes
protocol ViewControllerCommunicationDelegate: class {
    func myTrackingBegan()
    func myTrackingContinuing(location: CGPoint)
    func myTrackingEnded()
}

class MyCustomControl: UIControl {

    // whichever class wants to be notified of the touch events must set the delegate to itself
    weak var delegate: ViewControllerCommunicationDelegate?
    
    override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        
        // notify the delegate (i.e. the view controller)
        delegate?.myTrackingBegan()
        
        // returning true means that future events (like continueTrackingWithTouch and endTrackingWithTouch) will continue to be fired
        return true
    }
    
    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        
        // get the touch location in our custom control's own coordinate system
        let point = touch.locationInView(self)
        
        // Update the delegate (i.e. the view controller) with the new coordinate point
        delegate?.myTrackingContinuing(point)
        
        // returning true means that future events will continue to be fired
        return true
    }
    
    override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
        
        // notify the delegate (i.e. the view controller)
        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")
          }
      }