Commits

Carlos Sola-Llonch committed affa802

Initial check-in

Comments (0)

Files changed (23)

+*.xc*

LocalServerJSBridge/BundledURLCache.h

+//
+//  CustomURLCache.h
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/27/10.
+//
+
+@interface BundledURLCache : NSURLCache {
+	NSMutableDictionary *cachedResponses;
+	NSArray *bundledResources;
+}
+
+@end

LocalServerJSBridge/BundledURLCache.m

+//
+//  CustomURLCache.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/27/10.
+//
+
+#import "BundledURLCache.h"
+
+@implementation BundledURLCache
+
+- (id)init {
+	if (self = [super init]) {
+		cachedResponses = [[NSMutableDictionary alloc] init];
+		NSString *path = [[NSBundle mainBundle] pathForResource:@"BundledResources" ofType:@"plist"];
+		bundledResources = [NSArray arrayWithContentsOfFile:path];
+	}
+	return self;
+}
+
+- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
+	NSString *key = [[request URL] absoluteString];
+	NSCachedURLResponse *response = [cachedResponses objectForKey:key];
+	if (!response) {
+		NSString *fullFileName = [[request URL] lastPathComponent];
+	
+		// want a case-sensitive compare because iOS FS unlike Mac FS is case sensitive.
+		NSArray *filteredArray = [bundledResources filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"fileName = %@", fullFileName]];
+		if ([filteredArray count] > 0) {
+			// it is so load it and store
+			NSString *extension = [fullFileName pathExtension];
+			NSString *fileName = [fullFileName stringByDeletingPathExtension];
+
+			NSDictionary *resource = [filteredArray objectAtIndex:0];
+			NSURL *resourceURL = [[NSBundle mainBundle] URLForResource:fileName withExtension:extension];
+			NSString *mimeType = [resource objectForKey:@"mimeType"];
+			NSData *data = [NSData dataWithContentsOfURL:resourceURL];
+			
+			NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL] MIMEType:mimeType expectedContentLength:[data length] textEncodingName:nil];
+			NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
+			[cachedResponses setObject:cachedResponse forKey:key];
+			return cachedResponse;
+		} 
+	} else
+		return response;
+
+	return [super cachedResponseForRequest:request];
+}
+
+@end

LocalServerJSBridge/Resources/Bootstrap.js

+(function (root) {
+	root.globals = {
+		listnerPort: -1
+	};
+})(window);

LocalServerJSBridge/Resources/BundledResources.plist

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+	<dict>
+		<key>fileName</key>
+		<string>Bootstrap.js</string>
+		<key>mimeType</key>
+		<string>text/javascript</string>
+	</dict>
+	<dict>
+		<key>fileName</key>
+		<string>jXHR.js</string>
+		<key>mimeType</key>
+		<string>text/javascript</string>
+	</dict>
+</array>
+</plist>

LocalServerJSBridge/Resources/jXHR.js

+// jXHR.js (JSON-P XHR)
+// v0.1 (c) Kyle Simpson
+// MIT License
+//
+// Original source at: http://mulletxhr.com/
+// Modifications by Carlos Sola-Llonch
+
+(function(global) {
+	global.jXHR = function() {
+		var doc = global.document;
+		
+		function throwError(err) {
+			try {
+				if (typeof this.onError == 'function')
+					this.onError(err);
+			} catch (e) {}
+		}
+		
+		function handleCallback(data) {
+			if (typeof this.onComplete == 'function')
+				this.onComplete(data)
+		}
+		
+		function removeScript(scriptElem) { 
+			try { 
+				scriptElem.parentNode.removeChild(scriptElem); 
+			} catch (err) {} 
+		}
+			
+		function handleScriptLoad() {
+			this.onload = null;
+			try {
+				removeScript(this);
+			} catch (err) {}
+		}
+
+		publicAPI = {
+			onComplete: null,
+			onError: null,
+			call: function(methodName, callParam) {
+				uniqKey = (new Date()).getTime();
+				(function (key) {
+					global.jXHR[key] = function(data) {
+						try {
+							handleCallback.call(publicAPI, data);
+							delete global.jXHR[key];
+						} catch (err) {
+							throwError.call(publicAPI, err);
+						}
+					}
+				})(uniqKey);
+				jsonParam = "jsonp=" + encodeURIComponent("jXHR["+ uniqKey +"]");
+				script_url = "http://127.0.0.1:" + global.globals.listnerPort + "/" + methodName + "?" + jsonParam;
+				if (callParam != null)
+					script_url += "&" + callParam;
+				
+				script_element = doc.createElement("script");
+				script_element.setAttribute("type","text/javascript");
+				script_element.onload = function(){handleScriptLoad.call(script_element);};
+				script_element.setAttribute("src",script_url);
+				doc.getElementsByTagName("head")[0].appendChild(script_element);
+			}
+		}
+		
+		return publicAPI;
+	};
+})(window);

LocalServerJSBridge/WebServer.h

