Tag Archives: Objective-C

NSMutableDictionary without automatic retaining of contained objects

There may arise a situation where you absolutely can't do something without either doing ugly hacks with overriding -release (which you should never, ever do), or using non-Objective-C constructs such as C++'s std::map (shudder), or rolling out your own key-value storage data structure (evil NIH syndrome strikes again).

The Reason

The only valid reason I can think of for doing this is to avoid a cyclic reference. For example, an object must be stored in a dictionary, but should be automatically removed from it upon being -dealloc'ed. This is exactly what I'm doing in a game I'm slowly working on in order to cache OpenGL textures. I tried hacking this by overriding -release and monitoring -retainCount. Any Objective-C developer worth the name will know that's a pretty dumb thing to do: -retainCount is a pretty shaky thing to depend on, due to various compiler optimizations, and overriding -release can only cause issues. (Yes, that includes overriding -release to force yourself and your teammates never to destroy a singleton. I actually saw that being done in production code. Pretty nasty stuff.)

Pretty much invalid reasons are:

  • storing non-Objective-C pointers or data types. If you're making use of NSMutableDictionary, you're probably making use of Objective-C and Foundation. So make use of the reference counting mechanism built into the framework by wrapping the non-Objective-C data type into something that can be swallowed by the framework nice and easy. Create a thin wrapper around this data by subclassing NSObject
  • not wanting to deal with the reference counting system. Oh, so you're one of those people who don't like to use -retain/-release/-autorelease? You find them abhorrent? Go and cry to your mommy; the reference counting system is one of the most powerful mechanisms enabled by Objective-C and provided by Foundation. Shunning it is no good.

Oh, and if you're one of the ARC-loving pansies developers, sorry; I have no idea what effect this'll have on your funny-colored little world. Because we're about to dive into the mean world of Core Foundation.

This also, sadly, means I have no idea how this'll work with GNUstep.

The Explanation

So you may have heard that Core Foundation equivalents of Foundation classes are "toll-free bridged". What does this mean?

This means that if you create a CFArray, you can use the resulting pointer as an NSArray, and vice versa. This is pretty handy if you're writing code that interacts with Mac OS X's kernel. When writing something that talks to Bluetooth subsystem (say, a new Bluetooth service), you will use C functions that accept and return CFDictionary instances. Oh, sir, yes they do.

So to clean up your code of all those nasty CFDictionary*() function calls, and make it look all nice and Objective-C-ish, what can you do? You just pass the resulting CFDictionary pointer as the first thing in the brackets (you know, where you usually put an Objective-C message target?) and you use plain old Foundation message sends to do operations with the dictionary. To get rid of the warning, you can cast it either prior to the message send or in-line when performing the send.

  CFDictionaryRef dict; // same as CFDictionary *
  // . . . initialize it here . . .

  [((NSDictionary*)dict) valueForKey:@"someKey"];
  // ...or alternatively:
  NSDictionary * theDict = (NSDictionary*)dict;
  [dict valueForKey:@"someKey"];

And you can also do the opposite thing! You can create an NSDictionary and pass it off as a CFDictionary.

  NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"value", @"key", nil];

  // . . . use it here . . .

  // now we'd have to do [dict release].
  // or, we could have autoreleased the object right after
  // initializing it.
  // but let's be fancy.
  CFDictionaryRef cfDict = (CFDictionaryRef)dict;

The Solution

So how do we actually create a NSMutableDictionary whose objects won't be retained nor released?

It turns out to be wonderfully simple. You see, CFDictionaryCreateMutable() is a C function. And C doesn't have a concept of reference counting built deep down into its core. So when you create a dictionary for use with C code, in a C-only program, you probably don't want the dictionary to try to send messages to pointers which are not really Objective-C objects.

And as we have demonstrated each CFDictionary is actually an NSDictionary.

If you are using a C function, it's a good idea to actually default to C behavior: no retaining and no releasing. It might also be a good idea to allow one to use a third-party reference counting mechanism?

That's exactly what was done here. When calling CFDictionaryCreateMutable(), you feed it an allocator which can be used to allocate memory instead of the default one, the default capacity (just like -initWithCapacity:), and two pointers which describe just how the dictionary should behave when retaining, releasing, describing, copying, hashing and comparing values and keys.

First thing I did, and that seems to work quite well, is just pass NULL for the last two pointers. That is, it works quite well when your keys are constant strings which won't be released that easily. I haven't experienced a crash even when they aren't, but let's not risk it.

So let's see.

