iPhone 活动指示器延迟?

发布于 2024-11-30 09:14:18 字数 1233 浏览 4 评论 0原文

因此,当我单击 mapView 中的标注附件时,几秒钟内没有任何反应,因为它正在发出 url 请求并解析它,所以我想显示活动指示器,这样用户就不会认为它被冻结了。这是代码:

- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
    // start activity indicator 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSLog(@"tapped");

    ArtPiece *artPiece = (ArtPiece *)pin.annotation;

    //when annotation is tapped switches page to the art description page
    artDescription *artD = [[artDescription alloc] initWithNibName:@"artDescription" bundle:nil];
    artD.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    artD.startingLocation = mapView.userLocation.location.coordinate;
    artD.selectedArtPiece = artPiece;
    NSLog(@"0");
    [self presentModalViewController:artD animated:YES];
    NSLog(@"1");

    [artD loadArt:artPiece];
    NSLog(@"2");
    // stop activity indicator 
    //[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [artD release];
}

奇怪的是(无论如何,对我来说,也许我错过了一些明显的东西,因为我相当缺乏经验),活动指示器直到方法完成后才显示,并且模态视图开始动画进入视图。我将 NSLogs 放入其中以查看花费时间的情况。我在“0”和“1”之间停顿了大约 2 秒,在“1”和“2”之间又停顿了几秒钟。然后指示器终于显示了,所以我确信它由于某种原因正在等待方法结束。有什么想法吗?

So when I click on a callout accessory in my mapView, nothing happens for several seconds because it is making a url request and parsing it, so I wanted to show the activity indicator so the user doesn't think it's frozen. Here's the code:

- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
    // start activity indicator 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSLog(@"tapped");

    ArtPiece *artPiece = (ArtPiece *)pin.annotation;

    //when annotation is tapped switches page to the art description page
    artDescription *artD = [[artDescription alloc] initWithNibName:@"artDescription" bundle:nil];
    artD.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    artD.startingLocation = mapView.userLocation.location.coordinate;
    artD.selectedArtPiece = artPiece;
    NSLog(@"0");
    [self presentModalViewController:artD animated:YES];
    NSLog(@"1");

    [artD loadArt:artPiece];
    NSLog(@"2");
    // stop activity indicator 
    //[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [artD release];
}

Strangely (to me anyway, maybe I'm missing something obvious as I'm pretty inexperienced), the activity indicator does not show until after the method is done, and the modal view starts animating into view. I put the NSLogs in to see what was taking time. I had about a 2 second pause between "0" and "1" and another couple seconds between "1" and "2". Then the indicator finally showed, so I am sure it is waiting until the end of the method for some reason. Any ideas why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅黛梨妆こ 2024-12-07 09:14:18

在控制权返回到应用程序的 主运行循环。直到您的方法结束并且堆栈展开之后才会发生这种情况。您需要显示活动指示器,然后将您正在等待的活动转储到后台线程:(

[self performSelectorInBackground:@selector(doThingINeedToWaitFor:)
                       withObject:anObject];

请注意,Apple 建议不再显式使用线程; performSelectorInBackground:withObject:< /code>是让某些代码从主线程运行的最简单方法。对于其他情况,还有更复杂的选项。 href="http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40008091-CH1-SW1" rel=" nofollow">并发编程指南。)

重要的问题是 UI 更新仍然需要在主线程上处理,因此在该方法中,当工作是完成后,您需要回调以停止活动指示器:

- (void) doThingINeedToWaitFor: (id)anObject {
    // Creating an autorelease pool should be the first thing
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Do your work...
    // ...
    // Update the UI back on the main thread
    [self performSelectorOnMainThread:@selector(allDoneWaiting:)
                           withObject:nil
                        waitUntilDone:YES];
    // Clear out the pool as the final action on the thread
    [pool drain];
}

在回调方法中,您再次隐藏活动指示器并执行任何其他必要的后处理。

The change to the UI, displaying the activity indicator, does not take effect until control has returned to the application's main run loop. This does not occur until after your method has ended and the stack has unwound. You need to show the activity indicator, then dump the activity you are waiting for onto a background thread:

[self performSelectorInBackground:@selector(doThingINeedToWaitFor:)
                       withObject:anObject];

(Note that Apple recommends that you move away from using threads explicitly; performSelectorInBackground:withObject: is the simplest method to get some code run off the main thread. More complex options are available for other situations. See the Concurrency Programming Guide.)

The important gotcha is that UI updates still need to be handled on the main thread, so in that method, when the work is done, you need to call back to stop the activity indicator:

- (void) doThingINeedToWaitFor: (id)anObject {
    // Creating an autorelease pool should be the first thing
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Do your work...
    // ...
    // Update the UI back on the main thread
    [self performSelectorOnMainThread:@selector(allDoneWaiting:)
                           withObject:nil
                        waitUntilDone:YES];
    // Clear out the pool as the final action on the thread
    [pool drain];
}

In your callback method, you hide the activity indicator again and do any other post-processing that's necessary.

英雄似剑 2024-12-07 09:14:18

您不能在同一函数中启动和停止活动指示器。

请参阅我为此问题提供的答案:按下按钮上传下一个视图或 webview 时如何显示活动指示器?

为了清楚起见进行编辑:

- (void) someFunction
{
    [activityIndicator startAnimation];

    // do computations ....

    [activityIndicator stopAnimation];  
}

上面的代码将不起作用,因为您没有提供 UI当您将 ActivityIndi​​cator 包含在当前运行的函数中时进行更新。所以我和许多其他人所做的就是将其分解为一个单独的线程,如下所示:

- (void) yourMainFunction {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

    [NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];

    //Your computations

    [activityIndicator stopAnimating];

}

- (void) threadStartAnimating {
    [activityIndicator startAnimating];
}

You cannot start and stop the activity indicator in the same function.

See the answer I provided for this question: How show activity-indicator when press button for upload next view or webview?

Edit for clarity:

- (void) someFunction
{
    [activityIndicator startAnimation];

    // do computations ....

    [activityIndicator stopAnimation];  
}

The above code will not work because you do not give the UI time to update when you include the activityIndicator in your currently running function. So what I and many others do is break it up into a separate thread like so:

- (void) yourMainFunction {
    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];

    [NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];

    //Your computations

    [activityIndicator stopAnimating];

}

- (void) threadStartAnimating {
    [activityIndicator startAnimating];
}
宁愿没拥抱 2024-12-07 09:14:18

有些东西正在减慢你的旋转器的速度。我建议使用线程在后台完成繁重的工作。试试这个:

-(void)myMethod{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    [NSThread detachNewThreadSelector:@selector(startWorkingThread) toTarget:self withObject:nil];
}

-(void)startWorkingThread{
     //Heavy lifting
     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

我假设您已经评论过:

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

出于测试目的......

Something is slowing down your spinner. I would recommend doing your heavy lifting in background, using a thread. Try this:

-(void)myMethod{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    [NSThread detachNewThreadSelector:@selector(startWorkingThread) toTarget:self withObject:nil];
}

-(void)startWorkingThread{
     //Heavy lifting
     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

I assume that you have commented the:

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

For testing purposes...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文