+//
+//  WebServer.h
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/27/10.
+//
+
+@class WebServer;
+
+typedef NSString * (^CommandHandler)(NSDictionary const *params, NSError **error);
+
+@protocol WebServerDelegate <NSObject>
+- (CommandHandler)handlerForCommand:(NSString *)command;
+@optional
+- (void)webServerDidStart:(WebServer *)webserver;
+- (void)webServerDidStop:(WebServer *)webserver;
+- (void)webServer:(WebServer *)webserver didFailWithError:(NSError *)error;
+@end
+
+@interface WebServer : NSObject
+
+@property (nonatomic, weak) id<WebServerDelegate> delegate;
+@property (readonly) NSUInteger currentPort;
+@property (readonly) BOOL serverStarted;
+
+- (void)startServer;
+- (void)stopServer;
+
+@end

LocalServerJSBridge/WebServer.m

+//
+//  WebServer.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/27/10.
+//
+
+#import "WebServer.h"
+#import <netinet/in.h>  // sockaddr_in
+#import <arpa/inet.h>   // inet_*
+#import <sys/socket.h>  // socket, AF_INET, getsockname
+#import <unistd.h>      // close
+#import <errno.h>       // errno
+#import <string.h>      // strerror
+
+@interface WebServer ()
+- (void)processDataForSocket:(NSValue *)socket;
+@end
+
+@implementation WebServer {
+	CFSocketRef socketRef;
+}
+
+- (id)init {
+	if (self = [super init]) {
+		_currentPort = 0;
+		_serverStarted = NO;
+	}
+	return self;
+}
+
+#define EIGHT_KB 8192
+
+- (NSString *)proxyResponseForCommand:(NSMutableDictionary *)bag {
+    NSString *result = nil;
+	NSError *err = nil;
+    CommandHandler handler = [_delegate handlerForCommand:[bag objectForKey:@"command"]];
+    if (handler) {
+        result = handler((NSDictionary const *)bag, &err);
+        if (err != nil) {
+            [bag setValue:err forKey:@"error"];
+        }
+        if (result)
+            [bag setValue:result forKey:@"response"];
+    }
+	return result;
+}
+
+- (void)processDataForSocket:(NSValue *)socket {
+    @autoreleasepool {
+        NSInteger fd;
+        [socket getValue:&fd];
+        
+        CFHTTPMessageRef request = CFHTTPMessageCreateEmpty(NULL, YES);
+        UInt8 buffer[EIGHT_KB];
+        int bytesRead;
+        while ((bytesRead = read(fd, buffer, EIGHT_KB)) > 0) {
+            CFHTTPMessageAppendBytes(request, buffer, bytesRead);
+            if (bytesRead != EIGHT_KB) break;
+        }
+        
+        if (bytesRead == -1) {
+            // TODO: handle error in delegate
+            
+        } else if (_delegate) {
+            NSURL *reqURL = CFBridgingRelease(CFHTTPMessageCopyRequestURL(request));
+            NSMutableString *command = [NSMutableString stringWithString:[reqURL path]];
+            [command deleteCharactersInRange:NSMakeRange(0, 1)];
+            
+            NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
+            NSArray *parmArray = [[reqURL query] componentsSeparatedByString:@"&"];
+            for (NSString *parm in parmArray) {
+                NSArray *keyVal = [parm componentsSeparatedByString:@"="];
+                [parameters setObject:[[keyVal objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
+                               forKey:[keyVal objectAtIndex:0]];
+            }
+            
+            NSError *err = nil;
+            CFHTTPMessageRef response = NULL;
+            
+            // force execution of delegate on main thread ....
+            NSMutableDictionary *bag = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                        [NSString stringWithString:command], @"command",
+                                        [NSDictionary dictionaryWithDictionary:parameters], @"parameters",
+                                        [NSNull null], @"response",
+                                        [NSNull null], @"error",
+                                        nil];
+            [self performSelectorOnMainThread:@selector(proxyResponseForCommand:) withObject:bag waitUntilDone:YES];
+            if ([bag objectForKey:@"error"] != [NSNull null])
+                err = [bag objectForKey:@"error"];
+            
+            if (err == nil) {
+                response = CFHTTPMessageCreateResponse(NULL, 200, NULL, kCFHTTPVersion1_0);
+                NSString *result = [bag valueForKey:@"response"] == [NSNull null] ? nil : [bag valueForKey:@"response"];
+                if (result) {
+                    NSString *resp = [NSString stringWithFormat:@"%@(\"%@\");", [parameters valueForKey:@"jsonp"], result];
+                    NSLog(@"%@", resp);
+                    
+                    NSData *bodyData = [resp dataUsingEncoding:NSUTF8StringEncoding];
+                    CFHTTPMessageSetBody(response, (__bridge CFDataRef)bodyData);
+                }
+            } else {
+                response = CFHTTPMessageCreateResponse(NULL, 500, (__bridge CFStringRef)[err localizedFailureReason], kCFHTTPVersion1_0);
+            }
+            
+            NSData *output = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(response));
+            CFRelease(response);
+            
+            if (write(fd, [output bytes], [output length]) == -1) {
+                NSString *err = [NSString stringWithCString:strerror(errno) encoding:NSASCIIStringEncoding];
+                NSLog(@"%@", err);
+            }
+        }
+        
+        close(fd);
+        CFRelease(request);
+    }
+}
+	
+void socketCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
+	// examine address....
+	char cli_addr[INET_ADDRSTRLEN];
+	struct sockaddr *saddr = (struct sockaddr *)address;
+	inet_ntop(AF_INET, saddr, cli_addr, INET_ADDRSTRLEN);
+	NSLog(@"received data request from: %s", cli_addr);
+
+	WebServer *me = (__bridge WebServer *)info;
+	int in_fd = *(CFSocketNativeHandle *)data;
+	NSValue *sockValue = [NSValue value:&in_fd withObjCType:@encode(NSInteger)];
+	[NSThread detachNewThreadSelector:@selector(processDataForSocket:) toTarget:me withObject:sockValue];
+}
+
+- (void)startServer {
+	if (_serverStarted) return;
+	
+	int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+	if (socket_fd == -1) {
+		// TODO: log stererror(errno)
+		return;
+	}
+	
+	socklen_t yes = 1;
+	if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(socklen_t)) == -1) {
+		// TODO: log stererror(errno)
+		return;
+	}
+	if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(socklen_t)) == -1) {
+		// TODO: log stererror(errno)
+		return;
+	}
+	
+	static struct sockaddr_in address;
+	address.sin_len = sizeof(struct sockaddr_in);
+	address.sin_family = AF_INET;
+	address.sin_port = 0;
+	memset(address.sin_zero, 0, sizeof(address.sin_zero));
+	
+	if ( !inet_pton(AF_INET, "127.0.0.1", &address.sin_addr) ) {
+		// TODO: log...
+		return;
+	}
+	
+	if (bind(socket_fd, (struct sockaddr *)&address, sizeof(struct sockaddr)) == -1) {
+		// TODO: log strerror(errno)
+		return;
+	}
+	
+	// get the port number that was selected
+	socklen_t sockaddr_len = sizeof(struct sockaddr);
+	if (getsockname(socket_fd, (struct sockaddr *)&address, &sockaddr_len) == -1) {
+		close(socket_fd);
+		// TODO: log stererror(errno)
+		return;
+	}
+	_currentPort = ntohs(address.sin_port);
+	
+	if (listen(socket_fd, 64) == -1) {
+		//TODO: log ....
+		return;
+	}
+	
+	CFSocketContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
+	socketRef = CFSocketCreateWithNative(kCFAllocatorDefault, socket_fd, kCFSocketAcceptCallBack, socketCallback, &context);
+	if (socketRef == NULL) {
+		// TODO: log...
+		return;
+	}
+	
+	CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socketRef, 0);
+	CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+	CFRelease(runLoopSource);
+	
+	_serverStarted = YES;
+	
+	if ([_delegate respondsToSelector:@selector(webServerDidStart:)])
+		[_delegate webServerDidStart:self];
+}
+
+- (void)stopServer {
+	CFSocketInvalidate(socketRef);
+	CFRelease(socketRef);
+
+	_currentPort = 0;
+	_serverStarted = NO;
+	
+	if ([_delegate respondsToSelector:@selector(webServerDidStop:)])
+		[_delegate webServerDidStop:self];
+}
+
+@end

