程式設計師的自述:如何在iOS中構建實時用戶的狀態更新

在構建聊天應用程序時,看到朋友的列表和朋友的狀態並不少見。像WhatsApp這樣的應用程序具有此功能,檢查您的朋友的狀態非常有用,並知道在那時向他們發送消息是否明智。


我們將在一個虛構的iOS聊天應用程序中構建一個類似的功能。我們將使用Pusher為應用程序實現實時功能,以便當有人發佈新狀態更新時,您可以實時看到它發生變化。

這裡是我們完成應用程序後的畫面記錄

程序員的自述:如何在iOS中構建實時用戶的狀態更新

要遵循本文,您必須具備以下要求:

- 有關Swift 3的一些知識

- 有關如何使用Xcode的知識

- 基本JavaScript知識- 安裝在您計算機上的NPM和CocoaPods。

- 有關終端的基本知識(命令行)

- Pusher應用程序(您將需要應用程序的ID,秘密,密鑰和群集)。

如果您目前沒有帳戶,請創建一個Pusher帳戶。

準備好我們的項目

要開始前,我們需要創建iOS項目,然後安裝應用程序正常運行所需的一些依賴關係。讓我們開始吧。

在Xcode中設置我們的項目在

您的機器上啟動Xcode並創建一個新項目。創建一個應用程序項目並按照嚮導進行操作,直到到達主要的故事板。一旦你在那裡,退出Xcode。

在您的終端中,cd進入Xcode項目目錄,然後運行以下命令:

$ pod init

這將Podfile在您的應用程序的根部創建一個內部。Podfile是我們將定義Cocoapods依賴關係的地方。在文本編輯器中打開並替換為以下內容:

platform :ios, '8.4'

target 'project_name' do

use_frameworks!

pod 'PusherSwift', '~> 4.0'

pod 'Alamofire', '~> 4.4'

end

在上面,我們剛剛指定了我們希望CocoaPods安裝到我們的應用程序中的依賴關係。不要忘記用您的實際項目名稱替換project_name。

現在去終端並運行命令:

$ pod install

這應該安裝我們在我們指定的所有依賴和庫Podfile。大!最後,打開項目目錄並雙擊目錄中的.xcworkspace文件以在Xcode中啟動項目工作區。

創建我們的實時iOS應用程序的用戶界面

現在我們已經在Xcode中創建了項目併成功安裝了所有的依賴關係,接下來我們要做的就是創建iOS應用程序的用戶界面。main.storyboard在Xcode中打開文件,讓我們開始設計UI。

這是我們在本節末尾想要的:

程序員的自述:如何在iOS中構建實時用戶的狀態更新

在畫布中添加一個導航控制器,並將其設置為根視圖控制器。完成此操作後,您需要將TableViewController附件更新到導航控制器。

首先,用Xcode創建一個新類ctrl+n; 類名應該是FriendsViewController,它應該擴展UITableViewController。然後,在main.storyboard文件中,確保你TableViewController使用它FriendsViewController作為它的自定義類。

程序員的自述:如何在iOS中構建實時用戶的狀態更新

配置原型單元格

現在我們已經創建了表格視圖控制器,我們需要配置其單元格以匹配我們試圖實現的目標。

點擊主故事板文件上的"Prototype Cells",並使屬性檢查器看起來接近下面的圖像。

對於圖像**avatar.png** **,您可以將45x45 像素的圖像添加到Xcode項目中,並將其用作單元格的圖像。**

程序員的自述:如何在iOS中構建實時用戶的狀態更新

我們可以做的最後一件事(完全是可選的)是改變我們應用程序的導航欄顏色。讓我們這樣做。

打開AppDelegate該類並在該application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)方法中粘貼以下內容:

UINavigationBar.appearance().barTintColor = UIColor(red: 18.0/255.0, green: 140.0/255.0, blue: 126.0/255.0, alpha: 1.0)

UINavigationBar.appearance().tintColor = UIColor.white

UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

有了這個,你已經完成了為應用程序創建UI,剩下的就是支持它的功能。現在讓我們來做。

創建我們的實時iOS應用程序的功能

對於功能,我們將它分成兩部分。第一部分將著重於添加用於更新狀態的功能,第二部分將著重於實時更新。

創建初始功能:U **** pdate status

允許打開FriendsViewController並進行一些修改。第一個修改是將一個更新"狀態"按鈕添加到導航欄的右上角。

在viewDidLoad控制器的方法中,添加下面的代碼:

navigationItem.title = "Friends List"

navigationItem.rightBarButtonItem = UIBarButtonItem(

title: "Status",

style: .plain,

target: self,

action: #selector(showPopup(_:))

)

上面的代碼只需在導航欄中設置控制器的標題,並在導航欄的右側添加一個按鈕。

如果你注意到,在action參數中它指向一個方法,showPopup所以讓我們創建這個方法。將此方法添加到控制器中:

public func showPopup(_ sender: Any) {

let alertController = UIAlertController(

title: "Update your status",

message: "What would you like your status to say?",

preferredStyle: .alert

)

alertController.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in

textField.placeholder = "Status"

})

alertController.addAction(UIAlertAction(title: "Update", style: .default, handler: {(_ action: UIAlertAction) -> Void in

let status = (alertController.textFields?[0].text)! as String

self.postStatusUpdate(message: status)

}))

alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

present(alertController, animated: true, completion: nil)

}

因此,我們在這裡所做的是,當調用操作並showPopup調用方法時,應用程序將顯示一個彈出框,要求用戶輸入其狀態。

現在,彈出窗口調用了一個postStatusUpdate在我們的應用程序中不存在的方法。現在讓我們創建這個方法。

在視圖控制器中,添加下面的方法:

public func postStatusUpdate(message: String) {

let params: Parameters = ["username": username, "status": message]

Alamofire.request(FriendsViewController.API_ENDPOINT + "/status", method: .post, parameters: params).validate().responseJSON { response in

switch response.result {

case .success:

_ = "Updated"

case .failure(let error):

print(error)

}

}

}

在這種方法中,我們正在使用該Alamofire庫向端點FriendsViewController.API_ENDPOINT + "/status``"(尚不存在)發出請求。現在,因為我們沒有導入Alamofire庫,也沒有定義FriendsViewController.API_ENDPOINT我們會得到錯誤。

在視圖控制器的頂部,導入Alamofire庫:

import 'Alamofire'

另外,在類內部,在類定義之後,添加以下內容來聲明API_ENDPOINT哪個將指向遠程HTTP服務器。


static let API_ENDPOINT = "http://localhost:4000";

我們現在使用的端點是本地服務器,稍後將在本文中創建。如果您使用遠程服務器,則需要將此值替換為服務器的URL。

所以,現在,當您運行應用程序並單擊"狀態"按鈕時,它會彈出一個對話框,您可以輸入更新。但是,由於我們尚未創建後端來響應此調用,因此它將失敗並且不會執行任何操作。我們將在後面的文章中談談。

更新默認表視圖控制器方法默認情況下,表視圖控制器

帶有一些方法,我們將迅速更改它們以適合我們的應用程序。

打開視圖控制器並更新方法numberOfSections。設置返回值1.這將確保顯示第一個和唯一部分。

接下來,更新tableView(tableView: UITableView, numberOfRowsInSection: section)方法並創建返回值friends.count。這將確保為friends列表中的每個條目創建適量的行。

要使單元格顯示每個朋友的詳細信息,請tableView(tableView:UITableView, cellForRowAt indexPath:IndexPath)使用以下代碼更新該方法的內容:

let cell = tableView.dequeueReusableCell(withIdentifier: "friends", for: indexPath)

var status = friends[indexPath.row]["status"]

if status == "" {

status = "User has not updated status!"

}

cell.detailTextLabel?.textColor = UIColor.gray

