現在就來一睹 Rumiya 的文章吧。
Parse 是與平台無關的第三方「雲端 App 解決方案」。你可以從這裡得知更多訊息。本文屬於進階的程式設計教學,將會介紹如何在 Swift 專案中運用 Parse ,並且將使用者登入資訊存放到 Parse 雲端儲存中。
開始使用
我已經預備好包含 Storyboard 和視圖控制器類別的專案範本了。此專案已經把登入( Login )、註冊( Sign Up )、重設密碼( Reset Password )和主畫面( Home Screen )等頁面都設計好了。
執行此專案應該會在主畫面上看到一個簡單的使用者設定檔。在開始之前,不妨花幾分鐘的時間先讓你自己熟悉一下這份專案範本。
加入 Parse 框架
首先,登入你的 Parse 帳號或是免費註冊新的帳號。來到 Dashboard 頁面,點擊「 Create a new App 」(建立新的 App )。將新的 App 命名為「 ParseDemo 」並且按下「 Create 」按鈕。
接著,選取此 App 方塊底部的「 Quickstart Guide 」(快速入門指南)。在後續的畫面中,依序點選: Data > Mobile > iOS > Swift — Existing Project 。
現在應該已經準備好可以依循「 Install the SDK 」(安裝 SDK )的步驟了。將 Parse 框架連同列出的程式庫新增到你的 App 的 Frameworks 群組中。
我們需要將 Parse 初始化。作法是匯入 Parse 和 Bolts 框架,並且以 QuickStart 所產生的程式碼(如下所示)來更新 AppDelegate.swift 檔案:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.enableLocalDatastore()
// 初始化 Parse
Parse.setApplicationId("OzyfQlVF5pHLA0OmRHB0RKsfXpdWwGWJ1mYgDTI6", clientKey: "f7Jw2X4XzSW0whm2aDtYl7wdIYn5hZVvHuPJ72zu")
// [選用] 追蹤統計 App 的開啟次數
PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
return true
}
別忘了置換成你自己的 App ID 和用戶端金鑰。你可以在自己的 Parse 儀表板的 Settings 分頁中找到這些金鑰。
確定在下列這些類別的開頭都匯入了 Parse :
- LoginViewController.swift
- HomeViewController.swift
- SignUpViewController.swift
- ResetPasswordViewController.swift
現在,編譯並執行。你的 iOS App 在執行時應該不會在 Xcode 中看到錯誤。
顯示登入畫面
在進入使用者設定檔的主畫面之前, App 的使用者必須先登入或註冊。假使目前的訪客並未登入的話,我們需要帶出登入畫面。
在 HomeViewController.swift 檔案中加入下列的函式,以便透過 Storyboard 識別碼「 Login 」來實體化 Login View Controller :
override func viewWillAppear(animated: Bool) {
if (PFUser.currentUser() == nil) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Login") as! UIViewController
self.presentViewController(viewController, animated: true, completion: nil)
})
}
}
編譯並執行此專案。 App 啟動後應該會帶出登入畫面。目前尚未有任何註冊的使用者。我們需要能夠導覽至註冊畫面,好讓使用者能夠註冊。
註冊
要在 Storyboard 上顯示註冊畫面,必須在登入視圖控制器中點擊 Sign Up 按鈕。按住 Control 鍵將選定的按鈕拖曳到 Sign Up View Controller 。當提示視窗彈出時,選取「 present modally 」(以強制回應方式呈現)。
在 SignUpViewController.swift 中,針對電子郵件、使用者名稱和密碼等文字欄位宣告下列的 Outlet 變數:
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var passwordField: UITextField!
接著,加入下列的程式碼,以便建立動作函式:
@IBAction func signUpAction(sender: AnyObject) {
let username = self.usernameField.text
let password = self.passwordField.text
let email = self.emailField.text
let finalEmail = email!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
// 驗證文字欄位
if let username = username where username.characters.count < 5 {
let alert = UIAlertView(title: "Invalid", message: "Username must be greater than 5 characters", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else if let password = password where password.characters.count < 8 {
let alert = UIAlertView(title: "Invalid", message: "Password must be greater than 8 characters", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else if let email = email where email.characters.count < 8 {
let alert = UIAlertView(title: "Invalid", message: "Please enter a valid email address", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else {
// 顯示旋轉圖示,代表工作正在進行中
let spinner: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(0, 0, 150, 150)) as UIActivityIndicatorView
spinner.startAnimating()
let newUser = PFUser()
newUser.username = username
newUser.password = password
newUser.email = finalEmail
// 以非同步方式註冊使用者
newUser.signUpInBackgroundWithBlock({ (succeed, error) -> Void in
// 停止旋轉圖示
spinner.stopAnimating()
if ((error) != nil) {
let alert = UIAlertView(title: "Error", message: "\(error)", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else {
let alert = UIAlertView(title: "Success", message: "Signed Up", delegate: self, cancelButtonTitle: "OK")
alert.show()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Home")
self.presentViewController(viewController, animated: true, completion: nil)
})
}
})
}
}
此動作函式會在使用者點擊 Sign Up 按鈕時被觸發。首先會針對文字欄位的數值進行簡單的驗證。如果驗證成功的話,便會呼叫 Parse 的 signUpInBackgroundWithBlock
函式。此 signUpInBackgroundWithBlock
函式的執行需要花費一些時間,因為它是採用非同步的方式。旋轉圖示指出工作正在進行中。當工作做完時,會有訊息通知使用者關於註冊的成敗。如果註冊成功的話,使用者將會登入並導覽至主畫面。
現在,來到 Storyboard 並且選取 Sign Up View Controller 場景。在 Connection Inspector 中,將每個 Outlet 變數連結到對應的文字欄位。
接著,選取 Sign Up 按鈕。在 Connection Inspector 中,將此按鈕連結到 Touch Up Inside 事件。當提示視窗彈出時,選取「 signUpAction: 」項目。
為了能夠關閉註冊畫面,我們需要定義用來解除的 Segue 。來到 LoginViewController.swift ,加入下列的解除動作:
@IBAction func unwindToLogInScreen(segue:UIStoryboardSegue) {
}
在 Storyboard 中,選取 Sign Up View Controller 場景,按住 Control 鍵並且拖曳關閉鈕至 Exit 圖示。當提示視窗彈出時,選取 Action Segue 區段中的「 unwindToHome: 」項目。
編譯並執行。現在應該能夠註冊使用者了。
來到你的 Parse 帳號,選取 ParseDemo 的 Core 。選取 User 區段以便檢視首位註冊成功的使用者:
登入與登出
接著讓我們來實作登入和登出的部分。在 LoginViewController.swift 中,針對使用者名稱與密碼等文字欄位宣告下列的 Outlet 變數:
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var passwordField: UITextField!
然後加入下列的動作函式:
@IBAction func loginAction(sender: AnyObject) {
let username = self.usernameField.text
let password = self.passwordField.text
// 驗證文字欄位
if let username = username where username.characters.count < 5 {
let alert = UIAlertView(title: "Invalid", message: "Username must be greater than 5 characters", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else if let password = password where password.characters.count < 8 {
let alert = UIAlertView(title: "Invalid", message: "Password must be greater than 8 characters", delegate: self, cancelButtonTitle: "OK")
alert.show()
} else {
// 顯示旋轉圖示,代表工作正在進行中
let spinner: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(0, 0, 150, 150)) as UIActivityIndicatorView
spinner.startAnimating()
// 送出登入的要求
PFUser.logInWithUsernameInBackground(username!, password: password!, block: { (user, error) -> Void in
// 停止旋轉圖示
spinner.stopAnimating()
if ((user) != nil) {
let alert = UIAlertView(title: "Success", message: "Logged In", delegate: self, cancelButtonTitle: "OK")
alert.show()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Home")
self.presentViewController(viewController, animated: true, completion: nil)
})
} else {
let alert = UIAlertView(title: "Error", message: "\(error)", delegate: self, cancelButtonTitle: "OK")
alert.show()
}
})
}
}
上述的程式碼會在使用者點擊 Login 按鈕時被觸發。跟我們在 SignUpViewController.swift 中所實作的動作函式很類似。差別在於這回呼叫的是 logInWithUsernameInBackground
(而不是 signUpInBackgroundWithBlock )函式,以便將輸入的使用者名稱與密碼傳送至 Parse 。如果登入成功的話,將會出現 Storyboard 識別碼為「 Home 」的 Home View Controller 。
現在,在 Storyboard 中,將 Login View Controller 的 Outlet 變數與對應的文字欄位相連結。選取 Login 按鈕。在 Connection Inspector 中,將此按鈕連結到 Touch Up Inside 事件。當提示視窗彈出時,選取「 loginAction: 」項目。
為了要讓使用者也能夠登出,我們必須在 HomeViewController.swift 中實作 logOutAction 動作函式:
@IBAction func logOutAction(sender: AnyObject){
// 傳送使用者登出的要求
PFUser.logOut()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Login")
self.presentViewController(viewController, animated: true, completion: nil)
})
}
上述的程式碼呼叫了 Parse 的 logOut 函式,並將 Login 場景實體化。
在 Storyboard 中,選取 Logout 按鈕。在 Connection Inspector 中,將此按鈕連結到 Touch Up Inside 事件。當提示視窗彈出時,選取「 logOutAction: 」項目。
在進行此部分的測試之前,我們還有一件事情要做。下列的步驟會將「 username 」文字置換成實際的使用者名稱(花幾分鐘思考一下原因吧)。現在輪到在 HomeViewController.swift 檔案中為 Username 標籤宣告 Outlet 變數了,示範如下:
@IBOutlet weak var userNameLabel: UILabel!
以下列的程式碼來更新 viewDidLoad
函式:
override func viewDidLoad() {
super.viewDidLoad()
// 顯示目前訪客的使用者名稱
if let pUserName = PFUser.currentUser()?["username"] as? String {
self.userNameLabel.text = "@" + pUserName
}
}
回到 Storyboard ,將 userNameLabel Outlet 變數與 Home View Controller 中對應的 User Name 標籤相連結。
編譯並執行。主畫面上將會顯示目前的使用者名稱。
重設密碼
在 ResetPasswordViewController.swift 中,針對 Email 文字欄位宣告如下的 Outlet 變數:
@IBOutlet weak var emailField: UITextField!
接著,加入下列的動作函式:
@IBAction func passwordReset(sender: AnyObject) {
let email = self.emailField.text
let finalEmail = email!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
// 傳送重設密碼的要求
PFUser.requestPasswordResetForEmailInBackground(finalEmail)
let alert = UIAlertController (title: "Password Reset", message: "An email containing information on how to reset your password has been sent to " + finalEmail + ".", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
在此我們只是呼叫 requestPasswordResetForEmailInBackground
函式並帶入指定的電子郵件,藉以重設密碼。隨後會由 Parse 接手處理密碼重設作業。假使電子郵件是有效的,便會將如何重設密碼的指示寄送到該電子郵件的地址。
現在你對於如何在 Storyboard 中設定 ResetPasswordViewController
的流程應該已經很熟悉了。從登入畫面設定 Segue 、將 Outlet 變數連結至文字欄位,並且將動作函式連結至按鈕。同時也別忘了賦予關閉按鈕解除的功能。
這樣就完成了!供你參考,請從這裡下載本文的完整 Xcode 專案。別忘了更新 AppDelegate.swift 裡面的 Parse 金鑰。
還沒有完,需要做的事情其實還有很多。舉例而言,可以嘗試找尋驗證電子郵件文字欄位正確性的方法。使用者的設定檔還沒有放照片。可以考慮實作上傳和儲存設定檔大頭照的功能。也可以加入以 Facebook 登入的選項。
如你所見, Parse 幫我們完成了許多繁雜的工作,讓你可以專注於製作漂亮又實用的 App 。試著用用看 Parse 吧,祝福你寫程式愉快!