国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > iOS > 正文

解析iOS開發(fā)中的FirstResponder第一響應對象

2020-07-26 03:33:21
字體:
供稿:網(wǎng)友

1. UIResonder

對于C#里所有的控件(例如TextBox),都繼承于Control類。而Control類的繼承關系如
下:

復制代碼 代碼如下:

System.Object

  System.MarshalByRefObject

    System.ComponentModel.Component

      System.Windows.Forms.Control


對于iOS里的UI類,也有類似的繼承關系。

例如對于UITextField,繼承于UIControl;UIControl繼承于UIView,UIView繼承于UIRe
sponder,UIResponder繼承于NSObject。

具體架構可以參見:

http://developer.apple.com/library/ios/#documentation/general/conceptual/Devp
edia-CocoaApp/Responder.html

UIResponder是UIKit框架中的類(Mac OS X Cocoa對應的是AppKit框架)。

 

2. 第一響應對象

在應用的響應對象里,會有一個成為第一響應對象。

第一響應對象和其他響應對象之間有什么區(qū)別?對于普通的觸摸事件沒什么區(qū)別。就算
我把一個按鈕設置成第一響應對象,當我點擊其他按鈕時,還是會響應其他按鈕,而不
會優(yōu)先響應第一響應對象。

第一響應對象的區(qū)別在于負責處理那些和屏幕位置無關的事件,例如搖動。

蘋果官方文檔的說法是:第一響應對象是窗口中,應用程序認為最適合處理事件的對象

一個班只能有一個班長,應用的響應對象中,只能有一個響應對象成為第一響應對象。

 

3. 成為與取消第一響應對象。

要當?shù)谝豁憫獙ο螅€需要有View來毛遂自薦:

復制代碼 代碼如下:

- (BOOL) canBecomeFirstResponder
{
    returnYES;
}

如果缺少了這段,就算用[view becomeFirstResponder]也不能讓一個view成為第一響應
對象。。。強扭的瓜不甜?好吧不是這個原因。大多數(shù)視圖默認只關心與自己有關聯(lián)的
事件,并且(幾乎)總是有機會來處理這些事件。以UIButton為例,當用戶單擊某個UIB
utton對象時,無論當前的第一響應對象是哪個視圖,該對象都會收到指定的動作消息。
當上第一響應對象吃力不討好么。。。所以只能由某個UIResponder明確表示自己愿意成
為第一響應對象才行。(我不知道設計上是基于什么考慮。。。安全?)

 

在當上第一響應對象時,不同對象可能會有一些特殊的表現(xiàn)。例如UITextField當上的時
候,就會調(diào)出一塊小鍵盤。

第一響應對象也有可能被辭退。發(fā)送一個resignFirstResponder,就可以勸退。

 

4. 第一響應對象的任務

剛才說了第一響應對象可以處理搖動。就來看個范例吧:

 

復制代碼 代碼如下:

- (void) motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if(motion == UIEventSubtypeMotionShake)
    {
        NSLog(@"Device is beginning to shake");
        [selfsetCircleColor:[UIColorredColor]];
        [selfsetNeedsDisplay];
    }
}

當搖動開始時觸發(fā)某些行為。

 

5. 獲取當前第一響應對象

源自這篇討論:http://stackoverflow.com/questions/1823317/get-the-current-firs
t-responder-without-using-a-private-api

提問的家伙用了如下的方式來獲取

復制代碼 代碼如下:

UIView   *firstResponder = [keyWindow
performSelector:@selector(firstResponder)];

結果被蘋果打回來,說用了非公開的API。。。

于是這家伙只好苦逼地用遞歸了:

復制代碼 代碼如下:

implementationUIView (FindFirstResponder)
- (UIView *)findFirstResponder
{
    if (self.isFirstResponder) {       
        return self;    
    }
    for (UIView *subView in self.subviews) {
        UIView *firstResponder = [subView findFirstResponder];
        if (firstResponder != nil) {
            return firstResponder;
        }
    }
    return nil;
}
@end

6.View的FirstResponder的釋放問題
今天遇到一個問題,當我隱藏掉一個正在接受用戶輸入的UITextField的時候,鍵盤并不會消失,而且鍵盤仍然接受用戶輸入,再次顯示該TextField時候發(fā)現(xiàn)在隱藏狀態(tài)下,所有的輸入仍然傳輸?shù)搅嗽揟extField中,于是查下官方資料找到如下解釋:
 
