自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Parse 教程:網(wǎng)絡(luò)后臺基礎(chǔ)

移動開發(fā)
網(wǎng)絡(luò)后臺支持可以為你的App添加許多嶄新的功能:不論是數(shù)據(jù)同步,社交分享,還是云端存儲都可應(yīng)付自如。作為一名專業(yè)的iOS開發(fā)者,如何才能為你的App添加服務(wù)器端的支持?

[[141390]]

本教程已針對Swift, iOS 8.3, Xcode 6.3及***的Parse SDK(1.7.1版本)更新。

網(wǎng)絡(luò)后臺支持可以為你的App添加許多嶄新的功能:不論是數(shù)據(jù)同步,社交分享,還是云端存儲都可應(yīng)付自如。作為一名專業(yè)的iOS開發(fā)者,如何才能為你的App添加服務(wù)器端的支持?

在本篇Parse教程中,你將會學(xué)到如何創(chuàng)建一個使用 Parse 后臺支持的App,此App主要功能為照片分享,包含用戶登錄、照片上傳和照片墻功能。為了使你集中精力在aParse的實現(xiàn)上,本工程預(yù)先包含了一部分用戶界面,但不包括上傳和現(xiàn)在照片的功能。你將一步一步地添加Parse服務(wù),完成一個完整的App。

準(zhǔn)備好輕松創(chuàng)建App了嗎?好的,讓我們開始了解Parse。

準(zhǔn)備工作

開始App部分的開發(fā)工作前,***步需要在后臺創(chuàng)建Parse App。 每個開發(fā)者、每個App都需要一個唯一標(biāo)識符,否則的話,你的數(shù)據(jù)和用戶就會和別人的弄混。

訪問 Parse.com,點擊“Get started for free”, 然后點擊注冊創(chuàng)建一個新的賬戶。

創(chuàng)建賬戶后,Parse會詢問你是否創(chuàng)建***個App。 你必須為每個iOS App注冊單獨的后臺App。在本教程中,我們叫它"Tutorial App"。Parse上可能存在許多app,它們的標(biāo)識符各不相同,但是現(xiàn)在只有一個app實例屬于你。

39.png

創(chuàng)建app后,你會看到歡迎界面,在上面有許多選項幫你添加Parse的功能。這些選項都會有模板功能供下載使用,但本教程暫時不需要。在網(wǎng)頁頂端有幾個選項按鈕,如下圖所示:

40.png

以下是這些選項的說明:

  • Core(核心):在這里你可以看到之前上傳的所有數(shù)據(jù),你也可以看到用戶,并手動管理這些數(shù)據(jù)。
  • Analytics(分析):這里你可以考到關(guān)于App的數(shù)據(jù)統(tǒng)計,如數(shù)據(jù)流量,已發(fā)送的推送通知和API調(diào)用次數(shù)。你也可以添加自定義的事件。
  • Push(推送):使用這個功能可以向任一組用戶發(fā)送推送通知。
  • Settings(設(shè)定):這里你可以看到所有API key。另外,你可以修改你的app的設(shè)定,管理安全選項,并且導(dǎo)出數(shù)據(jù)。
  • Docs(文檔):在這里你可以看到教程、示例工程,API文檔,學(xué)習(xí)到所有使用Parse擴(kuò)展app功能的方法。

Parse示例程序

為了集中在后臺服務(wù)上,該教程包含一個初始工程。你可以直接下載,然后按照教程步驟添加Parse調(diào)用。

使用Xcode打開工程并運(yùn)行。首先,你將看到一個登陸頁面。但這個頁面上的按鈕還不能做任何事情。稍后你會學(xué)到如何創(chuàng)建這些功能。

42.png

開始之前,先打開Main.storyboard文件,看看這個app的結(jié)構(gòu)和流程。

43.png

該工程包含以下4個主視圖:

  • 登錄:登錄界面有用戶名和密碼文本框,還有一個注冊按鈕用以創(chuàng)建新用戶。
  • 注冊:該界面用于輸入用戶名和密碼在后臺創(chuàng)建新的用戶。
  • 圖片墻:這是該應(yīng)用的主視圖。在此,可看到所有其他用戶上傳的圖片、創(chuàng)建日期和照片評論。
  • 上傳:在這個視圖中,用戶可以上傳自己的圖片到照片庫,并添加一個備注(可選)。

每個視圖在Storyboard中都有對應(yīng)的UIViewController, 但你需要注意“照片墻”視圖有兩個表現(xiàn)形式。這是因為你要看到使用Parse實現(xiàn)該視圖的兩種方式。

Parse快速準(zhǔn)備

***步,自然是在使用Parse配置你的工程。

