现在的位置: 首页 > 综合 > 正文

iOS 6 Passbook 入门 1/2

2014年09月24日 ⁄ 综合 ⁄ 共 30492字 ⁄ 字号 评论关闭

步骤:(不完整)

1,生成pass.json的校验和:

  1. openssl sha1 pass.json

  2,将生成的校验值置于manifest.json的pass.json的key-value下。

2,根据已有的3个pem文件和pass.json来生成签名文件

  1. openssl smime -binary -sign
    -certfile WWDR.pem -signer passcertificate.pem
    -inkey passkey.pem -in manifest.json
    -out signature -outform DER
    -passin
    pass:123

3,将所有生成pass相关的文件打包成passbook--

  1. zip -r freehugcoupon.pkpass manifest.json pass.json signature logo.png logo@2x.png icon.png icon@2x.png strip.png
    strip@2x.png



iOS 6 Passbook 入门 1/2

这篇文章还可以在这里找到 英语俄语

Learn Passbook in the iOS 6 SDK!
这是 iOS 6 盛宴 的第二篇教程! 这篇教程是我们的新书 iOS
6 By Tutorials
 中的一个缩略版本。 Marin Todorov 是这个章节的作者 — 他也写了 iOS 5 by Tutorials 大部分 “奖励” 章节。 希望你喜欢。

这是 iOS 教程团队成员 Marin Todorov 的一篇博客, 一个有着12年经验的软件开发者,独立
iOS 开发者,并且是 Touch Code Magazine 的创始人。

Passbook 是苹果发布的 iOS 6 技术中最火热的一个, 它所带来的开创性超过我们的想象。

Passbook 是一些是一个非常棒的组合。 四项独立的技术结合到一起,为 iPhone 用户带来了一个全新的体验:

  1. 新的 iOS 框架 PassKit
  2. 全新的 Passbook 应用,随着 iOS 一起绑定发布
  3. 苹果的 推送通知 服务(这次会保证发送成功)
  4. 你自己的服务端代码!

Passbook 和你曾经用到过的其他苹果的技术很不同。 让他变得与众不同的是关于一个文件格式的概念。 由你来创建 Passbook 文件, 然后用你希望的方式将他们展现给用户。 用什么技术和编程语言来实现它也完全取决于你!

毫无疑问, 通过这样的设置,相比其他苹果的技术, 你能够对你实现的东西有更多的控制。

因为苹果并没有处理 Passbook 的后端机制, 你需要使用一系列不同的技术来实现它。 在这篇教程中, 你将会用到 Objective-C 和 iOS,使用 JSON, 发送带有附件的多部分 Email, 使用 OpenSSL 对文件进行数字签名, 还有更多。

这篇教程被分为两个部分:

  1. 首先,你会学习到如何手工的创建 Passbook 文件。 你将从一个空的文件开始,最终完成一个完全风格化并且数字签名的 Passbook 文件。
  2. 然后, 你将会开发一个小型的 iOS 应用,用来在 iPhone 模拟器或者你的设备上面预览 Passbook。 你也将会了解不同种类的 Passbook 文件, 然后你会成为 Passbook 专家。

这个章节看起来有些凌乱, 但非常有好处 – 看完它之后, 你将会精通苹果最新的技术!

第一部分:了解和创建 Passbook 文件

Passbook 就是你口袋里的一切东西

苹果关于 Passbook 的介绍中说 “你口袋里面的一切东西”。 我非常喜欢这句话, 因为它非常好的演示了你怎样能够并且应该创造性的创建你的应用程序和服务。 Passbook 可以是任何东西。

但他们是什么呢?”, 你可能会这样问.

好吧, 这就是 Passbook 在 iPhone 上面的样子:

你能够很容易的认出这个 Pass 上面的几个不同的元素, 他们给了你一些重要的信息:一个 logo 和 公司的名称在最上方, “Free hug!” 清楚的描述了这个
Pass, 并且还有关于它的可用性的信息 (起始时间,持续时间)。

然后,在最下面,有一个条形码。 它和你在火车票,飞机票,购物券上面看到的条形码很象。如果你仔细的想一想, 你的 iPhone 中的 Pass 可以和那些塞满你口袋的纸质的票据保存同样的信息,对吧? 一些文字,一个条形码 – 就是这些了。相信我,你的 iPhone 上面的数字票卷可以做更多的事情。

Pass 由什么构成,一个Pass

再看一下 pass 中有什么, 想一想它拥有的不同部分:


所有类型的 pass 都有这些重要的东西:

  1. 顶部抬头. 顶部条包含了一个容易辨认的 Logo 和一个公司名称。 头部区域用户会在 Passbook 的列表中看到。 它包含了你要给用户提供的最关键的信息, 这样他们就可以辨认出他们需要的
    pass 了。
  2. 主体区域. 这部分包含了 pass 的内容。 每个 pass 在这个区域都有不同的风格, 它通常在 pass 打开时显示最主要的信息。 像是 “打折 20%”, “一杯免费咖啡”,
    “余额 $120″ 或是其他这类的信息非常有用。
  3. 附加信息. 第三个部分用作附加信息 – 仍然是很重要的资料(例子中的促销的有效性和开始时间), 但绝对不像关于 pass 是什么东西这样的信息那么重要。
  4. 条形码. 条形码包含了编码后的信息, 可以通过条形码扫描器很容易的将这些信息转移到其他系统中。在上面的例子中, 条形码包含了一个加密代码。 档被扫描器节解码后, 它会给这个
    pass 的所有者一个免费的拥抱(立即发送)。

现在,你可能会想纸质的票和购物券是什么样的。 这些你每天用到的东西可以被转换到 iPhone 上面。

Do I board with this pass, or do I get a free coffee?

在你写任何代码之前, 看一下不同类型的 pass。

苹果定义了 4 种不同的 pass, 每个都很常用, 还有第 5 种, 用作 “普遍” 用途。 为什么有这么多不同的 pass 呢, 你怎样识别他们呢?

预定义的这些 pass 类型,每一个都是为了显示不同种类的信息,以适应不同的用途。这也是为什么你的健身房会员证和你的音乐会门票的布局和内容是不同的! 前者需要你的照片,而后者不需要。

布局是区分这些不同种类的 pass 的主要方式, 但是一些 UI 特性, 比如圆角,剪纸同样能很容易的识别出 pass 来。 这些不同之处很小, 但是很明显, 这也是为什么你要确保用的是正确的 pass 类型的原因。

这里是四个预定义的 pass 类型:

  • 优惠劵
  • 登机牌
  • 购物券
  • 活动门票

但让, 还有通用类型的 pass。 教程的第二部分会讨论所有这五种类型。

现在,看一下下面这个登机牌的例子。 你会看到他和前面的那个拥抱优惠券很像, 但有一些关键的不同点:它提供了两列的布局方式, 这样能够很容易的找出离开和到达的城市; 离开的站台号,事件和座位号也都摆放整齐。

现在,我确定你已经被说服了, pass 是 iPhone 上面一个很伟大的东西! 让我们看看 pass 是如何设置的, 并且如何创建一个!

pass 的内部结构

这部分将会介绍 pass 的构成部分。 pass 通过一个扩展名为 .pkpass 的文件展现给用户。 (“pkpass” 的意思是 PassKit Pass – 很好理解,对吗?)

.pkpass 只是一个 .zip 文件。 如果你将它重新命名为 ZIP 并解压它, 你会找到一些文件。 这是你前面看到的Free Hug Pass 的内容:

  • pass.json – 关于这个 pass 的信息区域的描述,他们的内容, 和元信息。
  • manifest.json – 这个文件描述了这个 pass 中的文件列表, 和每个文件的 SHA1 校验和。
  • signature – manifest.json 一个分离的的 DER 签名, 通过苹果提供的证书生成的。
  • background.png – 显示在 pass 正面的图片。
  • background@2x.png – 视网膜屏尺寸的显示在 pass 正面的图片。
  • logo.png – 在 pass 的头部区域显示的 logo。 苹果推荐的是一个纯色单色的 logo。 图片的尺寸由你决定, 但是高度不能大于 50px 以便适合头部的高度。
  • logo@2x.png – 视网膜屏幕的 logo 图片
  • icon.png – pass 的一个小图标, 当 pass 作为 email 附件的时候会被用到。 在写这篇教程的时候, 还没有关于这个图片尺寸的文档,但看起来像是
    29×29 像素(大尺寸的图标会被缩放,所以他们的显示效果也不错)。
  • icon@2x.png – 视网膜版本的图标
  • strip.png 和 strip@2x.png –
    用作主条目的背景;仅用于优惠劵和购物券

