高级程序员笔记:如何在iOS中构建实时图表
如今,收集数据是理解产品如何被感知的关键之一。收集用户的一些数据可以帮助您构建更好的产品并理解用户。然而,世界上所有的数据都是没有办法可视化的。
在本文中,我们将探讨如何在iOS中创建一个简单的实时图表。该图表将实时接收数据并更新到当前登录到您应用程序的每个人的屏幕。我们将假设这是一个监视有多少访问者正在使用网站的图表。让我们开始。
对于上下文,这里是我们将要构建的示例:
小编是iOS开发人员,需要深入了解这个行业的朋友,可以关注我或私信给我 。这篇文章的源码可私信我
iOS学习交流群:638302184,群里有系统学习教程和学习路线以及详细的规划,希望帮助开发者少走弯路。
在iOS中构建实时图表的要求
在开始本教程之前,您需要先确定以下要求:
- MacBook Pro。- 安装在你的机器上。
- 和使用Xcode的基本知识。
- 基本的JavaScript知识(Node.js)。
- 您的机器上安装了Node.js和NPM。
- 您的机器上安装了Cocoapods。
当你有所有的要求,那么我们就可以开始。
准备在Xcode中创建我们的实时图表应用程序
在Mac上启动Xcode并创建一个新项目(可以随意调用它)。按照新的应用程序向导创建一个新的单页应用程序。项目创建完成后,关闭Xcode并启动终端应用程序。
在终端中,cd到应用程序目录的根目录。然后运行该命令pod init。这将生成一个Podfile。将Podfile的内容更新为以下内容(替换PROJECT_NAME为您的项目名称):
platform :ios, '9.0'
target 'PROJECT_NAME' do
use_frameworks!
pod 'Charts', '~> 3.0.2'
pod 'PusherSwift', '~> 4.1.0'
pod 'Alamofire', '~> 4.4.0'
end
保存Podfile,然后转到您的终端并运行命令:pod install。
运行此命令将安装构建实时iOS图表应用程序所需的所有第三方包。
它将安装的第一个软件包是Charts,它是用于在iOS上制作精美图表的软件包。第二个包是Pusher swift SDK。最后一个包是Alamofire,它是一个用于在iOS上发出HTTP请求的包。
安装完成后,打开**.xcworkspace**项目目录根目录下的文件。这应该启动Xcode。现在我们准备开始创建我们的iOS应用程序。
在Xcode中创建我们的实时图表应用程序视图
首先,我们将创建我们实时图表应用程序所需的必要视图。打开Main.storyboard文件,让我们开始设计我们的视图。
首先,在故事板中的视图控制器的顶部从边到边创建一个矩形视图。在该视图中,添加一个按钮并添加标题"模拟访问"。接下来,创建另一个也是矩形的视图,从上面的第一个视图的末尾到屏幕的底部。这个视图将成为我们渲染实时图的地方。
完成视图创建后,您应该看到如下图所示的内容。
就目前而言,意见无能为力。让我们将一些功能连接到iOS图表应用程序视图。
为我们的iOS图表应用程序添加基本功能
如前所述,我们的应用程序的视图和按钮没有连接到我们,ViewController所以我们来修复它。
在Xcode中,故事板仍处于打开状态,单击页面右上角的"显示助手编辑器"按钮将视图分割为故事板和代码视图。现在,单击您创建的按钮,并在按住的同时ctrl,单击并拖动链接到代码编辑器。然后创建一个@IBaction如下图所示:
当链接完成后,您应该看到类似这样的内容添加到代码编辑器中:
@IBAction func simulateButtonPressed(_ sender: Any) {
}
大!既然您已经创建了第一个链接,我们将不得不再创建一个链接到图表视图。
在故事板上,单击视图并在"身份检查"选项卡上,确保视图已连接,LineChartView如下所示。
现在视图连接到一个视图类,重复以前的操作来链接按钮,只是这一次,而不是创建一个@IBAction我们将创建一个@IBOutlet。图像如下所示:
当链接完成后,您应该看到类似这样的内容添加到代码编辑器中:
@IBOutlet weak var chartView: LineChartView!
最后,在ViewController导入图表包的顶部。您可以在下面添加右边的代码import UIKit中ViewController。
import Charts
现在我们已经将两个元素链接到我们的代码中,每次按下Simulate Visits按钮时,都会调用simulateButtonPressed函数。
为我们的iOS图表应用程序添加实时功能
拼图的最后一部分将显示图表,并在查看图表的所有设备上实时更新。
为了达到这个目标,我们将做以下工作:
创建一个函数,根据数字更新我们的图表。
让我们的请求按钮调用后端,然后将模拟数据发送到Pusher。
创建一个函数,用于侦听来自Pusher的事件,并在收到事件时触发我们之前创建的更新图表函数。
创建一个触发器函数来更新我们的图表让我们创建一个函数,根据提供给它的数字来更新我们的图表。打开它ViewController,并在其中声明类声明下的类属性。我们将使用此属性来跟踪访问者:
var visitors: [Double] = []
接下来,我们将添加将实际更新功能添加到图表视图的功能:
private func updateChart() {
var chartEntry = [ChartDataEntry]()
for i in 0..<visitors.count {
let value = ChartDataEntry(x: Double(i), y: visitors[i])
chartEntry.append(value)
}
let line = LineChartDataSet(values: chartEntry, label: "Visitor")
line.colors = [UIColor.green]
let data = LineChartData()
data.addDataSet(line)
chartView.data = data
chartView.chartDescription?.text = "Visitors Count"
}
在上面的代码中,我们声明chartEntry了我们打算存储所有图表数据的位置。然后,我们遍历可用的,visitors并为他们每个人添加一个新的ChartDataEntry(x: Double(i), y: visitors[i]),告诉图表X和Y的位置。
我们设置折线图将显示的颜色。我们创建LineChartData并添加line包含我们数据点的颜色。最后,我们将数据添加到chartView并设置图表视图描述。
让我们的模拟按钮调用一个端点
我们需要做的下一件事是让我们的请求按钮触发一个后端,后者会将模拟数据发送到Pusher。
为此,我们需要再次更新视图控制器。在ViewController图表包中正确导入Alamofire包:
import Alamofire
现在用simulateButtonPressed下面的代码替换函数:
@IBAction func simulateButtonPressed(_ sender: Any) {
Alamofire.request("http://localhost:4000/simulate", method: .post).validate().responseJSON { (response) in
switch response.result {
case .success(_):
_ = "Successful"
case .failure(let error):
print(error)
}
}
}
在下面的代码中,我们使用Alamofire发送POST请求到http:// localhost:4000 /模拟哪一个是本地Web服务器(我们将很快创建该后端)。在实际的应用程序中,这通常会指向一个真正的Web服务器。
这个端点没有使用任何参数来简化教程。我们也不需要对回应做任何事情。我们只需要在每次按下模拟访问按钮时发送POST请求。
使用Pusher绑定实时功能
为了完成所有这些工作,我们将创建一个函数来侦听来自Pusher的事件,并且当收到一个事件时,我们将该值保存visitors并然后触发我们之前创建的更新图表函数。
为此,请打开顶部的Alamofire软件包ViewController并导入PusherSwiftSDK:
import PusherSwift
接下来,我们将为Pusher实例声明一个类属性。我们可以在visitors声明行下正确执行此操作:
var pusher: Pusher!
然后声明属性后,我们需要将下面的函数添加到类中,以便它可以侦听事件:
private func listenForChartUpdates() {
pusher = Pusher(key: "PUSHER_KEY", options: PusherClientOptions(host: .cluster("PUSHER_CLUSTER")))
let channel = pusher.subscribe("visitorsCount")
channel.bind(eventName: "addNumber", callback: { (data: Any?) -> Void in
if let data = data as? [String: AnyObject] {
let count = data["count"] as! Double
self.visitors.append(count)
self.updateChart()
}
})
pusher.connect()
}
在上面的代码中,我们实例化Pusher并传入我们的密钥和集群(您可以从Pusher应用程序的仪表板获取密钥和集群)。然后,我们订阅visitorsChannel并绑定到该addNumber频道上的活动名称。
当事件被触发时,我们触发回调中的逻辑,它只是将计数附加到visitors,然后调用updateChart函数,实时更新实际图表。
最后我们调用pusher.connect()哪些形式连接到Pusher。
在viewDidLoad函数中只需添加一个调用listenForChartUpdates方法:
override func viewDidLoad() {
super.viewDidLoad()
// ...stuff
listenForChartUpdates()
}
就这样!我们在Xcode中创建了我们的应用程序,我们已准备好进行测试。然而,为了测试,我们需要创建后端,POST当点击按钮时,我们发送请求到后端。为了创建这个后端,我们将使用Node.js. 现在我们来做。
为我们的实时iOS图表应用程序创建后端服务
要开始,请为该Web应用程序创建一个目录,然后在该目录内创建一些新文件:
文件:index.js
// -------------------------------------------------------
// Require Node dependencies
// -------------------------------------------------------
let Pusher = require('pusher');
let express = require('express');
let bodyParser = require('body-parser');
let app = express();
// Instantiate Pusher
let pusher = new Pusher(require('./config.js'));
// -------------------------------------------------------
// Load express middlewares
// -------------------------------------------------------
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// -------------------------------------------------------
// Simulate multiple changes to the visitor count value,
// this way the chart will always update with different
// values.
// -------------------------------------------------------
app.post('/simulate', (req, res, next) => {
var loopCount = 0;
let sendToPusher = setInterval(function(){
let count = Math.floor((Math.random() * (100 - 1)) + 1)
pusher.trigger('visitorsCount', 'addNumber', {count:count})
loopCount++;
if (loopCount === 20) {
clearInterval(sendToPusher);
}
}, 2000);
res.json({success: 200})
})
// Handle index
app.get('/', (req, res) => {
res.json("It works!");
});
// Handle 404's
app.use((req, res, next) => {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// -------------------------------------------------------
// Serve application
// -------------------------------------------------------
app.listen(4000, function(){
console.log('App listening on port 4000!')
});
上面的文件是一个用JavaScript编写的简单的Express应用程序。我们实例化所有我们需要的包,并使用我们即将创建的配置文件来配置推送器。然后我们创建一条路线,/simulate并在此路线中触发频道中的addNumber事件visitorCount。这是应用程序正在侦听的同一频道和事件。
为了使它更简单一些,我们使用setInterval每2000毫秒向Pusher后端发送随机访问者数量。循环20次后,循环停止。这应该足以测试我们的应用程序。
创建下一个文件config.js:
module.exports = {
appId: 'PUSHER_APP_ID',
key: 'PUSHER_APP_KEY',
secret: 'PUSHER_APP_SECRET',
cluster: 'PUSHER_APP_CLUSTER',
};
用PUSHER_APP_*您自己的Pusher应用程序中的凭证替换密钥。
下一个也是最后一个文件是package.json:
{
"main": "index.js",
"dependencies": {
"body-parser": "^1.16.0",
"express": "^4.14.1",
"pusher": "^1.5.1"
}
}
在这个文件中我们只是声明依赖关系。
现在打开终端并连接cd到Web应用程序目录的根目录并运行以下命令以分别安装NPM依赖项和运行应用程序:
$ npm install
$ node index.js
安装完成并且应用程序准备就绪后,您应该看到以下输出:
测试应用程序
一旦运行了本地节点Web服务器,您需要进行一些更改,以便您的应用程序可以与本地Web服务器通信。在该info.plist文件中,进行以下更改:
通过这一改变,您可以构建并运行您的应用程序,并且可以直接与您的本地Web应用程序通话。
结论
本文向您展示了如何结合Pusher和Charts包创建实时iOS图表应用程序。还有许多其他图表类型可以使用该包创建,但为简洁起见,我们已经完成了最简单的操作。您可以浏览其他图表类型,甚至可以为每个请求传递多个数据点。
如果您有任何问题,反馈或更正,可以将它们发布在下面的评论部分。
上面的分享的源代码需要的朋友可私信我“源码”领取。