SampleApp/Contacts-Info.plist

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>info.solallonch.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

SampleApp/Contacts-Prefix.pch

+//
+// Prefix header for all source files of the 'LocalServerJSBridge' target in the 'LocalServerJSBridge' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_4_0
+#warning "This project uses features only available in iOS SDK 4.0 and later."
+#endif
+
+#ifdef __OBJC__
+    #import <UIKit/UIKit.h>
+    #import <Foundation/Foundation.h>
+#endif

SampleApp/ContactsAppDelegate.h

+//
+//  ContactsAppDelegate.h
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 1/5/13.
+//  Copyright (c) 2013 Carlos Sola-Llonch.
+//
+
+#import <UIKit/UIKit.h>
+
+@class MainViewController;
+
+@interface ContactsAppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@property (strong, nonatomic) MainViewController *viewController;
+
+@end

SampleApp/ContactsAppDelegate.m

+//
+//  ContactsAppDelegate.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 1/5/13.
+//  Copyright (c) 2013 Carlos Sola-Llonch.
+//
+
+#import "ContactsAppDelegate.h"
+#import "MainViewController.h"
+#import "BundledURLCache.h"
+
+@implementation ContactsAppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+	NSURLCache *cache = [[BundledURLCache alloc] init];
+	[NSURLCache setSharedURLCache:cache];
+    
+    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+    
+    // Override point for customization after application launch.
+    self.viewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
+    self.window.rootViewController = self.viewController;
+    [self.window makeKeyAndVisible];
+    
+    return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
+    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end