这就是所有了!

正如你看到的, pass 的主文件是 pass.json 这个 JSON 文件。 在它里面你声明了这个 pass 正面和反面的所有信息, 你提供了这个 pass 需要显示的所有图片(在优惠券的情况中,
你仅仅需要指定background.png和它的视网膜版本)。最终,你需要一个清单文件,它包含了所有这些文件的 SHA1 校验和,和一个分开的签名, 这样 Passbook 能够验证这个 pass 在你创建之后没有被修改过。

让我们来写一些 JSON!

现在你可以写一些代码了。 让我们看看你能否重新创建一个Free Hug pass!

等一下! JSON 不是 Objective-C。 它甚至不是任何一种编程语言。 它仅仅是一个标记语言, 用来描述数据结构。 那么,你如何写 JSON 呢? 实际上你可以使用任何的文本编辑器 – Xcode, TextMate, Coda 或者 TextEdit. 在这章中, 你会用到 Xcode。

在 Xcode 的菜单中, 选择 File/New/File… 然后选择 iOS/Other/Empty 作为文件类型。 将新文件命名为 pass.json 并将它保存到你选择的目录中。
注意你可能想要创建一个新的目录来存放 pass, 因为你会将很多和 pass 相关的文件存放到同一个目录中, 将他们放在一起是一个不错的选择。

你现在应该能看到这个空白的窗口, 就像这个:

但那没什么问题 – 不用担心!

对于那些不了解 JSON 的人 – 他很简单。 你可以用数字,字符串,数组和字典。 信息将会写成这样:

14.37457for numbers 
“Some text here!” – for strings
[object1, object2, object3,]for arrays

And:

{“key1”: object1, “key2”: object2, “key3”: object3,}for dictionaries

Object1, object2, object3 可以是这四种类型的任意一种 – 你可以用数组包含字典, 字典包含数组,字符串,数字,等等

你可以了解更多关于 JSON 的信息:http://en.wikipedia.org/wiki/JSON

你可能注意到了,苹果的 plist 文件存放着和 JSON 一样的信息 – 数组,字典,数字和其他。你可能会感到奇怪, 为什么苹果用 JSON 而不用 plist 呢。

是这样, pass 很有可能是在非 iOS 或者 OS X 的环境下生成的 – 更有可能的是, pass 是由 web 服务器作为对用户请求的响应生成的。 苹果想让你能够很容易的从所有的 web 脚本语言中生成这个文件, 因为 JSON 都被 PHP, .NET, Rubym Python 这样的语言良好的支持,最终, JSON 看起来是最佳的选择。

让我们从 Free Hug Pass 的架构开始! 将这些代码复制到 pass.json 文件中:

{
    "formatVersion" : 1,
    "passTypeIdentifier" : "pass.com.yourdomain.couponfreehug",
    "serialNumber" : "001",
    "teamIdentifier" : "<YOUR TEAM IDENTIFIER>",
    "organizationName" : "Free Hugs LLC",
    "description" : "Coupon for 1 Free Hug"
}

这是你需要提供的最小量的元数据:

  • formatVersion – 文件格式的版本,因为这是一个全新的文件格式, 你用的是 1(注意,1 是一个数字;如果你用字符串来表示这个值的话,这个文件就会是无效的。)
  • passTypeIdentifier – 这是 Pass 的标识。 这个和 iOS 中的 bundle identifier 差不多。 稍后会更多的介绍关于这个标识的内容。
  • serialNumber – 这个是 pass 的序列号。 你可以用任何方式生成它 – 它可以是数组, 例如 “00193”(注意,它仍然被写成字符串值), 或者是字母和数字的组合,像是你在登机牌上面看到的序列号(例如
    “XS83A”)。
  • teamIdentifier – 这是苹果分配和每个 iOS 开发者的一个唯一的十个字符的标识。 如果你创建过你自己的 iOS 应用,你应该已经熟悉它了。 你可以登陆到
    iOS Member Center 并点击你的组织名来找到你的 team identifier。你可以在 “Company/Organization ID” 标签后面找到它。 我在稍后会告诉你另外一个找到它的方法,
  • organizationName – 你的组织名称。
  • description – 关于 pass 一个简短的介绍。

这包含了很多信息, 所以让我们看看他们如何被苹果应用。

因为 pass 不是必须要和 iOS 应用相关联, 所以没有一个自动化的方式来让 pass 和指定的 iOS 开发者账号相关联(需要验证 pass 中的内容), Pass 可以独立于应用到达用户的设备上, 通过邮件或者下载的方式, 这也是为什么在 pass 的元数据中要包含 teamIdentifier 了 – 用于将 pass 和开发者账号相关联。一旦苹果知道了创建这个 pass 的开发者标识,它就会用 passTypeIdentifier 来确定它是哪种类型的 pass。 每种类型的 pass 都有它自己的证书,这样苹果就能过通过这个证书来验证包含在
pass 中的签名了 – 确保没有人篡改 pass 的内容。

最后, serialNumber 为指定的 pass 类型分配的序列号。

复习一下, 想一下这个例子:

  • Joe’s Café 有一个苹果开发者账号。 他们将他们的 team identifier 应用到他们所有的 pass 上面。
  • 他们有预先设置好余额的购物券,用户可以用他们到商店里兑换咖啡。 购物券的 passTypeIdentifier 为 “pass.com.joescafe.storeCard”。
  • 他们还有一种优惠券, 持有另外一个不同的 passTypeIdentifier – “pass.com.joescafe.discountCoupon”。
  • 每个用户可以拥有多个购物券(例如,他们自己买了一个,然后他们的朋友又最为礼物送给他们一个), 所以 serial number 用来区分同一类型的两张购物券(例如 “0134″ 和 “0274″).
  • 拥有同样 passTypeIdentifier 的 Pass 会被放到 Passbook 的一个组里面。 当用户到达 Joe’s Café 时, 他们会在 Passbook 中点击 Joe’s Café 的购物券组,然后选择一个他们想用的 – 还仍然有效的那个!

现在你应该明白 pass 标识是如何工作的了。 所以, “通过” 这节,去看看下面的吧, 你将会创建你自己的 pass 类型。

给我证书!

