objective c - Fast Enumeration over NSMutableArray problems -


i having issues trying wrap head around why can not mutate collection during enumeration... apparently, if doing sort of fast enumeration, system should throw exception if try mutate. below have 3 examples mutating during enumeration. 1 simple c-style loop, , other 2 use form of fast-enumeration. getting enumeration exceptions thrown case 2. shouldn't getting exceptions thrown case 1? why case 1 valid? also, people throughout stack overflow case 3 bad practice, why? simple , seems work. inconsistency in how 2 different fast-enumeration loops behaving , general disgust c-style loop screwing understanding here. instead of vague generic rules of thumb, if can break down science help. fundamental level want know why exceptions not consistent here , why case 3 works me when apparently "shouldn't" or "bad practice."

//case 1: nsmutablearray *array = [nsmutablearray arraywithobjects:@"phuj", @"whub", @"adgh", nil]; [array enumerateobjectsusingblock:^(id obj, nsuinteger idx, bool *stop) {         [array removeobjectatindex:idx]; }];  //case 2: nsmutablearray *array = [nsmutablearray arraywithobjects:@"phuj", @"whub", @"adgh", nil]; (nsstring *string in array) {     [array removeobject:string]; }  //case 3: nsmutablearray *array = [nsmutablearray arraywithobjects:@"phuj", @"whub", @"adgh", nil]; (int = 0; < [array count]; i++) {     [array removeobjectatindex:i]; } 

we love simple , straightforward code.

i won't talk case 2, because throws exception , can't mutate array in it.

i want start example, suppose want remove "whub" item mutable array , content of array "phuj, whub, whub, adgh", has 2 whub see.

let's start write code using c style loop:

for (int = 0; < [marray1 count]; i++) {     nsstring *str = marray1[i] ;     if ([str isequaltostring:@"whub"]) {         [marray1 removeobjectatindex:i] ;     } } 

the code has bug, after removes first "whub", indexes of item located after decrease 1, index of second whub should 1 , i 1 @ moment. in next loop, i 2, skips second whub. can change code make correct.

for (int = 0; < [marray1 count]; i++) {     nsstring *str = marray1[i] ;     if ([str isequaltostring:@"whub"]) {         [marray1 removeobjectatindex:i] ;         --i ;     } } 

it works, it's not straightforward, modify index i , makes code complex.

let's try write code using enumerateobjectsusingblock method case 1:

nsmutablearray *array = [nsmutablearray arraywithobjects:@"phuj", @"whub", @"whub", @"adgh", nil] ; [array enumerateobjectsusingblock:^(id obj, nsuinteger idx, bool *stop) {     if ([obj isequaltostring:@"whub"]) {         [array removeobjectatindex:idx] ;     } }]; 

if build , run it, find result array still contains 1 "whub" , time, can't modify index fix it.

conclude: talk can mutate array in loop, fact can mutate array doesn't mean correct answer. in fact, c style loop can ever want, won't crash, bad because have better way go. in practice, we'd use simple code achieve target, others can understand easily, ourselves can benefit it.

i'd use way, think simple , straightforward.

nsmutablearray *arrayremove = [nsmutablearray array] ; (nsstring *str in marray1) {     if ([str isequaltostring:@"whub"]) {         [arrayremove addobject:str] ;     } } [marray1 removeobjectsinarray:arrayremove] ; 

Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -