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:
我发现,正如我在为文件编写映像时预测的那样,我的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];
}
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:
为了避免UI阻塞,我已经将writeToFile放入了一个*调度队列中,以便它作为一个并发线程运行。但是当写完线程完成后,我想发布一个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];
}
});
});
}
What is the correct mechanism here to post this notification to gain the functionality I want ?
这里发布此通知以获得我想要的功能的正确机制是什么?
2 个解决方案
#1
6
A couple possibilities here.
两个可能性。
1)
1)
How about [NSObject performSelectorOnMainThread: ...] ?
那么[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];
}
});
});
}
更多细节在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)
或2)
Completion Callbacks
完成回调
as seen at How can I be notified when a dispatch_async task is complete?
如在dispatch_async任务完成时如何通知我?
#2
1
-(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()?
这已经是正确的。但是,如果已经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.
无论你做什么,都会在调用[[NSNotificationCenter defaultCenter] postNotificationName: kimagesavedsuccessful object:self]的线程的同一线程上完成;也就是主线程。
#1
6
A couple possibilities here.
两个可能性。
1)
1)
How about [NSObject performSelectorOnMainThread: ...] ?
那么[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];
}
});
});
}
更多细节在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)
或2)
Completion Callbacks
完成回调
as seen at How can I be notified when a dispatch_async task is complete?
如在dispatch_async任务完成时如何通知我?
#2
1
-(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()?
这已经是正确的。但是,如果已经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.
无论你做什么,都会在调用[[NSNotificationCenter defaultCenter] postNotificationName: kimagesavedsuccessful object:self]的线程的同一线程上完成;也就是主线程。