cell.imageView?.image = UIImage(named: "avatar.png")

cell.textLabel?.text = friends[indexPath.row]["username"]

cell.detailTextLabel?.text = status

return cell

上面的代碼只是獲取當前單元格,並用狀態,用戶名和圖像更新所需的單元格標籤(以防您想添加另一個圖像)。

最後,向視圖控制器添加一個新方法:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

return 75.0

}

這隻會將表格的行高增加到等於75.0。這將更容易適應單元格的內容。

使用Pusher為我們的iOS應用程序添加實時更新狀態

現在,在我們使用Pusher添加實時在線狀態更新之前,我們希望添加一些排序的偽朋友列表。

我們將使用Pusher來做朋友列表。我們將通過創建一個不持久的類屬性來實現這一點,並且在這個變量中,我們將存儲任何聯機的人的詳細信息。

添加一個偽朋友列表

在視圖控制器中,添加一些新的屬性:

var friends : [[String:String]] = []

var username : String = ""

var pusher : Pusher!

該friends屬性將存儲所有聯機用戶,該username屬性將為當前用戶存儲一個隨機用戶名,並且該pusher屬性將存儲Pusher庫實例。

現在,在該viewDidLoad方法中,添加以下代碼:

username = "Anonymous" + String(Int(arc4random_uniform(1000)))

listenForRealtimeEvents()

// --- Update online presence at intervals --- //

let date = Date().addingTimeInterval(0)

let timer = Timer(fireAt: date, interval: 1, target: self, selector: #selector(postOnlinePresence), userInfo: nil, repeats: true)

RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)

在第1行,我們只需將該username屬性隨機字符串作為用戶名。

在第3行,我們調用一個listenForRealtimeEvents還不存在的方法(我們稍後會創建它)。

而在第6 - 8行,我們只是基本上添加了一個循環調用postOnlinePresence(還不存在)。這個電話會每秒更新一次您的在線狀態。

listenForRealtimeEvents現在讓我們創建該方法。將下面的代碼添加到視圖控制器:

private func listenForRealtimeEvents() {

pusher = Pusher(key: "PUSHER_KEY", options: PusherClientOptions(host: .cluster("PUSHER_CLUSTER")))

let channel = pusher.subscribe("new_status")

let _ = channel.bind(eventName: "online", callback: { (data: Any?) -> Void in

if let data = data as? [String: AnyObject] {

let username = data["username"] as! String

let index = self.friends.index(where: { $0["username"] == username })

if username != self.username && index == nil {

self.friends.append(["username": username, "status": "No Status"])

self.tableView.reloadData()

}

}

})

pusher.connect()

}

在我們剛剛創建的方法中,我們使用Pusher鍵和應用程序集群實例化了Pusher庫。然後我們訂閱了一個名為new_status的Pusher頻道,並且在該頻道上,我們開始收聽名為online的事件。

在回調中,當事件監聽器被觸發時,我們從事件中獲取用戶名。然後,我們檢查在friends匹配列表中是否有用戶名。如果沒有,我們將它附加到朋友列表並重新載入表格數據。

因此,總之,每次有人上線時,都會將名稱附加到朋友列表中,並重新載入表格視圖。

接下來,我們將創建一種postOnlinePresence定期發佈當前用戶在線狀態的方法,以便其他人可以將其選中。在視圖控制器中添加下面的代碼:

public func postOnlinePresence() {

let params: Parameters = ["username": username]

Alamofire.request(FriendsViewController.API_ENDPOINT + "/online", method: .post, parameters: params).validate().responseJSON { response in

switch response.result {

case .success:

_ = "Online"

case .failure(let error):

print(error)

}

}

}

上面的代碼只是點擊一個端點,從而將用戶標記為在線。

使用Pusher嚮應用程序添加狀態更新我們iOS應用程序的最後部分將添加更新的偵聽器,以便每次有人更新其狀態時都會添加更新。

