How to make random entries into the iPhone address book (updated)

A few years have passed since I posted a blog entry entitled How to make random entries into the iPhone address book, and while you might be able to figure out how to make this code work if you try to use it with iOS 9, I figured it was time to revisit.

Here is the iOS 9 compliant method for creating the random address book entries:

- (IBAction)add25ButtonPressed:(id)sender
#define URL_FORMAT  @""
    CFErrorRef error1 = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error1);
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error2) {
        // callback can occur in background, address book must be accessed on thread it was created on
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error2)
                NSLog(@"Address book error: %@", ((__bridge NSError *)error2).localizedDescription);
            else if (!granted)
                NSLog(@"Access to the address book has been denied.");
                // access granted
                NSString *genderOfNames = ((arc4random() % 2) == 1 ? @"m" : @"f");
                NSString *urlString = [NSString stringWithFormat:URL_FORMAT, genderOfNames, NUMBER_OF_RANDOM_ENTRIES];
                NSURL *url = [NSURL URLWithString:urlString];
                NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
                NSURLResponse *response = nil;
                NSError *error = nil;
                NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
                NSString *stringData = [NSString stringWithUTF8String:[data bytes]];
                NSString *areaCode = [NSString stringWithFormat:@"%03d", (arc4random() % 799 + 200)];
                NSArray *lineArray = [stringData componentsSeparatedByString:@"\n"];
                for (NSString *line in lineArray)
                    if ([line length] > 0)
                        NSArray *fieldArray = [line componentsSeparatedByString:@","];
                        if ([fieldArray count] == 3)
                            ABRecordRef person = ABPersonCreate();
                            NSString *phone = [NSString stringWithFormat:@"%@-%03d-%04d", areaCode,
                                               (arc4random() % 799 + 200), (arc4random() % 9999)];
                            ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
                            CFStringRef phoneType = (arc4random() % 2 == 0 ? kABPersonPhoneMainLabel : kABPersonPhoneMobileLabel);
                            ABMultiValueAddValueAndLabel(phoneNumberMultiValue, (__bridge CFTypeRef)(phone), phoneType, NULL);
                            NSString *email = [NSString stringWithFormat:@"", fieldArray[1], fieldArray[2]];
                            ABMutableMultiValueRef emailMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
                            CFStringRef emailType = kABHomeLabel;
                            ABMultiValueAddValueAndLabel(emailMultiValue, (__bridge CFTypeRef)(email), emailType, NULL);
                            ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef)(fieldArray[1]), nil);
                            ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFTypeRef)(fieldArray[2]), nil);
                            ABRecordSetValue(person, kABPersonPhoneProperty, phoneNumberMultiValue, nil);
                            ABRecordSetValue(person, kABPersonEmailProperty, emailMultiValue, nil);
                            ABAddressBookAddRecord(addressBook, person, nil);
                            NSLog(@"Created record for %@ %@ (%@: %@; %@)", fieldArray[1], fieldArray[2], phoneType, phone, email);
                ABAddressBookSave(addressBook, nil);
                NSLog(@"Done creating address book data.");

BTW, Happy Birthday to Windows, first available 30 years ago today. Coincidentally, on the same exact day those 30 years ago, the Pittsburgh Pirates hired Jim Leyland to be their manager. And in both instances, the rest is history.

Big Android BBQ Day 2

Well, the Big Android BBQ 2015 conference is in the books. I found the content on day 2 to be a bit more helpful to me at my current level of Android experience, with the highlights being sessions on lean layouts and fragments. A bit basic for the seasoned Android developer, but just right for me.

BTW, Happy Birthday to Omar Moreno, the great center fielder on the Pirates teams of the late 70s and early 80s, and leadoff man for the 1979 World Series champs.


Big Android BBQ Day 1

Well, day 1 of the Big Android BBQ in Hurst, Texas is in the books. The content was pretty good, with the highlight of the day being the Location and Context and Speed, Oh My! presentation. Also, I attended presentations on What’s New in Android Marshmellow, Android Performance at Scale, and continuous testing. Each of them contained some good takeaways.

BTW, to continue the theme from yesterday’s BTW, Happy Birthday to Christopher Lloyd, who most famously portrayed Doc Brown in the Back To The Future movies.