SampleApp/MainViewController.h

+//
+//  MainViewController.h
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 1/5/13.
+//  Copyright (c) 2013 Carlos Sola-Llonch. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <AddressBookUI/AddressBookUI.h>
+#import "StatusView.h"
+#import "WebServer.h"
+
+@interface MainViewController : UIViewController <WebServerDelegate, ABPeoplePickerNavigationControllerDelegate>
+
+@property (weak, nonatomic) IBOutlet UIWebView *webView;
+@property (weak, nonatomic) IBOutlet UIBarButtonItem *toggleButton;
+@property (weak, nonatomic) IBOutlet UIBarButtonItem *loadPageButton;
+@property (weak, nonatomic) IBOutlet StatusView *statusView;
+@property (weak, nonatomic) IBOutlet UILabel *portLabel;
+
+- (IBAction)toggleServer:(id)sender;
+- (IBAction)loadPage:(id)sender;
+
+@end

SampleApp/MainViewController.m

+//
+//  MainViewController.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 1/5/13.
+//  Copyright (c) 2013 Carlos Sola-Llonch. All rights reserved.
+//
+
+#import "MainViewController.h"
+#import <AddressBook/AddressBook.h>
+
+@implementation MainViewController {
+    NSString *_firstName, *_lastName;
+    WebServer *_webServer;
+}
+
+#define textForNumber(portNumber)  [NSString stringWithFormat:@"listening port: %d", portNumber]
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+	// Do any additional setup after loading the view, typically from a nib.
+    _webServer = [[WebServer alloc] init];
+    _webServer.delegate = self;
+    _statusView.state = stopped;
+    _loadPageButton.enabled = NO;
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+
+- (IBAction)toggleServer:(id)sender
+{
+	if (!_webServer.serverStarted)
+		[_webServer startServer];
+	else
+		[_webServer stopServer];
+}
+
+- (IBAction)loadPage:(id)sender
+{
+	NSURL *landingURL = [[NSBundle mainBundle] URLForResource:@"Landing" withExtension:@"html"];
+	[_webView loadRequest:[NSURLRequest requestWithURL:landingURL]];
+}
+
+- (void)webViewDidFinishLoad:(UIWebView *)inWebView {
+	[inWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.globals.listnerPort=%d; showPort();", _webServer.currentPort]];
+}
+
+#pragma mark - WebServerDelegate methods
+
+- (void)webServerDidStart:(WebServer *)webserver {
+	_toggleButton.title = @"Stop";
+	_statusView.state = started;
+	_portLabel.text = textForNumber(webserver.currentPort);
+    _loadPageButton.enabled = YES;
+}
+
+- (void)webServerDidStop:(WebServer *)webserver {
+	_toggleButton.title = @"Start";
+	_statusView.state = stopped;
+	_portLabel.text = textForNumber(webserver.currentPort);
+    _loadPageButton.enabled = NO;
+}
+
+- (CommandHandler)handlerForCommand:(NSString *)command
+{
+    MainViewController * __weak weakSelf = self;
+    
+    if ([command isEqualToString:@"showContacts"]) {
+        return ^NSString *(NSDictionary const *params, NSError **error) {
+            ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
+            picker.peoplePickerDelegate = self;
+            [weakSelf presentViewController:picker animated:YES completion:nil];
+            
+            return nil;
+        };
+    } else if ([command isEqualToString:@"selectContact"]) {
+        return ^NSString *(NSDictionary const *params, NSError **error) {
+            NSString *json = [NSString stringWithFormat:@"{'fName':'%1$@','lName':'%2$@'}", _firstName, _lastName];
+            _firstName = nil;
+            _lastName = nil;
+            return json;
+        };
+    }
+    return nil;
+}
+
+#pragma mark - ABPeoplePickerNavigationControllerDelegate methods
+
+- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
+	[peoplePicker dismissViewControllerAnimated:YES completion:nil];
+}
+
+- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
+	_firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
+	_lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
+    
+	[peoplePicker dismissViewControllerAnimated:YES completion:nil];
+	[_webView stringByEvaluatingJavaScriptFromString:@"contactSelected();"];
+	return NO;
+}
+
+// not needed for our purposes, but required by protocol
+- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
+	return NO;
+}
+
+@end

SampleApp/Resources/Default-568h@2x.png

Added
New image

SampleApp/Resources/Default.png

Added
New image

SampleApp/Resources/Default@2x.png

Added
New image

SampleApp/Resources/Landing.html

