你好,tvOS 快速入门指南

本指南介绍如何创建你的第一个 Xamarin.tvOS 应用及其开发工具链。 它还将介绍用于将 UI 控件公开给代码 Xamarin 设计器,并说明如何构建、运行和测试 Xamarin.tvOS 应用程序。

警告

iOS Designer 在 Visual Studio 2019 版本 16.8 和 Visual Studio 2019 for Mac 版本 8.8 中已经弃用,并且已从 Visual Studio 2019 版本 16.9 和 Visual Studio for Mac 版本 8.9 中移除。 要生成 iOS 用户界面,建议直接在运行 Xcode 的 Interface Builder 的 Mac 上操作。 有关详细信息,请参阅用 Xcode 设计用户界面

Apple 已经发布了第 5 代 Apple TV,也就是 Apple TV 4K,它运行 tvOS 11。

Apple TV 平台向开发人员开放,让他们可以创建丰富、沉浸式的应用,并通过 Apple TV 的内置 App Store 发布。

如果你熟悉 Xamarin.iOS 开发,那么你应该会发现过渡到 tvOS 相当简单。 大多数 API 和功能是相同的,但许多常见 API 不可用(如 WebKit)。 此外,使用 Siri Remote 会带来一些设计挑战,而在基于触摸屏的 iOS 设备中没有这些挑战。

本指南将介绍如何在 Xamarin 应用中使用 tvOS。 有关 tvOS 的详细信息,请参阅 Apple 的为 Apple TV 4K 做好准备文档。

概述

借助 Xamarin.tvOS,可使用以 Swift(或 Objective-C)和 Xcode 进行开发时所用的相同 OS X 库和接口控件通过 C# 和 .NET 开发完全原生 Apple TV 应用。

此外,由于 Xamarin.tvOS 应用是通过 C# 和 .NET 编写的,因此可与 Xamarin.iOS、Xamarin.Android 和 Xamarin.Mac 应用共享常用后端代码;同时在每个平台上实现本机体验。

文本将说明如何构建一个基本的“Hello, tvOS”应用来计算按钮点击次数,进而介绍使用 Xamarin.tvOS 和 Visual Studio 创建 Apple TV 应用所需的关键概念:

示例应用运行

我们将介绍以下概念:

  • Visual Studio for Mac - 介绍 Visual Studio for Mac,以及如何使用它来创建 Xamarin.tvOS 应用程序。
  • Xamarin.tvOS 应用剖析 - Xamarin.tvOS 应用包含的内容。
  • 创建用户界面 - 如何使用 Xamarin Designer for iOS 创建用户界面。
  • 部署和测试 - 如何在 tvOS 模拟器和真实 tvOS 硬件中运行和测试应用。

在 Visual Studio for Mac 中启动新的 Xamarin.tvOS 应用

如上所述,我们将创建一个名为 Hello-tvOS 的 Apple TV 应用,用于向主屏幕添加一个按钮和标签。 点击此按钮后,标签会显示已点击次数。

若要开始,请执行以下操作:

  1. 启动 Visual Studio for Mac:

    Visual Studio for Mac

  2. 单击屏幕左上角的“新建解决方案...”链接,打开“新建项目”对话框。

  3. 选择“tvOS”>“应用”>“单视图应用”,然后单击“下一步”按钮:

    选择“单一视图应用”

  4. 输入 Hello, tvOS 作为应用名称,输入组织标识符,然后单击“下一步”按钮:

    输入“Hello, tvOS”

  5. 输入 Hello_tvOS 作为项目名称,然后单击“创建”按钮:

    输入“HellotvOS”

Visual Studio for Mac 会创建新的 Xamarin.tvOS 应用,并显示添加到此应用程序解决方案的默认文件:

默认文件视图

Visual Studio for Mac 按与 Visual Studio 相同的方式使用解决方案和项目。 解决方案是可包含一个或多个项目的容器;项目可包含应用程序、支持库和测试应用程序等。在本例中,Visual Studio for Mac 已经为你创建了一个解决方案和一个应用程序项目。

如果需要,可以创建一个或多个包含通用共享代码的代码库项目。 这些库项目可由应用程序项目使用,或者与其他 Xamarin.tvOS 应用项目共享(或者根据代码类型,与 Xamarin.iOS、Xamarin.Android 和 Xamarin.Mac 共享),就像你构建标准 .NET 应用程序一样。

