[CS193P] 第十四堂課摘要及心得筆記

在這一次的課堂上,我們將學習在iPhone開發平台上關於觸控事件的處理,而多點觸控的功能更是iPhone應用程式開發的重點,就讓我們一起來看看吧!
評論
評論

在這一次的課堂上,我們將學習在 iPhone 開發平台上關於觸控事件的處理,而多點觸控的功能更是 iPhone 應用程式開發的重點,就讓我們一起來看看吧!

觸控的序列

在 iPhone 的操作上面,像是如下圖般一筆劃的觸控動作,會被轉成一系列的 UITouch 物件,儲存在 UIEvent 之後傳遞給 view。

UITouch 物件描述了某支手指頭在觸控螢幕上得動作,包含以下這些屬性:

@property(nonatomic,readonly) NSTimeInterval	timestamp; // 觸控的時間點 @property(nonatomic,readonly) UITouchPhase	phase; // 觸控中的哪一階段(後面會有敘述) @property(nonatomic,readonly) NSUInteger	tapCount; // 連續點了幾下 @property(nonatomic,readonly,retain) UIWindow	*window; // 在哪個 Window 上點擊 @property(nonatomic,readonly,retain) UIView	*view; // 在哪個 View 上點擊 - (CGPoint)locationInView:(UIView *)view; // 在某個 view 上的座標位置 - (CGPoint)previousLocationInView:(UIView *)view; // 在某個 view 上的前一個座標位置

而 UIEvent 如同我們剛剛所提及的,是 UITouch 的容器,當我們有多點觸控的時候,這個容器就會包含數個 UITouch 物件。UIEvent 具有以下類別:

@property(nonatomic,readonly) NSTimeInterval timestamp; // 觸控的時間點 - (NSSet *)allTouches; // 所有的 UITouch 物件 - (NSSet *)touchesForWindow:(UIWindow *)window; // 回傳某個 windows 上的 UITouch 物件 - (NSSet *)touchesForView:(UIView *)view; // 回傳某個 view 上的 UITouch 物件

而以上這些物件均會傳透過 UIResponder 的方法傳遞給我們的應用程式,包含以下幾個方法:

- (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; // 觸控取消

上面所謂的觸控取消,雖然僅會發生在很少的機會,像是忽然接到來電,但仍然不能忘記對這些物件進行處理,詳細的原因在課堂的稍後會在做解釋。

多點觸控

在我們要開始接收包含多個 UITouch 的 UIEvent 物件之前,我們必須先將 UIView 的 BOOL multipleTouchEnabled; 屬性設定成 YES 才行。

而當使用者若同時將兩隻手指放在 iPhone 上時、或者是兩隻手指頭同時在螢幕上移動時,我們就會接收到包含多個 UITouch 物件的 UIEvent。但需要注意的是,如果使用者將兩隻手指同時放在畫面上,但只有一個手指在移動,這樣我們所接收到的 UIEvent 物件只會包含在移動中的 UITouch 物件!

而若是兩隻手指分別在不同的 View 上呢?那兩個 View 分別會接收到 touchesMoved: withEvent: 的呼叫,並且除了自己 view 上的 UITouch 物件之外,也會收到另外一個 View 上得 UITouch 物件。

然而,有時候我們不希望使用者可以同時操作兩個 UIView 物件,特別是我們在開發遊戲的時候,我們可能會禁止使用者同時移動並且開火,這時候我們就可以設定 UIVIew 中的 BOOL exclusiveTouch; 屬性為 YES,這樣一來就可以避免同時有兩個以上的 View 接收到 UIEvent 物件了。

或許當讀者看到上面的方法會感到好奇,那 iPhone 是如何判斷某個 Touch 是屬於哪個 View 呢?事實上,iPhone 會透過呼叫 hitTest:withEvent: 這個測試方法,測試 UIWindow 上的每一個 view 是否符合以下三個條件:

  • userInteractionEnabled 屬性是否為 YES
  • hidden 是否為 YES,或是 alpha 設定在一個很低的數字(也就是透明)
  • 透過呼叫 pointInside:withEvent: 檢查觸控點是不是在 view 的範圍內

當某個 UIView 符合以上條件的話,iPhone 就會繼續測試其底下所包含的 subviews,直到找到最適合的 view 為止。

而當找到 View 之後,會對其 UIViewController 呼叫 (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; 等方法傳遞 UIEvent 物件。但若是最底層的 View 沒有實做這個方法回應觸控事件的話,則會往 superview 傳遞 UIEvent 物件。然後重複這個循環,直到找到可以回應觸控事件的 View 為止,而若是所有的 superview 對於目前的 UIEvent 物件沒有處理的話,則會轉而呼叫 UIWindow 甚至是 UIApplication 進行處理。整體的階層架構如下圖:

最佳作法

iPhone 開發平台釋出也有一段時間了,隨著越來越多的應用程式開發完成,開發者們也對於觸控事件有一些常見的錯誤及解決方法,以下就是幾個常見的開發好習慣:

當某個 View 被 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; 方法回傳,也就代表他應該要處理所有的觸控事件,包含以下四個:

- (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;

由於大多數的觸控處理都會暫時將 UIEvent 儲存起來以跟後續的觸控行為進行比對、計算,而如果我們漏掉處理其中某一種(特別是觸控取消時),就很有可能造成物件產生無法預期的錯誤。

而當我們需要繼承 UIView 建立自己的 View 類別時,也必須遵守以上的慣例,也就是處理每一個階段的觸控事件。而且要注意,在這些處理方法中千萬不能向上呼叫父類別的處理方法。

至於若是繼承其他 UIKit 的類別,像是 UIButton 時,你可以選擇處理某些觸控事件即可,但是跟上面相反的是,你必須在每個觸控事件處理方法呼叫父類別的相對方法,否則物件原有的觸控反應將會無效。

最後,如果你萬不得已,非得需要將某個觸控事件轉移給別的 View 的話,那要記得那些 View 必須是自己設計的 UIView 子類別,因為 UIKit 內建的類別並不保證可以在這樣的狀況下正確運作。

結論

相信各位讀者應該在這次的課程中,對於觸控的事件處理有很詳細的了解,也已經可以透過這些知識設計出多點觸控的應用程式了!在下一次的課程中,我們將探討那些在 iPhone SDK 中所附的模擬器中無法測試的硬體功能,像是羅盤、GPS 或者是加速度計等等,請繼續鎖定本連載!

參考資源


用 Line 視訊太久會致癌?別再污名化手機通訊,謠言比電磁波更有害!

「聽說 LINE 通話會讓電磁波飆高 6 萬倍」、「手機通話的電磁波可以爆爆米花」…這些如同都市傳說的網路文章,你是否也曾閱讀過呢?
評論
Photo Credit:Unsplash
評論

茶水間內,兩位 OL 正在一邊加熱中午的便當一邊閒聊著,「最近有一件事情讓我有點擔心⋯」今年剛滿三十歲的北漂族 A小姐說道,「因為疫情我跟我男友已經好幾個月沒有見面了,但我們還很熱戀呀,所以常常每晚都開著 Line 視訊電話聊到睡著。」

「這樣很甜蜜啊,有什麼好煩惱的?」B 小姐盯著微波爐內旋轉著的便當盒答。A 小姐吞了吞口水,「還不是最近看到一些網路文章,說電子產品用太多,那個什麼⋯電磁波會影響大腦,聽說會致癌耶!太可怕了,害我這陣子都怕怕的⋯⋯」

Photo Credit:unsplash

Q:聽說LINE通話會讓電磁波飆高 6 萬倍,恐導致癌症,這是真的嗎?

答案是錯的喔,台大電機系教授陳士元表示,手機的電磁波並不會因為你現在在用何種 APP,就會發出不同的電磁波。只要在一樣的通訊情境下,不管是滑臉書、看 YouTube,還是用 Line 講視訊電話,電磁波都不會大幅改變的。

當然還是會有輕微變動的狀況,通常發生於手機開機與接通電話的瞬間,電磁波會稍微增強,不過正常使用和通話期間電磁波反而強度會削弱,不過這些電磁波的數值都符合國家及國際規範。

你可能會問,但用 Line 講電話的時候,手機都會變得比較燙呀?陳士元教授解釋,這與電磁波無關,純粹就是手機用電量增加而熱度提高,大家毋須擔心。

這裡補充一個小知識——根據國際非游離輻射防護委員會規定,手機電磁波高低判定,是看每一款手機的電磁波能量比吸收率(Specific Absorption Rate ,簡稱 SAR 值),也就是指生物體在每單位公斤所吸收到的輻射量功率,當 SAR  值越低,代表人體所接收到的輻射量越少。

如果你和 A 小姐一樣,很好奇或擔心自己的手機到底會釋放多少 SAR值,可以到 NCC 網站中,點擊「型式認證查詢網頁」(https://nccmember.ncc.gov.tw/Application/Fun/Fun016.aspx),輸入手機的「廠牌」、「型號」或「型式認證號碼」等資訊,最後再輸入確認碼後就可以看到相對應的資料囉。網頁中也列出不符 NCC 所定技術規範的電子設備,也趁機檢查看看家中是否有這些帶有風險的裝置吧。

Q:之前曾在網路上看過手機通話時的電磁波可以爆爆米花的影片,看起來好危險喔,這是真的嗎?

這個在網路上流傳的影片,乍看之下好像很嚇人沒錯,但其實是美國的廣告影片,所以即使看起來很真實,但裡面的效果都是假象喔,大家可千萬別信以為真。

仔細想想,中午熱便當所使用的微波爐,也至少要花一分鐘才有可能將玉米變成爆米花,更何況是平均輸出功率更低的手機,簡直是不可能的任務。所以影片中應是在桌下藏了瞬間加熱器的裝置,才能在幾秒間將玉米變成爆米花呢。

Photo Credit:Unsplash

基地台太近對健康有害?答案並非你想的那樣!

民眾可能會有個迷思:離通訊基地台越近,信號越強電磁波應該也越強,對健康會造成危害?

事實上,手機發射的訊號與基地台電磁波的強度,兩者是反比關係喔。距離基地台越近,手機訊號越好,手機電磁波的強度越弱;反之,距離基地台越遠,訊號越差,手機電磁波反而強度越強。

此外,現在的通訊基地台皆採用「蜂巢式通訊系統」的架構來建造,將服務區域切割成小塊小塊的範圍,透過大數量基地台所組成的「蜂巢」來涵蓋所有通訊區域的範圍。也因此,每座基地台的電磁波強度皆不高,且都在人體可接受的範圍內,因此不會對健康有所危害。

 別再污名化電磁波,好好相處才是長久之道

今天我們簡單洗刷了「電磁波」的冤屈,還它個清白——A 小姐不需要再擔心使用 Line 通話會被電磁波影響健康了,如果你想認識更多相關資訊,歡迎至國家通訊傳播委員會的行動通訊電磁波官網(https://memf.ncc.gov.tw/),查看更多延伸閱讀。

除此之外,如果你對家中或手機的電磁波曝露量很有疑慮,也歡迎撥打基地臺電磁波量測服務專線 0800-580-010(0800,我幫您,量一量),讓專業人士到府服務來替你排除疑慮,停止被謠言迷惑心智!

國家通訊傳播委員會 廣告