Best objective-c questions in June 2011

What kind of leaks does Objective-C's automatic reference counting (in Xcode 4.2) not prevent/minimize?

13 votes

In the Mac and iOS platforms, memory leaks are often caused by unreleased pointers, so it is (as of now, at least) important to check your allocs, copies and retains to make sure each has a corresponding release message.

Xcode 4.2 introduces automatic reference counting with the latest version of Clang that totally does away with this problem by getting the compiler to memory-manage your stuff for you. That's pretty cool, and it does cut lots of unnecessary, mundane development time and prevent a lot of careless memory leaks that are easy to fix with proper retain/release balance. Even autorelease pools need to be managed differently when you enable ARC for your Mac and iOS apps (as you shouldn't allocate your own NSAutoreleasePools anymore).

But what other memory leaks does it not prevent that I still have to watch out for?

As a bonus, what are the differences between ARC on Mac and iOS and garbage collection on Mac OS X?

The primary memory-related problem you'll still need to be aware of is retain cycles. This occurs when one object has a strong pointer to another, but the target object has a strong pointer back to the original. Even when all other references to these objects are removed, they still will hold on to one another and will not be released. This can also happen indirectly, by a chain of objects that might have the last one in the chain referring back to an earlier object.

It is for this reason that the __unsafe_unretained and __weak ownership qualifiers exist. The former will not retain any object it points to, but leaves open the possibility of that object going away and it pointing to bad memory, whereas the latter doesn't retain the object and automatically sets itself to nil when its target is deallocated. Of the two, __weak is generally preferred on platforms that support it.

You would use these qualifiers for things like delegates, where you don't want the object to retain its delegate and potentially lead to a cycle.

Of course, there are several other less frequent, but still potentially problematic cases, which the published specification goes into in detail.

Much of the new behavior, based on keeping objects around as long as there is a strong pointer to them, is very similar to garbage collection on the Mac. However, the technical underpinnings are very different. Rather than having a garbage collector process that runs at regular intervals to clean up objects no longer being pointed to, this style of memory management relies on the rigid retain / release rules we all need to obey in Objective-C.

ARC simply takes the repetitive memory management tasks we've had to do for years and offloads them to the compiler so we never have to worry about them again. This way, you don't have the halting problems or sawtooth memory profiles experienced on garbage collected platforms. I've experienced both of these in my garbage collected Mac applications, and am eager to see how they behave under ARC.

For more on garbage collection vs. ARC, see this very interesting response by Chris Lattner on the Objective-C mailing list, where he lists many advantages of ARC over Objective-C 2.0 garbage collection. I've run into several of the GC issues he describes.

Is there a way to make Objective-C support a multi-variable switch construct?

13 votes

I was wondering: is there a way to make Objective-C support a multi-variable switch construct?

I mean, very often I have to deal with problems in which the solution depends on a pair of variables instead of a single one. For a long list of single variable values one can use a simple switch/case construct:

switch (var) {
    case 0: ...
    case 1: ...
    default: ...
}

But when you have to deal with the combination of two values you often happen to do something like this:

switch (var1) {
    case 0: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }
    case 1: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }        
    ...
}

And it gets more and more complicated ... What I'd really love to do is something like this:

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

that will result in a more simple and readable construct. Is there any solution to support such a structure? Or a slight variation of this one?

I like the answer from saphrosit but I'll make try to make it easy to understand.

Imagine the possible outcomes of your problem as squares in a grid where one edge of the edge of the grid represents values of var1 and the other edge represents the possible values of var2, then if you incrementialy counted through the squares of the of the grid you would it get something like this

      ||                              var1                                   |    
      ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
======++=====================================================================|
    0 ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
    1 ||    n    |    n+1    |    n+2    | ... |    n+j    | ... |  n+(n-1)  |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------| 
    2 ||   2*n   |   2*n+1   |  2*n+2    | ... |   2*n+j   | ... | 2*n+(n-1) |
 v ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 a    ||    .    |     .     |     .     |     |     .     |     |  .        |
 r ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 2  i ||   i*n   |   i*n+1   |   i*n+2   | ... |   i*n+j   | ... | i*n+(n-1) |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
      ||    .    |      .    |      .    |     |     .     |     |  .        |
  ----||---------+-----------+-----------+-----+-----------+-----+-----------|
  m-1 || (m-1)*n | (m-1)*n+1 | (m-1)*n+2 | ... | (m-1)*n+j | ... |   mn-1    | <-- (m-1)*n+(n-1) = m*n-n + (n-1) = mn-1
