Push object to end of array using new literal syntax

PHP has:

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

If the string will be added to the end of the array.

Is there any equivalent to this in the new Objective-C literal syntax? The most concise way I can do this is:

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

but maybe there is something better?

+6
source share
2 answers

Take a look at the documentation for the new literal syntax . When you assign to an array using an index, the call is converted to a call to the setObject:atIndexedSubscript: method:

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

If you had your own implementation of a mutable array, you can add a special case to the setObject:atIndexedSubscript: method to increase the array when assigning the size of the array. I very much doubt that the default implementation of NSMutableArray does something like this, most likely you will just get an exception from the index that goes beyond. And this is really what NSMutableArray does, see the reference documentation :

If the index is equal to the count, the element is added to the end of the array, increasing the array.

Thank Martin for the heads up!

+7
source

I really do not recommend doing this, but Objective-C allows you to extend the setObject:atIndexedSubscript: method using native code. This process is called the "swizzling method" and it is explained here: http://darkdust.net/writings/objective-c/method-swizzling

Here is the actual working code demonstrating this process. The cold bit is in main() , where I can use fib[-1] = ... instead of fib[fib.count] = ... Of course, there is no huge advantage; the code is no more efficient and certainly harder to read. But I still need to record " fib " twice.

The main drawback of this approach is that Objective-C doesnโ€™t actually have rules on the order in which categories are loaded, so if someone else provided a category with similar functionality, it would be dreary which one was last loaded. (And if they accidentally chose the same name for their category, I would think that it would be a throw that loaded at all.)

So, on the bottom line, do not 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; } 
0
source

Source: https://habr.com/ru/post/927714/


All Articles