IBAction 中跳过的用户界面命令

发布于 2025-01-08 08:33:07 字数 648 浏览 0 评论 0原文

这是我的代码:

-(IBAction)saveDownloadedImage
{
    NSLog(@"Test");    EXECUTED
    indicatorView.hidden = NO;  NOT EXECUTED
    [indicatorView startAnimating];  NOT EXECUTED
    [statusLabel setText:@"WHY?"];  NOT EXECUTED
    [currentPicture setImage:[imageView image]];   EXECUTED
    ImageFileManager *fileManager = [[ImageFileManager alloc] init]; EXECUTED
    [fileManager saveImageToDisk:currentPicture]; EXECUTED
    indicatorView.hidden = YES;
    [statusLabel setText:@"Image saved successfully."]; EXECUTED
    saveButton.enabled = NO; EXECUTED

}

保存过程大约需要 5 秒。所以在 UI 中看到该指示器是正常的。但什么也没发生!有什么想法吗?

Here is my code:

-(IBAction)saveDownloadedImage
{
    NSLog(@"Test");    EXECUTED
    indicatorView.hidden = NO;  NOT EXECUTED
    [indicatorView startAnimating];  NOT EXECUTED
    [statusLabel setText:@"WHY?"];  NOT EXECUTED
    [currentPicture setImage:[imageView image]];   EXECUTED
    ImageFileManager *fileManager = [[ImageFileManager alloc] init]; EXECUTED
    [fileManager saveImageToDisk:currentPicture]; EXECUTED
    indicatorView.hidden = YES;
    [statusLabel setText:@"Image saved successfully."]; EXECUTED
    saveButton.enabled = NO; EXECUTED

}

The proccess of saving takes about 5 seconds. So it would be normal to see the indicator in the UI. But nothing happens! Any idea?

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

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

发布评论

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

评论(4

猫九 2025-01-15 08:33:08

您需要向这样的发送者声明您的方法

-(IBAction)saveDownloadedImage:(id)sender

You need to declare your method with a sender like this

-(IBAction)saveDownloadedImage:(id)sender
原来分手还会想你 2025-01-15 08:33:07

一切都被执行了。您的问题是 saveImageToDisk 调用是同步的,并且您是从 UI 线程调用它。当您阻塞 UI 线程时,不会重新绘制任何内容。指示器已显示,但无法将其绘制到屏幕上,直到 IBAction 返回(此时它将再次隐藏)。

您必须异步调用保存方法。
阻塞 UI 线程从来都不是一个好主意。

编辑:请参阅以下问题的答案以获得正确的解决方案: asynchronous requests to database in ios

Edit2:可能的解决方案之一(未测试)


-(IBAction)saveDownloadedImage {
    indicatorView.hidden = NO; //Note you can use hidesWhenStopped property for this
    [indicatorView startAnimating];
    [statusLabel setText:@"BECAUSE..."];
    [currentPicture setImage:[imageView image]];

    [NSThread detachNewThreadSelector:@selector(save) toTarget:self withObject:nil]
}

- (void)save {
    @autoreleasepool {
        ImageFileManager *fileManager = [[ImageFileManager alloc] init];
        [fileManager saveImageToDisk:currentPicture];

        [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
    }
}

- (void)updateUI {
    indicatorView.hidden = YES;
    [statusLabel setText:@"Image saved successfully."];
    saveButton.enabled = NO;
}

Everything is executed. Your problem is that the saveImageToDisk call is synchronous and you are calling it from the UI thread. When you are blocking the UI thread, nothing is ever repainted. The indicator is shown but it cannot be drawn to the screen until the IBAction returns when it will have been hidden again.

You have to call the saving method asynchronously.
Blocking UI thread is never a good idea.

Edit: see the answer for the following question for the correct solution: asynchronous calls to database in ios

Edit2: One of the possible solutions (not tested)


-(IBAction)saveDownloadedImage {
    indicatorView.hidden = NO; //Note you can use hidesWhenStopped property for this
    [indicatorView startAnimating];
    [statusLabel setText:@"BECAUSE..."];
    [currentPicture setImage:[imageView image]];

    [NSThread detachNewThreadSelector:@selector(save) toTarget:self withObject:nil]
}

- (void)save {
    @autoreleasepool {
        ImageFileManager *fileManager = [[ImageFileManager alloc] init];
        [fileManager saveImageToDisk:currentPicture];

        [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
    }
}

- (void)updateUI {
    indicatorView.hidden = YES;
    [statusLabel setText:@"Image saved successfully."];
    saveButton.enabled = NO;
}

枉心 2025-01-15 08:33:07

您确定

1)indicatorView 和 statusLabel 不为 null,并且

2)indicatorView 和 statusLabel 作为子视图添加到 self.view 中吗?

Are you sure that

1) indicatorView and statusLabel are not null, and

2) indicatorView and statusLabel are added as subviews to self.view?

后知后觉 2025-01-15 08:33:07

在我的看法中,您正在启动活动指示器主线程。

相反,在主线程上显示指示器,

您应该在单独的线程上调用指示器,如下所示。

-(IBAction)saveDownloadedImage
{
NSLog(@"Test");    EXECUTED
commented below code
//indicatorView.hidden = NO;  NOT EXECUTED
// [indicatorView startAnimating];  NOT EXECUTED
//instead of main thread create new Thread as Below
[NSThread detachNewThreadSelector:@selector(showloader) toTarget:self withObject:nil];
[statusLabel setText:@"WHY?"];  NOT EXECUTED
[currentPicture setImage:[imageView image]];   EXECUTED
ImageFileManager *fileManager = [[ImageFileManager alloc] init]; EXECUTED
[fileManager saveImageToDisk:currentPicture]; EXECUTED

[statusLabel setText:@"Image saved successfully."]; EXECUTED
saveButton.enabled = NO;
[indicatorView stopAnimating:YES];
indicatorView.hidden = YES;
}


//Custome method For shoing the Indicator.
-(void)showloader{
//call below method  here indicatorView object created already.
[indicatorView startAnimating]
}

It'll definitely work

In My Perception your are starting the Activity Indicator main Thread.

Instead Showing the Indicator on main thread

you should call Indicator on seperate Thread as Below.

-(IBAction)saveDownloadedImage
{
NSLog(@"Test");    EXECUTED
commented below code
//indicatorView.hidden = NO;  NOT EXECUTED
// [indicatorView startAnimating];  NOT EXECUTED
//instead of main thread create new Thread as Below
[NSThread detachNewThreadSelector:@selector(showloader) toTarget:self withObject:nil];
[statusLabel setText:@"WHY?"];  NOT EXECUTED
[currentPicture setImage:[imageView image]];   EXECUTED
ImageFileManager *fileManager = [[ImageFileManager alloc] init]; EXECUTED
[fileManager saveImageToDisk:currentPicture]; EXECUTED

[statusLabel setText:@"Image saved successfully."]; EXECUTED
saveButton.enabled = NO;
[indicatorView stopAnimating:YES];
indicatorView.hidden = YES;
}


//Custome method For shoing the Indicator.
-(void)showloader{
//call below method  here indicatorView object created already.
[indicatorView startAnimating]
}

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