使用以下鏈接下載Parse iOS SDK:https://parse.com/downloads/ios/parse-library/latest

下載后,解壓并拖拽frameworks文件夾下的三個framework文件到你的工程中。當(dāng)提示框顯示時,選擇"Copy items..."和"Create groups..."。Xcode默認(rèn)會將這些framework添加到"ParseTutorial"的target下,不需要額外配置。

  • Parse.framework: 這是最主要的framework, 包含了Parse所有的后臺功能。
  • Bolts.framework: 這個framework是許多底層庫的集合,它使許多任務(wù)變得輕松快捷。
  • ParseUI.framework: 這個framework包含一些非常方便的UI元素,可以直接和Parse對象進(jìn)行交互。你將使用這個framework創(chuàng)建照片墻。

備注:當(dāng)添加Parse到現(xiàn)有工程中時,你還需要添加一些Parse framework依賴的framework,如CoreGraphics和SystemConfiguration。我們的起始工程已經(jīng)包含了這些,你可以在"Parse Quick Start Guide"中找到完整步驟。

Parse SDK是使用Objective-C實現(xiàn)的,而你將使用Swift去創(chuàng)建你的App,要在Swift程序中使用Parse Obj-C的SDK,你需要一個Objective-C橋接頭文件(Objective-C bridging Header file)。

創(chuàng)建橋接頭文件最簡單的方法,就是在你的工程中添加任一Objective-C文件,這樣,Xcode就會自動為你創(chuàng)建頭文件。

Xcode中,選擇File\New\File...并選擇iOS\Source\Objective-C file模板。隨意命名(我們稍后會刪除該文件),然后保存。當(dāng)你保存這個文件時,Xcode會提供一個Objective-C橋接頭文件。如圖所示:

44.png

點擊Yes后,Xcode會創(chuàng)建橋接頭文件并且添加到你的工程中。Objective-C文件已經(jīng)用不上了,可以直接刪除。

打開新創(chuàng)建的"ParseTutorial-Bridging-Header.h"文件,添加以下內(nèi)容到文件底部:

  1. #import #import #import 

添加后,這三個framework就可以在Swift代碼中使用。

接下來,你需要在Parse網(wǎng)站上API key供我們的app使用。在Parse Dashboard上打開你的app的Settings界面,在左邊的面板上選擇Keys按鈕。記下application ID和Client Key。

45.png

