- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
假设您创建了两个 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/
我想创建一个基于 jQuery 的非常简单的 html 编辑器(不是所见即所得)。 我的问题是如何制作 textarea或 div可能 在上面写一些文字 然后样式即标签(例如 some stuff 将
根据文档 isset 条款“测试此项目中是否已设置给定属性”。我不明白设置属性时 isset 返回 true 还是 false 在下面的代码片段中,当 env.JAVA_HOME 未设置时,java.
我正在尝试取消映射 o这是执行 :only 的默认命令( :help :only ),所以我尝试的第一件事是: nmap o 这种作品,除非我按 ,等待超过timeoutlen ms 然后按 o
我有以下型号: class MetaData(models.Model): created_at = models.DateTimeField(auto_now_add=True, auto_
下面列出了两行代码。两者对日期和时间的期望相同,但只有一个有效。我正在使用 R 3.1。 以下不起作用: DateTime2=strftime("08/13/2010 05:26:24.350", f
我有一个关于 C 代码的问题。 #include void foo(void){ int a; printf("%d\n",a); } void bar(void){
如果文件大小 > 8k,为什么读取的最后一个字节 = 0? private static final int GAP_SIZE = 8 * 1024; public static void main(
我有一个命令 Get-Testdata从不同来源检索测试数据并将这些数据存储到 PSObject以不同的值作为属性。然后将对象总数存储为数组,以便于操作、排序、计算等。 我的问题是我希望能够将这些数据
我正在使用 epoll 将大消息写入使用 HTTP 协议(protocol)的服务器。 fds 都设置为非阻塞,我正在使用边缘触发事件。我知道对于 EPOLLIN,我需要循环读取 fd,直到返回 EA
这对我来说听起来很奇怪: $test_1 = 'string'; $test_2 = '0'; var_dump(intval($test_1)); // Output: int 0 var_dump
这个问题在这里已经有了答案: Java: Integer equals vs. == (7 个回答) 7年前关闭。 请您解释以下行为。 public class EqAndRef { publ
Drupal 的行为到底是什么? 它为模块开发人员提供什么类型的服务层? 它映射到 jQuery.ready 的关系类型是什么? 最佳答案 长版:Drupal.behaviors 不仅仅是 jQuer
以下代码: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ for (int i=0
人们可以将项目添加到数据库中。我让他们选择在此时添加它,或手动选择日期。 因此我得到了这个 HTML 结构。 (请注意,我将日期和时间选择器妥协为只有一行文本) Selec
创建了一个数据框: simpleDF is.na(simpleDF$vals) [1] TRUE TRUE FALSE > is.nan(simpleDF$vals) [1] FALSE TRU
我有一个大的 docker 镜像 A,我创建了一个新的 Dockerfile FROM A RUN rm /big-folder 我尝试使用以下方法构建图像: docker build --squas
我想知道以下情况下 JVM 的行为是什么: JVM 最小堆大小 = 500MB JVM 最大堆大小 = 2GB 操作系统有 1GB 内存 JVM启动后,程序运行一段时间后,使用内存超过1GB。我想知道
我们正在使用 spikeearrest 策略,但我们不了解其工作原理。峰值逮捕配置如下: 5pm 阅读文档,我们了解到,如果我们在一分钟内调用此流超过 5 次,则该策略将在第 5 次之后
我正在使用 cURL 发送 POST 请求: curl http://tarvos.local:8080/partial_Users/2 -d '{currentPage : 1, firstID :
我的表中有 6442670 条记录,我正在使用以下命令获取它们jdbctemplate 使用行号一次 1000000 个。以下是查询 select * from (select rowNum rn
我是一名优秀的程序员,十分优秀!