使用 Grand Central Dispatch 时如何发布 NSNotification?

发布于 2024-12-08 13:33:26 字数 1291 浏览 6 评论 0原文

我发现,正如我所预测的,当我将图像写入文件时,我的 UI 在这段时间内被阻止,这是不可接受的。当我将图像写入文件时,我会发布 NS 通知,以便我可以执行与该完成相关的其他一些特定工作。原始工作但 UI 阻塞代码:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];
    BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];

if (jpgData) {        
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
}

为了避免 UI 阻塞,我将 writeToFile: 放入 Grand Central Dispatch 队列中,以便它作为并发线程运行。但是当写入完成并且线程完成时,我想发布一个 NSNotification。我不能,因为代码显示在此处,因为它位于后台线程中。但这就是我想要完成的功能,意识到这不是可行的代码:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
            }
        });
    });
}

发布此通知以获得我想要的功能的正确机制是什么?

I found that as predicted when I was writing an image to file that my UI was blocked for the duration, which was not acceptable. When I write the image to file I then post an NS Notification so that I can do some other specific jobs related to that completion. Original working but UI blocking code:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];
    BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];

if (jpgData) {        
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
}

To avoid the UI blocking I have put the writeToFile: into a Grand Central Dispatch queue so it runs as a concurrent thread. But when the write is completed and the thread is done, I want to post an NSNotification. I cannot as the code is shown here because it is in a background thread. But that is the functionality I want to accomplish, realizing this is not workable code:

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
            }
        });
    });
}

What is the correct mechanism here to post this notification to gain the functionality I want ?

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

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

发布评论

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

评论(2

纸伞微斜 2024-12-15 13:33:27

这里有几种可能性。

1)

[NSObject PerformSelectorOnMainThread: ...] 怎么样?

EG

-(void) doNotification: (id) thingToPassAlong
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:thingToPassAlong];
}

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {   
                [self performSelectorOnMainThread: @selector(doNotification:) withObject: self waitUntilDone: YES];
            }
        });
    });
}

更多详细信息,请访问 http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone

或 2)

完成回调,

当dispatch_async任务发生时如何通知我完成了吗?

A couple possibilities here.

1)

How about [NSObject performSelectorOnMainThread: ...] ?

E.G.

-(void) doNotification: (id) thingToPassAlong
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:thingToPassAlong];
}

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {   
                [self performSelectorOnMainThread: @selector(doNotification:) withObject: self waitUntilDone: YES];
            }
        });
    });
}

More details at http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:

or 2)

Completion Callbacks

as seen at How can I be notified when a dispatch_async task is complete?

梦毁影碎の 2024-12-15 13:33:27
-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
            }
        });
    });
}

这已经是正确的了。但是,如果您已经使用了dispatch_get_main_queue(),为什么还需要使用通知呢?

无论如何,只要使用

        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            //Do whatever you want with the image here
            }
        });

你原来的解决方案就可以了。这不是阻塞。基本上它会将文件保存在其他线程中,一旦完成,它就会执行所需的操作。

您所做的任何事情都将在与调用 [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessively object:self]; 的线程相同的线程上完成即主线程。

-(void)saveImageToFile {
    NSString *imagePath = [self photoFilePath];

    // execute save to disk as a background thread
    dispatch_queue_t myQueue = dispatch_queue_create("com.wilddogapps.myqueue", 0);
    dispatch_async(myQueue, ^{
        BOOL jpgData = [UIImageJPEGRepresentation([[self captureManager] stillImage], 0.5) writeToFile:imagePath atomically:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self];
            }
        });
    });
}

That is already correct. However why do you need to use notification if you already dispatch_get_main_queue()?

Just use

        dispatch_async(dispatch_get_main_queue(), ^{
            if (jpgData) {        
            //Do whatever you want with the image here
            }
        });

Anyway your original solution is fine. It's not blocking. Basically it'll save the file at other thread and once it's done it'll do what it takes.

What ever you do will be done on the same thread with the thread that call [[NSNotificationCenter defaultCenter] postNotificationName:kImageSavedSuccessfully object:self]; namely main thread.

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