【问题标题】:View Stack, UIViewController, and Rotation查看堆栈、UIViewController 和旋转
【发布时间】:2013-02-09 12:13:43
【问题描述】:

我有一个 UIViewcontroller,它承载了很多 Viewcontroller。我在它及其子视图上设置了自动旋转,一旦应用程序加载它就可以正常工作。我遇到的问题是,在初始加载过程中,应用程序必须在本地连接并下载一些文件。在此加载期间,如果用户旋转 iPad,UIViewController 将无法正确旋转!我确实设置了标志并应该自动旋转,但仍然无法正常工作。

PS:我允许这四个方向:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
 {
  return (interfaceOrientation == UIInterfaceOrientationPortrait ||
        interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight);
 }

加载完成后,行为正确并正确旋转。现在我认为这可能是因为其中一些内部 VC 正在加载一些数据,让我解释一下: 大 View Controller 托管所有其他 VC(让我们称他为 BigDaddy),在 bigdaddy 的 Viewdidload 中,我有(为了论证)另外三个 ViewController:Busta、Skeezix 和 Lawrence。所以我这样做:

[[Busta alloc] initWithNibName:@"Busta" bundle:nil];

这反过来又调用了 Busta 的 -viewDidLoad,所以我通过执行以下操作使该异步的文件加载部分:

    dispatch_async(dispatch_get_main_queue(), ^{
    }); 

这些更改确实有点帮助,因为在异步调度之前加载过程需要 5 秒(在这几秒内,iPad 的任何倾斜都会导致旋转事件,我的整个视图都消失了。现在我将这 5 秒缩短到 1.2 秒。 我的问题是,我的问题有解决方案吗?它永远不会起作用吗?是否可以让应用在四个方向上旋转并在加载数据时响应旋转变化?

【问题讨论】:

    标签: ios xcode ipad uiviewcontroller


    【解决方案1】:

    我怀疑问题在于您如何进行“连接”。我假设您的意思是您正在使用 NSURLConnection 或类似方法连接到远程服务器。请注意,如果您在主线程上使用同步连接,您冻结应用程序直到连接完成。适当的方法是利用异步调用,或者更好地将工作转移到辅助线程(参见 NSOperationQueue 文档),然后将基于该信息的 UI 更新移回主线程(再次参见 NSOperationQueue 文档)。

    WWDC 2012 视频中有一个很好的例子。

    【讨论】:

    • 嗨,我认为这是主要问题,我在 dispatch_async(dispatch_get_main_queue(), ^{ });不应该这样做吗?
    • @Huang 问题是,你仍然将它发送到主队列——你需要创建一个辅助队列!因为你使用的是'dispatch_get_main_queue()',所以你实际上从来没有卸载工作,你只是稍微延迟一下。
    • hmm,好吧,我很困惑(对目标 C 来说还是新手),所以我确实创建了自己的队列并在其上 sipatch,但现在我得到了异常,试图从一个线程以外的线程获取网络锁主线程或网络线程。这可能是从辅助线程调用 UIKit 的结果。现在崩溃了...基本上在这个单独的队列中,我正在创建 uiwebviews 并预加载它们,然后将它们添加到 main.view。所以我
    • 所以我假设需要在主 UI 线程上执行将 webview 广告到 UI 的调用。当我不在主队列时,我该怎么做??
    • @Huang 这应该给你一个很好的起点:[[NSOperationQueue mainQueue] addOperationWithBLock:];
    【解决方案2】:

    为什么不直接实现 -shouldAutorotateToInterfaceOrientation... 方法,使其仅在应用完成加载所需数据后才允许旋转?

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        BOOL appIsFinishedLoadingData = <your code here>
        return shouldRotate;
    }
    

    (考虑到您允许所有可能的轮换,我缩短了您的代码,因此实际上无需检查提供的轮换。您的方式更具前瞻性,我的方式更易于阅读.)

    【讨论】:

    • 嗯,好吧,我试过了,但是在某些时代它不起作用,现在我有 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if([self isLoading]) { return false; } return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft etc etc } 在我的 iPad 上运行时,我在 isloading 下点击了 false 分支,并返回 false,但 iPad 仍在旋转!
    • @Caleb 这种方法仍然会遇到关键问题,即他在主线程上进行网络工作——这将导致应用程序被 Apple 拒绝。让应用程序在任何时间段内冻结的唯一方法是在应用程序仍在加载时执行此操作,在它显示任何类型的 UI 之前。
    • @RonLugge 看起来我误读了这个问题——我在想 OP 想要避免在加载完成之前旋转。你关于冻结主线程的观点是一个很好的观点,但我认为你有点夸大了你的情况。从主线程使用网络并不是那么糟糕提供,您可以使用例如+[NSURLConnection sendAsyncrhonousRequest...] 异步执行它。但是,是的,您不应该做任何导致应用停止响应用户或以其他方式显示冻结的事情。
    • @Caleb 我的观点可能表述错误。在我看来,使用异步网络调用会自动将您从当前线程中移出。我不确定这在幕后在技术上是否属实,但我倾向于这样认为。
    猜你喜欢
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    相关资源
    最近更新 更多