进入 iOS Developer Portal (https://developer.apple.com/devcenter/ios/index.action),
在你登录进去之后, 在右边的菜单栏中打开 iOS Provisioning Portal。

如果你已经得到了签出到最新的 iOS 6 版本了,你可能已经注意到左边多了一个菜单项 Pass Type IDs。 点击那个链接,在接下来的页面中, 你将会看到你已经创建过的 pass 类型的列表(这时可能还是空的)。

点击 New Pass Type ID 按钮, 你将会进入一个创建新的类型的页面。 在描述区域填入 “Free Hug Pass”, 在标识区域填入 “pass.com.yourdomain.couponfreehug”。 对于 Pass Type ID, 苹果推荐使用以 “pass“ 开头的反向域名表示法。 这就是你要用的格式。

注意: 对于这章的目的来说, 你可以使用 “com.yourdomain” 这种形式, 但是在正式的应用中, 记住要将 com.yourdomain 这种替换成实际你自己的域名的方向表示法。☺

还要注意,如果你决定将标识从 “pass.com.yourdomain.couponfreehug” 修改为别的, 你还要相应的修改 pass.json 文件中的 passTypeIdentifier 的值。

接下来, 点击 Submit 按钮来创建你的 pass。

顺便说一句,那个指示灯没有变成绿色, 你可能已经猜到,还缺一些东西。 你是对的。 你还需要生成一个 pass 证书。 点击 Configure 按钮。 将要展示的下一个页面是说明 pass 的标识的好地方。

这里你能看到你的 teamIdentifier (以 ABC 开头的前10个字符), 用这个 ID 来更新 pass.json 文件 – 确保仅替换 占位符,并保留两边的引号!

好了! 你的 pass.json 现在更新了。 然而, 还有一些额外的步骤将你的证书导入你的开发环境。
返回 iOS Provisioning Portal, 点击 Configure 按钮:

这将会打开 Pass Certificate Assistant (*奇特的名字!), 它将会引导你完成证书的生成。 仔细看一下对话框中的内容,并跟随它的步骤。

当你提交你的签名请求之后, 你的证书将会及时的生成出来,并且你应该看到一个成功对话框:

点击 Continue 几次, 然后点击 Download 按钮来得到证书文件。 文件被下载后, 找到他,并双击它将它导入到钥匙串中。 注意大多数情况下它在你的用户目录中的 Downloads 文件夹中,除非你在浏览器中设置了另外一个默认下载地址。

如果钥匙串让你确定是否导入, 点击 Add 按钮:

然后, 你将会在钥匙串中看到你的证书:

你已经完成了证书的制作! 现在你在 JSON 文件里有了真实的数据, 并且当需要签名的时候你有了正确的证书。

Pass 的样式风格!

让我们继续构建 pass.json 文件 – 接下来修改它的外观。

打开 pass.json 并且在最后定义一个 ”description“ 键, 添加一个逗号 – 因为你需要在字典中增加多个键。 在大括号结束前, 添加:

    "logoText" : "Free Hugs LLC",
    "foregroundColor" : "rgb(255, 255, 255)",
    "backgroundColor" : "rgb(135, 129, 189)",
    "labelColor" : "rgb(45, 54, 129)"

这些键的作用:

  • logoText – 这是显示在 pass 头部并且紧挨着 logo 图片的文本。
  • foregroundColor – 文本的颜色。
  • backgroundColor – pass 的背景颜色。 Passbook 将会根据背景色的色值来创建一个漂亮的渐变效果, 这样来给 pass 的正面一个良好的视觉外观,
    苹果推荐使用鲜艳的颜色。
  • labelColor – 根据你的背景颜色,pass 上面的标签将会被渲染为一个和背景色反差比较大的颜色。如果你需要的话, 你可以为这些标签指定你自己的颜色。

现在你的 pass 有了一些样式! Heidi Klum 会感到很荣幸。

除非你达到了在 Passbook 中构建并测试的最小要求, 否则你还需要继续添加更多的元素。 接下来,你将会添加一个条形码。
听起来很复杂,对吗? 幸运的是,做起来很简单。 PassKit 支持三种不同的条形码 (所有这些都是二维条码格式): QR, PDF417 and Aztec
描述一下我的意思:

换句话说, pass 不支持那些老式的条形码, 你通常会在杂货店的商品包装上看到它们, 并且今后也不会支持它们。 PassKit 使用的是 2D 格式,可以让基于图片扫描的设备(像是 iPhone) 很容易的阅读它。

你将会使用 PDF417 标准来构建 Free Hug 优惠券的条形码 (上面这些图的中间那个), 在代码的最后一行添加一个逗号(在结尾大括号的前面),并把它粘贴到 barcode 的 JSON 中:

    "barcode" : {
        "message" : "All you need is love",
        "format" : "PKBarcodeFormatPDF417",
        "messageEncoding" : "iso-8859-1"
    }

不管你信不信, 这是所有你需要做的 – 苹果会帮你生成一个条形码! barcode 字典有三个键:

  • message – 这是条形码包含的数据。 它可以是唯一的编码, 持有者的客户ID, 或者其他任何东西。 在 Free Hug 的例子中, 它仅仅是一个文本消息,用来让持有者得到一个免费的拥抱。
  • format – 条形码的格式名称。 使用 PKBarcodeFormatQR, PKBarcodeFormatPDF417 or PKBarcodeFormatAztec
    其中一个常量, 来生成 2D 条形码。
  • messageEncoding – 用来解码消息的文本编码名称。 如果你使用非拉丁语言, 你将要用 UTF8 或者其他形式适合你的文本编码(如果你私用标准的英语和数字,
    它的默认值是 “iso-8859-1”)。

目前为止, pass 的源代码看起来是这样的:

{
    "formatVersion" : 1,
    "passTypeIdentifier" : "pass.com.yourdomain.couponfreehug",
    "serialNumber" : "001",
    "teamIdentifier" : "ABC1230000",
    "organizationName" : "Free Hugs LLC",
    "description" : "Coupon for 1 Free Hug",
    "logoText" : "Free Hugs LLC",
    "foregroundColor" : "rgb(255, 255, 255)",
    "backgroundColor" : "rgb(135, 129, 189)",
    "labelColor" : "rgb(45, 54, 129)",
    "barcode" : {
        "message" : "All you need is love",
        "format" : "PKBarcodeFormatPDF417",
        "messageEncoding" : "iso-8859-1"
    }
}

接下来,你会添加一些有价值的信息到 pass 的正面。

再说一便, 在 barcode 字典的结尾大括号后面添加一个逗号。(你要保持这样, 因为我希望你的 JSON 文件在任何时候都是有效的。 一旦你习惯于写有效的 JSON, 你可以节省很多调试的时间。)

继续并添加一个键,用来表示这个 pass 是一个优惠券(将这段代码粘贴到最后一个结尾大括号的前面):

    "coupon" : {
    }

在这个空的字典中, 你将会添加所有的定义和数据来显示优惠券上面的信息。
在 “coupon” 中添加:

       "primaryFields" : [
           {
           "key" : "offer",
           "label" : "for you",
           "value" : "Free hug"
           }
       ]

这种结构第一眼看上去比较奇怪, 但是相信我 – 它是有意义的。 首先你添加了一个新键 “primaryFields”, 它的值是一个数组。 为什么是数组呢? 因为每一节都可以显示一个或多个字段,所以你需要一个有序列表来指定他们的先后顺序。

在个列表中的每一个字典都描述了一个字段。 你大概已经看明白它们了, 但让我用例子来说明它。 对于每一个字段你都会得到如下几个基本键:

  • key – 字段的名称。 在这个例子中, “offer” 字段显示在这个 pass 的主内容区域。
  • label – 这个字段的副标签。 在这个例子中, “for you” 将会在下面以一行小字母显示。
  • value – 显示在 pass 上面的文本域。 在这个例子中, “Free hug!” 将会在主内容区域以一个大字体显示。

对于每一个字段,还有很多键可以用, 但你会在稍后看到它们。

重要的东西是 – 你现在有了一个完整的 pass.json 文件! 太酷了!

是时候让它变得更漂亮了!

他们说一张图片顶得上千言万语 – 你很幸运, 在 pass 的正面没有地方显示上千个文字, 所以为了适应这个限制, 你也要使用图片。

下载我为你准备的资源:PassAssets.zip
解压这些文件, 并在 FreeHugCoupon 目录下,你将会找到一系列的 PNG 文件。 将它们拷贝到你的 pass 工作目录中。

就是这样 – 你完成了! 非常容易。

等一下, 什么? 你不需要在 pass.json 添加任何代码来告诉 Passbook 要加载哪一张图片。 没错!

Passbook 会根据标准的命名规范来加载图片。这意味着名称为 icon.png; icon@2x.png; logo.png; logo@2x.png; strip.png and strip@2x.png 的图片
将会显示在 pass 上面。 除了需要把这些文件包含在 pass 的包中, 不需要在做任何其他事情(教程后面还会用到更多的图片。)

注意: 这里有一点 pass 图片比较难理解的地方 – 我花了一段时间才弄明白 – 图片文件需要导出成 PNG24 格式。 由于某些原因,比较小尺寸的 PNG8 格式不会显示在 Passbook 上面。

“让我们试试这个 pass 吧! 我已经想看看它了!”,

不幸的是, 在 pass 包完成,并且签名,压缩之前, 你不能够预览它。 Passbook 不能显示任何无效的(不完整的) pass。 所以,再忍耐一会儿, 继续工作。

pass 清单文件

pass 清单文件是另外一个你需要创建的 JSON 文件, 并且它描述了 pass bundle 中包含的所有文件和他们的 SHA1 校验和。

你可以通过自己生成 SHA1 校验和(稍后我会给你展示),但为了更快的创建完你的第一个 pass, 我将一个已经生成好的 manifest.json 文件放到了 PassAssets.zip 文件中,你已经下载并解压它了。在你解压 zip 的地方找到 manifest.json 文件, 将它拷贝到你的 pass 工作目录中。

它的内容如下:

{
 "strip.png":"25b4c9ff2bafe056f3e28379db0ef3fb460c718b",
 "strip@2x.png":"dee775ed6fb3c7278b84c65853401e760caabc92",
 "icon.png":"8eaa0896db93f2165fa417df3d002ce9c61fcd92",
 "icon@2x.png":"555ce7f70f2f44fb7ac9d9f46df5738ec6250f37",
 "logo.png":"e8c4edfbcae41d9d88fad7137d8ed30ae5f73e67",
 "logo@2x.png":"1f9b1cc4c75b380ade07e9f2b7f37f988d9d14c3",
 "pass.json":"<INSERT YOUR PASS SHA1 HERE>"
}

这些图片的 SHA1 校验和已经填好了, 但是最终的校验和 – pass.json 文件的 – 还没有。
你将会自己生成它的 SHA1。 这非常简单 – 打开终端并定位到你的 pass 目录。

注意: 如果你不熟悉如何在终端定位目录, 这样做: 将你的 pass 文件移动到桌面的 “FreeHugCoupon” 文件夹中, 然后打开终端,输入这个命令:

cd ~/Desktop/FreeHugCoupon

这样就好了

在终端提示符中输入这个命令:

openssl sha1 pass.json

命令行的输出看起来是这样(实际的校验和可能会不同):

SHA1(pass.json)= c24766ef5aa92197eace640fcc4fb584a505a733

用将这个字母数字组成的校验和替换 manifest.json 文件中的 “”。 保存这个文件, 你就完成了! (确保你保留这个双引号)。

注意!
一个很重要的事情,就是在我没让你修改 pass.json 这个文件之前, 不要再修改它了。即便你仅仅向 pass.json 添加了一个字符, SHA1 校验和就会改变, 这样你的 manifest.json 文件将会失效,因为这里给出的校验和不再和修改后的 pass.json 文件的校验和相匹配。

这是你最后一个要修改的源文件了。 棒极了!

我能有你的签名吗?

现在,进行创建 pass 中最有趣的一部分。

还记得你为你的 pass 类型从苹果获得的证书吗? 你已经将它导入到钥匙串中了, 并且还没有接触过它。 现在你将会把这个证书和秘钥导出成 PEM 格式, 这样你可以把它们用于 OpenSSL。

打开钥匙串访问, 在左边的菜单中选择证书(在类型下面),并找到叫做 “Pass Type ID: pass.com.yourdomain.couponfreehug” 的证书。 确保你选中的是证书本身,而不是它下面的私钥:

接下来, 右键点击这个证书, 在弹出菜单中选择导出 “Pass Type ID: pass.com.yourdomain.couponfreehug”…,将导出的文件保存成 “Certificates.p12” 到你的工作目录中。将会有一个弹出框,让你输入一个密码:

为了让这个过程更简单一点, 直接点击 OK – 这个证书将会导出为不带密码保护的。

注意: 在这是,你可能会被要求输入登陆钥匙串的密码。 如果是这种情况, 直接输入你电脑的用户密码就足够了。 Certificates.p12 文件现在包含了 pass 的证书和私钥。 OpenSSL 需要单独的两个文件,
所以现在你需要将他们从 .p12 文件中提取出来。

切换回终端 – 是 OpenSSL 魔术的时候了!

在确保当前目录是正确的之后 (输入 “ls -al” 然后点击 Enter 键 – 你应该看到这个目录的文件列表,并且这个列表应该包含你的 Certificates.p12 文件), 输入如下命令:

openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -out passcertificate.pem -passin pass:

这将仅将 pass 证书导出为 PEM 格式,并在同一个目录中把它保存成 “passcertificate.pem”。(如果这个操作成功的话, OpenSSL 将会输出 “MAC verified OK” 消息。)

接下来, 通过这个命令将私钥也导出成单独的文件:

openssl pkcs12 -in Certificates.p12 -nocerts -out passkey.pem -passin pass: -passout pass:12345

注意到这次, 你需要提供一个密码来导出这个私钥文件。 在这个例子中, 仅使用 “12345″ – 在生产环境中, 应当使用一个强密码 – 不能是 “password1” 或者 “passw00t” 这种东西。

为了给你的 pass bundle 签名, 你需要另外一个证书 –
To sign your pass bundle you will need one more certificate – WWDR Intermediate 证书, 用来验证发给你证书的发布者 – 苹果。 你已经将它安装到钥匙串中了。 打开钥匙串访问, 选择 “证书” 分类, 并找到一个叫做 “Apple Worldwide Developer Relations Certification Authority” 的证书(是的,这确实是一个很长的名字):

如果万一你没有这个证书, 那么打开你的浏览器, 访问这个页面 http://www.apple.com/certificateauthority/。在这里你可以下载你可能需要的最重要的苹果证书。
翻到下面,找到 WWDR 证书, 下载 .cer 文件, 并导入到钥匙串中。

你已经准备好导出这个证书了。 返回到钥匙串访问, 右键点击证书名称并在弹出的菜单中选择导出选项:

在 “另存为…” 对话框中, 找到 format 下拉框,并选择 Privacy Enhanced Mail (.pem) 选项:

在对话框顶部的文本框中, 输入文件的名称 “WWDR.pem”, 选择 pass 的工作目录作为目标, 然后点击保存按钮来完成导出。 你已经可以创建签名了, 输入这个命令:

openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem -inkey passkey.pem -in manifest.json -out signature -outform DER -passin pass:12345

仔细看一看上面的命令行 – 非常容易理解所有的参数。 signer 参数是你的 pass 证书的文件名; inkey 是用于对 manifest.json 签名的私钥文件; in 是输入文件的文件名; out 是输出文件的文件名;outform 是输出的格式(你需要用 “DER“ 来创建一个分离的签名); 最后, passin 是私钥的密码。

现在你有了你的签名, pass 的创建基本完成了。

还剩下最后一步, 就是将 pass 中的多个文件集中到 .pkpass 文件中。 在终端输入这个命令:

zip -r freehugcoupon.pkpass manifest.json pass.json signature logo.png logo@2x.png icon.png icon@2x.png strip.png strip@2x.png

通过使用 shell 命令 “zip”, 你创建一个叫做 freehugcoupon.pkpass 的 ZIP 文件, 并且这个档案包中包含了后面列表中的所有文件。
不管你是否相信。。。 就是这样! 全部都完成了! 你做到了!

给我展示一下吧!

是的, 你最终到达了, 你拥有了一个完整并有效的 pass, 你可以在 iOS 6 的设备上看到它了。

创建一个 email 消息(或者到你在 iOS 6 设备中设置的邮箱账号) 并附带一个你刚刚创建的 .pkpass 文件。 发送出去, 打开 Mail.app 并看一看! 你应该在附件中看到这个 pass, 像是这样:

如果你看到这个 pass 了 – 祝贺你! 你创建好它了!

如果没有, 不要失望 – 这是一个很长并容易出错的过程,你要回到开始阶段, 然后检查一些是否执行了所有必须的步骤。 确保你的 JSON 文件是有效的并且正确地导出了你的证书文件和私钥。

提示:如果你想验证 JSON 文件的有效性, 使用这个在线工具: http://jsonlint.com/ 来快速的验证你的代码。

是时候看看这个 pass 了! 在邮件消息中点击它, 然后 Passbook 将会弹出来并显示给你伟大的东西!

这非常棒! 点击右上角的 Add 按钮, 你将会看到一个精致的动画效果, pass 滑了下去(进入 pass 中, 但是你很有可能是空的) 然后你会返回到 Mail 中。

注意: 如果你想在你的 Passbook 中看到更多的 pass,可以用你的移动浏览器访问 http://passk.it/samples。 这个网站上面有一系列非常有趣的 pass 的样本。

现在,退出 Mail, 并打开 Passbook 应用。 这是你的第一个 pass。 祝贺你!

在 Passbook 预览一下这个 pass, 正面和背面(你可能会感到奇怪, 你可以通过点击右下角的那个小的斜体 “i” 来访问 pass 的背面):

你必须承认, pass 看起来很漂亮, 但它的信息不是很充足。 是的 – 稍后你会添加更多的字段。 我打赌你现在已经忍不住想把这个 pass 撕掉了 – 去吧! 不管怎么样, 你现在想创建多少个, 就创建多少个, 所以 – 撕掉一些吧 ☺ 点击垃圾箱按钮, 然后。。。

接下来去哪?

现在你了解了创建 pass 的基本方式和用 email 分发它们。 但是, pass 还有更多东西!

教程的第二部分
你将会学到:

  • 如何将信息添加到 pass 中
  • 如何创建不同风格的 pass
  • 如果使用 pass 文件格式提供的所有特性
  • 如何格式化数字, 日期, 添加地图链接, 还有更多!

如果你还想学习更多, 看一下 iOS 6 by Tutorials, 里面包含了这个教程的第三部分,将会引导你如何自动创建
pass 并通过你的 web 服务器分发他们。

------------------------------------------------------------------------------------------------------------------------------------------------------

iOS 6 Passbook 入门 2/2

这篇文章还可以在这里找到 英语俄语

Learn Passbook in the iOS 6 SDK!
这是 iOS 6 盛宴 的第二篇教程! 这篇教程是我们的新书 iOS
6 By Tutorials
 中的一个缩略版本。 Marin Todorov 是这个章节的作者 — 他也写了 iOS 5 by Tutorials 大部分 “奖励” 章节。 希望你喜欢。

这是 iOS 教程团队成员 Marin Todorov 的一篇博客, 一个有着12年经验的软件开发者,独立
iOS 开发者,并且是 Touch Code Magazine 的创始人。

如果你看过这个系列的第一部分
那么你应该知道如何构建一个 pass 包, 如何给他们签名, 如何通过邮件发送他们。我确信,你已经迫不及待的想要更深入的了解苹果这个最热门并且最新的技术了。

系好安全带 – 我们将继续上次没完成的部分!

关于 pass 更多的信息

pass 有两面: 在正面你可以在一些预定义的区域中添加文本信息; 在背面, 你可以尽可能的显示你想显示的信息。 让我们先对正面进行一些维护。☺

打开 pass.json 并找到 primaryFields 数组的定义。 在它的同一级上, 在 coupon 字典中, 你将会添加更多的段, 来显示更多的信息。

你将添加另外的键到 coupon 字典上, 你首先需要添加一个逗号, 然后定义这个新键。当你将要在 coupon 字典添加另外一个键时, 你需要首先添加一个逗号, 然后再定义这个新键。在文件最后一个结尾方括号后面添加这个逗号(看看下面这张图片指出的位置)。

在逗号的下一行, 将 JSON 代码粘贴过去:

    "secondaryFields" : [
      {
        "key" : "expires",
        "label" : "Valid for",
        "value" : "Lifetime"
      }
    ],
    "auxiliaryFields" : [
      {
        "key" : "date",
        "label" : "Promo starts on",
        "dateStyle" : "PKDateStyleMedium",      
        "timeStyle" : "PKDateStyleNone",
        "value" : "2013-01-11T00:00Z"
      }
    ]

现在除了 primaryFields 字典, 你有了 secondaryFields 和 auxiliaryFields –
这些是 pass 的正面的一些附加字段。 他们不像主字段那么重要, 但仍然足够重要,所以要留在正面。

auxiliary 字段可能会引起你特别的兴趣 – 它包含了一些你之前没有用到过的属性。 这个字段, 和你用到它其他字段不同, 它是一个日期字段。 Passbook 会处理将 日期/时间 值转换成用户所在的本地化时间的工作, 并将它格式化为本地化的文本显示。

看一下日期字段的属性:

  • value – 它是一个 W3C datatime 格式化后的值(关于它的文档, 可以看一下这里 http://www.w3.org/TR/NOTE-datetime)。
  • dateStyle – 用于格式化日期部分的风格; 必须是这些其中之一:PKDateStyleNone, PKDateStyleShort, PKDateStyleMedium,
    PKDateStyleLong or PKDateStyleFull。
  • timeStyle – 和 date 字段的风格一样; 使用同样的常量来定义时间的风格。

这就完成了! 现在你可以进行另外一次构建, 并且看一下 pass 这时候是什么样子了! 你已经觉得很有趣了吧?

要执行的构建步骤:

  1. 确保 JSON 代码看起来没问题 (否则,确保用 http://jsonlint.com/ 来检测它)。
  2. 在终端里, 进入你的工作目录, 生成 pass.json 文件的 SHA1 校验和:

    openssl sha1 pass.json
  3. 将 pass.json 的 SHA1 校验和放入 manifest.json 文件中。
  4. 为 pass 生成一个分离的签名:

    openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem -inkey passkey.pem -in manifest.json -out signature -outform DER -passin pass:12345
  5. 最终, 将这些文件打包到 .pkpass 中:

    zip -r freehugcoupon.pkpass manifest.json pass.json signature logo.png logo@2x.png icon.png icon@2x.png strip.png strip@2x.png
  6. 通过电子邮件将文件发送到你的 iOS 6 设备上!

任务完成了! 你的 pass 应该看起来和下面的图片一样:

正面基本完成了, 可以在背面做一些事情了!

打开 pass.json 并且在最后一个方括号后面添加一个逗号(现在你应该很熟练的能将逗号放在正确的位置上了)。 在逗号后面, 为卡片的背面添加一个字段:

    "backFields" : [
      {
        "key" : "extras",
        "label" : "Extras",
        "value" : "Your friends receive 50% off price"
      },
      {
        "key" : "phone",
        "label" : "For more info",
        "value" : "800-1234567890"
      },
      {
        "key" : "terms",
        "label" : "TERMS AND CONDITIONS",
        "value" : "Free hugs last 18 seconds and must be claimed on your birthday. Bring your pass or an id"
      }
    ]

幸运的是,pass 的背面是可以滚动的,所以你可以添加更多你需要的信息。(是的, 有时候合同条款会占据很长的空间, 所以滚动是很必须的。)

现在 – 是时候看一下你刚刚添加的字段在 pass 上看起来是什么样的了。 根据前面的说明再次构建, 并且通过电子邮件将 pass 发送到你的设备上。 按下 “i” 按钮, 然后背面将会显示出来 – 它应该看起来和下面的图片一样:

目前还不错! 再看看电话号码 – 它会自动被转换成链接,点击它你就可以直接拨打电话。 你可以在背面添加其他一些交互信息 – 像是地址(将会在地图中打开) 和电子邮箱(将会在 Mail 应用中打开)。

Pass 预览应用

你可能已经感觉到了, 如果构建和预览 pass 的过程能够更简单快速一点,那就更棒了。
我的意思是, 继续, 我们一定要在每次想预览 pass 的时候, 必须要用邮件发送给我们自己吗?

当然 – 好消息! 因为我知道在你找到合适的 pass 之前, 你将会尝试多种颜色的组合, 图片和文字, 在这部分章节中, 你将会创建一个 iOS 应用, 它可以让你更快速的在 iPhone 模拟器中预览你的 pass。

注意: OS X 10.8.2 现在支持直接在你的 MAC 上面预览 pass。如果你双击 .pkpass 文件, 你将会看到 pass 的外观。 但是, 检测 pass 是否有效的唯一一个方法是, 在你的设备和模拟器上面打开它,
并试着导入它。

还有一个方法可以将 pass 安装到 Passbook 中, 我之前没有提到。 除了将 pass 通过 email 发送,并直接在 web 服务器上下载它, 你还可以使用 iOS 6 中新的 PassKit framework, 来通过 iOS 应用来安装 pass。

PassKit 是一个非常简单的 framework, 它仅包含了 3 个类。 为了创建一个简单的 pass 预览应用, 你将会用到 PKAddPassesViewController。这个类接受一个 PKPass 并将它显示到屏幕上。

在现实情况中, 你的应用很可能从服务端抓取一个 pass, 或者从 iClound 中得到它, 但在这个例子中, 你仅用到在你应用本地包中的 pass。

开始吧!

在 Xcode 的菜单中, 选择 File/New/Project…, 然后选择 iOS/Application/Single View Application 并且点击 Next。将项目命名为 “PassesPreview”, 并确保它是一个 iPhone 应用。 还要确保 Use Storyboards 和 Use Automatic Reference Counting 是选中的。 将项目保存到你选定一个位置。

在 Project Navigator 中, 选择 Xcode 项目(项目树中的第一个选项), 并在右边的条目中,确保 “PassesPreview” target 是选中的。 接下来点击 Build Phases 选项卡, 然后打开 Link Binary With Libraries 条目。

点击 (+) 按钮, 在 frameworks 的列表中双击 “PassKit.framework” 来将它包含到你的 Xcode 项目中 (或者选择 PassKit.framework 然后点击(+)按钮)。

现在选择 MainStoryboard.storyboard – 应用的界面显示出来了。 你需要一个全屏的表格, 所以将一个 TableView 拖动到主界面中。

接下来, 按住 Ctrl 并且将控制器对象拖动到下面的调色板中。 一个弹出框将会显示出来。 点击 “dataSource”, 然后重复这个操作, 并且第二次的时候,选择 “delegate”。 这个表格现在正确的连接到你的视图控制器中了。

现在,完成一些 Objective-C 的东西!

打开 ViewController.m 并将它的内容替换成这样:

#import "ViewController.h"
#import <PassKit/PassKit.h> //1
 
@interface ViewController () //2
<UITableViewDelegate, UITableViewDataSource,
    PKAddPassesViewControllerDelegate>
{
    NSMutableArray *_passes; //3
}
@end
 
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
 
    //4
    if (![PKPassLibrary isPassLibraryAvailable]) {
        [[[UIAlertView alloc] initWithTitle:@"Error"
                               message:@"PassKit not available"
                                   delegate:nil
                          cancelButtonTitle:@"Pitty"
                          otherButtonTitles: nil] show];
        return;
    }
}
 
@end

这个代码非常基础并且只要 4 处需要解释的:

  1. 首先, 你导入 PassKit framework 头文件。
  2. 在 ViewController 的类扩展中, 你让它实现 UITableView 的数据源和代理协议, 最后,还有一个 PKAddPassesViewControllerDelegate 协议。
  3. 你声明了一个数组实例变量来保存所有 pass 文件包的列表。
  4. 最终在 viewDidLoad 里面, 如果 [PKPassLibrary isPassLibraryAvailable] 的结果是 NO, 那么你将显示一个消息, 来让用户知道他们的 Passbook 不可用。(你不属于这种情况的用户,但这是一个好机会来向你展示如何检测 Passbook 的可用性, 所以我把它放到了这里。)

我们的目标是检测这个 app 中是否带有 pass 包, 如果有的话, 显示他们的一个列表。当用户点击某个 pass 的文件名时, 这个应用也会显示一个漂亮的预览视图。

在 viewDidLoad 的最后, 添加如下代码:

    // 1 initialize objects
    _passes = [[NSMutableArray alloc] init];
 
    //2 load the passes from the resource folder
    NSString* resourcePath =
    [[NSBundle mainBundle] resourcePath];
 
    NSArray* passFiles = [[NSFileManager defaultManager]
                          contentsOfDirectoryAtPath:resourcePath
                          error:nil];
 
    //3 loop over the resource files
    for (NSString* passFile in passFiles) {
        if ( [passFile hasSuffix:@".pkpass"] ) {
            [_passes addObject: passFile];
        }
    }

这个简单的代码做的事情:

  1. 首先初始化了一个 _passes 数组。
  2. 将应用所有资源文件的列表添加到 passFiles 数组中。
  3. 检测 passFiles 数组中所有的文件名, 并且将所有扩展名为 .pkpass 的文件添加到 _passes 数组中。

非常简单! 你有了你应用中所有 pass 文件名的列表。 接下来, 将他们显示到表格中!

在 ViewController.m 中添加三个方法, 来让 TableView 运行起来:

#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _passes.count;
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell) cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
 
    NSString *object = _passes[indexPath.row];
    cell.textLabel.text = object;
    return cell;
}

