使用新的文字语法将对象推送到数组的末尾

时间:2012-10-15 07:07:46

标签: objective-c nsmutablearray objective-c-literals

PHP有:

arr[] = 'Push this onto my array';

将字符串添加到数组的末尾。

新的Objective-C文字语法中是否有相应的内容?我能想到的最简洁的方法是:

arr[arr.count] = @"Add me";

但也许那里有更好的东西?

2 个答案:

答案 0 :(得分:7)

看看the documentation for the new literal syntax。使用下标分配到数组时,调用将转换为setObject:atIndexedSubscript:方法调用:

NSMutableArray *foo = …;
foo[0] = @"bar"; // => [foo setObject:@"bar" atIndexedSubscript:0];

如果您有自己的可变数组实现,则可以在setObject:atIndexedSubscript:方法中添加一个特殊情况,以便在分配超过数组大小时增大数组。 我非常怀疑默认的NSMutableArray实现做了类似的事情,很可能你只是得到一个关于索引超出范围的例外。这确实是NSMutableArray的确如此,请参阅the reference documentation

  

如果索引等于count,则将元素添加到结尾处   数组,增长数组。

谢谢马丁的单挑!

答案 1 :(得分:0)

我实际上并不建议这样做,但Objective-C 可以使用您自己的代码扩展setObject:atIndexedSubscript:方法。这个过程叫做“方法调配”,这里解释一下:http://darkdust.net/writings/objective-c/method-swizzling

这是一些演示过程的实际工作代码。酷位位于main(),我可以使用fib[-1] = ...代替fib[fib.count] = ...。当然,这里没有巨大的优势;代码不再有效,而且肯定难以阅读。但我确实不必两次写出“fib”。

主要这种方法的缺点是Objective-C实际上并没有关于加载类别的顺序的任何规则,所以如果其他人提供了具有类似功能的类别,它会是一个人最后加载的折腾。 (如果他们恰好为他们的类别选择相同的名称,那么我认为这将是一个人们加载的折腾。)

所以,底线,不要这样做:但可能。

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

@interface NSMutableArray (NegativeOne)
+(void)load;
-(void)swizzled_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
@end

@implementation NSMutableArray (NegativeOne)

+(void)load
{
    Method original = class_getInstanceMethod(self, @selector(setObject:atIndexedSubscript:));
    Method swizzled = class_getInstanceMethod(self, @selector(swizzled_setObject:atIndexedSubscript:));
    method_exchangeImplementations(original, swizzled);
}

-(void)swizzled_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
{
    if (idx == -1)  idx = [self count];
    [self swizzled_setObject:obj atIndexedSubscript:idx];  // go use the old method: not a typo!
}

@end

int main()
{
    int x = 0, y = 1;
    NSMutableArray *fib = [NSMutableArray new];

    for (int i=0; i < 10; ++i) {
        fib[-1] = @(x);  // wowie zowie!
        int temp = x+y;  x = y;  y = temp;
    }
    NSLog(@"%@", fib);
    return 0;
}