Skip to content

Latest commit

 

History

History
77 lines (50 loc) · 5.03 KB

2013-01-28-nsvalue.md

File metadata and controls

77 lines (50 loc) · 5.03 KB
title author category tags excerpt
NSValue
Mattt Thompson
Cocoa
nshipster
Boxing is the process of encapsulating scalars and value types with an object container, and is primarily used to store those values in collection objects—namely arrays and dictionaries. In Foundation, the reigning featherweight champion of boxing is NSValue.

As part of playing the role of Abraham Lincoln in the eponymous 2012 biopic, Daniel Day-Lewis would insist on walking through a refrigerator box marked "TIME MACHINE" anytime he entered or left the set. True Story.

While the ends certainly justify the means when it comes to Mr. Day-Lewis' method acting, one can't help but marvel at the absurdity of a magical cardboard box used as a nexus between the modern and historical worlds.

Yet, this is exactly what we do as Objective-C programmers.

...well not exactly, but there is a box involved.

As mentioned time and again in NSHipster, what makes Objective-C such a curiosity is the way it merges the old, procedural world of C with the modern Object-Oriented influences of Smalltalk. When done correctly, this tension can be exploited to craft semantically rich software without sacrificing performance. But bridging that gap between old and new is a miasma of casts, bridges, and of course, boxes.

Boxing is the process of encapsulating scalars (int, double, BOOL, etc.) and value types (struct, enum) with an object container, and is primarily used to store those values in collection objects—namely arrays and dictionaries.

NSNumber is often used to box scalars, but in Foundation, the reigning featherweight champion of boxing is NSValue.


NSValue is a simple container for a single C or Objective-C data value. It can hold scalars and value types, as well as pointers and object IDs.

While boxing is an admittedly dry subject matter, there are two methods in particular that are worth noting: +valueWithBytes:objCType:, which serves as a primer for working with NSValue, and +valueWithNonretainedObject:, which is surprisingly useful for being relatively unknown.

valueWithBytes:objCType:

+valueWithBytes:objCType: Creates and returns an NSValue object that contains a given value, which is interpreted as being of a given Objective-C type.

  • value: The value for the new NSValue object.
  • type: The Objective-C type of value. type should be created with the Objective-C @encode() compiler directive; it should not be hard-coded as a C string.

@encode was discussed in our rundown of the myriad @ Compiler Directives:

@encode(): Returns the type encoding of a type. This type value can be used as the first argument encode in NSCoder -encodeValueOfObjCType:at.

The subject of type encodings would make for a great article of its own, but the main takeaway is that it serves as a terse, human-readable representation of the structure of a type. For example,

typedef struct example {
  id   anObject;
  char *aString;
  int  anInt;
} Example;

...has the encoding:

{example=@*i}

NSValue uses this type encoding to create the necessary data structures to represent these values internally. Neat!

valueWithNonretainedObject:

+valueWithNonretainedObject: Creates and returns an NSValue object that contains a given object.

anObject: The value for the new object.

If you already knew about valueWithNonretainedObject, you should be nodding with a knowing grin. If you didn't, you're likely staring incredulously with mouth agape. Or if not, you will be soon.

In short, valueWithNonretainedObject: allows objects to be added to a collection, without the need for satisfying <NSCopying>.

It's something that comes up occasionally, working with objects that can't be directly added to an NSArray or NSDictionary. Without knowing about valueWithNonretainedObject:, this would be something that would throw off your entire game—especially if you're just starting out in Objective-C.

But now you're in the know. You won't be stifled by such pedestrian concerns. You need not grope around for answers with NSPointerArray or NSMapTable. Today is a new day.


Having unpacked all of this wisdom about NSValue, you can now face that cruel divide between procedural and object-oriented; C and Smalltalk. Because everything is easy with a magic box.