2012-10-15 31 views

Trả lời

7

Hãy xem the documentation for the new literal syntax. Khi bạn gán vào một mảng sử dụng một số phụ, cuộc gọi được dịch sang cuộc gọi setObject:atIndexedSubscript: phương pháp:

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

Nếu bạn đã có riêng thực hiện mảng có thể thay đổi, bạn có thể thêm một trường hợp đặc biệt để các setObject:atIndexedSubscript: phương pháp để phát triển mảng khi ấn định kích thước mảng. Tôi rất nghi ngờ việc triển khai mặc định NSMutableArray thực hiện bất kỳ điều gì giống như vậy, có thể bạn sẽ chỉ có ngoại lệ về chỉ mục nằm ngoài giới hạn. Và điều này thực sự những gì NSMutableArray làm là, xem the reference documentation:

Nếu chỉ số này tương đương với đếm phần tử được thêm vào cuối mảng , phát triển mảng.

Cảm ơn Martin đã cảnh giác!

+3

Lệnh 'tài liệu NSMutableArray' cho' setObject: atIndexedSubscript: 'explicitely khẳng định: " Nếu chỉ số này bằng 'count' nguyên tố này sẽ được thêm vào cuối mảng, phát triển mảng" –

0

Tôi không thực sự khuyên bạn nên làm điều này, nhưng Mục tiêu-C không giúp bạn có thể mở rộng phương thức setObject:atIndexedSubscript: bằng mã của riêng bạn. Quá trình này được gọi là "phương pháp nổi loạn" và được giải thích ở đây: http://darkdust.net/writings/objective-c/method-swizzling

Đây là một số mã thực tế thể hiện quá trình này. Các bit mát mẻ là trong main(), nơi tôi có thể sử dụng fib[-1] = ... thay vì fib[fib.count] = .... Tất nhiên không có lợi thế lớn ở đây; mã không hiệu quả hơn và chắc chắn khó đọc hơn. Nhưng tôi tiết kiệm phải viết ra "fib" hai lần.

A chính bất lợi của cách tiếp cận này là Mục tiêu-C không thực sự có bất kỳ quy tắc nào về thứ tự các danh mục được tải, vì vậy nếu ai đó cung cấp danh mục có chức năng tương tự, nó sẽ là một cái nào được tải cuối cùng. (Và nếu chúng xảy ra để chọn cùng một tên cho danh mục của chúng, nó sẽ là một thứ mà bạn có thể tải, tôi nghĩ vậy.)

Vì vậy, dòng dưới cùng, đừng làm điều này: nhưng nó có thể là .

#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; 
} 
Các vấn đề liên quan