Quantcast
Channel: NSHipster
Viewing all 382 articles
Browse latest View live

NSOrderedSet

$
0
0

Here’s a question: why isn’t NSOrderedSet a subclass of NSSet?

It seems perfectly logical, after all, for NSOrderedSet–a class that enforces the same uniqueness constraint of NSSet–to be a subclass of NSSet. It has the same methods as NSSet, with the addition of some NSArray-style methods like objectAtIndex:. By all accounts, it would seem to perfectly satisfy the requirements of the Liskov substitution principle, that:

If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.

So why is NSOrderedSet a subclass of NSObject and not NSSet or even NSArray?

Mutable / Immutable Class Clusters

Class Clusters are a design pattern at the heart of the Foundation framework; the essence of Objective-C’s simplicity in everyday use.

But class clusters offer simplicity at the expense of extensibility, which becomes especially tricky when it comes to mutable / immutable class pairs like NSSet / NSMutableSet.

As expertly demonstrated by Tom Dalling in this Stack Overflow question, the method -mutableCopy creates an inconsistency that is inherent to Objective-C’s constraint on single inheritance.

To start, let’s look at how -mutableCopy is supposed to work in a class cluster:

NSSet* immutable = [NSSet set];
NSMutableSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES

Now let’s suppose that NSOrderedSet was indeed a subclass of NSSet:

// @interface NSOrderedSet : NSSet

NSOrderedSet* immutable = [NSOrderedSet orderedSet];
NSMutableOrderedSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // NO (!)

That’s no good… since NSMutableOrderedSet couldn’t be used as a method parameter of type NSMutableSet. So what happens if we make NSMutableOrderedSet a subclass of NSMutableSet as well?

// @interface NSOrderedSet : NSSet
// @interface NSMutableOrderedSet : NSMutableSet

NSOrderedSet* immutable = [NSOrderedSet orderedSet];
NSMutableOrderedSet* mutable = [immutable mutableCopy];

[mutable isKindOfClass:[NSSet class]]; // YES
[mutable isKindOfClass:[NSMutableSet class]]; // YES
[mutable isKindOfClass:[NSOrderedSet class]]; // NO (!)

This is perhaps even worse, as now NSMutableOrderedSet couldn’t be used as a method parameter expecting an NSOrderedSet.

No matter how we approach it, we can’t stack a mutable / immutable class pair on top of another existing mutable / immutable class pair. It just won’t work in Objective-C.

Rather than subject ourselves to the perils of multiple inheritance, we could use Protocols to get us out of this pickle (as it does every other time the spectre of multiple inheritance is raised). Indeed, Foundation’s collection classes could become more aspect-oriented by adding protocols:

  • NSArray : NSObject <NSOrderedCollection>
  • NSSet : NSObject <NSUniqueCollection>
  • NSOrderedSet : NSObject <NSOrderedCollection, NSUniqueCollection>

However, to reap any benefit from this arrangement, all of the existing APIs would have to be restructured to have parameters accept id <NSOrderedCollection> instead of NSArray. But the transition would be painful, and would likely open up a whole can of edge cases… which would mean that it would never be fully adopted… which would mean that there’s less incentive to adopt this approach when defining your own APIs… which are less fun to write because there’s now two incompatible ways to do something instead of one… which…

…wait, why would we use NSOrderedSet in the first place, anyway?


NSOrderedSet was introduced in iOS 5 & Mac OS X 10.7. The only APIs changed to add support for NSOrderedSet, though, were part of Core Data.

This was fantastic news for anyone using Core Data at the time, as it solved one of the long-standing annoyances of not having a way to arbitrarily order relationship collections. Previously, you’d have to add a position attribute, which would be re-calculated every time a collection was modified. There wasn’t a built-in way to validate that your collection positions were unique or that the sequence didn’t have any gaps.

In this way, NSOrderedSet is an answer to our prayers.

Unfortunately, its very existence in Foundation has created something between an attractive nuisance and a red herring for API designers.

Although it is perfectly suited to that one particular use case in Core Data, NSOrderedSet is probably not a great choice for the majority of APIs that could potentially use it. In cases where a simple collection of objects is passed as a parameter, a simple NSArray does the trick–even if there is an implicit understanding that you shouldn’t have duplicate entries. This is even more the case when order matters for a collection parameter–just use NSArray (there should be code to deal with duplicates in the implementation anyway). If uniqueness does matter, or the semantics of sets makes sense for a particular method, NSSet has and remains a great choice.


So, as a general rule: NSOrderedSet is useful for intermediary and internal representations, but you probably shouldn’t introduce it as a method parameters unless it’s particularly well-suited to the semantics of the data model.

If nothing else, NSOrderedSet illuminates some of the fascinating implications of Foundation’s use of the class cluster design pattern. In doing so, it allows us better understand the trade-off between simplicity and extensibility as we make these choices in our own application designs.


KVC Collection Operators

$
0
0

Rubyists laugh at Objective-C’s bloated syntax.

Although we lost a few pounds over the summer with our sleek new object literals, those Red-headed bullies still taunt us with their map one-liners and their fancy Symbol#to_proc.

Really, a lot of how elegant (or clever) a language is comes down to how well it avoids loops. for, while; even fast enumeration expressions are a drag. No matter how you sugar-coat them, loops will be a block of code that does something that is much simpler to describe in natural language.

“get me the average salary of all of the employees in this array”, versus…

double totalSalary = 0.0;
for (Employee *employee in employees) {
  totalSalary += [employee.salary doubleValue];
}
double averageSalary = totalSalary / [employees count];

Meh.

Fortunately, Key-Value Coding gives us a much more concise–almost Ruby-like–way to do this:

[employees valueForKeyPath:@"@avg.salary"];

KVC Collection Operators allows actions to be performed on a collection using key path notation in valueForKeyPath:. Any time you see @ in a key path, it denotes a particular aggregate function whose result can be returned or chained, just like any other key path.

Collection Operators fall into one of three different categories, according to the kind of value they return:

  • Simple Collection Operators return strings, numbers, or dates, depending on the operator.
  • Object Operators return an array.
  • Array and Set Operators return an array or set, depending on the operator.

The best way to understand how these work is to see them in action. Consider a Product class, and a products array with the following data:

@interface Product : NSObject
@property NSString *name;
@property double price;
@property NSDate *launchedOn;
@end

Key-Value Coding automatically boxes and un-boxes scalars into NSNumber or NSValue as necessary to make everything work.

NamePriceLaunch Date
iPhone 5$199September 21, 2012
iPad Mini$329November 2, 2012
MacBook Pro$1699June 11, 2012
iMac$1299November 2, 2012

Simple Collection Operators

  • @count: Returns the number of objects in the collection as an NSNumber.
  • @sum: Converts each object in the collection to a double, computes the sum, and returns the sum as an NSNumber.
  • @avg: Takes the double value of each object in the collection, and returns the average value as an NSNumber.
  • @max: Determines the maximum value using compare:. Objects must support comparison with one another for this to work.
  • @min: Same as @max, but returns the minimum value in the collection.

Example:

[products valueForKeyPath:@"@count"]; // 4
[products valueForKeyPath:@"@sum.price"]; // 3526.00
[products valueForKeyPath:@"@avg.price"]; // 881.50
[products valueForKeyPath:@"@max.price"]; // 1699.00
[products valueForKeyPath:@"@min.launchedOn"]; // June 11, 2012

Pro Tip: To get the aggregate value of an array or set of NSNumbers, you can simply pass self as the key path after the operator, e.g. [@[@(1), @(2), @(3)] valueForKeyPath:@"@max.self"] (/via @davandermobile, citing Objective Sea)

Object Operators

Let’s say we have an inventory array, representing the current stock of our local Apple store (which is running low on iPad Mini, and doesn’t have the new iMac, which hasn’t shipped yet):

NSArray *inventory = @[iPhone5, iPhone5, iPhone5, iPadMini, macBookPro, macBookPro];
  • @unionOfObjects / @distinctUnionOfObjects: Returns an array of the objects in the property specified in the key path to the right of the operator. @distinctUnionOfObjects removes duplicates, whereas @unionOfObjects does not.

Example:

[inventory valueForKeyPath:@"@unionOfObjects.name"]; // "iPhone 5", "iPhone 5", "iPhone 5", "iPad Mini", "MacBook Pro", "MacBook Pro"
[inventory valueForKeyPath:@"@distinctUnionOfObjects.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"

Array and Set Operators

Array and Set Operators are similar to Object Operators, but they work on collections of NSArray and NSSet.

This would be useful if we were to, for example, compare the inventory of several stores, say appleStoreInventory, (same as in the previous example) and verizonStoreInventory (which sells iPhone 5 and iPad Mini, and has both in stock).

  • @distinctUnionOfArrays / @unionOfArrays: Returns an array containing the combined values of each array in the collection, as specified by the key path to the right of the operator. As you’d expect, the distinct version removes duplicate values.
  • @distinctUnionOfSets: Similar to @distinctUnionOfArrays, but it expects an NSSet containing NSSet objects, and returns an NSSet. Because sets can’t contain duplicate values anyway, there is only the distinct operator.

Example:

[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"  

This is Probably a Terrible Idea

Curiously, Apple’s documentation on KVC collection operators goes out of its way to make the following point:

Note: It is not currently possible to define your own collection operators.

This makes sense to spell out, since that’s what most people are thinking about once they see collection operators for the first time.

However, as it turns out, it is actually possible, with a little help from our friend, objc/runtime.

Guy English has a pretty amazing post wherein he swizzles valueForKeyPath: to parse a custom-defined DSL, which extends the existing offerings to interesting effect:

NSArray *names = [allEmployees valueForKeyPath: @"[collect].{daysOff<10}.name"];

This code would get the names of anyone who has taken fewer than 10 days off (to remind them to take a vacation, no doubt!).

Or, taken to a ridiculous extreme:

NSArray *albumCovers = [records valueForKeyPath:@"[collect].{artist like 'Bon Iver'}.<NSUnarchiveFromDataTransformerName>.albumCoverImageData"];

Eat your heart out, Ruby. This one-liner filters a record collection for artists whose name matches “Bon Iver”, and initializes an NSImage from the album cover image data of the matching albums.

Is this a good idea? Probably not. (NSPredicate is rad, and breaking complicated logic up is under-rated)

Is this insanely cool? You bet! This clever example has shown a possible direction for future Objective-C DSLs and meta-programming.


KVC Collection Operators are a must-know for anyone who wants to save a few extra lines of code and look cool in the process.

While scripting languages like Ruby boast considerably more flexibility in its one-liner capability, perhaps we should take a moment to celebrate the restraint built into Objective-C and Collection Operators. After all, Ruby is hella slow, amiright? </troll>

instancetype

$
0
0

Want to know what’s coming next in Objective-C? Keep your ear to the ground.

Objective-C is a rapidly evolving language, in a way that you just don’t see in established programming languages. ARC, object literals, subscripting, blocks: in the span of just three years, so much of how we program in Objective-C has been changed (for the better).

All of this innovation is a result of Apple’s philosophy of vertical integration. Just as Apple’s investment in designing its own chipsets gave them leverage to compete aggressively with their mobile hardware, so too has their investment in LLVM allowed their software to keep pace.

Clang developments range from the mundane to paradigm-changing, but telling the difference takes practice. Because we’re talking about low-level language features, it’s difficult to understand what implications they may have higher up with API design.

One such example is instancetype, the subject of this week’s article.


In Objective-C, conventions aren’t just a matter of coding best-practices, they are implicit instructions to the compiler.

For example, alloc and init both have return types of id, yet in Xcode, the compiler makes all of the correct type checks. How is this possible?

In Cocoa, there is a convention that methods with names like alloc, or init always return objects that are an instance of the receiver class. These methods are said to have a related result type.

Class constructor methods, although they similarly return id, don’t get the same type-checking benefit, because they don’t follow that naming convention.

You can try this out for yourself:

[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // ❗ "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"

[[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)

Because alloc and init follow the naming convention for being a related result type, the correct type check against NSArray is performed. However, the equivalent class constructor array does not follow that convention, and is interpreted as id.

id is useful for opting-out of type safety, but losing it when you do want it sucks.

The alternative, of explicitly declaring the return type ((NSArray *) in the previous example) is a slight improvement, but is annoying to write, and doesn’t play nicely with subclasses.

This is where the compiler steps in to resolve this timeless edge case to the Objective-C type system:

instancetype is a contextual keyword that can be used as a result type to signal that a method returns a related result type. For example:

@interface Person
+ (instancetype)personWithName:(NSString *)name;
@end

instancetype, unlike id, can only be used as the result type in a method declaration.

With instancetype, the compiler will correctly infer that the result of +personWithName: is an instance of a Person.

Look for class constructors in Foundation to start using instancetype in the near future. New APIs, such as UICollectionViewLayoutAttributes are using instancetype already.

Further Implications

Language features are particularly interesting because, again, it’s often unclear of what impact they’ll have on higher-level aspects of software design.

While instancetype may seem to be a rather mundane, albeit welcome addition to the compiler, it can be used to some rather clever ends.

Jonathan Sterling wrote this quite interesting article, detailing how instancetype could be used to encode statically-typed collections, without generics:

NSURL <MapCollection> *sites = (id)[NSURL mapCollection];
[sites put:[NSURL URLWithString:@"http://www.jonmsterling.com/"]
        at:@"jon"];
[sites put:[NSURL URLWithString:@"http://www.nshipster.com/"]
        at:@"nshipster"];

NSURL *jonsSite = [sites at:@"jon"]; // => http://www.jonmsterling.com/

Statically-typed collections would make APIs more expressive–no longer would a developer be unsure about what kinds of objects are allowed in a collection parameter.

Whether or not this becomes an accepted convention in Objective-C, it’s fascinating to how a low-level feature like instancetype can be used to change shape of the language (in this case, making it look more like C#.


instancetype is just one of the many language extensions to Objective-C, with more being added with each new release.

Know it, love it.

And take it as an example of how paying attention to the low-level details can give you insights into powerful new ways to transform Objective-C.

CGGeometry

$
0
0

Unless you were a Math Geek or an Ancient Greek, Geometry was probably not your favorite subject in high school. No, chances are that you were that kid in class who dutifully programmed all of the necessary formulæ into your TI-8X calculator.

So for those of you who spent more time learning TI-BASIC than Euclidean geometry, here’s the cheat-sheet for how geometry works in Quartz 2D, the drawing system used in iOS and Mac OS X:

  • A CGPoint is a struct that represents a point in a two-dimensional coordinate system. For iOS, the origin is at the top-left, so points move right and down as their x and y values, respectively, increase. OS X, by contrast, is oriented with (0, 0) in the bottom left, with y moving up as it increases.

  • A CGSize is a struct that represents the dimensions of width and height.

  • A CGRect is a struct with both a CGPoint (origin) and a CGSize (size), representing a rectangle drawn from its origin point with the width and height of its size.

Because CGRect is used to represent the frame of every view drawn on screen, a programmer’s success in graphical programming is contingent on their ability to effectively manipulate rectangle geometry.

Fortunately for us, Quartz comes with a slew of useful functions to reduce the amount of floating point math we have to do ourselves. As central as view programming is to Cocoa, and as useful as these functions are, however, they remain relatively unknown to most iOS developers.

This will not stand! Let’s shine some light on the most useful functions and save y’all some typing!


Transformations

First on our list are the geometric transformations. These functions return a CGRect, which is the result of performing a particular set of operations on the passed rectangle.

CGRectOffset

CGRectOffset: Returns a rectangle with an origin that is offset from that of the source rectangle.

CGRect CGRectOffset(
  CGRect rect,
  CGFloat dx,
  CGFloat dy
)

Consider using this anytime you’re changing the origin of a rectangle. Not only can it save a line of code when changing both the horizontal and vertical position, but more importantly, it represents the translation more semantically than manipulating the origin values individually.

CGRectInset

CGRectInset: Returns a rectangle that is smaller or larger than the source rectangle, with the same center point.

CGRect CGRectInset(
  CGRect rect,
  CGFloat dx,
  CGFloat dy
)

Want to make a view-within-a-view look good? Give it a nice 10pt padding with CGRectInset. Keep in mind that the rectangle will be resized around its center by ± dx on its left and right edge (for a total of 2 × dx), and ± dy on its top and bottom edge (for a total of 2 × dy).

If you’re using CGRectInset as a convenience function for resizing a rectangle, it is common to chain this with CGRectOffset by passing the result of CGRectInset as the rect argument in CGRectOffset.

CGRectIntegral

CGRectIntegral: Returns the smallest rectangle that results from converting the source rectangle values to integers.

CGRect CGRectIntegral (
  CGRect rect
)

It’s important that CGRect values all are rounded to the nearest whole point. Fractional values cause the frame to be drawn on a pixel boundary. Because pixels are atomic units (cannot be subdivided†) a fractional value will cause the drawing to be averaged over the neighboring pixels, which looks blurry.

CGRectIntegral will floor each origin value, and ceil each size value, which will ensure that your drawing code will crisply align on pixel boundaries.

As a rule of thumb, if you are performing any operations that could result in fractional point values (e.g. division, CGGetMid[X|Y], or CGRectDivide), use CGRectIntegral to normalize rectangles to be set as a view frame.

† Technically, since the coordinate system operates in terms of points, Retina screens, which have 4 pixels for every point, can draw ± 0.5f point values on odd pixels without blurriness.

Value Helper Functions

These functions provide a shorthand way to calculate interesting dimensional values about a particular CGRect.

CGRectGet[Min|Mid|Max][X|Y]

  • CGRectGetMinX

  • CGRectGetMinY

  • CGRectGetMidX

  • CGRectGetMidY

  • CGRectGetMaxX

  • CGRectGetMaxY

These six functions return the minimum, middle, or maximum x or y value for a rectangle, taking the form:

CGFloat CGRectGet[Min|Mid|Max][X|Y] (
  CGRect rect
)

These functions will replace code like frame.origin.x + frame.size.width with cleaner, more semantically expressive equivalents (especially with the mid and max functions).

CGRectGet[Width|Height]

CGRectGetHeight: Returns the height of a rectangle.

CGFloat CGRectGetHeight (
   CGRect rect
)

CGRectGetWidth: Returns the width of a rectangle.

CGFloat CGRectGetWidth (
   CGRect rect
)

Much like the previous functions, CGRectGetWidth& CGRectGetHeight are often preferable to returning the corresponding member of a CGRect’s size. While it’s not extremely competitive in terms of character savings, remember that semantic clarity trumps brevity every time.

Identities

There are three special rectangle values, each of which have unique properties that are important to know about:

CGRectZero, CGRectNull, & CGRectInfinite

  • const CGRect CGRectZero: A rectangle constant with location (0,0), and width and height of 0. The zero rectangle is equivalent to CGRectMake(0.0f, 0.0f, 0.0f, 0.0f).
  • const CGRect CGRectNull: The null rectangle. This is the rectangle returned when, for example, you intersect two disjoint rectangles. Note that the null rectangle is not the same as the zero rectangle.
  • const CGRect CGRectInfinite: A rectangle that has infinite extent.

CGRectZero is perhaps the most useful of all of the special rectangle values. When initializing subviews, their frames are often initialized to CGRectZero, deferring their layout to -layoutSubviews.

CGRectNull is distinct from CGRectZero, despite any implied correspondence to NULL == 0. This value is conceptually similar to NSNotFound, in that it represents the absence of an expected value. Be aware of what functions can return CGRectNull, and be prepared to handle it accordingly, by testing with CGRectIsNull.

CGRectInfinite is the most exotic of all, and has some of the most interesting properties. It intersects with all points and rectangles, contains all rectangles, and its union with any rectangle is itself. Use CGRectIsInfinite to check to see if a rectangle is infinite.

And Finally…

Behold, the most obscure, misunderstood, and useful of the CGGeometry functions: CGRectDivide.

CGRectDivide

CGRectDivide: Divides a source rectangle into two component rectangles.

void CGRectDivide(
  CGRect rect,
  CGRect *slice,
  CGRect *remainder,
  CGFloat amount,
  CGRectEdge edge
)

CGRectDivide divides a rectangle into two components in the following way:

  • Take a rectangle and choose an edge (left, right, top, or bottom).
  • Measure out an amount from that edge.
  • Everything from the edge to the measured amount is stored in the rectangle referenced in the slice argument.
  • The rest of the original rectangle is stored in the remainder out argument.

That edge argument takes a value from the CGRectEdge enum:

enum CGRectEdge {
   CGRectMinXEdge,
   CGRectMinYEdge,
   CGRectMaxXEdge,
   CGRectMaxYEdge
}

CGRectDivide is perfect for dividing up available space among several views (call it on subsequent remainder amounts to accommodate more than two views). Give it a try next time you’re manually laying-out a UITableViewCell.


So what if you didn’t pay attention in Geometry class–this is the real world, and in the real world, you have CGGeometry.h

Know it well, and you’ll be on your way to discovering great new user interfaces in your apps. Do good enough of a job with that, and you may run into the greatest arithmetic problem of all: adding up all of the money you’ll make with your awesome new app. Mathematical!

Reader Submissions - New Year's 2013

$
0
0

In celebration of the forthcoming year++, I thought it’d be fun to compile a list of some of your favorite tips and tricks of the trade–to give y’all a chance to show off some of your NSHipster cred.

Thanks to Cédric Luthi, Jason Kozemczak, Jeff Kelley, Joel Parsons, Maximilian Tagher, Rob Mayoff, Vadim Shpakovski, & @alextud for answering the call with excellent submissions.


Associated Objects in Categories

This first tip is so nice it was mentioned twice, both by Jason Kozemczak& Jeff Kelley.

Categories are a well-known feature of Objective-C, allowing new methods to be added to existing classes. Much less well known is that with some objc runtime hacking, you can add new properties as well. Observe!

NSObject+IndieBandName.h

@interface NSObject (IndieBandName)
@property (nonatomic, strong) NSString *indieBandName;
@end

NSObject+IndieBandName.m

#import "NSObject+Extension.h"
#import <objc/runtime.h>

static char const * const IndieBandNameKey = "IndieBandName";    

@implementation NSObject (IndieBandName)
@dynamic indieBandName;

- (NSString *)indieBandName {
    return objc_getAssociatedObject(self, IndieBandNameKey);
}

- (void)setIndieBandName:(NSString *)indieBandName {
    objc_setAssociatedObject(self, IndieBandNameKey, indieBandName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

This way, all of your objects can store and retrieve the name of their band, which–by the way–is performing this Wednesday night, and you should totally come.

While this is a cool trick and all, it should only be used as a method of last resort. Before you go this route, ask yourself if a particular property can’t either be derived from existing values, or should be managed by another class.

A good example of an associated object is how AFNetworking adds a property for an image request operation in its UIImageView category.

LLDB View Hierarchy Dump

Rob Mayoff responded with an obscure and powerful incantation to make debugging views a delight. Create .lldbinit in your home directory, if it doesn’t already exist, and add the following:

~/.lldbinit

command regex rd 's/^[[:space:]]*$/po [[UIApp keyWindow] recursiveDescription]/' 's/^(.+)$/po [%1 recursiveDescription]/'

Now you can get a recursive hierarchy of any view in your iOS application with the LLDB debugger. You can try this for yourself by setting a breakpoint in a view controller, and type rd self.view. You may be surprised by what’s under the hood with some of the built-in UI controls!

LLDB Print Contents of a CGPathRef

While we’re on the subject of LLDB, Rob Mayoff sent in a useful incantation for printing out the contents of a CGPathRef from the debugger:

p (void)CGPathPrint(pathRef, 0)

If you’re doing any kind of complex Core Graphics drawing, be sure to keep this one handy.

Use +initialize, Not +load

Vadim Shpakovski wrote in with some advice about class loading and initialization. There are two magical class methods in Objective-C: +load and +initialize, which are automatically called by virtue of the class being used. The difference between the two methods, however, has significant performance implications for your application.

Mike Ash has a great explanation of this:

+load is invoked as the class is actually loaded, if it implements the method. This happens very early on. If you implement +load in an application or in a framework that an application links to, +load will run before main(). If you implement +load in a loadable bundle, then it runs during the bundle loading process.

The +initialize method is invoked in a more sane environment and is usually a better place to put code than +load. +initialize is interesting because it’s invoked lazily and may not be invoked at all. When a class first loads, +initialize is not called. When a message is sent to a class, the runtime first checks to see if +initialize has been called yet. If not, it calls it before proceeding with the message send.

tl;dr: Implement +initialize, not +load, if you need this automatic behavior.

+initialize is great for registering NSURLProtocol, NSValueTransformer, and NSIncrementalStore subclasses, or any class that requires some kind of extra initialization step before being used.

Xcode Snippets

Maximilian Tagher gave a shout-out to the benefits of Xcode Snippets.

Great developers take pride in knowing their tools, and being able to use them to maximum effect. For better or for worse, this means knowing Xcode like the back of our hand. Verbose as Objective-C is, “do more by typing less” rings especially true as a productivity mantra, and Xcode Snippets are one of the best ways to do this.

If you’re looking for a place to start, try downloading and forking these Xcode Snippets.

Macro for Measuring Execution Time

Here’s a helpful macro for easily measuring the elapsed time for executing a particular block of code, sent in from @alextud:

NS_INLINE void MVComputeTimeWithNameAndBlock(const char *caller, void (^block)()) {
    CFTimeInterval startTimeInterval = CACurrentMediaTime();
    block();
    CFTimeInterval nowTimeInterval = CACurrentMediaTime();
    NSLog(@"%s - Time Running is: %f", caller, nowTimeInterval - startTimeInterval);
}

#define MVComputeTime(...) MVComputeTimeWithNameAndBlock(__PRETTY_FUNCTION__, (__VA_ARGS__))

Block Enumeration Methods

Joel Parsons submitted a great tip about using -enumerateObjectsWithOptions:usingBlock: in NSArray and other collection classes. By passing the NSEnumerationConcurrent option, you can get significant performance benefits over NSFastEnumeration’s for...in-style enumeration by executing the block concurrently.

However, be warned! Not all enumerations lend themselves to concurrent execution, so don’t go around replacing all of your for...in blocks with NSEnumerationConcurrent willy-nilly, unless random crashing is something you like in an app.

Reverse-Engineered Implementation of NSString Equality Methods

Displaying his characteristic brilliance and familiarity of Cocoa internals Cédric Luthi submitted a reverse-engineered implementation of the NString equality methods. Fascinating!

Animate NSLayoutConstraint.constant

This one goes out to all you fans of Cocoa Auto Layout, from Vadim Shpakovski:

viewConstraint.constant = <#Constant Value From#>;
[view layoutIfNeeded];

viewConstraint.constant = <#Constant Value To#>;
[view setNeedsUpdateConstraints];

[UIView animateWithDuration:ConstantAnimationDuration animations:^{
     [view layoutIfNeeded];
}];

Attentive readers may have already noted this, but the code above would make an excellent Xcode Snippet, by the way.

Printing NSCache Usage

Finishing up this batch of tips and tricks is Cédric Luthi again, this time unearthing the private method cache_print as a way to get some visibility into NSCache:

extern void cache_print(void *cache);

- (void) printCache:(NSCache *)cache {
    cache_print(*((void **)(__bridge void *)cache + 3));
}

This code sample has only been tested on iOS, and should only be used for debugging (i.e. take this out before submitting to Apple!).


Thanks again to everyone for their submissions this time around. We’ll definitely be doing this again, so feel free to send your favorite piece of Objective-C trivia, framework arcana, hidden Xcode feature, or anything else you think is cool to @NSHipster!

And thank you, dear reader, for your support of NSHipster over these last wonderful months. We have a lot of insanely great things planned for NSHipster in 2013, and we look forward to being able to share it all with all of you.

nil / Nil / NULL / NSNull

$
0
0

Understanding the concept of nothingness is as much a philosophical issue as it is a pragmatic one. We are inhabitants of a universe of somethings, yet reason in a logical universe of existential uncertainties. As a physical manifestation of a logical system, computers are faced with the intractable problem of how to represent nothing with something.

In Objective-C, there are several different varieties of nothing. The reason for this goes back to a common NSHipster refrain, of how Objective-C bridges the procedural paradigm of C with Smalltalk-inspired object-oriented paradigm.

C represents nothing as 0 for primitive values, and NULL for pointers (which is equivalent to 0 in a pointer context).

Objective-C builds on C's representation of nothing by adding nil. nil is an object pointer to nothing. Although semantically distinct from NULL, they are technically equivalent to one another.

On the framework level, Foundation defines NSNull, which defines a class method, +null, which returns the singleton NSNull object. NSNull is different from nil or NULL, in that it is an actual object, rather than a zero value.

Additionally, in Foundation/NSObjCRuntime.h, Nil is defined as a class pointer to nothing. This lesser-known title-case cousin of nil doesn't show up much very often, but it's at least worth noting.

There's Something About nil

Newly-alloc'd NSObjects start life with their contents set to 0. This means that all pointers that object has to other objects begin as nil, so it's unnecessary to, for instance, set self.(association) = nil in init methods.

Perhaps the most notable behavior of nil, though, is that it can have messages sent to it.

In other languages, like C++, this would crash your program, but in Objective-C, invoking a method on nil returns a zero value. This greatly simplifies expressions, as it obviates the need to check for nil before doing anything:

// For example, this expression...if(name!=nil&&[nameisEqualToString:@"Steve"]){...}// ...can be simplified to:if([nameisEqualToString:@"steve"]){...}

Being aware of how nil works in Objective-C allows this convenience to be a feature, and not a lurking bug in your application. Make sure to guard against cases where nil values are unwanted, either by checking and returning early to fail silently, or adding a NSParameterAssert to throw an exception.

NSNull: Something for Nothing

NSNull is used throughout Foundation and other frameworks to skirt around the limitations of collections like NSArray and NSDictionary not being able to contain nil values. You can think of NSNull as effectively boxing the NULL or nil value so that it can be used in collections:

NSMutableDictionary*mutableDictionary=[NSMutableDictionarydictionary];mutableDictionary[@"someKey"]=[NSNullnull];// Sets value of NSNull singleton for `someKey`NSLog(@"Keys: %@",[mutableDictionaryallKeys]);// @[@"someKey"]

So to recap, here are the four values representing nothing that every Objective-C programmer should know about:

SymbolValueMeaning
NULL(void *)0literal null value for C pointers
nil(id)0literal null value for Objective-C objects
Nil(Class)0literal null value for Objective-C classes
NSNull[NSNull null]singleton object used to represent null

__attribute__

$
0
0

A recurring theme of this publication has been the importance of a healthy relationship with the compiler. Like any craft, one's effectiveness as a practitioner is contingent on how they treat their tools. Take good care of them, and they'll take good care of you.

__attribute__ is a compiler directive that specifies characteristics on declarations, which allows for more error checking and advanced optimizations.

The syntax for this keyword is __attribute__ followed by two sets of parentheses (the double parentheses makes it easy to "macro out", especially with multiple attributes). Inside the parentheses is a comma-delimited list of attributes. __attribute__ directives are placed after function, variable, and type declarations.

// Return the square of a numberintsquare(intn)__attribute__((const));// Declare the availability of a particular APIvoidf(void)__attribute__((availability(macosx,introduced=10.4,deprecated=10.6)));// Send printf-like message to stderr and exitexternvoiddie(constchar*format,...)__attribute__((noreturn,format(printf,1,2)));

If this is starting to remind you of ISO C's #pragma, you're not alone.

In fact, when __attribute__ was first introduced to GCC, it was faced with some resistance by some who suggested that #pragma be used exclusively for the same purposes.

There are, however, two very good reasons why __attribute__ exists:

  1. It is impossible to generate #pragma commands from a macro.
  2. There is no telling what the same #pragma might mean in another compiler.

Quoth the GCC Documentation for Function Attributes:

These two reasons applied to almost any application that might have been proposed for #pragma. It was basically a mistake to use #pragma for anything.

Indeed, if you look at modern Objective-C--in the headers of Apple frameworks and well-engineered open-source projects--__attribute__ is used for myriad purposes. (By contrast, #pragma's main claim to fame these days is decoration: #pragma mark)

So without further ado, let's take a look at the most important attributes:


GCC

format

The format attribute specifies that a function takes printf, scanf, strftime or strfmon style arguments which should be type-checked against a format string.

externintmy_printf(void*my_object,constchar*my_format,...)__attribute__((format(printf,2,3)));

Objective-C programmers can also use the __NSString__ format to enforce the same rules as format strings in NSString +stringWithFormat: and NSLog().

nonnull

The nonnull attribute specifies that some function parameters should be non-null pointers.

externvoid*my_memcpy(void*dest,constvoid*src,size_tlen)__attribute__((nonnull(1,2)));

Using nonnull encodes expectations about values into an explicit contract, which can help catch any NULL pointer bugs lurking in any calling code. Remember: compile-time errors ≫ run-time errors.

noreturn

A few standard library functions, such as abort and exit, cannot return. GCC knows this automatically. The noreturn attribute specifies this for any other function that never returns.

For example, AFNetworking uses the noreturn attribute for its network request thread entry point method. This method is used when spawning the dedicated network NSThread to ensure that the detached thread continues execution for the lifetime of the application.

pure / const

The pure attribute specifies that a function has no effects except the return value, such that their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be.

The const attribute specifies that a function does not examine any values except their arguments, and have no effects except the return value. Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void.

intsquare(intn)__attribute__((const));

pure and const are both attributes that invoke a functional programming paradigm in order to allow for significant performance optimizations. const can be thought as a stricter form of pure since it doesn't depend on global values or pointers.

For example, because the result of a function declared const does not depend on anything other than the arguments passed in, the result of the function can cache that result and return any time the function is called with that same combination of arguments. (i.e. we know that the square of a number is constant, so we only need to compute it once).

unused

This attribute, attached to a function, means that the function is meant to be possibly unused. GCC will not produce a warning for this function.

The same effect can be accomplished with the __unused keyword. Declare this on parameters that are not used in the method implementation. Knowing that little bit of context allows the compiler to make optimizations accordingly. You're most likely to use __unused in delegate method implementations, since protocols frequently provide more context than is often necessary, in order to satisfy a large number of potential use cases.

LLVM

Like many features of GCC, Clang supports __attribute__, adding its own small set of extensions.

To check the availability of a particular attribute, you can use the __has_attribute directive.

availability

Clang introduces the availability attribute, which can be placed on declarations to describe the lifecycle of that declaration relative to operating system versions. Consider the function declaration for a hypothetical function f:

voidf(void)__attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7)));

The availability attribute states that f was introduced in Mac OS X 10.4, deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7.

This information is used by Clang to determine when it is safe to use f: for example, if Clang is instructed to compile code for Mac OS X 10.5, a call to f() succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call succeeds but Clang emits a warning specifying that the function is deprecated. Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call fails because f() is no longer available.

The availability attribute is a comma-separated list starting with the platform name and then including clauses specifying important milestones in the declaration's lifetime (in any order) along with additional information.

  • introduced: The first version in which this declaration was introduced.
  • deprecated: The first version in which this declaration was deprecated, meaning that users should migrate away from this API.
  • obsoleted: The first version in which this declaration was obsoleted, meaning that it was removed completely and can no longer be used.
  • unavailable: This declaration is never available on this platform.
  • message Additional message text that Clang will provide when emitting a warning or error about use of a deprecated or obsoleted declaration. Useful to direct users to replacement APIs.

Multiple availability attributes can be placed on a declaration, which may correspond to different platforms. Only the availability attribute with the platform corresponding to the target platform will be used; any others will be ignored. If no availability attribute specifies availability for the current target platform, the availability attributes are ignored.

Supported Platforms:

  • ios: Apple’s iOS operating system. The minimum deployment target is specified by the -mios-version-min=*version* or -miphoneos-version-min=*version* command-line arguments.
  • macosx: Apple’s Mac OS X operating system. The minimum deployment target is specified by the -mmacosx-version-min=*version* command-line argument.

overloadable

Clang provides support for C++ function overloading in C. Function overloading in C is introduced using the overloadable attribute. For example, one might provide several overloaded versions of a tgsin function that invokes the appropriate standard function computing the sine of a value with float, double, or long double precision:

#include <math.h>float__attribute__((overloadable))tgsin(floatx){returnsinf(x);}double__attribute__((overloadable))tgsin(doublex){returnsin(x);}longdouble__attribute__((overloadable))tgsin(longdoublex){returnsinl(x);}

Note that overloadable only works for functions. You can overload method declarations to some extent by using generic return and parameter types, like id and void *.


Context is king when it comes to compiler optimizations. By providing constraints on how to interpret your code, you're increases the chance that the generated code is as efficient as possible. Meet your compiler half-way, and you'll always be rewarded.

And __attribute__ isn't just for the compiler either: The next person to see the code will appreciate the extra context, too. So go the extra mile for the benefit of your collaborator, successor, or just 2-years-from-now-(and-you've-forgotten-everything-about–this-code) you.

Because in the end, the love you take is equal to the love you make.

NSLocalizedString

$
0
0

Strings are perhaps the most versatile data type in computing. They're passed around as symbols, used to encode numeric values, associate values to keys, represent resource paths, store linguistic content, and format information. Having a strong handle on user-facing strings is essential to making a great user experience.

In Foundation, there is a convenient wrapper function for denoting strings as user-facing: NSLocalizedString.

NSLocalizedString provides string localization in "compile-once / run everywhere" fashion, replacing all localized strings with their respective translation according to the string tables of the user settings. But even if you're not going to localize your app to any other markets, NSLocalizedString does wonders with respect to copy writing & editing.

For more information about Localization (l10n) and Internationalization (i18n) see the NSHipster article about NSLocale.


NSLocalizedString is a Foundation function that returns a localized version of a string. It has two arguments: key, which uniquely identifies the string to be localized, and comment, a string that is used to provide sufficient context for accurate translation.

In practice, the key is often just the base translation string to be used, while comment is usually nil, unless there is an ambiguous context:

textField.placeholder=NSLocalizedString(@"Username",nil);

NSLocalizedString can also be used as a format string in NSString +stringWithFormat:. In these cases, it's important to use the comment argument to provide enough context to be properly translated.

self.title=[NSStringstringWithFormat:NSLocalizedString(@"%@'s Profile",@"{User First Name}'s Profile"),user.name];
label.text=[NSStringstringWithFormat:NSLocalizedString(@"Showing %lu of %lu items",@"Showing {number} of {total number} items"),[pagecount],[itemscount]];

NSLocalizedString& Co.

There are four varieties of NSLocalizedString, with increasing levels of control (and obscurity):

NSString*NSLocalizedString(NSString*key,NSString*comment)
NSString*NSLocalizedStringFromTable(NSString*key,NSString*tableName,NSString*comment)
NSString*NSLocalizedStringFromTableInBundle(NSString*key,NSString*tableName,NSBundle*bundle,NSString*comment)
NSString*NSLocalizedStringWithDefaultValue(NSString*key,NSString*tableName,NSBundle*bundle,NSString*value,NSString*comment)

99% of the time, NSLocalizedString will suffice. If you're working in a library or shared component, NSLocalizedStringFromTable should be used instead.

Localizable.strings

At runtime, NSLocalizedString determines the preferred language, and finds a corresponding Localizable.strings file in the app bundle. For example, if the user prefers French, the file fr.lproj/Localizable.strings will be consulted.

Here's what that looks like:

/* No comment provided by engineer. */
"Username"="nom d'utilisateur";
/* {User First Name}'s Profile */
"%@'s Profile"="%1$@ profil";

Localizable.strings files are initially generated with genstrings.

The genstrings utility generates a .strings file(s) from the C or Objective-C (.c or .m) source code file(s) given as the argument(s). A .strings file is used for localizing an application for different languages, as described under "Internationalization" in the Cocoa Developer Documentation.

genstrings goes through each of the selected source files, and for each use of NSLocalizedString, appends the key and comment into a target file. It's up to the developer to then create a copy of that file for each targeted locale and have a localizer translate it.

No Madlibs

After reading that part about localized format strings, you may be tempted to take a clever, DRY approach by creating reusable grammar templates like `@"{Noun} {Verb} {Noun}", and localizing each word individually...

DON'T. This cannot be stressed enough: don't subdivide localized strings. Context will be lost, grammatical constructions will be awkward and unidiomatic, verbs will be incorrectly conjugated, and you'll have missed the point entirely—taking great effort to make something worse than if you hadn't bothered in the first place.

Numbers, dates, and similar values are almost always safe replacements. Nouns are subject to pluralization and verb conjugation, but usually safe as direct or indirect objects.

For additional guidelines, see Localizing String Resources from Apple's Internationalization Programming guide.


NSLocalizedString is a remarkably reliable indicator of code quality. Those who care enough to take a few extra seconds to internationalize are very likely to be just as thoughtful when it comes to design and implementation.

Always wrap user-facing strings with NSLocalizedString.

Even if you don't plan to localize your app into any other languages, there is immense utility in being able to easily review all of the strings that a user will see. And if localization is in the cards, it's significantly easier to NSLocalize your strings as you go along the first time, then try to find all of them after-the-fact.


NSValue

$
0
0

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,

typedefstructexample{idanObject;char*aString;intanInt;}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.

Type Encodings

$
0
0

From number stations and numerology to hieroglyphs and hobo codes, there is something truly fascinating about finding meaning that hides in plain sight. Though hidden messages in and of themselves are rarely useful or particularly interesting, it's the thrill of the hunt that piques our deepest curiosities.

It is in this spirit that we take a look at Objective-C Type Encodings in this week's edition of NSHipster.


Last week, in a discussion about NSValue, there was mention of +valueWithBytes:objCType:, whose second parameter should be created with the Objective-C @encode() compiler directive.

@encode, one of the @ Compiler Directives, returns a C string that encodes the internal representation of a given type (e.g., @encode(int)i), similar to the ANSI C typeof operator. Apple's Objective-C runtime uses type encodings internally to help facilitate message dispatching.

Here's a rundown of all of the different Objective-C Type Encodings:

Objective-C Type Encodings
CodeMeaning
cA char
iAn int
sA short
lA longl is treated as a 32-bit quantity on 64-bit programs.
qA long long
CAn unsigned char
IAn unsigned int
SAn unsigned short
LAn unsigned long
QAn unsigned long long
fA float
dA double
BA C++ bool or a C99 _Bool
vA void
*A character string (char *)
@An object (whether statically typed or typed id)
#A class object (Class)
:A method selector (SEL)
[array type] An array
{name=type...}A structure
(name=type...)A union
bnumA bit field of num bits
^typeA pointer to type
?An unknown type (among other things, this code is used for function pointers)

Of course, charts are fine, but experimenting in code is even better:

NSLog(@"int        : %s",@encode(int));NSLog(@"float      : %s",@encode(float));NSLog(@"float *    : %s",@encode(float*));NSLog(@"char       : %s",@encode(char));NSLog(@"char *     : %s",@encode(char*));NSLog(@"BOOL       : %s",@encode(BOOL));NSLog(@"void       : %s",@encode(void));NSLog(@"void *     : %s",@encode(void*));NSLog(@"NSObject * : %s",@encode(NSObject*));NSLog(@"NSObject   : %s",@encode(NSObject));NSLog(@"[NSObject] : %s",@encode(typeof([NSObjectclass])));NSLog(@"NSError ** : %s",@encode(typeof(NSError**)));intintArray[5]={1,2,3,4,5};NSLog(@"int[]      : %s",@encode(typeof(intArray)));floatfloatArray[3]={0.1f,0.2f,0.3f};NSLog(@"float[]    : %s",@encode(typeof(floatArray)));typedefstruct_struct{shorta;longlongb;unsignedlonglongc;}Struct;NSLog(@"struct     : %s",@encode(typeof(Struct)));

Result:

int        : i
float      : f
float *    : ^f
char       : c
char *     : *
BOOL       : c
void       : v
void *     : ^v

NSObject * : @
NSObject   : #
[NSObject] : {NSObject=#}
NSError ** : ^@

int[]      : [5i]
float[]    : [3f]
struct     : {_struct=sqQ}

There are some interesting takeaways from this:

  • Whereas the standard encoding for pointers is a preceding ^, char * gets its own code: *. This makes sense conceptually, as C strings are thought to be entities in and of themselves, rather than a pointer to something else.
  • BOOL is c, rather than i, as one might expect. Reason being, char is smaller than an int, and when Objective-C was originally designed in the 80's, bits (much like the dollar) were more valuable than they are today. BOOL is specifically a signed char (even if -funsigned-char is set), to ensure a consistent type between compilers, since char could be either signed or unsigned.
  • Passing NSObject directly yields #. However, passing [NSObject class] yields a struct named NSObject with a single class field. That is, of course, the isa field, which all NSObject instances have to signify their type.

Method Encodings

As mentioned in Apple's "Objective-C Runtime Programming Guide", there are a handful of type encodings that are used internally, but cannot be returned with @encode.

These are the type qualifiers for methods declared in a protocol:

Objective-C Method Encodings
CodeMeaning
rconst
nin
Ninout
oout
Obycopy
Rbyref
Voneway

For anyone familiar with NSDistantObject, you'll doubtless recognize these as a vestige of Distributed Objects.

Although DO has fallen out of fashion in the age of iOS, it was an interprocess messaging protocol used between Cocoa applications--even running on different machines on the network. Under these constraints, there were benefits to be had from the additional context.

For example, parameters in distributed object messages were passed as proxies by default. In situations where proxying would be unnecessarily inefficient, the bycopy qualifier could be added to make sure a full copy of the object was sent. Also by default, parameters were inout, signifying that objects needed to be sent back and forth when sending the message. By specifying a parameter as in or out instead, the application could avoid the round-trip overhead.


So what do we gain from our newfound understanding of Objective-C Type Encodings?
Honestly, not that much.

But as we said from the very outset, there is wisdom in the pursuit of deciphering secret messages.

Looking at type encodings reveals details about Objective-C runtime internals, which is a noble pursuit in and of itself. Going further down the rabbit hole, and we come to the secret history of Distributed Objects, and the obscure parameter qualifiers that still linger around to this day.

NSURLCache

$
0
0

NSURLCache provides a composite in-memory and on-disk caching mechanism for URL requests to your application. As part of Foundation's URL Loading System, any request loaded through NSURLConnection will be handled by NSURLCache.

Network caching reduces the number of requests that need to be made to the server, and improve the experience of using an application offline or under slow network conditions.

When a request has finished loading its response from the server, a cached response will be saved locally. The next time the same request is made, the locally-cached response will be returned immediately, without connecting to the server. NSURLCache returns the cached response automatically and transparently.

In order to take advantage of NSURLCache, a shared URL cache must be initialized and set. This should be done in -application:didFinishLaunchingWithOptions: on iOS, or –applicationDidFinishLaunching: on Mac OS X:

-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{NSURLCache*URLCache=[[NSURLCachealloc]initWithMemoryCapacity:4*1024*1024diskCapacity:20*1024*1024diskPath:nil];[NSURLCachesetSharedURLCache:URLCache];}

Caching policies are specified in both the request (by the client) and in the response (by the server). Understanding these policies and how they relate to one another is essential to finding the optimal behavior for your application.

NSURLRequestCachePolicy

NSURLRequest has a cachePolicy property, which specifies the caching behavior of the request according to the following constants:

  • NSURLRequestUseProtocolCachePolicy: Caching logic defined in the protocol implementation is used for a particular URL load request. This is the default policy.
  • NSURLRequestReloadIgnoringLocalCacheData: Data should be loaded from the originating source. No existing cache data should be used.
  • NSURLRequestReloadIgnoringLocalAndRemoteCacheData: Not only should the local cache data be ignored, but proxies and other intermediates should be instructed to disregard their caches so far as the protocol allows.
  • NSURLRequestReturnCacheDataElseLoad: Existing cached data should be used, regardless of its age or expiration date. If there is no existing data in the cache corresponding to the request, the data is loaded from the originating source.
  • NSURLRequestReturnCacheDataDontLoad: Existing cache data should be used, regardless of its age or expiration date. If there is no existing data in the cache corresponding to the request, no attempt is made to load the data from the originating source, and the load is considered to have failed, (i.e. "offline" mode).
  • NSURLRequestReloadRevalidatingCacheData: Existing cache data may be used provided the origin source confirms its validity, otherwise the URL is loaded from the origin source.

It may not surprise you that these values are poorly understood and often confused with one another.

Adding to the confusion is the fact that NSURLRequestReloadIgnoringLocalAndRemoteCacheData and NSURLRequestReloadRevalidatingCacheDataaren't even implemented! (Link to Radar).

So here's what you actually need to know about NSURLRequestCachePolicy:

ConstantMeaning
UseProtocolCachePolicyDefault behavior
ReloadIgnoringLocalCacheDataDon't use the cache
ReloadIgnoringLocalAndRemoteCacheDataSeriously, don't use the cache
ReturnCacheDataElseLoadUse the cache (no matter how out of date), or if no cached response exists, load from the network
ReturnCacheDataDontLoadOffline mode: use the cache (no matter how out of date), but don't load from the network
ReloadRevalidatingCacheDataValidate cache against server before using

HTTP Cache Semantics

Because NSURLConnection is designed to support multiple protocols—including both FTP and HTTP/HTTPS—the URL Loading System APIs specify caching in a protocol-agnostic fashion. For the purposes of this article, caching will be explained in terms of HTTP semantics.

HTTP requests and responses use headers to communicate metadata such as character encoding, MIME type, and caching directives.

Request Cache Headers

By default, NSURLRequest will use the current time to determine whether a cached response should be returned. For more precise cache control, the following headers can be specified:

  • If-Modified-Since - This request header corresponds to the Last-Modified response header. Set the value of this to the Last-Modified value received from the last request to the same endpoint.
  • If-None-Match - This request header corresponds to the Etag response header. Use the Etag value received previously for the last request to that endpoint.

Response Cache Headers

An NSHTTPURLResponse contains a set of HTTP headers, which can include the following directives for how that response should be cached:

  • Cache-Control - This header must be present in the response from the server to enable HTTP caching by a client. The value of this header may include information like its max-age (how long to cache a response), and whether the response may be cached with public or private access, or no-cache (not at all). See the Cache-Control section of RFC 2616 for full details.

In addition to Cache-Control, a server may send additional headers that can be used to conditionally request information as needed (as mentioned in the previous section):

  • Last-Modified - The value of this header corresponds to the date and time when the requested resource was last changed. For example, if a client requests a timeline of recent photos, /photos/timeline, the Last-Modified value could be set to when the most recent photo was taken.
  • Etag - An abbreviation for "entity tag", this is an identifier that represents the contents requested resource. In practice, an Etag header value could be something like the MD5 digest of the resource properties. This is particularly useful for dynamically generated resources that may not have an obvious Last-Modified value.

NSURLConnectionDelegate

Once the server response has been received, the NSURLConnection delegate has an opportunity to specify the cached response in -connection:willCacheResponse:.

NSCachedURLResponse is a class that contains both an NSURLResponse with the cached NSData associated with the response.

In -connection:willCacheResponse:, the cachedResponse object has been automatically created from the result of the URL connection. Because there is no mutable counterpart to NSCachedURLResponse, in order to change anything about cachedResponse, a new object must be constructed, passing any modified values into –initWithResponse:data:userInfo:storagePolicy:, for instance:

-(NSCachedURLResponse*)connection:(NSURLConnection*)connectionwillCacheResponse:(NSCachedURLResponse*)cachedResponse{NSMutableDictionary*mutableUserInfo=[[cachedResponseuserInfo]mutableCopy];NSMutableData*mutableData=[[cachedResponsedata]mutableCopy];NSURLCacheStoragePolicystoragePolicy=NSURLCacheStorageAllowedInMemoryOnly;// ...return[[NSCachedURLResponsealloc]initWithResponse:[cachedResponseresponse]data:mutableDatauserInfo:mutableUserInfostoragePolicy:storagePolicy];}

If -connection:willCacheResponse: returns nil, the response will not be cached.

-(NSCachedURLResponse*)connection:(NSURLConnection*)connectionwillCacheResponse:(NSCachedURLResponse*)cachedResponse{returnnil;}

When left unimplemented, NSURLConnection will simply use the cached response that would otherwise be passed into -connection:willCacheResponse:, so unless you need to change or prevent caching, this method does not need to be implemented in the delegate.

Caveats

Just like its unrelated-but-similarly-named cohort, NSCache, NSURLCache is not without some peculiarities.

As of iOS 5, disk caching is supported, but only for HTTP, not HTTPS, requests (though iOS 6 added support for this). Peter Steinberger wrote an excellent article on this subject, after digging into the internals while implementing his own NSURLCache subclass.

Another article by Daniel Pasco at Black Pixel describes some unexpected default behavior when communicating with servers that don't set cache headers.


NSURLCache reminds us of how important it is to be familiar with the systems we interact with. Chief among them when developing for iOS or Mac OS X is, of course, the URL Loading System.

Untold numbers of developers have hacked together an awkward, fragile system for network caching functionality, all because they weren't aware that NSURLCache could be setup in two lines and do it 100× better. Even more developers have never known the benefits of network caching, and never attempted a solution, causing their apps to make untold numbers of unnecessary requests to the server.

So be the change you want to see in the world, and be sure to always start you app on the right foot, by setting a shared NSURLCache in -application:didFinishLaunchingWithOptions:.

ReactiveCocoa

$
0
0

Languages are living things. They are nudged and challenged and bastardized and mashed-up in a perpetual cycle of undirected and rapid evolution. Technologies evolve, requirements change, corporate stewards and open source community come and go; obscure dialects are vaulted to prominence on the shoulders of exciting new frameworks, and thrust into a surprising new context after a long period of dormancy.

Objective-C has a remarkable history spanning four decades in as many acts:

In its 1st act, Objective-C was adopted as the language of NeXT, powering NeXTSTEP and the world's first web server.

In its 2nd act, Objective-C positioned itself in the heart Apple's technology stack (after a prolonged turf war with Java) with Apple's acquisition of NeXT.

In its 3rd act, Objective-C rose to unprecedented significance with the release of iOS, making it the most important language of mobile computing.

Objective-C's 4th act takes us to the present day, with an influx of new iOS developers from the Ruby, Python, and Javascript communities sparked a revolution open source participation. For the first time, Objective-C is being directly shaped and guided by the contributions of individuals outside of Apple.

Breaking from a tradition of covering Apple APIs exclusively, this edition of NSHipster will look at an open source project that exemplifies this brave new era for Objective-C: ReactiveCocoa.


For a complete look at ReactiveCocoa, refer to the project's README, Framework Overview and Design Guidelines.

ReactiveCocoa is an open source library that brings Functional Reactive Programming paradigm to Objective-C. It was created by Josh Abernathy& Justin Spahr-Summers in the development of GitHub for Mac. Last week, ReactiveCocoa reached a major milestone with its 1.0 release.

Functional Reactive Programming (FRP) is a way of thinking about software in terms of transforming inputs to produce output continuously over time. Josh Abernathy frames the paradigm thusly:

Programs take input and produce output. The output is the result of doing something with the input. Input, transform, output, done.

The input is all the sources of action for your app. Its taps. Its keyboard events. Its timer triggers, GPS events, and web service responses. These things are all inputs. They all feed into the app, and the app combines them all in some way to produce a result: the output.

The output is often a change in the app’s UI. A switch is toggled or a list gets a new item. Or it could be more than that. It could be a new file on the device’s disk, or it could be an API request. These things are the outputs of the app.

But unlike the classic input/output design, this input and output happens more than once. It’s not just a single input → work → output—the cycle continues while the app is open. The app is always consuming inputs and producing outputs based on them.

To illustrate the difference between the conventional, imperative paradigm of Objective-C programming versus a functional reactive approach, consider the common example of validating a signup form:

Conventional

-(BOOL)isFormValid{return[self.usernameField.textlength]>0&&[self.emailField.textlength]>0&&[self.passwordField.textlength]>0&&[self.passwordField.textisEqual:self.passwordVerificationField.text];}#pragma mark - UITextFieldDelegate-(BOOL)textField:(UITextField*)textFieldshouldChangeCharactersInRange:(NSRange)rangereplacementString:(NSString*)string{self.createButton.enabled=[selfisFormValid];returnYES;}

In the conventional example, logic is fragmented across different methods in the view controller, with calls to self.createButton.enabled = [self isFormValid]; interspersed throughout delegate methods and view lifecycle callbacks.

Compare this with equivalent code using ReactiveCocoa:

ReactiveCocoa

RACSignal*formValid=[RACSignalcombineLatest:@[self.username.rac_textSignal,self.emailField.rac_textSignal,self.passwordField.rac_textSignal,self.passwordVerificationField.rac_textSignal]reduce:^(NSString*username,NSString*email,NSString*password,NSString*passwordVerification){return@([usernamelength]>0&&[emaillength]>0&&[passwordlength]>8&&[passwordisEqual:passwordVerification]);}];RAC(self.createButton.enabled)=formValid;

Here, all of the logic for validating form input is contained in a single chain of logic and responsibility. Each time any of the text fields is updated, their inputs are reduced into a single boolean value, which automatically enables / disables the create button.

Overview

ReactiveCocoa is comprised of two major components: RACSignal and RACSequence.

RACSignal

  • Handling Asynchronous Or Event-driven Data Sources: Much of Cocoa programming is focused on reacting to user events or changes in application state.
  • Chaining Dependent Operations: Dependencies are most often found in network requests, where a previous request to the server needs to complete before the next one can be constructed.
  • Parallelizing Independent Work: Working with independent data sets in parallel and then combining them into a final result is non-trivial in Cocoa, and often involves a lot of synchronization.

Signals send three different types of events to their subscribers:

  • The next event provides a new value from the stream. Unlike Cocoa collections, it is completely valid for a signal to include nil.
  • The error event indicates that an error occurred before the signal could finish. The event may include an NSError object that indicates what went wrong. Errors must be handled specially – they are not included in the stream's values.
  • The completed event indicates that the signal finished successfully, and that no more values will be added to the stream. Completion must be handled specially – it is not included in the stream of values.

The lifetime of a signal consists of any number of next events, followed by one error or completed event (but not both).

RACSequence

  • Simplifying Collection Transformations: Higher-order functions like map, filter, fold/reduce are sorely missing from Foundation.

Sequences are a kind of collection, similar in purpose to NSArray. Unlike an array, the values in a sequence are evaluated lazily (i.e., only when they are needed) by default, potentially improving performance if only part of a sequence is used. Just like Cocoa collections, sequences cannot contain nil.

RACSequence allows any Cocoa collection to be manipulated in a uniform and declarative way.

RACSequence*normalizedLongWords=[[words.rac_sequencefilter:^BOOL(NSString*word){return[wordlength]>=10;}]map:^(NSString*word){return[wordlowercaseString];}];

Precedents in Cocoa

Capturing and responding to changes has a long tradition in Cocoa, and ReactiveCocoa is a conceptual and functional extension of that. It is instructive to contrast RAC with those Cocoa technologies:

RAC vs. KVO

Key-Value Observing is at the heart of all magic in Cocoa—indeed, it is the underlying mechanism used to implement ReactiveCocoa. However, KVO is neither pleasant nor easy to use: its API is overwrought with unused parameters and sorely lacking a blocks-based interface.

RAC vs. Bindings

Bindings are magic—voodoo, really.

Although essential to managing the complexity of a Mac OS X application, Bindings' cultural relevance has waned for years, as the focus has shifted to iOS and UIKit, which notably lacks support. Bindings replace a lot of boilerplate glue code and allow programming to be done in Interface Builder, but they're severely limited and impossible to debug. RAC offers a clear, understandable, and extensible code-based API that works in iOS and is apt to replace all but the most trivial uses of bindings in your OS X application.


Objective-C was built from Smalltalk's ideas on top of C's metal, but its cultural imports go far beyond its original pedigree.

@protocol was a rejection of C++'s multiple inheritance, favoring an abstract data type pattern comparable to a Java Interface. Objective-C 2.0 introduced @property / @synthesize, a contemporary of C#'s get; set; shorthand for getter and setter methods (as well as dot syntax, which is still a point of contention for NeXTSTEP hard-liners). Blocks injected some functional programming flavor to the language, which paired nicely with Grand Central Dispatch--a queue-based concurrency API almost certainly influenced by Fortran / C / C++ standard OpenMP. Subscripting and object literals, a standard feature in scripting languages like Ruby and Javascript, now finally brought to Objective-C thanks to a Clang language extension.

ReactiveCocoa brings a healthy dose of functional and reactive programming influence to Objective-C, and was itself influenced by C#'s Rx library, Clojure, and Elm.

Good ideas are contagious. ReactiveCocoa is a reminder that good ideas can come from unlikely places, and that a fresh perspective can make all of the difference with familiar problems.

NSAssertionHandler

$
0
0

"When at first you don't succeed, use an object-oriented injection point to override default exception handling." This is the sort of advice you would have learned at mother's knee if you were raised by NSAssertionHandler.

Programming incorporates numerous disciplines of human reasoning, from high-level discourse and semantics—the "story" we tell each other to explain how a system works—to the mathematical and philosophical machinery that underpins everything.

Assertions are a concept borrowed from classical logic. In logic, assertions are statements about propositions within a proof. In programming, assertions denote assumptions the programmer has made about the application at the place where they are declared.

When used in the capacity of preconditions and postconditions, which describe expectations about the state of the code at the beginning and end of execution of a method or function, assertions form a contract. Assertions can also be used to enforce conditions at run-time, in order to prevent execution when certain preconditions fail.

Assertions are similar to unit testing in that they define expectations about the way code will execute. Unlike unit tests, assertions exist inside the program itself, and are thereby constrained to the context of the program. Because unit tests are fully independent, they have a much greater capacity to isolate and test certain behaviors, using tools like methods stubs and mock objects. Developers should use assertions and unit tests in combination and in reasonable quantity to test and define behavior in an application.

Foundation Assertion Handling

Objective-C combines C-style assertion macros with an object-oriented approach to intercepting and handling assertion failures. Namely, NSAssertionHandler:

Each thread has its own assertion handler, which is an object of class NSAssertionHandler. When invoked, an assertion handler prints an error message that includes the method and class names (or the function name). It then raises an NSInternalInconsistencyException exception.

Foundation defines two pairs of assertion macros:

  • NSAssert / NSCAssert
  • NSParameterAssert / NSCParameterAssert

Foundation makes two distinctions in their assertion handler APIs that are both semantic and functional.

The first distinction is between a general assertion (NSAssert) and a parameter assertion (NSParameterAssert). As a rule of thumb, methods / functions should use NSParameterAssert / NSCParameterAssert statements at the top of methods to enforce any preconditions about the input values; in all other cases, use NSAssert / NSCAssert.

The second is the difference between C and Objective-C assertions: NSAssert should only be used in an Objective-C context (i.e. method implementations), whereas NSCAssert should only be used in a C context (i.e. functions).

  • When a condition in NSAssert or NSParameterAssert fails, -handleFailureInMethod:object:file:lineNumber:description: is called in the assertion handler.
  • When a condition in NSCAssert or NSCParameterAssert fails, -handleFailureInFunction:file:lineNumber:description: is called in the assertion handler.

Additionally, there are variations of NSAssert / NSCAssert, from NSAssert1 ... NSAssert5, which take their respective number of arguments to use in a printf-style format string.

Using NSAssertionHandler

It's important to note that as of Xcode 4.2, assertions are turned off by default for release builds, which is accomplished by defining the NS_BLOCK_ASSERTIONS macro. That is to say, when compiled for release, any calls to NSAssert& co. are effectively removed.

And while Foundation assertion macros are extremely useful in their own right—even when just used in development—the fun doesn't have to stop there. NSAssertionHandler provides a way to gracefully handle assertion failures in a way that preserves valuable real-world usage information.

That said, many seasoned Objective-C developers caution against actually using NSAssertionHandler in production applications. Foundation assertion handlers are something to understand and appreciate from a safe distance. Proceed with caution if you decide to use this in a shipping application.

NSAssertionHandler is a straightforward class, with two methods to implement in your subclass: -handleFailureInMethod:... (called on a failed NSAssert / NSParameterAssert) and -handleFailureInFunction:... (called on a failed NSCAssert / NSCParameterAssert).

LoggingAssertionHandler simply logs out the assertion failures, but those failures could also be logged to an external web service to be aggregated and analyzed, for example.

LoggingAssertionHandler.h

@interfaceLoggingAssertionHandler : NSAssertionHandler@end

LoggingAssertionHandler.m

@implementationLoggingAssertionHandler-(void)handleFailureInMethod:(SEL)selectorobject:(id)objectfile:(NSString*)fileNamelineNumber:(NSInteger)linedescription:(NSString*)format,...{NSLog(@"NSAssert Failure: Method %@ for object %@ in %@#%i",NSStringFromSelector(selector),object,fileName,line);}-(void)handleFailureInFunction:(NSString*)functionNamefile:(NSString*)fileNamelineNumber:(NSInteger)linedescription:(NSString*)format,...{NSLog(@"NSCAssert Failure: Function (%@) in %@#%i",functionName,fileName,line);}@end

Each thread has the option of specifying an assertion handler. To have the NSAssertionHandler subclass start handling failed assertions, set it as the value for the NSAssertionHandlerKey key in the thread's threadDictionary.

In most cases, it will make sense to set your assertion handler on the current thread inside -application: didFinishLaunchingWithOptions:.

AppDelegate.m

-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{NSAssertionHandler*assertionHandler=[[LoggingAssertionHandleralloc]init];[[[NSThreadcurrentThread]threadDictionary]setValue:assertionHandlerforKey:NSAssertionHandlerKey];// ...returnYES;}

NSAssertionHandler reminds us of the best practices around articulating our expectations as programmers through assert statements.

But if we look deeper into NSAssertionHandler—and indeed, into our own hearts, there are lessons to be learned about our capacity for kindness and compassion; about our ability to forgive others, and to recover from our own missteps. We can't be right all of the time. We all make mistakes. By accepting limitations in ourselves and others, only then are we able to grow as individuals.

Or whatever.

Back Row

$
0
0

For years, many have predicted the announcement of an Apple TV SDK. We all know it's coming. It has to. And it will be amazing when it happens... whenever that is.

Everything is in place for Apple to kick-start the next generation of television, completely leap-frogging the current, pathetic crop of "smart TVs" like the iPhone did with its "smart phone" predecessors. All they need to do is open up the ecosystem.

But rather than simply wait for the future, we can take matters into our own hands, with class-dump and some reverse-engineering chutzpah.

Voila! A class dump of the Apple TV private framework headers

That's right: this edition of NSHipster covers a topic so obscure, it doesn't even officially exist.


Back Row is a private framework used in the Apple TV user experience. Its name is a reference to Front Row, an application included in Mac OS X 10.4 – 10.6 that paired with the Apple Remote to transform the Mac into a couch-friendly media center.

The original Apple TV could be described as a "short Mac Mini", which ran a modified version of Front Row on a stripped-down build of Mac OS X. It was little more than an iTunes remote, streaming content from a shared iTunes library on a separate computer.

The second generation of the device took a smaller form factor, shifting its focus from media storage and management to on-demand streaming. The second generation Apple TV user interface reflected this in both its design and implementation. BackRow was ported from OS X to iOS, as it transcended its original role coordinating iTunes libraries to become an extensible platform for streaming media appliances.

Back Row & UIKit

Back Row (name prefix: BR) bears a striking resemblance to UIKit, with many of the familiar metaphors and conventions of iOS development.

Here's a brief list of some Back Row classes & protocols and their UIKit equivalents:

Back RowUIKit
<BRResponder><UIResponder>
<BRAppliance><UIApplication>
BRControllerUIViewController
BRMenuControllerUITableViewController
BRControllerStackUINavigationController
BRGridViewUICollectionView
BRListViewUITableView

Apple TV Appliance Structure

Apple TV Home Screen

In the current Apple TV interface, the home screen contains a grid of rectangular icons, similar to the home screen on iOS. Each icon corresponds to an appliance.

Why an appliance and not an application? An appliance is more limited in what it can do as compared to an application. On iPhone or iPad, applications range from social media clients and photo tools to games and musical instruments. Whereas on Apple TV, an appliance consists of a series of remote-friendly menus, lists, and grids, which ultimately lead to media playback of some form. When it comes to appliances, (audio / video) content is king.

When an appliance launches, it displays a list of BRApplianceCategory items. Each category has its own name, identifier, and preferred ordering. When a category is selected, the appliance calls - controllerForIdentifier:args:, which returns a BRController object.

An appliance also has an optional topShelfController, which is what displays at the top of the home screen when the app is highlighted.

Pushing and popping controllers is managed by a shared BRControllerStack. When a controller is selected with in a list, it is pushed onto the stack. When the user presses the Menu button, the stack is popped.

Apple TV YouTube

A typical controller consists of a menu list on the right, with some kind of complimentary view on the left.

On top-level controllers, this sometimes takes the form of a BRMarqueeStack, which animates a Cover-Flow-style sequence of preview images for each of the controllers.

For controllers listing media that can be played, the complimentary view usually shows a preview image, along with meta data in a BRMetadataControl, such as runtime, date created, and other relevant information.

Apple TV Movie

iTunes store controllers also use a horizontally-stacked layout, with media information at the top, with related titles listed below.

Points of Interest

Diving into the class dump of the Apple TV frameworks reveals a treasure trove of interesting tidbits. With only undocumented header files to go by, there's still a lot of mystery to what all's in these private frameworks, or how they fit together. However a thoughtful analysis of class and method names offers some workable clues into their inter-workings.

Here are some of the more interesting parts of the Back Row framework headers (again, all of this is complete speculation):

  • BRURLImageProxy: A protocol that encapsulates the process of loading and displaying images at various dimensions.
  • BRKeyboard: It's always fascinating to see how Apple architects controls. Keyboards populate and manage interactions with the grid view of character and action keys, and are divided into classes for Roman and Japanese scripts.
  • BRStateMachine: No other Apple frameworks expose a class for state machines. LATVLeaseAgent is a subclass in the AppleTV framework that appears to negotiate the terms of iTunes movie rentals.
  • BRMappingDictionary: A new and useful-looking collection class that functions as an NSMutableDictionary, but also allows for an NSValueTransformer to be set for each key (-transformedValueForKey:forObject: in addition to -valueForKey:)
  • BRMerchant: What you might expect in terms of a class representing a store client, with some interesting class methods. itms is in reference to the iTunes Music Store, but what's sedona and flagstaff? They're probably codewords for streaming services that fall under the umbrella of the iTunes store.
  • <BRControlFactory><BRMetadataPopulator>& BRControlMediator: Factories, Populators, and Mediators are not commonly seen design patterns in Apple frameworks, although they are described in the Cocoa Fundamentals Guide.

Building Your Own Apple TV App

In the immortal words of Jeff Goldblum: "Life finds a way".

Undeterred by the litigious shadow of Apple Inc., nor the undocumented wilds of a private API, a cadre of jail-breaking homesteaders have cracked the nut on Apple TV development with promising results.

One of the most polished among them is UitzendingGemist led by none other than Eloy Durán of CocoaPods fame, along with Kevin Bradley and Michael Gile.

As you can see from this video of an early version, you can run your very own applications on a jail-broken Apple TV (OS 5.0.1 or compatible). The code is relatively straightforward, fetching a catalog of media files from the Dutch public broadcasting site UitzendingGemist.nl, and playing them on demand.


It's hard to say what it will take for Apple to open up the Apple TV ecosystem. Is it a matter of getting the APIs documented and ready for public use? Is there a process underway to refactor Back Row into UIKit? Or is everything pretty much ready, and it's just a matter of other business pieces falling into place?

Only time will tell.

In the meantime, you can get a head-start on what will almost certainly be a gold-rush on the scale of the first generation of iPhone apps.

UIAppearance

$
0
0

Style vs. Substance.
Message vs. Medium.
Rhetoric vs. Dialectic.

Is beauty merely skin deep, or is it somehow informed by deeper truths?
What does it mean for something to posses good design?
Are aesthetic judgments relative, or absolute?

These are deep questions that have been pondered by philosophers, artists, and makers alike for millenia.

And while we all continue our search for beauty and understanding in the universe, the app marketplace has been rather clear on this subject:

Users will pay a premium for good-looking software.

When someone purchases an iPhone, they are buying into Apple's philosophy that things that work well should look good, too. The same goes for when we choose to develop for iOS—a sloppy UI reflects poorly on the underlying code.

It used to be that even trivial UI customization on iOS required AppStore-approval-process-taunting ju-ju like method swizzling. Fortunately, with iOS 5, developers were given an easier way: UIAppearance.


UIAppearance allows the appearance of views and controls to be consistently defined across the entire application.

In order to have this work within the existing structure of UIKit, Apple devised a rather clever solution: UIAppearance is a protocol that returns a proxy that will forward any configuration to instances of a particular class. Why a proxy instead of a property or method on UIView directly? Because there are non-UIView objects like UIBarButtonItem that render their own composite views. Appearance can be customized all instances, or scoped to particular view hierarchies:

  • +appearance: Returns the appearance proxy for the receiver.
  • +appearanceWhenContainedIn:(Class <UIAppearanceContainer>)ContainerClass,...: Returns the appearance proxy for the receiver in a given containment hierarchy.

To customize the appearance of all instances of a class, you use appearance to get the appearance proxy for the class. For example, to modify the tint color for all instances of UINavigationBar:

[[UINavigationBarappearance]setTintColor:myColor];

To customize the appearances for instances of a class when contained within an instance of a container class, or instances in a hierarchy, you use appearanceWhenContainedIn: to get the appearance proxy for the class:

[[UIBarButtonItemappearanceWhenContainedIn:[UINavigationBarclass],nil]setTintColor:myNavBarColor];[[UIBarButtonItemappearanceWhenContainedIn:[UINavigationBarclass],[UIPopoverControllerclass],nil]setTintColor:myPopoverNavBarColor];[[UIBarButtonItemappearanceWhenContainedIn:[UIToolbarclass],nil]setTintColor:myToolbarColor];[[UIBarButtonItemappearanceWhenContainedIn:[UIToolbarclass],[UIPopoverControllerclass],nil]setTintColor:myPopoverToolbarColor];

Determining Which Properties Work With UIAppearance

One major downside to UIAppearance's proxy approach is that it's difficult to know which selectors are compatible. Because +appearance returns an id, Xcode can't provide any code-completion information. This is a major source of confusion and frustration with this feature.

In order to find out what methods work with UIAppearance, you have to look at the headers:

$ cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/
  Developer/SDKs/iPhoneOS*.sdk/System/Library/Frameworks/UIKit.framework/Headers
$ grep -H UI_APPEARANCE_SELECTOR ./* | sed 's/ __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0) UI_APPEARANCE_SELECTOR;//'

UIAppearance looks for the UI_APPEARANCE_SELECTOR macro in method signatures. Any method with this annotation can be used with the appearance proxy.

For your convenience, here is the list of properties as of iOS 6.1

Implementing <UIAppearance> in Custom UIView Subclasses

Much like how NSLocalizedString and #pragma are marks of quality in Objective-C code, having custom UI classes conform to UIAppearance is not only a best-practice, but it demonstrates a certain level of care being put into its implementation.

Peter Steinberger has this great article, which describes some of the caveats about implementing UIAppearance in custom views. It's a must-read for anyone who aspires to greatness in their open source UI components.

Alternatives

Another major shortcoming of UIAppearance is that style rules are imperative, rather than declarative. That is, styling is applied at runtime in code, rather than being interpreted from a list of style rules.

Yes, if there's one idea to steal from web development, it's the separation of content and presentation. Say what you will about CSS, but stylesheets are amazing.

Stylesheet enthusiasts on iOS now have some options. Pixate is a commercial framework that uses CSS to style applications. NUI, an open-source project by Tom Benner, does much the same with a CSS/SCSS-like language. Another open source project along the same lines is UISS by Robert Wijas, which allows UIAppearance rules to be read from JSON.


Cocoa developers have a long history of obsessing about visual aesthetics, and have often gone to extreme ends to achieve their desired effects. Recall the Delicious Generation of Mac developers, and applications like Disco, which went so far as to emit virtual smoke when burning a disc.

This spirit of dedication to making things look good is alive and well in iOS. As a community and as an ecosystem, we have relentlessly pushed the envelope in terms of what users should expect from their apps. And though this makes our jobs more challenging, it makes the experience of developing for iOS all the more enjoyable.

Settle for nothing less than the whole package.
Make your apps beautiful from interface to implementation.


C Storage Classes

$
0
0

It's time, once again, to take a few steps back from the world of Objective-C, and look at some underlying C language features. Hold onto your fedoras, ladies & gents, as we dive into C storage classes in this week's edition of NSHipster.


In C, the scope and lifetime of a variable or function within a program is determined by its storage class. Each variable has a lifetime, or the context in which they store their value. Functions, along with variables, also exist within a particular scope, or visibility, which dictates which parts of a program know about and can access them.

There are 4 storage classes in C:

  • auto
  • register
  • static
  • extern

At least a few of these will look familiar to anyone who has done a cursory amount of Objective-C programming. Let's go into more detail with each one:

auto

There's a good chance you've never seen this keyword in the wild. That's because auto is the default storage class, and therefore doesn't need to be explicitly used often.

Automatic variables have memory automatically allocated when a program enters a block, and released when the program leaves that block. Access to automatic variables is limited to only the block in which they are declared, as well as any nested blocks.

register

Most Objective-C programmers probably aren't familiar with register either, as it's just not widely used in the NS world.

register behaves just like auto, except that instead of being allocated onto the stack, they are stored in a register.

Registers offer faster access than RAM, but because of the complexities of memory management, putting variables in registers does not guarantee a faster program—in fact, it may very well end up slowing down execution by taking up space on the register unnecessarily. As it were, using register is actually just a suggestion to the compiler to store the variable in the register; implementations may choose whether or not to honor this.

register's lack of popularity in Objective-C is instructive: it's probably best not to bother with it, as it's much more likely to cause a headache than speed up your app in any noticeable way.

static

Finally, one that everyone's sure to recognize. static denotes global scope and storage within the source file in which its declared.

Unlike automatic variables, static variables can be accessed and mutated by any function, regardless of the context in which they are declared—so long as those functions appear in the same file as the static variable. The same goes for static functions.

Static Singletons

A common pattern in Objective-C is the static singleton_, wherein a statically-declared variable is initialized and returned in either a function or class method. dispatch once is used to guarantee that the variable is initialized _exactly once in a thread-safe manner:

+(instancetype)sharedInstance{staticid_sharedInstance=nil;staticdispatch_once_tonceToken;dispatch_once(&onceToken,^{_sharedInstance=[[selfalloc]init];});return_sharedInstance;}

The singleton pattern is useful for creating objects that are shared across the entire application, such as an HTTP client or a notification manager, or objects that may be expensive to create, such as formatters.

extern

Whereas static makes functions and variables globally visible within a particular file, extern makes them visible globally to all files.

Global variables are not a great idea, generally speaking. Having no constraints on how or when state can be mutated is just asking for impossible-to-debug bugs. That said, there are two common and practical uses for extern in Objective-C.

Global String Constants

Any time your application uses a string constant with a non-linguistic value in a public interface, it should declare it as an external string constant. This is especially true of keys in userInfo dictionaries, NSNotification names, and NSError domains.

The pattern is to declare an externNSString * const in a public header, and define that NSString * const in the implementation:

AppDelegate.h

externNSString*constkAppErrorDomain;

AppDelegate.m

NSString*constkAppErrorDomain=@"com.example.yourapp.error";

It doesn't particularly matter what the value of the string is, so long as it's unique. Using a string constant establishes a strict contract, that the constant variable is used instead of the string's literal value itself.

Public Functions

Some APIs may wish to expose helper functions publicly. For auxiliary concerns and state-agnostic procedures, functions are a great way to encapsulate these behaviors—and if they're particularly useful, it may be worth making them available globally.

The pattern follows the same as in the previous example:

TransactionStateMachine.h

typedefNS_ENUM(NSUInteger,TransactionState){TransactionOpened,TransactionPending,TransactionClosed,};externNSString*NSStringFromTransactionState(TransactionStatestate);

TransactionStateMachine.m

NSString*NSStringFromTransactionState(TransactionStatestate){switch(state){caseTransactionOpened:return@"Opened"caseTransactionPending:return@"Pending";caseTransactionClosed:return@"Closed";default:returnnil;}}

To understand anything is to make sense of its context. What we may see as obvious and self-evident, is all but unknown to someone without our frame of reference. Our inability to truly understand or appreciate the differences in perspective and information between ourselves and others is perhaps our most basic shortcoming.

That is why, in our constructed logical universe of 0's and 1's, we take such care to separate contexts, and structure our assumptions based on these explicit rules. C storage classes are essential to understanding how a program operates. Without them, we are left to develop as one might walk on egg shells. So take heed of these simple rules of engagement and go forth to code with confidence.

Search Kit

$
0
0

NSHipsters love irony, right? How about this for irony:

There's this framework called Search Kit, which despite being insanely powerful and useful for finding information, is something that almost no one has ever heard of.

It's true! I'd reckon there's a better chance that you have implemented your own search functionality from scratch than have ever even heard of Search Kit. (Heck, most people haven't even heard of Core Services, its parent framework)

If only everyone knew that they could harness the same killer search functionality that Apple uses for their own applications...


Search Kit is a C framework for searching and indexing content in human languages. It supports matching on phrase or partial word, including logical (AND, OR) and wildcard (*) operators, and can rank results by relevance. Search Kit also provides document summarization, which is useful for generating representative excerpts. And best of all: it's thread-safe.

All of the whiz-bang search-as-you-type features in Mac OS X—from Mail.app and Xcode to System Preferences and Spotlight—use Search Kit under the hood.

But to understand how Search Kit does its magic, it's important to explain some of the basics of Information Retrieval and Natural Language Processing.

Be sure to check out Apple's Search Kit Programming Guide for an authoritative explanation of the what's, why's, and how's of this great framework.

Search 101

Quoth Apple:

You have an information need. But before you can ask a question, you need someone or something to ask. That is, you need to establish who or what you will accept as an authority for an answer. So before you ask a question you need to define the target of your question.

Finding the answer in a reasonable amount of time requires effort from the start. This is what that process looks like in general terms:

Extract

First, content must be extracted from a corpus. For a text document, this could involve removing any styling, formatting, or other meta-information. For a data record, such as an NSManagedObject, this means taking all of the salient fields and combining it into a representation.

Once extracted, the content is tokenized for further processing.

Filter

In order to get the most relevant matches, it's important to filter out common, or "stop" words like articles, pronouns, and helping verbs, that don't really contribute to overall meaning.

Reduce

Along the same lines, words that mean basically the same thing should be reduced down into a common form. Morpheme clusters, such as grammatical conjugations like "computer", "computers", "computed", and "computing", for example, can all be simplified to be just "compute", using a stemmer. Synonyms, likewise, can be lumped into a common entry using a thesaurus lookup.

Index

The end result of extracting, filtering, and reducing content into an array of normalized tokens is to form an inverted index, such that each token points to its origin in the index.

After repeating this process for each document or record in the corpus until, each token can point to many different articles. In the process of searching, a query is mapped onto one or many of these tokens, retrieving the union of the articles associated with each token.

Using Search Kit

Creating an Index

SKIndexRef is the central data type in Search Kit, containing all of the information needed to process and fulfill searches, and add information from new documents. Indexes can be persistent / file-based or ephemeral / in-memory. Indexes can either be created from scratch, or loaded from an existing file or data object—and once an index is finished being used, like many other C APIs, the index is closed.

Adding Documents to an Index

SKDocumentRef is the data type associated with entries in the index. When a search is performed, documents (along with their context and relevance) are the results.

Each SKDocumentRef is associated with a URI.

For documents on the file system, the URI is simply the location of the file on disk:

NSURL*fileURL=[NSURLfileURLWithPath:@"/path/to/document"];SKDocumentRefdocument=SKDocumentCreateWithURL((__bridgeCFURLRef)fileURL);

For Core Data managed objects, the NSManagedObjectID -URIRepresentation can be used:

NSURL*objectURL=[objectIDURIRepresentation];SKDocumentRefdocument=SKDocumentCreateWithURL((__bridgeCFURLRef)objectURL);

For any other kinds of data, it would be up to the developer to define a URI representation.

When adding the contents of a SKDocumentRef to an SKIndexRef, the text can either be specified manually:

NSString*string=@"Lorem ipsum dolar sit amet"SKIndexAddDocumentWithText(index,document,(__bridgeCFStringRef)string,true);

...or collected automatically from a file:

NSString*mimeTypeHint=@"text/rtf"SKIndexAddDocument(index,document,(__bridgeCFStringRef)mimeTypeHint,true);

To change the way a file-based document's contents are processed, properties can be defined when creating the index:

NSSet*stopwords=[NSSetsetWithObjects:@"all",@"and",@"its",@"it's",@"the",nil];NSDictionary*properties=@{@"kSKStartTermChars":@"",// additional starting-characters for terms@"kSKTermChars":@"-_@.'",// additional characters within terms@"kSKEndTermChars":@"",// additional ending-characters for terms@"kSKMinTermLength":@(3),@"kSKStopWords":stopwords};SKIndexRefindex=SKIndexCreateWithURL((CFURLRef)url,NULL,kSKIndexInverted,(CFDictionaryRef)properties);

Searching

SKSearchRef is the data type constructed to perform a search on an SKIndexRef. It contains a reference to the index, a query string, and a set of options:

NSString*query=@"kind of blue";SKSearchOptionsoptions=kSKSearchOptionDefault;SKSearchRefsearch=SKSearchCreate(index,(CFStringRef)query,options);

SKSearchOptions is a bitmask with the following possible values:

  • kSKSearchOptionDefault: Default search options include:
    • Relevance scores will be computed
    • Spaces in a query are interpreted as Boolean AND operators.
    • Do not use similarity searching.

These options can be specified individually as well:

  • kSKSearchOptionNoRelevanceScores: This option saves time during a search by suppressing the computation of relevance scores.
  • kSKSearchOptionSpaceMeansOR: This option alters query behavior so that spaces are interpreted as Boolean OR operators.
  • kSKSearchOptionFindSimilar: This option alters query behavior so that Search Kit returns references to documents that are similar to an example text string. When this option is specified, Search Kit ignores all query operators.

Putting this all together is SKIndexCopyDocumentURLsForDocumentIDs, which performs the search and fills arrays with the results. Iterating through the range of found matches provides access to the document URL and relevance score (if calculated):

NSUIntegerlimit=...;// Maximum number of resultsNSTimeIntervaltime=...;// Maximum time to get results, in secondsSKDocumentIDdocumentIDs[limit];CFURLRefurls[limit];floatscores[limit];CFIndexcount;BooleanhasResult=SKSearchFindMatches(search,limit,documentIDs,scores,time,&count);SKIndexCopyDocumentURLsForDocumentIDs(index,foundCount,documentIDs,urls);NSMutableArray*mutableResults=[NSMutableArrayarray];[[NSIndexSetindexSetWithIndexesInRange:NSMakeRange(0,count)]enumerateIndexesUsingBlock:^(NSUIntegeridx,BOOL*stop){CFURLRefurl=urls[idx];floatrelevance=scores[idx];NSLog(@"- %@: %f",url,relevance);if(objectID){[mutableResultsaddObject:(NSURL*)url];}CFRelease(url);}];

For more examples of Search Kit in action, be sure to check out Indragie Karunaratne's project, SNRSearchIndex.


And so this article becomes yet another document in the corpus we call the Internet. By pointing to Search Kit, and explaining even the briefest of its features, this—the strings of tokens you read at this very moment—are (perhaps) making it easier for others to find Search Kit.

...and it's a good thing, too, because Search Kit is a wonderful and all-too-obscure framework, which anyone building a content-based system would do well to investigate.

iCloud

$
0
0

The Lisa. The Twentieth Anniversary Macintosh. The iPod Hi-Fi. The MacBook Wheel.

Each of these products exemplifies Apple's obsessive pursuit of quality as much as its unrivaled ability to anticipate the direction of things to come and execute flawlessly.

In the words of Wayne Gretzky: Skate where the puck's going, not where it's been.

But perhaps what Apple is most renowned for, however, is its consistent track record for creating great webservices. From consumer products like MobileMe and Ping to developer tools including the Provisioning Portal and iTunes Connect, Apple has continued to set new standards for convenience, robustness, and extensibility.

So when Apple introduced iCloud at WWDC in 2011, everyone in the audience was rapt in anticipation, overcome with a sense of optimistic wonder. "Not again!", we said to ourselves, shaking our head with a knowing smile. "This changes everything!"

And indeed, iCloud has changed everything. Although it seemed almost too good to be true when Steve Jobs got up on that stage in Moscone to announce iCloud to the world that morning in June—if anything, Apple has under-promised and over-delivered with iCloud.

Now, NSHipster usually covers obscure topics that you've probably never heard of. But this is one of those days where it just feels right to take this opportunity today to make sure we're all on the same page about iCloud.


iCloud is an umbrella term for the latest evolution of Apple's consumer webservices. Following from the success of iTools, .Mac, and MobileMe, iCloud manages our digital lives like never before, with features like Photo Stream, iTunes Match, and Documents in the Cloud.

What really ties everything together are the iCloud Storage APIs that allow developers to easily create applications to stay connected across all of your devices. These APIs come in three different flavors, depending on the particular needs of your application:

  • Key-value storage for discrete values, such as preferences, settings, and simple app state.
  • Document storage for user-visible file-based information such as word processing documents, drawings, and complex app state.
  • Core Data storage for shoebox-style apps and server-based, multi-device database solutions for structured content. iCloud Core Data storage is built on document storage and employs the same iCloud APIs.

Key-Value Storage... in the Cloud!

To store discrete values in iCloud for app preferences, app configuration, or app state, use iCloud key-value storage. Key-value storage is similar to the local user defaults database; but values that you place in key-value storage are available to every instance of your app on all of a user’s various devices.

Everyone knows that key-value storage is the secret to achieving Web Scale. That's just science.

Inject a healthy dose of Web Scale convenience into your app by incorporating NSUbiquitousKeyValueStore into your app:

-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(ubiquitousKeyValueStoreDidChange:)name:NSUbiquitousKeyValueStoreDidChangeExternallyNotificationobject:[NSUbiquitousKeyValueStoredefaultStore]];[[NSUbiquitousKeyValueStoredefaultStore]synchronize];returnYES;}

Document Storage... in the Cloud!

Adopting iCloud document storage makes your app’s documents available on all of a user’s devices. Documents automatically implement most of the behavior expected of iCloud apps. Specifically, a document automatically ensures that local changes are safely coordinated with iCloud-originated changes.

Leave filesystem-based storage to those poor terrestrial bound souls who haven't been raptured to the iCloud. Dropbox? Never heard of 'em.

Having documents reside entirely in application-specific cloud containers means less clutter in your digital life. Why should other applications be able to access documents anyway? Why would I want to use any more than a single app for any particular task?

They say seeing is believing, but iCloud is built on faith—that everything will be there next time you open Pages, Keynote, or TextEdit. Leave the Finder to play with its folders and .DS_Store files; we shall inherit the open skies of digital freedom.

Core Data Storage... in the Cloud!

Adopting iCloud Core Data storage makes the content in a shoebox-style app (like iPhoto) or a database-style app (like Bento) available on all of a user’s devices. Each instance of your app, on each device attached to an iCloud account, maintains its own local Core Data store file. When data changes locally, Core Data writes change log files to your app’s default ubiquity container.

Developers really love Core Data syncing over iCloud. Seriously, they just can'tstopravingaboutit.

Just when you thought Core Data couldn't get simpler, iCloud once again redefines our expectations.

Every time your application receives a NSPersistentStoreDidImportUbiquitousContentChangesNotification is reminiscent of that excitement of seeing the FedEx truck pull up with your pre-ordered iPhone 5. "This is the first day of the rest of my life", you'll think to yourself as you sign the proverbial confirmation slip of the package.

Sure, there's a chance that what you're signing is actually a repossession confirmation, and that the delivery guy will proceed to bust into your apartment and take everything you once owned, but at least you still have your new iPhone.

So it goes. Even an enlightened iLife is not without its risks.


Life just seems to float by, now that iCloud is managing our digital existence. No longer do we have to think about whether we have all of the information we need to go about our day:

From the moment our iPhone wakes us up with the "Marimba" ringtone, to our daily commute with Siri talking us through our day, and a productive work day using iWork; from the walk to the gym, listening to Podcasts.app, and working out with iTunes Sync, until our last waking hours as we wind down the day with Game Center, Apple and iCloud makes every day special.

And with the iCloud Storage APIs, you too can add your application to that perfect routine of digitally-synced bliss.

No foolin'.

BOOL / bool / Boolean / NSCFBoolean

$
0
0

We've talked before about the philosophical and technical concerns of nothingness in programming. This week, our attention turns to another fundamental matter: Truth.

Truth. Vēritās. The entire charter of Philosophy is founded upon the pursuit of it, and yet its exact meaning and implications still elude us. Does truth exist independently, or is it defined contingently against falsity? Can a proposition be at once both true and false? Is there absolute truth in anything, or is everything relative?

Once again, encoding our logical universe into the cold, calculating bytecode of computers forces us to deal with these questions one way or another. And as you'll see from our discussion of boolean types in Objective-C and its kin, truth is indeed stranger than fiction.


Objective-C defines BOOL to encode truth value. It is a typedef of a signed char, with the macros YES and NO to represent true and false, respectively.

Boolean values are used in conditionals, such as if or while statements, to conditionally perform logic or repeat execution. When evaluating a conditional statement, the value 0 is considered "false", while any other value is considered "true". Because NULL and nil are defined as 0, conditional statements on these nonexistent values are also evaluated as "false".

In Objective-C, use the BOOL type for parameters, properties, and instance variables dealing with truth values. When assigning literal values, use the YES and NO macros.

The Wrong Answer to the Wrong Question

Novice programmers often include an equality operator when evaluating conditionals:

if([aisEqual:b]==YES){...}

Not only is this unnecessary, but depending on the left-hand value, it may also cause unexpected results, as described in the Big Nerd Ranch blog post, "BOOL's Sharp Edges":

staticBOOLdifferent(inta,intb){returna-b;}

An overly clever C programmer might take some satisfaction in the simplicity of this approach: indeed, two integers are equal if and only if their difference is 0.

However, because of the reality of BOOL being typedef'd as a signed char, this will not behave as expected:

if(different(11,10)==YES){printf("11 != 10\n");}else{printf("11 == 10\n");}if(different(10,11)==YES){printf("10 != 11\n");}else{printf("10 == 11\n");}if(different(512,256)==YES){printf("512 != 256\n");}else{printf("512 == 256\n");}

This evaluates to:

11 != 10
10 == 11
512 == 256

Now, this might be acceptable for JavaScript, but Objective-C don't suffer fools gladly.

Deriving truth value directly from an arithmetic operation is never a good idea. Like the sentence "Colorless green ideas sleep furiously", it may be grammatical (after all, BOOL is a signed char like any other, so it could be treated as a number), but it doesn't make sense semantically. Instead, use the result of the == operator, or cast values into booleans with the ! (or !!) operator.

The Truth About NSNumber and BOOL

Pop quiz: what is the output of the following expression?

NSLog(@"%@",[@(YES)class]);

The answer:

__NSCFBoolean

Wait, what?

All this time, we've been lead to believe that NSNumberboxes primitives into an object representation. Any other integer- or float-derived NSNumber object shows its class to be __NSCFNumber. What gives?

NSCFBoolean is a private class in the NSNumberclass cluster. It is a bridge to the CFBooleanRef type, which is used to wrap boolean values for Core Foundation property lists and collections. CFBoolean defines the constants kCFBooleanTrue and kCFBooleanFalse. Because CFNumberRef and CFBooleanRef are different types in Core Foundation, it makes sense that they are represented by different bridging classes in NSNumber.

For most people, boolean values and boxed objects "just work", and don't really care what goes into making the sausage. But here at NSHipster, we're all about sausages.


So, to recap, here is a table of all of the truth types and values in Objective-C:

NameTypedefHeaderTrue ValueFalse Value
BOOLsigned charobjc.hYESNO
bool_Bool (int)stdbool.htruefalse
Booleanunsigned charMacTypes.hTRUEFALSE
NSNumber__NSCFBooleanFoundation.h@(YES)@(NO)
CFBooleanRefstructCoreFoundation.hkCFBooleanTruekCFBooleanFalse

NSSecureCoding

$
0
0

A short post for this week: everything you need to know about NSSecureCoding.


NSSecureCoding is a protocol introduced in the iOS 6 / Mac OS X 10.8 SDKs. Aside from a few mentions at WWDC, NSSecureCoding remains relatively obscure—most developers have perhaps heard of it, but perhaps never went so far as to look up what it does.

NSSecureCoding extends the NSCoding protocol by adding the class method:

+(BOOL)supportsSecureCoding;

By conforming to NSSecureCoding and returning YES for +supportsSecureCoding, a class declares that it handles encoding and decoding of instances of itself in a way that guards against substitution attacks.

Specifically, classes that override -initWithCoder and conform to NSSecureCoding should use -decodeObjectOfClass:forKey: rather than -decodeObjectForKey:.

Why is this important? Recall that NSCoding is Foundation's way of marshaling objects to be either archived on a file system, or copied to another address space. When -decodeObjectForKey: is used to decode representations of objects into actual objects, there is no guarantee that the result of creating the object will be what was expected. If that representation is corrupted—specifically, in changing the target class (and thus designated initializer)—the application runs the risk of constructing unknown objects. Whether by malicious intent or an incidental coding error, this can cause serious problems.

It's not an apples-to-apples comparison, but it's somewhat similar to recent YAML exploit found in Rails.

For an XPC service, which is designed with security in mind, data integrity of this nature is especially important. It's a safe bet that XPC will only wax influence in subsequent iOS and OS X releases, so it's good to keep this all in mind.

Anyway, NSSecureCoding patches this vulnerability by establishing a contract for best practices. Now, decoding an object requires the class to be known ahead of time.

Whereas a standard, secure implementation of -initWithCoder: might have a check like:

idobj=[decoderdecodeObjectForKey:@"myKey"];if(![objisKindOfClass:[MyClassclass]]){// fail}

...an NSSecureCoding-conforming class would use:

idobj=[decoderdecodeObjectOfClass:[MyClassclass]forKey:@"myKey"];

Sometimes, a little API change makes all of the difference.


So now you know what's up with NSSecureCoding. Keep an eye out for that going forward: XPC is only going to become more important. Perhaps not today, perhaps not tomorrow, but someday—you will probably need to implement NSSecureCoding. And when that day comes... you'll be ready.

Stay safe, everyone.

Viewing all 382 articles
Browse latest View live