------||---------+-----------+-----------+-----+-----------+-----+-----------|

This would is called a row major matrix since you start by counting accross the rows. There is also a column major matrix where you start counting down first instead of across. This is how matrixes are stored in the C BLAS library so it should be very fimilar to many people.

In your case the outcome you're looking for can be addressed as var3 = var2*n + var1 you could lay this out in code as

#define N 10 // Maximum size of var1

int main() {

   int var1 = 1;
   int var2 = 1;

   switch(var1 + var2 * N){
      case 1 + 1 * N: printf("One One"); break;
      case 2 + 2 * N: printf("Two Two"); break;
      default:
      printf("Bada Bing");
   }

   return 0;
}

NOTE: the code that was here earlier wouldn't have worked, this works.

How does the new automatic reference counting mechanism work?

10 votes

Can someone briefly explain to me how ARC works? I know it's different from Garbage Collection, but I was just wondering exactly how it worked.

Also, if ARC does what GC does without hindering performance, then why does Java use GC? Why doesn't it use ARC as well?


For those voting to close questions about ARC: Whilst the iOS 5 SDK is still under NDA, ARC itself isn’t. ARC has been publicly announced and there’s some public documentation on LLVM’s Web site.

Every new developer who comes to Objective-C has to learn the rigid rules of when to retain, release, and autorelease objects. These rules even specify naming conventions that imply the retain count of objects returned from methods. Memory management in Objective-C becomes second nature once you take these rules to heart and apply them consistently, but even the most experienced Cocoa developers slip up from time to time.

With the Clang Static Analyzer, the LLVM developers realized that these rules were reliable enough that they could build a tool to point out memory leaks and overreleases within the paths that your code takes.

Automatic reference counting (ARC) is the next logical step. If the compiler can recognize where you should be retaining and releasing objects, why not have it insert that code for you? Rigid, repetitive tasks are what compilers and their brethren are great at. Humans forget things and make mistakes, but computers are much more consistent.

However, this doesn't completely free you from worrying about memory management on these platforms. I describe the primary issue to watch out for (retain cycles) in my answer here, which may require a little thought on your part to mark weak pointers. However, that's minor when compared to what you're gaining in ARC.

When compared to manual memory management and garbage collection, ARC gives you the best of both worlds by cutting out the need to write retain / release code, yet not having the halting and sawtooth memory profiles seen in a garbage collected environment. About the only advantages garbage collection has over this are its ability to deal with retain cycles and the fact that atomic property assignments are inexpensive (as discussed here). I know I'm replacing all of my existing Mac GC code with ARC implementations.

As to whether this could be extended to other languages, it seems geared around the reference counting system in Objective-C. It might be difficult to apply this to Java or other languages, but I don't know enough about the low-level compiler details to make a definitive statement there. Given that Apple is the one pushing this effort in LLVM, Objective-C will come first unless another party commits significant resources of their own to this.

The unveiling of this shocked developers at WWDC, so people weren't aware that something like this could be done. It may appear on other platforms over time, but for now it's exclusive to LLVM and Objective-C.

Control iPod from another app?

9 votes

I took a look at Apple's AddMusic sample code, but that's not quite what I want. I'm trying to find a way to start/stop music playing in the iPod app, not controlling what's contained in my app's sandbox.

Something like this...

 ____________
|            |
| |<  ||  >| |    skip back, play/pause, skip forward
|            |
|  XXXXXXXX  |    album art
|  XXXXXXXX  |
|  XXXXXXXX  |
|  XXXXXXXX  |
|            |
|____________|

Of course the app is more complex than this, but for now, I want to focus on assuming direct control.
+1 virtual cookie if you get the reference without using Google.

If this definitely isn't possible, I can rework AddMusic, but I'd rather not. Too messy.


— Artwork loading error moved to a new question.

— Text-to-Speech implementation moved to a new question.

— Progress bar fills to 100% as soon as the song starts. Working on a fix. (Failing pretty badly right now...)