很简单的代码 – 已可能已经很多次用到它了。 但是,
注意一下新的改变: 你可以通过 _passes.count 这种形式来访问 count 方法(不是属性)得到数组中元素的总数。 从数组(或字典中)中取出元素非常简单:

NSString *object = _passes[indexPath.row];

这些改变, 像是通过 . 表示法来调用方法, 在 iOS 6 之前就有了, 但他们仍然是新的。 其他关于数组的表示法就是全新的了, 你可以在第一章 “What’s New in Objective-C” 中了解到。

这就足够了 – 你可以运行这个项目, 并且没有任何警告和错误, 并且在屏幕上显示一个空的 TableView。

好了, 是时候包含一些 pass 文件到这个应用中了。 首先下载我为你准备好的: Passes.zip。解压这些文件,
将所有的 .pkpass 文件从 Passes 目录拷贝到你的 Xcode 项目根目录中。

注意: 确保这些文件添加到 PassesPreview target 中。默认情况下, Xcode 不会包含它们, 因为他们不是代码文件,也不是其他已知的 iOS 资源文件。

注意: 当你设计你自己的 pass 时,不要选中 “Copy items into …” 复选框。将 .pkpass 文件从 Pass 目录链接到 Xcode 项目中更加简单。当你更改代码或者替换图片后, 然后重新构建
pass 并且重启 Xcode 项目, 并且修改后的 pass 将会显示到屏幕上。

