iOS中的事件

語言: CN / TW / HK

highlight: a11y-dark theme: cyanosis


「這是我參與11月更文挑戰的第23天,活動詳情檢視:2021最後一次更文挑戰

iOS中的事件

  • 在使用者使用APP過程中,會產生各種各樣的事件,可以分為三大類
  • 觸控事件(如點選...)
  • 加速器事件(如搖一搖...)
  • 遠端控制事件(如耳機可以控制手機音量...)

響應者物件(UIResponder)

說到觸控事件,首先需要了解一個概念:響應者物件

  • 在iOS中不是任何物件都能處理事件,只有繼承了 UIResponder 的物件才能接收並處理事件,通常被稱為“響應者物件”。如 UIApplicationUIViewControllerUIView 等等

  • UIResponder 內部提供了以下方法來處理事件

  • 觸控事件 ```js

    • (void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event; ```
  • 加速器事件

    js - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event; - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event; - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event; - 遠端控制方法

    js - (void)remoteControlReceivedWithEvent:(UIEvent *)event;


UIView 的觸控事件處理

  • UIViewUIResponder 的子類,可以覆蓋以下4個方法處理不同的觸控事件

  • 一根或者多根手指開始觸控 view,系統會自動呼叫 view 的下面方法 ```js

    • (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event; ```
  • 一根或者多根手指在 view 上移動,系統會自動呼叫 view 的下面方法 ```js
    • (void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event; ```
  • 一根或者多根手指離開 view,系統會自動呼叫 view 的下面方法 js - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
  • 觸控結束前,某個系統事件(例如電話呼入)會打斷觸控過程,系統會自動呼叫 view 的下面方法 ```js
    • (void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event; ```

UITouch

  • 當用戶用一根手指觸控式螢幕幕時,會建立一個與手指關聯的 UITouch 物件
  • 一根手指對應一個 UITouch 物件
  • UITouch 的作用:儲存著跟手指相關的資訊,比如觸控的位置、時間、階段
  • 當手指移動時,系統會更新同一個 UITouch 物件,使之能夠一直儲存該手指在的觸控位置
  • 當手指離開螢幕時,系統會銷燬相應的 UITouch 物件
  • UITouch 相關屬性

    • window 觸控產生時所處的視窗
    • view 觸控產生時所處的檢視
    • tapCount 短時間內按螢幕的次數,根據 tapCount 判斷單擊、雙擊或更多點選
    • timestamp 記錄了觸控事件產生或變化的時間,單位是秒
    • phase 當前觸控事件所處的狀態
  • UITouch 相關方法

    • 返回值表示觸控在 view 上的位置,這裡返回的位置是針對view的座標系的(以 view 的左上角為原點(0,0)),呼叫時如果傳入的 view 引數是 nil 的話,返回的時觸控點在 window 的位置 js [touch locationInView:view];
    • 該方法記錄了上一個點的位置

      js [touch previousLocationInView:view];

注:
iPhone開發中,要避免使用雙擊事件
如果要在一個 view 中監聽多個手指,需要設定屬性 ```js //需要view支援多個手 view.multipleTouchEnabled = YES;

  • (void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event{     NSLog(@"%ld",(long)touches.count); //2 } ```

UIEvent

  • 每產生一個事件,就會產生一個 UIEvent 物件
  • UIEvent 被稱為事件物件,用於記錄事件產生的時刻和型別
  • UIEvent 相關屬性
    • 事件型別
      • type 列舉型別(觸控事件、加速器事件、遠端控制事件)
      • subtype
    • timestamp 事件產生時間
  • UIEvent 相關方法
    • UIEvent 提供相應方法用於獲取在某個 view 上面的接觸物件(UITouch

簡單示例

實現需求:一個按鈕可以在螢幕任務拖拽

Kapture 2021-11-22 at 22.49.40.gif

1.自定義一個 UIImageView ```js @implementation InputImageView

  • (instancetype)initWithFrame:(CGRect)frame{     self = [super initWithFrame:frame];     if (self) {                 UIImage *image = [UIImage imageNamed:@"inputButton"];         self.image = image;         self.userInteractionEnabled = YES;     }     return self; }
  • (void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event{ UITouch *touch = touches.anyObject; //獲取當前點 CGPoint currentPoint = [touch locationInView:self]; //獲取上一個點的位置 CGPoint previousPoint = [touch previousLocationInView:self]; //獲取x軸偏移量     CGFloat offsetX = currentPoint.x - previousPoint.x;     CGFloat offsetY = currentPoint.y - previousPoint.y;     //修改view的位置     self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY); } @end 2.實際呼叫js

import "ViewController.h"

import "InputImageView.h"

@interface ViewController () @property (nonatomic,strong) InputImageView *redView; @end

@implementation ViewController

  • (void)viewDidLoad {     [super viewDidLoad];     InputImageView *inputImageView = [[InputImageView alloc]initWithFrame:CGRectMake(150, 150, 56, 56)];     [self.view addSubview:inputImageView]; } @end ```