Xamarin.tvOS 应用剖析

如果你熟悉 iOS 编程,你会发现这里有很多相似之处。 事实上,tvOS 9 是 iOS 9 的子集,因此这里的很多概念将会有所重叠。

让我们来看一下项目中的文件:

  • Main.cs – 此文件包含应用的主入口点。 启动应用时,其中会包含运行的首个类和方法。
  • AppDelegate.cs - 此文件包含的主应用程序类负责侦听操作系统中的事件。
  • Info.plist - 此文件包含应用程序属性,例如应用程序名称和图标等。
  • ViewController.cs - 这是表示主窗口并控制其生命周期的类。
  • ViewController.designer.cs - 此文件包含的 plumbing 代码有助于与主屏幕的用户界面进行集成。
  • Main.storyboard - 主窗口的 UI。 此文件可由 Xamarin Designer for iOS 进行创建和维护。

以下部分将简要介绍其中的一些文件。 之后我们将更详细地介绍它们,但现在了解它们的基础知识会很有帮助。

Main.cs

Main.cs 文件包含静态 Main 方法,该方法会创建一个新的 Xamarin.tvOS 应用实例,并传递将处理 OS 事件的类的名称(在本例中为 AppDelegate 类):

using UIKit;

namespace Hello_tvOS
{
    public class Application
    {
        // This is the main entry point of the application.
        static void Main (string[] args)
        {
            // if you want to use a different Application Delegate class from "AppDelegate"
            // you can specify it here.
            UIApplication.Main (args, null, "AppDelegate");
        }
    }
}

AppDelegate.cs

AppDelegate.cs 文件包含 AppDelegate 类,该类负责创建窗口和侦听 OS 事件:

using Foundation;
using UIKit;

namespace Hello_tvOS
{
    // The UIApplicationDelegate for the application. This class is responsible for launching the
    // User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
    [Register ("AppDelegate")]
    public class AppDelegate : UIApplicationDelegate
    {
        // class-level declarations

        public override UIWindow Window {
            get;
            set;
        }

        public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
        {
            // Override point for customization after application launch.
            // If not required for your application you can safely delete this method

            return true;
        }

        public override void OnResignActivation (UIApplication application)
        {
            // Invoked when the application is about to move from active to inactive state.
            // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
            // or when the user quits the application and it begins the transition to the background state.
            // Games should use this method to pause the game.
        }

        public override void DidEnterBackground (UIApplication application)
        {
            // Use this method to release shared resources, save user data, invalidate timers and store the application state.
            // If your application supports background execution this method is called instead of WillTerminate when the user quits.
        }

        public override void WillEnterForeground (UIApplication application)
        {
            // Called as part of the transition from background to active state.
            // Here you can undo many of the changes made on entering the background.
        }

        public override void OnActivated (UIApplication application)
        {
            // Restart any tasks that were paused (or not yet started) while the application was inactive.
            // If the application was previously in the background, optionally refresh the user interface.
        }

        public override void WillTerminate (UIApplication application)
        {
            // Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
        }
    }
}

除非你之前构建过 iOS 应用程序,否则你可能不熟悉此代码,但它非常地简单。 让我们查看重要的行。

首先,让我们看一下类级别变量声明:

public override UIWindow Window {
            get;
            set;
        }

Window 属性提供对主窗口的访问。 tvOS 使用所谓的模型视图控制器 (MVC) 模式。 通常,对于每个创建的窗口(以及窗口内许多其他项),存在一个负责窗口生命周期的控制器,例如显示窗口、向窗口添加新视图(控件)等。

接下来,我们有 FinishedLaunching 方法。 此方法在应用程序实例化之后运行,它实际上负责创建应用程序窗口并启动在其中显示视图的过程。 由于我们的应用使用情节提要来定义其 UI,因此这里不需要任何其他代码。

模板中提供了其他很多方法,例如 DidEnterBackgroundWillEnterForeground。 如果应用中没有使用应用程序事件,则可以安全地删除这些事件。

ViewController.cs

ViewController 类是主窗口的控制器。 这意味着它负责主窗口的生命周期。 稍后我们将详细探讨这一点,现在让我们快速了解一下:

using System;
using Foundation;
using UIKit;

namespace Hello_tvOS
{
    public partial class ViewController : UIViewController
    {
        public ViewController (IntPtr handle) : base (handle)
        {
        }

        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            // Perform any additional setup after loading the view, typically from a nib.
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
    }
}

