Best objective-c questions in December 2010

Why must the last part of an Objective-C method name take an argument (when there is more than one part)?

41 votes

In Objective-C, you can't declare method names where the last component doesn't take an argument. For example, the following is illegal.

-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;

Why was Objective-C designed this way? Was it just an artifact of Smalltalk that no one saw a need to be rid of?

This limitation makes sense in Smalltalk, since Smalltalk doesn't have delimiters around message invocation, so the final component would be interpreted as a unary message to the last argument. For example, BillyAndBobby take:'$100' andRun would be parsed as BillyAndBobby take:('$100' andRun). This doesn't matter in Objective-C where square brackets are required.

Supporting parameterless selector components wouldn't gain us much in all the usual ways a language is measured, as the method name a programmer picks (e.g. runWith: rather than take:andRun) doesn't affect the functional semantics of a program, nor the expressiveness of the language. Indeed, a program with parameterless components is alpha equivalent to one without. I'm thus not interested in answers that state such a feature isn't necessary (unless that was the stated reasons of the Objective-C designers; does anyone happen to know Brad Cox or Tom Love? Are they here?) or that say how to write method names so the feature isn't needed. The primary benefit is readability and writability (which is like readability, only... you know), as it would mean you could write method names that even more closely resemble natural language sentences. The likes of -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication (which Matt Gallagher points out on "Cocoa With Love" is a little bit confusing when you drop the formal parameter) could be named -(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, thus placing the parameter immediately next to the appropriate noun.

Apple's Objective-C runtime (for example) is perfectly capable of handling these kind of selectors, so why not the compiler? Why not support them in method names as well?

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface Potrzebie : NSObject
-(void)take:(id)thing;
@end

@implementation Potrzebie
+(void)initialize {
    SEL take_andRun = NSSelectorFromString(@"take:andRun");
    IMP take_ = class_getMethodImplementation(self, @selector(take:));
    if (take_) {
        if (NO == class_addMethod(self, take_andRun, take_, "@@:@")) {
            NSLog(@"Couldn't add selector '%@' to class %s.", 
                  NSStringFromSelector(take_andRun), 
                  class_getName(self));
        }
    } else {
        NSLog(@"Couldn't find method 'take:'.");
    }
}

-(void)take:(id)thing {
    NSLog(@"-take: (actually %@) %@",NSStringFromSelector(_cmd), thing);
}
@end

int main() {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Potrzebie *axolotl=[[Potrzebie alloc] init];
    [axolotl take:@"paradichloroaminobenzaldehyde"];
    [axolotl performSelector:NSSelectorFromString(@"take:andRun") 
                  withObject:@"$100"];
    [axolotl release];

    [pool release];
    return 0;
}

This is Brad Cox. My original answer misunderstood the question. I assumed reallyFast was a hardcoded extension to trigger faster messaging, not a kind of syntactic sugar. The real answer is that Smalltalk didn't support it, perhaps because its parser couldn't deal with the (assumed) ambiguity. Although OC's square brackets would remove any ambiguity, I simply didn't think of departing from Smalltalk's keyword structure.

Making Objective C Classes look Beautiful

20 votes

I wanted to ask you all for you opinions on code smells in Objective C, specifically Cocoa Touch. I'm working on a fairly complex game, and about to start the Great December Refactoring.

A good number of my classes, the models in particular, are full of methods that deal with internal business logic; I'll be hiding these in a private category, in my war against massive header files. Those private categories contain a large number of declarations, and this makes me feel uneasy... almost like Objective-C's out to make me feel guilty about all of these methods.

The more I refactor (a good thing!), the more I have to maintain all this duplication (not so good). It just feels wrong.

In a language like Ruby, the community puts a LOT of emphasis on very short, clear, beautiful methods. My question is, for Objective C (Cocoa Touch specifically), how long are your methods, how big are your controllers, and how many methods per class do you all find becomes typical in your projects? Are there any particularly nice, beautiful examples of Classes made up of short methods in Objective C, or is that simply not an important part of the language's culture?

DISCLOSURE: I'm currently reading "The Little Schemer", which should explain my sadness, re: Objective C.

Beauty is subjective. For me, an Objective-C class is beautiful if it is readable (I know what it is supposed to do) and maintainable (I can see what parts are responsible for doing what). I also don't like to be thrown out of reading code by an unfamiliar idiom. Sort of like when you are reading a book and you read something that takes you out of the immersion and reminds you that you are reading.

