Avoiding an Objective-C Pitfall #1

Below is a very commonly used design pattern in Objective-C.

CommonDesignPattern

It’s the typical Objective-C “Singleton Pattern” because it does just that.  Returns a singleton of the class it belongs to.  If we take a look at an example that uses it we can see it in action.

Screen Shot 2017-05-16 at 1.07.57 PM

The “@synchronized(self)” statement ensures that only one thread at a time enters that inner block and keeps more than one copy of the class from being created.  Without it two or more threads might just happen to get past the “if(_inst == nil)” statement before one of the threads manages to complete the assignment to the static local variable “_inst”.

If you run this program you get the output you’d expect:

Screen Shot 2017-05-16 at 1.22.27 PM

The class “Test1” created exactly ONE instance of itself, stored it in the static local variable “_inst” and then returned it.  If the program had called the class method a second time it would have gotten the exact same instance that was created in the first call like so:

Screen Shot 2017-05-16 at 1.28.55 PMScreen Shot 2017-05-16 at 1.29.08 PM

All well and good!  Now, let’s add a little wrinkle to the situation by creating a subclass of “Test1”:

Screen Shot 2017-05-16 at 1.08.34 PM

In this example, “Test2” inherits directly from “Test1”.  It’s very simple and doesn’t even override any methods.  We’ve also set the second instance object in the main function, “o2”, to get the result of calling [Test2 instance] instead of [Test1 instance].  But since we didn’t override anything it’s still really calling the same method found in “Test1”.  Now, let’s run it and see what output we get.

Screen Shot 2017-05-16 at 1.41.44 PM

Now, for some of you, this is not what you were expecting to see.  You were probably expecting to see “Returned Class 2 = Test2“.  However the more I thought about it this was exactly what I was expecting to see.  The reason for this is simple.  Static local variables are scoped to the method in which they are created.  Since this was a class method (belongs to the class definition rather than instances of the class) it belongs to the class in which the method was defined.  Bottom line this would have been EXACTLY as if I had coded it as follows:

Screen Shot 2017-05-16 at 3.19.15 PM

Notice that the static local variable is now your everyday, garden variety global variable.  The only difference now is that from a scope perspective it can be “seen” from the entire program instead of just inside the [Test1 instance] method.

Coincidentally, if you reverse the two calls to the “instance” method you’ll get instances of “Test2” instead of “Test1”.

Screen Shot 2017-05-16 at 3.45.09 PMScreen Shot 2017-05-16 at 3.45.22 PM

Why didn’t an instance of “Test1” get created?  Because we called [Test2 instance] instead of [Test1 instance].  But why since we didn’t override that method in “Test2?”  For a better explanation of meta-classes in Objective-C I refer you to this excellent blog post: What is a meta-class in Objective-C?

But there’s also another more problematic issue with this test case.  That “@synchronized(self)” statement?  It’s rendered completely useless in our example if [Test1 instance] is called from one thread and [Test2 instance] is called at the same time from another thread.  The reason is evident in the second line of the output.  Even though the method belongs to the class definition for “Test1” we’re calling it from the scope of the subclass definition “Test2”.  (Again, read the blog post at the link given above.) So if there are two threads and one thread calls [Test1 instance] and the other thread calls [Test2 instance] that synchronization lock will be locking on two entirely different objects because the “self” properties in both calls will be pointing to two different objects.  Bottom line:  you could end up with an instance of the wrong class than what you were expecting.

Below is one solution albeit not the optimal one.  We simply override the class method in “Test2.”

Screen Shot 2017-05-16 at 1.59.34 PMScreen Shot 2017-05-16 at 2.09.22 PM

Why isn’t this the optimal solution?  Because you have blatant code duplication.  Not just within the program as a whole but even worse, given that we’re talking about Object Oriented Programming, within the a subclass!

No, a better solution is needed.  And one that I’ve come up with in my own code is only slightly more complicated but, I think, solves the problem very nicely without adding much memory or CPU time overhead.  Let’s look at the newly refactored “instance” method.

Screen Shot 2017-05-16 at 4.16.12 PM

We will now store the singleton instances in a dictionary using the class name as the key. This ensures that if we call this method using [Test2 instance] we get an actual instance of “Test2” and if we call it using [Test1 instance] we get an actual instance of “Test1”.  Moreover we still only create just one instance of any given class.

Finally we change the object being synchronized on to simply the static base class, [Test1 class], rather than allowing it to be based on the “self” property.

So, after a quick change to the “main” function to test the results.

Screen Shot 2017-05-16 at 4.24.04 PMScreen Shot 2017-05-16 at 4.24.30 PM

