為 Apple TV 開(kāi)發(fā) tvOS App Part 1

作者:Jameson Quave,原文鏈接,原文日期:2015/09/09
譯者:ray16897188;校對(duì):numbbbbb;定稿:shanks

教程結(jié)束時(shí),我們會(huì)做出這樣一個(gè)應(yīng)用:


你更喜歡哪個(gè)藝術(shù)家?
你更喜歡哪個(gè)藝術(shù)家?

開(kāi)始

在我們開(kāi)始之前你需要安裝 Xcode 7.1 beta 版,可以從這里下載:下載Xcode 7.1 Beta
注意:你需要準(zhǔn)備一個(gè) Apple 開(kāi)發(fā)者賬號(hào),而且由于目前是預(yù)覽版,以后代碼也可能發(fā)生變化。

安裝的時(shí)候要注意,如果你重命名 Xcode 7.1 應(yīng)用,會(huì)遇到一個(gè)已知 bug。一定有人會(huì)這么做,所以提前說(shuō)明……別這么做,否則你的 tvOS 模擬器會(huì)崩潰。

還要注意,如果系統(tǒng)是 Yosemite,性能會(huì)有限制。推薦用 OSX 10.11 El Capitan 或更新的系統(tǒng)。El Capitan beta 可以在這里下載。

下面我們來(lái)學(xué)習(xí)一些 tvOS 的名詞。

TVMLKit

TVMLKit 是 Apple 設(shè)計(jì)的一個(gè)新框架,能在使用 Swift 或 Objective-C 實(shí)現(xiàn)應(yīng)用邏輯的同時(shí)使用 Javascript 和 XML 開(kāi)發(fā)更炫酷的用戶界面。

TVML

TVML 是"TV Markup Language"(TV 標(biāo)記語(yǔ)言)的縮寫(xiě),基本上是一些 XML 語(yǔ)句,用于實(shí)現(xiàn)基于C/S(client-server,客戶端-服務(wù)端)架構(gòu)的 tvOS 應(yīng)用布局。布局界面時(shí),我們會(huì)用到一些 Apple 提供的 TVML 模板創(chuàng)建我們的 UI,然后用 TVJS 寫(xiě)交互腳本。

TVJS

我能告訴你的是,TVJS 就是你(可能已經(jīng))熟悉的 JavaScript。

Hello World

我們從一個(gè)基本的 hello world 程序開(kāi)始。就 Apple TV 而言,我們可以只把"Hello World"輸出到主機(jī)上。這也許是個(gè)不錯(cuò)的開(kāi)始,但更好的選擇是使用 Apple TV 的一些 TVMLKit 元素在屏幕上創(chuàng)建一個(gè)模板。

首先,打開(kāi) Xcode 7.1 并創(chuàng)建一個(gè)新項(xiàng)目。你可以看到一個(gè)模板列表,我們?cè)谧髠?cè)選擇CHANGE tvOS,然后再選Single View Application模板。

這樣就會(huì)根據(jù) tvOS 模板創(chuàng)建一些默認(rèn)文件和一個(gè)簡(jiǎn)單的 Swift 入口點(diǎn),對(duì)一會(huì)兒創(chuàng)建 UI 很有幫助。

建立 TVJS 主文件

在 C/S 架構(gòu)的 tvOS 應(yīng)用中,服務(wù)端本質(zhì)上就是 TVML 和 JavaScript 文件以及和它們相關(guān)的所有數(shù)據(jù)。JavaScript 文件會(huì)裝載 TVML 并把頁(yè)面(page)放入視圖棧中。可以從另一個(gè)角度理解:JavaScript 文件就像 TVML 文件的路由器或是控制器(controller),而 TVML 文件本質(zhì)上是若干視圖(views)。

拉開(kāi)序幕

首先我們要修改應(yīng)用的AppDelegate.swift文件。第一步是讓我們的應(yīng)用遵循TVApplicationControllerDelegate協(xié)議。該協(xié)議定義在 TVMLKit 框架中,所以需要導(dǎo)入它。更新AppDelegate.swift文件,如下所示:

