shlist

share and manage lists between multiple people
Log | Files | Refs

commit 90a32f54f1b8d585ac939c762d93b0e4cd1cb8cb
parent 94668258c864cec02b1df5cf70a91add0940c226
Author: Kyle Milz <kyle@Kyles-MacBook-Pro.local>
Date:   Sun, 20 Sep 2015 13:52:28 -0600

ios: make Network object a singleton

+ add the ability to connect/reconnect when app is backgrounded/foregrounded

Diffstat:
Mios-ng/shlist/AppDelegate.m | 18+++++++++++++++++-
Mios-ng/shlist/MainTableViewController.m | 61+++++++++++++++++++++++++++++++++----------------------------
Mios-ng/shlist/Network.h | 7+++++++
Mios-ng/shlist/Network.m | 49+++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 100 insertions(+), 35 deletions(-)

diff --git a/ios-ng/shlist/AppDelegate.m b/ios-ng/shlist/AppDelegate.m @@ -1,6 +1,9 @@ #import "AppDelegate.h" +#import "Network.h" -@interface AppDelegate () +@interface AppDelegate () { + Network *network_connection; +} @end @@ -9,6 +12,9 @@ - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // we need to issue connect/reconnects from here + network_connection = [Network shared_network_connection]; + // customization after application launch return YES; } @@ -34,6 +40,9 @@ // terminated later. // If your application supports background execution, this method is // called instead of applicationWillTerminate: when the user quits. + + NSLog(@"info: app: entering background, disconnecting network"); + [network_connection disconnect]; } - (void) applicationWillEnterForeground:(UIApplication *)application @@ -41,6 +50,10 @@ // 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. + + NSLog(@"info: app: entering foreground, reconnecting..."); + [network_connection connect]; + [network_connection send_message:3 contents:nil]; } - (void) applicationDidBecomeActive:(UIApplication *)application @@ -54,6 +67,9 @@ { // Called when the application is about to terminate. Save data if // appropriate. See also applicationDidEnterBackground:. + + NSLog(@"info: app: teminating, disconnecting network"); + [network_connection disconnect]; } @end \ No newline at end of file diff --git a/ios-ng/shlist/MainTableViewController.m b/ios-ng/shlist/MainTableViewController.m @@ -8,19 +8,18 @@ #include "libkern/OSAtomic.h" @interface MainTableViewController () { + NSString *phone_number; + Network *network_connection; NSString *phone_num_file; } -@property (strong, nonatomic) Network *server; @property NSMutableDictionary *phnum_to_name_map; @property (strong, retain) AddressBook *address_book; -@property (strong, nonatomic) NSString *phone_number; @end @implementation MainTableViewController - - (void) viewDidLoad { [super viewDidLoad]; @@ -28,6 +27,10 @@ // display an Edit button in the navigation bar for this view controller self.navigationItem.leftBarButtonItem = self.editButtonItem; + // there's a race here when assigning self + network_connection = [Network shared_network_connection]; + network_connection->shlist_tvc = self; + // main lists self.shared_lists = [[NSMutableArray alloc] init]; self.indirect_lists = [[NSMutableArray alloc] init]; @@ -37,22 +40,20 @@ NSString *documentsDirectory = [paths objectAtIndex:0]; phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"]; - _server = [[Network alloc] init]; - _server->shlist_tvc = self; - - _phnum_to_name_map = [[NSMutableDictionary alloc] init]; - _phone_number = nil; + phone_number = nil; if ([self load_phone_number]) { // phone number loaded, try loading device id - if ([_server load_device_id:[_phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { + if ([network_connection load_device_id:[phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { NSLog(@"info: network: connection ready"); // bulk update, doesn't take a payload - [_server send_message:3 contents:nil]; + [network_connection send_message:3 contents:nil]; } // else, device id request sent } // else, phone number entry is on screen + _phnum_to_name_map = [[NSMutableDictionary alloc] init]; + // get instance and wait for privacy window to clear _address_book = [AddressBook shared_address_book]; _address_book.main_tvc = self; @@ -63,7 +64,7 @@ if ([[NSFileManager defaultManager] fileExistsAtPath:phone_num_file]) { // file exists, read what it has // XXX: validate length of file too - _phone_number = [NSString stringWithContentsOfFile:phone_num_file]; + phone_number = [NSString stringWithContentsOfFile:phone_num_file]; return true; } @@ -83,7 +84,7 @@ } - (void)alertView:(UIAlertView *)alertView - clickedButtonAtIndex:(NSInteger)buttonIndex +clickedButtonAtIndex:(NSInteger)buttonIndex { NSString *entered_phone_num = [[alertView textFieldAtIndex:0] text]; NSLog(@"warn: main: writing phone num '%@' to disk", entered_phone_num); @@ -97,12 +98,12 @@ NSLog(@"warn: load phone number: entered emtpy phone number"); } - _phone_number = entered_phone_num; + phone_number = entered_phone_num; - if ([_server load_device_id:[_phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { + if ([network_connection load_device_id:[phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { NSLog(@"info: network: connection ready"); // bulk update, doesn't take a payload - [_server send_message:3 contents:nil]; + [network_connection send_message:3 contents:nil]; } // else, device id request sent } @@ -129,8 +130,8 @@ disp_name = @"No Name"; // map the persons known phone number to their massaged name - for (NSString *phone_number in contact.phone_numbers) - [_phnum_to_name_map setObject:disp_name forKey:phone_number]; + for (NSString *tmp_phone_number in contact.phone_numbers) + [_phnum_to_name_map setObject:disp_name forKey:tmp_phone_number]; } } @@ -169,12 +170,16 @@ // good to save NSData *payload = [list.name dataUsingEncoding:NSUTF8StringEncoding]; - [_server send_message:1 contents:payload]; + [network_connection send_message:1 contents:payload]; } - (void) finished_new_list_request:(SharedList *) shlist { + // shlist.cell = [self.tableView cellForRowAtIndexPath:] [self.shared_lists addObject:shlist]; + + // [self.tableView insertRowsAtIndexPaths:index_path withRowAnimation:UITableViewRowAnimationMiddle]; + [self.tableView reloadData]; } @@ -193,7 +198,7 @@ NSLog(@"info: joining list '%@'", list.name); // the response for this does all of the heavy row moving work - [_server send_message:4 contents:list.id]; + [network_connection send_message:4 contents:list.id]; } - (void) finished_join_list_request:(SharedList *) shlist @@ -323,13 +328,13 @@ if (!OSAtomicAnd32(0xffff, &_address_book->ready)) { // not ready NSMutableString *output = [[NSMutableString alloc] init]; - for (id phone_number in phnum_array) { - if ([phone_number compare:_phone_number] == NSOrderedSame) { + for (id tmp_phone_number in phnum_array) { + if ([tmp_phone_number compare:phone_number] == NSOrderedSame) { [output appendString:@"You"]; continue; } - [output appendFormat:@", %@", phone_number]; + [output appendFormat:@", %@", tmp_phone_number]; } return output; } @@ -339,14 +344,14 @@ int others = 0; // anything past the second field are list members - for (id phone_number in phnum_array) { + for (id tmp_phone_number in phnum_array) { // try to find the list member in our address book - NSString *name = _phnum_to_name_map[phone_number]; + NSString *name = _phnum_to_name_map[tmp_phone_number]; if (name) [members addObject:name]; - else if (_phone_number && ([_phone_number compare:phone_number] == NSOrderedSame)) + else if (phone_number && ([phone_number compare:tmp_phone_number] == NSOrderedSame)) [members addObject:@"You"]; else // didn't find it, you don't know this person @@ -409,7 +414,7 @@ NSLog(@"info: leaving '%@' id '%@'", list.name, list.id); // send leave list message, response will do all heavy lifting - [_server send_message:5 contents:list.id]; + [network_connection send_message:5 contents:list.id]; } - (NSString *)tableView:(UITableView *)tableView @@ -434,10 +439,10 @@ [segue.destinationViewController setMetadata:list]; // has to be done before issuing network request - _server->shlist_ldvc = segue.destinationViewController; + network_connection->shlist_ldvc = segue.destinationViewController; // send update list items message - [_server send_message:6 contents:list.id]; + [network_connection send_message:6 contents:list.id]; } // DetailObject *detail = [self detailForIndexPath:path];ß diff --git a/ios-ng/shlist/Network.h b/ios-ng/shlist/Network.h @@ -14,7 +14,14 @@ } +- (void) connect; +- (void) disconnect; + +// only networking really cares about the device id - (bool) load_device_id:(NSData*)phone_number; - (void) send_message:(uint16_t)msg_type contents:(NSData *)data; +// returns singleton instance ++ (id) shared_network_connection; + @end \ No newline at end of file diff --git a/ios-ng/shlist/Network.m b/ios-ng/shlist/Network.m @@ -23,12 +23,23 @@ @implementation Network ++ (id) shared_network_connection +{ + static Network *network_connection = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + network_connection = [[self alloc] init]; + }); + return network_connection; +} + - (id) init { if (self = [super init]) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; device_id_file = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; + device_id = nil; msg_buf_position = 0; @@ -45,6 +56,8 @@ - (void) connect { + NSLog(@"info: network: connecting"); + CFReadStreamRef readStream; CFWriteStreamRef writeStream; @@ -62,12 +75,12 @@ [inputShlistStream open]; [outputShlistStream open]; - - NSLog(@"info: network: bound to amp.ca"); } - (void) disconnect { + NSLog(@"info: network: disconnecting"); + [inputShlistStream close]; [outputShlistStream close]; @@ -114,6 +127,7 @@ - (void) send_message:(uint16_t)send_msg_type contents:(NSData *)payload { NSMutableData *msg = [NSMutableData data]; + NSLog(@"info: network: send_message: msg type %i", send_msg_type); uint16_t msg_type_network = htons(send_msg_type); [msg appendBytes:&msg_type_network length:2]; @@ -126,6 +140,10 @@ uint16_t msg_len_network = htons([device_id length] + payload_length); [msg appendBytes:&msg_len_network length:2]; + if (device_id == nil) { + NSLog(@"warn: network: send_message called before device_id was ready"); + return; + } [msg appendData:device_id]; if (payload) { @@ -142,6 +160,7 @@ NSLog(@"warn: network: resend failed after reconnect, giving up"); } } + NSLog(@"info: network: send_message: msg type %i done", send_msg_type); } - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode @@ -154,6 +173,7 @@ switch (eventCode) { case NSStreamEventNone: + NSLog(@"NSStreamEventNone"); break; case NSStreamEventOpenCompleted: NSLog(@"info: network: %@ stream opened", stream_name); @@ -187,6 +207,7 @@ break; default: + NSLog(@"handleEvent: default case"); break; } } @@ -357,12 +378,15 @@ NSLog(@"info: network: response for new list '%@' has %i fields", shlist.name, [fields count]); - [shlist_tvc finished_new_list_request:shlist]; + if ([self check_tvc:shlist_tvc]) + [shlist_tvc finished_new_list_request:shlist]; } else if (msg_type == 3) { [self handle_bulk_list_update:msg_string]; - [shlist_tvc.tableView reloadData]; + + if ([self check_tvc:shlist_tvc]) + [shlist_tvc.tableView reloadData]; } else if (msg_type == 4) { @@ -377,7 +401,8 @@ // shlist.list_name = <network>; // shlist.members = <network>; - [shlist_tvc finished_join_list_request:shlist]; + if ([self check_tvc:shlist_tvc]) + [shlist_tvc finished_join_list_request:shlist]; } else if (msg_type == 5) { @@ -398,14 +423,26 @@ // shlist.list_name = <network>; // shlist.members = <network>; - [shlist_tvc finished_leave_list_request:shlist]; + if ([self check_tvc:shlist_tvc]) + [shlist_tvc finished_leave_list_request:shlist]; } } +- (bool) check_tvc:(MainTableViewController *) tvc +{ + if (tvc) + return true; + NSLog(@"warn: network: trying to update main_tvc before it's ready, ignoring!"); + return false; +} + - (void) handle_bulk_list_update:(NSString *)raw_data { NSLog(@"info: handling bulk list update message"); + if (![self check_tvc:shlist_tvc]) + return; + // split over double \0 NSArray *list_types = [raw_data componentsSeparatedByString:@"\0\0"]; if ([list_types count] != 2) {