下一步,打開AppDelegate.swift文件,定位到application(_:didFinishLaunchingWithOptions:)。在該方法起始處添加如下內(nèi)容:

  1. Parse.setApplicationId("--AppID Goes Here--", clientKey: "--ClientKey Goes Here--"

當(dāng)然,需要在AppID和clientKey的位置要填入你之前記下的真實ID和Key。

Build后運(yùn)行App。如果沒有任何錯誤,意味著app已經(jīng)注冊并連接到Parse后臺。你已經(jīng)可以調(diào)用Parse相關(guān)的服務(wù)了。

下個步驟中,我們要創(chuàng)建一些示例對象。

#p#

創(chuàng)建示例對象

每個上傳的Parse對象都會成為訪問數(shù)據(jù)庫結(jié)構(gòu)的入口。你可以把這些對象看做是字典——事先存儲以關(guān)鍵字標(biāo)示的數(shù)據(jù),然后你就可以通過關(guān)鍵字取到對象。

在該例子中,你將上傳一個叫做“Player”的對象,包含“Name”和“Score”兩個字段。因此在數(shù)據(jù)庫中,將會有一個叫“Player”的表包含所有以“Player”名字上傳的對象。稍后你會看到這個例子。

打開AppDelegate.swift,添加以下代碼到application(_:didFinishLaunchingWithOptions:)方法中,注意放到return true之前。

 
  1. let player = PFObject(className: "Player"
  2. player.setObject("John", forKey: "Name"
  3. player.setObject(1230, forKey: "Score"
  4. player.saveInBackgroundWithBlock { (succeeded, error) -> Void in 
  5.   if succeeded { 
  6.     println("Object Uploaded"
  7.   } else { 
  8.     println("Error: \(error) \(error.userInfo!)"
  9.   } 

正如你看到的,上傳對象的代碼是異步的,你將在閉包中檢查到返回結(jié)果。

PFObject是Parse中的一個基類,它提供了一些基本的對象操作方法。***的好處是,你不需要在Parse網(wǎng)站上創(chuàng)建表,Parse會基于你提交的對象創(chuàng)建表結(jié)構(gòu)。

構(gòu)建,運(yùn)行。如果你正確放置了API key,且app正確注冊了Parse服務(wù),app應(yīng)該正常運(yùn)行。否則,你將收到錯誤信息。

等等,你的對象去哪了?只是漂浮在網(wǎng)絡(luò)空間嗎?

想要正確查看你保存的對象,只需要打開Parse的dashboard,點擊Core,你就能看到如下圖所示的對象:

47.png

恭喜你,你已經(jīng)成功的和網(wǎng)絡(luò)后臺進(jìn)行交互。

注意:如果你在iOS模擬器上運(yùn)行app,并看到錯誤信息如“The network connection was lost”。請嘗試重啟模擬器。其他的網(wǎng)絡(luò)錯誤也可以用這個方法試一下。

若你已經(jīng)獲得“Object Uploaded”消息,但在Dashboard上沒有看到數(shù)據(jù),請點擊右上方的“Refresh”按鈕刷新Dashboard頁面。

進(jìn)行下一步之前,先創(chuàng)建另外一條數(shù)據(jù)。設(shè)置name為“John”,score為810.現(xiàn)在你有兩條數(shù)據(jù),name都為John,但score不同。再添加第三條數(shù)據(jù),name為“Sally”, score為2400。

獲取對象

現(xiàn)在,我們嘗試一下獲取對象。Parse中有PFQuery類來支持這個功能。它可以執(zhí)行數(shù)據(jù)請求,你可以在 PFQuery documentation 中查看到更多資料。

讓我們來實現(xiàn)獲取符合如下條件的對象:

score大于1000,且name等于“John”,注釋掉(或刪除)之前的代碼,不然的話每次運(yùn)行都會上傳一個新的對象。然后放置如下代碼:

 
  1. // 1 
  2. let query = PFQuery(className: "Player"
  3. // 2 
  4. query.whereKey("Name", equalTo: "John"
  5. query.whereKey("Score", greaterThan: 1000
  6. // 3 
  7. query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 
  8.   if error == nil { 
  9.     println("Successfully retrieved: \(objects)"
  10.   } else { 
  11.     println("Error: \(error) \(error.userInfo!)"
  12.   } 
  1. 這里我們創(chuàng)建了數(shù)據(jù)請求的對象,class name即為表名。
  2. 通過whereKey方法,指定只獲取符合條件的對象(name為John,score大于1000)
  3. 發(fā)送請求,然后在閉包中打印結(jié)果。

再次構(gòu)建并運(yùn)行app,數(shù)據(jù)請求是異步的,因此不會對拖慢UI顯示的速度——這會使用戶更滿意。在控制臺中,你應(yīng)該會看到所有符合條件的對象,如圖所示:

48.png

現(xiàn)在我們已經(jīng)探索了存儲和獲取數(shù)據(jù)的基本操作,我們在真實項目里應(yīng)用一下。

記得先注釋掉application(_:didFinishLaunchingWithOptions:) 中我們剛寫的代碼。

用戶注冊

首先,用戶會使用我們的app注冊賬號。

打開RegisterViewController.swift, 當(dāng)前這個界面什么都干不了。我們的任務(wù)就是實現(xiàn)點擊“Sign Up”按鈕后的功能。

定位到signUpPressed(_:)方法中,將代碼替換為:

  1. @IBAction func signUpPressed(sender: AnyObject) { 
  2.   //1 
  3.   let user = PFUser() 
  4.    
  5.   //2 
  6.   user.username = userTextField.text 
  7.   user.password = passwordTextField.text 
  8.    
  9.   //3 
  10.   user.signUpInBackgroundWithBlock { succeeded, error in 
  11.     if (succeeded) { 
  12.       //The registration was successful, go to the wall 
  13.       self.performSegueWithIdentifier(self.scrollViewWallSegue, sender: nil) 
  14.     } else if let error = error { 
  15.       //Something bad has occurred 
  16.       self.showErrorView(error) 
  17.     } 
  18.   } 

以上代碼中,按照如下步驟創(chuàng)建用戶:

  1. 創(chuàng)建PFUser對象,賦值給user。你將使用這個對象來完成登錄和注冊流程。它將存儲你的認(rèn)證用戶信息,這樣你就可以訪問該用戶的數(shù)據(jù)了。你可以通過該鏈接訪問PFUser的文檔:http://www.parse.com/docs/ios/api/Classes/PFUser.html
  2. 取得界面上username和password文本框的內(nèi)容,分別給user對象中相應(yīng)的字段賦值。
  3. 后臺調(diào)用注冊的方法,然后檢查返回值??赡苡袃煞N結(jié)果:返回正常證明已成功創(chuàng)建了用戶,并以該用戶的身份登錄;若有錯誤為創(chuàng)建失敗。創(chuàng)建成功后就直接跳轉(zhuǎn)到照片墻界面,否則則給出錯誤提示。

構(gòu)建、運(yùn)行app查看是否有錯誤。在Log In界面中,點擊Sign Up按鈕,你將看到如下界面:

[[141393]]

輸入用戶名、密碼,點擊Sign Up 按鈕,若一切正常的話你將跳轉(zhuǎn)到照片墻界面。

不錯,不過保險起見,我們還是驗證一下新用戶是否真的已經(jīng)在表中創(chuàng)建成功:Dashboard中打開User選項,如下所示:

50.png

恭喜!你已經(jīng)創(chuàng)建了***個用戶?,F(xiàn)在讓我們用這個用戶登錄,在做些有意思的事情。

登錄

打開LoginViewController.swift類,找到一下方法:

 
  1. @IBAction func logInPressed(sender: AnyObject) { 
  2.   //If user logged succesful: 
  3.   performSegueWithIdentifier(scrollViewWallSegue, sender: nil) 

正如你所見到的,這個方法和注冊流程中的十分相似。這里我們還要用到PFUser,不過是要用做登錄的。替換方法中的代碼:

  1. @IBAction func logInPressed(sender: AnyObject) { 
  2.   PFUser.logInWithUsernameInBackground(userTextField.text, password: passwordTextField.text) { user, error in 
  3.     if user != nil { 
  4.       self.performSegueWithIdentifier(self.scrollViewWallSegue, sender: nil) 
  5.     } else if let error = error { 
  6.       self.showErrorView(error) 
  7.     } 
  8.   } 

流程非常簡單。跳轉(zhuǎn)到下個界面前,我們首先要檢查用戶名和密碼是否能和數(shù)據(jù)庫中的記錄匹配。

構(gòu)建、運(yùn)行程序,效果如下:

51.png

嘗試用我們創(chuàng)建的用戶登錄,如果一切正常,app將會跳轉(zhuǎn)到照片墻界面。保險起見,可以嘗試用錯誤的用戶名或密碼來登錄,看是否有錯誤代碼顯示。

#p#

發(fā)送照片到照片墻

之前的注冊、登錄操作都會跳轉(zhuǎn)到照片墻視圖。在這個視圖中,你會看到所有用戶上傳的圖片和評論。

在那之前,我們得先上傳一些圖片。

使用Parse上傳文件很簡單。打開UploadImageViewController.swift,我們將在這個類中實現(xiàn)上傳功能。

所有用戶登錄后都可以點擊“Upload”按鈕跳轉(zhuǎn)到上傳視圖。

[[141394]]

在這里,用戶可以選擇輸入備注并點擊“Select Picture”,使用系統(tǒng)標(biāo)準(zhǔn)的image picker從照片庫中獲取照片,上傳。

所有上述代碼已經(jīng)在起始工程中實現(xiàn),現(xiàn)在我們需要實現(xiàn)sendPressed(_:)代碼。這個action方法連接到導(dǎo)航欄的“Send”按鈕上。它將照片和備注發(fā)送到服務(wù)器上。
該過程包含兩個部分,一是使用PFFile對象上傳圖片,二是將其添加到PFObject,并上傳至服務(wù)器。

之前我們已經(jīng)看到,可以使用setKey和objectForKey方法添加和獲取PFObject的字段。但現(xiàn)在我們需要用到特定的對象類型(照片墻),這時,自定義的子類可以更好的發(fā)揮作用。接下來你會看到如何實現(xiàn)。

自定義Parse對象

打開Model group下的WallPost.swift文件。當(dāng)前你會看到繼承自NSObject類的簡單類。首先,修改父類,使其繼承自PFObject:

  1. class WallPost: PFObject {   

你還需要WallPost類遵循PFSubclassing協(xié)議。

PFSubclassing協(xié)議 定義了一些繼承PFObject的必要方法。PFObject+Subclass.h中定義的category實現(xiàn)了這些方法,你需要做的是在自己的子類中重寫它們。

具體做法是在WallPost類中添加擴(kuò)展,擴(kuò)展中包含這兩個必要方法:

 
  1. extension WallPost: PFSubclassing { 
  2.   // Table view delegate methods here 
  3.   //1 
  4.   class func parseClassName() -> String { 
  5.     return "WallPost" 
  6.   } 
  7.    
  8.   //2 
  9.   override class func initialize() { 
  10.     var onceToken: dispatch_once_t = 0 
  11.     dispatch_once(&onceToken) { 
  12.       self.registerSubclass() 
  13.     } 
  14.   } 
  1. 按照后臺數(shù)據(jù)庫的記錄設(shè)置類名。
  2. 讓Parse知道:所有類的類型為WallPost的對象,都將使用該子類。這個方法只應(yīng)被調(diào)用一次,因此我們使用dispatch_once_t方法。

接下來,我們?yōu)閃allPost類添加三個屬性:

  • @NSManaged var image: PFFile
  • @NSManaged var user: PFUser
  • @NSManaged var comment: String?

這里,我們用PFFile類型的image放置上傳用的照片,PFUser類型的user保存用戶信息,還有String類型的comment保存照片備注。

我們使用了@NSManager,因為從底層角度來看,PFObject的屬性只是一些鍵值對參數(shù)的集合。當(dāng)我們設(shè)置某一個屬性的時候,會自動被作為鍵值對設(shè)置。

另外,在子類中我們需要定義一個query()方法,返回PFQuery對象,添加以下代碼到WallPost.swift文件:

 
  1. override class func query() -> PFQuery? { 
  2.   //1 
  3.   let query = PFQuery(className: WallPost.parseClassName()) 
  4.   //2 
  5.   query.includeKey("user"
  6.   //3 
  7.   query.orderByDescending("createdAt"
  8.   return query 

以下是這段代碼的詳細(xì)說明:

  1. 為WallPost類創(chuàng)建PFQuery對象。
  2. 調(diào)用該方法以返回完整的user信息。若沒有這句,該query只會返回當(dāng)前對象的引用,而不包含任何成員的信息。
  3. 按照創(chuàng)建日期排序。

***,我們需要添加初始化方法。

  1. init(image: PFFile, user: PFUser, comment: String?) { 
  2.   super.init() 
  3.    
  4.   self.image = image 
  5.   self.user = user 
  6.   self.comment = comment 
  7.    
  8. override init() { 
  9.   super.init() 

以上就是一個簡單的初始化方法,不管是否給定初始值,都可以創(chuàng)建一個WallPost對象。

WallPost已經(jīng)完成,讓我們繼續(xù)上傳照片的工作。

打開UploadImageViewController.swift, 在sendPresed(_:)方法末尾處,添加以下代碼:

 
  1. //Upload a new picture 
  2. //1 
  3. let file = PFFile(name: "image", data: pictureData) 
  4. file.saveInBackgroundWithBlock({ (succeeded, error) -> Void in 
  5.   if succeeded { 
  6.     //2 
  7.     self.saveWallPost(file) 
  8.   } else if let error = error { 
  9.     //3 
  10.     self.showErrorView(error) 
  11.   } 
  12. }, progressBlock: { percent in 
  13.    //4 
  14.    println("Uploaded: \(percent)%"
  15. }) 

以下是詳細(xì)說明:

  1. 使用image data創(chuàng)建PFFile對象,然后在后臺執(zhí)行保存動作。
  2. 如果成功,保存文件相關(guān)PostWall對象。
  3. 如果不成功,告知用戶。
  4. 保存文件時,Parse支持跟蹤保存進(jìn)度。通過progress block即可得知當(dāng)前進(jìn)度。這里我們只是簡單的把進(jìn)度打印到控制臺。

接下來實現(xiàn)saveWallPost(_:)方法:

 
  1. func saveWallPost(file: PFFile) 
  2.   //1 
  3.   let wallPost = WallPost(image: file, user: PFUser.currentUser()!, comment: self.commentTextField.text) 
  4.   //2       
  5.   wallPost.saveInBackgroundWithBlock{ succeeded, error in 
  6.     if succeeded { 
  7.       //3 
  8.       self.navigationController?.popViewControllerAnimated(true
  9.     } else { 
  10.       //4 
  11.       if let errorMessage = error?.userInfo?["error"] as? String { 
  12.         self.showErrorView(error!) 
  13.       } 
  14.     } 
  15.   } 

詳細(xì)說明如下:

  1. 根據(jù)上傳圖片、當(dāng)前已登錄用戶和圖片備注創(chuàng)建WallPost對象。
  2. 后臺保存WallPost對象。
  3. 如果成功,返回照片墻。
  4. 否則,告知用戶。

構(gòu)建、運(yùn)行app。登錄之前創(chuàng)建的用戶,進(jìn)入圖片上傳界面,點擊“Select Picture”按鈕,從照片庫中選擇一張圖片,然后隨便寫一條備注,點擊“Send”按鈕。

在控制臺上你可以看到上傳的百分比。這里只是將其顯示在控制臺上,在最終版的app中,使用該進(jìn)度顯示一個progress bar更合適。

在Dashboard上,查看Core數(shù)據(jù),你將會看到一個新的表,名為WallPost。不錯,但是唯一的不足是你沒有辦法在app上看到上傳的照片。

那么我們下一步就來實現(xiàn)取回照片的功能。

#p#

在照片墻上展示照片

打開WallPicturesViewController.swift,該視圖將會顯示所有用戶上傳的照片。當(dāng)該視圖加載時,它會調(diào)用getWallImages()方法來獲取所有對象,當(dāng)前其為空。

要是其可以工作,我們得先添加一些代碼,在獲取照片后放置它們在照片墻。添加loadWallViews(_:)方法:

 
  1. func loadWallViews(objects: [WallPost]) { 
  2.   cleanWall() 
  3.    
  4.   var originY: CGFloat = 0 
  5.    
  6.   for wallPost in objects { 
  7.     //1 
  8.     let wallView = UIView(frame: CGRect(x: 0, y: originY, 
  9.       width: self.wallScroll.frame.size.width, height: 270)) 
  10.    
  11.     //2 
  12.     wallPost.image.getDataInBackgroundWithBlock { data, error in 
  13.       if let data = data, image = UIImage(data: data) { 
  14.         //3 
  15.         //Add the image 
  16.         let imageView = UIImageView(image: image) 
  17.         imageView.frame = CGRect(x: 10, y: 10, width: wallView.frame.size.width - 20, height: 200
  18.         imageView.contentMode = UIViewContentMode.ScaleAspectFit 
  19.         wallView.addSubview(imageView) 
  20.    
  21.         //4 
  22.         //Add the info label (User and creation date) 
  23.         let creationDate = wallPost.createdAt 
  24.         let dateFormatter = NSDateFormatter() 
  25.         dateFormatter.dateFormat = "HH:mm dd/MM yyyy" 
  26.    
  27.         let infoLabel = UILabel(frame: CGRect(x: 10, y: 220, width: 0, height: 0)) 
  28.         let dateString = dateFormatter.stringFromDate(creationDate!) 
  29.    
  30.         if let username = wallPost.user.username { 
  31.           infoLabel.text = "Uploaded by: \(username), \(dateString)" 
  32.         } else { 
  33.           infoLabel.text = "Uploaded by anonymous: , \(dateString)" 
  34.         } 
  35.    
  36.         infoLabel.text = "Uploaded by: \(wallPost.user.username), \(dateString)" 
  37.         infoLabel.font = UIFont(name: "HelveticaNeue", size: 12
  38.         infoLabel.textColor = UIColor.whiteColor() 
  39.         infoLabel.backgroundColor = UIColor.clearColor() 
  40.         infoLabel.sizeToFit() 
  41.         wallView.addSubview(infoLabel) 
  42.    
  43.         //5 
  44.         //Add the comment label (User and creation date) 
  45.         let commentLabel = UILabel(frame: CGRect(x: 10, y: CGRectGetMaxY(infoLabel.frame)+5, width:0, height: 0)) 
  46.         commentLabel.text = wallPost.comment 
  47.         commentLabel.font = UIFont(name: "HelveticaNeue", size: 16
  48.         commentLabel.textColor = UIColor.whiteColor() 
  49.         commentLabel.backgroundColor = UIColor.clearColor() 
  50.         commentLabel.sizeToFit() 
  51.         wallView.addSubview(commentLabel) 
  52.       } 
  53.     } 
  54.    
  55.     //6 
  56.     wallScroll.addSubview(wallView) 
  57.     originY += 270 
  58.   } 
  59.   //7 
  60.   wallScroll.contentSize.height = CGFloat(originY) 

首先我們清除scrollview上所有的UIView對象.然后我們使用快速枚舉的方法遍歷數(shù)組中的對象,針對每一個對象,執(zhí)行以下步驟:

  1. 創(chuàng)建一個視圖來顯示圖片和詳情。
  2. 下載圖片數(shù)據(jù)。
  3. 添加圖片視圖到照片墻。
  4. 獲取上傳圖片的用戶的信息,將創(chuàng)建日期放置在label上。
  5. 添加包含備注信息的label。
  6. 將上述界面元素放置到scroll view上,并且增加用以指示下個顯示位置的坐標(biāo)。
  7. 設(shè)置scrollview的content size。

現(xiàn)在,替換getWallImages()方法的內(nèi)容:

 
  1. func getWallImages() { 
  2.   //1 
  3.   let query = WallPost.query()! 
  4.   query.findObjectsInBackgroundWithBlock { objects, error in 
  5.     if error == nil { 
  6.       //2 
  7.       if let objects = objects as? [WallPost] { 
  8.         self.loadWallViews(objects) 
  9.       } 
  10.     } else if let error = error { 
  11.       //3 
  12.       self.showErrorView(error) 
  13.     } 
  14.   } 

詳細(xì)說明:

  1. 創(chuàng)建一個簡單的query 對象來獲取WallPost對象,并將結(jié)果按照創(chuàng)建日期排序。
  2. 查找到符合條件的對象。這里,即為WallPost對象。如果一切正常,則在照片墻上加載圖片。
  3. 如果有錯誤的話,提示用戶。

構(gòu)建、運(yùn)行app。你將看到之前上傳的圖片和備注信息?;c時間玩一下,再多添加些圖片和備注。然后在照片墻上看看。

很酷,不是嗎?

Parse UI

之前提過,還有另外一種展示保存圖片的方法。接下來我們看一下這種方法。

前面的例子中,我們使用了一個簡單的UIScrollView對象來展示圖片,這需要我們自己來計算content size。你可能想過使用UITableView可能更好,當(dāng)然,聰明的Parse開發(fā)者早就考慮到了,因此,它們編寫了ParseUI.framework,提供了很多方便的東西來顯示Parse相關(guān)的UI。

我們主要看看以下三個:

  • PFQueryTableViewController:這是UITableViewController的子類??梢杂脕砗芊奖愕脑趖able view中顯示PFQuery的結(jié)果。
  • PFTableViewCell:UITableViewCell的子類,和PFQueryTableViewController搭配使用。
  • PFImageView:UIImageView的子類,包含管理下載和顯示Parse圖片的功能。

現(xiàn)在,打開WallPicturesTableViewController.swift將它的父類從UITableViewController 修改為PFQueryTableViewController。

當(dāng)然,WallPostTableViewCell也要繼承自PFTableViewCell,其中的postImage對象的類型也要改為PFImageView。

編寫代碼之前,我們需要對storybaord做些修改。打開Main.storyboard,找到WallTableView scene:

55.png

打開屬性查看器(Attributes Inspector),你會看到一個包含PFQueryTableViewController參數(shù)的選項:

56.png

這些參數(shù)可以讓你選擇顯示在table上的對象類型。并且可以指定下拉刷新、分頁和loading界面。當(dāng)使用簡單的UITableview來展示結(jié)果時,你甚至可以設(shè)置table中要顯示的PFObject字段的key,而不需要動手在代碼中去設(shè)置。在Parse Class的參數(shù)中,填入WallPost。

現(xiàn)在回到WallPicturesTableViewController.swift文件,添加以下方法:

  1. override func viewWillAppear(animated: Bool) { 
  2.   loadObjects() 
  3.    
  4. override func queryForTable() -> PFQuery { 
  5.   let query = WallPost.query() 
  6.   return query! 

每次顯示照片墻界面,我們都希望它被重新加載。為了指定運(yùn)行的請求,我們重寫queryForTable()方法為WallPost返回一個query對象。

***,添加以下tableview的delegate方法:

 
  1. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell? { 
  2.   // 1 
  3.   let cell = tableView.dequeueReusableCellWithIdentifier("WallPostCell", forIndexPath: indexPath) as! WallPostTableViewCell 
  4.    
  5.   // 2           
  6.   let wallPost = object as! WallPost 
  7.    
  8.   // 3   
  9.   cell.postImage.file = wallPost.image 
  10.   cell.postImage.loadInBackground(nil) { percent in 
  11.   cell.progressView.progress = Float(percent)*0.01 
  12.     println("\(percent)%"
  13.   } 
  14.    
  15.   // 4           
  16.   let creationDate = wallPost.createdAt 
  17.   let dateFormatter = NSDateFormatter() 
  18.   dateFormatter.dateFormat = "HH:mm dd/MM yyyy" 
  19.   let dateString = dateFormatter.stringFromDate(creationDate!) 
  20.    
  21.   if let username = wallPost.user.username { 
  22.     cell.createdByLabel.text = "Uploaded by: \(username), \(dateString)" 
  23.   } else { 
  24.     cell.createdByLabel.text = "Uploaded by anonymous: , \(dateString)" 
  25.   } 
  26.    
  27.   cell.createdByLabel.text = "Uploaded by: \(wallPost.user.username), \(dateString)" 
  28.    
  29.   cell.commentLabel.text = wallPost.comment 
  30.    
  31.   return cell 

這個方法替換掉UITableView原生的data source方法tableView(_:cellForRowAtIndexPath:),這樣的形式更合適,因為它直接傳遞PFObject對象,而不需要通過index path查找對應(yīng)的對象。

我們來看一下具體的代碼解釋:

  1. 從table view中dequeue出一個cell對象,轉(zhuǎn)換成WallPostTableViewCell類型。
  2. 轉(zhuǎn)換PFObject對象為WallPost類型。
  3. 調(diào)用PFImageView的loadInBackground方法,下載圖片。在complete closure中記錄下載進(jìn)度。這里你需要將這個進(jìn)度顯示在UIProgressBar上。
  4. 添加創(chuàng)建日期、用戶名和備注到cell上。

運(yùn)行代碼前,還有***一個步驟.打開LoginViewController.swift,在loginPressed(_:)方法中,將scrollViewWallSegue替換為tableViewWallSegue。在RegisterViewController.swift中,也進(jìn)行同樣的替換,這樣就可以正常跳轉(zhuǎn)到新版本的照片墻視圖。

構(gòu)建、運(yùn)行app, 你會看到照片墻顯示在table view上,圖片下載時,還能看到進(jìn)度條更新進(jìn)度。

#p#

保持登入、登出

你應(yīng)該已經(jīng)意識到,每次app啟動時,用戶都需要重新登錄。另外,"Log Out"按鈕每次只是將用戶帶到主界面,而沒有實際的登出功能。

在教程的***,我們將添加記住登錄狀態(tài)的功能,即使app重新啟動,登錄狀態(tài)也會保持。另外,我們還會添加真正的登出功能。

打開LoginViewController.swift,添加以下代碼到viewDidLoad()方法中:

  1. //Check if user exists and logged in 
  2. if let user = PFUser.currentUser() { 
  3.   if user.isAuthenticated() { 
  4.     self.performSegueWithIdentifier(scrollViewWallSegue, sender: nil) 
  5.   } 

當(dāng)用戶登錄后,Parse將會在app重啟時記錄用戶和狀態(tài)。這里我們用可選值綁定(if let)檢查當(dāng)前是否存在用戶。如果存在,我們檢查用戶是否已認(rèn)證,若已認(rèn)證,證明用戶已登錄,直接跳轉(zhuǎn)到照片墻視圖。

要登出用戶,打開WallPicturesTableViewController.swift, 找到logOutPressed(_:)方法,添加以下代碼:

  1. @IBAction func logOutPressed(sender: AnyObject) { 
  2.   PFUser.logOut() 
  3.   navigationController?.popToRootViewControllerAnimated(true

這里我們簡單地登出當(dāng)前用戶,并跳轉(zhuǎn)到初始的登錄界面。記得在WallPicturesViewController.swift中添加同樣的登出代碼。

構(gòu)建、運(yùn)行,大功告成!

下一步做什么?

這個鏈接包含了完整的實例工程:http://cdn4.raywenderlich.com/wp-content/uploads/2015/04/ParseTutorial-Finished.zip

你已經(jīng)看到了使用PFObject子類上傳、下載對象是如何便利。也學(xué)到了在Parse使用PFUser的方法。

使用Parse可以完成更多的工作。Parse還支持在app內(nèi)部給你的用戶發(fā)送推送通知。還有更多的社交功能已經(jīng)集成到framework中。你也可以添加數(shù)據(jù)分析記錄用戶行為。

Parse提供更多高級特性,例如編寫云端代碼,在后臺安排可循環(huán)執(zhí)行的計劃任務(wù)。

在你編寫Parse app的過程中,你會更加了解它。本人強(qiáng)烈推薦你探索更多高級的特性。

現(xiàn)在,對于添加后臺功能這件事,你應(yīng)該已經(jīng)信心十足了。如何創(chuàng)建一個云端應(yīng)用,現(xiàn)在已經(jīng)不是一件高不可攀的事情了。

希望看到你做出更多基于Parse的app。如果有任何問題或建議,請加入論壇,一起討論。

責(zé)任編輯:倪明 來源: raywenderlich'文章
相關(guān)推薦

2011-07-15 14:19:10

故障恢復(fù)控制臺

2011-07-11 10:30:46

2022-07-06 07:48:38

分布式存儲架構(gòu)

2010-06-11 13:53:54

UML建模

2015-06-24 10:06:09

iOS 9適配后臺

2014-05-04 13:47:39

銳捷網(wǎng)絡(luò)極簡網(wǎng)絡(luò)

2011-08-10 15:48:10

iPhone網(wǎng)絡(luò)

2018-11-28 14:30:49

權(quán)限系統(tǒng)數(shù)據(jù)

2017-12-12 07:47:59

dockermarathon服務(wù)器

2011-07-21 10:17:53

java

2011-06-02 10:28:11

網(wǎng)絡(luò)命令

2021-11-22 08:50:20

Kubernetes網(wǎng)絡(luò)策略云原生應(yīng)用程序

2017-07-18 10:14:23

OracleMerge into教程

2011-07-18 09:35:29

iPhone 框架

2009-07-22 13:32:43

iBATIS DAO

2020-10-17 09:48:55

Spinnaker實踐

2021-07-14 10:29:30

REvil勒索軟件基礎(chǔ)設(shè)施

2022-05-02 18:45:33

Kubernetes網(wǎng)絡(luò)模型

2011-03-10 15:34:21

網(wǎng)絡(luò)管理

2010-09-10 13:42:03

wifi無線網(wǎng)絡(luò)
點贊
收藏

51CTO技術(shù)棧公眾號