Important If you hide a view that is currently the first responder, the view does not automatically resign its first responder status. Events targeted at the first responder are still delivered to the hidden view. To prevent this from happening, you should force your view to resign the first responder status when you hide it.   
 
  意思是如果這個View是當前的第一響應者的時候,隱藏該View并不會自動放棄其第一響應者的身份,而且會繼續(xù)以第一響應者的身份接受消息。我們可以通過在隱藏View之前,手動調(diào)用resignFirstResponder來強制該view放棄第一響應者身份。
 
  下面請看小例子:

復制代碼 代碼如下:

SvTestFirstResponder.h

//
//  SvTestFirstResponder.h
//
//  Created by maple on 3/15/12.
//  Copyright (c) 2012 SmileEvday. All rights reserved.
//
//  當一個view時當前響應者時,調(diào)用其hidden方法并不會自動放棄第一響應者身份,所有的消息仍然會發(fā)送到這個view
//  可以通過在hidden前強制放棄第一響應者,恢復正常的消息傳遞
//

#import <UIKit/UIKit.h>

@interface SvTestFirstResponder : UIView {
    UITextField *_inputField;
}

@end


復制代碼 代碼如下:

SvTestFirstResponder.m

//
//  SvTestFirstResponder.m
//
//  Created by maple on 3/15/12.
//  Copyright (c) 2012 SmileEvday. All rights reserved.
//

#import "SvTestFirstResponder.h"

@interface SvTestFirstResponder()

- (void)hiddenInputView:(id)sender;
- (void)showInputView:(id)sender;

@end

@implementation SvTestFirstResponder

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
       
        _inputField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
        _inputField.center = CGPointMake(160, 50);
        [_inputField setFont:[UIFont systemFontOfSize:24]];
        _inputField.text = @"input you text";
        _inputField.clearsOnBeginEditing = YES;
        _inputField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
        _inputField.borderStyle = UITextBorderStyleRoundedRect;
        [self addSubview:_inputField];
        _inputField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
       
        UIButton *hiddenBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        hiddenBtn.frame = CGRectMake(0, 0, 115, 40);
        hiddenBtn.center = CGPointMake(80, 110);
        [hiddenBtn setTitle:@"Hide TextField" forState:UIControlStateNormal];
        [hiddenBtn addTarget:self action:@selector(hiddenInputView:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:hiddenBtn];
        hiddenBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
        hiddenBtn.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
       
        UIButton *showBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        showBtn.frame = CGRectMake(0, 0, 115, 40);
        showBtn.center = CGPointMake(240, 110);
        [showBtn setTitle:@"Show TextField" forState:UIControlStateNormal];
        [showBtn addTarget:self action:@selector(showInputView:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:showBtn];
        showBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
        showBtn.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

- (void)hiddenInputView:(id)sender
{
    _inputField.hidden = YES;
}

- (void)showInputView:(id)sender
{
    _inputField.hidden = NO;
}

@end

這個簡單的例子中,當輸入框進入接受用戶輸入狀態(tài)的時候,點擊hide按鈕,鍵盤并不會消失而且會繼續(xù)接收用戶輸入并且將用戶輸入傳到TextField中去,后面再點擊Show按鈕的時候你會發(fā)現(xiàn)所有在隱藏狀態(tài)下輸入的文字都已經(jīng)成功的被接收。我們可以修改hide方法如下:
 

復制代碼 代碼如下:

- (void)hiddenInputView:(id)sender

{

    if (_inputField.isFirstResponder) {

        [_inputField resignFirstResponder];

    }

    _inputField.hidden = YES;

}

  這樣就可以在隱藏之前強制釋放第一響應者身份,這個問題比較細節(jié),但有時候可能就是這種細節(jié)問題導致一些莫名奇妙的問題,在隱藏一些可能成為第一響應者的view之前添加強制釋放第一響應者身份,可能會幫我們避免一些奇怪的問題,而且也幾乎不會有什么開銷,何樂而不為呢。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 肇州县| 含山县| 澄城县| 商丘市| 津市市| 太湖县| 龙井市| 阳朔县| 岗巴县| 大足县| 武清区| 绩溪县| 德江县| 舟山市| 潍坊市| 获嘉县| 望城县| 巴中市| 堆龙德庆县| 桦川县| 无锡市| 永昌县| 南靖县| 凤庆县| 什邡市| 班戈县| 池州市| 揭东县| 库车县| 沁源县| 汨罗市| 钟祥市| 阿克| 康乐县| 三明市| 定襄县| 宁明县| 永城市| 海淀区| 弋阳县| 合作市|