iOS問(wèn)題解決(二):自定義UIView不響應(yīng)touchesBegan事件

iOS開(kāi)發(fā)中會(huì)使用到自定義UIView,下面是我在學(xué)習(xí)過(guò)程中寫(xiě)的一個(gè)自定義UIView:

#import "BNRHypnosisView.h"

@interface BNRHypnosisView()

@property(nonatomic, strong) UIColor *circleColor;

@end

@implementation BNRHypnosisView

- (void)setCircleColor:(UIColor *)circleColor {
    _circleColor = circleColor;
    [self setNeedsDisplay];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        self.circleColor = [UIColor lightGrayColor];
        //self.userInteractionEnabled = YES; //開(kāi)啟用戶交互仍然不能響應(yīng)touchesBegan事件
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef cgContext = UIGraphicsGetCurrentContext();

    CGRect bounds = self.bounds;
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;

    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;

    UIBezierPath *path = [[UIBezierPath alloc] init];
    
   for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -=     20) {
        [path moveToPoint:CGPointMake(center.x + currentRadius, center.y)];
        [path addArcWithCenter:center radius:currentRadius startAngle:0.0   endAngle:M_PI*2.0 clockwise:YES];
    }

    [self.circleColor setStroke];

    path.lineWidth = 10.0;

    [path stroke];


    CGContextSaveGState(cgContext);
    CGContextSetShadow(cgContext, CGSizeMake(4, 7), 3);

    UIImage *logoImage = [UIImage imageNamed:@"logo.png"];

    [logoImage drawInRect:rect];

    CGContextRestoreGState(cgContext);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent   *)event {

    NSLog(@"%@ was touched", self);

    float red = (arc4random() % 100) / 100.0;
    float green = (arc4random() % 100) / 100.0;
    float blue = (arc4random() % 100) / 100.0;

    UIColor *randomColor = [UIColor colorWithRed:red
                                       green:green blue:blue alpha:1.0];
    self.circleColor = randomColor;
}

@end

在AppDelegate中使用這個(gè)自定義UIView,代碼如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    NSArray *windows = [[UIApplication sharedApplication] windows];
    for(UIWindow *window in windows) {
        if(window.rootViewController == nil){
            UIViewController *vc = [[UIViewController alloc]initWithNibName:nil
                                                                 bundle:nil];
            window.rootViewController = vc;
        }
    }

    CGRect firstFrame = self.window.bounds;
    BNRHypnosisView *firstView = [[BNRHypnosisView alloc] initWithFrame:firstFrame];

   [self.window addSubview:firstView];


    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

看似很完美的代碼,但是一運(yùn)行,無(wú)法響應(yīng)touchesBegan事件,開(kāi)始以為是沒(méi)有開(kāi)啟用戶交互,加上開(kāi)啟用戶交互self.userInteractionEnabled = YES,仍然沒(méi)用,后來(lái)有人說(shuō)是這個(gè)自定義UIView視圖被遮擋,導(dǎo)致無(wú)法響應(yīng)觸摸事件,給了我開(kāi)啟視圖調(diào)試器調(diào)試看看的建議,果然,開(kāi)啟視圖調(diào)試器看到這個(gè)自定義UIView確實(shí)被遮擋了,如下圖所示:

viewdebug.png

該怎么解決呢?有人說(shuō)是[self.window makeKeyAndVisible]出了問(wèn)題,他會(huì)把window的rootViewController放到最前面,但我想這肯定是沒(méi)讀懂官方文檔對(duì)makeKeyAndVisible方法的解釋?zhuān)缦聢D所示:

makeKeyAndVisible.png

它是UIWindow對(duì)象的一個(gè)實(shí)例方法,是把當(dāng)前window置于其他window的前面,也就是說(shuō)是把整個(gè)包含了我的自定義UIView的window對(duì)象置于最前面,所以,即使注釋掉這行代碼,仍然無(wú)法解決我的自定義UIView被遮擋的問(wèn)題。

那么問(wèn)題出在哪里呢?對(duì),問(wèn)題就出在AppDelegate的下面這段代碼中:

NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow *window in windows) {
    if(window.rootViewController == nil){
        UIViewController *vc = [[UIViewController alloc]initWithNibName:nil
                                                                 bundle:nil];
        window.rootViewController = vc; 
    }
}
rootViewController.jpeg

根據(jù)上圖所示官方文檔對(duì)rootViewController的說(shuō)明,可以知道設(shè)置了window.rootViewController會(huì)給window設(shè)定一個(gè)content view。根據(jù)視圖調(diào)試器顯示出來(lái)的內(nèi)容,這個(gè)content view應(yīng)該也就是一個(gè)UIView。所以當(dāng)這個(gè)自定義的UIView添加到self.window上,代碼如下所示:

CGRect firstFrame = self.window.bounds;
BNRHypnosisView *firstView = [[BNRHypnosisView alloc] initWithFrame:firstFrame];

[self.window addSubview:firstView];

這個(gè)自定義UIView就會(huì)被rootViewController設(shè)定的content view遮擋,就不能響應(yīng)觸摸事件了。

因此,解決這個(gè)問(wèn)題修改后的關(guān)鍵代碼如下所示:

CGRect firstFrame = self.window.bounds;
BNRHypnosisView *firstView = [[BNRHypnosisView alloc] initWithFrame:firstFrame];

[self.window.rootViewController.view addSubview:firstView];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,242評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,229評(píng)論 4 61
  • 自我覺(jué)得自己是特能吃苦的女生,總感覺(jué)自己已經(jīng)很闖蕩了,可當(dāng)面臨一些自己從沒(méi)做過(guò)的事情就開(kāi)始畏懼了。 ...
    夏莉沫花閱讀 663評(píng)論 1 0
  • 在我年輕的時(shí)候,詩(shī)歌和詩(shī)人,都是受尊敬的詞語(yǔ),我的同齡人里,誰(shuí)的枕邊沒(méi)有一本抄寫(xiě)著各種感動(dòng)句子的筆記本?同學(xué)之間的...
    曾穎閱讀 277評(píng)論 2 2
  • 看著他日益蒼老的臉龐,和佝僂的背,淚腺總感覺(jué)開(kāi)了閘道一般,嘩嘩的往下掉。 以前他嗜酒如命,與煙為友,我總覺(jué)得他...
    伊茶芽閱讀 167評(píng)論 0 0