You'll probably get lots of different, mutually exclusive advice, but here are my thoughts.

  • Nothing wrong with private methods being in a private category. That's what it is there for. If you don't like the declarations clogging up the file either use code folding in the IDE, or have your extensions as a category in a different file.
  • Group related methods together and mark them with #pragma mark statements
  • Whatever code layout you use, consistency is important. Take a few minutes and write your own guidelines (here is an example) so if you forget what you are supposed to be doing you have a reference.
  • The controller doesn't have to be the delegate and datasource you can always have other classes for these.
  • Use descriptive names for methods and properties. Yes, you may document them, but you can't see documentation when Xcode applies code completion, where well named methods and properties pay off. Also, code comments get stale if they aren't updated while the code itself changes.
  • Don't try and write clever code. You might think that it's better to chain a sequence of method calls on one line, but the compiler is better at optimising than you might think. It's okay to use temporary variables to hold values (mostly these are just pointers anyway, so relatively small) if it improves readability. Write code for humans to read.
  • DRY applies to Objective-C as much as other languages. Don't be worried about refactoring code into more methods. There is nothing wrong with having lots of methods as long as they are uesful.

When to use NSInteger vs int?

14 votes

When should I be using NSInteger vs int when developing for iOS? I see in the apple sample code they use NSInteger (or NSUInteger) when passing a value as an argument to a function or returning a value from a function.

- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...

But w/in a function they're just using int to track a value

for (int i; i < something; i++)
...

int something;
something += somethingElseThatsAnInt;
...

I've read (been told) that NSInteger is a safe way to reference an integer in either a 64-bit or 32-bit environment so why use int at all?

You usually want to use NSInteger when you don't know what kind of processor architecture your code might run on, so you may for some reason want the largest possible int type, which on 32 bit systems is just an int, while on a 64-bit system it's a long.

I'd stick with using NSInteger instead of int/long unless you specifically require them.

NSInteger/NSUInteger are defined as *dynamic typedef*s to one of these types, and they are defined like this:

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

Gap above NSMenuItem custom view.

12 votes

I am using the setView: method on an NSMenuItem to set a custom view. In this custom view there is an image which takes the whole of the view. The NSMenuItem with this custom view is the first in the menu but the problem is it doesn't sit flush with the top of the menu, there is a big gap as you can see here:

alt text

Why is this happening and how can I stop it?


EDIT

I am using this code now but I am getting EXC_BAD_ACCESS on the line InstallControlEventHandler.

-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    HIViewRef contentView;
    MenuRef menuRef = [statusMenu carbonMenuRef];

    HIMenuGetContentView(menuRef, kThemeMenuTypePullDown, &contentView);

    EventTypeSpec hsEventSpec[1] = {
        { kEventClassMenu, kEventMenuCreateFrameView }
    };

    InstallControlEventHandler(contentView,
                           NewEventHandlerUPP((EventHandlerProcPtr)hsMenuCreationEventHandler),
                           GetEventTypeCount(hsEventSpec),
                           hsEventSpec,
                           NULL,
                           NULL); // Get EXC_BAD_ACCESS here.
}

static OSStatus hsMenuContentEventHandler( EventHandlerCallRef caller, EventRef event, void* refcon )
{
    OSStatus  err;

    check( GetEventClass( event ) == kEventClassControl );
    check( GetEventKind( event ) == kEventControlGetFrameMetrics );

    err = CallNextEventHandler( caller, event );
    if ( err == noErr )
    {
        HIViewFrameMetrics  metrics;

        verify_noerr( GetEventParameter( event, kEventParamControlFrameMetrics, typeControlFrameMetrics, NULL,
                                        sizeof( metrics ), NULL, &metrics ) );

        metrics.top = 0;

        verify_noerr( SetEventParameter( event, kEventParamControlFrameMetrics, typeControlFrameMetrics,
                                        sizeof( metrics ), &metrics ) );
    }

    return err;
}

static OSStatus hsMenuCreationEventHandler( EventHandlerCallRef caller, EventRef event, void* refcon )
{
    OSStatus  err = eventNotHandledErr;

    if ( GetEventKind( event ) == kEventMenuCreateFrameView)
    {
        err = CallNextEventHandler( caller, event );
        if ( err == noErr )
        {
            static const EventTypeSpec  kContentEvents[] =
            {
                { kEventClassControl, kEventControlGetFrameMetrics }
            };

            HIViewRef          frame;
            HIViewRef          content;

            verify_noerr( GetEventParameter( event, kEventParamMenuFrameView, typeControlRef, NULL,
                                            sizeof( frame ), NULL, &frame ) );
            verify_noerr( HIViewFindByID( frame, kHIViewWindowContentID, &content ) );
            InstallControlEventHandler( content, hsMenuContentEventHandler, GetEventTypeCount( kContentEvents ),
                                       kContentEvents, 0, NULL );
        }
    }

    return err;
}

Also note the line metrics.top = 0 this is the line which should remove the gap at the top. However I cannot get it work that far. Does anyone know why I would be recieving an EXC_BAD_ACCESS there. I have already created and allocated statusMenu so surely it should work?

Your post is tagged "Objective-C" and "Cocoa", although your sample code is C and Carbon. I assume you'd prefer a Cocoa solution?

It's actually pretty simple in Cocoa. The only trick is learning how to draw outside the lines. :-)

@interface FullMenuItemView : NSView
@end

@implementation FullMenuItemView
- (void) drawRect:(NSRect)dirtyRect
{
    NSRect fullBounds = [self bounds];
    fullBounds.size.height += 4;
    [[NSBezierPath bezierPathWithRect:fullBounds] setClip];

    // Then do your drawing, for example...
    [[NSColor blueColor] set];
    NSRectFill( fullBounds );
}
@end

Use it like this:

CGFloat menuItemHeight = 32;

NSRect viewRect = NSMakeRect(0, 0, /* width autoresizes */ 1, menuItemHeight);
NSView *menuItemView = [[[FullMenuItemView alloc] initWithFrame:viewRect] autorelease];
menuItemView.autoresizingMask = NSViewWidthSizable;

yourMenuItem.view = menuItemView;

How to draw a "speech bubble" on an iPhone?

9 votes

Hi there.

I'm trying to get a "speech bubble" effect similar to the one in Mac OS X when you right click on something in the dock. Here's what I have now:

alt text

I need to get the "triangle" part of the lower portion. Is there any way I can draw something like that and get a border around it? This will be for an iPhone app.

Thanks in advance!

EDIT: Many thanks to Brad Larson, here's what it looks like now: alt text

I've actually drawn this exact shape before (rounded rectangle with a pointing triangle at the bottom). The Quartz drawing code that I used is as follows:

CGRect currentFrame = self.bounds;

CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineWidth(context, strokeWidth);
CGContextSetStrokeColorWithColor(context, [MyPopupLayer popupBorderColor]); 
CGContextSetFillColorWithColor(context, [MyPopupLayer popupBackgroundColor]);

// Draw and fill the bubble
CGContextBeginPath(context);
CGContextMoveToPoint(context, borderRadius + strokeWidth + 0.5f, strokeWidth + HEIGHTOFPOPUPTRIANGLE + 0.5f);
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f - WIDTHOFPOPUPTRIANGLE / 2.0f) + 0.5f, HEIGHTOFPOPUPTRIANGLE + strokeWidth + 0.5f);
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f) + 0.5f, strokeWidth + 0.5f);
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f + WIDTHOFPOPUPTRIANGLE / 2.0f) + 0.5f, HEIGHTOFPOPUPTRIANGLE + strokeWidth + 0.5f);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, strokeWidth + HEIGHTOFPOPUPTRIANGLE + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, round(currentFrame.size.width / 2.0f + WIDTHOFPOPUPTRIANGLE / 2.0f) - strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, strokeWidth + 0.5f, HEIGHTOFPOPUPTRIANGLE + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, strokeWidth + HEIGHTOFPOPUPTRIANGLE + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, HEIGHTOFPOPUPTRIANGLE + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);

// Draw a clipping path for the fill
CGContextBeginPath(context);
CGContextMoveToPoint(context, borderRadius + strokeWidth + 0.5f, round((currentFrame.size.height + HEIGHTOFPOPUPTRIANGLE) * 0.50f) + 0.5f);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, round((currentFrame.size.height + HEIGHTOFPOPUPTRIANGLE) * 0.50f) + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, round(currentFrame.size.width / 2.0f + WIDTHOFPOPUPTRIANGLE / 2.0f) - strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, strokeWidth + 0.5f, HEIGHTOFPOPUPTRIANGLE + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, round((currentFrame.size.height + HEIGHTOFPOPUPTRIANGLE) * 0.50f) + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, round((currentFrame.size.height + HEIGHTOFPOPUPTRIANGLE) * 0.50f) + 0.5f, borderRadius - strokeWidth);
CGContextClosePath(context);
CGContextClip(context);     

The clipping path at the end can be left out if you're not going to use a gradient or some other more fill that's more complex than a simple color.

Mobile developer interview questions, that a non-mobile developer can ask

8 votes

I need to interview some people for a mobile developer position (iphone) soon. The problem is that my strength is in Java web development.

