iOS : Modifying NSFastEnumerationState to hide mutation while enumerating

356 Views Asked by At

I have a case where in my collections will be mutated while enumerating.But this is not allowed in iOS.On further investigation found that the NSFastEnumerationState is a c type struct as follows

typedef struct {
        unsigned long state;
        id *itemsPtr;
        unsigned long *mutationsPtr;
        unsigned long extra[5];
    } NSFastEnumerationState;

So state->mutationPtr denotes whether the collection was mutated or not,based on which exceptions are thrown.Can we override this to show that the collection is not mutated(even if it is mutated),So that the exceptions are not thrown.By overriding we can achieve mutation while enumeration.I don know whether this is a correct idea.Please let me know your suggestions.

1

There are 1 best solutions below

2
On

The idea is incorrect, just copy the object you are enumerating and enumerate the copy.

Edit: To address your comments, it seems that it's technically possible to achieve what you want. First thing I did is to go to the NSEnumerator documentation to check if you could basically create your own enumerator and implement a custom nextObject method to resolve the problem. This is what I found:

Note: It is not safe to modify a mutable collection while enumerating through it. Some enumerators may currently allow enumeration of a collection that is modified, but this behavior is not guaranteed to be supported in the future.

Additionally, I checked the Enumeration: Traversing a Collection’s Elements - Using an Enumerator section and I found a very similar thing:

It is not safe to remove, replace, or add to a mutable collection’s elements while enumerating through it. If you need to modify a collection during enumeration, you can either make a copy of the collection and enumerate using the copy or collect the information you require during the enumeration and apply the changes afterwards.

So if you sum this all up, it seems to me that you have 2 options:

  1. Create your custom NSEnumerator subclass and use it to do what you need.
  2. Don't use NSFastEnumeration at all and find another way to do what you need.