好了, 现在你在应用中得到了一些 pass, 点击 Run 你将会看到 pass 的列表:

最终, 你需要添加代码来在屏幕上显示选中的 pass, 将他们添加到 ViewController.m 中:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{   //1
    NSString* passName = _passes[indexPath.row];
    [self openPassWithName:passName];
}
 
-(void)openPassWithName:(NSString*)name
{
    //2
    NSString* passFile = [[[NSBundle mainBundle] resourcePath]
                          stringByAppendingPathComponent: name];
 
    //3
    NSData *passData = [NSData dataWithContentsOfFile:passFile];
 
    //4
    NSError* error = nil;
    PKPass *newPass = [[PKPass alloc] initWithData:passData
                                             error:&error];
    //5
    if (error!=nil) {
        [[[UIAlertView alloc] initWithTitle:@"Passes error"	
                                    message:[error  
                                         localizedDescription]
                                   delegate:nil
                          cancelButtonTitle:@"Ooops"
                          otherButtonTitles: nil] show];
        return;
    }
 
    //6
    PKAddPassesViewController *addController =
      [[PKAddPassesViewController alloc] initWithPass:newPass];
 
    addController.delegate = self;
    [self presentViewController:addController
                       animated:YES
                     completion:nil];
}

好了 – 代码稍微多了一点, 但是很好理解:

  1. 首先, 当表格的一行被选中后, 你调用 openPassWithName 方法。
  2. 在 openPassWithName 中, 你重新创建了 .pkpass 文件的完整路径。
  3. 然后你读取了 .pkpass 文件的内容,并放到一个 NSData 实例中。
  4. 然后你通过初始化方法 initWithData:error: 创建一个新的 PKPass 对象。
  5. 你通过 error 变量来检测一切的加载问题。
  6. 最后, 你创建一个新的 PKAddPassesViewController 实例 – 这是一个特殊的视图控制器, 接受一个 PKPass 对象作为参数, 并显示它。 将 delegate 属性赋值为 self, 并且模态的显示这个控制器到屏幕上。

