一、A,B两个类都继承于UIView,B是A的subView,两者都重写了touchBegan方法,点击B时,两个touchBegan方法的调用顺序是什么?
分析:
1.如果touchBegan没有调用super的touchBegan,那么只会调用B的touchBegan
@implementation AView
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"%@ touchesBegan", self);
}
@end
@implementation BView
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"%@ touchesBegan", self);
}
@end
<BView: 0x7f9e0fc05c20; frame = (50 50; 50 50); layer = <CALayer: 0x600002b65b00>> touchesBegan
2.如果B的touchBegan调用了super的touchBegan,那么A的touchBegan也会调用
结论:如果自己实现touchBegan方法并且不调用super,那么就阻断了触摸事件的继续传递,所以superView的touchBegan不会调用,如果一直没有阻断传递,最终appDelegate会收到事件,这个大家可以试下。此外,touchBegan方法的调用在hitTest:withEvent:之后,hitTest:withEvent:是寻找触摸事件目标view的方法,touchBegan方法个人认为是已经到了事件响应阶段,所以不实现的话,就是传递到最外层的superResponder,要拦截事件响应的话,自然是实现此方法,至于需要调用super的touchBegan与否,则是看自己的业务需要了
关于touchBegan方法的解释:
UIKit calls this method when a new touch is detected in a view or window. Many UIKit classes
override this method and use it to handle the corresponding touch events. The default
implementation of this method forwards the message up the responder chain. When creating
your own subclasses, call super to forward any events that you do not handle yourself. For
example,
[super touchesBegan:touches withEvent:event];
If you override this method without calling super (a common use pattern), you must also
override the other methods for handling touch events, even if your implementations do
nothing.
翻译:
当在视图或窗口中检测到新触摸时,UIKit调用此方法。许多UIKit类重写此方法并使用它来处
理相应的触摸事件。此方法的默认实现将消息转发到响应程序链。创建自己的子类时,请调
用super来转发您自己未处理的任何事件。例如,
[super touchesBegan:touch withEvent:event];
如果在不调用super(常用模式)的情况下覆盖此方法,则还必须覆盖其他方法来处理触摸
事件,即使您的实现不执行任何操作也是如此。
二、如果category中有一个与原类中同名但返回值不同的方法,会覆盖原方法吗?
结论:会覆盖,oc中是以selector其实就是一个string,比如:@selector(hitTest:withEvent:),selector是不包含返回值的信息的,(PS:我要发消息给你,我只要把完整的消息告诉你就行了,我并不关心你的反应/返回值)
三、gcd中,如果在同步队列a中向同步队列b中添加任务,会死锁吗?
结论:不会,死锁产生的条件是:“在某一个串行队列中,同步的向这个队列添加block”。这里说不会的原因是,没有间接地在b的向a又添加了任务,这样就形成了一个循环的等待状态,类比于内存的循环引用,具体可以参考这个文章,我觉得写的很多好:
https://blog.csdn.net/abc649395594/article/details/48017245
试验:
dispatch_queue_t A = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t B = dispatch_queue_create("com.example.pass", DISPATCH_QUEUE_SERIAL);
dispatch_sync(A, ^{//sync1
NSLog(@"log 1, %@", [NSThread currentThread]);
dispatch_sync(B, ^{//sync2
NSLog(@"log 2, %@", NSThread.currentThread);
});
dispatch_sync(dispatch_get_main_queue(), ^{//sync3
NSLog(@"log 3, %@", NSThread.currentThread);
});
NSLog(@"log 4, %@", NSThread.currentThread);
});
NSLog(@"log 5, %@", NSThread.currentThread);
输出:
log 1, <NSThread: 0x6000000b93c0>{number = 1, name = main}
log 2, <NSThread: 0x6000000b93c0>{number = 1, name = main}
为什么同是串行队列,同步地向B队列添加任务没有导致死锁,但是向主队列中添加任务导致了死锁?
知识点:队列只是GCD给出的抽象数据结构。队列是可以嵌套的,比如在A队列(串行)添加一个任务a,在a这个任务中向B队列(串行)添加任务b,在b这个任务中又向A队列添加任务,这就间接满足了“在某一个串行队列中,同步的向这个队列添加block”。
示例分析:我们向队列A添加了任务a(包括任务1,sync2,sync3,任务4),在sync2中向队列B添加了任务2,在sync3中向主队列中添加了任务3,sync与async的组合使用类似于“与”操作,多个sync嵌套其实还是直接向主队列添加了任务(最外围还是主队列的任务),最终其实是:主队列中任务3添加在了任务5之后(block中的任务是添加在队列最后的),但是任务5需要等待sync1返回才能执行,而sync1需要等待block中的任务3执行完后返回,相互等待=>死锁
PS:(语拙,自己理解的也不够透彻)
四、bitcode是什么?
http://blog.jonyfang.com/2017/06/21/introduction-to-bitcode/
这个文章我觉得写的简单易懂
网友评论