前言
這還是斯坦福大學(xué)的課程-Developing iOS 9 APPs with Swift,這是第5節(jié)課的內(nèi)容悲立,我將我認(rèn)為的關(guān)鍵點記錄在我的學(xué)習(xí)筆記系列中薪夕。手勢操作功能 (Gesture) 在蘋果的各大產(chǎn)品中都占有相當(dāng)重要的地位原献。用mac book的童鞋應(yīng)該都深有體會它的觸摸板是多么強(qiáng)大嚼贡,很多時候(除了玩游戲)我都更愿意用觸摸板,鼠標(biāo)反而更麻煩一些误窖。在iOS中,它的功能也是相當(dāng)強(qiáng)大的柔吼,iphone的屏幕操作帶給人的是一種享受。
Demo
今天仍然是這張萌蠢的臉想际,只是換了個發(fā)型胡本,加了一些有趣的手勢操作侧甫,可以改變他的表情,昨天還說讓你自己敲代碼去改呢~ 今天省了不少事咒锻。233
手勢操作 (Gestures)
- 手勢操作由一個叫 UIGestureRecognizer 的家伙管理,但是敦捧,它自己本事是abstract的碰镜,你無法直接使用它。但你可以使用它下面的很多子類秽荤,比如swipe窃款,pinch晨继,tap等等紊扬。
- 有兩個方面你可以使用手勢識別器(gesture recognizer)檀葛。
- 往UIView中添加一個手勢識別器(叫UIView去識別那些手勢)
- 當(dāng)識別器無法識別的時候屿聋,需要一個控制器(gesture handler)润讥,通過狀態(tài)機(jī)(state machine)來處理手勢
- 上面的第1點象对,一般由控制器完成勒魔。注意只有view能識別手勢冠绢,controller是不可以的,但是controller可以往它的view里添加手勢喊式。
- 上面的第2點夏哭,handler可以由UIView或者Controller完成竖配,但也可以由別的東西完成进胯,但絕對不會是model,因為model是 UI-independent 的原押。
- 這里有一點,也是充分體現(xiàn)在代碼中的,就是比如scale(縮放),color(改變顏色)之類的违崇,view可以自己 recognize 和 handle;但是如果手勢改變了model诊霹,那么必須由Controller來handle,因為view和model是相對獨立的伴箩。
- 往UIView中添加手勢,比如添加“pan”手勢:
@IBOutlet weak var pannableView: UIView {
didSet {
let recognizer = UIPanGestureRecognizer (
target: self, action: #selector(ViewController.pan(_:))
)
pannableView.addGestureRecognizer(recognizer)
}
}
- didSet只被調(diào)用一次,在運行時iOS關(guān)聯(lián)這個布局時調(diào)用這部分代碼桦踊。
- 當(dāng)手勢被識別出來的時候椅野,target表示由 self 來handle這個手勢,這里是Controller它自己
- action表示需要在 self 里用到什么方法用籍胯,
(_:)
里面的_:
表示有參數(shù)炼蛤,但是參數(shù)名隨意,就是說,老子不管它叫什么炸裆,反正我就是要有參數(shù)国拇。 - 一個handler需要更詳細(xì)的手勢信息才能handle那個手勢,以UIPanGestureRecognizer為例土思,它里面有3個重要的方法:
func translantionInView(UIView) -> CGPoint //從下筆開始記錄
func velocityInView(UIView) -> CGPoint // 移動的速度
func setTranslation(CGPoint, inView: UIView) // 設(shè)置從哪里開始
- 這個抽象的超類也提供了狀態(tài)信息
var state: UIGestureRecognizerState { get }
- 狀態(tài)一直在
.possible
务热,直到開始識別。 - 對于離散的手勢己儒,比如swipe途样,它就變成了
.Recognized
- 對于連續(xù)的手勢赖晶,比如pan律适,它就變成了
.Began
捂贿,然后是不停的.Changed
厂僧,最后停下.Ended
- 它也可以
.Failed
和.Cancelled
。 - 那么一個pan handler是應(yīng)該什么樣子的呢?
func pan(gesture: UIPanGestureRecognizer) {
switch gesture.state {
case .Changed:
fallthrough
//不同于其它語言的switch case,fallthrough表示這個case完成了浇衬,它還可以繼續(xù)下個case,而不是break
case .Ended:
let translation = gesture.tanslationInView(pannableView)
// 通過 translation.x 和 .y 更新依賴于pan手勢的任何其它內(nèi)容
gesture.setTranslation(CGPointZero, inView: pannableView)
default: break
}
}
- UIPinchGestureRecognizer, 這就是兩只手指縮放的功能
var scale: CGFloat // 可重置辕近,如demo
var velocity: CGFloat { get } // 每秒鐘為單位
- UIRotationGestureRecognizer, 旋轉(zhuǎn)
var rotation: CGFloat // 也可以在弧度中重置
var velocity: CGFloat { get } //每秒的旋轉(zhuǎn)速度
- UISwipeGestureRecognizer, 滑動
var direction: UISwipeGestureRecognizerDirection // 哪個方向滑動
var numberOfTouchesRequired: Int // 幾個手指
- UITapGestureRecognizer, 點擊
雖然這是離散的方法浅乔,但是可以設(shè)置點擊的數(shù)量,可以用.Ended
來控制結(jié)束的點
var numberofTapsRequired: Int // 點擊的數(shù)量
var numberOfTouchesRequired: Int // 手指數(shù)量
多個MVC組合
MVC中, Controller的職責(zé)是將Model翻譯給View靖苇。有些Controller可以拿別的MVC當(dāng)作自己的View席噩。
iOS提供了一些很強(qiáng)大的控制器(Controller),它們以別的 “MVC” 作為自己的View贤壁。這也是做一個app必須具備的(你不能只有一個界面吧悼枢?囧)。e.g.
UITabBarController
UISplitViewController // i-pad, iphone 6 plus; split one screen into 2 parts
UINavigationController
* 當(dāng)然你可以自己設(shè)計控制器(Controller)來做這個工作脾拆,但是那個馒索。。名船。你會的話教教我??
- UINavigationController绰上,一個MVC里有很多MVC,點擊其中一個按鈕進(jìn)入下一個MVC包帚,系統(tǒng)就將這多級的MVC存放在一個堆里渔期。左上角有一個返回鍵,點擊返回鍵的時候,當(dāng)前的MVC就被系統(tǒng)拋棄了(從堆里徹底消失了疯趟,重新點擊會創(chuàng)建一個新的)拘哨,返回上一級MVC.
獲取子MVC模塊(Accessing the sub-MVCs)
- 可以通過viewControllers的屬性獲得子MVC模塊
var viewController: [UIViewController]? { get set } // 可以是optional的(比如tab bar)
對于一個tab bar來講,它們是從左到右順序排列的信峻,存在數(shù)組當(dāng)中
對于一個split view來說倦青,[0]是主體部分, [1]是細(xì)節(jié)部分
對于一個navigation controller來說盹舞,[0]是根产镐,其它部分在堆中按順序排列(如之前所說)。
僅管這是可設(shè)置的踢步,但一般都是在storyboard里進(jìn)行癣亚。
比如,navigation controller的pop和push方法
那我如何使用這些屬性(SVC, TBC, NC)呢获印?
其實UIViewController會告訴你這三個非常重要的屬性在哪個view中(如果有的話述雾,沒有就是nil,它們都是optional的)兼丰。
var tabBarController: UITabBarController? { get }
var splitViewController: UISplitViewController? { get }
var navigationController: UINavigationController? { get }
比如玻孟,你想知道你的分屏控制器(split view controller,翻譯的不好別罵我 = =)的細(xì)節(jié)鳍征,你可以使用如下語句
if let detailVC: UIViewController = splitViewController?.viewControllers[1] { ... } // 如上所說黍翎,[1] 是detail,細(xì)節(jié)艳丛,如果沒有就是nil
如何鏈接這些MVC
以分屏控制器(split view controller)為例匣掸,只需從object library里拉一個過來就OK了,好簡單质礼。然后按住ctrl旺聚,分別往你的兩個mvc上拉兩條線,一條設(shè)置master眶蕉,另一條設(shè)置detail砰粹。就像這樣:
- 但是split view只能在iPad上使用,要想在iphone上使用怎么辦呢造挽?我們需要放一些Navigation Controllers在里面碱璃,Navigation Controllers對于ipad也是可以的。最簡單的方法就是將Navigation Controller包含在一個MVC中饭入,通過
Editor -> Embed In
by:諸葛俊偉
喜歡我的可以訪問我的個人網(wǎng)站了解更多哦~