Getting a JSON string from an array of NSValue objects holding CGPoint structs

I am a big fan of SBJson, and let’s face it, who isn’t? (Thanks Stig!) It has served me well for a long time, and only occasionally do I have to do any real work when it comes to serializing and deserializing JSON.

My current needs required me to take an NSArray of NSValue objects that each hold a CGPoint value, and send that down the wire via JSON. Simply passing the array inside the proxyForJson method halts the processing, so as I looked into it further I discovered that I needed to set up a utility function to create an NSDictionary that could be handled by the SBJson framework. Here is the code that I am using:

+ (NSArray *)jsonCompatibleArrayOfCGPoints:(NSArray *)pts
{
    NSMutableArray *pointsArr = [NSMutableArray array];
    for (int idx = 0; idx < [pts count]; idx++)
    {
        CGPoint pt = [pts[idx] CGPointValue];
        [pointsArr addObject:@ { @"x" : [NSNumber numberWithFloat:pt.x], @"y" : [NSNumber numberWithFloat:pt.y] }];
    }
 
    return [NSArray arrayWithArray:pointsArr];
}

BTW, great sadness today as it is the anniversary of the untimely and far too early passing of Duane Allman, lost in a motorcycle accident this day in 1971.

iOS Mail app load testing

If you hand me your iPad to load the latest test build of the app, and I see this notification bubble on your iOS Mail app icon, then you are doing it wrong…

ios-mail-app-icon

BTW, Happy Birthday (posthumously) to Tor Johnson, who appeared in 3 of the MST3K episodes.

Different Settings app entries for Debug vs. Release builds

So compiler directives can only take you so far when building your Objective-C iOS apps, especially when you have testers who want to keep switching things up. Rebuilding and redeploying is not the end of the world, but it gets old quick.

Luckily I figured out how to switch up the Settings.bundle file so that I can have one version for the release app, and a different version with some extra options for the debug build. This way, they don’t have to drop by every hour when they want to change something that would previously require me to comment in/out some compiler directive and rebuild and redeploy.

The theory behind this is to create a new Settings_Debug.bundle file in the same location as the current Settings.bundle file, change up the plist for your additional settings, and then in the build process, just replace the plist file in Settings.bundle with the one from the Settings_Debug.bundle file. Sounds easy, right?

Here is basically what you need to do step by step:

  • Create a new Settings_Debug.bundle file
  • Copy the plist from Settings.bundle and make the necessary modifications in the Settings_Debug.bundle
  • Click the project in file explorer, select target, select Build Phases
  • Leave release version Settings.bundle in the Copy Bundle Resources, but remove Settings_Debug.bundle from Copy Bundle Resources
  • Click Add Build Phase > Add Run Script
  • Copy following into text view below Shell