What questions should i ask without sounding like an idiot? Also, what are valid answers to these questions?

Hi MKoryak. If it was me, I would ask them...

are they completely familiar with these TEN KEY POINTS:

  • XCode (and ideally it's debugging tools)
  • Interface Builder
  • submitting apps to the app store, everything that involves (certs, blah blah)
  • in objective-C, using properties inside out
  • in objective-C, using delegates inside out
  • networking with ASIHttpRequest, AsyncSockets, GameKit, Bonjour
  • total understanding of subclassing
  • basics like CoreAnimation and CoreData
  • "all the usual interfaces" on iOS like UITableView, etc etc etc etc
  • utterly everything, from top to bottom, about memory management

I think that's a good starter list. (If I've forgotten anything obvious, it will soon be suggested.)

Note that item 10, memory management, is the critical item. You just can't build finished working production mobile device apps unless you are a memory expert on your platform. Furthermore someone who's really good at iPhone memory management is usually good at everything else on the iPhone. If I could only ask one thing that's it!

There are also a dozen (more?) little things you just have to have absolutely down pat to develop for iPhone - for example "preferences," "accelerometer," "icons and splash screens," "playing sounds," and so on and on. You have to be able to do all those in five minutes, not five days of investigation, in production. It's pretty tough really. Someone could probably list all these "minor must-haves".

A perhaps separate somewhat specialist issue is OpenGL. Depending on what you're payin' them and what you need, you may demand someone who is, furthermore, an OpenGL expert.

Is your company's field games development? If so, it is perfectly likely that, furthermore, as a "total" iPhone games developer, you may need someone who is, also, already completely expert with

  • Unity3D (for 3D etc)
  • the popular physics (2D) packages (eg chipmunk, etc)
  • one way or another, the server side of client-server systems

So that's that. A question is - what SPECIFICALLY are you going to be doing (in general terms)? ie, scientific computing, game development, marketing apps to get rich, in-house catalogs, hand-held clients, or?? If you tell us we can tell you what they need.

And finally overwhelmingly -- you would have to be able to see 3+ actual apps that they have done. With the iPhone, you really need to be able to "bring it home", writing good code snippets is not enough, you know. It's tough.


Here's the "stuff we forgot in the ten critical points" list beginning already!

  • Matt points out, they should be comfortable with "MVC" which stands for model-view-controller thinking. (This is kind of a fascist cult within the iOS world - we all adhere! We can't tell you about it until you are one of us. If their face lights up when you mention MVC, you're all set. If they get dark and uncomfortable looking, move on...)

  • David and Brad point out that - perhaps unlike other programming fields - iPhone and Mac programmers almost always have to have a sense of the interface. You just have to have a feel for that clean iPhone interface, you have to know how to layout any particular problem on the iPhone using the iOS elements that add up to the iPhone user experience. Make sure they know what HIG stands for.

How to convert photos to Polaroid-like programmatically?

8 votes

How to convert modern day photos to the look and feel of those Polaroid photos ? References and/or sample codes are welcome. Thanks!

Convert the images to HSV (cv::cvtColor) then look at adjusting the hue/saturation values

see http://en.wikipedia.org/wiki/HSL_and_HSV for a rather too technical article

Windows development using Objective-C

7 votes

Having recently read up a on Objective-C it strikes me as a fairly neat language with plenty of cool features.

I have no intention of doing any iPhone development, however I understand that GCC is able to compile Objective-C code and so I wanted to know - Is Objective-C a viable alternative language to C99 for Windows development?

In particular:

  • Is anyone currently doing Windows development using Objective-C?
  • Are there any runtime components that would need to be distributed with my applications?
  • I understand that Objective-C is a superset of C, does this mean that it is possible to use any C-compatible library? (for example the Windows API)
  • Would I get garbage collection in my applications?
  • I've found Cocotron and GNUstep which are often mentioned when talking about using Objective-C on other platforms, however as GCC can already be used to compile Objective-C I don't really understand why I would need these.
  • Are there any other pitfalls or traps I might run in attempting Windows development using Objective-C?

With respect to your first question, I don't know if anyone is seriously doing development on windows with Objective-C, but there may be, though those numbers would probably be less than those doing serious work with a language like whitespace.

Secondly, you would need, at a minimum the objective-c runtime. There are two runtimes, NeXT's (now Apple's) runtime, and the GNU Objective-C runtime. They are not compatible. If you are on a non-NeXT and non-Apple platform, such as windows, you have no choice, GNU runtime only.

Objective-C is a superset of C, and yes you can use the Win32 API if you so desire directly in your objective-c code. As well, you would only get garbage collection if you use a conservative collector, and it ties in with the libraries you're using. In short: No.

