Archive for the ‘iOS’ Category.

CLGeocoder with built-in NSCache

In case you were wondering, Apple “recommends” that you only make one call per minute to their geocoding system. I can kind of understand the reasoning behind this, as they do not want to let people abuse the system. If you have a bunch of geocoding requests that you need to make within a short amount of time, you will not be cut off immediately if you push through a bunch of requests within seconds, but eventually you will get clipped. Now, if the requests you make are part of a table view that is scrolling, wouldn’t it be neat if you could find a CLGeocoder with built-in NSCache?

Well now you can. Please check out my GitHub repository for BPGeocoder:

https://github.com/Wave39/BPGeocoder

This class inherits from CLGeocoder and you use it as a replacement for CLGeocoder, except that it maintains its own NSCache of addresses that it has geocoded, and if you pass in an address it has already seen, it does not bother contacting the Apple servers, it just returns back the cached results it found earlier.

BTW, Happy Birthday to Terry Farrell, who played Valerie in Back To School and Lt. Dax on Star Trek: Deep Space 9, which was the best Star Trek series, IMHO. (Additionally, I think we need to get an internet campaign going to get IMDb to change the cast photo on their DS9 page to be one with Terry. Leave a comment if you agree. Sorry, Nicole!)

EXC_BAD_ACCESS when creating Address Book records on iOS

I have this code in one of my apps that creates some test records in the Contacts app, so that I can quickly build up some address book data for testing purposes. However, I just uncommented out this code for the first time in a long time, and now I am getting some kind of object release EXC_BAD_ACCESS exception when creating Address Book records on newer versions of iOS.

I tracked the problem down to this line:

ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABPersonPhoneProperty);

While this used to work just fine, I needed to change it to this line:

ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);

And now my address book records are created without any kind of memory crash.

BTW, Happy Anniversary to Godzilla, who premiered in Japanese theaters on this day 60 years ago. Additional BTW, for U.S. readers, don’t forget to get out and vote tomorrow.

Swift (or in other words, “Et tu, Objective-C?”)

Well the WWDC keynote has come and gone. And what do you know, a developer conference keynote geared towards developers. I guess all those bloggers and press types that took up some of the WWDC tickets from us actual developers are pretty disappointed today, as there were no shiny new devices shown.

The big announcement in my opinion was Swift, which will be the successor to Objective-C for developing on the Mac and iOS platforms. It looks somewhat interesting, as yet again they have lowered the bar and made it much easier to develop software for their platforms. But this is a disadvantage as well as a strength, as folks will continue to churn out the clones and inferior products that clutter up the App Store.

I applaud Apple for creating Swift and not recycling an existing language such as Ruby, Python, or Javascript, as these languages all come with their own baggage. Hopefully I will not be throwing away the 6 years of experience that I have built up with Objective-C and they will allow it to be used for the foreseeable future.

Ah, I miss the days when retain/release separated the men from the boys in the iOS world…

There was some good news in the presentations from yesterday. In the Platforms State of the Union presentation, they indicated that the 100 device barrier for beta testing and internal testing will essentially be rendered moot through Apple’s integration of TestFlight. This feature can’t come soon enough for me, so please hurry up Apple.

BTW, so many birthdays today, not sure where to begin… Kerry King of Slayer (happy 50th), Ian Hunter most famously of Mott the Hoople, Chuck Barris of the Gong Show… But the name that jumps out for me is Tristan Rogers, currently portraying Colin on The Young And The Restless. Happy Birthday, mate!

resignFirstResponder does not put away keyboard on UIModalPresentationFormSheet

I started to use a few view controllers inside of navigation controllers that are presented with the UIModalPresentationFormSheet style, and to my dismay discovered that the resignFirstResponder call does not make the keyboard disappear.

Apparently there is a reason for this, if you are interested you can look it up and get a full explanation. For my purposes, I was just happy to discover that overriding the disablesAutomaticKeyboardDismissal method and returning NO seems to do the trick. Basically, now when I need to present a navigation controller in this fashion, I alloc the navigation controller with the class of MyNavigationController instead of UIViewController. Here is the code for MyNavigationController.m:

#import "MyNavigationController.h"
 
@implementation MyNavigationController
 
- (BOOL)shouldAutorotate
{
    return YES;
}
 
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}
 
- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}
 
@end

You will of course need to change the rotation methods to your own needs.

Today, I have a double BTW for you. Happy birthday to Joe Bonamassa, one of my favorite guitar players and all around performers. And on a sad note, one year ago today, Jeanne Cooper, the grand old dame of The Young and The Restless, passed away. The show has not been the same without her.

Unable to simultaneously satisfy constraints

All of a sudden, I started getting this error popping up in the console while developing my iOS 7 app:

2014-04-30 11:32:27.199 MyApp[4495:60b] Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; 
	(2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't
	understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x1946a510 h=-&- v=-&- DetailTableView:0xe39ce00.width == UIView:0x2613afd0.width - 293>",
    "<NSAutoresizingMaskLayoutConstraint:0x12ccfd50 h=--& v=-&- H:[UITransitionView:0x12ca7570(768)]>",
    "<NSAutoresizingMaskLayoutConstraint:0xcf18c40 h=-&- v=-&- UIView:0x2613afd0.width == ADTransitionView:0xcf16f20.width - 768>",
    "<NSAutoresizingMaskLayoutConstraint:0xcf19bb0 h=-&- v=-&- ADTransitionView:0xcf16f20.width == UITransitionView:0x12ca7570.width>"
)
 
Will attempt to recover by breaking constraint 
<NSAutoresizingMaskLayoutConstraint:0x1946a510 h=-&- v=-&- DetailTableView:0xe39ce00.width == UIView:0x2613afd0.width - 293>
 
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

A few notes about the app:

1. I am still a noob when it comes to Auto Layout, so I have been kind of easing into it on some of the less critical areas of the app, but the part of the app in question is still all springs and struts.
2. I am using the ADTransitionView library to do customized view controller transitions.
3. It did not do this until this morning.

If I hit continue a couple of times on the debug console, the app moves along as if there is no problem, so this is not a critical issue, but I still wanted to find out how to take care of this issue first, and then try to figure out what triggered it.

The way that I was able to get around the issue was to look at all of the nib files that make up my view controller, table view, and cells. I found that one of the component nib files was still flagged to use Auto Layout, even though there were no constraints of any kind in that nib file. When I turned off the Auto Layout flag on that file and ran the app, it started to transition between view controllers without the ‘Unable to simultaneously satisfy constraints’ message.

BTW, Happy Birthday to Phil “Scrap Iron” Garner, who was an infielder for the Pittsburgh Pirates in the late 70’s and early 80’s.