Migrate performSelectorOnMainThread and performSelectorInBackground invocations to GCD

This commit is contained in:
Blake Watters
2012-06-18 23:54:52 -04:00
parent 57e4e0933a
commit ec6cdd1356
7 changed files with 59 additions and 29 deletions

View File

@@ -398,7 +398,7 @@ static RKManagedObjectStore *defaultObjectStore = nil;
// If we are a background Thread MOC, we need to inform the main thread on save
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeChanges:)
selector:@selector(managedObjectContextDidSaveNotification:)
name:NSManagedObjectContextDidSaveNotification
object:managedObjectContext];
}
@@ -406,18 +406,11 @@ static RKManagedObjectStore *defaultObjectStore = nil;
return managedObjectContext;
}
- (void)mergeChangesOnMainThreadWithNotification:(NSNotification *)notification
- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification
{
assert([NSThread isMainThread]);
[self.primaryManagedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
- (void)mergeChanges:(NSNotification *)notification
{
// Merge changes into the main context on the main thread
[self performSelectorOnMainThread:@selector(mergeChangesOnMainThreadWithNotification:) withObject:notification waitUntilDone:YES];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.primaryManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
#pragma mark -

View File

@@ -133,10 +133,14 @@
- (void)invokeOnMainThread
{
[self retain];
[self serializeManagedObjects];
[self performSelectorOnMainThread:@selector(performInvocationOnMainThread) withObject:nil waitUntilDone:YES];
[self release];
if ([NSThread isMainThread]) {
[self performInvocationOnMainThread];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
[self performInvocationOnMainThread];
});
}
}
- (void)dealloc

View File

@@ -29,6 +29,9 @@
#import "RKConfigurationDelegate.h"
#import "RKRouter.h"
// Retrieves the dispatch queue for emitting network processing events
dispatch_queue_t rk_get_network_processing_queue(void);
/**
RKClient exposes the low level client interface for working with HTTP servers
and RESTful services. It wraps the request/response cycle with a clean, simple
@@ -82,6 +85,7 @@
provided via the RKRequestSerializable protocol and is not specific to
NSDictionary objects.
### Sending Asynchronous Requests
A handful of methods are provided as a convenience to cover the common

View File

@@ -37,7 +37,7 @@
static RKClient *sharedClient = nil;
///////////////////////////////////////////////////////////////////////////////////////////////////
// URL Conveniences functions
// Conveniences functions
NSURL *RKMakeURL(NSString *resourcePath) {
return [[RKClient sharedClient].baseURL URLByAppendingResourcePath:resourcePath];
@@ -63,6 +63,17 @@ NSString *RKPathAppendQueryParams(NSString *resourcePath, NSDictionary *queryPar
return [resourcePath stringByAppendingQueryParameters:queryParams];
}
static dispatch_queue_t rk_network_processing_queue;
dispatch_queue_t rk_get_network_processing_queue(void)
{
if (rk_network_processing_queue == NULL) {
rk_network_processing_queue = dispatch_queue_create("org.restkit.network.processing-queue", 0);
}
return rk_network_processing_queue;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@interface RKClient ()

View File

@@ -36,6 +36,8 @@
#import "RKParserRegistry.h"
#import "RKRequestSerialization.h"
extern dispatch_queue_t rk_get_network_processing_queue(void);
NSString *RKRequestMethodNameFromType(RKRequestMethod method) {
switch (method) {
case RKRequestMethodGET:
@@ -492,7 +494,11 @@ RKRequestMethod RKRequestMethodTypeFromName(NSString *methodName) {
if ([self shouldLoadFromCache]) {
RKResponse *response = [self loadResponseFromCache];
self.loading = YES;
[self performSelector:@selector(didFinishLoad:) withObject:response afterDelay:0];
dispatch_async(rk_get_network_processing_queue(), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
[self didFinishLoad:response];
});
});
} else if ([self shouldDispatchRequest]) {
[self createTimeoutTimer];
#if TARGET_OS_IPHONE
@@ -548,7 +554,11 @@ RKRequestMethod RKRequestMethodTypeFromName(NSString *methodName) {
errorMessage, NSLocalizedDescriptionKey,
nil];
NSError *error = [NSError errorWithDomain:RKErrorDomain code:RKRequestBaseURLOfflineError userInfo:userInfo];
[self performSelector:@selector(didFailLoadWithError:) withObject:error afterDelay:0];
dispatch_async(rk_get_network_processing_queue(), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
[self didFailLoadWithError:error];
});
});
}
}
}

View File

@@ -281,7 +281,9 @@ static const NSTimeInterval kFlushDelay = 0.3;
// We always want to dispatch requests from the main thread so the current thread does not terminate
// and cause us to lose the delegate callbacks
if (! [NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(loadNextInQueue) withObject:nil waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
[self loadNextInQueue];
});
return;
}
@@ -590,8 +592,9 @@ static NSInteger networkActivityCount;
- (void)refreshActivityIndicator
{
if (![NSThread isMainThread]) {
SEL sel_refresh = @selector(refreshActivityIndicator);
[self performSelectorOnMainThread:sel_refresh withObject:nil waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
[self refreshActivityIndicator];
});
return;
}
BOOL active = (self.networkActivityCount > 0);

View File

@@ -130,12 +130,13 @@
self.loading = NO;
self.loaded = successful;
if ([self.delegate respondsToSelector:@selector(objectLoaderDidFinishLoading:)]) {
[(NSObject<RKObjectLoaderDelegate>*)self.delegate performSelectorOnMainThread:@selector(objectLoaderDidFinishLoading:)
withObject:self waitUntilDone:YES];
}
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.delegate respondsToSelector:@selector(objectLoaderDidFinishLoading:)]) {
[(NSObject<RKObjectLoaderDelegate>*)self.delegate objectLoaderDidFinishLoading:self];
}
[[NSNotificationCenter defaultCenter] postNotificationName:RKRequestDidFinishLoadingNotification object:self];
[[NSNotificationCenter defaultCenter] postNotificationName:RKRequestDidFinishLoadingNotification object:self];
});
}
// Invoked on the main thread. Inform the delegate.
@@ -185,7 +186,9 @@
- (void)processMappingResult:(RKObjectMappingResult *)result
{
NSAssert(_sentSynchronously || ![NSThread isMainThread], @"Mapping result processing should occur on a background thread");
[self performSelectorOnMainThread:@selector(informDelegateOfObjectLoadWithResultDictionary:) withObject:[result asDictionary] waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[self informDelegateOfObjectLoadWithResultDictionary:[result asDictionary]];
});
}
#pragma mark - Response Object Mapping
@@ -472,10 +475,12 @@
if (self.result) {
[self processMappingResult:self.result];
} else {
[self performSelectorInBackground:@selector(didFailLoadWithError:) withObject:error];
dispatch_async(rk_get_network_processing_queue(), ^{
[self didFailLoadWithError:error];
});
}
} else {
[self performMappingInDispatchQueue];
[self performMappingInOperationQueue];
}
}
}