+<html>
+<head>
+	<script src="Bootstrap.js"></script>
+	<script src="jXHR.js"></script>
+	<script>
+	function showPort() {
+		document.getElementById('port').innerHTML = "listening on port: " + globals.listnerPort;
+	}
+	function requestContacts() {
+		xhr = new jXHR();
+		xhr.onError = function() {
+			alert('failure');
+		}
+		xhr.call("showContacts", null);
+	}
+	function contactSelected() {
+		xhr = new jXHR();
+		xhr.onComplete  = function(data) {
+			var obj = eval('(' + data + ')');
+			alert (obj.fName);
+		};
+		xhr.call("selectContact", null);
+	}
+	</script>
+</head>
+<body>
+	<div id="port"></div>
+	<input type="button" onclick="requestContacts();" value="Show Contacts" />
+	<br/>
+	
+</body>
+</html>

SampleApp/StatusView.h

+//
+//  StatusView.h
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/30/10.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum  {
+	started,
+	stopped
+} StatusState;
+
+@interface StatusView : UIView {
+	StatusState state;
+}
+
+@property (nonatomic, assign) StatusState state;
+
+@end

SampleApp/StatusView.m

+//
+//  StatusView.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 12/30/10.
+//
+
+#import "StatusView.h"
+
+@implementation StatusView
+
+@synthesize state;
+
+- (id)initWithFrame:(CGRect)frame {
+    
+    self = [super initWithFrame:frame];
+    if (self) {
+		state = stopped;
+    }
+    return self;
+}
+
+- (void)drawRect:(CGRect)rect {
+	CGContextRef context = UIGraphicsGetCurrentContext();
+	CGContextSetFillColorWithColor(context, (state == stopped ? [UIColor redColor].CGColor : [UIColor greenColor].CGColor));
+	CGContextAddEllipseInRect(context, rect);
+	CGContextFillPath(context);
+}
+
+- (void)setState:(StatusState)newState {
+	if (state == newState) return;
+	state = newState;
+	[self setNeedsDisplay];
+}
+
+@end

SampleApp/en.lproj/InfoPlist.strings

+/* Localized versions of Info.plist keys */
+

SampleApp/en.lproj/MainViewController.xib