ViewController.Designer.cs

主窗口类的设计器文件现在为空,但在我们使用 iOS 设计器创建用户界面时,Visual Studio for Mac 会自动填充它:

using Foundation;

namespace HellotvOS
{
    [Register ("ViewController")]
    partial class ViewController
    {
        void ReleaseDesignerOutlets ()
        {
        }
    }
}

我们通常不担心设计器文件,因为它们由 Visual Studio for Mac 自动管理,并提供必需的 pluming 代码,通过该代码可访问已添加到应用程序中任意窗口或视图的控件。

现在我们已经创建了 Xamarin.tvOS 应用,并对其组件有了基本了解,接下来让我们看看如何创建 UI。

创建用户界面

你无需使用 Xamarin Designer for iOS 来为 Xamarin.tvOS 应用创建用户界面,可直接通过 C# 代码创建 UI,但这超出了本文的讨论范围。 为简单起见,在本教程的其余部分,我们将使用 iOS 设计器创建 UI。

若要开始创建 UI,请在解决方案资源管理器中双击 Main.storyboard 文件,以在 iOS 设计器中打开它进行编辑:

解决方案资源管理器中的 Main.storyboard 文件

这应该会启动设计器,如下所示:

Designer

若要详细了解 iOS 设计器及其工作原理,请参阅 Xamarin Designer for iOS 简介指南。

我们现在向 Xamarin.tvOS 应用的设计图面添加控件。