你还需要一个方法 – 当用户关闭 pass 对话框时会被调用。 (你在这里不会做太多特别的操作,但为了你以后开发更复杂的功能,你最好知道还有这么一个选择。)

添加 PKAddPassesViewController 代理协议必须的一个方法:

#pragma mark - Pass controller delegate
 
-(void)addPassesViewControllerDidFinish: (PKAddPassesViewController*) controller
{
    //pass added
    [self dismissViewControllerAnimated:YES completion:nil];
}

现在你可以再次运行项目, 并且点击 FreeHug.pkpass 这行, 非常酷!你可以预览这个 pass, 并且还可以将他们导入到你的 iPhone 模拟器总的 Passbook 应用中。

这和你在 Mail 应用中打开一个 pass 附件时显示的对话框是完全一样的。注意, 如果你在 Passbook 中已经有了一个同样的 pass, 那么右上角的 Add 按钮将会被禁用。

成功了!

最后一步 – 在 viewDidLoad 的最后,添加如下代码:

    if ([_passes count]==1) {
        [self openPassWithName:[_passes objectAtIndex:0]];
    }

如果你只有一个 pass, 这样可以省去你再多点击一下!

现在, 现在你知道了关于如何创建一个优惠券的所有步骤, 并且你知道了怎样简单的测试和预览你的 pass。 这些技能的组合可以到达我们的下一个主题: 熟悉不同种类的 pass。

pass 的风格详解…

