【问题标题】:Displaying UIActivityIndicatorView until UIView is loaded在加载 UIView 之前显示 UIActivityIndi​​catorView
【发布时间】:2012-08-27 15:07:52
【问题描述】:

在我的 UIViewController 的 loadView 方法中,我启动了一个 UIActivityIndi​​cator。稍后在 loadView 中,我加载了一个复杂的 UIView,加载大约需要 2-3 秒。 (UIScrollView 有很多更具体的图片)。我的问题是 UIActivityIndi​​cator 微调器只有在我的其他图层也加载后才可见。 (这对我当然没用)。处理这个问题的正确方法是什么?

- (void)loadView {

    CGRect fullScreenRect=[[UIScreen mainScreen] bounds];

    UIView *contentView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
    self.view = contentView;

    spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
    spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
    spinner.center = self.view.center;
    [self.view addSubview:spinner];
    [spinner startAnimating];


     scrollView=[[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
     ...setting up scrollView...

     [self.view addSubview:scrollView];
}

- (void)viewDidLoad
{ 
    [super viewDidLoad];
    [spinner removeFromSuperview];
}

我发现了一个有点相似的线程: UIActivityIndicatorView not showing until after loading done

但它建议在后台线程中加载东西,但据我所知,加载和显示 UIView 只能在主线程中进行。

我是初学者,如果我的问题根本上是错误的,我很抱歉。

【问题讨论】:

  • 我看到了几个选项 - 您可以在后台线程中将视图渲染为屏幕外的图像,完成后,将视图的图像添加到滚动视图,或者您可以实现滚动查看平铺并按需加载滚动视图内容。可能还有其他优化 - 运行仪器。如果您在理解这些选项方面需要更多帮助,请告诉我。
  • 你为什么使用 loadView 而不是使用 nib?您是初学者,但正在尝试使用先进的技术,这将使您需要做的事情变得非常困难。所以使用带视图的笔尖。当您获得 viewDidLoad 时,将微调器添加到您的视图中。提供一种方法来关闭微调器并更新您的视图。在 viewDidLoad 中,在默认队列上使用 dispatch_async() 来完成后台繁重的工作。完成后,让它通过 dispatch_async(dispatch_get_main_queue() 发送另一条消息,告诉您的 viewController 工作已完成。这将花费您几天的时间,因此请做好计划。

标签: ios uiview uiactivityindicatorview


【解决方案1】:

我设法按照 Carl Veazey 的建议进行了制作。实际上这很容易。我产生了一个新的后台线程,并在那里加载了我的 UIScrollView。

我在 LoadView 中使用过:

spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
    spinner.center = self.view.center;
[self.view addSubview:spinner];
[spinner startAnimating];

[self performSelectorInBackground:@selector(populateScrollView) withObject:nil];

还有:

-(void) populateScrollView{

    ...creating scrollView...

    [self.view addSubview:scrollView];
    [spinner removeFromSuperview];

}

完美运行。对我来说真正奇怪的是,我在后台线程中将滚动视图添加到 UI,而不是在主线程中。我以为我只能在主线程中弄乱 UI。

(我可以用 GCD 做同样的事情。当后台线程完成加载滚动视图时,我可以在主线程的队列中显示滚动视图。但是以前的解决方案也可以工作......)

【讨论】:

  • 这不是我在评论中的意思。我的意思是将视图内容绘制到图像中,然后在主线程上用该图像创建一个图像视图。这个工作的事实并不能使 UIKit 线程安全。它并不总是崩溃,它有时会开始表现得很奇怪。所以我很高兴它可以工作,但是从后台线程操作视图层次结构是一个编程错误。
  • 所以我想正确的方法是在后台线程中创建我的滚动视图,但将其添加到主线程中的视图层次结构中?
  • 观看 2012 wwdc 视频并发用户界面。您使用绘图函数将在 drawRect: 中绘制的内容绘制到图像上下文中。然后将该图像传递给主线程,然后将其放入图像视图中。如果绘图是您的瓶颈,它将对您有所帮助。看看视频,虽然它比我解释得更好:)
  • 完全理解 Carl Veazey 花了几个月的时间,但解决方案很棒。我希望我能接受评论作为解决方案。
  • 很高兴能帮上忙!你当然可以接受你自己的答案:)
【解决方案2】:

对于难看的文本格式,我们深表歉意。 有一种非常可爱的方式可以做你想做的事。 首先,您必须显示指标视图,并且仅在一小段时间(0.1 秒甚至更短)之后您才要求您的滚动视图填充。

- (void)loadView {

    CGRect fullScreenRect=[[UIScreen mainScreen] bounds];

    UIView *contentView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
    self.view = contentView;

    spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
    spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
    spinner.center = self.view.center;
    [self.view addSubview:spinner];
    [spinner startAnimating];

    double delayInSeconds = 0.1;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        scrollView=[[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
     ...setting up scrollView...

       [self.view addSubview:scrollView];
    });
}

【讨论】:

    【解决方案3】:

    试试这个简单的方法,它对我很有效......

    UIActivityIndicatorView *activityIndicator= [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
    activityIndicator.layer.cornerRadius = 05;
    activityIndicator.opaque = NO;
    activityIndicator.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f];
    activityIndicator.center = self.view.center;
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
    [activityIndicator setColor:[UIColor colorWithRed:0.6 green:0.8 blue:1.0 alpha:1.0]];
    [self.view addSubview: activityIndicator];
    

    在加载视图时添加以下行

    //-- Add this line while processing to load your view
        [activityIndicator startAnimating];
    
    //-- Add this line when after you view loaded
        [activityIndicator stopAnimating];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多