What GCC has is support for the objective-c language, and runtime, no standard library. What the GNU objc runtime provides you with in terms of a standard library, is two objects: Object, and NXConstantString class, which is needed to support the @"" syntax. Object is merely a base class. Not very useful, eh? This is why frameworks like Cocotron and GNUstep exist — to give you access to an implementation of OPENSTEP/Cocoa.

Regarding pitfalls or traps, yeah: Your application, even using Cocotron or GNUstep may never be portable to the Mac for instance, or you may get bit by things like typed selectors in the GNU objc runtime, or a plethora of other problems. Let me finish answering this by posing another question: What pitfalls or traps might you run into targeting .NET? I'm sure some if not most of those apply in this case too. Standard pitfalls and traps apply.

I hope this helps.

Purpose of @ Symbol Before Strings?

7 votes

I've been using Objective-C for a while now, but have never really understood what the purpose of the @ symbol before all strings is. For instance, why do you have to declare a string like this:

NSString *string = @"This is a string";

and not like this:

NSString *anotherString = "This is another string";

as you do in Java or so many other programming languages. Is there a good reason?

It denotes a NSString (rather than a standard C string)

an NSString is an Object that stores a unicode string and provides a bunch of method to assist with manipulating.

a C string is just a \0 terminated bunch of characters (bytes).

EDIT: and the good reason is that Objective-C builds on top of C, the C language constructs need to be still available. @"" is an objective-c only extension.

How do I redirect all errors, including uncaught exceptions, NSLog calls, and other logs, to a log file on Mac OS X?

6 votes

I am attempting to find a logging framework for a Cocoa application, written in ObjC.

What I've attempted so far:

  1. Use NSLog, but then realise that it is very hard to configure and redirect. I suppose I could hack it and write a macro that obtains the information I want, such as thread ID, current function, current line, current file, current time, the message, etcetera, and then uses NSLog, however...
  2. NSLog ultimately uses NSLogv, which ultimately uses asl, so I thought "fantastic", I tried using asl instead, with the default client and context (If I was doing this properly, I would've had to create a new client for each thread), however, unless I create a macro, this is also very verbose, and I noticed that the logs sent via asl got broadcast system wide, whereas NSLog only logged to stderr, and I want them to both go to the same log!
  3. I then noticed that errors, are formatted in a different way (different datestamp, etc), so there is now a third logging context.

What l logging framework setup can I use to have ALL messages logged through that framework in a convenient fashion so that if there is a problem with an application, a developer can get the log files, and figure out what went wrong?

I don't want to simply redirect stderr, I want to have a structured log output that contains all of the logs. I don't want some logs going to standard output, I don't want any logs sent to a syslogd, I just want all the logs written to a single file, that reliably identifies all the pertinent information about that log message (such as thread ID, message, the function that called the logger, etcetera), in format that is easy to view and visualise.

What I want is to redirect all current logs to the new destination.

Does anyone have any suggestions?

EDIT:

Effectively, what I want to do, in ObjC terms is:

  1. Do "method swizzling" on the NSLog function. Is this possible? Is it possible to (re)configure the use of the Apple System Logger to override any prior configuration of the service within the same application?
  2. Determine all the places where I have to catch unhandled exceptions. THis includes, but possibly isn't limited to: Unhandled Cocoa Exceptions. Unhandled ObjC exceptions. Unhandled C++ exceptions. Unix Signals.
  3. Catch and log the stack for errors such as those raised by CoreGraphics. (The ones that simply log a message saying "Add a breakpoint using your debugger!!!").

You can intercept NSLog() messages (but not ASL in general) using _NSSetLogCStringFunction(). It’s documented here for WebObjects 4 for Windows, but it exists in current Mac OS and iOS releases too. However, it’s a private function that may go away at any time, so you shouldn’t rely on it in released code.

If you want to be able to safely do this for non-debug builds, I suggest duplicating this enhancement request on Radar.

iPhone: How to get local currency symbol (i.e. "$" unstead of "AU$")

6 votes

Here's a code of how I get currency symbol now:

NSLocale *lcl = [[[NSLocale alloc] initWithLocaleIdentifier:@"au_AU"] autorelease];
NSNumberFormatter *fmtr = [[[NSNumberFormatter alloc] init] autorelease];
[fmtr setNumberStyle:NSNumberFormatterCurrencyStyle];
[fmtr setLocale:lcl];

NSLog( @"%@", [lcl displayNameForKey:NSLocaleCurrencySymbol value:@"AUD"] );
NSLog( @"%@", [fmtr currencySymbol] );

Both NSLogs return "AU$". As I understood from Apple development documentation, there are at least two currency symbols for each currency (these symbols could be the same, though) - local (that is used within a country. $ for Australia, for example) and international (AU$ for Australia). So, the question is how to get LOCAL currency symbol. Any ideas?

Thanks in advance.

It's not ideal in that it's not coming out of the system, but obviously you could create your own internal table using a list of current currency symbols*. Since that list has the unicode symbols for it it would simply be a matter of matching up the Apple list of locales with the list.

Y'know, just in case the Apple-provided ones aren't actually accessible.

*Note: link not intended to be authoritative, see comments.

Help with multithreaded Core Data app design

6 votes

alt text

Above is a simplification of what my model looks like. My app has a NSWindowController object controlling two NSViewController objects for the user and account entities. When a user logs in to the app, they can modify user or account information by bringing up the relevant view controller. In the background I have the application periodically populating the user's logs in the application delegate on a separate thread.

I am using a separate NSManagedObjectContext for the background thread and the application delegate's NSManagedObjectContext for data entry in the view controllers. I would like to know a few things:

1) is this good practice? Should I create a NSManagedObjectContext for each view controller and then merge the contexts whenever the user is done making changes?

