今天寫了這麼一小段測試代碼,如下:
[cpp]
CGRect imageRect = (CGRect){100, 100, 100, 100};
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:imageRect] autorelease];
imageView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:imageView];
UIButton *maskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
maskBtn.frame = imageView.bounds;
maskBtn.backgroundColor = [UIColor redColor];
[maskBtn addTarget:self action:@selector(maskBtnDidClick:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:maskBtn];
結果點擊按鈕不響應事件,小糾結了一下,在SO上得到信息:
UIImageView has userInteractionEnabled set to NO by default. You are adding the button as a subview to the image view. You should set it to YES.
所以,添加了一行代碼,設置imageView響應用戶交互即可:
[cpp]
CGRect imageRect = (CGRect){100, 100, 100, 100};
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:imageRect] autorelease];
imageView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:imageView];
imageView.userInteractionEnabled = YES;
UIButton *maskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
maskBtn.frame = imageView.bounds;
maskBtn.backgroundColor = [UIColor redColor];
[maskBtn addTarget:self action:@selector(maskBtnDidClick:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:maskBtn];
這純粹就是一個知識點引發的坑,因為以前在UIImageView上都是使用TapGesture來響應用戶交互的,所以對這個坑沒有太大印象 —— 我遇到過沒?
上面代碼所構建的視圖層級大致如下:
其中紅色方框代表的是UIImageView上的UIButton按鈕。
參考View Programming Guide for iOS文檔,當用戶在紅色按鈕上點擊了一下後:
1. 硬件設施會通知UIKit有觸摸事件;
2. UIKit將觸摸事件信息封裝成UIEvent對象,分發給合適的視圖;
1) UIKit將事件對象放到當前App的事件隊列中;
2) 參考Event Handling Guide for iOS文檔,當前App會從事件隊列取出一個事件對象,然後發送給key window對象;
3) key window對象通過Hit-Testing獲取觸摸事件發生時所在的視圖對象;
4) 通過Hit-Testing獲得的視圖成為第一個可以響應事件的對象,first responder,如果它不響應,則事件對象會沿著響應者鏈傳遞。響應者鏈,即Responder Chain,是由first responder到當前App對象所構成的一串對象,它們都繼承於UIResponder類;
P.S. 具體描述可以見此文檔。
3. 找到合適的處理事件的對象,比如上面代碼是self(ViewController),響應事件做些事情;如果找不到就丟棄掉。