From f63e0307c557c14059ffe32561dc9aba4ea9d25a Mon Sep 17 00:00:00 2001 From: Tomaz Kragelj Date: Tue, 29 Nov 2011 11:19:55 +0100 Subject: [PATCH 1/2] Added ARC support. --- XPCKit.xcodeproj/project.pbxproj | 1 + XPCKit/NSArray+XPCParse.m | 4 ++++ XPCKit/NSDictionary+XPCParse.m | 4 ++++ XPCKit/NSFileHandle+XPCParse.m | 5 ++++- XPCKit/XPCConnection.m | 5 ++++- XPCKit/XPCService.h | 4 ++++ XPCKit/XPCService.m | 6 ++++++ XPCKit/XPCUUID.m | 19 ++++++++++++++++--- 8 files changed, 43 insertions(+), 5 deletions(-) diff --git a/XPCKit.xcodeproj/project.pbxproj b/XPCKit.xcodeproj/project.pbxproj index d69637a..bf58b54 100644 --- a/XPCKit.xcodeproj/project.pbxproj +++ b/XPCKit.xcodeproj/project.pbxproj @@ -546,6 +546,7 @@ 1EEDD01F13DD485400D5AEC3 /* Project object */ = { isa = PBXProject; attributes = { + LastUpgradeCheck = 0420; ORGANIZATIONNAME = Mustacheware; }; buildConfigurationList = 1EEDD02213DD485400D5AEC3 /* Build configuration list for PBXProject "XPCKit" */; diff --git a/XPCKit/NSArray+XPCParse.m b/XPCKit/NSArray+XPCParse.m index 71a16df..90975de 100644 --- a/XPCKit/NSArray+XPCParse.m +++ b/XPCKit/NSArray+XPCParse.m @@ -31,7 +31,11 @@ +(NSArray *)arrayWithContentsOfXPCObject:(xpc_object_t)object{ } return true; }); +#if __has_feature(objc_arc) + return [array copy]; +#else return [[array copy] autorelease]; +#endif } -(xpc_object_t)newXPCObject{ diff --git a/XPCKit/NSDictionary+XPCParse.m b/XPCKit/NSDictionary+XPCParse.m index 5c82e4d..ef87095 100644 --- a/XPCKit/NSDictionary+XPCParse.m +++ b/XPCKit/NSDictionary+XPCParse.m @@ -32,7 +32,11 @@ +(NSDictionary *)dictionaryWithContentsOfXPCObject:(xpc_object_t)object{ } return true; }); +#if __has_feature(objc_arc) + return [dict copy]; +#else return [[dict copy] autorelease]; +#endif } -(xpc_object_t)newXPCObject{ diff --git a/XPCKit/NSFileHandle+XPCParse.m b/XPCKit/NSFileHandle+XPCParse.m index aacc053..0cea8f2 100644 --- a/XPCKit/NSFileHandle+XPCParse.m +++ b/XPCKit/NSFileHandle+XPCParse.m @@ -23,7 +23,10 @@ @implementation NSFileHandle (XPCParse) +(NSFileHandle *)fileHandleWithXPCObject:(xpc_object_t)xpc{ int fd = xpc_fd_dup(xpc); - NSFileHandle *handle = [[[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES] autorelease]; + NSFileHandle *handle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES]; +#if !__has_feature(objc_arc) + [handle autorelease]; +#endif return handle; } diff --git a/XPCKit/XPCConnection.m b/XPCKit/XPCConnection.m index c44bdec..f7a457e 100644 --- a/XPCKit/XPCConnection.m +++ b/XPCKit/XPCConnection.m @@ -37,7 +37,9 @@ - (id)initWithServiceName:(NSString *)serviceName{ -(id)initWithConnection:(xpc_connection_t)connection{ if(!connection){ +#if !__has_feature(objc_arc) [self release]; +#endif return nil; } @@ -60,8 +62,9 @@ -(void)dealloc{ xpc_release(_connection); _connection = NULL; } - +#if !__has_feature(objc_arc) [super dealloc]; +#endif } -(void)setDispatchQueue:(dispatch_queue_t)dispatchQueue{ diff --git a/XPCKit/XPCService.h b/XPCKit/XPCService.h index 1c5f9b0..8be5a88 100644 --- a/XPCKit/XPCService.h +++ b/XPCKit/XPCService.h @@ -24,7 +24,11 @@ @interface XPCService : NSObject @property (nonatomic, copy) XPCConnectionHandler connectionHandler; +#if __has_feature(objc_arc) +@property (nonatomic, strong, readonly) NSArray *connections; +#else @property (nonatomic, readonly) NSArray *connections; +#endif +(void)runServiceWithConnectionHandler:(XPCConnectionHandler)connectionHandler; -(id)initWithConnectionHandler:(XPCConnectionHandler)connectionHandler; diff --git a/XPCKit/XPCService.m b/XPCKit/XPCService.m index 7b44c45..451f39f 100644 --- a/XPCKit/XPCService.m +++ b/XPCKit/XPCService.m @@ -23,7 +23,9 @@ static void XPCServiceConnectionHandler(xpc_connection_t handler){ XPCConnection *connection = [[XPCConnection alloc] initWithConnection:handler]; [[NSNotificationCenter defaultCenter] postNotificationName:XPCConnectionReceivedNotification object:connection]; +#if !__has_feature(objc_arc) [connection release]; +#endif } @implementation XPCService @@ -71,7 +73,11 @@ +(void)runServiceWithConnectionHandler:(XPCConnectionHandler)connectionHandler{ [XPCService runService]; +#if __has_feature(objc_arc) + (void)service; // get rid of unused variable warning under ARC... +#else [service release]; +#endif } @end diff --git a/XPCKit/XPCUUID.m b/XPCKit/XPCUUID.m index 9910157..74258c9 100644 --- a/XPCKit/XPCUUID.m +++ b/XPCKit/XPCUUID.m @@ -31,7 +31,10 @@ @implementation XPCUUID +(XPCUUID *)uuid{ CFUUIDRef uuidRef = CFUUIDCreate(NULL); - XPCUUID *uuid = [[[self alloc] initWithUUIDRef:uuidRef] autorelease]; + XPCUUID *uuid = [[self alloc] initWithUUIDRef:uuidRef]; +#if !__has_feature(objc_arc) + [uuid autorelease]; +#endif CFRelease(uuidRef); return uuid; } @@ -60,7 +63,10 @@ +(XPCUUID *)uuidWithXPCObject:(xpc_object_t)xpc{ #undef CopyByte CFUUIDRef uuidRef = CFUUIDCreateFromUUIDBytes(NULL, uuidBytes); - XPCUUID *uuid = [[[self alloc] initWithUUIDRef:uuidRef] autorelease]; + XPCUUID *uuid = [[self alloc] initWithUUIDRef:uuidRef]; +#if !__has_feature(objc_arc) + [uuid autorelease]; +#endif CFRelease(uuidRef); @@ -97,7 +103,12 @@ -(xpc_object_t)newXPCObject{ } -(NSString *)string{ - return [((NSString *)CFUUIDCreateString(NULL, self.uuidRef)) autorelease]; + CFStringRef result = CFUUIDCreateString(NULL, self.uuidRef); +#if __has_feature(objc_arc) + return (__bridge NSString *)result; +#else + return [((NSString *)result) autorelease]; +#endif } -(NSString *)description{ @@ -128,7 +139,9 @@ -(void)dealloc{ _uuidRef = nil; } +#if !__has_feature(objc_arc) [super dealloc]; +#endif } @end From 91f8f1cddee64c79104d416f9058e6054a335b08 Mon Sep 17 00:00:00 2001 From: Tomaz Kragelj Date: Tue, 29 Nov 2011 12:15:45 +0100 Subject: [PATCH 2/2] Added support for errors. Errors are handled in similar way as messages - through block handler. Original xpc_object_t object is passed through, so user can check what kind of error it is (i.e. XPC_ERROR_CONNECTION_INTERRUPTED etc). Second parameter is user friendly description retrieved from the error object via xpc_dictionary_get_string() function and lastly the connection itself. --- TestApp/TestAppAppDelegate.m | 14 ++++++++++++++ XPCKit/XPCConnection.h | 1 + XPCKit/XPCConnection.m | 18 ++++++++++++++++-- XPCKit/XPCTypes.h | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/TestApp/TestAppAppDelegate.m b/TestApp/TestAppAppDelegate.m index b67fcaa..5bd5808 100644 --- a/TestApp/TestAppAppDelegate.m +++ b/TestApp/TestAppAppDelegate.m @@ -29,6 +29,20 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application mathConnection = [[XPCConnection alloc] initWithServiceName:@"com.mustacheware.TestService"]; + mathConnection.errorHandler = ^(xpc_object_t object, NSString *description, XPCConnection *inConnection) { + if (object == XPC_ERROR_CONNECTION_INTERRUPTED) { + // test by adding abort() or assert() to TestService's main.m file + NSLog(@"XPC_ERROR_CONNECTION_INTERRUPTED: %@", description); + } else if (object == XPC_ERROR_CONNECTION_INVALID) { + // test by using invalid name in initWithServiceName: above + NSLog(@"XPC_ERROR_CONNECTION_INVALID: %@", description); + } else if (object == XPC_ERROR_TERMINATION_IMMINENT) { + // Not really an error, but more like a message that the app/service is terminating AFAIK, not sure how to test it or if it even needs to be handled, but it's here for the sake of completness... + NSLog(@"XPC_ERROR_TERMINATION_IMMINENT: %@", description); + } else { + NSLog(@"ERROR: %@", description); + } + }; mathConnection.eventHandler = ^(NSDictionary *message, XPCConnection *inConnection){ NSNumber *result = [message objectForKey:@"result"]; NSData *data = [message objectForKey:@"data"]; diff --git a/XPCKit/XPCConnection.h b/XPCKit/XPCConnection.h index 0cfded9..83570f6 100644 --- a/XPCKit/XPCConnection.h +++ b/XPCKit/XPCConnection.h @@ -30,6 +30,7 @@ - (id)initWithConnection: (xpc_connection_t)connection; @property (nonatomic, copy) XPCEventHandler eventHandler; +@property (nonatomic, copy) XPCErrorHandler errorHandler; @property (nonatomic, readonly) xpc_connection_t connection; @property (nonatomic, assign) dispatch_queue_t dispatchQueue; diff --git a/XPCKit/XPCConnection.m b/XPCKit/XPCConnection.m index f7a457e..a12c14f 100644 --- a/XPCKit/XPCConnection.m +++ b/XPCKit/XPCConnection.m @@ -24,9 +24,15 @@ #define XPCSendLogMessages 1 +@interface XPCConnection () +- (void)invokeErrorHandlerWithObject:(xpc_object_t)object connection:(XPCConnection *)connection; +@end + +#pragma mark - + @implementation XPCConnection -@synthesize eventHandler=_eventHandler, dispatchQueue=_dispatchQueue, connection=_connection; +@synthesize eventHandler=_eventHandler, errorHandler=_errorHandler, dispatchQueue=_dispatchQueue, connection=_connection; - (id)initWithServiceName:(NSString *)serviceName{ xpc_connection_t connection = xpc_connection_create([serviceName cStringUsingEncoding:NSUTF8StringEncoding], NULL); @@ -84,9 +90,11 @@ -(void)receiveConnection:(xpc_connection_t)connection{ __block XPCConnection *this = self; xpc_connection_set_event_handler(connection, ^(xpc_object_t object){ if (object == XPC_ERROR_CONNECTION_INTERRUPTED){ + if (this.errorHandler) [this invokeErrorHandlerWithObject:object connection:this]; }else if (object == XPC_ERROR_CONNECTION_INVALID){ - }else if (object == XPC_ERROR_KEY_DESCRIPTION){ + if (this.errorHandler) [this invokeErrorHandlerWithObject:object connection:this]; }else if (object == XPC_ERROR_TERMINATION_IMMINENT){ + if (this.errorHandler) [this invokeErrorHandlerWithObject:object connection:this]; }else{ id message = [NSObject objectWithXPCObject: object]; @@ -122,6 +130,12 @@ -(void)sendMessage:(NSDictionary *)aDictMessage{ }); } +- (void)invokeErrorHandlerWithObject:(xpc_object_t)object connection:(XPCConnection *)connection { + const char *string = xpc_dictionary_get_string(object, XPC_ERROR_KEY_DESCRIPTION); + NSString *description = [NSString stringWithCString:string encoding:NSUTF8StringEncoding]; + connection.errorHandler(object, description, connection); +} + -(NSString *)connectionName{ __block char* name = NULL; dispatch_sync(self.dispatchQueue, ^{ diff --git a/XPCKit/XPCTypes.h b/XPCKit/XPCTypes.h index 01704db..a3884b8 100644 --- a/XPCKit/XPCTypes.h +++ b/XPCKit/XPCTypes.h @@ -23,6 +23,7 @@ @class XPCConnection; typedef void (^XPCEventHandler)(NSDictionary *, XPCConnection *); +typedef void (^XPCErrorHandler)(xpc_object_t, NSString *, XPCConnection *); typedef void (^XPCConnectionHandler)(XPCConnection *); #pragma mark Notifications