2) Because the log entity is created in the background thread, it has it's own NSManagedObjectContext. However, each log includes information from the user and account entities, which are created in the application delegate's NSManagedObjectContext. This is how I am fetching a user:

- (NSManagedObjectID*) fetchUser:(NSString*) userID {   
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];   
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"user":inManagedObjectContext:self.managedObjectContext];
    /** snip **/
}

This method is called by the background thread as follows:

NSManagedObjectID* userObjectID = [self fetchUser:userID];
NSManagedObject* userObject = [self.logsManagedObjectContext objectWithID:userObjectID];

Is what I'm doing in fetchUser thread-safe? Do I need to lock the main managed object context while fetching a user in case one of the views is modifying the same user? From this article I understand (perhaps incorrectly) that I may have to do so. So far I haven't run into any problems but I don't want to leave a potential edge case.

3) When one of the view controllers makes changes to the application delegate's NSManagedObjectContext it posts a notification that is handled as follows:

- (void)contextDidSave:(NSNotification *)notification {
    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
    [self.logManagedObectContext performSelector:selector onThread:backgroundThread withObject:notification waitUntilDone:NO];
}

Is this how I should handle the merge or should I be merging the application delegate's NSManagedObjectContext instead? I found that doing that (on the main thread) locked up the UI.

Any help will be appreciated.

NSManagedObjectContext objects are not thread-safe. This means that if you wish to access Core Data from multiple threads, you will need one for each thread (and created on the thread too). Each of these can use the same NSPersistentStoreCoordinator, which will serialise access to the persistent store.

This occurs because each NSManagedObjectContext knows how to properly lock the NSPersistentStoreCoordinator when it is in use, avoiding collisions. By following these rules, you should remain thread-safe.

As you're already doing, NSManagedObjectID objects should be used to pass Core Data objects from one MOC to another (and by extension from one thread to another). However you are calling fetchUser: which uses the MOC from your main thread, on a background one. This isn't correct. That fetchUser: method call must be called from the main thread. Of course, there's nothing to stop you from retrieving the user in the background thread using the background MOC.

In summary, always make calls to an NSManagedObjectContext from the thread it was created in.

The trick here is to make sure that both MOCs know about the other's saves, so you must register to receive the notifications from each context. You should then be performing the mergeChangesFromContextDidSaveNotification: from the appropriate thread for the MOC. At the moment, your background context is being notified about changes from the main thread's context, but not vice versa.

Oh, and there's no need to have a separate context for each NSViewController. As UI elements, their interactions with the context will occur on the same (main) thread, so sharing is fine.

How to make something like iPhone Folders?

6 votes

Hi there!

I'm wanting to know if there's a way I can transform my view to look something like iPhone folders. In other words, I want my view to split somewhere in the middle and reveal a view underneath it. Is this possible?

alt text

EDIT: Per the suggestion below, I could take a screenshot of my application by doing this:

UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Not sure what to do with this, however.

EDIT:2 I've figured out how to add some shadows to my view, and here's what I've achieved (cropped to show relevant part):

alt text

the basic thought will be to take a picture of your current state and split it somewhere. Then animate both parts by setting a new frame. I don't know how to take a screenshot programmatically so I can't provide sample code…

EDIT: hey hey it's not looking great but it works ^^

