溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ios響應(yīng)鏈的工作原理是什么

發(fā)布時(shí)間:2023-05-11 17:48:10 來(lái)源:億速云 閱讀:162 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下ios響應(yīng)鏈的工作原理是什么的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

事件響應(yīng)鏈的工作原理

iOS 中,事件響應(yīng)鏈的工作原理可以簡(jiǎn)單概括為:從最上層的 UIWindow 開始,依次向下傳遞事件,直到找到最適合處理事件的響應(yīng)者對(duì)象為止。在這個(gè)過(guò)程中,每個(gè)響應(yīng)者對(duì)象都有機(jī)會(huì)處理事件。

當(dāng)用戶執(zhí)行一個(gè)操作時(shí),如觸摸屏幕或運(yùn)動(dòng)設(shè)備,系統(tǒng)會(huì)創(chuàng)建一個(gè) UIEvent 對(duì)象,并將其發(fā)送到當(dāng)前的第一響應(yīng)者對(duì)象。如果第一響應(yīng)者對(duì)象無(wú)法處理該事件,則系統(tǒng)會(huì)將該事件傳遞給響應(yīng)者鏈中的下一個(gè)對(duì)象,直到找到能夠處理該事件的對(duì)象。如果最終沒(méi)有對(duì)象能夠處理該事件,則事件被系統(tǒng)丟棄。

以下是事件響應(yīng)鏈的示意圖:

         UIWindow
             |
       UIViewController
             |
           UIView
             |
     subviews of UIView

在這個(gè)示意圖中,UIWindow 是響應(yīng)者鏈的起點(diǎn),它是所有視圖的根視圖。UIViewControllerUIView 都是響應(yīng)者對(duì)象,它們都可以處理事件。UIViewController 可以接收和處理來(lái)自其根視圖的事件,而 UIView 可以接收和處理來(lái)自其自身的事件,以及來(lái)自其子視圖的事件。

響應(yīng)者對(duì)象的特點(diǎn)

響應(yīng)者對(duì)象是一種特殊類型的對(duì)象,它們實(shí)現(xiàn)了 UIResponder 類。響應(yīng)者對(duì)象可以處理事件,可以成為第一響應(yīng)者對(duì)象,并且可以將事件傳遞給下一個(gè)響應(yīng)者對(duì)象。以下是 UIResponder 類中的一些常用方法:

  • canBecomeFirstResponder:返回一個(gè)布爾值,指示對(duì)象是否可以成為第一響應(yīng)者對(duì)象。

  • becomeFirstResponder:將對(duì)象設(shè)置為第一響應(yīng)者對(duì)象。

  • resignFirstResponder:放棄第一響應(yīng)者對(duì)象的地位。

  • next:返回響應(yīng)者鏈中的下一個(gè)響應(yīng)者對(duì)象。

響應(yīng)者對(duì)象還可以實(shí)現(xiàn)許多方法來(lái)處理事件,例如:

  • touchesBegan(_:with:):當(dāng)用戶在視圖上開始觸摸時(shí)調(diào)用。

  • touchesMoved(_:with:):當(dāng)用戶在視圖上移動(dòng)觸摸時(shí)調(diào)用。

  • touchesEnded(_:with:):當(dāng)用戶在視圖上結(jié)束觸摸時(shí)調(diào)用。

  • touchesCancelled(_:with:):當(dāng)系統(tǒng)取消觸摸事件時(shí)調(diào)用。

自定義事件處理

Swift 中,可以通過(guò)重寫 UIResponder 子類的方法來(lái)自定義事件處理。以下是一個(gè)示例代碼,展示如何重寫 UIView 子類的 touchesBegan 方法來(lái)處理觸摸事件:

class CustomView: UIView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        // 處理觸摸事件
        // ...
    }
}

在這個(gè)示例中,當(dāng)用戶在 CustomView 上開始觸摸時(shí),系統(tǒng)會(huì)調(diào)用 CustomViewtouchesBegan 方法。在此方法中,開發(fā)者可以編寫自己的觸摸事件處理代碼。