Busy day

Today is a busy day, as it is the travel day for attending the Big Android BBQ. I do not know what to expect from the conference, but I will post some recaps in this here space in the next few days.

By the way, today has been a busy day in several other very important ways:

  • Todd Richards gets fired as coach of the Columbus Blue Jackets and gets replaced by John Tortorella
  • Joe Biden announces that he is not seeking the Democratic Presidential nomination for 2016
  • OS X El Capitan 10.11.1 GM drops
  • Xcode 7.1 GM drops
  • iOS 9.1 GM drops
  • tvOS GM drops (it’s a full Apple download day I guess)
  • The Mets finish off the Cubs

In closing, Happy Back To The Future Day to everyone. I must live in a back water town, as I have not seen people wearing spiky metal hatsĀ or using hoverboards…

NS_ENUM works without the typedef (sort of)

You may have heard that NS_ENUM works without the typedef (sort of). What I mean by this is that most of the time, it all just works even if you leave off the typedef on something like this:

NS_ENUM(NSInteger, BinaryItemType)

However, if I ran into a situation where I did something to my code base to cause it to start throwing build errors like this:

duplicate symbol _BinaryItemType in:
ld: 15 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

And of course, I did not realize that the typedef missing was causing this error. As soon as I changed the NS_ENUM to look like this, all went well:

typedef NS_ENUM(NSInteger, BinaryItemType)

BTW, Happy Birthday to Rosalind Chao, who so ably portrayed Keiko O’Brien in Star Trek The Next Generation and Star Trek Deep Space Nine.

UITextField inside UITableViewCell moves one pixel on becoming first responder

If you have ever noticed that your UITextField inside of a UITableViewCell moves one pixel on becoming the first responder, and then moves one pixel back when resigning the first responder, then you are in luck, as I have found a work around.

Basically, I found that if your UITextField in Interface Builder is set to System 17.0 font, go ahead and change it to Helvetica Neue 17.0. For some reason, this works for me and does not move at all when becoming or resigning the first responder.

BTW, The King left us on this day back in 1977, so sing a verse of Jailhouse Rock or Heartbreak Hotel in his honor.

Someone should take their own advice on Adobe Flash

So I am wandering through my news feeds a while back, and I happen upon this…


I guess all days that end in a “y” are good days to update your Adobe Flash.

By the way, Happy Birthday to Carlos Santana (the guitarist, not the Cleveland Indians baseball player).

The final word on .NET background processing (for now)

While snooping around for information on .NET background processing, I came across a bunch of interesting articles by .NET MVP Stephen Cleary that go into great detail about using Task.Run vs. a BackgroundWorker control. Here is the link to the introduction of the series of articles:

Task.Run vs BackgroundWorker: Intro

BTW, I am impressed so far with the content that was revealed at the WWDC 2015 conference. I have been going through the presentations and, while there were no “knock your socks off” moments, there is still a ton of great stuff that they are packing into the new versions of iOS, OS X, and watchOS.

Expected expression error when creating new variable in switch case block

So I am coding along in my iOS app and I come across an Expected expression error when I am creating a new variable in switch case block. For example, this looks innocent enough…

switch (actionType)
    case 0:
        NSArray *componentArray = [theString componentsSeparatedByString:@","];
        // do more stuff here
    // more cases here

No matter what I do, the Xcode compiler complains about the NSArray line right below the case 0 statement. What kind of horse hockey is this? The code is so simple that it is laughable.

My investigations led me to discover that there is a C compilation rule that specifies that you cannot have a variable declaration right after a label. And apparently, case statements are compiled into labels. (By exactly what sorcery escapes me, I am sure if you are interested you can dig into the C language definitions and figure it out.)

So I am forced to do this instead:

NSArray *componentArray;
switch (actionType)
    case 0:
        componentArray = [theString componentsSeparatedByString:@","];
        // do more stuff here
    // more cases here

BTW, Happy Birthday to Cheryl Burke, who is by far my favorite pro dancer on Dancing With The Stars. I hope Cheryl returns to the show at some point in the future.

Gee, I would have never guessed that password…

A password so insecure, it is secure.


BTW, Happy Earth Day to the citizens of planet Earth reading this message. (Which should be most of you.)