The MediaPlayer framework is what you are looking for. There is a useful guide which also contains a link to the MediaPlayer API overview.

Specifically, you're looking for MPMusicPlayerController. Your app can control either a dedicated app media player or the iPod media player which appears to be what you want.

A simple example would be something like (header omitted):

@implementation MyPlaybackController

- (id)initWithNibName:(NSString *)nibName bundle:(id)bundleOrNil 
{
  if ((self = [super initWithNibName:nibName bundle:bundleOrNil])) {
    self.musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
  }  
  return self;
}

- (IBAction)skipForward:(id)sender
{
  [self.musicPlayer skipToNextItem];
}

- (IBAction)skipBack:(id)sender
{
  [self.musicPlayer skipToPreviousItem];
}

- (IBAction)togglePlayback:(id)sender
{
  if (self.musicPlayer.playbackState == MPMusicPlaybackStatePlaying) {
    [self.musicPlayer pause];
  } else {
    [self.musicPlayer play];
  }
}

@end

Do take time to read the documentations and take note of the caveats mentioned with regards to Home Sharing. You'll also want to register for notifications in changes to the player state that can occur from outside your control.

How to paint a good RGB color map?

8 votes

I'm trying to paint a full RGB color map that eventually will allow a user to select a color by tapping that visual map at any point. My current code is the following:

- (void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();

    for (float x=0; x<320; x++) {
        for (float y=0; y<416; y++) {

            float r = x / 320;
            float g = y / 416;
            float b = (y < 208) ? y / 208 : (416 - y) / 208;

            CGContextSetRGBFillColor(c, r, g, b, 1.0);
            CGContextFillRect(c, CGRectMake(x, y, 1, 1));

        }
    }
}

The result is not too bad but I'm not satisfied yet. The spectrum misses bright colors including white. The reason is clear: red, green and blue will never reach 1.0 at the same time.

Screenshot of the resulting color map

Do you have any advise how to improve that map so it represents the full spectrum of the RGB color space?

Thanks for all your input!

UPDATE:

As suggested by Josh Caswell I've used the HSB color space and the following code:

- (void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();

    int size = 20;

    for (float x=0; x<320; x+=size) {

        float s = x < 160 ? 1       : (320 - x) / 160;
        float b = x < 160 ? x / 160 : 1;

        for (float y=0; y<416; y+=size) {

            float h = y / 416;

            [[UIColor colorWithHue:h saturation:s brightness:b alpha:1.0] setFill];
            CGContextFillRect(c, CGRectMake(x, y, size, size));
        }
    }
}

This results in the following output which is perfect for my needs.

Result using HSB color space

Thanks for all input!

Well, you're trying to flatten a three-dimensional object onto a plane. An RGB color basically represents a point inside of a cube. Mapping the RGB solid onto a surface may be mathematically possible, but probably won't be particularly intuitive for this color-selection purpose.

You might have better luck using HSB, which is more like a cylinder with hue as angle around the circumference. You could "unroll" the cylinder, mapping hue to the y coordinate, then vary either brightness or saturation along the x axis -- you can do some simple testing to decide which component is more important for your application. A two-finger-swipe could be used for the third component if you felt it was necessary to include it.

HSB with saturation on X-axis:
HSB map; S on X axis

With brightness on X-axis:
HSB map; B on X axis

With saturation and brightness equal and both on X-axis:
HSB map; S=B on X axis

If you need white, which occurs when S = 0%, B = 100%, you could either stick a strip along one side, or try S = 1/B.

How to explain this Objective C method declaration "- method:parameter;"

8 votes

Declaring, implementing and using method like this:

Test.h:

- method:parameter;

Test.m:

- method:parameter{
    return nil;
}

Using:

[test method:anObject];

There is no return-type and parameter-type, but it works without any warning or error. Can somebody explain it?

As the Objective-C Programming Language document states:

If a return or parameter type isn’t explicitly declared, it’s assumed to be the default type for methods and messages — an id.

So:

- method:parameter;

effectively means:

- (id)method:(id)parameter;

and, correspondingly:

- method:parameter{
    return nil;
}

effectively means:

- (id)method:(id)parameter{
    return nil;
}

What does Objective-C actually do when you declare an object?

8 votes

I have read the memory management guide from Apple and I don't see where this case is explained...