事件傳遞和事件響應(yīng)

事件傳遞和事件響應(yīng)是事件響應(yīng)鏈的兩個(gè)重要環(huán)節(jié)。在事件傳遞階段,系統(tǒng)會(huì)將事件從上往下傳遞,直到找到最適合處理事件的對(duì)象。在事件響應(yīng)階段,系統(tǒng)會(huì)將事件從下往上響應(yīng),直到事件被處理或者傳遞到響應(yīng)者鏈的頂部。

在事件傳遞階段,UIViewUIViewController 都有一個(gè) hitTest( *:with:) 方法,該方法返回一個(gè) UIView 對(duì)象。當(dāng)系統(tǒng)接收到事件時(shí),它會(huì)調(diào)用 hitTest(* :with:) 方法來(lái)確定最適合處理該事件的視圖對(duì)象。hitTest( *:with:) 方法首先檢查自己是否能夠處理該事件,如果不能,它會(huì)將事件傳遞給其子視圖,并遞歸調(diào)用子視圖的 hitTest(* :with:) 方法,直到找到能夠處理該事件的視圖對(duì)象。

在事件響應(yīng)階段,系統(tǒng)會(huì)將事件傳遞到第一響應(yīng)者對(duì)象,并沿著響應(yīng)者鏈向上傳遞,直到事件被處理或者傳遞到響應(yīng)者鏈的頂部。在這個(gè)過(guò)程中,每個(gè)響應(yīng)者對(duì)象都有機(jī)會(huì)處理事件。如果某個(gè)響應(yīng)者對(duì)象能夠處理事件,則它將調(diào)用相應(yīng)的方法來(lái)處理事件,例如 touchesBegan(_:with:) 方法。如果該對(duì)象不能處理事件,則它將調(diào)用 next 方法,將事件傳遞給響應(yīng)者鏈中的下一個(gè)對(duì)象。

事件攔截

hitTest(_:with:) 方法中,我們可以檢查觸摸點(diǎn)是否在指定區(qū)域內(nèi),如果在,則返回當(dāng)前視圖作為攔截目標(biāo),否則返回 nil,讓系統(tǒng)將事件傳遞給下一個(gè)響應(yīng)者。示例代碼如下:

class CustomView: UIView {
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if self.bounds.contains(point) {
            // 觸摸點(diǎn)在視圖內(nèi),攔截事件
            return self
        } else {
            // 觸摸點(diǎn)不在視圖內(nèi),將事件傳遞給下一個(gè)響應(yīng)者
            return super.hitTest(point, with: event)
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        print("CustomView touchesBegan")
    }
 
}

在上述代碼中,我們重寫了 hitTest( *:with:) 方法,并在該方法中檢查觸摸點(diǎn)是否在視圖內(nèi)。如果在,則返回當(dāng)前視圖作為攔截目標(biāo),否則返回 nil,讓系統(tǒng)將事件傳遞給下一個(gè)響應(yīng)者。在 touchesBegan(* :with:) 方法中,我們打印了一條日志,以便在觸摸事件發(fā)生時(shí)能夠看到該方法是否被調(diào)用。

事件傳遞到父視圖

要將事件傳遞到父視圖,可以調(diào)用 next?.touchesBegan(touches, with: event) 方法,讓父視圖處理觸摸事件。示例代碼如下:

class CustomView: UIView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        // 處理觸摸事件
        // 如果無(wú)法處理該事件,傳遞給父視圖進(jìn)行處理
        next?.touchesBegan(touches, with: event)
    }
}

class ParentView: UIView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        // 處理觸摸事件
    }
}

在上面的示例中,CustomViewParentView 都是 UIView 的子類。當(dāng)用戶在 CustomView 上觸摸時(shí),CustomViewtouchesBegan 方法會(huì)被調(diào)用。在這個(gè)方法中,如果 CustomView 無(wú)法處理該事件,它會(huì)將該事件傳遞給其父視圖(ParentView)進(jìn)行處理。