NSMutableDictionary * ourDictionary = (NSMutableDictionary*)CFDictionaryCreateMutable(nil, 0, NULL, NULL);

Good, but let's improve it by passing a pointer to a default structure for copying and releasing keys. Note that NSMutableDictionary also copies its keys. Exploring why it does so should be an exercise for the reader.

NSMutableDictionary * ourDictionary = (NSMutableDictionary*)CFDictionaryCreateMutable(nil, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);

Now our keys are copied and released where appropriate, while the values are left untouched.

Optionally, explore using kCFTypeDictionaryKeyCallBacks in situations where your keys may be other CFType-derived objects. (That is, not just CFStrings/NSStrings.) Don't use this if there is even a remote chance of your key being a mutable object.

Developing Objective-C apps for Android using Mac OS X

** Unpaid mini-ad (Oct 31st 2012): **
Check out Yeecco's StellaSDK. From my experiments with Stella and from interaction with the company, they may be a good choice if you need an easy-to-use solution right now, with as little work as possible. The PDF has not been maintained, and I have not experimented with improving the procedure; it may be good for improving the understanding of the problems, but if you need something that'll work right now, talk to Yeecco — especially if you want to easily port a Cocos2d game.
** End of mini-ad **

** Unpaid mini-ad #2 (May 27th 2013): **
Another company that provides an SDK for easier porting of iOS apps to Android is Apportable. They have a free starter SDK (check out their plans) — and that's the extent of my familiarity with their product, for now 🙂
** End of mini ad #2 **

** Clang in Android NDK! (Mar 20th 2013): **
Android NDK is now shipping with Clang. Additionally, there's also some work on getting GNUstep Base to build for Android. Sweet! I'll update this post with a link to additional information once this is proven to work okay.

** Rebuilding GCC (Jan 8th 2013): **
Instead of downloading prebuilt GCC, try rebuilding it.
Instructions blogpost (with various reference links)
Great presentation by Jackie Gleason
** End of rebuilding GCC **

I'm no fan of Java, and in fact, I'm not a fan of Android. When I originally heard Google is working on a Linux phone, I rejoiced. When I heard that Java would be the base of the userland, and that no existing program for Linux would be directly supported, my heart sank. In the meantime I became a big fan of Objective-C, Cocoa, Cocoa Touch, Mac, and all related technologies and projects.

So, I want to keep working in Objective-C. I sat down and studied my options. We have the Android SDK, we have the Android NDK, and a third party offering called Android NDK GCC 4.2.1 with Objective-C support.

SMALL UPDATE, May 8th 2012: I have not tested this, but here's the CrystaX .NET Improved Android NDK. Thanks to jeffamaphone for pointing it out. I did not test it, but r7 ships with GCC 4.6+.

Studying all this takes a while. Well, more than a while. I spent a day or two wrapping my head around all this, reading Android documentation. All this not counting stuff that I read, heard and discussed in previous months on this subject.

Android SDK is documented well enough, as long as you stick to Java. Android NDK is not particularly well documented, but solidly enough. Playing with the Objective-C is however a bit more complex, especially since Android NDK by itself does not come with Objective-C support turned on. Authors of the add-on compiler for Objective-C did not publicly document its proper use at all. Its use is nearly ungoogleable.

Since I'd hate to see you, my little lemon drops, spend as much time as I did on studying all this, here is something that will help you understand the complexities of the design of NDK, and how to combine all this with the Objective-C compiler.

Proficiency with GNU Make and Objective-C is highly recommended.
Proficiency with Java and Android is not required (I have none).

Not much in this article depends on Mac OS X apart from the paths, and the fact that there is no prebuilt Objective-C compiler for platforms other than Mac OS X. Parts that are about SDK and NDK should cleanly apply to Linux version of the Android SDK and NDK. It probably cannot easily apply to Windows.

Update on December 7, 2011: I just learned about a great presentation by Jackie Gleason (@LifeIsTooShort) on the same subject: Adding Objective-C Support to the Android NDK

If you wish to do so, you can donate me via PayPal for writing this PDF. Definitely not mandatory, though!

Donation choice

You can also send me other amounts directly via PayPal to address: ivucica@gmail.com

What I'm missing in Xcode4?

I'm a big fan of Xcode3. Xcode4 is a step in the right direction for me, though. Not so much as it would be when I started with Mac and iOS development, but still, it's ok.

