7

PHPには次のものがあります。

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

文字列が配列の末尾に追加される場所。

新しいObjective-Cリテラル構文にこれに相当するものはありますか? 私が考えることができる最も簡潔な方法は次のとおりです。

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

しかし、多分そこにもっと良いものがありますか?

4

2 に答える 2

7

新しいリテラル構文のドキュメントを参照してください。setObject:atIndexedSubscript:添え字を使用して配列に割り当てると、呼び出しはメソッド呼び出しに変換されます。

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

独自の変更可能な配列の実装がある場合は、setObject:atIndexedSubscript:メソッドに特別なケースを追加して、配列サイズを超えて割り当てるときに配列を大きくすることができます。デフォルトのNSMutableArray実装がそのようなことを行うとは思えません。おそらく、インデックスが範囲外であるという例外が発生するだけでしょう。そして、これは実際に行うことです。参照ドキュメントNSMutableArrayを参照してください。

インデックスが count と等しい場合、要素が配列の最後に追加され、配列が大きくなります。

ヘッズアップしてくれてありがとう、マーティン!

于 2012-10-15T07:21:08.717 に答える
0

I don't actually recommend doing this, but Objective-C does make it possible to extend the setObject:atIndexedSubscript: method with your own code. The process is called "method swizzling", and it's explained here: http://darkdust.net/writings/objective-c/method-swizzling

Here's some actual working code that demonstrates the process. The cool bit is in main(), where I'm able to use fib[-1] = ... instead of fib[fib.count] = .... Of course there's no huge advantage here; the code is no more efficient, and certainly harder to read. But I do save having to write out "fib" twice.

A major disadvantage of this approach is that Objective-C doesn't really have any rules about the order in which categories get loaded, so if somebody else provided a category with similar functionality, it would be a toss-up which one got loaded last. (And if they happened to choose the same name for their category, it would be a toss-up which one got loaded at all, I think.)

So, bottom line, don't do this: but it is possible.

#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;
}
于 2012-10-26T19:46:45.633 に答える