【问题标题】:tvOS: How to get TVApplicationController to play nice with native view controllers?tvOS:如何让 TVApplicationController 与本机视图控制器配合使用?
【发布时间】:2015-10-20 19:53:08
【问题描述】:

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

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

// 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 视图的显示方式:-

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

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

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

【问题讨论】:

    标签: view window tvos tvapplicationcontroller


    【解决方案1】:

    如果您想在原生视图上显示 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];
    }
    

    【讨论】:

    • 未加载 http 路径链接:警告:尝试在其视图上显示不在窗口层次结构中的 <_tvappnavigationcontroller:>!
    • @bluedome 虽然您的代码将 TVML 推送到本机视图控制器之上(而不是相反,就像我的代码那样),但它实际上有很大帮助。通过异步而不是在viewDidLoad 中延迟创建TVApplicationController,我现在可以成功地将本机控制器推送到TVML 之上,这可能有助于解决我的问题。谢谢!
    • 这个解决方案解决了我试图通过原生 UIVIewController 呈现 TVML 模板的问题。
    • @Pankaj Bhardwaj 在viewWillAppear: 之后致电presentViewController:animated:completion:,请。
    【解决方案2】:

    当您将self.window 传递给[TVApplicationController alloc] initWithContext:context window:self.window delegate:self] 时,TVApplicationController 会自动将其navigationController 设置为提供的rootViewControllerself.window。这意味着self.tvAppController.navigationController 将成为您应用程序的初始控制器。但是您可以随时将在您的 xcode 应用程序中实例化的控制器推送到self.tvAppController.navigationController。但是,您的代码将 TVApplicationController 显示在 UIViewController 上方的原因是因为 TVApplicationController 需要更多时间来初始化,然后是 UIViewController,这会导致异步问题。您可以使用简单的 dispatch_after 来验证这一点。如果您希望 UIViewController 成为应用程序的初始控制器,则必须将 nil 而不是 self.window 传递给 initWithContext:window:delegate:,然后使用 [self.window.rootViewController presentViewController:self.appController.navigationController animated:YES completion:nil]; 呈现 TVApplicationController 当然,此时,而不是呈现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];
    

    【讨论】:

    • 我不遵循您的代码试图实现的目标。您正在创建一个新窗口并将其分配给self.window,然后将nil 作为window 参数传递给TVApplicationController 初始化程序。我的问题不是让我的主视图控制器成为根 - 正如你所说,我可以通过将其设置为情节提要中的初始视图控制器来做到这一点,我的问题是在 TVApplicationController 的顶部以模态方式推动不同的视图控制器导航堆栈。您的代码是否正在尝试解决这个问题?
    • 我的代码实现了流程,您将本机 UIViewController 作为根控制器,然后在稍后的某个时间以模态方式呈现 TVApplicationController。如果你想要一个相反的场景,你将self.window 传递给TVApplicationController 并使用[tvAppController.navigationController presentViewController:nativeViewController animated:YES completion:nil] 呈现本机控制器。但请注意我之前写过的异步问题。
    猜你喜欢
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2015-07-16
    相关资源
    最近更新 更多