commit 170227102196f4a0daa65e1bf12d3486d3ad65fa
parent 3cdd0ec015130c97c175e9382a91bca5cb143815
Author: Kyle Milz <kyle@Kyles-MacBook-Pro.local>
Date: Sun, 20 Sep 2015 02:20:42 -0600
ios: move phone number resolution into cell generation
This allows me to do a non-blocking address book request, which is nice.
Diffstat:
7 files changed, 122 insertions(+), 109 deletions(-)
diff --git a/ios-ng/shlist/AddressBook.h b/ios-ng/shlist/AddressBook.h
@@ -1,6 +1,11 @@
#import <Foundation/Foundation.h>
-@interface AddressBook : NSObject
+#import "MainTableViewController.h"
+
+
+@interface AddressBook : NSObject {
+ @public volatile uint32_t ready;
+}
@property (strong, retain) NSMutableArray *contacts;
@property unsigned long num_contacts;
@@ -8,9 +13,7 @@
// returns singleton instance
+ (id) shared_address_book;
-- (void) wait_for_ready;
-
-@property volatile uint32_t ready;
+@property (strong, nonatomic) MainTableViewController *main_tvc;
@end
diff --git a/ios-ng/shlist/AddressBook.m b/ios-ng/shlist/AddressBook.m
@@ -1,4 +1,5 @@
#import "AddressBook.h"
+
#include <AddressBook/AddressBook.h>
#import <UIKit/UIKit.h>
@@ -6,8 +7,6 @@
@interface AddressBook ()
-// - (void) get_contacts_or_fail;
-
@end
// empty implementation
@@ -32,7 +31,7 @@
if (self)
{
_contacts = [[NSMutableArray alloc] init];
- _ready = 0;
+ ready = 0;
[self get_contacts_or_fail];
}
return self;
@@ -70,10 +69,14 @@
if (granted) {
// if they gave you permission, then just carry on
[self listPeopleInAddressBook:addressBook];
+ if (_main_tvc)
+ [_main_tvc update_address_book];
+ else
+ NSLog(@"warn: address book: address book ready before main_tvc assigned!");
// atomically set the ready flag; this completion handler
// can be run on an arbitrary thread
- OSAtomicIncrement32((volatile int32_t *)&_ready);
+ OSAtomicIncrement32((volatile int32_t *)&ready);
} else {
// however, if they didn't give you permission, handle it gracefully, for example...
@@ -125,25 +128,4 @@
NSLog(@"info: address book: %lu contacts found", _num_contacts);
}
-// call this to make the address book authorization block
-- (void) wait_for_ready
-{
- int cumulative_ms = 0;
- int sleep_for_ms = 10;
- // wait for the database to become ready, no upper bound
- while (!OSAtomicAnd32(0xffff, &_ready)) {
- usleep(sleep_for_ms * 1000);
- cumulative_ms += sleep_for_ms;
-
- // if we've spun for over a second reduce polling speed
- if (cumulative_ms > 1 * 1000) {
- NSLog(@"warn: address book: not ready for more than %i s",
- cumulative_ms / 1000);
- sleep_for_ms = 1 * 1000;
- }
- }
-
- NSLog(@"info: address book: ready after %i ms", cumulative_ms);
-}
-
@end
\ No newline at end of file
diff --git a/ios-ng/shlist/DataStructures.h b/ios-ng/shlist/DataStructures.h
@@ -9,7 +9,7 @@
@property NSString *name;
@property NSData *id;
-@property NSString *members;
+@property NSArray *members_phone_nums;
@property NSDate *date;
@property int items_ready;
@property int items_total;
diff --git a/ios-ng/shlist/MainTableViewController.h b/ios-ng/shlist/MainTableViewController.h
@@ -7,6 +7,8 @@
@property NSMutableArray *shared_lists;
@property NSMutableArray *indirect_lists;
+- (void) update_address_book;
+
- (void) finished_new_list_request:(SharedList *) shlist;
- (void) finished_join_list_request:(SharedList *) shlist;
- (void) finished_leave_list_request:(SharedList *) shlist;
diff --git a/ios-ng/shlist/MainTableViewController.m b/ios-ng/shlist/MainTableViewController.m
@@ -1,13 +1,18 @@
+#import "AddressBook.h"
#import "MainTableViewController.h"
#import "NewListViewController.h"
#import "Network.h"
#import "ListTableViewController.h"
#import <AddressBook/AddressBook.h>
+#include "libkern/OSAtomic.h"
@interface MainTableViewController ()
@property (strong, nonatomic) Network *server;
+@property NSMutableDictionary *phnum_to_name_map;
+@property (strong, retain) AddressBook *address_book;
+@property (strong, nonatomic) NSString *phone_number;
@end
@@ -24,6 +29,12 @@
self.shared_lists = [[NSMutableArray alloc] init];
self.indirect_lists = [[NSMutableArray alloc] init];
+ // first thing we need is a phone number, can't even send registration without it
+ // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ // NSString *documentsDirectory = [paths objectAtIndex:0];
+ // NSString *phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"];
+ _phone_number = @"4037082094";
+
// create one and only server instance, this gets passed around
_server = [[Network alloc] init];
_server->shlist_tvc = self;
@@ -33,6 +44,41 @@
// bulk update, doesn't take a payload
[_server send_message:3 contents:nil];
}
+
+ // the capacity here assumes one phone number per person
+ _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;
+ // [_address_book wait_for_ready];
+}
+
+- (void) update_address_book
+{
+ [_phnum_to_name_map removeAllObjects];
+ // XXX: it'd be nice to resize the mutable array to num_contacts here
+
+ for (Contact *contact in _address_book.contacts) {
+ NSString *disp_name;
+ // show first name and last initial if possible, otherwise
+ // just show the first name or the last name or the phone number
+ if (contact.first_name && contact.last_name)
+ disp_name = [NSString stringWithFormat:@"%@ %@",
+ contact.first_name, [contact.last_name substringToIndex:1]];
+ else if (contact.first_name)
+ disp_name = contact.first_name;
+ else if (contact.last_name)
+ disp_name = contact.last_name;
+ else if ([contact.phone_numbers count])
+ disp_name = [contact.phone_numbers objectAtIndex:0];
+ else
+ 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];
+ }
}
- (void) didReceiveMemoryWarning
@@ -58,7 +104,7 @@
return 0;
}
-// new list dialogue has been cancelled or saved
+// new list dialogue has been saved
- (IBAction) unwindToList:(UIStoryboardSegue *)segue
{
NewListViewController *source = [segue sourceViewController];
@@ -162,6 +208,7 @@
[self.tableView setEditing:FALSE animated:TRUE];
}
+
- (UITableViewCell *) tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
@@ -174,7 +221,7 @@
if ([indexPath section] == 0) {
shared_list = [self.shared_lists objectAtIndex:row];
cell.textLabel.text = shared_list.name;
- cell.detailTextLabel.text = shared_list.members;
+ cell.detailTextLabel.text = [self process_members_array:shared_list.members_phone_nums];
// fill in the completion fraction
UILabel *completion_fraction;
@@ -199,7 +246,7 @@
else if ([indexPath section] == 1) {
shared_list = [self.indirect_lists objectAtIndex:row];
cell.textLabel.text = shared_list.name;
- cell.detailTextLabel.text = shared_list.members;
+ cell.detailTextLabel.text = [self process_members_array:shared_list.members_phone_nums];
shared_list.cell = cell;
// Modify the look of the off the shelf cell
@@ -218,7 +265,57 @@
return cell;
}
+- (NSString *) process_members_array:(NSArray *)phnum_array
+{
+ 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) {
+ [output appendString:@"You"];
+ continue;
+ }
+
+ [output appendFormat:@", %@", phone_number];
+ }
+ return output;
+ }
+
+ // we can do phone number to name mappings
+ NSMutableArray *members = [[NSMutableArray alloc] init];
+ int others = 0;
+
+ // anything past the second field are list members
+ for (id phone_number in phnum_array) {
+
+ // try to find the list member in our address book
+ NSString *name = _phnum_to_name_map[phone_number];
+
+ if (name)
+ [members addObject:name];
+ else if ([phone_number compare:_phone_number] == NSOrderedSame)
+ [members addObject:@"You"];
+ else
+ // didn't find it, you don't know this person
+ others++;
+ }
+
+ NSMutableString *members_str =
+ [[members componentsJoinedByString:@", "] mutableCopy];
+
+ if (others) {
+ char *plural;
+ if (others == 1)
+ plural = "other";
+ else
+ plural = "others";
+ NSString *buf = [NSString stringWithFormat:@" + %i %s",
+ others, plural];
+ [members_str appendString:buf];
+ }
+ return members_str;
+}
// section header titles
- (NSString *)tableView:(UITableView *)tableView
diff --git a/ios-ng/shlist/Network.m b/ios-ng/shlist/Network.m
@@ -1,6 +1,5 @@
#import "Network.h"
#import "DataStructures.h"
-#import "AddressBook.h"
@interface Network () {
NSData *msg_data;
@@ -19,11 +18,7 @@
int connected;
}
-@property (strong, retain) NSMutableData *data;
-@property (strong, retain) AddressBook *address_book;
-@property NSMutableDictionary *phnum_to_name_map;
-
-@property (strong, nonatomic) NSString *phone_number;
+// @property (strong, retain) NSMutableData *data;
@property (strong, nonatomic) NSData *device_id;
@end
@@ -41,37 +36,6 @@
msg_type = 0;
msg_type_pos = 0;
-
- // [self connect];
-
- // get instance and wait for privacy window to clear
- _address_book = [AddressBook shared_address_book];
- [_address_book wait_for_ready];
-
- // the capacity here assumes one phone number per person
- _phnum_to_name_map = [NSMutableDictionary
- dictionaryWithCapacity:_address_book.num_contacts];
-
- for (Contact *contact in _address_book.contacts) {
- NSString *disp_name;
- // show first name and last initial if possible, otherwise
- // just show the first name or the last name or the phone number
- if (contact.first_name && contact.last_name)
- disp_name = [NSString stringWithFormat:@"%@ %@",
- contact.first_name, [contact.last_name substringToIndex:1]];
- else if (contact.first_name)
- disp_name = contact.first_name;
- else if (contact.last_name)
- disp_name = contact.last_name;
- else if ([contact.phone_numbers count])
- disp_name = [contact.phone_numbers objectAtIndex:0];
- else
- 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];
- }
}
return self;
@@ -105,8 +69,6 @@
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
- // NSString *phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"];
- _phone_number = @"4037082094";
NSString *device_id_file = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"];
// NSError *error = nil;
@@ -381,7 +343,7 @@
if (msg_type == 1) {
NSArray *fields = [msg_string componentsSeparatedByString:@"\0"];
- if ([fields count] != 2) {
+ if ([fields count] != 3) {
NSLog(@"warn: network: new list response has invalid number of fields %i",
[fields count]);
return;
@@ -390,7 +352,7 @@
SharedList *shlist = [[SharedList alloc] init];
shlist.id = [[fields objectAtIndex:0] dataUsingEncoding:NSUTF8StringEncoding];
shlist.name = [fields objectAtIndex:1];
- shlist.members = @"You";
+ shlist.members_phone_nums = [NSArray arrayWithObjects:[fields objectAtIndex:2], nil];
shlist.items_ready = 0;
shlist.items_total = 0;
@@ -487,46 +449,13 @@
NSLog(@"info: parse_list: '%@' has %i fields",
[list_fields objectAtIndex:0], field_count);
- NSMutableArray *members = [[NSMutableArray alloc] init];
- int others = 0;
-
- // anything past the second field are list members
- NSArray *phone_numbers = [list_fields subarrayWithRange:NSMakeRange(2, field_count - 2)];
- for (id phone_number in phone_numbers) {
-
- // try to find the list member in our address book
- NSString *name = _phnum_to_name_map[phone_number];
-
- if (name)
- [members addObject:name];
- else if ([phone_number compare:_phone_number])
- [members addObject:@"You"];
- else
- // didn't find it, you don't know this person
- others++;
- }
-
- NSMutableString *members_str =
- [[members componentsJoinedByString:@", "] mutableCopy];
-
- if (others) {
- char *plural;
- if (others == 1)
- plural = "other";
- else
- plural = "others";
-
- NSString *buf = [NSString stringWithFormat:@" + %i %s",
- others, plural];
- [members_str appendString:buf];
- }
// we've got everything we need
SharedList *shared_list = [[SharedList alloc] init];
shared_list.name = [list_fields objectAtIndex:0];
shared_list.id = [[list_fields objectAtIndex:1] dataUsingEncoding:NSUTF8StringEncoding];
- shared_list.members = members_str;
+ shared_list.members_phone_nums = [list_fields subarrayWithRange:NSMakeRange(2, field_count - 2)];
// we don't currently get this information back
// XXX: lists your not in will not return this information
diff --git a/ios-ng/shlist/NewListViewController.m b/ios-ng/shlist/NewListViewController.m
@@ -35,7 +35,7 @@
self.shared_list = [[SharedList alloc] init];
self.shared_list.name = self.textField.text;
// self.shared_list.list_date = self.datePicker.date;
- self.shared_list.members = @"You";
+ // self.shared_list.members = @"You";
NSLog(@"NewListViewController::prepareForSegue(): %@", self.textField.text);
}