2012-10-15 10 views

Odpowiedz

7

Spójrz na the documentation for the new literal syntax. Po przypisaniu do tablicy za pomocą indeksu, połączenie zostanie przetłumaczony na wezwanie setObject:atIndexedSubscript: metoda:

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

Jeśli miał swoją własną implementację zmienny tablicy, można dodać szczególny przypadek metody rosnąć tablicę setObject:atIndexedSubscript: przy przypisywaniu przeszłości do rozmiaru tablicy. Bardzo wątpię, że domyślna implementacja NSMutableArray robi coś podobnego, prawdopodobnie dostaniesz wyjątek dotyczący tego, że indeks jest poza zasięgiem. I to jest rzeczywiście to, co robi NSMutableArray patrz the reference documentation:

Jeśli indeks jest równy liczyć element zostanie dodany do końca tablicy , rosnące tablicę.

Dziękuję Martinowi za heads-up!

+3

Opcja 'dokumentacji NSMutableArray' dla' setObject: atIndexedSubscript: 'jawnie stwierdza:„ Jeśli indeks jest równy 'count' element zostanie dodany do końca tablicy, rosnące tablicę” –

0

Nie polecam tego, ale Objective-C ma umożliwia rozszerzenie metody setObject:atIndexedSubscript: o własny kod. Proces ten jest nazywany "metodą swizzling" i jest wyjaśniony tutaj: http://darkdust.net/writings/objective-c/method-swizzling

Oto trochę rzeczywistego działającego kodu, który demonstruje proces. Chłodnym bitem jest main(), gdzie mogę użyć fib[-1] = ... zamiast fib[fib.count] = .... Oczywiście nie ma tu dużej przewagi; kod nie jest bardziej wydajny i na pewno trudniejszy do odczytania. Ale nie muszę zapisywać "fib" dwa razy. Wadą tego podejścia jest to, że Objective-C tak naprawdę nie ma żadnych reguł dotyczących kolejności ładowania kategorii, więc gdyby ktoś inny dostarczył kategorię o podobnej funkcjonalności, byłby to rzut monetą. w górę, który został załadowany jako ostatni. (A jeśli oni się wybrać tę samą nazwędla ich kategorii, to byłoby to wrzucić-up, który z nich został załadowany w ogóle, myślę.)

Więc dolnej linii, nie rób tego, lecz możliwe jest .

#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; 
} 
Powiązane problemy