However, there are large omissions and important bugs that are heavily influencing my productivity.

  1. Removed Right-click, Find In Documentation. (Update on April 1st 2011, 16:42 CET: Alt+left-click is a replacement for this.)
  2. Removed Command+shift+up to switch between header and source. Assistant views are not a replacement since I work on Macbook, which doesn't have all that much screen real-estate, especially, when you have the File Navigator on the left. (Update on July 12th 2011, 16:21 CET: Use Ctrl+cmd+up, or three-fingers-down-to-up touchpad gesture.)
  3. No ability opening multiple Get Info dialogs on the screen for different project Targets. In fact, Get Info was removed and replaced with (admittedly superior) way of editing build settings.
  4. When autocomplete lists tons of options, Page-down (Fn+Down) does not work. That's right, you can't scroll over a screenful of symbols at a time.
  5. Command+shift+b has been reassigned to … get this … Build & Analyze. Ok, that needed a shortcut (maybe), but Command+shift+b used to be the shortcut to open "build progress" output dialog.
  6. Build progress is now assigned a navigator; that is, hit Command+7 to get it. However… the Editor view does not automatically focus on latest build progress and.
  7. Closely related to previous item: there is no obvious shortcut for switching focus between Editor and Navigator. I really want to quickly choose a file, to quickly choose a build log, and to quickly choose an issue from the list. While this is not something that used to exist in Xcode3 (or at least I couldn't find it) it is still something that would be highly useful. Open Quickly – Command+Shift+O – is not a substitute.
  8. I really miss the old "Groups & Files" view. Not a big deal, but having that as an alternative to the new Navigators view would be excellent.
  9. While autocomplete got even better, Command+doubleclick is extremely dumbed down and cannot guess that in [[NSString alloc] initWithString:@"something"]; attempting to find initWithString in header probably means NSString's -initWithString:, right? Well, if you have another initWithString: in another class, Xcode4 will ask you which one you refer to (despite [NSString alloc] being declared to return NSString, thus there being no dillema whose -initWithString: needs to be used).
  10. Despite introducing tabs, they are next to useless: hard to open, and with no obvious keyboard shortcuts to switch tabs or close tabs.
  11. added March 18 2011, 14:12 Oh. Right-click, Add Files to "projectname.xcodeproj" does not take into account parent group path anymore. That means, despite configuring that pesky Window Systems/iOS group to point to path "relative to group" and pointing to "windowsystem/iOS" filesystem folder, Add Files dialog will no longer default to that folder. Meaning I nevertheless have to dig around the filesystem to find the relevant files.
  12. added March 18 2011, 14:40 You can no longer easily access full path to a currently open file by right-clicking on the titlebar. This is important in case error log refers to system-wide installed header file, which you go and happily change without affecting header file that you should be changing — the one in a subproject.

These are just some omissions that significantly reduce my productivity compared to Xcode3. I sincerely hope they will be patched by Apple, otherwise I'll simply have to do without them. There's no other way: iOS devs (and to some extent Mac devs) are hostages of the latest SDK which ships only with the latest IDE.

Upotreba Objective-C u igrama; moje mišljenje

A short Croatian language opinion post on use of Objective-C in games

Dobio sam nedavno pitanje o tome da li se isplati učiti Objective-C (u kontekstu igara).

Moje je mišljenje da Objective-C ima deset puta logičniju internu strukturu nego C++, te da je svojom kombinacijom karakteristika dinamičnih i statičnih jezika izuzetno pogodan za pisanje igara. Primjerice, evo stvaranje kapitalnog svemirskog broda koristeći string, i spremanje istog u SvemirskiBrod:
Continue reading

Getting Objective-C 2.0 to work on Debian's GNUstep with clang

If you are a Cocoa or Cocoa Touch developer, you may have attempted to use features such as properties in GNUstep, only to be surprised that these don't seem to be supported. This is because these are Objective-C 2.0 features.

To get the new features, the only way is to use a different compiler called clang. You may have seen this compiler used in newer releases of Xcode. This is a compiler that targets a virtual machine called LLVM before producing native code.

UPDATE May 4th 2011: GCC 4.6 has got the Objective-C 2.0 treatment, and since Debian includes GCC 4.6, I'd recommend you to try compiling your software that way. Not because it's a better compiler — I have no idea which one works better — but because it's there. Also, consider compiling GNUstep from trunk using GCC 4.6; it's rather easy to do. (CC=gcc-4.6 ./configure, whenever compiling a component of GNUstep).

Let's presume you managed to run an Objective-C program with GNUstep; that is, let's presume you are aware of Project Center, or GNUmakefiles. If you are didn't use GNUmakefiles, you should know that Project Center generates these in order to build your app.

Now you want to switch to clang, and you want to do so on your favorite operating system, Debian GNU/Linux.
Continue reading