gpt4 book ai didi

ios - 响应链 - touchesMoved 与 touchesBegan 的不同行为?

转载 作者:搜寻专家 更新时间:2023-10-31 22:43:06 24 4
gpt4 key购买 nike

假设您创建了两个 View Controller ,A 和 B。A 有一个 segue 到 B(我认为具体哪个 segue 在这里并不重要,因为结果似乎是相同的。我将使用 push 作为示例。 ). A 有以下实现:

class A: UIViewController {

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("A received a begin touch")
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("A received a move touch")
}
}

在 B 中,你有:

class B: UIViewController {

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("B received a begin touch")
}
}

这将阻止任何触摸到 ViewController A。即使有移动触摸,A 也不会收到它。

但是,如果 B 的代码是:

class B: UIViewController {

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("B received a move touch")
}
}

然后 A 的“开始触摸”打印,A 和 B 的“移动触摸”打印。所以总而言之,当在 B 类中实现 touchesBegan 时,打印到控制台的唯一内容是“B 收到了开始触摸”。在 B 类中仅实现 touchesMoved 时,控制台会打印“A received a begin touch”,然后交替显示 A 和 B 都接收到移动触摸。

那么造成这种差异的原因是什么?为什么 touchesBegan 在 B 中覆盖会阻止 touchesMoved 方法在 A 中触发?为什么 B 中的 touchesMoved 方法不阻止 A 中的 touchesMoved 方法触发?我在文档中看到如果不调用 super 就必须覆盖所有触摸方法,但我仍然不明白为什么这里有必要这样做。

最佳答案

经过调查,我想我可能有所发现。

我已经创建了一个 Xcode 项目来将您的示例投入使用,同时使用 UIViewcontroller 和 UIViews.. 来查看它的行为方式。然后我想使用众所周知的 Swift 模式重新创建相同的“结果”,就好像我要实现 UIViews/UIViewController 响应者链一样。我在下面添加了指向这些文件的链接。

最终的行为是结合子类+协议(protocol)和标准实现得到的,所以当事件链到来时,你实现了哪些方法是有区别的。假设所有事件都是通过名为 stuff() 的基金交付的,并考虑以下因素。

enum State: Int {
case None
case Start
case Doing
case End
}

protocol StuffTouches {
var superStuff: StuffTouches? {get set}
var gesturingState: State {get set}
func begin()
func moves()
func ended()
mutating func stuff()
}

extension StuffTouches {
mutating func stuff() {
switch gesturingState {
case .None:
gesturingState = .Start
print("Protocol \(self) BEGIN")
begin()
case .Start:
gesturingState = .Doing
print("Protocol \(self) Moves")
moves()
case .End:
gesturingState = .None
print("Protocol \(self) Ended")
ended()
case .Doing:
print("Protocol \(self) Moves")
moves()
}
if gesturingState == .None {
gesturingState = .Start

}

}
func moves() {
print("Protocol \(self) Moves")
superStuff?.moves()
}
func ended() {
print("Protocol \(self) Ended")
superStuff?.ended()
}

}

class BaseStuff: StuffTouches {
var superStuff: StuffTouches?
var gesturingState: State = .None


func begin() {
print("Base \(self) BEGIN")
}

func moves() {
print("Base \(self) Moves")
}

func ended() {
print("Base \(self) Ended")
}
}

class TypeCStuff: BaseStuff {
override func moves() {
print("C Moves")
}
}

var stuff = TypeCStuff() as BaseStuff
stuff.superStuff = BaseStuff()
print("Event 1 - Touches begin")
stuff.stuff()
print("Event 2 - Continues")
stuff.stuff()
print("3")
stuff.stuff()
print("4")
stuff.stuff()
print("5")
stuff.stuff()

打印输出是:

Event 1 - Touches begin
Protocol __lldb_expr_7.TypeCStuff BEGIN
Base __lldb_expr_7.TypeCStuff BEGIN
Event 2 - Continues
Protocol __lldb_expr_7.TypeCStuff Moves
C Moves
3
Protocol __lldb_expr_7.TypeCStuff Moves
C Moves
4
Protocol __lldb_expr_7.TypeCStuff Moves
C Moves
5
Protocol __lldb_expr_7.TypeCStuff Moves
C Moves

它完全模拟了您在所描述的事件中发现的行为。

为了研究,我创建了一个项目和一个 Playground ,可以在 github 上找到它们

回到最初的问题:我不确定 Responder 实现是什么,但我相信 Apple 要求您同时实现两者的原因之一是默认实现使用协议(protocol)、扩展和子类的组合,如果您没有覆盖所有方法,您可能会被排除在链之外,如下所示:

protocol ThisProtocol {

}

extension ThisProtocol {
func test() {
print("Protocol")
}

func someOtherMethods() {
print("Protocol 2")
}

func ultimateTest() {
test()
someOtherMethods()
}
}

struct ThisStruct: ThisProtocol {

func test1() {
test()
}

func test2() {
ultimateTest()
}

func test() {
print("ThisStruct")
(self as ThisProtocol).test()
}
}

ThisStruct().test2()

上面代码的输出是:

Protocol
Protocol 2

(尽管 func test() 是在 ThisStruct 中实现的)

如果您改为调用 test1(),您将看到 ThisStruct.test() 被正确调用。

关于ios - 响应链 - touchesMoved 与 touchesBegan 的不同行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43133860/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com