Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to get the neat Objective-C literal indexing feature in Xcode 4.4?

I read all about the new Objective-C literals, and used Xcode to convert my old code, but the indexing code didn't change. I changed it by hand but then it wouldn't compile. I saw a post that said we have to wait until iOS 6, but I want the indexing NOW!

Is there any solution?

like image 679
David H Avatar asked Jul 27 '12 19:07

David H


1 Answers

Well, there is a way to do it! Add the indexing methods as a category to NSArray and NSDictionary, and you can get the feature for most of the classes you'd want it for. You can read up on ObjectiveC literals here. And thanks to James Webster's solution for @YES and @NO you can use them properly in your projects now too! (the technique)

1) Create the Interface files

// NSArray+Indexing.h
#if !defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
@interface NSArray (Indexing)
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
@end
@interface NSMutableArray (Indexing)
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
@end
// NSDictionary+Indexing.h
@interface  NSDictionary (Indexing)
- (id)objectForKeyedSubscript:(id)key;
@end
@interface  NSMutableDictionary (Indexing)
- (void)setObject:(id)obj forKeyedSubscript:(id)key;
@end
#endif

2) Create the Implementation files // see edit below before doing this - you can skip this

// NSArray+Indexing.m
#if !defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
#import "NSArray+Indexing.h"
@implementation NSArray (Indexing)
- (id)objectAtIndexedSubscript:(NSUInteger)idx
{
    return [self objectAtIndex:idx];
}
@end
@implementation NSMutableArray (Indexing)
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
{
    [self replaceObjectAtIndex:idx withObject:obj];
}
@end

// NSMutableDictionary+Indexing.m
@implementation  NSDictionary (Indexing)

- (id)objectForKeyedSubscript:(id)key
{
    return [self objectForKey:key];
}
@end
@implementation  NSMutableDictionary (Indexing)
- (void)setObject:(id)obj forKeyedSubscript:(id)key
{
    [self setObject:obj forKey:key];
}
@end
#endif

3) Add the Interface files to your pch file for global use, or add them as needed to .m files

// Add to PCH file
#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
...
#if !defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0

// New Indexing
#import "NSDictionary+Indexing.h"
#import "NSArray+Indexing.h"

// Provided by James Webster on StackOverFlow
#if __has_feature(objc_bool) 
#undef YES 
#undef NO 
#define YES __objc_yes 
#define NO __objc_no 
#endif 

#endif
#endif

#endif

4) Rebuild, then add the below files to verify that it all works

// Test Example
{

    NSMutableArray *a = [NSMutableArray arrayWithArray:@[ @"a", @"b", @"c" ]];
    NSLog(@"%@", a[1]);
    a[1] = @"foo";
    NSLog(@"a: %@", a);

    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{ @"key" : @"object" }];
    NSLog(@"%@", dict[@"key"]);

    dict[@"key"] = @"New Object";
    dict[@"newKey"] = @"WOW a new object";

    NSLog(@"dict: %@", dict);

    NSLog(@" %@ %@", @YES, @NO );
}

EDIT: Well, according to a key llvm/clang Apple engineer, there is a library that already gets linked in with the implementations, so you just need the interface file:

Date: Mon, 20 Aug 2012 15:16:43 -0700 From: Greg Parker To: ... Subject: Re: How to make Obj-C collection subscripting work on iOS 5? ...

As an experiment I added the category @interface for these methods, but not the @implementation — the app still ran fine (at least in the 5.1 simulator)

The compiler emits the same calls. The magic is in the increasingly inaccurately named libarclite ("It's Not Just For ARC Anymore™"), which adds implementations of the subscripting methods at runtime if they don't already exist.

IIRC there are some subscript-able classes that libarclite does not upgrade (NSOrderedSet, maybe?) so you still need to test thoroughly on older deployment targets.

like image 155
David H Avatar answered Oct 11 '22 21:10

David H