迅速
これらは をサブクラス化する複数の方法UIControl
です。親ビューがタッチ イベントに反応するか、コントロールから他のデータを取得する必要がある場合、これは通常、(1) ターゲットまたは (2) オーバーライドされたタッチ イベントを含むデリゲート パターンを使用して行われます。完全を期すために、(3)ジェスチャ認識エンジンで同じことを行う方法も示します。これらの各メソッドは、次のアニメーションのように動作します。

次のいずれかの方法を選択するだけです。
方法 1: ターゲットを追加する
A UIControl
subclass has support for targets already built in. 多くのデータを親に渡す必要がない場合は、おそらくこれが必要なメソッドです。
MyCustomControl.swift
import UIKit
class MyCustomControl: UIControl {
// You don't need to do anything special in the control for targets to work.
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
@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()
// Add the targets
// Whenever the given even occurs, the action method will be called
myCustomControl.addTarget(self, action: #selector(touchedDown), forControlEvents: UIControlEvents.TouchDown)
myCustomControl.addTarget(self, action: #selector(didDragInsideControl(_:withEvent:)),
forControlEvents: UIControlEvents.TouchDragInside)
myCustomControl.addTarget(self, action: #selector(touchedUpInside), forControlEvents: UIControlEvents.TouchUpInside)
}
// MARK: - target action methods
func touchedDown() {
trackingBeganLabel.text = "Tracking began"
}
func touchedUpInside() {
trackingEndedLabel.text = "Tracking ended"
}
func didDragInsideControl(control: MyCustomControl, withEvent event: UIEvent) {
if let touch = event.touchesForView(control)?.first {
let location = touch.locationInView(control)
xLabel.text = "x: \(location.x)"
yLabel.text = "y: \(location.y)"
}
}
}
ノート
- アクション メソッド名については、特別なことは何もありません。私は彼らを何と呼んでもよかった。ターゲットを追加したときとまったく同じように、メソッド名のスペルに注意する必要があります。そうしないと、クラッシュします。
- の 2 つのコロン
didDragInsideControl:withEvent:
は、2 つのパラメーターがメソッドに渡されることを意味しますdidDragInsideControl
。コロンを追加するのを忘れた場合、または正しい数のパラメーターがない場合、クラッシュが発生します。
- イベントを手伝ってくれたこの回答に感謝し
TouchDragInside
ます。
他のデータを渡す
カスタムコントロールに値がある場合
class MyCustomControl: UIControl {
var someValue = "hello"
}
ターゲット アクション メソッドでアクセスしたい場合は、コントロールへの参照を渡すことができます。ターゲットを設定するときは、アクション メソッド名の後にコロンを追加します。例えば:
myCustomControl.addTarget(self, action: #selector(touchedDown), forControlEvents: UIControlEvents.TouchDown)
touchedDown:
(コロン付き) であり、(コロンなし) ではないことに注意してくださいtouchedDown
。コロンは、パラメーターがアクション メソッドに渡されることを意味します。アクション メソッドで、パラメーターがUIControl
サブクラスへの参照であることを指定します。その参照を使用して、コントロールからデータを取得できます。
func touchedDown(control: MyCustomControl) {
trackingBeganLabel.text = "Tracking began"
// now you have access to the public properties and methods of your control
print(control.someValue)
}
方法 2: パターンをデリゲートし、タッチ イベントをオーバーライドする
サブクラス化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")
}
}
方法 3: Gesture Recognizer を使用する
ジェスチャ レコグナイザーの追加は、任意のビューで行うことができ、UIControl
. 上の例と同様の結果を得るには、UIPanGestureRecognizer
. 次に、イベントが発生したときのさまざまな状態をテストすることで、何が起こっているかを判断できます。
MyCustomControl.swift
import UIKit
class MyCustomControl: UIControl {
// nothing special is required in the control to make it work
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
@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()
// add gesture recognizer
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureRecognized(_:)))
myCustomControl.addGestureRecognizer(gestureRecognizer)
}
// gesture recognizer action method
func gestureRecognized(gesture: UIPanGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.Began {
trackingBeganLabel.text = "Tracking began"
} else if gesture.state == UIGestureRecognizerState.Changed {
let location = gesture.locationInView(myCustomControl)
xLabel.text = "x: \(location.x)"
yLabel.text = "y: \(location.y)"
} else if gesture.state == UIGestureRecognizerState.Ended {
trackingEndedLabel.text = "Tracking ended"
}
}
}
ノート
- のアクション メソッド名の後にコロンを追加することを忘れないでください
action: "gestureRecognized:"
。コロンは、パラメーターが渡されることを意味します。
- コントロールからデータを取得する必要がある場合は、上記の方法 2 のようにデリゲート パターンを実装できます。