import TVMLKit

class AppDelegate: UIResponder,
UIApplicationDelegate,
TVApplicationControllerDelegate {

....

此協(xié)議包含四個(gè) tvOS 實(shí)現(xiàn)AppDelegate后會(huì)調(diào)用的函數(shù),用于給我們的應(yīng)用發(fā)送 tvOS 生命周期通知?,F(xiàn)在我們無(wú)需操心這些,但在后面的教程中我們會(huì)對(duì)它們進(jìn)行深入研究。目前只要像上面的代碼那樣把協(xié)議加進(jìn)去就夠了。

下一步,我們要添加一些代碼,讓 JS 文件起作用。由于是 beta 版,我們還需要自己完成這些工作。我相信在 Xcode 的后續(xù)版本中這一步會(huì)變成一個(gè)模板。

在程序里didFinishLaunchingWithOptions這個(gè)函數(shù)中我們要完成一些步驟。它們對(duì)所有應(yīng)用來(lái)說(shuō)都是一樣的,所以你可以直接復(fù)制這段代碼:

// 在一個(gè)可選屬性中保存對(duì) appController 的引用
var appController: TVApplicationController?
 
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  self.window = UIWindow(frame:UIScreen.mainScreen().bounds)
 
  let appControllerContext = TVApplicationControllerContext()
 
  let jsFilePath = NSURL(string: "http://localhost:8000/main.js")
  let javascriptURL = jsFilePath!
 
  appControllerContext.javaScriptApplicationURL = javascriptURL
  if let options = launchOptions
  {
    for (kind, value) in options
    {
      if let kindStr = kind as? String
      {
        appControllerContext.launchOptions[kindStr] = value
      }
    }
  }
 
  self.appController = TVApplicationController(context: appControllerContext, window: self.window, delegate: self)
 
  return true
}

簡(jiǎn)單說(shuō)說(shuō)這段代碼干了什么:它拿到了一個(gè)TVApplicationControllerContext引用,這個(gè)Context只是為我們的AppDelegate類(lèi)提供了一些啟動(dòng)數(shù)據(jù),然后給了我們一個(gè)能調(diào)整和修改啟動(dòng)過(guò)程的接口。接著把 URL 傳給待會(huì)兒要運(yùn)行的main.js文件,并將appController的路徑設(shè)置成這個(gè) URL。

現(xiàn)在就要添加我們的 JavaScript 文件了,點(diǎn)擊 File > New,然后在 iOS tab 下面選擇 Other > Empty file。將這個(gè)文件命名為main.js。

用同樣方法創(chuàng)建一個(gè)hello.tvml文件。

main.js文件中添加一些簡(jiǎn)單的 JavaScript 代碼,用來(lái)裝載hello.tvml文件:

function getDocument(url) {
  var templateXHR = new XMLHttpRequest();
  templateXHR.responseType = "document";
  templateXHR.addEventListener("load", function() {pushDoc(templateXHR.responseXML);}, false);
  templateXHR.open("GET", url, true);
  templateXHR.send();
  return templateXHR;
}
 
function pushDoc(document) {
  navigationDocument.pushDocument(document);
}
 
App.onLaunch = function(options) {
  var templateURL = 'http://localhost:8000/hello.tvml';
  getDocument(templateURL);
}
 
App.onExit = function() {
  console.log('App finished');
}

現(xiàn)在在hello.tvml文件中添加:

<document>
  <alertTemplate>
      <title>Hello tvOS!</title>
  </alertTemplate>
</document>

TVML 文件是 UI 的實(shí)際內(nèi)容。文檔(document)必須用模板編寫(xiě),否則現(xiàn)在的代碼運(yùn)行時(shí)會(huì)崩潰。這個(gè) TVML 文件只是包含了一個(gè)簡(jiǎn)單的模板和一個(gè)單元素的標(biāo)題。