為此,打開listenForRealtimeEvents方法並在實例化推送變量後添加以下內容:

let channel = pusher.subscribe("new_status")

let _ = channel.bind(eventName: "update", callback: { (data: Any?) -> Void in

if let data = data as? [String: AnyObject] {

let username = data["username"] as! String

let status = data["status"] as! String

let index = self.friends.index(where: { $0["username"] == username })

if index != nil {

self.friends[index!]["status"] = status

self.tableView.reloadData()

}

}

})

上面的代碼為new_status通道的更新事件創建一個偵聽器。當事件被觸發時,回調會檢查用戶名是否是朋友列表的一部分。如果是,則更新該條目的狀態並重新載入表格視圖數據。

現在我們已經成功地將實時功能添加到我們的應用程序中。接下來我們要做的是創建一個後端來幫助我們實際觸發可以被我們的iOS應用程序拾取的Pusher事件。

為我們的實時iOS狀態更新應用程序創建NodeJS後端

為Web應用程序創建一個目錄,然後創建一些新文件:

**index.js**

// ------------------------------------------------------

// Import all required packages and files

// ------------------------------------------------------

let Pusher = require('pusher');

let express = require('express');

let app = express();

let bodyParser = require('body-parser')

let pusher = new Pusher(require('./config.js'));

// ------------------------------------------------------

// Set up Express middlewares

// ------------------------------------------------------

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: false }));

// ------------------------------------------------------

// Define routes and logic

// ------------------------------------------------------

app.post('/status', (req, res, next) => {

let payload = {username: req.body.username, status: req.body.status};

pusher.trigger('new_status', 'update', payload);

res.json({success: 200});

});

app.post('/online', (req, res, next) => {


let payload = {username: req.body.username};

pusher.trigger('new_status', 'online', payload);

res.json({success: 200});

});

app.get('/', (req, res) => {

res.json("It works!");

});

// ------------------------------------------------------

// Catch errors

// ------------------------------------------------------

app.use((req, res, next) => {

let err = new Error('Not Found: ');

err.status = 404;

next(err);

});

// ------------------------------------------------------

// Start application

// ------------------------------------------------------

app.listen(4000, () => console.log('App listening on port 4000!'));

在這個文件中,我們創建了一個基本的Express應用程序。該應用程序有兩個重要的端點:POST /online和POST /status。它們都會觸發Pusher事件,並且會在我們的iOS應用程序中被偵聽器拾取。

接下來創建config.js文件:

module.exports = {

appId: 'PUSHER_ID',

key: 'PUSHER_KEY',

secret: 'PUSHER_SECRET',

cluster: 'PUSHER_CLUSTER',

};

這是我們的Pusher配置文件。在這裡,用您的推子儀表板中提供的憑證替換空的字符串。

最後,創建一個package.json文件:

{

"main": "index.js",

"dependencies": {

"body-parser": "^1.16.0",

"express": "^4.14.1",

"pusher": "^1.5.1"

}

}

該文件包含Node應用程序正常運行所需的所有節點程序包。

最後,在Node應用程序的目錄中,運行下面的命令:

$ npm install && node index.js

第一個命令將安裝所有依賴項,第二個命令將在節點中啟動一個Express服務器。當您看到消息" 應用程序在4000端口監聽!" **時,您知道您的後端應用程序已準備就緒。

測試我們的實時狀態更新應用程序

一旦運行了本地節點Web服務器,您需要進行一些更改,以便您的應用程序可以與本地Web服務器通信。在該info.plist文件中,進行以下更改:

程序員的自述:如何在iOS中構建實時用戶的狀態更新

通過這一改變,您可以構建並運行您的應用程序,並且可以直接與您的本地Web應用程序通話。

程序員的自述:如何在iOS中構建實時用戶的狀態更新

總結

在文章中,我們已經能夠創建一個具有實時用戶狀態更新的iOS應用程序,類似於WhatsApp目前的應用程序。


分享到:


相關文章: