在這一課中,你會繼續在FoodTracker菜譜的場景工做。你會從新安排現有的UI元素並使用圖像採集器添加到照片用戶界面。當你完成,你的應用程序將是這個樣子:android
學習目標swift
在課程結束時,你將可以:app
瞭解視圖控制器的生命週期,如viewDidLoad,viewWillAppear和viewDidAppear這些回調函數
在視圖控制器之間傳遞數據
讓一個視圖控制器消失
使用手勢識別生成一個事件
預測的基於UIView/ UIControl類層次的對象行爲
使用asset目錄,添加圖像資源到項目中編輯器
理解視圖控制器的生命週期ide
到目前爲止,FoodTracker應用程序有一個單一的場景,其用戶界面是由一個單一視圖控制器管理。爲了打造更復雜的應用程序,你會要處理更多的場景,並須要管理載入和卸載在屏幕上來來去去的Views函數
UIViewController類(及其子類)的對象提供了一組方法,這些方法管理其視圖層次結構。當一個視圖控制器的狀態在轉變時,iOS會在適當的時間自動調用這些方法。當你建立一個視圖控制器子類,它繼承了的UIViewController中定義的方法,讓你爲每種方法添加本身的自定義行。重要的是要了解,當這些方法被調用,這樣你就能夠在適當的步驟下設置或拆卸你正在展現的Views,未來你會須要作這些事情。這裏能夠和Android中的Activity的生命週期作對比佈局
UIViewController的方法調用以下:學習
viewDidLoad()----當視圖控制器的內容視圖(頂層視圖)被建立而且從一個storyboard載入後調用。這個方法適用於初始化設置,然而,由於因爲APP中的資源限制可能會讓views被清除,不能保證這個方法只被調用一次測試
viewWillAppear()---在view可見以前發生的行爲。由於一個view的可見度能開關或被其餘Views遮蔽,在內容視圖出如今屏幕以前,這個方法會當即調用動畫
viewDidAppear()---用於view一可見你就想要發生的操做,如獲取數據或顯示動畫。由於一個view的可見度能開關或被其餘Views遮蔽,因此這個方法在內容視圖出如今屏幕後會當即調用
另外與之對應的還有一套對立的方法存在,如上面狀態圖所示。
你會在FoodTracker APP中適當的時間內使用一些方法來載入和顯示view數據。實際上,若是你有印象,咱們已經寫過viewDidLoad()方法中的一些處理
override func viewDidLoad() { super.viewDidLoad() // Handle the text field’s user input through delegate callbacks. nameTextField.delegate = self }
在你的views和數據模型之間,視圖控制器做爲通訊管道, APP這種設計風格被稱爲MVC(模型-視圖-控制器)。在這個模式中,模型跟蹤你的app數據,視圖顯示你的用戶界面,並組成一個內容,控制器管理你的views。經過相應用戶的動做而且從數據模型得來的內容以填充view。對於任意iOS app來講MVC是一個相當重要的好的設計,到目前爲止,FoodTracker一直沿用MVC規則構建。在app剩餘的設計中,在頭腦裏保持MVC模式,是時候把基礎的UI帶到下一水平了,咱們會爲菜譜場景建立最終的佈局
添加一張菜譜的圖片
接下來的是完成菜譜場景的UI,咱們添加一個方法來顯示一張具體的菜譜照片。爲此,咱們將使用Image View(弄過android的是否是很熟悉?),這裏iOS中使用的是UIImageView類,這是一個UI元素用來顯示一張圖片,步驟以下:
1.打開storyboard,Main.stroyboard
2.打開實用區域的對象庫(也能夠選擇View > Utilities > Show Object Library)
3.在對象庫中,輸入image view來快速過濾出你想要的對象
4.拖動Image View到場景中,在咱們先前按鈕控件的下方
5.選中ImageView,打開Size inspector,你能夠調整ImageView的大小和位置
6.在下方的Intrinsic Size字段,選擇Placeholder
7.在上方View和下方的Placeholder中都Width和Height中輸入320,而後按下Return,由於一個空的iamge view沒有內在大小,你給定image view的placeholder大小,而後能夠在界面中指定適當的約束
8.在畫布的底部右邊,點擊Pin按鈕
9.選擇Aspect Ratio複選框,以下所示:
10.在Pin菜單中,點擊Add 1 Constraints
你的圖片如今是1:1的長寬比,因此他看起來會是個正方形
11.選擇image view,打開Attributes inspector
12.在Attributes inspector中,找到Mode而後點擊下拉列表,選擇Aspect Fill
這個選項有助於確保不一樣尺寸的圖像在image view中不會失真。
13.在Attributes inspector中,找到Interaction ,而後選中User Interaction Enabled複選框
稍後,你將須要此功能,讓用戶與image view交互。如今的UI應該以下所示:
顯示一個默認照片
用戶須要一個指示,讓他們知道能夠和image view交互,並能選擇一張照片。要作到這一點,須要添加一個默認placeholder圖像,來傳達給用戶,他們能選擇一個照片
你能夠點擊這裏下載咱們這章所須要的圖片。下面讓咱們來添加圖片到項目中
1.在項目導航中,選擇Assets.xcassets(不一樣Xcode版本,名字可能不同,有的也許是Images.xcassets)進入asset目錄,這個目錄是存儲你圖片的地方
2.在頂部角落,點擊+按鈕並選擇New Image Set
3.而後在出現的Image上,雙擊,重命名爲defaultPhoto
4.在你的電腦中,找到這個圖片。
5.而後拖動到x2位置出,放下
2x是 iPhone 6模擬器下的分辨率,圖片放在這個位置最佳
接下來咱們要在image view中顯示默認圖片
a.打開你的storyboard
b.在storyboard中選擇image view
c.選中image view的狀況下打開Attributes inspector
d.在Attributes inspector中找到Image字段,而後選擇defaultPhoto
運行你的APP,效果以下:
將Image View鏈接到代碼
如今,你須要實現必要的功能,來在運行時改變圖片。你但願能從代碼中改變圖片,爲此,你首先須要在ViewController.swift中鏈接image view到代碼:
1.點擊Assistant打開assistant editor
2.若是你想要更多的工做空間,你能夠摺疊 project navigator和utility area
3.在storyboard中,選擇image view
4.按住Control鍵拖動image view畫布到右邊的代碼編輯器中,選擇outlets,以下圖:
5.在彈出的對話框中,Name:photoImageView:
6.點擊Connect。Xcode會添加必要的代碼到ViewController.swift中
你如今能訪問iamge view了,從代碼上來改變圖像,但你如何知道什麼時候改變圖片?你須要給用戶一個方式來告訴他們能夠改變圖片。例如,點擊image view。而後你要定義一個動做方法來處理點擊事件。
views和controls之間有微妙的區別,view有一個特定的版原本響應用戶的動做。一個視圖顯示內容,然而control會以某種方式來修改它,一個control(UIControl)是UIView的子類。實際上,你已經使用過了,例如Views(標籤,image view),controls(文本框,按鈕)
建立一個手勢識別
一個image view不是一個控制,因此它不會像按鈕那樣被設計爲能響應輸入。例如,當一個用戶點擊image view時你不能簡單的建立一個動做方法來觸發一個事件。(若是你試圖按住Control鍵拖動iamge view到你的代碼中,你會發現,在Connection字段後面,它不能選擇Action)
幸運的是,它能夠很容易的給定一個view添加一個手勢識別,做爲和控制的能力。手勢識別是一個能夠附加到view上的對象,view能夠響應動做。手勢識別能夠解釋觸摸來肯定它們是否對應於特定的手勢,諸如滑動,擠壓或旋轉。你能寫一個動做方法,用來處理當手勢識別發現它對應的手勢時,這正是你須要爲image view作的
咱們能夠附加一個點擊手勢識別(UITapGestureRecognizer)到image view中,當一個用戶輕擊image view時,它將會識別。你能在storyboard輕鬆搞定這件事。步驟以下:
1.打開Object library
2.輸入tap gesture快速過濾出咱們想要的識別事件對象
3.拖動Tap Gesture Recognizer到場景中,放在 image view的上方一點
這個Tap Gesture Recognizer會出如今菜譜的場景Dock中
將手勢識別鏈接到代碼中
如今鏈接手勢識別到一個動做方法中。步驟以下:
1.按住Control鍵拖動手勢識別到代碼編輯器,而後在//MARK:Action放下
2.在彈出的對話框中,Connection字段旁,選擇Action
3.Name字段旁,輸入selectImageFromPhotoLibrary
4.Type旁,選擇UITapGestureRecognizer
5.點擊Connect或按下Return
建立一個圖片選擇器來響應用戶的輕擊事件
那麼何時用戶會輕擊image view,據推測,用戶應該能用照片集中選擇一個照片。幸運的是,UIImagePickerController已經把這種行爲內置到裏面了。一個圖片選擇器控制者管理一個UI,用於拍照並選擇保存圖像。正如你在文本框工做時須要一個文本框委託同樣,你須要一個圖片選擇控制器委託來幫助你圖片選擇控制器的工做。這個委託的是一個協議(UIImagePickerControllerDelegate),你在ViewController定義這個圖片選擇控制器委託對象。首先
ViewController須要採用
UIImagePickerControllerDelegate協議。由於ViewController將掌管圖片選擇控制器的展現,同時咱們還須要採用UINavigationControllerDelegate協議,該協議只是讓ViewController獲取一些基本的導航職責。接下來讓咱們添加這兩個協議:
1.返回standard editor
2.在項目導航中,選擇ViewController.swift
3.在ViewController.swift中,找到class這行:
class ViewController: UIViewController, UITextFieldDelegate {
4.而後添加以下代碼:
class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
接下來咱們須要實現selectImageFromPhotoLibrary()方法了
a .在ViewController.swift中找到selectImageFromPhotoLibrary()動做方法
@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {
}
b.在方法體中,添加以下代碼:
// Hide the keyboard. nameTextField.resignFirstResponder()
該方法是確保,用戶在點擊image view時,若是軟鍵盤正輸入打開狀態,須要關閉它
c.添加代碼,來建立一個圖片選擇控制器
// UIImagePickerController is a view controller that lets a user pick media from their photo library. let imagePickerController = UIImagePickerController()
d.而後添加這行代碼:
// Only allow photos to be picked, not taken. imagePickerController.sourceType = .PhotoLibrary
這行代碼是設置圖片選擇控制器的源,或者是它獲取圖片的地方。.PhotoLibrary選項表示使用模擬器的相機膠捲,這個imagePickerController.sourceType是UIImagePickerControllerSourceType中的一個類型。它是一個枚舉。意思是你能寫縮寫形式.PhotoLibrary來代替UIImagePickerControllerSourceType.PhotoLibrary
e.添加以下代碼設置圖片選擇控制器的委託爲ViewController:
// Make sure ViewController is notified when the user picks an image. imagePickerController.delegate = self
f.最後加上這一行
presentViewController(imagePickerController, animated: true, completion: nil)
presentViewController(_:animated:completion:)是ViewController中調用的方法,雖然這個方法沒有顯式的寫入,但方法會在隱式的self對象上執行。改方法詢問
ViewController
to出示imagePickerController定義的視圖控制器,animated爲true表示圖像選擇控制器是否以動畫呈現。
completion表示當此方法執行完後,執行一個關包。由於不須要作任何事,因此這個參數傳nil便可。你完整的selectImageFromPhotoLibrary()方法應該以下所示:
@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) { // Hide the keyboard. nameTextField.resignFirstResponder() // UIImagePickerController is a view controller that lets a user pick media from their photo library. let imagePickerController = UIImagePickerController() // Only allow photos to be picked, not taken. imagePickerController.sourceType = .PhotoLibrary // Make sure ViewController is notified when the user picks an image. imagePickerController.delegate = self presentViewController(imagePickerController, animated: true, completion: nil) }
在圖片選擇控制器展示完後,它的行爲會交給委託。給用戶選擇圖片的能力,你須要實現UIImagePickerControllerDelegate中的兩個委託方法
func imagePickerControllerDidCancel(picker: UIImagePickerController)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
其中第一項,imagePickerControllerDidCancel(_:),讓你獲得當用戶點擊圖片選擇器的取消按鈕的調用。這種方法給你一個機會讓UIImagePickerController消失。實現以下:
func imagePickerControllerDidCancel(picker: UIImagePickerController) { // Dismiss the picker if the user canceled. dismissViewControllerAnimated(true, completion: nil) }
第二項,imagePickerController,當用戶選擇一個照片時調用。這種方法可讓你有機會在用戶從選擇器中選擇一個或多個圖像時作些什麼。在本例中,咱們會採起選定的圖像,並在UI中顯示。實現以下
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { // The info dictionary contains multiple representations of the image, and this uses the original. let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage // Set photoImageView to display the selected image. photoImageView.image = selectedImage // Dismiss the picker. dismissViewControllerAnimated(true, completion: nil) }
第一行代碼表示info字典包含你選中原始圖像,若是存在,是已編輯的圖片版本。爲了簡單,咱們將使用原始的,未經編輯的圖片做爲菜譜照片。咱們把這個照片存儲在selectedImage常量中。
第二行代碼表示咱們給前面的場景中的image view設置它的image
第三行代碼固然是讓圖片選擇器消失啦
檢查點:運行你的應用程序。你應該能夠點擊Image View 查看圖像選擇器。系統會有一個權限警告,詢問許可給FoodTracker應用程序訪問照片,點擊OK便可。而後,您能夠點擊取消按鈕關閉選擇器,或打開相機膠捲並單擊圖像來選擇它,並在Image View中顯示
若是你經過在模擬器中發現沒有任何照片的話。你能夠直接添加本身的圖像到模擬器來測試。前面Image View中的默認圖文件夾中,附帶了一張菜譜的圖片。你把圖片直接從電腦上拖入模擬器便可