Many times, especially when writing a class method to return an instance of a class, I'll start it out like this, because that's how I've seen it done, and it works.

[NOTE] This code is from memory - I'll update it when I get home to show an example that really works (I made this up to illustrate it, but obviously I don't recall it well enough to construct something that makes sense...

[EDIT] Here's my actual method - of course everyone was right that I must be calling alloc which I am.

+ (id)player
{
    Player *player = nil;
    if ((player = [[[super alloc] initWithFile:@"rocket.png"] autorelease])) {
    [player setProjectileType:kProjectileBullet];
        [player setProjectileLevel:1];
        [player setInvincible:YES];
        [player setEmitter:[CCParticleSystemQuad particleWithFile:@"exhaust.plist"]];
        [[player emitter] setPosition:ccp(0.0, player.contentSize.height/2)];
        [player addChild:player.emitter];
    }
    return player;
}

So what I got from the responses is: * Declaring the instance just gets me a pointer to a memory location and tells Xcode what class the object will be. * Setting the pointer to nil pretty much just sets it to zero - keeping it from having garbage in it (right?) * Since I'm autoreleasing the instance, the object that is returned is also autoreleased.

Thanks for helping me understand this!

Can someone explain what the compiler does when it sees this?

    DooDad* aDooDad = nil;

If you are really interested in what the compiler does, the answer is: the compiler will reserve some memory on the stack for the local variable aDooDad, which is a pointer type (it is generally 64 or 32 bits in size depending on the processor). That pointer is then initialized to contain nil (usually 0x00..00).

A statement like this:

         DooDad* aDooDad = [[DooDad alloc] init...];

makes use of pointer variable aDooDad to store the address in memory of the object that is further allocated (which is the address of memory reserved by alloc).

So, in the end,

    DooDad* aDooDad = nil;

is not declaring an object, just a variable whose content is interpreted as the address of an object of DooDad type. Such declaration, therefore, is just like any other declaration you know, e.g. when initializing an int to 0, so that later you can assign it some value in an if statement.

A statement like:

 [aDooDad doSomething];

is interpreted by the Objective-C runtime system like: send message doSomething to the object whose address is stored in aDooDad. If that address is nil no message is sent. On the other hand, if you dereference a nil pointer: *aDooDad you'll get undefined behavior.

Pointers are pretty low level stuff. I hope this helps.

Round to (1, 2, or 5) x 10^n in Objective-C?

8 votes

Is there a simple way of rounding a value either down to or to the nearest (1, 2, or 5) x 10^n where n is an integer? As in one of {..., .05 .1, .2, .5, 1, 2, 5, 10, 20, 50, 100...}

Thanks.

You can take the d=floor(log10(n)) of your number n to get the scale, then divide by 10 to the d to normalize the number to the range of [1.0,10.0). From that point it should be easy to round because there are very limited possibilities. Once you've done that, multiply by 10 to the d to restore the number to the original range.

The following function is in C, I don't know enough about Objective-C to know if this is idiomatic.

double RoundTo125(double value)
{
   double magnitude;
   magnitude = floor(log10(value));
   value /= pow(10.0, magnitude);
   if (value < 1.5)
      value = 1.0;
   else if (value < 3.5)
      value = 2.0;
   else if (value < 7.5)
      value = 5.0;
   else
      value = 10.0;
   value *= pow(10.0, magnitude);
   return value;
}

Remove all strings with duplicates in an NSArray

8 votes

I am trying to figure out how to implement this in Objective-C.

I want to remove the strings in an NSArray that have appear more than once in the array.

At the end I want to have an array that only has the unique lines in an array (meaning that not just the duplicates are deleted but also the original string that matches the duplicates.)

For example if you had the following array:

NSArray *array = [NSArray arrayWithObjects:@"bob", @"frank", @"sarah", @"sarah", @"fred", @"corey", @"corey", nil];

I would want the new array to look like this:

@"bob", @"frank", @"fred"

Use an NSCountedSet:

NSCountedSet *countedSet = [NSCountedSet setWithArray:yourArray];
NSMutableArray *finalArray = [NSMutableArray arrayWithCapacity:[yourArray count]];

for(id obj in countedSet) {
   if([countedSet countForObject:obj] == 1) {
      [finalArray addObject:obj];
   }
}

