如何解决IBM ibmbluemixx启动应用时崩奈侍

3470人阅读
云服务器(1)
活动(12)
Bluemix(15)
概述 通过本文学习,你将能够在IBM的云平台Bluemix上创建自己的PHP Web 应用程序,添加并使用语言翻译服务,发布自己的PHP应用到云服务器上。 本地开发测试环境:Windows 7 x64,PHP,Nginx 有关本地分环境的搭建,请参考:Bluemix&是什么?IBM&Bluemix&是开放式标准云平台,用于构建、运行和管理应用程序。使用&Bluemix,开发者可以集中通过灵活的计算选项、DevOps&工具的选择以及一组强大的&IBM&及第三方&API&和服务来构建卓越的用户体验。注册Bluemix云服务器,登陆Bluemix平台,进行部署/开发,创建 Web 应用程序 通过 IBM& Bluemix(TM),可以在 Bluemix 用户界面中创建应用程序。创建应用程序后,可以决定是继续使用 UI,使用 cf 命令行界面,还是使用 IBM Bluemix DevOps Services 来开发、跟踪、规划和部署应用程序。在 Bluemix 中创建应用程序时,首先是创建入门模板。入门模板是一种模板,包含预定义的服务和使用特定 buildpack 配置的应用程序代码。入门模板有两种类型:样板和运行时。样板是一种容器,用于应用程序及其关联的运行时环境,以及针对特定域的预定义服务。例如,“移动云”样板包含 Node.js 运行时,以及 Mobile Data、Mobile Application Security 和 Push 服务。样板还包含 SDK 和样本应用程序,方便着手开发用于访问这些服务的移动应用程序。运行时是用于运行应用程序的一组资源。Bluemix 提供运行时环境来作为不同类型应用程序的容器。运行时环境作为 buildpack 集成到 Bluemix 中,并自动配置以供使用,只需很少维护,甚至完全无需维护。要开始创建应用程序,请执行以下步骤:1、在&Bluemix&用户界面中,转至“仪表板”。2、单击创建应用程序。3、单击&Web,然后按照指导经验来选择入门模板,指定名称以及选择编码方式。输入应用程序名称应用程序名称是唯一的,接下来要通过它做为二级域名来访问你的应用!点击完成之后,需要等待一会儿,然后可以看到下图的界面这时就可以访问你刚刚创建的应用了。如下图:4、按照指导经验完成操作后,单击查看应用程序概述。“仪表板”上将显示应用程序的“概述”。通过文件和日志,可以查看默认页面的源代码:通过仪表板页面的应用程序,可以找到自己已经创建的应用程序;5、可以通过单击&Bluemix&用户界面中应用程序“概述”上的添加服务或 API,将服务添加到应用程序中。也可以使用 cf 命令行界面。请参阅。6、在应用程序“概述”上,单击添加 Git&可将应用程序源代码保存到 Git 存储库中,并创建 Git 托管的项目。您还可以从&&部署应用程序。本文不使用Git,而是使用CF(Cloud Foundry)上传应用程序! 注:&如果绑定到应用程序的服务崩溃,那么该应用程序可能会停止运行或发生错误。Bluemix&不会自动重新启动应用程序以从这些问题中恢复。请考虑对应用程序进行编码,以便识别中断、异常和连接失败状况并从中进行恢复。请参阅故障诊断主题,以获取更多信息。开发基于服务的应用 1、获取服务信息 进入自己的应用程序》概述页面,找到已经添加的服务,点击“显示凭证”,可以查看服务的具体信息:
在浏览器中访问服务URL
在浏览器请求支持的语言: 服务URL:https://gateway.watsonplatform.net/language-translation/api/v2/identifiable_languages
2、编写PHP代码AJAX调用代码//通过AJAX调用后台翻译程序
function doExecTrans(){
var txt = $(&#InputText&).val();
if (txt == &&){
alert(&请输入要翻译的文本!&);
$(&#ProgressDiv&).show();
type: &GET&,
url: &trans.php&,
dataType:&json&,
data: {&txt&:txt},
success: function(data){
$(&#ProgressDiv&).hide();
console.log(data);
if (data.error){
alert(data.error);
$(&#OutputText&).text(data.text);
error: function(data){
console.log(data);ssss
alert( &Error Msg: & + data );
$(&#ProgressDiv&).hide();
}PHP代码// powered by: testcs_dn
// Blog: http://blog.csdn.net/testcs_dn
// Create time:
//获取get请求携带的参数
function get($paramName){
if(is_array($_GET)&&count($_GET)&0)//判断是否有Get参数
if(isset($_GET[$paramName]))//判断所需要的参数是否存在,isset用来检测变量是否设置,返回true or false
return $_GET[$paramName];//存在
return &&;
//要翻译的文本
$txt=get(&txt&);
if ($txt == &&){
exit('{&error&:&请输入要翻译的文本!&}');
$url = &https://gateway.watsonplatform.net/language-translation/api/v2/translate?source=en&target=es&text=&.$
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//https请求必须设置以下两项
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
//设置凭证
curl_setopt($ch, CURLOPT_USERPWD, '您的用户名:您的密码');
//执行请求
$output = curl_exec($ch);
if($output === false)
echo curl_error($ch);
//echo '操作完成没有任何错误&br /&';
//打印获得的数据
echo '{&text&:&'.$output.'&}';
//var_dump($output);
//var_dump($ch);
//$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
//var_dump(curl_getinfo($ch));
// Close handle
curl_close($ch);上传应用程序登录到&Bluemix(TM)&后,可以使用&cf push&命令来上传应用程序。开始之前,您必须:1、安装 Cloud Foundry 命令行界面。请根据自己使用的操作系统下载对应的版本;我使用的是Windows 7 64位操作系统,下载Binaries版本的不需要安装,直接解压到Windows目录就可以了。以下执行的命令你可以通过访问&https://www.ng.bluemix.net/docs/#starters/upload_app.html#upload_app__push查看属于自己的命令;2、连接到&Bluemix。打开命令提示符窗口:开始》运行,输入“cmd”,回车执行:cf api https://api.ng.bluemix.net,如下图:3、登录到&Bluemix。注意,这里要换成对应你自己账户的命令!cf login -u
-s ivu4e 4、发出&cf push&命令时,cf&命令行界面将提供使用 buildpack 来构建并运行应用程序的&Bluemix&环境的工作目录。从应用程序目录中,输入带有应用程序名称的&cf push&命令。在&Bluemix&环境中,应用程序名称必须是唯一的。后面的&-m 512m&是修改应用程序内存配额的,可以不带这个参数,如下图:提示:&使用&cf push&命令时,cf&命令行界面会将当前目录中的所有文件和目录复制到&Bluemix。确保应用程序目录中只包含必需的文件。例如我的目录,下面只有一个:test.php,这是测试是使用的文件,后续应用相关文件有所改变。执行“cf push”命令成功之后,我们再到文件和日志中看一看我们上传的文件:OK,我们访问一下,看看效果吧:http://php2info.mybluemix.net/test.phpcf push appname -m 512mBluemix&包含内置 buildpack。在某些情况下,即便对于内置 buildpack,也必须提供&-c&选项来指定用于启动应用程序的命令。例如,需要使用&-c&选项来推送 Node.js 应用程序:cf push appname -c start_command此外,Node.js 应用程序还必须包含有效的&package.json&文件。所有其他外部 buildpack 都必须使用&-b&选项来推送。例如:cf push appname -b buildpack_URLcf push&命令上传应用程序并将其部署到&Bluemix。有关&cf push&的更多信息,请参阅&。有关 buildpack 的信息,请参阅。如果更改了应用程序,可以通过再次输入&cf push&命令来上传这些更改。&cf&命令行界面会使用您先前的选项以及您对提示的响应来通过新的代码段更新应用程序的任何运行中实例。提示:&您还可以从&Bluemix DevOps Services&上传或部署应用程序。请参阅。应用上线效果点击效果图片链接可以直接在线访问,由于目前服务器还在国外,打开速度有点慢;http://php2info.mybluemix.net/使用体验创建、部署和维护 Web 应用程序都很简单,让开发人员可以更专注于应用的开发。文档比较全面,不过感觉有些地方说的不够细,比如语言翻译服务我就没有找到如何翻译一句话或一篇文章的方法,每次只能翻译一个单词!由于目前服务器还在国外,打开速度有点慢;希望能早日进驻国内。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4969867次
积分:45452
积分:45452
排名:第55名
原创:664篇
转载:191篇
译文:21篇
评论:1164条
文章:129篇
阅读:1286479
文章:33篇
阅读:157422
文章:16篇
阅读:109469
阅读:8508
文章:29篇
阅读:261433
文章:18篇
阅读:214303
文章:44篇
阅读:286448
(15)(20)(17)(4)(16)(12)(17)(25)(34)(19)(15)(17)(15)(23)(12)(12)(14)(13)(14)(20)(58)(25)(31)(16)(33)(31)(20)(24)(23)(21)(20)(14)(36)(14)(14)(7)(6)(15)(3)(2)(9)(6)(7)(32)(3)(8)(7)(22)(2)(30)(4)developerWorks 社区
Array Software 创始人/CEO
作为一个没有时间观看太多比赛的热心的足球迷,我想获得一种了解最新比分的直观方式。大多数相关的应用程序似乎都很臃肿和平淡无奇,所以我决定自己构建一个。在本教程中,我将介绍我如何构建 “Occer” 应用程序并将它部署在 IBM 的 Bluemix 平台上。后端 API 层是使用 Ruby、Sinatra 和 MongoDB 构建的。它使用免费的 football-data.co.uk 数据提要来获取最新结果。该应用程序本身是一个使用 Swift 编写的 iOS 应用程序,使用了 IBM Bluemix Mobile SDK 来处理推送通知。“本教程将介绍如何构建一个 iOS 应用程序来获取英格兰足球超级联赛的最新足球比分,并在有新比分时发送推送通知。”构建您的应用程序需要做的准备工作&在本地安装 Ruby、RubyGems 和 Bundler在本地安装 MongoDB 和一个
帐户一个物理 iOS 设备,用于测试推送通知一个
帐户您可以从 IBM DevOps Services 的 “moccer” 项目中获取下面的说明中提及的代码。第 1 步. 构建后端 API&构建此应用程序的第一步是创建一个后端,该后端将执行以下操作:从 football-data.co.uk 抓取并解析最新信息提要如果有新结果,则更新 MongoDB 数据库提供 API 端点来查找更新和获取给定日期的比分创建一个新 Sinatra 应用程序&我们首先会创建一个基本的 Sinatra 应用程序。为您的项目创建一个目录,向其中添加一个名为 Gemfile 的新文件。将以下代码添加到此文件中。
source 'https://rubygems.org'
gem 'mongo'
gem 'bson'
gem 'bson_ext'
gem 'sinatra'
gem 'thin'在命令提示符下,导航到您的项目目录,运行以下代码来安装依赖项。
$ bundle install创建一个名为 app.rb 的文件并向其中添加以下代码。
require 'sinatra'
get '/' do
'Hello, world!'
end此代码定义一个非常基本的 “Hello, World” Sinatra 应用程序,该应用程序在用户导航到它的根目录时显示此消息。在运行该应用程序之前,创建另一个名为 config.ru 的新文件,并添加以下代码。
require './app'
run Sinatra::Application要启动该应用程序,请在提示符下输入以下命令:
$ rackup -p 4567您现在应该能够打开您选择的 Web 浏览器,访问 http://localhost:4567 并看到显示了熟悉的 “Hello, World!” 消息。抓取比分数据并将该数据存储在 MongoDB 中&我们将整个 app.rb 文件替换为将从 football-data.co.uk 文件抓取数据,并将这些数据存储在 MongoDB 数据库中的代码。确保您有一个本地 MongoDB 数据库正在运行,否则该应用程序不会启动。要进行核实,可以在命令行上运行 mongo。如果看到一条类似 “connect failed” 的消息,则表明 MongoDB 未在本地运行。您需要做的第一件事是加载一些 Ruby gem,它们会帮助您抓取数据,解析 CSV 内容并将其存储在数据库中。确保您已完全删除 app.rb 文件中的所有代码,并将其替换为以下代码。
require 'net/http'
require 'uri'
require 'csv'
require 'mongo'
require 'sinatra'
require 'json'
include Mongo接下来,添加两个配置代码块。第一个代码块仅在开发环境中运行(您将在生产环境中连接到一个 Bluemix 托管的 MongoDB 数据库)。第二个代码块将在任何环境中运行。
configure :development do
host = 'localhost'
port = MongoClient::DEFAULT_PORT
client = MongoClient.new(host, port)
db = client.db('occer-data')
set :coll, db.collection('scores') || db.create_collection('scores')
configure do
set :csvUrl, "http://www.football-data.co.uk/mmz/E0.csv"
CSV::Converters[:date_to_iso] = lambda do |s|
Date.strptime(s, '%d/%m/%y').strftime('%Y-%m-%d')
end在第一个代码块中,您定义了 MongoDB 连接参数、数据库名称和集合(或者如果该集合还不存在,则创建它)。在第二个代码块中,将会定义用于查找足球比赛结果的 URL。请注意,1415 表示足球赛季 。要抓取另一个赛季的数据,可将 1415 替换为相关的值。您还需要定义一个 CSV 转换器,它将获取日期并将该日期格式化为 ISO 数据标准 (YYYY-MM-DD)。定义一个基本的 API 端点,它将抓取该 CSV 文件的最新版本,检查其中是否包含新记录,以及更新 MongoDB 数据库中的数据。将此代码添加到紧挨前一个清单的代码后面。
get '/update' do
count = settings.coll.find.count
uri = URI.parse(settings.csvUrl)
response = Net::HTTP.get_response uri
csv = CSV.new(response.body, { :headers =& :first_row, :header_converters =& :symbol,
:converters =& [:all, :date_to_iso] })
keep = [ :date, :hometeam, :awayteam, :fthg, :ftag, :ftr, :hthg, :htag, :htr, :referee ]
data = csv.to_a.map { |row| row.to_hash.select { |k, v| keep.include?(k) } }
data.delete_if { |v| v[:ftr] == nil }
records = data.length - count
if records & 0
# Push notification!
settings.coll.remove
settings.coll.insert(data)
{ :success =& true, :records =& records }.to_json
end此代码将获取数据库中比分统计,抓取最新的数据,并进行比较,以查看是否有新比分。我们放置了一个占位符来发送推送通知。稍后将返回这里。为了简便起见,我们删除了数据库中的所有记录,将它们替换为来自 CSV 文件的最新数据。实际上,您可能希望使用增量更新。此刻,您可以启动该应用程序,查看您导航到此 API 端点时发生了什么。为此,首先按下 Ctrl + C 重新启动 Rack 服务器并再次发出以下命令:
$ rackup -p 4567在您浏览器中导航到 http://localhost:4567/update。您会看到一个类似这样的响应:
{"success":true,"records":110}请注意,找到的记录数量取决于您阅读本教程的时间,所以绝不应该是 110。&该 iOS 应用程序的第一个视图是一个比赛日期列表,允许用户下钻到某个比赛日期来查看那天举行的比赛的比分。为了实现此目的,我们需要提供一个返回比赛日期列表的 API。 将以下代码添加到 app.rb 文件中。
get '/dates' do
dates = settings.coll.distinct('date').to_a.sort! { |x, y| y &=& x }
dates.to_json
end此代码从 Mongo 集合获取不同日期的列表,将它们存储在一个数组中,然后按逆序排序该数组,并以 JSON 格式返回它。如果重新加载 Rack 服务器并导航到 http://localhost:4567/dates,您会看到与以下内容类似的输出:
["","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]同样地,请记住您可能会看到比我多得多的日期,因为到您阅读本文时举行了更多比赛。&最后的 API 端点将抓取一个给定比赛日期的比分数组。它接受一个查询参数,该参数告诉该 API 要查找的日期。如果未提供任何参数,则会获取并使用最大的比赛日期。 将以下代码附加到 app.rb 文件中并保存。
get '/' do
date_str = params[:date]
date = Date.strptime(date_str, '%Y-%m-%d') rescue nil
if date.nil?
maxdate = settings.coll.find({}, :fields =& ["date"], :limit =& 1, :sort =& ['date','desc']).to_a
date_str = maxdate.length & 0 ? maxdate[0]["date"] : ''
date = Date.strptime(date_str, '%Y-%m-%d') rescue nil
unless date.nil?
# Get scores that match the given date
scores = settings.coll.find({"date" =& date_str}).to_a
scores.to_json
[].to_json
end此 API 在 URI 中寻找一个日期查询参数。如果它未找到,则使用限制和排序指令个从数据库获取最新的比赛日期。它然后在 Mongo 集合中查找所有与给定日期匹配的比分,并以 JSON 格式返回。同样地,重新启动服务器进程,这次导航到 http://localhost:4567/。您会看到与下面类似的内容:
[{"_id":{"$oid": "5464efb0f10cf604dd0000d9"},"date":"","hometeam":"Sunderland","awayteam":"Everton","fthg":1,"ftag":1,"ftr":"D","hthg":0,"htag":0,"htr":"D","referee":"L Mason"},{"_id":{"$oid": "5464efb0f10cf604dd0000da"},"date":"","hometeam":"Swansea","awayteam":"Arsenal","fthg":2,"ftag":1,"ftr":"H","hthg":0,"htag":0,"htr":"D","referee":"P Dowd"},{"_id":{"$oid": "5464efb0f10cf604dd0000db"},"date":"","hometeam":"Tottenham","awayteam":"Stoke","fthg":1,"ftag":2,"ftr":"A","hthg":0,"htag":2,"htr":"A","referee":"M Jones"},{"_id":{"$oid": "5464efb0f10cf604dd0000dc"},"date":"","hometeam":"West Brom","awayteam":"Newcastle","fthg":0,"ftag":2,"ftr":"A","hthg":0,"htag":1,"htr":"A","referee":"C Pawson"}]请记住,您看到的数据可能会有所不同,但键值应该是类似的。后端现在已完成。现在,让我们将后端部署到 Bluemix。第 2 步. 将后端部署到 Bluemix&要将应用程序推送到 Bluemix,首先需要向项目目录添加一个 manifest.yml 文件,告诉 Bluuemix 您想要部署的应用程序的一些信息。创建此文件并向其添加以下内容。
applications:
- name: occer
host: occer
disk: 1024M
domain: mybluemix.net
instances: 1备注:您需要将名称和主机值更改为您应用程序独有的值。创建清单文件后,现在可以将应用程序推送到 Bluemix 了。在命令提示符下,运行以下命令,使用 cf 实用程序登录到 Bluemix 并将您的代码推送到云。如果尚未安装 cf 实用程序,请 。运行 cf login 命令后,在提示时,需要输入您的 Bluemix 帐户电子邮件地址和密码。
$ cf api https://api.ng.bluemix.net
$ cf login
$ cf push当您首先推送应用程序时,它不会实际运行,因为不存在 MongoDB 生产配置,所以将出现一些错误。要更正此错误,您需要配置一个新的 MongoDB 服务实例,并将它绑定到应用程序。再次声明,记住将这里的名称更改为惟一的值,否则应用程序无法运行。对 occer 的引用是您在 manifest.yml 文件中创建的应用程序名称。
$ cf create-service mongodb 100 occer-db
$ cf bind-service occer occer-db打开 app.rb 文件,将以下配置代码块添加到您早先创建的开发配置代码块上方。
configure :production do
# Get the credentials for the MongoDB Bluemix service
env = JSON.parse(ENV["VCAP_SERVICES"])["mongodb-2.4"].first["credentials"]
# Connect to MongoDB and authenticate using environment variables
conn = MongoClient.new(env["hostname"], env["port"])
db = conn.db(env["db"])
db.authenticate(env["username"], env["password"])
# Store the DB connection in a setting for easy retrieval later
set :coll, db.collection('scores') || db.create_collection('scores')
end您现在已准备好将该应用程序推送到 Bluemix。
$ cf push导航到您的应用程序 URL,确认您的应用程序在运行,该 URL 应该类似于 http://occer.mybluemix.net。导航到更新 API 端点地址 http://occer.mybluemix.net/update,确保该应用程序已抓取最新结果。您会看到一个与以下内容类似的结果:
{"success":true,"records":110}根据您阅读本教程的时间,您获得的数量可能与 110 不同。请注意,如果您已经填充了该数据库,就会看到一个记录数量 0。这是因为未找到新记录。接下来,您将构建前端 iOS 应用程序来显示这些比分。第 3 步. 创建 iOS 应用程序&启动 Xcode 并创建一个新的大纲-细节 iOS 应用程序项目。将它命名为 Occer,将 Organization Name 和 Bundler Identifier 设置为 Demo。将 Language 设置为 Swift,将 Devices 设置为 iPhone。保留 Use Core Data 未选择并按下 Next。选择一个位置来存储您的项目,然后将创建该项目。设计用户界面&在项目导航器面板中,单击 Main.storyboard 文件。这将打开一个设计视图,其中显示了 3 个屏幕:导航控制器、大纲视图和细节视图。双击大纲视图中的标题栏编辑它,将标题更改为 Occer 2014/15。大纲视图将显示一个比赛日期列表,点击一个日期将显示那天的比分列表。要实现此目的,您需要在细节视图和大纲视图中提供一个表格视图。单击 Detail View content goes here 并按下键盘上的 Backspace 键删除该消息。单击细节视图中较大的白色区域来选中它,按下 Backspace 删除该白色区域。删除它后,您会看到灰色的文本 Detail View Controller。从对象库(通常在底部右侧,第三个图标)中找到一个 Table View 对象(不是 表格视图控制器),并将它拖到细节视图中。将一个 Table View Cell 对象拖到表格视图中。细节视图现在将类似于大纲视图。选择您刚添加的 Table View Cell 对象。在 Attributes Inspector 中,将 Style 更改为 Basic。在标识符字段中输入 Cell。表格视图单元格中将显示一个标签。单击该标签以选择它。在 Attributes Inspector 中,单击中间的按钮将文本居中。完成这些操作后,故事板应该类似于:UI 工作现在已完成,您已准备好将应用程序连接到后端。构建类来处理后端 API&创建两个将连接到 Ruby API 的新类。在 project navigator 中,右键单击 Occer 文件夹并选择 New File。从打开的菜单中,选择 Swift File 并按下 Next。将该文件命名为 DateAPIController。将在 Xcode 编辑器中打开一个空 Swift 文件。将内容替换为以下代码。 import Foundation
protocol DateAPIControllerProtocol {
func didReceiveDates(dates: NSArray)
class DateAPIController {
var delegate: DateAPIControllerProtocol?
func getDates() {
let urlPath = "http://occer.mybluemix.net/dates"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response,
error -& Void in
if(error != nil) {
println(error.localizedDescription)
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil,
error: &err) as NSArray
self.delegate?.didReceiveDates(jsonResult)
if(error != nil) {
println("JSON Error \(err!.localizedDescription)")
task.resume()
}此代码定义了一个协议,允许我们将特定于视图的函数放在该类外,在从服务器收到响应时使用委托来更新 UI。getDates() 方法在 Bluemix 上查找该 API 并以 JSON 格式抓取数据,然后再在协议中调用委托函数 didReceiveDates()。备注:一定要将 urlPath 常量更改为您自己的 Bluemix 托管的 Ruby 应用程序的 URL。以相同的方式创建另一个新的 Swift 文件,但这一次将它命名为 ScoreAPIController。此文件的代码非常相似,但它会查找比分 API。将此文件的内容替换为以下代码。 import Foundation
protocol ScoreAPIControllerProtocol {
func didReceiveScores(scores: NSArray)
class ScoreAPIController {
var delegate: ScoreAPIControllerProtocol?
func getScores(date: NSString) {
let urlPath = "http://occer.mybluemix.net/?date=\(date)"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response,
error -& Void in
if(error != nil) {
println(error.localizedDescription)
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: nil,
error: &err) as NSArray
self.delegate?.didReceiveScores(jsonResult)
if(error != nil) {
println("JSON Error \(err!.localizedDescription)")
task.resume()
}此文件与 DateAPIController 文件的主要区别在于,getScores() 方法接受一个日期字符串作为参数,而且这个字符串会作为查询字符串参数附加到 API URL。除此之外,它们的工作原理完全相同。再次声明,确保将 urlPath 常量更改为您自己的 Bluemix 托管的 API 应用程序的实际 URL。&要让所有功能正常运行,需要将 API 类连接到视图控制器。 在项目导航器面板中,单击 MasterViewController.swift 显示此文件的代码。您现在将对此文件进行一些更改,以便将它连接到 DatesAPIController。找到下面这行,该行定义了 MasterViewController 类:
class MasterViewController: UITableViewController {将此行更改为以下代码,以便让它实现 DateAPIControllerProtocol 协议:
class MasterViewController: UITableViewController, DateAPIControllerProtocol {将把对象定义为 NSMutableArray 的行替换为以下代码:
var objects = NSArray()
var api = DateAPIController()您不需要在对象数组中添加或删除内容,所以应将它定义为一个常规 NSArray,而不是一个 NSMutableArray。还要初始化 DateAPIController 类。将 viewDidLoad() 方法更改为以下形式:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
refreshControl = UIRefreshControl()
refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubview(refreshControl!)
}这会向表格视图添加一个 pull-to-refresh 控件子视图。执行此操作时,会调用 refresh() 方法。 在 viewDidLoad() 方法下,添加以下代码:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.refresh(self)
func refresh(sender: AnyObject) {
self.api.delegate = self
self.api.getDates()
func didReceiveDates(dates: NSArray) {
dispatch_async(dispatch_get_main_queue(), {
self.objects = dates
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}只要出现该表格视图,viewWillAppear() 方法就会刷新该表格。视图出现时或使用表格的 pull-to-refresh 控件时,将调用 refresh() 方法。最后,didReceiveDates() 方法是早先定义的 DateAPIControllerProtocol 的实现。它将对象数组设置为 API 调用的结果,重新加载表格视图数据,并告诉 pull-to-refresh 控件停止刷新。完全删除 insertNewObject() 方法。此应用程序不需要它。在 prepareForSegue() 方法中,找到下面这行:
let object = objects[indexPath.row] as NSDate将此行更改为以下代码:
let object = objects[indexPath.row] as NSString保留接下来几个方法不变,找到下面这个方法定义:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -& UITableViewCell {在此定义内,找到下面这行:
let object = objects[indexPath.row] as NSDate将此行更改为以下代码:
let object = objects[indexPath.row] as NSString删除最后两个方法,因为不需要使用它们:canEditRowAtIndexPath 和 commitEditingStyle 表格视图方法。保存文件。接下来,您将连接 DetailViewController。将比分 API 连接到细节视图控制器&您需要向 DetailViewController 添加一点代码,因为目前尚未包含所需的表格视图方法。首先,找到这个类定义:
class DetailViewController: UIViewController {更改此定义,使该类实现 ScoreAPIControllerProtocol 协议:
class DetailViewController: UITableViewController, ScoreAPIControllerProtocol {删除下面这行:
@IBOutlet weak var detailDescriptionLabel: UILabel!将它替换为以下代码:
var objects = NSArray()
var api = ScoreAPIController()更改 detailItem 的定义,使它成为 NSString? 类型,而不是 AnyObject? 类型:
var detailItem: NSString? {
// Update the view
self.configureView()
}将 configureView() 方法内容替换为对一个名为 refresh 的新方法的调用,我们稍后将创建该方法。
func configureView() {
self.refresh(self)
}在 viewDidLoad() 方法中,将 self.configure() 行替换为以下代码,以实现 pull-to-refresh:
refreshControl = UIRefreshControl()
refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubview(refreshControl!)在此方法下,添加以下代码:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.refresh(self)
func refresh(sender: AnyObject) {
if let detail:NSString = self.detailItem {
self.title = detail
self.api.delegate = self
self.api.getScores(detail)
func didReceiveScores(scores: NSArray) {
dispatch_async(dispatch_get_main_queue(), {
self.objects = scores
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}保留 didReceiveMemoryWarning() 方法不变,添加以下 3 个方法来完成该类:
// MARK: - Table View
override func numberOfSectionsInTableView(tableView: UITableView) -& Int {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -& Int {
return objects.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -& UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
as UITableViewCell
let object = objects[indexPath.row] as NSDictionary
let homeTeam = object["hometeam"] as NSString
let awayTeam = object["awayteam"] as NSString
let homeScore = object["fthg"] as NSInteger
let awayScore = object["ftag"] as NSInteger
cell.textLabel.text = "\(homeTeam) \(homeScore) - \(awayScore) \(awayTeam)"
return cell
}在 iOS 模拟器中运行该应用程序&在工具栏中按下 Play 按钮,在 iOS 模拟器中构建并启动该应用程序。除非构建失败,否则您会在 iOS 模拟器中看到一个类似下图的屏幕。 点击一个日期,您会看到一个类似下图的屏幕:提示:如果应用程序成功构建但在启动时崩溃了,应用程序可能无法连接到 Bluemix API。确保您在 API 地址中拥有正确的 URL,而且拥有互联网连接。在真实设备上运行应用程序&要让应用程序在真实设备上运行,需要执行一些步骤,尤其在您想让推送通知在下一节中生效的时候。在 Project Properties 中打开 Background Modes 功能。选择 Remote notifications 选项。 要在物理设备上运行该应用程序,需要安装一个配置概要文件。如果还没有这个概要文件,Xcode 会自动为您设置一个。不幸的是,这将使用一个通配符 App ID,这个 ID 无法用于拥有推送通知功能的应用程序。因此,您需要为您的应用程序设置一个显式的 App ID。为此,导航到
并登录到 Member Center。单击 Certificates, Identifiers & Profiles 链接。单击 Identifiers 并选择右侧的 App ID,然后按加号按钮来创建一个新 App ID。为应用程序输入一段描述(比如 Occer App ID),并确保选择了 Explicit App ID。Bundle ID 值应该与您应用程序的 Bundle Identifier 匹配,该标识符可在 Project Properties 中的 General 表格中找到(如果已按照早先的指南进行操作,该值应该类似于 Demo.Occer)。在 App Services 列表中,确保选择了 Push Notifications 并按下 Continue。再次检查选择并按下 Continue 来创建 App ID。您现在需要为该 App ID 启用推送通知,生成一个可供 Push Notification 服务使用的客户端 SSL 证书。在 App IDs 中,选择您刚创建的 App ID。请注意,在 Application Services 中,Push Notifications 选项拥有值 Configurable。按下 Edit 按钮。在 Push Notifications 下,请注意您可以选择为开发和生产环境创建 SSL 证书。按下 “Development SSL Certificate” 下的 Create Certificate 按钮。按照显示的如何创建证书签名请求 (CSR) 的说明操作。单击 Continue。选择您创建的 CSR 文件并上传它。单击 Generate 生成您的证书。将 .cer 文件下载到您的计算机,打开它,以便将它添加到您的 Keychain 中。在以后使用 Bluemix Push 时,需要上传一个 P12 密钥文件。让我们现在就生成一个密钥文件。从 “My Certificates” 类别中选择 Apple Development IOS Push Services certificate 并展开它,以便显示私钥。同时选择证书和私钥,转到 File & Export Items。确保已选中 Personal Information Exchange (.p12) 文件格式,单击 Save 将证书导出到您的计算机。系统会要求您输入密码并进行确认。在将此文件上传到 IBM Bluemix 时,需要使用此密码,所以不要忘记它。系统会提示您输入您的登录密钥链密码,然后会创建您的 P12 文件。接下来,需要创建一个新的配置概要文件。从 Apple Developer Center 中的左侧菜单,选择 “Provisioning Profiles” 下的 Development。然后单击加号按钮添加一个新的概要文件。在第一个屏幕上,选择 iOS App Development 并按下 Continue。确保已选择您刚创建的 App ID,再次按下 Continue。选择该应用程序用于签名的证书(Xcode 应已为您创建此证书。如果尚未创建该证书,可以尝试在物理 iOS 设备上运行您的应用程序。)接下来,选择要包含在配置概要文件中的设备。最后,为该配置概要文件提供一个名称并单击 Generate。下载该配置概要文件并在 Finder 中打开它。安装配置概要文件后,确保使用了正确的配置概要文件来对您的应用程序签名。在 Xcode 中,转到 Project Properties 页面并导航到 Build Settings 选项卡。确保显示了所有 部分。找到 “Code Signing” 部分,查找 Provisioning Profile 选项。从此列表中选择您刚刚创建的概要文件。您现在应该能够在实际设备上运行该应用程序,而且应该将它配置为接收推送通知,我们将在下一节介绍推送通知。下图显示该应用程序正在 iPhone 6 Plus 上运行。这可能看起来类似于图 2,但请注意运营商名称是真实的运营商,而且显示了网络信号。 现在我们向应用程序添加推送通知功能,完成该应用程序。第 4 步. 实现推送通知&登录到 IBM Bluemix 仪表板 ()。导航到您的应用程序并单击 Add a Service。要添加推送服务,还需要添加 Mobile Application Security 服务,所以首先应该添加该服务。为该服务提供一个名称,比如 occer-mas(应该是惟一名称),然后创建它。在系统要求您重新启动应用程序时按下 Cancel。再次单击 Add a Service,这一次从 Mobile 类别中选择推送服务。为该服务提供一个名称,比如 occer-push。在系统要求您重新启动应用程序时,按下 OK。在 Bluemix 中配置推送服务&单击您创建的 occer-push 服务,并在 Configuration 选项卡中,单击 Apple Push Notification Service (APNS) 下的 Edit。在 Sandbox Configuration 部分,选择您早先在 Keychain Access 中创建的 P12 证书文件,输入您选择的密码。单击 Save。APNS 配置将经过验证。这需要一段时间,完成后您会看到一条绿色的确认消息。 接下来,向 iOS 应用程序添加一些代码,以便允许它接收推送通知。此代码要求用户接受或拒绝接收来自应用程序的推送通知。为此,您需要下载 Bluemix iOS SDK ()。解压该 zip 文件,复制 IBMBluemix.framework 和 IBMPush.framework 文件夹,然后使用 File & Add Files to Occer 导入到您的 Xcode 项目中。确保 Copy items if needed 已被选中。Bluemix SDK 是使用 Objective-C 编写的,所以开始在 Swift 代码中使用它之前,您需要做一些准备工作。向您的项目添加一个新文件。从模板对话框中选择 Header File,并将该文件命名为 Occer-Header-Bridge.h。删除该文件的内容,将其替换为以下代码。
#import &IBMBluemix/IBMBluemix.h&
#import &IBMPush/IBMPush.h&现在告诉项目查找此文件作为 Objective-C 桥的头文件。在 Project Properties 中,转到 Build Settings 选项卡,在靠近底部的位置找到一个名为 “Swift Compiler - Code Generation” 部分。编辑选项 Objective-C Bridging Header,使用值 Occer-Header-Bridge.h。备注:如果该文件已添加到您应用程序结构中的 Occer 子文件夹中,您可能需要值 Occer/Occer-Header-Bridge.h。在 Swift 代码中使用 Bluemix SDK 之前,转到 IBM Bluemix 并导航到您的 Occer 应用程序的 Overview 页面。单击 Mobile Options 下拉列表来显示您的应用程序的一些信息,包括路由、App ID 和 App Secret。片刻之后,您需要将这些信息插入到 Xcode 项目中。打开 AppDelegate.swift 文件并找到 didFinishLaunchingWithOptions 方法。将此方法替换为以下代码。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[NSObject: AnyObject]?) -& Bool {
// Override point for customization after application launch.
IBMBluemix.initializeWithApplicationId("yourappid", andApplicationSecret: "yourappsecret",
andApplicationRoute: "yourapproute.mybluemix.net")
IBMPush.initializeService()
var type = UIUserNotificationType.Badge | UIUserNotificationType.Alert |
UIUserNotificationType.Sound
var settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes:
type, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
return true
}确保已将 yourappid、yourappsecret 和 yourapproute 值替换为您应用程序的实际值。此代码初始化 IBM SDK 并尝试向应用程序注册远程通知。在用户第一次启动该应用程序时,他会被要求允许发送该应用程序的推送通知。以后不会再收到此提示,但应用程序每次启动时都会尝试注册。如果用户选择不允许发送推送通知,但在以后通过 iOS 设置手动授予访问权,应用程序将在下次启动时应用此更改。将以下代码添加到 AppDelegate.swift 文件的末尾处,放在结束 } 的前面:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
deviceToken: NSData) {
var pushService: IBMPush = IBMPush.service()
pushService.registerDevice("occeralias", withConsumerId: "occerconsumerid", withDeviceToken:
deviceToken.description).continueWithBlock({
(task: BFTask!) -& BFTask in
if task.error() != nil {
println(task.error().description)
println(task.result().description)
return task
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
error: NSError) {
println("Push Registration Failed. error: \(error.debugDescription)")
}如果用户向应用程序授予了向设备发送推送通知的权限,此代码会向 IBM 推送服务注册该设备。occeralias 和 occerconsumerid 值无关紧要。本例中的惟一 ID 是设备令牌。在执行这些更改后,再次在物理设备上运行该应用程序。这一次,您将被要求授予接收来自应用程序的推送通知的权限。点击 Allow。如果意外地单击了 Not Now,可以随时通过 iOS 设置启用推送通知。请注意,此提醒只显示一次,然后不会再在此设备上显示。 从 Bluemix 发送测试推送通知&现在设备已注册了推送通知,您可以向设备发送一个测试通知。在 IBM Bluemix 仪表板中,导航到应用程序的推送服务,并转到 Registrations 选项卡。您会在这里看到一个针对您设备的条目。接下来转到 Notification 选项卡。确保 Sandbox 已被选中。在 Message text 字段中,输入 Testing push notifications for Occer,按下 Next。在 Choose Recipients 屏幕中,选择 All registered mobile devices,单击 Send。您看到的通知类型取决于您的设备目前是否锁定。如果设备是锁定的,那么您会看到与下面这个屏幕类似的屏幕。如果您点击该提醒,它会直接启动 Occer 应用程序。在添加新比分时发送推送通知&从 Bluemix 仪表板发送推送通知不是很有用。我们更改一下 Ruby 后端,以便它会在每次向数据库添加新记录的时候发送通知。在 Ruby 项目中打开 app.rb 文件,在 /update 路由中找到下面这行:
# Push notification!在此行下方,添加以下代码:
app_id = 'yourappid'
app_secret = 'yourappsecret'
push_url = URI('https://mobile.ng.bluemix.net/push/v1/apps/' + app_id + '/messages')
https = Net::HTTP.new(push_url.host, push_url.port)
https.use_ssl = true
push_body = {
:message =& {
:alert =& 'New English Premier League soccer scores are available'
req = Net::HTTP::Post.new(push_url.path, initheader = {'Content-Type' =& 'application/json'})
req['IBM-Application-Secret'] = app_secret
req.body = push_body
res = https.request(req)保存该文件并使用以下命令将您的应用程序推送到 Bluemix:
$ cf push当然,要实际测试此功能的运行情况,需要触发该数据库的一次更新,以便从 football-data.co.uk 服务查找新比分。自您上次更新 Bluemix 数据库中的比分以来,不太可能添加了新比分。幸运的是,您可以在本地强制添加新比分,方法是使用 mongo CLI 客户端登录 MongoDB 并从数据库中删除所有比分。完成这些操作之后,使用以下命令再次启动您的本地应用程序:
$ rackup -p 4567您现在可以返回到 http://localhost:4567/update 下载更新的比分。这会导致发送推送通知。&最后一步是确保您的应用程序每天检查比分更新。这通常使用 cron 作业来完成。不幸的是,IBM Bluemix 没有 cron 作业的概念。但是,它有一个名为 Workload Scheduler 的服务可用来实现同样的目的。您可以轻松地构建一个应用程序,使用
每天自动向您的 Bluemix 有一些的 /update API 端点发送 HTTP GET 请求。也可以使用免费的 Web 服务(比如 )来实现同样的目的,无需构建另一个应用程序。结束语&本教程介绍了大量技术,从 Ruby 和 Sinatra 到 iOS 应用程序和推送通知。作为开发人员,Bluemix 平台使您能够将精力集中在构建优秀的功能上,无需担忧服务器和设备管理。本教程所描述的应用程序只是您可以使用 Bluemix 实现的功能的一个小示例。我很期待看到您提出新的想法。
注意:评论中不支持 HTML 语法
剩余 1000 字符
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=移动开发, Cloud computing, Web developmentArticleID=1009342ArticleTitle=在 IBM Bluemix 上构建移动足球比赛比分通知publish-date=

我要回帖

更多关于 ibm bluemix 教程 的文章

 

随机推荐