the swift array... do the elements stay in the order you put them?

this sounds like such a rudimentary question, but I'm trying to tarck down a problem and it keeps looping back to this.


a sketch of what I am doing:

I have an array, then I add an array to that array using the insert(contents of: method (which allows you to insert an entire array at an index.)

then somewhere downstream these elements are laid out (it's a graphics thing)

in order to lay out the items in the array, the first thing I do is filter the array, excluding elements that are laid out separately. I use the filter method:

array.filter({$0 is MyClass}) // something like that


then I layout the graphics. it's a top down layout. I start at the top of the workspace, and I increment the position of the frame of the element, subtracting the height from the y position...

newPosition = CGPoint(x: 0, y: lastPosition.y - thisItem.frame.height) // that sort of thing.


so, I rely heavily on the order of the items... not changing. But it seems to do exactly that. Now, I have a few other things to track down... this is more likely some kind of transposition error in figuring out the "real world" index to insert the new items, but it brings up a more pressing and generalised concern. I have to be certain about Arrays... is there any effort to maintain the order in an array? including when run through methods that return Other arrays such as filter?

Accepted Reply

Array elements keep their order. Deletions and insertion may change the index of elements already/still in the array, but it won't change their relative order.


The "filter" method is documented to preserve the order of the elements it keeps:


https://developer.apple.com/documentation/swift/array/2994718-filter

Replies

How do you browse the array ? With an index loop (for i in 0..<array.count) of with an item loop (for item in array).


I tested if that could be that the first guarantees order, not the second. But the simple test I did in playground seems to prove this is not the case.


Could you show the complete manipulation you do on array ?

Array elements keep their order. Deletions and insertion may change the index of elements already/still in the array, but it won't change their relative order.


The "filter" method is documented to preserve the order of the elements it keeps:


https://developer.apple.com/documentation/swift/array/2994718-filter

Hi Polyphonic,

ObjC NSArrays, generally did the same. But they explicitly warned that relying on that behavior was a bad idea, because it isn't guaranteed, and it may change without warning.


fast forward to today, I found my issue was a transcription error. But I was still faced with a "is it safe to rely on this behavior, or should I build in my own sorting property?" moment. I tried to find concrete definitive terminology in the docs before coming to the forums.


thanks for the response, it puts my mind at ease.

But they explicitly warned that relying on that behavior was a bad idea …

Ah, um, no they didn’t. Do you remember where you saw that warning? Either you’ve misinterpreted it, or there’s a bug in our docs.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

HI eskimo,

I've been working with NSArray, and the documentation about NSArray, since the release of OSX server. There have been multiple, completely new documentation systems for what eventually became "Foundation" since that point. Many additions, redactions, and completely different directions. There are indeed things I know are no longer the case, and things that are now undocumented but unchanged since they were documented. None of this makes doing the work easier.
my memory is not laid out according to which epoch of Apple documentation a particular datum was in, so... I don't know where or when I saw this warning. It was years ago however. Vaguely, I think it is associated with the advent of binding, and NSArrayController, as it seems to be tangled up in the concept behind the necessity for "arranged objects" instead of just a straight list of the contents of the array. But, that may just be an association I made. I know I came away with the impression that the thing we call an NSArray, had long since become a category, and a host of very individualized private classes and the note was generally a guide that relying on this particular feature of Arrays may not be a good idea going forward, even though it worked at that point.


my original issue (which prompted this thread) was a mismatch issue with how I was counting elements in the array. i was filtering out elements, counting that index, and then trying to insert at that index in the unfiltered array. Once I realized the index offset was predictable it was fairly easy to find.

Having the elements stay in the order you put them is kind of the defining feature of an array, across all languages in all of computer science. If there was some case where a particular NSArray instance was a “view” into some external data structure that might change, i.e. some external code might modify the array, well, that’s something different. But arrays in general *always* remain in order.

OK, this clarifies what's going on about the order.


NSArray's object order is fixed, and there's nothing to be careful of here.


NSArrayController (an unrelated class) has an "arrangedObjects" property of type NSArray. This property's array's elements are sorted by … something, it matters not here how the order is determined … and the order will change if something causes re-sorting, if the elements or sort order changes.


For UI elements that are bound to "arrangedObjects", there is typically no problem, because the re-sorting triggers a KVO update which updates the UI via bindings.


However, in code, if you refer to the "arrangedObjects" array to determine indexes where to insert or remove objects, you have to be aware that the index in "arrangedObjects" may not be the same as the index in the underlying (unsorted) array, or the same as the arranged indexes you had earlier in the app's execution. Indeed, you must use different APIs depending on which set of indexes you happen to have in hand.


So, yes, if you're using NSArrayController directly, you do have to be careful about indexes for two separate reasons — (1) re-sortability, and (2) arranged order index vs. underlying index.


This, incidentally, is a good reason to avoid using NSArrayController directly in code, but the details of what you "should" do depend on your app design scenario.