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:
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) {