`
啸笑天
  • 浏览: 3465701 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

ios 事件拦截

    博客分类:
  • ios
 
阅读更多

先介绍下事件分发:

 移动平台上的开发主要关注数据以及数据的处理,事件的处理以及UI。所以事件的分发处理是很重要的一个环节,对于一个平台的优劣来说也是一项重要的参数。如果事件的分发设计的不好,一些复杂的UI场景就会变得很难写甚至没法写。从小屏没有触摸的功能机开始到现在大屏多点触摸的智能机,对于事件的分发处理基本思路都是一样的——链(设计模式中有个模式就是职责链chain of responsibility),只是判定的复杂程度不同。

        iOS中的事件有3类,触摸事件(单点,多点,手势)、传感器事件(加速度传感器)和远程控制事件,这里我介绍的是第一种事件的分发处理。

        

        上面的这张图来自苹果的官方。描述了Responder的链,同时也是事件处理的顺序。通过这两张图,我们可以发现:

        1. 事件顺着responder chain传递,如果一环不处理,则传递到下一环,如果都没有处理,最后回到UIApplication,再不处理就会抛弃

        2. view的下一级是包含它的viewController,如果没有viewController则是它的superView

        3. viewController的下一级是它的view的superView

        4. view之后是window,最后传给application,这点iOS会比OS X简单(application就一个,window也一个)

         总结出来传递规则是这样的:

        

        这样事件就会从first responder逐级传递过来,直到被处理或者被抛弃。

 

        由于UI的复杂,这个responder chain是需要根据事件来计算的。比如,我现在在一个view内加入了2个Button,先点击了一个,则first responder肯定是这个点击过的button,但我下面可以去点击另一个button,所以显然,当触摸事件来时,这个chain是需要重新计算更新的,这个计算的顺序是事件分发的顺序,基本上是分发的反过来

        

        无论是哪种事件,都是系统本身先获得,是iOS系统来传给UIApplication的,由Application再决定交给谁去处理,所以如果我们要拦截事件,可以在UIApplication层面或者UIWindow层面去拦截。

        

        

        UIView是如何判定这个事件是否是自己应该处理的呢?iOS系统检测到一个触摸操作时会打包一个UIEvent对象,并放入Application的队列,Application从队列中取出事件后交给UIWindow来处理,UIWindow会使用hitTest:withEvent:方法来递归的寻找操作初始点所在的view,这个过程成为hit-test view。

        hitTest:withEvent:方法的处理流程如下:调用当前view的pointInside:withEvent:方法来判定触摸点是否在当前view内部,如果返回NO,则hitTest:withEvent:返回nil;如果返回YES,则向当前view内的subViews发送hitTest:withEvent:消息,所有subView的遍历顺序是从数组的末尾向前遍历,直到有subView返回非空对象或遍历完成。如果有subView返回非空对象,hitTest方法会返回这个对象,如果每个subView返回都是nil,则返回自己。

        好了,我们还是看个例子:

        

        这里ViewA包含ViewB和ViewC,ViewC中继续包含ViewD和ViewE。假设我们点击了viewE区域,则hit-test View判定过程如下:

       1. 触摸在A内部,所以需要检查B和C

       2. 触摸不在B内部,在C内部,所以需要检查D和E

       3. 触摸不在D内部,但在E内部,由于E已经是叶子了,所以判定到此结束

 

        我们可以运行一段代码来验证,首先从UIView继承一个类myView,重写里面的

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event  
  2. {  
  3.     UIView *retView = nil;  
  4.     NSLog(@"hitTest %@ Entry! event=%@", self.name, event);  
  5.       
  6.     retView = [super hitTest:point withEvent:event];  
  7.     NSLog(@"hitTest %@ Exit! view = %@", self.name, retView);  
  8.      
  9.     return retView;  
  10. }  

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event  
  2. {  
  3.     BOOL ret = [super pointInside:point withEvent:event];  
  4. //    if ([self.name isEqualToString:@"viewD"]) {  
  5. //        ret = YES;  
  6. //    }  
  7.     if (ret) {  
  8.         NSLog(@"pointInside %@ = YES", self.name);  
  9.     } else {  
  10.         NSLog(@"pointInside %@ = NO", self.name);  
  11.     }  
  12.       
  13.     return ret;  
  14. }  

        在viewDidLoad方法中手动加入5个view,都是myView的实例。

 

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     _viewA = [[myView alloc] initWithFrame:CGRectMake(10, 10, 300, 200) Color:[UIColor blackColor] andName:@"viewA"];  
  6.     [self.view addSubview:_viewA];  
  7.     [_viewA release];  
  8.       
  9.     _viewB = [[myView alloc] initWithFrame:CGRectMake(10, 240, 300, 200) Color:[UIColor blackColor] andName:@"viewB"];  
  10.     [self.view addSubview:_viewB];  
  11.     [_viewB release];  
  12.       
  13.     _viewC = [[myView alloc] initWithFrame:CGRectMake(10, 10, 120, 180) Color:[UIColor blueColor] andName:@"viewC"];  
  14.     [_viewB addSubview:_viewC];  
  15.     [_viewC release];  
  16.       
  17.     _viewD = [[myView alloc] initWithFrame:CGRectMake(170, 10, 120, 180) Color:[UIColor blueColor] andName:@"viewD"];  
  18.     [_viewB addSubview:_viewD];  
  19.     [_viewD release];  
  20.       
  21.     _viewE = [[myView alloc] initWithFrame:CGRectMake(30, 40, 60, 100) Color:[UIColor redColor] andName:@"viewE"];  
  22.     [_viewD addSubview:_viewE];  
  23.     [_viewE release];  
  24.   
  25. }  

        这个样式如下:

 

        当我点击viewE的时候,打印信息如下:

 

2014-01-25 18:32:46.538 eventDemo[1091:c07] hitTest viewB Entry! event=<UITouchesEvent: 0x8d0cae0> timestamp: 6671.26 touches: {(

)}

2014-01-25 18:32:46.538 eventDemo[1091:c07] pointInside viewB = YES

2014-01-25 18:32:46.539 eventDemo[1091:c07] hitTest viewD Entry! event=<UITouchesEvent: 0x8d0cae0> timestamp: 6671.26 touches: {(

)}

2014-01-25 18:32:46.539 eventDemo[1091:c07] pointInside viewD = YES

2014-01-25 18:32:46.539 eventDemo[1091:c07] hitTest viewE Entry! event=<UITouchesEvent: 0x8d0cae0> timestamp: 6671.26 touches: {(

)}

2014-01-25 18:32:46.540 eventDemo[1091:c07] pointInside viewE = YES

2014-01-25 18:32:46.540 eventDemo[1091:c07] hitTest viewE Exit! view = <myView: 0x8c409f0; frame = (30 40; 60 100); layer = <CALayer: 0x8c40a90>>

2014-01-25 18:32:46.540 eventDemo[1091:c07] hitTest viewD Exit! view = <myView: 0x8c409f0; frame = (30 40; 60 100); layer = <CALayer: 0x8c40a90>>

2014-01-25 18:32:46.541 eventDemo[1091:c07] hitTest viewB Exit! view = <myView: 0x8c409f0; frame = (30 40; 60 100); layer = <CALayer: 0x8c40a90>>

2014-01-25 18:32:46.541 eventDemo[1091:c07] touchesBegan viewE

2014-01-25 18:32:46.624 eventDemo[1091:c07] touchesEnded viewE

 

        从打印信息可以看到,先判断了viewB,然后是viewD,最后是viewE,但事件就是直接传给了viewE。

 

 拦截处理方式1:

  我们知道事件的分发是由Application到Window再到各级View的,所以显然最安全可靠的拦截地方是Application。这里拦截事件后如果不手动往下分发,则进入hit-test View过程的机会都没有。

        UIApplication和UIWindow都有sendEvent:方法,用来分发Event。我们可以继承类,重新实现sendEvent:方法,这样就可以拦截下事件,完成一些特殊的处理。

        比如:有一个iPad应用,要求在非某个特定view的区域触摸时进行一项处理。

        我们当然可以在其余每一个view里面增加代码进行判断,不过这样比较累,容易漏掉一些地方;另外当UI需求变更时,维护的GG往往会栽进这个坑,显然这不是一个好方法。

        这里比较简单的解决方案就是在继承UIApplication类,实现自己的sendEvent:,在这个方法里面初步过滤一下事件,是触摸事件就发送Notification,而特定的view会注册这个Notification,收到后判断一下是否触摸到了自己之外的区域。

        恩,还是上代码吧,比较清楚一点:

1. 继承UIApplication的DPApplication类

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #import <UIKit/UIKit.h>  
  2.   
  3. extern NSString *const notiScreenTouch;  
  4.   
  5. @interface DPApplication : UIApplication  
  6.   
  7. @end  

 

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #import "DPApplication.h"  
  2.   
  3. NSString *const notiScreenTouch = @"notiScreenTouch";  
  4.   
  5. @implementation DPApplication  
  6.   
  7. - (void)sendEvent:(UIEvent *)event  
  8. {  
  9.     if (event.type == UIEventTypeTouches) {  
  10.         if ([[event.allTouches anyObject] phase] == UITouchPhaseBegan) {  
  11.             [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:notiScreenTouch object:nil userInfo:[NSDictionary dictionaryWithObject:event forKey:@"data"]]];  
  12.         }  
  13.     }  
  14.     [super sendEvent:event];  
  15. }  
  16.   
  17. @end  

2.要在main.m文件中替换掉UIApplication的调用

 

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #import <UIKit/UIKit.h>  
  2.   
  3. #import "AppDelegate.h"  
  4. #import "DPApplication.h"  
  5.   
  6. int main(int argc, charchar *argv[])  
  7. {  
  8.     @autoreleasepool {  
  9.         //return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));  
  10.         return UIApplicationMain(argc, argv, NSStringFromClass([DPApplication class]), NSStringFromClass([AppDelegate class]));  
  11.     }  
  12. }  

3. 这时已经实现了拦截消息,并在touchBegan的时候发送Notification,下面就是在view里面注册这个Notification并处理

 

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onScreenTouch:) name:notiScreenTouch object:nil];  

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. - (void)onScreenTouch:(NSNotification *)notification  
  2. {  
  3.     UIEvent *event=[notification.userInfo objectForKey:@"data"];  
  4.       
  5.     NSLog(@"touch screen!!!!!");  
  6.     CGPoint pt = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self.button];  
  7.     NSLog(@"pt.x=%f, pt.y=%f", pt.x, pt.y);  
  8. }  


        这样就实现了事件的预处理,固有的事件处理机制也没有破坏,这个预处理是静悄悄的进行的。当然,如果我需要把某些事件过滤掉,也只需在DPApplication的sendEvent:方法里面抛弃即可。

 

 

 拦截处理方式2:

http://www.cnblogs.com/Quains/p/3369132.html

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

返回在层级上离当前view最远(离用户最近)且包含指定的point的view。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 返回boolean值指出receiver是否包含指定的point。

重写hittext方法,拦截用户触摸视图的顺序
hitTest方法的都用是由window来负责触发的。
如果希望用户按下屏幕 , 就立刻做出响应 , 使用touchesBegin
如果希望用户离开屏幕 , 就立刻做出响应 , 使用touchesEnd
通常情况下使用touchesBegin,以防止用户认为点击了没有反应。

把hitTest的点转换为 redView的点,使用convertPoint: toView;

 CGPoint redP = [self convertPoint:point toView:self.redView];

判断一个点是否在视图的内部:

if ([self.greenView pointInside:greenP withEvent:event]) {
return self.greenView;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"clcik me root");
}
/*
 重写hittext方法,拦截用户触摸视图的顺序
hitTest方法的都用是由window来负责触发的。
 
 如果希望用户按下屏幕 , 就立刻做出响应 , 使用touchesBegin
 如果希望用户离开屏幕 , 就立刻做出响应 , 使用touchesEnd
 通常情况下使用touchesBegin。
 */

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    //1.判断当前视图是否能接受用户响应
    /*self.UserInteractionEnabled=YES
      self.alpha > 0.01;
      self.hidden = no;
     */
    //2.遍历其中的所有的子视图,能否对用户触摸做出相应的响应
    //3.把event交给上级视图活上级视图控制器处理
    //4.return nil;如果发挥nil,说明当前视图及其子视图均不对用户触摸做出反应。
    /*
     参数说明:
        point:参数是用户触摸位置相对于当前视图坐标系的点;
     注视:以下两个是联动使用的,以递归的方式判断具体响应用户事件的子视图
            - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
            - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
        这两个方法仅在拦截触摸事件时使用,他会打断响应者链条,平时不要调用。
     提醒:如果没有万不得已的情况,最好不要自己重写hitTest方法;
     */
    return nil;
    CGPoint redP = [self convertPoint:point toView:self.redView];
    //转换绿色视图的点
    CGPoint greenP = [self convertPoint:point toView:self.greenView];
    //pointInside  使用指定视图中的坐标点来判断是否在视图内部,最好不要在日常开发中都用。
    if ([self.greenView pointInside:greenP withEvent:event]) {
        return self.greenView;
    }
    NSLog(@"%@",NSStringFromCGPoint(redP));
    if ([self.redView pointInside:redP withEvent:event]) {
        
        return self.redView;

    }
    return [super hitTest:point withEvent:event];
}

 

不继承重写的话可以用category来实现:

+(void)initialize{
    Method m = class_getInstanceMethod([UIView class],@selector(pointInside:withEvent:));
    Method m2 = class_getInstanceMethod([UIView class],@selector(pointInside11:withEvent:));
    method_exchangeImplementations(m, m2);
}
- (BOOL)pointInside11:(CGPoint)point withEvent:(UIEvent *)event
{
//todo 
   if (*****) {

        return NO;
    }
    
    return [self pointInside11:point withEvent:event];
}

  

 

不解:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 和- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 方法都执行三遍,不知道具体原理 ,运行下看了event参数,可能是苹果判断单指多指等复杂操作才这样的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论
15 楼 啸笑天 2017-03-09  
史上最详细的iOS之事件的传递和响应机制-原理篇
http://www.jianshu.com/p/2e074db792ba
14 楼 啸笑天 2017-03-09  
事件的传递和响应的区别:
事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件。
13 楼 啸笑天 2017-03-09  
如何做到一个事件多个对象处理:
因为系统默认做法是把事件上抛给父控件,所以可以通过重写自己的touches方法和父控件的touches方法来达到一个事件多个对象处理的目的。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// 1.自己先处理事件...
NSLog(@"do somthing...");
// 2.再调用系统的默认做法,再把事件交给上一个响应者处理
[super touchesBegan:touches withEvent:event];
}
12 楼 啸笑天 2017-03-09  
触摸事件处理的整体过程

1>用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件2>找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理touchesBegan…touchesMoved…touchedEnded…3>这些touches方法的默认做法是将事件顺着响应者链条向上传递(也就是touch方法默认不处理事件,只传递事件),将事件交给上一个响应者进行处理
11 楼 啸笑天 2017-03-09  
想让谁成为最合适的view就重写谁自己的父控件的hitTest:withEvent:方法返回指定的子控件,或者重写自己的hitTest:withEvent:方法 return self。但是,建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!
10 楼 啸笑天 2017-03-09  
iOS事件响应链中Hit-Test View的应用
http://www.jianshu.com/p/d8512dff2b3e

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    if ([self pointInside:point withEvent:event]) {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subview convertPoint:point fromView:self];
            UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
    }
    return nil;
}


//in custom button .m
//overide this method
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
    return CGRectContainsPoint(HitTestingBounds(self.bounds, self.minimumHitTestWidth, self.minimumHitTestHeight), point);
}

CGRect HitTestingBounds(CGRect bounds, CGFloat minimumHitTestWidth, CGFloat minimumHitTestHeight) {
    CGRect hitTestingBounds = bounds;
    if (minimumHitTestWidth > bounds.size.width) {
        hitTestingBounds.size.width = minimumHitTestWidth;
        hitTestingBounds.origin.x -= (hitTestingBounds.size.width - bounds.size.width)/2;
    }
    if (minimumHitTestHeight > bounds.size.height) {
        hitTestingBounds.size.height = minimumHitTestHeight;
        hitTestingBounds.origin.y -= (hitTestingBounds.size.height - bounds.size.height)/2;
    }
    return hitTestingBounds;
}


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    /**
     *  此注释掉的方法用来判断点击是否在父View Bounds内,
     *  如果不在父view内,就会直接不会去其子View中寻找HitTestView,return 返回
     */
//    if ([self pointInside:point withEvent:event]) {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subview convertPoint:point fromView:self];
            UIView *hitTestView = [subview hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
//    }
    return nil;
}


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    UIView *hitTestView = [super hitTest:point withEvent:event];
    if (hitTestView) {
        hitTestView = self.scrollView;
    }
    return hitTestView;
}
9 楼 啸笑天 2016-03-03  
Responder Chain简析  http://blog.csdn.net/chun799/article/details/8223612
如果需要将事件传递给next responder,可以直接调用super的对应事件处理方法,super的对应方法将事件传递给next responder,即使用

[super touchesBegan:touches withEvent:event];
不建议直接向nextResponder发送消息,这样可能会漏掉父类对这一事件的其他处理。

[self.nextResponder  touchesBegan:touches withEvent:event];
另外,在定制UIView子类的事件处理方法时,如果其中一个方法没有调用super的对应方法,则其他方法也需要重写,不使用super的方法,否则事件处理流程会很混乱。
8 楼 啸笑天 2016-01-15  
过程应该是 UIView 在接受到 hit-testing 消息后,先是判断自身的 alpha 、userInteractionEnabled、hidden 等属性,如果这些属性不满足要求那么

- (UIView *)hitTest:(CGPoint)*point* withEvent:(UIEvent *)*event;
直接返回 nill ,如果符合要求就掉用

- (BOOL)pointInside:(CGPoint)*point* withEvent:(UIEvent *)*event;
判断事件是否发生在自己这里,如果不在自己这里,就返回 nill ,如果是在自己这里那么就对自己的 SubView 调用

- (UIView *)hitTest:(CGPoint)*point* withEvent:(UIEvent *)*event;
从而得到一个 View 并且返回。
7 楼 啸笑天 2016-01-15  
但是问题来了 hit-testing 是以什么顺序找 SubView 的呢。就是你添加 SubView 的逆序来遍历的,换句话说就是从最顶层的 SubView 开始找。
http://www.jianshu.com/p/c5fee92ddf31
6 楼 啸笑天 2016-01-15  
在遍历子视图时会按照层级从高到低的顺序,一旦有视图可以接受此次事件,就不会再往下遍历。
5 楼 啸笑天 2016-01-15  
手势UIGestureRecognizer对象也可以附加在view上,来实现其他丰富的手势事件。在view添加单击手势之后,原来的touchesEnded方法就无效了。最开始我一直认为view添加手势之后,原有的touches系列方法全部无效。但是在测试demo中,发现view添加手势之后,touchesBegan方法是有进行回调的,但是moved跟ended就没有进行回调。
4 楼 啸笑天 2016-01-15  
事件对象
iOS使用UIEvent表示用户交互的事件对象,在UIEvent.h文件中,我们可以看到有一个UIEventType类型的属性,这个属性表示了当前的响应事件类型。分别有多点触控、摇一摇以及远程操作(在iOS之后新增了3DTouch事件类型)。在一个用户点击事件处理过程中,UIEvent对象是唯一的
点击对象
UITouch表示单个点击,其类文件中存在枚举类型UITouchPhase的属性,用来表示当前点击的状态。这些状态包括点击开始、移动、停止不动、结束和取消五个状态。每次点击发生的时候,点击对象都放在一个集合中传入UIResponder的回调方法中,我们通过集合中对象获取用户点击的位置。其中通过- (CGPoint)locationInView:(nullable UIView *)view获取当前点击坐标点,- (CGPoint)previousLocationInView:(nullable UIView *)view获取上个点击位置的坐标点。
3 楼 啸笑天 2016-01-15  
在iOS中,能够响应事件的对象都是UIResponder的子类对象。UIResponder提供了四个用户点击的回调方法,分别对应用户点击开始、移动、点击结束以及取消点击,其中只有在程序强制退出或者来电时,取消点击事件才会调用。
2 楼 啸笑天 2016-01-15  
操作系统把包含这些点击事件的信息包装成UITouch和UIEvent形式的实例,然后找到当前运行的程序,逐级寻找能够响应这个事件的对象,直到没有响应者响应。这一寻找的过程,被称作事件的响应链,如下图所示,不用的响应者以链式的方式寻找
1 楼 啸笑天 2016-01-15  
http://www.jianshu.com/p/a8926633837b 
http://www.2cto.com/kf/201504/388332.html

相关推荐

    iOS和H5页面交互拦截

    本主题将详细讲解如何实现iOS与H5页面之间的事件拦截和实时通信。 首先,iOS与H5交互的基础是WebView。在iOS应用中,我们通常使用UIWebView或WKWebView来加载和显示HTML内容。这两个控件提供了JavaScriptCore框架,...

    ios电话拦截

    在iOS系统中,电话拦截是一项重要的功能,它旨在帮助用户管理来电,避免不必要的打扰,特别是来自骚扰电话或诈骗电话的侵扰。iOS电话拦截通过内置的屏蔽机制和第三方应用程序实现,为用户提供了一套完整的防骚扰解决...

    iOS5短信拦截小demo

    【iOS5短信拦截小demo】是一个面向iOS平台的示例项目,主要展示了如何在iOS系统中实现短信的拦截功能。这个项目可能适用于开发者或者对iOS系统底层操作感兴趣的用户,特别是那些想要了解或开发类似功能的人。 在iOS...

    IOS 5 拦截手机短信(需越狱)

    【标题】"IOS 5 拦截手机短信(需越狱)" 描述了在iOS 5系统上通过越狱手段实现对手机短信的拦截这一技术主题。在苹果的封闭式操作系统环境下,用户通常无法直接访问或修改系统底层功能,但通过越狱,开发者和高级用户...

    ios-将系统返回手势拦截到自定义手势上(全屏返回).zip

    在iOS开发中,手势交互是用户体验的重要组成部分。本教程聚焦于如何将系统内置的导航控制器(NavController)的返回手势拦截并映射到自定义的手势识别器(GestureRecognizer),特别是全屏返回手势。这一技巧可以让...

    iOS 拦截奔溃 使程序不在崩溃

    Runloop是iOS中的一个核心组件,负责管理应用程序的事件处理。通过在Runloop中添加观察者,我们可以在程序即将退出时获取通知,并采取措施防止奔溃。 以下是一个使用Runloop防止奔溃的例子: ```objc - (void)...

    swift-系统返回按钮事件拦截Swift版本

    本文将深入探讨如何在Swift中实现系统返回按钮事件的拦截。 首先,我们需要理解的是,iOS中的导航控制器(UINavigationController)默认提供了左侧的返回按钮,这个按钮的行为通常是返回上一级视图控制器。在Swift...

    iOS UIWebView URL拦截.pdf

    为了实现这一需求,文中提出了通过URL拦截的方法来解决。 首先,我们需要了解iOS中的URL Loading System,这是一个系统级别的网络请求框架,UIWebView正是利用这个系统来加载网页内容。NSURLCache作为URL Loading ...

    iOS安全之拦截http请求 ( 为小白用户定制的精简版本)

    1、基于NSURLProtocol拦截请求: HTTP 请求开始时,URL 加载系统创建一个合适的 NSURLProtocol 对象处理对应的 URL 请求,因此我们只需写一个继承自 NSURLProtocol 的类,并通过 - registerClass: 方法注册我们的...

    iOS oc拦截网页wkwebview视频内容 的demo

    "iOS oc拦截网页wkwebview视频内容的demo"是一个示例项目,它展示了如何利用Objective-C(oc)来拦截WKWebView加载的网页中的视频内容。WKWebView是苹果提供的一个高级组件,用于在iOS应用中渲染网页,它相比...

    iOS拦截 HTTP 请求demo源码:修改请求的HTTPHeaderField,设置代理IP和端口

    版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/z929118967/article/details/115690756

    iOS和JS的交互之在代理方法拦截Url,识别判断

    本文将深入探讨如何在代理方法中拦截URL,以实现iOS和JS之间的有效通信。首先,我们需要理解iOS中的WKWebView组件,它是苹果提供的用于加载和呈现Web内容的工具,它支持与JavaScript的深度集成。 ### WKWebView简介...

    iOS安全之【拦截请求,实现特定目的 】(修改HTTPHeaderField、不走全局proxy、设置代理IP和端口、对网络请求的数据进行报文级别的加密)

    2、应用场景: 2.1、 自定义请求头的HTTPHeaderField 2.2、针对NSURLSessionConfiguration设置代理IP和端口,让一些特殊的请求走自定义的隧道IP和端口 ...3、原理:利用NSURLProtocol 拦截 HTTP 请求

    iOS程序异常crash捕获与拦截

    本文将深入探讨iOS程序异常crash的捕获与拦截机制,以及如何通过源码和工具来实现这一目标。 一、异常处理基础 1. 异常体系:iOS中的异常处理基于Objective-C的异常体系,它通过抛出(throw)、捕获(catch)和...

    iOS 解决侧滑返回各种不兼容问题

    在iOS开发中,侧滑返回(Swipe Back)是苹果提供的一种常见手势,让用户可以方便地在导航控制器的视图之间切换。然而,在某些特定场景下,如使用ScrollView或地图组件时,侧滑返回可能会与其他交互产生冲突,导致不...

    iOS9.3.3骚扰电话拦截黑名单数据库

    iOS9.3.3骚扰电话拦截黑名单数据库

    iOS使用 NSURLProtocol 拦截 HTTP 请求的简单例子

    2、原理:利用NSURLProtocol 拦截 HTTP 请求 3、应用场景:隧道APP请求我们自己接口的都不走隧道、修改请求的HTTPHeaderField,设置代理IP和端口、防抓包(使Thor,Charles,Burp等代理抓包方式全部失效)

    IOS开发webview强制视频内联播放(在没有设置webview.allowsInlineMediaPlayback的情况下也有效)!

    3. 触发播放:库可能还会处理播放事件,确保视频在合适的时机开始播放,避免因为自动播放策略而被阻止。 引入JavaScript库的方式有两种常见方法: - 直接在HTML文件中通过`&lt;script&gt;`标签引入库。 - 通过Webview的`...

    详解如何拦截iOS所有网络请求

    iOS 网络请求拦截详解 iOS 平台上的网络请求拦截是移动应用开发中的一项重要技术。通过拦截网络请求,可以实现统计所有的网络请求,了解应用程序的网络行为,从而优化应用程序的性能和用户体验。在本文中,我们将...

Global site tag (gtag.js) - Google Analytics