在 didSelectRowAtIndexPath 中调用 PushViewController 时无法显示 UIActivityIndi​​cator

发布于 2024-12-26 02:15:04 字数 987 浏览 1 评论 0原文

这是我的代码...

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

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    activityIndicator=[[UIActivityIndicatorView alloc] init];
    [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center=[self tableView].center;
    [[self tableView] addSubview:activityIndicator];

    [NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];
    EventController *eventController = [[EventController alloc] init];
    [eventController setEventID:[[lineItems objectAtIndex:[indexPath row]] objectForKey:@"view_event_button_param"]];
    [activityIndicator stopAnimating];
    [[self navigationController] pushViewController:eventController animated:YES];
}

事件控制器包含一个需要几秒钟加载的 Web 服务。我可以让活动指示器显示的唯一方法是如果我在那里抛出一个无限循环...我发现了一堆提到将其放在单独线程中的示例,但它似乎不起作用。

Here is my code...

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

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    activityIndicator=[[UIActivityIndicatorView alloc] init];
    [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center=[self tableView].center;
    [[self tableView] addSubview:activityIndicator];

    [NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];
    EventController *eventController = [[EventController alloc] init];
    [eventController setEventID:[[lineItems objectAtIndex:[indexPath row]] objectForKey:@"view_event_button_param"]];
    [activityIndicator stopAnimating];
    [[self navigationController] pushViewController:eventController animated:YES];
}

The event controller contains a web service that takes a few seconds to load. The only way I can get the activity indicator to show is if I throw an infinite loop in there... I found a bunch of examples that mentioned putting it in a separate thread but it doesn't seem to work.

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

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

发布评论

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

评论(2

热鲨 2025-01-02 02:15:04

您的问题是,如果您在 viewDidLoad 中获取数据,那么直到加载视图之后才会调用该方法,这通常是在首次显示该视图控制器的过程中。在您的情况下,这是在 pushViewController:animated: 调用期间。

因此,做你想做的事情的一种方法可能是交换这两行:

[activityIndicator stopAnimating];
[[self navigationController] pushViewController:eventController animated:YES];

但是,老实说,我会创建一个名为 EventControllerDelegate 的协议,对 id < 有一个弱引用属性;EventControllerDelegate> 在您的 EventController 中,然后在推送之前设置创建 EventController 作为委托的视图控制器。然后在委托中定义一个方法并在视图控制器中实现它,并在该方法中停止微调器。然后,在 EventController 中,加载完数据后,调用委托方法。

编辑:如果您确实想在不定义委托的情况下执行此操作,您可以尝试将代码更改为如下所示:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    activityIndicator=[[UIActivityIndicatorView alloc] init];
    [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center=[self tableView].center;
    [[self tableView] addSubview:activityIndicator];

    EventController *eventController = [[EventController alloc] init];
    [eventController setEventID:[[lineItems objectAtIndex:[indexPath row]] objectForKey:@"view_event_button_param"]];

    [activityIndicator startAnimating];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIView *v = eventController.view;

        dispatch_async(dispatch_get_main_queue(), ^{
            [activityIndicator stopAnimating];
            [[self navigationController] pushViewController:eventController animated:YES];
        });
    });
}

为了清晰起见,它使用 GCD 和通常的“访问视图属性以强制 loadView / viewDidLoad”黑客。

Your problem is that if you're getting the data in viewDidLoad then that method won't be called until after the view is loaded, which is usually during the process of first displaying that view controller. In your case this is during the pushViewController:animated: call.

So one way to do what you want might be to swap around these two lines:

[activityIndicator stopAnimating];
[[self navigationController] pushViewController:eventController animated:YES];

But, in all honesty, I would create a protocol called EventControllerDelegate, have a weak reference property to an id <EventControllerDelegate> in your EventController and then set the view controller which creates the EventController as the delegate before you push it. Then define a method in the delegate and implement it in your view controller and in that method stop the spinner. Then in EventController, when you've finished loading your data, call the delegate method.

Edit: If you really want to do it without defining a delegate, you could try changing your code to something like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    activityIndicator=[[UIActivityIndicatorView alloc] init];
    [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center=[self tableView].center;
    [[self tableView] addSubview:activityIndicator];

    EventController *eventController = [[EventController alloc] init];
    [eventController setEventID:[[lineItems objectAtIndex:[indexPath row]] objectForKey:@"view_event_button_param"]];

    [activityIndicator startAnimating];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIView *v = eventController.view;

        dispatch_async(dispatch_get_main_queue(), ^{
            [activityIndicator stopAnimating];
            [[self navigationController] pushViewController:eventController animated:YES];
        });
    });
}

It's using GCD for clarity and the usual "access the view property to force a loadView / viewDidLoad" hack.

御守 2025-01-02 02:15:04

您需要为 activityIndi​​cator 设置帧大小。

activityIndicator.frame = CGRectMake(x, y, 40, 40);

You need to set a frame size for your activityIndicator.

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