1

我正在尝试构建一个包含本机和 TVML 内容的 tvOS 应用程序。理想情况下,我想在容器视图中呈现 TVML 内容;如果做不到这一点,如果我可以在 TVML 内容上以模态方式呈现本机 UIViewController,我会很高兴。到目前为止,我在这两种方法中都失败了。

到目前为止,我最接近的是模态呈现,但我的问题是模态视图控制器总是在 TVML 内容后面显得模糊。代码如下(它基于 Ray Wenderlich 网站的片段):-

// URL and context
NSString *baseURL = @"http://localhost:9001/";
NSString *bootURL = [NSString stringWithFormat:@"%@js/application.js", baseURL];
TVApplicationControllerContext *context = [[TVApplicationControllerContext alloc] init];
context.javaScriptApplicationURL = [NSURL URLWithString:bootURL];
context.launchOptions = @{@"BASEURL": baseURL};

// only seems to work with a full-screen window
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

// instantiate TVApplicationController
self.tvAppController = [[TVApplicationController alloc] initWithContext:context window:window delegate:self];

// get a simple test view controller from storyboard and present modally
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"testVC"];
[self.tvAppController.navigationController pushViewController:controller animated:YES];

这里有几件事我不明白。

首先,我需要分配一个全新的全尺寸窗口才能正常工作。尝试使用现有self.view.window的 或尝试使用较小的窗口都失败了,即没有显示 TVML。所以我假设新窗口正在以相当高的级别添加到视图层次结构中并排在其他所有内容之前?这似乎非常有限 - 我错过了什么吗?

其次,Apple 的文档建议可以省略该窗口,以便更好地控制 TVML 视图的显示方式:-

如果没有提供窗口,导航控制器可以在二进制应用程序中手动显示和关闭。

但是,我不能从那句话中得到什么实际意义。如果我将 window 参数设置为nil,则 TVML 内容根本不会出现。他们希望我如何“呈现”只读导航控制器?(我尝试将它嵌入到容器视图中,但出现异常。)

我已经尝试了我能想到的一切。有没有人设法让混合的 TVML 和 tvOS 原生视图同时工作?

4

2 回答 2

4

如果您想在原生视图上显示 TVML,请在TVAppController没有窗口的情况下创建并像这样显示它。

// your viewController

- (IBAction)buttonAction:(id)sender {
    TVApplicationControllerContext *context = ...;
    self.tvAppController = [[TVApplicationController alloc] initWithContext:context window:nil delegate:self];

    [self presentViewController:self.tvAppController.navigationController animated:YES completion:nil];
}
于 2015-10-26T03:11:41.997 回答
0

当您传递self.window到 时[TVApplicationController alloc] initWithContext:context window:self.window delegate:self],TVApplicationController 会自动将其设置navigationControllerrootViewController提供的self.window。这意味着self.tvAppController.navigationController它将成为您的应用程序的初始控制器。但是您可以随时将在您的 xcode 应用程序中实例化的控制器推送到self.tvAppController.navigationController任何时候。但是,您的代码在 UIViewController 上方显示 TVApplicationController 的原因是因为 TVApplicationController 需要更多时间来初始化,然后才用于 UIViewController,这会导致异步问题。您可以使用简单的 dispatch_after 来验证这一点。如果您希望 UIViewController 成为应用程序的初始控制器,则必须传递nil而不是传递self.windowinitWithContext:window:delegate:然后呈现 TVApplicationController[self.window.rootViewController presentViewController:self.appController.navigationController animated:YES completion:nil];当然,在这一点上,你可以做同样的事情,而不是模态显示 TVApplicationController initWithContext:window:delegate:,也就是[self.window setRootViewController:self.appController.navigationController];继续将 UIViewControllers 推送到self.appController.navigationController,但对我来说似乎不太灵活。考虑这个例子:

...
self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
[self.window makeKeyAndVisible];

self.appController = [[TVApplicationController alloc] initWithContext:appControllerContext window:nil delegate:self];

UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"testVC"];

[self.window setRootViewController:viewController];
//Note that you don't have to init window and UIViewController if you have your storyboard set as Main in info.plist and the storyboard has an initial controller selected. In this case, you'll just need the following code:

[self.window.rootViewController presentViewController:self.appController.navigationController animated:YES completion:nil];
于 2015-10-26T02:17:19.453 回答