请执行以下操作:

  1. 找到工具箱,它应该在设计图面右侧:

    工具箱

    如果在此处找不到它,请浏览到“视图”>“板”>“工具箱”来查看它。

  2. 将标签从工具箱拖动到设计图面:

    从工具箱拖动标签

  3. 单击“属性”板中的 Title 属性,将按钮的标题更改为 Hello, tvOS,然后将字号设置为 128:

    将标题设置为“Hello, tvOS”并将字号设置为 128

  4. 调整标签大小,使所有字词可见,并将其居中置于窗口顶部附近:

    调整标签大小并使其居中

  5. 标签现在需要限制到其所在位置,以便无论屏幕大小如何, 它都按预期显示。 为此,请单击标签,直到出现 T 形图柄:

    T 形图柄

  6. 若要在水平方向限制标签,请选择中间的方块,并将其拖动到垂直虚线:

    选择中心方块

    标签应变为橙色。

  7. 选择标签顶部的 T 图柄,然后将其拖到窗口的上边缘:

    将图柄拖到窗口的上边缘

  8. 接下来,单击宽度,然后单击高度骨形图柄,如下所示:

    宽度和高度骨形图柄

    单击每个骨形图柄时,分别选择宽度和高度来设置固定尺寸。

  9. 完成后,约束应类似于“属性”板的“布局”选项卡中的内容:

    示例约束

  10. 从工具箱拖动某个按钮,将其放到标签下方。

  11. 单击“属性”板中的 Title 属性,将按钮的标题更改为 Click Me

    将按钮标题更改为“单击我”

  12. 重复上述步骤 5-8 来限制 tvOS 窗口中的按钮。 但是,将 T 形图柄拖到标签底部,而不是将它拖动到窗口顶部(参见步骤 #7 中):

    限制选择

  13. 将另一个标签拖到按钮下,将其调整为与第一个标签相同的宽度,并将“对齐”设置为“居中”:

    将另一个标签拖到按钮下,将其调整为与第一个标签相同的宽度,并将“对齐”设置为“居中”

  14. 与第一个标签和按钮一样,将此标签设置为居中,并将其固定到位置和大小:

    将标签固定到位并设置其小

  15. 保存对用户界面的更改。

在调整控件大小和移动控件时,你应该会注意到,设计器会根据 Apple TV 人机界面指南提供有用贴靠提示。 这些指南可帮助你创建外观和风格为 Apple TV 用户所熟悉的高质量应用程序。

如果查看“文档大纲”部分,请注意构成用户界面的元素的布局和层次结构是如何显示的:

“文档大纲”部分

从这里,你可选择要进行编辑的项,或者根据需要进行拖动来对 UI 元素重新排序。 例如,如果某个 UI 元素被另一元素覆盖,你可将其拖动到列表底部,使其成为窗口上最顶层的项。

现在我们已经创建了用户界面,接下来需要公开 UI 项,以便 Xamarin.tvOS 可访问它们并在 C# 代码中与之交互。

访问代码隐藏文件中的控件

主要有两种方法来从代码访问你在 iOS 设计器中添加的控件:

  • 在控件上创建事件处理程序。
  • 为控件命名,以便稍后可以引用它。

添加其中任一项时,将更新 ViewController.designer.cs 中的分部类以反映更改。 这样,便可以访问视图控制器中的控件。

创建事件处理程序

在此示例应用程序中,单击按钮时,我们希望发生事件,因此需要将事件处理程序添加到按钮上的特定事件。 若要设置此项,请执行以下操作:

  1. 在 Xamarin iOS 设计器中,选择视图控制器上的按钮。

  2. 在“属性”板中选择“事件”选项卡:

    “事件”选项卡

  3. 找到 TouchUpInside 事件,并将它提供一个名为 Clicked 的事件处理程序:

    TouchUpInside 事件

  4. 按 Enter 时,会打开 ViewController.cs 文件,在代码中建议事件处理程序的位置。 使用键盘上的箭头键设置位置:

    设置位置

  5. 这将创建分部方法,如下所示:

    分部方法

现在我们已准备好开始添加一些代码,以使按钮正常运行。

对控件命名

单击按钮时,标签应根据单击次数进行更新。 为此,我们需要访问代码中的标签。 这是通过为其命名来完成的。 请执行以下操作:

  1. 打开情节提要,然后选择视图控制器底部的标签。

  2. 在“属性”板中选择“小组件”选项卡:

    选择“小组件”选项卡

  3. 在“标识”>“名称”下,添加 ClickedLabel

    设置 ClickedLabel

我们现在已准备好开始更新标签!

如何访问控件

如果在解决方案资源管理器中选择 ViewController.designer.cs,你将能够看到 ClickedLabel 标签和 Clicked 事件处理程序是如何映射到 C# 中的输出口和操作的:

输出口和操作

你可能还会注意到,ViewController.designer.cs 是一个分部类,因此 Visual Studio for Mac 不必修改 ViewController.cs,该项将覆盖我们对类所做的任何更改。

通过这样公开 UI 元素,你可以在视图控制器中访问它们。

通常,你永远都不需要自行打开 ViewController.designer.cs,这里提供它只是为了进行介绍。

编写代码

创建用户已经界面,并且其 UI 元素已通过输出口和操作公开给代码,我们最终准备好了编写代码来赋予程序功能。

在我们的示例应中用,每次单击第一个按钮时,我们都会更新标签,显示此按钮的点击次数。 为了完成此操作,请在 Solution Pad 中双击 ViewController.cs 文件来打开它进行编辑:

Solution Pad

首先,需要在 ViewController 类中创建类级别变量来跟踪已发生的点击数。 编辑类定义,使其类似于如下所示:

using System;
using Foundation;
using UIKit;

namespace Hello_tvOS
{
    public partial class ViewController : UIViewController
    {
        private int numberOfTimesClicked = 0;
        ...

接下来,在同一个类 (ViewController) 中,需要替代 ViewDidLoad 方法和某些代码,从而设置标签的初始消息:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Set the initial value for the label
    ClickedLabel.Text = "Button has not been clicked yet.";
}

需要使用 ViewDidLoad 而不是 Initialize 等其他方法,因为 OS 从 .storyboard 文件加载和实例化用户界面后会调用 ViewDidLoad 如果我们尝试在 .storyboard 文件完全加载和实例化之前尝试访问标签控件,我们会遇到 NullReferenceException 错误,因为此时标签控件尚未创建。

下一步,需要添加代码以对用户点击按钮作出响应。 将以下内容添加到我们创建的分部类:

partial void Clicked (UIButton sender)
{
    ClickedLabel.Text = string.Format("The button has been clicked {0} time{1}.", ++numberOfTimesClicked, (numberOfTimesClicked

每当用户单击按钮时,都会调用此代码。

现在一切已就绪,我们准备好生成和测试 Xamarin.tvOS 应用程序。

测试应用程序

现在即可生成并运行应用程序,确保其可按预期运行。 可在一个步骤中同时生成和运行应用程序,或者只生成应用而不运行。

每次生成应用程序时,都可以选择所需的生成类型:

  • 调试 - 调试版本会编译到 ``(应用程序)文件,其中有额外的元数据,让我们能够在应用程序运行时调试发生的情况。
  • 发布 - 发布版本也会创建 `` 文件,但其中不包含调试调试信息,因此其大小更小,执行速度更快。

可以从 Visual Studio for Mac 屏幕左上角的“配置选择器”中选择生成的类型:

选择生成类型

生成应用程序

在本例中,我们只需要调试版本,因此让请确保已选择“调试”。 首先,按 ⌘B 或在“生成”菜单中选择“生成所有”,生成应用程序。

如果没有任何错误,你将在 Visual Studio for Mac 状态栏中看到“已成功生成”消息。 如果出现错误,请检查项目,并确定是否已正确执行步骤。 首先请确认代码(Xcode 和 Visual Studio for Mac 中的代码)与本教程中的代码匹配。

运行应用程序

若要运行应用程序,有三个选项可用:

  • ⌘+Enter
  • 在“运行”菜单中,选择“调试”
  • 单击 Visual Studio for Mac 工具栏中的“播放”按钮(位于“解决方案资源管理器”上方)。

应用程序会生成(如果尚未生成)并在调试模式下启动,tvOS 模拟器将启动,并且应用将启动并显示主界面窗口:

示例应用主屏幕

在“硬件”菜单中选择“显示 Apple TV Remote”,这样可以控制模拟器。

选择“显示 Apple TV Remote”

远程使用模拟器时,如果单击按钮几次,标签应更新显示计数:

具有更新计数的标签

祝贺你! 我们在这里介绍了很多内容,但是如果你从头到尾都遵循本教程,那么你现在应该对 Xamarin.tvOS 应用的组件以及用于创建它们的工具有了扎实的了解。

接下来怎么做?

由于用户与界面之间断开连接(它在房间的另一边,不在用户的手里),以及 tvOS 对应用大小和存储的限制,开发 Apple TV 应用存在一些挑战。

因此,我们强烈建议在进入 Xamarin.tvOS 应用的设计之前,先阅读以下文档:

  • tvOS 9 简介–本文介绍 tvOS 9 为 Xamarin.tvOS 开发人员提供的所有新增和修改的 API 和功能。
  • 使用导航和焦点 - Xamarin.tvOS 应用的用户不会向使用 iOS 那样直接与应用界面进行交互(在 iOS 上,用户点击设备屏幕上的图像),而是使用 Siri Remote 从房间的另一端间接进行交互。 本文介绍焦点的概念,说明如何在 Xamarin.tvOS 应用的用户界面中使用它来处理导航。
  • Siri Remote 和蓝牙控制器 - 用户与 Apple TV 和 Xamarin.tvOS 应用交互的主要方式是通过随附的 Siri Remote。 如果应用是一个游戏,你也可选择在应用中内置对第三方 Made For iOS (MFI) 蓝牙游戏控制器的支持。 本文介绍如何在 Xamarin.tvOS 应用中支持新的 Siri Remote 和蓝牙游戏控制器。
  • 资源和数据存储 - 与 iOS 设备不同,新的 Apple TV 不提供针对 tvOS 应用的持久本地存储。 因此,如果 Xamarin.tvOS 应用需要保留信息(例如用户首选项),它必须存储并从 iCloud 检索该数据。 本文介绍如何在 Xamarin.tvOS 应用中使用资源和持久数据存储。
  • 使用图标和图像 - 创建迷人的图标和图像是为 Apple TV 应用开发沉浸式用户体验的关键部分。 本指南将介绍创建和添加 Xamarin.tvOS 应用所需的图形资产而需要的步骤。
  • 用户界面–常规用户体验 (UX) 覆盖范围,包括用户界面(UI)控件,请在使用 Xamarin.tvOS 时使用 Xcode 的 Interface Builder 和 UX 设计原则。
  • 部署和测试 - 本部分介绍用于测试应用以及如何分发应用的主题。 本部分的主题包括用于调试的工具、如何部署给测试员以及如何将应用程序发布到 Apple TV App Store 等内容。

如果在使用 Xamarin.tvOS 时遇到任何问题,请参阅我们的故障排除文档,获取有关已知问题和解决方案的列表。

总结

通过本文,可快速开始通过创建简单的“Hello, tvOS”应用,使用 Visual Studio for Mac 创建适用于 tvOS 的应用。 它介绍了 tvOS 设备预配、界面创建、tvOS 编码以及在 tvOS 模拟器上进行测试的基础知识。