if [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Shared/Settings_Debug.bundle/Root.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle/Root.plist"
echo "Debug settings bundle copied"
else
cp -r "${PROJECT_DIR}/Shared/Settings.bundle/Root.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle/Root.plist"
echo "Release settings bundle copied"
fi

Here are a few caveats to keep in mind…

  • In my example above, note that my Settings.bundle file is in a folder called Shared off the project directory
  • I am not using the Root.strings file
  • It was done this way because just copying the .bundle file threw errors trying to copy the .svn files and folders
  • For me, it seems way easier to work with Root.plist in source code mode instead of property list mode

BTW, it was pretty slim pickings (not Slim Pickens, one of the great characters of all time) on the births, deaths, and events for September 21, so let me just wish everyone a Happy International Day of Peace.

Objective-C preprocessor paranoia

I am always deathly afraid of test code working its way into a release app. Usually for me this happens when I am trying to optimize a portion of the code by modifying something that is already there and working, which usually leads to something like this in my code during development:

//#define SAFE_OPTION_1
//#define RISKY_OPTION_2
#define DANGEROUS_OPTION_3

So finally I started to set it up so that I can verify that, at least for the archival build of the app, that the wrong option is not selected by using something like this:

#ifndef DEBUG_VERSION
 #if !defined(SAFE_OPTION_1)
  #error The release build of MyApp must have the SAFE_OPTION_1 option selected.
 #endif
#endif

This code will give me a build error if I forget to set the option back to the safe option, which is good.

Also, I wanted to make sure that one of the three options was selected, as commenting out all 3 options is not good, and may not necessarily generate any build errors on their own. So I then figured out that this would do the trick for me:

#if !defined(SAFE_OPTION_1) && !defined(RISKY_OPTION_2) && !defined(DANGEROUS_OPTION_3)
 #error Please select an option.
#endif

Now I get a build error when I accidentally have all 3 options commented out.

BTW, Happy 20th Birthday to the X-Files, which first aired on this date in 1993. I think it is about time for me to go back through and binge watch all 9 seasons of the show.

HTTP post in VBA

I have some very nice C# .NET web services that I created and use from some web sites, .NET desktop applications, and iOS apps. But of course, this is not a wide enough range of technologies that I have to deal with, so I needed to figure out how I could call my web service from within an Access database using Visual Basic for Applications (VBA).

The web service just takes in a couple of form variables, chugs through the database looking for the matching records, and returns a string with the pertinent data. Here is the VBA code that I put together to accomplish this task:

Sub Method1()
 
    Set objHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
    URL = "https://www.mywebsite.com/WebService.asmx/StatusCall"
    objHTTP.Open "POST", URL, False
 
    objHTTP.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
    objHTTP.send "formVariable1=value1&formVariable2=value2"
 
    If objHTTP.Status = 200 Then
        MsgBox objHTTP.responseText
    Else
        MsgBox "Failed at getting response from web service:" & objHTTP.Status
    End If
 
End Sub

The response text is being sent to a message box, but you could just as easily return that string, or better yet, use an XML parser to dig into the data for just what you need. Perhaps I will save that code for another post later.

BTW, Happy Birthday to Julie Newmar, by far the best Catwoman from any Batman live action or animated TV show or movie.

Multiplicative persistence

I saw a story this morning in Gizmodo about hard logic puzzles, and one of them caught my attention for some brute force computational processing.

Martin Gardner was a famous mathematician, and in one of his books, he talks about the persistence of a number as the number of times it iteratively takes to multiply the individual digits of an integer together until you end up with a single digit number. As an example, if you consider the number 25, the persistence is 2 because 2×5 equals 10 (step 1), and then 1×0 equals 0 (step 2).

So here is a quick algorithm I threw together in VB.NET to find the smallest number that has a particular persistence:

Module Module1
 
    Function Persistence(num As Integer) As Integer
 
        Dim n As Integer = Math.Abs(num)
        Dim p As Integer = 0
        While n >= 10
            Dim nString = n.ToString()
            n = 1
            For i = 0 To nString.Length - 1
                n *= Convert.ToInt16(nString.Substring(i, 1))
            Next
            p = p + 1
        End While
 
        Return p
 
    End Function
 
    Sub Main()
 
        Dim persistenceList As List(Of Integer) = New List(Of Integer)()
 
        Dim p As Integer
        For i = 1 To 10000000
            p = Persistence(i)
            If persistenceList.Count < p Then
                Console.WriteLine("Just found a persistence of " + p.ToString() + " for " + i.ToString())
                persistenceList.Add(i)
            End If
        Next
 
        Console.WriteLine("Press any key to exit...")
        Console.ReadKey()
 
    End Sub
 
End Module

When you run this, you see something like this in the console:

Just found a persistence of 1 for 10
Just found a persistence of 2 for 25
Just found a persistence of 3 for 39
Just found a persistence of 4 for 77
Just found a persistence of 5 for 679
Just found a persistence of 6 for 6788
Just found a persistence of 7 for 68889
Just found a persistence of 8 for 2677889
Press any key to exit...

Above a persistence of 8, it can take a very very long time to brute force a solution.

BTW, Happy Birthday to Anton Fig, a fantastic drummer who has worked with one of my favorite artists, Joe Bonamassa.

Centering the toolbarItems in a UINavigationController

When you add to the toolbarItems array of your UINavigationController, it puts the items left justified in the toolbar at the bottom of the screen. If you instead want the items to be centered in the toolbar, here is a way to do it…

NSArray *itemArray = @ [ @"Item 1", @"Item 2" ];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(0.0, 0.0, 240.0, 30.0);
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *item = [[[UIBarButtonItem alloc] initWithCustomView:segmentedControl] autorelease];
UIBarButtonItem *flex1 = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease];
UIBarButtonItem *flex2 = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease];
self.toolbarItems = @ [ flex1, item, flex2 ];
[segmentedControl release];