接下来,你将会看到关于不同风格 pass 的详细讲解。
这里有一个预览, 当他们导入到 Passbook 中看起来是怎样的 – 你可以看到每个类型都有一个小的触摸区域:

怎么创建不同的 pass 呢? 回到 FreeHug 优惠券的源代码中,并打开 pass.json。在顶层的字典中,你添加了一个键叫做 “coupon” – 这个键的值是一个包含字段定义的字典。
所有的 pass 都以同样的方式工作 – 你仅需要做的是将这个 key 的名称从 coupon 修改为你想要的风格名称!

Santa 应得的假期旅行

为了让这个部分的例子更加有趣, Vicki Wenderlich 计划了 Santa 的假期旅行, 并准备了他这个应得的假期中所有需要的 pass。通过他 iPhone 的 Passbook 中提前购买好的优惠券,VIP卡和机票, Santa 可以不需要在它的玩具袋里面携带任何多余的纸张。第一个例子当然是 Santa 非飞往 Tahiti 的机票。这是这个章节资源中的 BoardingPass.pkpass 里面的 pass.json 文件的内容。

{
  "formatVersion" : 1,
  "passTypeIdentifier" : "pass.com.iOS6-By-Tutorials",
  "serialNumber" : "AX6184HJDG",
  "teamIdentifier" : "ABC1230000",
  "barcode" : {
    "message" : "AXB739-StClaus-A280",
    "format" : "PKBarcodeFormatQR",
    "messageEncoding" : "iso-8859-1"
  },
  "organizationName" : "Reindeer Airways LLC",
  "description" : "Train Boarding Pass",
  "logoText" : "Reindeer Airways",
  "foregroundColor" : "rgb(255, 255, 255)",
  "backgroundColor" : "rgb(230, 72, 56)",
  "boardingPass" : {
    "headerFields" : [
      {
        "key" : "header",
        "value" : "1",
        "label" : "Seat"
      }
    ],
    "primaryFields" : [
      {
        "key" : "from",
        "value" : "NorthPole"
      },
      {
        "key" : "to",
        "value" : "Tahiti"
      }
    ],
    "secondaryFields" : [
      {
        "key" : "meal",
        "label" : "Meal",
        "value" : "Milk & Cookies"
      }
    ],
    "auxiliaryFields" : [
      {
        "key" : "departure",
        "label" : "Departure:",
        "dateStyle" : "PKDateStyleMedium",
        "timeStyle" : "PKDateStyleMedium",      
        "value" : "2012-12-27T10:35Z"
      }    
    ],
    "backFields" : [
      {
        "label" : "terms & conditions",
        "key" : "terms",
        "value" : "Ticket is non-refundable.  Please specify which type of cookie you want upon check-in: chocolate chip, peanut butter, or M&M sugar cookie."
      }
    ],
    "transitType" : "PKTransitTypeAir"
  }
}

正如你看到的,这个文件的结构,和你之前的那个基本上是相同的, 唯一不同的是这次用 boardingPass 替代了 coupon 键。还有另一个有趣的东西:在 boardingPass 字典中多了一个 “transitType”。这个字段是 boardingPass 特有的, 用来在 pass 的正面显示一个运送图标。

transitType, 根据你正在创建的 boardingPass 的类型, 你可以用这些预定义的常量之一:PKTransitTypeAir, PKTransitTypeTrain, PKTransitTypeBus, PKTransitTypeBoat, 和 PKTransitTypeGeneric。

这就是创建 coupon 和 boarding pass 的不同之处了! 上面的源代码的结果就是这个漂亮的登机牌:

你能在这个登机牌上面找到 Santa 的饮食偏好吗? 这样才能让服务员知道 – 他打算进行一个轻松的飞行!

登机牌样式的考虑

  • 注意到主字段使用了一个非常大的字体, 所以这里只能显示很少的文字。 比较长的目的地名称,像是 “San Francisco”, 将会被截断, 所以要考虑用目的地的代码来替代名称。最好是将城市的全名用作标签, 将代码用作值。
  • 登机牌不显示任何图片, 所以只需要 icon 和 logo 图片文件。
  • 一个好主意是,将头部字段用作机场登机口, 站台或者座位号

确保你为你的登机牌用了正确的 transit type! 下面是不同类型显示出来的图标样式:

这里还有一个所有你可以用到的字段的预览(当然,你不需要用到所有的字段; 这里给了你这些可用字段的样式和位置的预览):

当你设计新的 pass 的时候, 有一个点重要的是你必须注意的:不同样式的条形码占据了 pass 的正面不同大小的区域。PDF417 条形码是横向布局, 所以它可以很好的放在卡片的底部 – 为 pass 的字段留下更多空间(就像上面的例子)。 另外一方面 QR 条形码是正方形的, 它在垂直区域占据更多的空间。看一下同样的 pass 使用了 QR 条形码之后,是什么样子:

你可以很明显的看到, 字段之间的垂直距离变短了, 这样条形码仍然能够放到卡片上;因此: 总要将 pass 设计到正确类型的条形码上, 这样你能够得到正确的字段布局。

注意: 如果你要重用任何这部分章节中例子中的代码, 不要忘记修改 team 和 pass type 的标识 – 否则, 你的 pass 将不能被导入到 Passbook 中。

你是高级会员吗?

接下来, 让我们看看购物券。 这些非常流行, 并且已经被广泛使用了, 所以我打赌, 很多商家都想用 iPhone 的 pass 格式来数字化他们的购物券。这里有一个购物券的例子。 Santa 打算进行一些户外运动, 所以它买了 Tahiti 冲浪和潜水学校的高级套餐。它的 pass 还方便的向他展示了他在这个学校的账户里,还剩下多少预付费的课程。

正如你看到的, 购物券的文件布局在某些方面和优惠券很像,但是 header 的样式是不同的。 快速的看一下上面这个 pass 的源代码:

{
  "formatVersion" : 1,
  "passTypeIdentifier" : "pass.com.iOS6-By-Tutorials",
  "serialNumber" : "00012",
  "teamIdentifier" : "ABC1230000",
  "barcode" : {
    "message" : "q2eq3aaa",
    "format" : "PKBarcodeFormatPDF417",
    "messageEncoding" : "iso-8859-1"
  },
  "organizationName" : "Tahiti Surf & Snorkel",
  "description" : "Diving Lessons",
  "logoText" : "Tahiti Surf & Snorkel",
  "foregroundColor" : "rgb(255, 255, 255)",
  "backgroundColor" : "rgb(68, 200, 190)",
  "storeCard" : {
    "headerFields" : [
      {
      "key" : "lessons",
      "label" : "Lessons",
      "value" : "4"
      }
    ],
    "primaryFields" : [
      {
        "key" : "balance",
        "label" : "Class",
        "value" : "Premium"
      }
    ],
    "secondaryFields" : [
      {
        "key" : "memberName",
        "label" : "Name",
        "value" : "Mr. Claus"
      }
    ],
    "backFields" : [
      {
        "key" : "date",
        "label" : "Valid from:",
        "dateStyle" : "PKDateStyleMedium",      
        "timeStyle" : "PKDateStyleNone",      
        "value" : "2013-01-01T00:00Z"
      },
      {
        "key" : "date",
        "label" : "Valid until:",
        "dateStyle" : "PKDateStyleMedium",      
        "timeStyle" : "PKDateStyleNone",      
        "value" : "2013-01-03T00:00Z"
      },
      {
        "key" : "terms",
        "label" : "TERMS AND CONDITIONS",
        "value" : "Lessons must be used between 1/1/2013 and 3/1/2013.  Appointments for lessons must be made no less than 48 hours in advance.  Customer must be able to swim."
      }
    ]
  }
}

基本的东西, 你已经知道并且喜欢的, 都在这里, 所以我不再赘述了。 但是,在 backFields 字典中, 还有一些东西值得讨论。在合同条款里面你有两个日期字段和一个文本字段,所有这三个字段都包含日期。 这是一个好机会,可以用来将 pass 和 iPhone上面的日历应用连接起来!按下右下角的 “i” 按钮, 然后看一下:

Passbook 自动检测日期, 并把他们变成链接。 当他们被点击时, 会给用户展示一个动作菜单, 可以将他们带入日历中的某一天, 或者帮助他们在日历中为特定的一天或一个阶段创建一个事件。 棒极了!

购物券样式考虑