@Caleb suggested adding a method to NSCountedSet called -objectsWithCount:,, which I've implemented here:

@interface NSCountedSet (JRCountedSetAdditions)

- (NSArray *) objectsWithCount:(NSUInteger) count;

@end

@implementation NSCountedSet (JRCountedSetAdditions) 

- (NSArray *) objectsWithCount:(NSUInteger) count {
   NSMutableArray *array = [NSMutableArray array];
   for(id obj in self) {
      if([self countForObject:obj] == count) {
        [array addObject:obj];
      }  
   }
   return [NSArray arrayWithArray:array];   
}

@end

Once that's done, all you need is one line:

NSArray *finalArray = [[NSCountedSet setWithArray:yourArray] objectsWithCount:1];

By the way, this is type-agnostic, so this will work with any Objective-C object. :-)

Integrating Bison/Flex/Yacc into XCode

7 votes

Is there a simple way for integrating Bison/Flex/Yacc into XCode?

I want to write my own language to be parsed, which interacts with my ObjC objects.

But the tools will only take STDIN as input, and will only produce C code, instead of ObjC. They're basically only seem useful for command-line tools, otherwise they need massive pain to override the output every time I regenerate the parser code.

In a nutshell, give your grammar files a .ym extension instead of .y. Xcode will then run Bison with the necessary magic to support Objective-C.

Oddly enough, I found this question because I wanted to do the same thing. I remembered a discussion about it on Apple's cocoa-dev mailing list, but this question came up higher in my Google search. I found the discussion I remembered though, on CocoaBuilder - there's a pretty extensive example at the end. I hope it helps both of us, LOL!

(Edit) Beats the heck out of me how anyone ever managed to find this out, by the way - I still haven't found any official documentation about it.

Some questions about Automatic Reference Counting in iOS5 SDK

6 votes


I'm currently developing an app for iPad. The development started for iOS 4.2 and is now continuing (and I think will be completed) for iOS 4.3. I just read about ARC in iOS 5, and basically I understood that we will never need to release and retain objects anymore. My questions are:

  • If I decide to upgrade to iOS 5, do I need to remove all [myObject retain] and [myObject release] statements from my code?

  • If I develop a new app for iOS 5 using ARC, will I need to implement some sort of "retro-compatibility" checks? I.e.: will I need to check the version of iOS and call retain and release accordingly? So, basically, is ARC available for all iOS versions or just for iOS 5?

Thank you

If I decide to upgrade to iOS 5, do I need to remove all [myObject retain] and [myObject release] statements from my code?

Yes (including dealloc), but XCode 4.2 includes a new "Migrate to Objective-C ARC" tool (in the Edit->Refactor menu), which does that for you.

You enable ARC using a new -fobjc-arc compiler flag. ARC is supported in Xcode 4.2 for Mac OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. (Weak references are not supported in Mac OS X v10.6 and iOS 4). There is no ARC support in Xcode 4.1.

-

If I develop a new app for iOS 5 using ARC, will I need to implement some sort of "retro-compatibility" checks? I.e.: will I need to check the version of iOS and call retain and release accordingly? So, basically, is ARC available for all iOS versions or just for iOS 5?

No, because ARC does it's magic on compile time and not on run time.

Instead of you having to remember when to use retain, release, and autorelease, ARC evaluates the lifetime requirements of your objects and automatically inserts the appropriate method calls for you at compile time. The compiler also generates appropriate dealloc methods for you.

Further Information on ARC: http://clang.llvm.org/docs/AutomaticReferenceCounting.html

Is this a good way to release memory?

6 votes

I have been programming on iPhone for quite sometime and have had bad experiences with memory management. I was wondering if the following way is a good way to release memory.

int count = [someObject retainCount];

for (int i = 0; i < count; i ++) 
{
[someObject release];
}

This method was an act of desperation in a few situations (particularly UIWebViews) I had faced. The variable's retainCount is reduced to zero which will release the memory being used by it. The method is a little dirty but are there any bottlenecks associated with it?

You should not rely on the retainCount because there are possibility of retaining the object by iOS frameworks,

Read below what Apple say about retainCount.

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

To understand the fundamental rules of memory management that you must abide by, read “Memory Management Rules”. To diagnose memory management problems, use a suitable tool: