Ash on UIAlertController

Ash Furrow wrote a really nice introduction to the new UIAlertController class. His example showed an alert view and presented it with a text field. Cool. It can also do much more. The new class actually cannibalizes UIActionSheet as well, and that is very cool. I've been building an app that uses this new class (albeit in Objective-C since I'm a dinosaur).

Here's some actual code from my app, and I'll explain the wrinkle that now exists with action sheets:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
                                                                             message:nil
                                                                      preferredStyle:UIAlertControllerStyleActionSheet];
    
    __weak UIAlertController *weakAlert = alertController;
    __weak typeof(self) weakSelf = self;
    UIAlertAction *showCameraAction = [UIAlertAction actionWithTitle:@"Take Picture"
                                                               style:UIAlertActionStyleDefault
                                                             handler:^(UIAlertAction *action) {
                                                                 typeof(weakSelf) strongSelf = weakSelf;
                                                                 
                                                                 [weakAlert dismissViewControllerAnimated:YES completion:^{
                                                                     [strongSelf.imagePicker showCameraInViewController:strongSelf];
                                                                 }];
                                                             }];
    UIAlertAction *showPickerAction = [UIAlertAction actionWithTitle:@"Choose Existing"
                                                               style:UIAlertActionStyleDefault
                                                             handler:^(UIAlertAction *action) {
                                                                 typeof(weakSelf) strongSelf = weakSelf;
                                                                 
                                                                 [weakAlert dismissViewControllerAnimated:YES completion:^{
                                                                     [strongSelf.imagePicker showImagePickerInViewController:strongSelf];
                                                                 }];
                                                             }];
    [alertController addAction:showCameraAction];
    [alertController addAction:showPickerAction];
    
    [self presentViewController:alertController animated:YES completion:nil];

It's all pretty standard stuff. You create the alert controller, and because it's just showing options to use the camera or image picker the button options are straightforward enough so I don't need a title or message. The wrinkle comes when I'm wanting to dismiss the alertController. Because it's a presented view controller (that seems to be doing presenting of its own), you need to have the alertController do its own dismissing. So you just need to create a weak version of it to call dismiss on, thus avoiding a nasty retain cycle.

So I'm a fan of this new class. Getting rid of the delegation that was needed for UIActionSheets and UIAlertViews is great. It can make for long methods to put it all on screen, but the tradeoff is worthwhile. I am disappointed that Apple didn't go farther, though. Here are a couple areas where I would like more customization:

  • My app uses a tint color for distinguishing buttons, but the action sheet doesn't respect it. Instead it's the standard iOS 7/8 blue. I think they should either respect the tint color, or allow you to set your own button color.

  • I also want to use a custom font. There's no way to set the font of buttons that I can tell and I really don't want to do any hacky runtime things. This feels very similar to what Dave and Brent are asking for for Vesper. Seems like a very reasonable request. Maybe for iOS 9.

Overall the upgrade to UIAlertController is a big, big improvement. Thumbs up!

UITableView Prototypes & Custom Cell Heights

I'm working on an app and building the UI with Storyboards on Xcode 6 and I've ran into an interesting problem. I have a UITableView with 2 defined prototypes, and I wanted them to each have their own heights. Seemed simple enough, since you can define row heights within the storyobard directly.

But when I ran, the row heights were all wrong. They reverted back to standard 44-point height.

What I had to do was change the row height in the Table View itself on the storyboard, because that's the number that really matters. At runtime it looks as if the custom heights are ignored completely in the storyboard (even if you override tableView:estimatedHeightForRowAtIndexPath:).

This leaves me with only 1 single row-height in my table. Not horrendous, since I can work around it and make the layout work and look good. But not ideal. I was hoping to have section 0 be more like a header (since I also couldn't get the tableView:viewForHeaderInSection: method to work properly, either).

Is this a bug in UIKit? Xcode? Something that should be reported at all?

Electrical Issue - Turns out...

I'm an idiot. Or at least, not electrician-smart. I got a new outlet for my side and installed it. Still no power. I then came to the conclusion that the outlet has to be switched, and that the Power2U isn't compatible.

So I opened up Emily's side and found that one of the black wires had come out of its terminal. Re-attaching it fixed the issue. Moral of the story: make sure that all the wires are secured firmly. Really firmly.

Huzzah!

An Electrical Problem

I got a new power outlet to replace the one on Emily's nightstand. This is one of those fancy outlets with the USB plugs on it. I finally got around to installing it today and ran into some troubles.

The old outlet had 2 blacks, 2 whites, a red, and an exposed wire. I've never done outlet replacements before so I looked it over and moved along.

The white recepticles were labeled with W and the green was for the exposed (I knew that it's the ground wire) so those weren't a problem. I then stuffed a black in each and the red in one of the blacks.

Fired the breaker back on and the outlet worked! But, now our light switch wouldn't ever turn our main light off. That light is hardwired into the wall and has nothing to do with the outlet.

Crap.

I figured that the red cable was where I went wrong, so I went to another outlet, the one by my nightstand, and opened it up to see how that one is configured. Mine has a black, a white, and a bare wire. What??? To figure this out I went to the world's greatest source of knowledge... the interenet!

I now know that the red wire is a switched wire. I unooked it, capped it off, and tested. The outlet now works and the light turns off. Perfect. Sealed it all up, flipped the breaker, and reset her clock.

Now my outlet doesn't work. Crap.

So my thinking is 1 of 2 things:

  1. I somehow blew out my outlet in all of this. It's old and could be fragile.

  2. Somehow disconnecting the red wire disabled my outlet.

Tomorrow I'll go get a new outlet and test my theory, praying all the while that it's #1 and not #2.

This is why I'm a programmer, and not a builder, electrician, plummer, etc. Code is so much easier.

Well That Didn't Work

When I left yesterday I had the crazy idea of writing my Bing Image fetcher in Swift. The main reason was that decoding the JSON sent back from a server requires lots of trial-and-error, and the playground seemed like the best place for that.

In reality I think I need to do some more investing into Swift to learn its idiocyncracies that I want to right now. I'm motivated to work on a product and not as much figure out a new language. I've run into 2 issues:

  1. Swift playgrounds don't seem to work well with network activity. I am trying to use the NSURLSession dataTaskWithRequest:completionHandler: method that takes a closure for a callback. In my testing I have never gotten the closure to be called in the sandbox. Not sure if this is a bug or not.

  2. I grabbed some sample JSON and started trying to decode it, but the playground kept crashing on me. I'm also having to do lots of crazy casting since Swift Dictionaries aren't what is getting decoded with the NSJSONSerialization class and I have to cast back to NSDictionary.

It's not that I'm thinking Swift isn't advanced enough for what I'm trying to do, rather I would rather get this part of the app working and move on. Swift is more of a curiosity to me right now since it's not done yet, continuously changing, and not production ready at the moment.

This feels like a good time to plug the Swift Workshop that's being held as part of CocoaConf in Seattle this October. I'm going and can't wait. After that I should be more ready to tackle Swift.

Objective-C Bing Search API

I'm working on a new app that will need to search a web API for images. Google Image search's API was deprecated long ago and it's not clear if they have anything to replace it. So I'm going with Bing.

The documentation is really bad. Like, really bad. So I'm foraging on my own for right now since there isn't a Cocoapod to handle this. I'm doing image search only, taking one term and wanting to convert the response into a bunch of NSObjects to display the results. Once the results have come back the user can tap on an image to assign it to their data.

Shouldn't be too hard, right?

Although now part of me wants to tackle this in Swift.

Always Learning

There have been a couple big things come together this week: Apple held WWDC and I am on the verge of completing the iOS development certificate that I started back in September. I just wrapped up all the homework and our last class is tomorrow.

The biggest news of the week was Swift, Apple's new programming language. My initial reaction was shock, followed by a little sadness that I've spent the last couple of years (learning on my own and then school) learning Objective-C and the Cocoa frameworks. And now there's a whole new language to learn.

But the sadness has worn off in the light of how cool Swift looks even from this first "public beta" and it dawned on me: If you get complacent as a developer, or in any profession really, you're not going to last. To excel you need to keep learning.

During my last couple of months at Micro I learned enough to put a basic ASP .net web application for us internally. At first I was hesitant to take it on but as I got to learning the C# language and some of the frameworks I grew to like it (despite some gripes). Learning those tools was fun.

I'm excited to have the certificate as something I can hang on my wall. I'm excited to dive into projects in the coming days. And being able to learn the Swift language. Because learning is a forever endeavor.

New Beginning

Today is my last day working at MicroK12. All told I've worked there for nearly 12.5 years in two stints, and done all the jobs there from retail sales to service to developer. It's been a crazy ride that started when I was 16.

I graduated from high school, bought a home, got married and had a kid all while working there. I've learned some about how to handle success, a lot about how to handle failure and even more about handling the difficulty that comes in between.

But a strange confluence of events has brought a new beginning to me. Starting on Monday I'll be working for Solomon Solution doing technical consulting work. My first client is going to be a huge project making improvements to an existing FileMaker database, building a web portal for customer use and integrating it with external systems.

I'm really excited about this new journey, albeit a bit nervous. Micro has always been steady and – aside from my 2 year stint working at Mars Hill – is really the only workplace I've ever known.

Really this is a story of God's grace. He's brought this opportunity along, and taking a step in faith often requires delving into the unknown. The guys that I've met at Solomon are really great dudes who care about each other and me. I'm elated to be joining that team and venturing into the unknown.

Separating CoreBluetooth and View Controllers

One of the things we did early this quarter was go over Core Bluetooth. In the class demos and in all the materials I've seen online dealing with these classes the logic for handling the Bluetooth events is put inside the view controllers responsible for displaying the UI. This felt like a bad practice to me.

For my homework I implemented separate classes for central and peripherals. I built 1 app that could fulfill both roles (on different devices) using these classes and it worked!

What I like about this practice is the separation. I can move them without having to reimplement every single time I need them in a view.

What I'm not fond of is still needing delegates so there are a few layers of callbacks. There is definitely some reimplementing of methods in whatever class is calling these.

I haven't tested these much yet so they're definitely not production ready. The files can be found here: CoreBluetooth helpers Gist

"Easy" iCloud Core Data Sync

I'm writing a small app that will allow me to save drafts of posts to the site, and I'm trying some things that I've learned lately.

The first is some of the best practices explained by Paul Goracke at the Seattle Xcoders meeting in February. He gave a cool example of sublassing NSManagedObjectContext and having that object setup the Core Data stack.

Doing things this way means that instead of having my App Delegate load the persistent store and setup its coordinator, I wrap that all in my Context's factory method to create the object. I really like how this is working out so far.

The other piece that I'm putting in place is iCloud sync. First off, I want to emphasize how simple my model is. I have one entity that will be synced, which represents a draft. That said, it's surprising to me how easy it was to setup the sync. Much of how I figured this out is from the great objc.io issue on sync.

First, the app needs to have the proper entitlements, which is dead simple in Xcode 5. A trip to the target's Capabilities tab and flipping the iCloud switch to "On" is all you need.

Then, add an option to the addPersistentStoreWithType:configuration:URL:options:error: method. There's a string constant called NSPersistentStoreUbiquitousContentNameKey, which is a key in the options dictionary and you just pass in the value of what you want the persistent store to be called.

Finally, you need to account for changes that get made to the local store and to the remote stores. These are monitored via NSNotificationCenter. I'm also adding a notification of my own that my view controller listens for, so that it knows when to update the UI when changes come in. Simple!

I haven't begun accounting for any edge cases yet, but the basics seem to be pretty straightforward to implement. Much simpler than I was expecting.

If you're interested to see how I've done it, you can view the ManagedObjectContext classes, or the entire project on Github. I'd also love to hear how I could make this better.