// wouldn't be sharp on retina displays, instead use "withOptions" and set scale to 0.0
// UIGraphicsBeginImageContext(self.view.bounds.size);
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *f = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CGRect fstRect = CGRectMake(0, 0, 320, 200);
CGRect sndRect = CGRectMake(0, 200, 320, 260); // was 0,200,320,280


CGImageRef fImageRef = CGImageCreateWithImageInRect([f CGImage], fstRect);
UIImage *fCroppedImage = [UIImage imageWithCGImage:fImageRef];
CGImageRelease(fImageRef);

CGImageRef sImageRef = CGImageCreateWithImageInRect([f CGImage], sndRect);
UIImage *sCroppedImage = [UIImage imageWithCGImage:sImageRef];
CGImageRelease(sImageRef);


UIImageView *first = [[UIImageView alloc]initWithFrame:fstRect];
first.image = fCroppedImage;
//first.contentMode = UIViewContentModeTop;
UIImageView *second = [[UIImageView alloc]initWithFrame:sndRect];
second.image = sCroppedImage;
//second.contentMode = UIViewContentModeBottom;

UIView *blank = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)];
blank.backgroundColor = [UIColor darkGrayColor];

[self.view addSubview:blank];
[self.view addSubview:first];
[self.view addSubview:second];

[UIView animateWithDuration:2.0 animations:^{
    second.center = CGPointMake(second.center.x, second.center.y+75);
}];

You can uncomment the two .contentMode lines and the quality will improve but in my case the subview has an offset of 10px or so (you can see it by setting a background color to both subviews)

//EDIT 2: ok found that bug. Had used the whole 320x480 screen, but had to cut off the status bar so it should be 320x460 and all is working great ;)

what is difference between alloc and allocWithZone: ?

6 votes

From forum discussion , seem like that the big difference is performance factor, allocWithZone: will alloc memory from particular memory area, which reduce cost of swapping.

In practice, almost get no chance to use allocWithZone: , anyone can give simple example to illustrate which case to use allocWithZone: ?

Thanks,

It wouldn't surprise me if I get downvoted for this answer, since I've never used the method and I'm also interested to hear what others say, but from the documentation:

When one object creates another, it’s sometimes a good idea to make sure they’re both allocated from the same region of memory. The zone method (declared in the NSObject protocol) can be used for this purpose; it returns the zone where the receiver is located.

This suggests to me that your ivars, and any objects your classes "create" themselves could make use of +allocWithZone: in this way, to make the instances they create in the same zone.

-(id)init {
  if (self = [super init]) {
    someIvar = [[SomeOtherClass allocWithZone:[self zone]] init];
  }

  return self;
}

Detect when a User takes a Screenshot.

6 votes

I am looking for way for my app to receive a notification when the user takes a screenshot either with Command-Shift-3 or Command-Shift-4.

An example of this are apps like Droplr and Cloud App which automatically upload the screenshot taken.

I have been searching around and found out that it may have something to do with Darwin Notifications but I am unsure as to where to start.

This was mentioned in one of the earlier comments, but you can use an NSMetadataQuery searching for files where kMDItemIsScreenCapture = 1. This is a special attribute that gets added to screenshot files.

I just whipped up a little demo showing how to do this and posted it on github:

https://github.com/davedelong/Demos/blob/master/ScreenShot%20Detector

return from inside a @synchronized block in objective-c

6 votes

Hi all, May somebody tell me if it is ok to return from inside a @synchronized block ?

For example:

    - (id)methodThatReturnsSomething:(BOOL)bDoIt
    {
        @synchronized(self) {      

             if(!bDoIt) return nil;
             ...
        }
    }

or should I unlock the block first (using NSLock instead)?

@synchronized will automatically take down its exception-handling context when you return, and relinquish the lock. So the code you've written is fine, except that you don't return a value from a method that should.

Activity Indicator when integrated into Searchbar does not display in iPhone SDK

5 votes

Hi Guys,

In my iPhone app, I want to add activity indicator on top of a searchbar.

When it is searching it should display activity indicator.

I have added the activity indicator in XIB and created its outlet.

I am making it hide when the searching finishes.

but Activity Indicator does not display.

Problem

I figured out that search function(say A)(where I animate the activity indicator) in turn calls another function(say B) so the main thread is being used in executing the function B. But for activity indicator to animate we require the main thread.

So I tried calling function B using performSelectorInBackGround:withObject method. Now when I click search the activity indicator is shown but the functionality of function B does not execute.

What can be a work around for this?

Please Help and Suggest

Thanks

Thanks to all the guys for your immense help and for appreciating the question.

Sorry to those whom I couldnt reply back.