通過(guò) next?.touchesBegan(touches, with: event) 方法將事件傳遞給父視圖,如果父視圖能夠處理該事件,它的 touchesBegan 方法將被調(diào)用。在這個(gè)方法中,可以處理觸摸事件。如果父視圖仍然無(wú)法處理該事件,該事件將被傳遞給更高級(jí)別的響應(yīng)對(duì)象進(jìn)行處理。

需要注意的是,當(dāng)事件被傳遞到下一個(gè)響應(yīng)對(duì)象時(shí),會(huì)調(diào)用該對(duì)象的 touchesBegan 方法。因此,在這個(gè)方法中,可以對(duì)事件進(jìn)行處理,也可以將其傳遞給更高級(jí)別的響應(yīng)對(duì)象進(jìn)行處理。

自定義事件響應(yīng)鏈

iOS 中,每個(gè)視圖都是一個(gè) UIResponder 對(duì)象。UIResponder 是一個(gè)抽象類,它定義了響應(yīng)者對(duì)象可以處理的事件類型,包括觸摸事件、加速計(jì)事件、遠(yuǎn)程控制事件等。每個(gè) UIResponder 對(duì)象都有一個(gè) next 響應(yīng)者,即下一個(gè)響應(yīng)者對(duì)象。當(dāng)一個(gè)事件發(fā)生時(shí),系統(tǒng)會(huì)將該事件從前往后依次傳遞給響應(yīng)者鏈中的對(duì)象,直到某個(gè)對(duì)象處理了該事件為止。如果沒(méi)有任何對(duì)象處理該事件,則該事件將被丟棄。

我們可以通過(guò)自定義 UIResponder 子類來(lái)實(shí)現(xiàn)更靈活的事件處理邏輯。下面是一個(gè)簡(jiǎn)單的自定義響應(yīng)者鏈的示例代碼:

class CustomResponder: UIResponder {
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        print("CustomResponder touchesBegan")
        next?.touchesBegan(touches, with: event)
    }
    
}

class ViewController: UIViewController {
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        print("ViewController touchesBegan")
    }
    
}

在上面的代碼中,我們定義了一個(gè)名為 CustomResponder 的自定義響應(yīng)者子類。在該類中,我們重寫了 touchesBegan(_:with:) 方法,并在該方法中打印了一條日志。在該方法中,我們還調(diào)用了 next?.touchesBegan(touches, with: event) 方法,將觸摸事件傳遞給下一個(gè)響應(yīng)者對(duì)象。

在 ViewController 中,我們也重寫了 touchesBegan( *:with:) 方法,并在該方法中打印了一條日志。當(dāng)觸摸事件發(fā)生時(shí),首先會(huì)調(diào)用 CustomRespondertouchesBegan(* :with:) 方法,并打印出 "CustomResponder touchesBegan"。然后,由于我們調(diào)用了 next?.touchesBegan(touches, with: event) 方法,系統(tǒng)會(huì)將觸摸事件傳遞給 CustomResponder 的下一個(gè)響應(yīng)者對(duì)象,即 ViewController。此時(shí),系統(tǒng)會(huì)調(diào)用 ViewControllertouchesBegan(_:with:) 方法,并打印出 "ViewController touchesBegan"。

通過(guò)自定義響應(yīng)者子類,我們可以更加靈活地處理事件,實(shí)現(xiàn)更復(fù)雜的事件處理邏輯。例如,我們可以在響應(yīng)者鏈中添加多個(gè)響應(yīng)者對(duì)象,根據(jù)事件類型、觸摸點(diǎn)位置等條件來(lái)決定哪個(gè)響應(yīng)者對(duì)象處理該事件。

以上就是“ios響應(yīng)鏈的工作原理是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

ios
AI