通常, 购物券中包含了客户在这个商店的余额。一个好主意是,将这些信息放到 pass 的主区域中。

Passbook 还可以展示出不同样式的货币格式, 所以如果你要显示余额, 考虑一下将他们展示成用户自己的货币,像是这样:

Passbook 甚至能够自动删除日元小数点之后的数字,因为日元不用小数! (1 是可能的最小值)。

为了修改货币余额的样式, 你需要一个数字值(不带双引号的数字) 并且有另外的键用来定义使用什么货币。 对日元来说, 代码如下:

{
  "key" : "amount",
  "label" : "Current credit store",
  "value" : 45.20,
  "currencyCode" : "JPY"
}

最后, 这里是购物券可以显示的所有字段类型:

它是一张门票, 它是一个 iPhone!

下一个 pass 类型是活动门票 – 它可以是音乐会门票, 电影票或者其他任何类型的你可以参与的门票!

回到 PassPreview 应用, 选择 ConcertTicket.pkpass。 一个漂亮的门票展现出来:

正如你看到的,Santa 没有很早的睡觉 – 它打算享受一下草裙舞表演和海边的夜晚。

当你提前计划好并将所有的门票放到口袋里非常容易 – 方便的存到你的 iPhone 里面吧!

活动门票有一些独特的特性。 如果你提供了一个背景图片文件, 它会拉伸,模糊, 并设置成整张卡片的背景。 如果你提供了一个预览图(thumbnail.png 和 thumbnail@2x.png), 图片会显示在右边。

注意, 因为背景图片会填满整个 pass 的正面, 你不再需要在你的 pass.json 文件中指定 “backgroundColor” 属性了。
除了点比较特殊,其他的地方你都已经知道了:

{
  "formatVersion" : 1,
  "passTypeIdentifier" : "pass.com.iOS6-By-Tutorials",
  "serialNumber" : "000024567",
  "teamIdentifier" : "ABC1230000",
  "barcode" : {
    "message" : "12946390566",
    "format" : "PKBarcodeFormatQR",
    "messageEncoding" : "iso-8859-1"
  },
  "organizationName" : "Tahiti Beach Hula Show",
  "description" : "Entrance ticket to Tahiti Beach Hula Show",
  "logoText" : "Tahiti Beach Hula Show",
  "foregroundColor" : "rgb(255, 255, 255)",
  "backgroundColor" : "rgb(242, 121, 55)",
  "eventTicket" : {
    "primaryFields" : [
      {
        "key" : "name",
        "value" : "Tahiti Beach Hula"
      }
    ],
    "secondaryFields" : [
      {
        "key" : "location",
        "label" : "Location",
        "value" : "Next to Maxi's Martini Bar"
      }
    ],
    "auxiliaryFields" : [
      {
        "key" : "date",
        "label" : "Event date",
        "dateStyle" : "PKDateStyleMedium",
        "timeStyle" : "PKDateStyleMedium",      
        "value" : "2012-12-29T19:00Z"
      }    
    ],
    "backFields" : [
      {
        "key" : "terms",
        "label" : "Terms & conditions",
        "value" : "This ticket may cause happiness and good cheer!  Free lei with ticket."
      }
    ]
  }
}

看过 pass.json 中的一些不同之处以后, 非常容易就能理解 pass.json 的源代码!再说一次,你可以用现在已知的任何方式来将信息包含在 pass 的正面和背面。

活动门票样式的考虑

  • 如果你提供了一个背景图片, 但没提供缩略图, 那么 Passbook 将也会在右边缩略图的区域显示背景图片。
  • 你可以禁用背景上的模糊效果 – 苹果用这种效果来突出文字信息。
  • 对于像是会议这类的活动门票, pass 正面缩略图的位置是放置参会者照片的好地方。

最终, 这里是活动门票正面所有可用的字段区域。

你一直都需要的 pass!

最后, 我们得到了你一直需要的 pass, 或者说是创建。 或者说是创建和得到。

最后一种类型的 pass 是通用 pass。 它有基本的样式,可以提供多种不同的文本域, 可以在正面显示一张图片, 并且, 你可以用它来实现所有种类的 pass, 其他四种 pass 不能很好适应的 – 优惠券, 登机牌, 购物券,或者活动门票。

现在, 我们发现 Santa 饮料的选择: 它想在海边喝一杯凉的马提尼, 享受吧, Santa!

打开 PassPreview 并点击 GenericPass.pkpass:

正如你看到的, 其他四种类型的样式都和这个不是很适应。 它给持有者提供 Maxi’s Martini Bar 的 VIP 休息室和每天一杯的马提尼。 它更像是酒吧的会员卡, 没有已存在的预定义样式。

但是这个通用的 pass 看起来非常棒! 是呀 – 你仍然机会去用我们已经讨论过的方式来自定义它! 在 pass.json 中没有什么特别的, 除了 pass 类型的键变成了 generic:

{
  "formatVersion" : 1,
  "passTypeIdentifier" : "pass.com.iOS6-By-Tutorials",
  "serialNumber" : "123456",
  "teamIdentifier" : "ABC1230000",
  "barcode" : {
    "message" : "7465-454-2234-1",
    "format" : "PKBarcodeFormatPDF417",
    "messageEncoding" : "iso-8859-1"
  },
  "organizationName" : "Maxi's Martini Bar",
  "description" : "Generic Pass Example",
  "logoText" : "Maxi's Martini Bar",
  "foregroundColor" : "rgb(33, 33, 33)",
  "backgroundColor" : "rgb(122, 230, 88)",
  "generic" : {
      "headerFields" : [
        {
          "key" : "header",
          "value" : "VIP"
        }
      ],
    "primaryFields" : [
      {
        "key" : "member",
        "value" : "Santa Claus"
      }
    ],
    "secondaryFields" : [
      {
        "key" : "faux1",
        "value" : ""
      },
      {
        "key" : "secondary1",
        "label" : "Rewards Earned",
        "value" : "Free Specialty Martini",
        "textAlignment" : "PKTextAlignmentRight"
      }
    ],
    "auxiliaryFields" : [
      {
        "key" : "faux2",
        "value" : ""
      },
      {
        "key" : "status",
        "value" : "Level 3",
        "label" : "Membership Status",
        "textAlignment" : "PKTextAlignmentRight"
      }
    ],
    "backFields" : [
      {
        "label" : "terms & conditions",
        "key" : "terms",
        "value" : "Must show proof of ID to claim rewards."
      }
    ]
  }
}

等一下。。 什么? (如果你没有发现任何问题, 那么你可能要重新再看一下这个代码了?)

这个字段是干什么用的?

      {
         "key" : "faux1",
         "value" : ""
      },

是的 – 是时候做一些技巧了! pass 正面那些字段的位置是预定义的, 所以, 它应该看起来是这样的: 第一个副标题显示在左边, 第二个副标题显示在右边, 第一个辅助标题显示, 等等。

那么,如果你想在第二个副标题的位置显示一块文本, 但是你不想在第一个副标题上显示任何信息呢?

哈哈! 定义一个 faux 类型的副标题, 并赋予空值并不带有任何 label(像是上面的代码), 非常棒!

另一个需要注意的地方是上面代码用到的 “textAlignment” 键。 使用这个键, 你可以告诉 Passbook 如何为一个文本域指定文字的对齐方式。 你可以从以下预定义的常量中选择一个:PKTextAlignmentLeft, PKTextAlignmentCenter, PKTextAlignmentRight, PKTextAlignmentJustified, and PKTextAlignmentNatural。

这里是你可以在通用 pass 中用到的所有可用字段的预览:

好了! 你基本完成了, 我希望这次学习是有意义的! 你知道了关于设计,制作和预览 pass 的一切信息。 OK! You’ve made it this far and I hope the trip was rewarding! 你已经学习到所有东西了!

接下来去哪?

你了解了很多关于如何创建 pass 的基础信息, 你知道了如何组成一个 pass, 有哪种类型的 pass 可用, 如何管理 pass 资源, 和更多内容!

如果你深入学习 iOS 6 by Tutorials 的话, 还有更多你可以学到的东西。在这些章节中你可以学到关于
Passbook 的:

  • 自动通过邮件和 web 发送 pass
  • 位置,时间相关的 pass
  • 更新 pass
  • 向 pass 的持有者发送通知
  • 还有更多…

抱歉!评论已关闭.