在Xcode 4.4中有没有获取Objective-C简洁的字面量索引功能的方法?

7
我阅读了关于新的Objective-C字面量的所有内容,并在Xcode中使用了它来转换我的旧代码,但索引代码没有改变。我手动更改了它,但是编译失败了。我看到一篇帖子说我们必须等到iOS 6,但是我现在就想要索引!有没有解决办法?
1个回答

21

没问题,有一种方法可以做到!将索引方法作为 NSArray 和 NSDictionary 的分类添加进去,你就可以在大多数你想要的类中使用该特性。你可以查阅 ObjectiveC 文字字面量相关信息这里。感谢 James Webster 提供的 @YES 和 @NO 解决方案,现在你也可以在项目中正确地使用它们了!(技术操作)

1)创建接口文件

// 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) 创建实现文件 // 在执行此步骤之前请参阅下面的编辑 - 你可以跳过此步骤

// 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)将接口文件添加到您的pch文件中以进行全局使用,或根据需要将它们添加到.m文件中。

// 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) 重新构建,然后添加以下文件以验证所有功能是否正常

// 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 );
}

编辑:根据一位重要的llvm/clang苹果工程师的说法,已经有一个库与实现链接在一起,所以你只需要接口文件:

日期:2012年8月20日星期一15:16:43 -0700 发件人:Greg Parker 收件人:... 主题:回复:如何使Obj-C集合下标化在iOS 5上运行? ...

作为一个实验,我添加了这些方法的类别@接口,但没有@实现——程序仍然可以正常运行(至少在5.1模拟器中)

编译器生成相同的调用。魔法在越来越不准确地命名为libarclite(“不仅限于ARC™”)的库中,在运行时增加下标化方法的实现(如果它们不存在)。

如果我没记错,某些能够使用下标的类(例如NSOrderedSet)libarclite不会升级,因此您仍然需要在旧的部署目标上进行彻底测试。


2
如果您只为iOS6编译,可以输入系统回退(system fallback)。 (#if !defined(__IPHONE_6_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0),请参见:https://gist.github.com/3314686 - calimarkus
同时,导入也不是必要的,因为消息是在运行时创建的。编译器不会显示警告,并且类将被加载。但是,保留导入语句可能会让代码更易读。 - calimarkus
我认为只需要接口的洞见值得成为一个单独的答案(并且是正确的答案)。在扫描时,上面添加的实现块注释不会突出显示,直到我已经开始实现代码并回来检查某些内容之前,我才滚动到底部。 - big_m
1
此外,这一点可能没有意义,但是setObject: atIndexedSubscript:的代码并不完全符合NSMutableDictionary方法的描述。后者允许索引比当前最高索引大1来使数组增加1,而replaceObjectAtIndex:withObject:会抛出异常。这是我(未经测试)尝试修复它的代码:https://gist.github.com/9623156 - big_m
这篇文章现在已经快两年了,我认为它现在的用处有限。 - David H
1
我想是这样。两年并不算太久,但在这种情况下,我猜可能没有很多人仍在使用iOS 5 SDK(我仍在使用它,因为苹果的兼容性宏不再在您使用目标操作系统中不可用的内容时生成警告)。无论如何,这对我仍然有帮助!谢谢! - big_m

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接