+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1536</int>
+		<string key="IBDocument.SystemVersion">12C60</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2844</string>
+		<string key="IBDocument.AppKitVersion">1187.34</string>
+		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			<string key="NS.object.0">1930</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>IBNSLayoutConstraint</string>
+			<string>IBProxyObject</string>
+			<string>IBUIBarButtonItem</string>
+			<string>IBUILabel</string>
+			<string>IBUIToolbar</string>
+			<string>IBUIView</string>
+			<string>IBUIWebView</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="IBProxyObject" id="372490531">
+				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+			<object class="IBProxyObject" id="843779117">
+				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+			<object class="IBUIView" id="774585933">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">274</int>
+				<array class="NSMutableArray" key="NSSubviews">
+					<object class="IBUIToolbar" id="279251915">
+						<reference key="NSNextResponder" ref="774585933"/>
+						<int key="NSvFlags">266</int>
+						<array class="NSMutableArray" key="NSSubviews">
+							<object class="IBUIView" id="587407037">
+								<reference key="NSNextResponder" ref="279251915"/>
+								<int key="NSvFlags">292</int>
+								<array class="NSMutableArray" key="NSSubviews">
+									<object class="IBUILabel" id="665161247">
+										<reference key="NSNextResponder" ref="587407037"/>
+										<int key="NSvFlags">292</int>
+										<string key="NSFrame">{{27, 3}, {109, 20}}</string>
+										<reference key="NSSuperview" ref="587407037"/>
+										<reference key="NSNextKeyView" ref="532092340"/>
+										<bool key="IBUIOpaque">NO</bool>
+										<bool key="IBUIClipsSubviews">YES</bool>
+										<int key="IBUIContentMode">7</int>
+										<bool key="IBUIUserInteractionEnabled">NO</bool>
+										<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+										<string key="IBUIText">Server Status</string>
+										<object class="NSColor" key="IBUITextColor">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MQA</bytes>
+											<object class="NSColorSpace" key="NSCustomColorSpace" id="150136543">
+												<int key="NSID">2</int>
+											</object>
+										</object>
+										<object class="NSColor" key="IBUIHighlightedColor" id="196963542">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MQA</bytes>
+										</object>
+										<object class="NSColor" key="IBUIShadowColor" id="143364514">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MC4zMzMzMzMzMzMzAA</bytes>
+										</object>
+										<int key="IBUIBaselineAdjustment">1</int>
+										<float key="IBUIMinimumFontSize">10</float>
+										<object class="IBUIFontDescription" key="IBUIFontDescription">
+											<string key="name">Helvetica-Bold</string>
+											<string key="family">Helvetica</string>
+											<int key="traits">2</int>
+											<double key="pointSize">16</double>
+										</object>
+										<object class="NSFont" key="IBUIFont">
+											<string key="NSName">Helvetica-Bold</string>
+											<double key="NSSize">16</double>
+											<int key="NSfFlags">16</int>
+										</object>
+										<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+									</object>
+									<object class="IBUILabel" id="532092340">
+										<reference key="NSNextResponder" ref="587407037"/>
+										<int key="NSvFlags">292</int>
+										<string key="NSFrame">{{5, 24}, {125, 14}}</string>
+										<reference key="NSSuperview" ref="587407037"/>
+										<reference key="NSNextKeyView" ref="720663845"/>
+										<bool key="IBUIOpaque">NO</bool>
+										<bool key="IBUIClipsSubviews">YES</bool>
+										<int key="IBUIContentMode">7</int>
+										<bool key="IBUIUserInteractionEnabled">NO</bool>
+										<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+										<string key="IBUIText">Listening port:</string>
+										<object class="NSColor" key="IBUITextColor">
+											<int key="NSColorSpace">1</int>
+											<bytes key="NSRGB">MSAxIDEgMC42AA</bytes>
+											<string key="IBUIColorCocoaTouchKeyPath">lightTextColor</string>
+										</object>
+										<reference key="IBUIHighlightedColor" ref="196963542"/>
+										<reference key="IBUIShadowColor" ref="143364514"/>
+										<int key="IBUIBaselineAdjustment">1</int>
+										<float key="IBUIMinimumFontSize">10</float>
+										<int key="IBUITextAlignment">1</int>
+										<object class="IBUIFontDescription" key="IBUIFontDescription">
+											<string key="name">Helvetica-Bold</string>
+											<string key="family">Helvetica</string>
+											<int key="traits">2</int>
+											<double key="pointSize">12</double>
+										</object>
+										<object class="NSFont" key="IBUIFont">
+											<string key="NSName">Helvetica-Bold</string>
+											<double key="NSSize">12</double>
+											<int key="NSfFlags">16</int>
+										</object>
+										<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+									</object>
+									<object class="IBUIView" id="1017839451">
+										<reference key="NSNextResponder" ref="587407037"/>
+										<int key="NSvFlags">292</int>
+										<string key="NSFrame">{{5, 5}, {17, 17}}</string>
+										<reference key="NSSuperview" ref="587407037"/>
+										<reference key="NSNextKeyView" ref="665161247"/>
+										<object class="NSColor" key="IBUIBackgroundColor" id="409838713">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MCAwAA</bytes>
+										</object>
+										<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+									</object>
+								</array>
+								<string key="NSFrame">{{92, 2}, {136, 40}}</string>
+								<reference key="NSSuperview" ref="279251915"/>
+								<reference key="NSNextKeyView" ref="1017839451"/>
+								<reference key="IBUIBackgroundColor" ref="409838713"/>
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+							</object>
+						</array>
+						<string key="NSFrameSize">{320, 44}</string>
+						<reference key="NSSuperview" ref="774585933"/>
+						<reference key="NSNextKeyView" ref="587407037"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+						<array class="NSMutableArray" key="IBUIItems">
+							<object class="IBUIBarButtonItem" id="38459539">
+								<string key="IBUITitle">Start</string>
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+								<int key="IBUIStyle">1</int>
+								<reference key="IBUIToolbar" ref="279251915"/>
+							</object>
+							<object class="IBUIBarButtonItem" id="1060149316">
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+								<reference key="IBUIToolbar" ref="279251915"/>
+								<int key="IBUISystemItemIdentifier">5</int>
+							</object>
+							<object class="IBUIBarButtonItem" id="784266875">
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+								<reference key="IBUICustomView" ref="587407037"/>
+								<reference key="IBUIToolbar" ref="279251915"/>
+							</object>
+							<object class="IBUIBarButtonItem" id="589716161">
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+								<reference key="IBUIToolbar" ref="279251915"/>
+								<int key="IBUISystemItemIdentifier">5</int>
+							</object>
+							<object class="IBUIBarButtonItem" id="1045069770">
+								<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+								<int key="IBUIStyle">1</int>
+								<reference key="IBUIToolbar" ref="279251915"/>
+								<int key="IBUISystemItemIdentifier">13</int>
+							</object>
+						</array>
+					</object>
+					<object class="IBUIWebView" id="720663845">
+						<reference key="NSNextResponder" ref="774585933"/>
+						<int key="NSvFlags">274</int>
+						<string key="NSFrame">{{0, 44}, {320, 504}}</string>
+						<reference key="NSSuperview" ref="774585933"/>
+						<reference key="NSNextKeyView"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<object class="NSColor" key="IBUIBackgroundColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MSAxIDEAA</bytes>
+						</object>
+						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+						<int key="IBUIDataDetectorTypes">1</int>
+						<bool key="IBUIDetectsPhoneNumbers">YES</bool>
+					</object>
+				</array>
+				<string key="NSFrame">{{0, 20}, {320, 548}}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSNextKeyView" ref="279251915"/>
+				<object class="NSColor" key="IBUIBackgroundColor">
+					<int key="NSColorSpace">3</int>
+					<bytes key="NSWhite">MC43NQA</bytes>
+					<reference key="NSCustomColorSpace" ref="150136543"/>
+				</object>
+				<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+				<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+				<object class="IBUIScreenMetrics" key="IBUISimulatedDestinationMetrics">
+					<string key="IBUISimulatedSizeMetricsClass">IBUIScreenMetrics</string>
+					<object class="NSMutableDictionary" key="IBUINormalizedOrientationToSizeMap">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<array key="dict.sortedKeys">
+							<integer value="1"/>
+							<integer value="3"/>
+						</array>
+						<array key="dict.values">
+							<string>{320, 568}</string>
+							<string>{568, 320}</string>
+						</array>
+					</object>
+					<string key="IBUITargetRuntime">IBCocoaTouchFramework</string>
+					<string key="IBUIDisplayName">Retina 4 Full Screen</string>
+					<int key="IBUIType">2</int>
+				</object>
+				<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="774585933"/>
+					</object>
+					<int key="connectionID">8</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">webView</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="720663845"/>
+					</object>
+					<int key="connectionID">14</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">statusView</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="1017839451"/>
+					</object>
+					<int key="connectionID">57</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">portLabel</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="532092340"/>
+					</object>
+					<int key="connectionID">58</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">toggleButton</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="38459539"/>
+					</object>
+					<int key="connectionID">59</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">loadPageButton</string>
+						<reference key="source" ref="372490531"/>
+						<reference key="destination" ref="1045069770"/>
+					</object>
+					<int key="connectionID">60</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="720663845"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">15</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">toggleServer:</string>
+						<reference key="source" ref="38459539"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">55</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">loadPage:</string>
+						<reference key="source" ref="1045069770"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">56</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="372490531"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="843779117"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="774585933"/>
+						<array class="NSMutableArray" key="children">
+							<object class="IBNSLayoutConstraint" id="148395034">
+								<reference key="firstItem" ref="720663845"/>
+								<int key="firstAttribute">4</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">4</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="419626366">
+								<reference key="firstItem" ref="720663845"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="279251915"/>
+								<int key="secondAttribute">4</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">6</int>
+								<float key="scoringTypeFloat">24</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="209832979">
+								<reference key="firstItem" ref="720663845"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="634731819">
+								<reference key="firstItem" ref="720663845"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="280541350">
+								<reference key="firstItem" ref="279251915"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="439104040">
+								<reference key="firstItem" ref="279251915"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="1010579389">
+								<reference key="firstItem" ref="279251915"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="774585933"/>
+								<int key="secondAttribute">3</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="774585933"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<reference ref="279251915"/>
+							<reference ref="720663845"/>
+						</array>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="279251915"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="38459539"/>
+							<reference ref="784266875"/>
+							<reference ref="589716161"/>
+							<reference ref="1045069770"/>
+							<reference ref="1060149316"/>
+						</array>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="1010579389"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="439104040"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="280541350"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="38459539"/>
+						<reference key="parent" ref="279251915"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="784266875"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="587407037"/>
+						</array>
+						<reference key="parent" ref="279251915"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="1045069770"/>
+						<reference key="parent" ref="279251915"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="589716161"/>
+						<reference key="parent" ref="279251915"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="1060149316"/>
+						<reference key="parent" ref="279251915"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">26</int>
+						<reference key="object" ref="587407037"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="532092340"/>
+							<reference ref="665161247"/>
+							<reference ref="1017839451"/>
+							<object class="IBNSLayoutConstraint" id="741924319">
+								<reference key="firstItem" ref="665161247"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="587407037"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">8</int>
+								<float key="scoringTypeFloat">29</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="1056538488">
+								<reference key="firstItem" ref="665161247"/>
+								<int key="firstAttribute">10</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="1017839451"/>
+								<int key="secondAttribute">10</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">6</int>
+								<float key="scoringTypeFloat">24</float>
+								<int key="contentType">2</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="350893275">
+								<reference key="firstItem" ref="665161247"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="587407037"/>
+								<int key="secondAttribute">3</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">3</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="659500736">
+								<reference key="firstItem" ref="587407037"/>
+								<int key="firstAttribute">4</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="532092340"/>
+								<int key="secondAttribute">4</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">2</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="624492617">
+								<reference key="firstItem" ref="1017839451"/>
+								<int key="firstAttribute">3</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="587407037"/>
+								<int key="secondAttribute">3</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">5</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="82048663">
+								<reference key="firstItem" ref="1017839451"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="532092340"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">0.0</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">6</int>
+								<float key="scoringTypeFloat">24</float>
+								<int key="contentType">2</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="517687204">
+								<reference key="firstItem" ref="587407037"/>
+								<int key="firstAttribute">6</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="1017839451"/>
+								<int key="secondAttribute">6</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">114</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">3</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="930314278">
+								<reference key="firstItem" ref="1017839451"/>
+								<int key="firstAttribute">5</int>
+								<int key="relation">0</int>
+								<reference key="secondItem" ref="587407037"/>
+								<int key="secondAttribute">5</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">5</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="587407037"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">3</int>
+							</object>
+						</array>
+						<reference key="parent" ref="784266875"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="532092340"/>
+						<array class="NSMutableArray" key="children">
+							<object class="IBNSLayoutConstraint" id="140375450">
+								<reference key="firstItem" ref="532092340"/>
+								<int key="firstAttribute">7</int>
+								<int key="relation">0</int>
+								<nil key="secondItem"/>
+								<int key="secondAttribute">0</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">125</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="532092340"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">1</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="833066851">
+								<reference key="firstItem" ref="532092340"/>
+								<int key="firstAttribute">8</int>
+								<int key="relation">0</int>
+								<nil key="secondItem"/>
+								<int key="secondAttribute">0</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">14</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="532092340"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">1</int>
+							</object>
+						</array>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="665161247"/>
+						<array class="NSMutableArray" key="children">
+							<object class="IBNSLayoutConstraint" id="66546388">
+								<reference key="firstItem" ref="665161247"/>
+								<int key="firstAttribute">7</int>
+								<int key="relation">0</int>
+								<nil key="secondItem"/>
+								<int key="secondAttribute">0</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">109</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="665161247"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">1</int>
+							</object>
+							<object class="IBNSLayoutConstraint" id="661624909">
+								<reference key="firstItem" ref="665161247"/>
+								<int key="firstAttribute">8</int>
+								<int key="relation">0</int>
+								<nil key="secondItem"/>
+								<int key="secondAttribute">0</int>
+								<float key="multiplier">1</float>
+								<object class="IBLayoutConstant" key="constant">
+									<double key="value">20</double>
+								</object>
+								<float key="priority">1000</float>
+								<reference key="containingView" ref="665161247"/>
+								<int key="scoringType">3</int>
+								<float key="scoringTypeFloat">9</float>
+								<int key="contentType">1</int>
+							</object>
+						</array>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="1017839451"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="930314278"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="659500736"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="350893275"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="517687204"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="1056538488"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="82048663"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">37</int>
+						<reference key="object" ref="624492617"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">38</int>
+						<reference key="object" ref="661624909"/>
+						<reference key="parent" ref="665161247"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="833066851"/>
+						<reference key="parent" ref="532092340"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">41</int>
+						<reference key="object" ref="140375450"/>
+						<reference key="parent" ref="532092340"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="720663845"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="634731819"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">48</int>
+						<reference key="object" ref="209832979"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">50</int>
+						<reference key="object" ref="419626366"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">51</int>
+						<reference key="object" ref="148395034"/>
+						<reference key="parent" ref="774585933"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">52</int>
+						<reference key="object" ref="741924319"/>
+						<reference key="parent" ref="587407037"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">53</int>
+						<reference key="object" ref="66546388"/>
+						<reference key="parent" ref="665161247"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.CustomClassName">MainViewController</string>
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="-2.CustomClassName">UIResponder</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="16.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<boolean value="NO" key="16.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="18.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="19.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="20.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="21.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="24.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="25.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<array class="NSMutableArray" key="26.IBViewMetadataConstraints">
+					<reference ref="930314278"/>
+					<reference ref="517687204"/>
+					<reference ref="82048663"/>
+					<reference ref="624492617"/>
+					<reference ref="659500736"/>
+					<reference ref="350893275"/>
+					<reference ref="1056538488"/>
+					<reference ref="741924319"/>
+				</array>
+				<string key="27.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<array key="27.IBViewMetadataConstraints">
+					<reference ref="833066851"/>
+					<reference ref="140375450"/>
+				</array>
+				<boolean value="NO" key="27.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="28.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<array class="NSMutableArray" key="28.IBViewMetadataConstraints">
+					<reference ref="661624909"/>
+					<reference ref="66546388"/>
+				</array>
+				<boolean value="NO" key="28.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="29.CustomClassName">StatusView</string>
+				<string key="29.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<boolean value="NO" key="29.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+				<string key="30.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="31.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="32.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="33.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="34.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="36.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="37.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="40.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="41.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="46.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="48.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="50.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="51.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="52.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="53.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<array key="6.IBViewMetadataConstraints">
+					<reference ref="1010579389"/>
+					<reference ref="439104040"/>
+					<reference ref="280541350"/>
+					<reference ref="634731819"/>
+					<reference ref="209832979"/>
+					<reference ref="419626366"/>
+					<reference ref="148395034"/>
+				</array>
+				<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<boolean value="NO" key="9.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">60</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes"/>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<bool key="IBDocument.UseAutolayout">YES</bool>
+		<string key="IBCocoaTouchPluginVersion">1930</string>
+	</data>
+</archive>
+//
+//  main.m
+//  LocalServerJSBridge
+//
+//  Created by Carlos Sola-Llonch on 1/5/13.
+//  Copyright (c) 2013 Carlos Sola-Llonch. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "ContactsAppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+    @autoreleasepool {
+        return UIApplicationMain(argc, argv, nil, NSStringFromClass([ContactsAppDelegate class]));
+    }
+}