And you can now see that the results are more inline with what you would expect without having to duplicate code in the subclasses.

 

Thoughts on GNUstep

For those that don’t know GNUstep is a project that started many years ago to help bring Objective-C to the masses using operating systems other than Mac OS X macOS.  Actually, Objective-C already existed on any platform that had access to the GCC compiler suite but what GNUstep sought to do was bring the primary frameworks (libraries) that were being used on macOS to make porting Mac applications to other platforms a lot easier.  In particular we’re talking about the Foundation and AppKit libraries.

For the most part they’ve nailed it on the head for simple applications and the Foundation library seems rock solid and fairly up-to-date with the Apple versions.  In fact the Foundation library seems to be up-to-date with at least macOS 10.9 and some of 10.10.

That said, there are a couple of places where people, including me, are having serious problems with GNUstep.  I have to add at this point that these are constructive criticisms!  The GNUstep folks had a definite goal in mind when they started and I have to say that they hit the nail on the head with this.  Also, like many open source projects, it’s an all volunteer army where people have day jobs and others simply lose interest for other projects.  In fact, the introduction of Swift has definitely contributed to that last point – many people have given up on Objective-C and jumped on the Swift bandwagon.

1. They Keep Breaking It

This mainly applies to the AppKit libraries when trying to use Objective-C 2.0 features such as the non-fragile ABI and ARC.  If you want to build your Objective-C 2.0 projects with the non-fragile ABI then you’re not going to be able to use the AppKit libraries.  Otherwise you’re applications will crash with a notice about mismatched ABIs.  The solution is to build without non-fragile ABI support.  This is not always desirable.

2. Strict Adherence to macOS Paradigms

Apple’s operating systems (macOS, iOS, watchOS, tvOS, etc.) all have this paradigm where basically everything is a directory.  Especially Frameworks and GUI Applications.  GNUstep tries its best to replicate this paradigm on other platforms but the truth is that it just isn’t necessary and adds a huge amount of complexity to the build process and the resulting product. The paradigm works very well indeed on Apple’s operating systems because there is support for the paradigm built right into the operating systems.  But on other operating systems such as Windows and Linux this paradigm doesn’t work so good.  In my opinion, and I’m not alone, it would be best to simply follow the best practices of those other platforms rather than trying to hammer a square peg into a round hole.  This applies to packaging too.  The default package manager for each platform should be used.  It’s less confusing for users of those platforms.

2.1. This Applies to GUI Applications Too

The GNUstep GUI applications ALL look like they were all written about 30 years ago.  They use concepts and HID guidelines that harken back to the NeXT operating system from whence everything is modeled from.  Even Apple has dropped most if not all of these old HID paradigms in favor of ones that are more modern and practical.  I mean, honestly, who has main menus that just hover somewhere detached from the main window of the application.  Really?

Yeah, okay, I know – GNUstep has this neat pluggable theme system and can be customized but 1) this is highly problematic (see point #1 above) and 2) it is not well documented – if at all.  And if it is documented you can’t find it unless you spend years scouring the web and happen to stumble across it like I did when I found this some FOUR years after it was first posted(scroll all the way to the end of the post to “Step 15: Making it Look like a Linux Application“)

3. Makefiles

Everything should be moved to CMake.  ’nuff said.

4. Distribution

There is no support in GNUstep for packaging your applications for distribution to system that don’t already have the GNUstep libraries on them.  I’ve seen ONE very outdated partial document describing one way to do it but that’s it.

How to Fix This

In an upcoming post that I’ll be sure to link to this one I’ll outline some steps for addressing these issues.  At least a couple of them I have already started work on: https://github.com/GalenRhodes/Rubicon

 

Identifying the Odd Electronic Component

If you ever come across an electronic component that looks like this (a small electrolytic capacitor or radial inductor) with simply the letters “HDX” and rattles if you shake it (even a little bit) then I’ll save you some trouble.  It’s called a “vibration switch”!  And, as you might guess, it’s a SPST switch that closes it’s contacts when it senses vibration.  These are not as sensitive as a G-Force sensor but they can do the trick in telling something when it’s being picked up or moved around.

IMG_1539

Power Supply

I needed a power supply that could give out enough peak current to power at least three Raspberry Pi 2s.  Just idle one Raspberry Pi 2 can draw almost 500 mA but at peak processing speed one can draw around 2 Amps at 5V.  I didn’t want to have to have three “wall warts” so I sat down and did some research on the internet and designed the circuit below.  With proper heat sinking on the 2N3055 power transistor it should allow for a peak of almost 7 Amps at 5V.

Powersupply