在編寫(xiě)這些代碼時(shí)我發(fā)現(xiàn)一個(gè)問(wèn)題:本地?zé)o法引用這些文件,文件必須放在一個(gè) web 服務(wù)器上。所以最簡(jiǎn)單的解決方案是找到你剛創(chuàng)建 TVML 和 JS 文件的位置,并在命令行中敲進(jìn)如下指令:

啟動(dòng)服務(wù)端

python -m SimpleHTTPServer 8000

這條指令用 Mac OS 內(nèi)建的 python 解釋器開(kāi)啟了一個(gè)端口號(hào)為 8000 的 web 服務(wù)器,可以用它來(lái)托管本地文件。如果你直接復(fù)制了上面的代碼,按一下 Xcode 的 play 鍵就能啟動(dòng) tvOS 模擬器。還有一個(gè)要注意的事情:這是一個(gè)不夠安全的 HTTP 請(qǐng)求,在 iOS 9 中會(huì)被默認(rèn)的應(yīng)用傳輸安全機(jī)制攔截。為了能夠按之前的方法來(lái)使用本地主機(jī),我們需要在Info.plist文件中添加一個(gè)key

允許直接加載(Allows Arbitrary Loads)

選擇Info.plist文件然后按加號(hào)(+)來(lái)創(chuàng)建一條新記錄。在列表中選擇"App Transport Security Settings"并按回車(chē)。這會(huì)在字典中創(chuàng)建一個(gè)新行,展開(kāi)它,在這行上按加號(hào)(+)添加一個(gè)子行。接著選中"Allows Arbitrary Loads"并將其設(shè)為true。都設(shè)好了之后我們就能用模擬器運(yùn)行應(yīng)用了。

添加按鈕

在本例中你看到的實(shí)際上是一個(gè)被 Apple 稱作alertTemplate的模板。你還能嵌入一些基本控件,比如在模板中添加文字和按鈕。試著添加一些按鈕吧:

<document>
    <alertTemplate>
        <title>Hello tvOS!</title>
        <button>
            <text>A Button</text>
        </button>
        <button>
            <text>A Second Button</text>
        </button>
    </alertTemplate>
</document>

這里我們只加了子按鈕(child button)元素,每個(gè)子按鈕都有它自己的子文本(child text)元素。這段代碼在 tvOS 模擬器上全屏顯示alert和兩個(gè)按鈕。如果你自學(xué)能力很強(qiáng),蘋(píng)果的官方文檔中列出了你能使用的所有模板和控件。否則的話請(qǐng)跟緊我,訂閱我的博客,之后我會(huì)教你開(kāi)發(fā)一個(gè)完整的應(yīng)用。

繼續(xù)學(xué)習(xí)

學(xué)習(xí)本教程的第二部分:為應(yīng)用添加交互事件。

如果你想在新文章發(fā)布時(shí)收到通知,請(qǐng)訂閱我的 newsletter

剛開(kāi)始學(xué)習(xí)難免會(huì)遇到問(wèn)題,如果你卡住了,別猶豫,在 twitter 上聯(lián)系我@jquave。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift版本點(diǎn)擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 26,103評(píng)論 7 249
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,318評(píng)論 4 61
  • 基貝拉,基貝拉,我從沒(méi)想過(guò)我是來(lái)基貝拉?;惱降资悄睦铮谖铱吹窖矍暗囊磺械臅r(shí)候,我偷偷拿出藏了一路的手機(jī)又再次...
    VentureHacker閱讀 2,276評(píng)論 12 8
  • 對(duì)江南古鎮(zhèn)的印象,因去過(guò)七寶、朱家角、西塘、周莊,覺(jué)得無(wú)非是小橋連石道、流水繞民房。若以此而論,這些古鎮(zhèn)倒也算是值...
    徽山人閱讀 455評(píng)論 1 3

友情鏈接更多精彩內(nèi)容