0

I'm a little confused about NSArray initialization. The confusing thing is we have different init methods to init it, and if I just init it without giving any size and any objects, how compiler knows it object count or size in RAM. What's the logic/difference behind init method? Can anybody explain it briefly?

Edit:

NSArray *sortedArray = [[NSArray alloc] init];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc]   initWithKey:@"quota" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor];
//How is that possible to modifying to immutable object
sortedArray = [sortedContainers sortedArrayUsingDescriptors:sortDescriptors];

I know the differences between NSArray and NSMutableArray and I'm not looking for the differences. I just wonder how that code can compile/execute without an error.

5
  • 1
    Method init came from NSObject. For NSArray it's totally useless. Commented May 5, 2015 at 13:16
  • so there is no purpose or benefit using init? Commented May 5, 2015 at 13:40
  • @Cy-4AH It's not useless at all. It's just empty. An empty array is a fairly normal thing to return. Commented May 5, 2015 at 13:40
  • @RobNapier, you can return @[] if you need empty erray. Commented May 5, 2015 at 13:46
  • @Cy-4AH In very modern ObjC, yes. But that's just syntactic sugar and is quite new in any case. Before array literals were added, [[NSArray alloc] init] and [NSArray array] were pretty common. That said, in the example above, it is incorrectly used. Commented May 5, 2015 at 14:04

2 Answers 2

5

[[NSArray alloc] init] returns an empty, immutable array. There's nothing surprising about that. What else would you return from a method to mean "no items?"

how compiler knows it object count or size in RAM

The object count is 0. It's empty. Its size in RAM is the size of an empty NSArray. NSArray is an object, so it has some standard objc_object overhead, plus some instance variables for NSArray.

That said, as an implementation detail, Cocoa optimizes this out and always returns the same singleton for all empty NSArray objects. You can demonstrate this with:

NSArray *a = [[NSArray alloc] init];
NSArray *b = [[NSArray alloc] init];
NSLog(@"%p", a);
NSLog(@"%p", b);
if (a == b) { // Pointer equality, not isEqual:
    NSLog(@"Same object");
}

So, what is this doing?

NSArray *sortedArray = [[NSArray alloc] init]; // (1)
// ... code that doesn't matter ...
sortedArray = [sortedContainers sortedArrayUsingDescriptors:sortDescriptors]; // (2)

At line 1, you're creating a local pointer variable, sortedArray and pointing it to an empty array (it happens to be a singleton, but that's an optimization detail).

At line 2, you create a completely different NSArray by calling sortedArrayUsingDescriptors:. You then point sortedArray at that object. ARC sees that you're no longer pointing at the empty array, and releases it. (Again, optimization details jump in here and the actual steps may be different, but the effect will be the same.)

The correct code here would be:

// ... Code that sets up sortDescriptors ...
NSArray *sortedArray = [sortedContainers sortedArrayUsingDescriptors:sortDescriptors]; 

Now, in very modern ObjC, you won't see [[NSArray alloc] init] written out very often. It's easier to write @[] (which is really just syntactic sugar for a method call). But before array literals were added to language, [[NSArray alloc] init] or [NSArray array] were reasonably common.

Sign up to request clarification or add additional context in comments.

4 Comments

so how this code executed without an error. NSArray *sortedArray = [[NSArray alloc] init]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"quota" ascending:NO]; NSArray *sortDescriptors = [NSArray arrayWithObject:descriptor]; sortedArray = [sortedContainers sortedArrayUsingDescriptors:sortDescriptors];
with no size how could it returns an array?
Your code is creating and throwing away an empty array; I'm not sure why you're doing that. You probably want to make more clear your confusion in the question rather than in comments.
I think I get the idea behind it. This code firstly allocate an empty array and then other line changes its pointer with and non-empty array is that right?
0

If you just init NSArray without giving any size and any objects it will remain empty during lifetime. NSArray is immutable

If your question is about NSMutableArray, read here at the SO

2 Comments

I know it's immutable so what can be the purpose to init it? Why or when do we need it?
There are useful -arrayByAddingObject:(id)anObject and -arrayByAddingObjectsFromArray: methods to get new NSArray from existing one

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.