The flex1 and flex2 items are just like adding the springs in Interface Builder, which space things out equally across the view. This code is not ARC approved as you can see from the autorelease and release methods, but if you need to use it in an ARC project you should be able to figure it out.

BTW, it looks to be a thin day for actor or musician birthdays, deaths, events, or holidays, so Happy Birthday to President Obama.

External full screen UIViewController

While trying to write an app that drives an external monitor hooked up to my iPad, I found that you need to set the wantsFullScreenLayout to your view controller in order for it to go edge to edge. No combination of constraints or struts and springs in Interface Builder or playing with the frame and bounds in code does the job.

As an aside, if you get the message “Could not change executable permissions on the application.” in Xcode when you try to run an app, it is most likely because there is already an app on the device or simulator that has the same bundle identifier that you have specified in your code. To solve, just remove the offending app from the device or simulator and run again, and it should work.

BTW, Happy 30th Birthday to the Nintendo Entertainment System, released 30 years ago today in Japan as the Famicom. Ice Hockey is still one of my all time favorite games.

UISearchBar gotcha

I sort of discovered something quite by accident today.

I have had a persistent crash problem in my app for a long time, so I put in some code from the QuincyKit so that I could get the crash logs from devices when they encountered a problem. Unfortunately, the crash logs that I have been getting have been 99% unhelpful, as the only mention of my app is the main.m line shown at the bottom of the thread 0 stack trace.

In diagnosing a problem in another app today, it occurred to me that the problem in one of my apps could be related. My users have a UISearchBar on top of a table view of items, and they can enter some text to narrow down the item list. I of course am hooking into the textDidChange method in the UISearchBarDelegate protocol. However, at the direction of a specific customer with specific instructions, I discovered that if the auto correction parameter is turned on for the search bar, and some text is entered that has a suggestion below it, then the act of selecting a row from the filtered table view will cause the text in the search bar to be replaced with the suggested text, and then hilarity ensues as the textDidChange is fired again and the program returns a nil record instead of the one I just selected from the table view, since the table view switched in the textDidChange method.

So I corrected this issue in the original app, and it got the wheels turning. So I tried doing much the same thing on a device in my other app, and sure enough, my exception breakpoint in Xcode fires! (I think I heard some angels singing right about this time.) And just for good measure, I set it up so that it does not crash anymore in that instance, it just sits there and does nothing, which apparently is better than a crash.

Needless to say, from now on I am going to set all of my UISearchBar items to have the auto correction parameter set to No.

BTW, happy birthday to Michael Anthony of Chickenfoot fame. Oh, and he was in some band called Van Halen for a while too.

EDIT: I knew that my Spidey sense was detecting something familiar when I was putting together this post. Maybe I should read my own blog every once in a while…

Search bar and correction don’t play nice together

WWDC 2013 wrap up

Well I have been back home for a few days now from the WWDC in San Francisco, and I have to say that it was a super busy week. The content was very solid, and the lines were massive, but all in all worth the time and expense.

BTW, Happy Birthday to Mia Sara, IMHO the real star of Ferris Bueller’s Day Off.