I have got the solution and it is as follows.

I just wrote the below line in Search button click event.

[NSThread detachNewThreadSelector:@selector(threadStartAnimating:) toTarget:self withObject:nil];

And defined the function threadStartAnimating: as follows:

-(void)threadStartAnimating:(id)data
{
   [activityIndicator setHidden:NO];
   [activityIndicator startAnimating]; 
}

Hope this helps someone.

Thanks once again.

Does UIViewController's presentModalViewController:animated: retain the modal controller?

5 votes

This has implications on the way I interact with my modal controllers. When I first started out in iOS development, I assumed that UIViewController did not retain the modally presented view. Well, really it was more like I had no reason to assume it did retain them. This left me with fairly awkward attempts at releasing them when I knew they would have finished their dismissal animations:

_myViewController = [[UIViewController alloc] init];
[self. present modalViewController:_myViewController animated:YES];
/* 
Some stuff, then in a different method all together,
probably as the result of a delegate callback or something...
*/
[self dismissModalViewControllerAnimiated:YES];
[_myViewController performSelector:@selector(release) withObject:nil afterDelay:0.5f];

Then, I saw the modalViewController property of UIViewController and thought, "Man, I hope it retains that property when a modal view controller is presented." Sure enough, I logged the retain count on several of these attempts and noticed a general increase immediate after the call to presentModalViewController:animated: (I know, retain counts are not a perfect metric). So, somewhere along the line, I have started using a much nicer pattern where I assume that any controller object I present modally is retained by the presenting controller. This lets me write the standard present code:

UIViewController* myViewController = [[UIViewController alloc] init];
[self presentModalViewController:myViewController animated:YES];
[myViewController release]; // <- Fire and forget!

Now, of course, there is no awkwardness: no need to wait for an animation to finish, or even keep a reference to the presented controller if I don't need it. I can blindly dismiss it later and not worry about leaking. I like it.

I have logged many a dealloc in my modally presented controllers and they are always called precisely when I want, which leads me to feel confident in my approach: UIViewController's presentModalViewController:animated: retains the presented controller as the modalViewController property.

But, and this is the meat of this question, I realized that I can't confirm this as documented behavior. And if it's not documented, I should not feel nearly as safe as I do, because Apple makes no promises about the longevity of undocumented behavior. The modalViewController property is publicly readonly, so I can only assume a retain behind the scenes, and the documentation on presentModalViewController:animated: says only:

Sets the modalViewController property to the specified view controller.

"Sets" could be assign or retain. Nothing I read blatantly confirms or denies my position. Since this is an assumption I make often, I would really love it if someone could point out a fact that I have missed somewhere in the bowels of documentation to put my mind at ease about the legitimacy of this practice.

EDIT: In the ebb and flow of day-to-day life in the iOS SDK, I found myself in the header for UIViewController and started reading some of it. I gleaned some useful info that reminded me of this question and I decided to post it, in the event some future user stumbles upon this question and wants as much info as possible to satisfy their paranoia of a very standard practice. The little morsel is simply this, from the @interface ivar block in UIViewController.h:

UIViewController *_childModalViewController;

As opposed to these other declarations:

UIViewController *_parentViewController; // Nonretained
NSHashTable      *_childViewControllers; // Nonretained

The comments seem to explicitly state what is not retained. By virtue of a lack of comment on the modal view controller ivar declaration, it would seem it is retained.

The memory management rules of Objective-C define the behaviour, so it doesn't need to expressly document that it retains the modal view controller. If an object needs to keep a passed object around after the method has finished executing, it will retain the object unless otherwise specified.

So in this case, you should just pass the view controller to presentModalViewController:animated: and then release it (or use autorelease).

This applies everywhere in Objective-C. If an object takes another object as method input, you never have to retain that object on its behalf.

As requested in the comments, if you read Apple's documentation on memory management, then you'll find the section on Weak References, which states:

Important: In Cocoa, references to table data sources, outline view items, notification observers, and delegates are all considered weak (for example, an NSTableView object does not retain its data source and the NSApplication object does not retain its delegate). The documentation only describes exceptions to this convention.

This actually states that this is a convention in itself and that exceptions will be stated in the documentation, however, going to the documentation for NSTableView and looking at the setDataSource: method, we see:

Discussion In a managed memory environment, the receiver maintains a weak reference to the data source (that is, it does not retain the data source, see Communicating With Objects). After setting the data source, this method invokes tile.

This method raises an NSInternalInconsistencyException if anObject doesn’t respond to either numberOfRowsInTableView: or tableView:objectValueForTableColumn:row:.