Summary of Traversal Methods in iOS

  • 2021-12-13 17:23:06
  • OfStack

In iOS development, you can use a variety of methods to traverse elements, including the following:

Classical for cycle


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
for (int i = 0; i < iosArray.count; i++) {
  // Processing data in an array 
  NSLog(@"%@", iosArray[i]);
}

NSEnumerator traversal


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
NSEnumerator *enumerator = [iosArray objectEnumerator];// Forward traversal 
// NSEnumerator *enumerator = [iosArray reverseObjectEnumerator];// Reverse traversal 

id object;

while ((object = [enumerator nextObject]) != nil) {
  // Working with data in an enumerator 
  NSLog(@"%@", object);
}

for-in Fast Traversal


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
for (NSString *obj in iosArray) {
  // Working with data in an array 
  NSLog(@"%@", obj);
}

EnumeratorBlock traversal


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
[iosArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  NSLog(@"%@", obj);
  if ([obj isEqualToString:@"e"]) {
    *stop = YES;  //  Jump traversal 
  }
}];

In addition, EnumeratorBlock also supports reverse traversal and concurrent traversal. Concurrent traversal can use multi-core optimization to make full use of system resources.

Reverse traversal


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
[iosArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
  NSLog(@"%@", obj);
  if ([obj isEqualToString:@"e"]) {
    *stop = YES;
  }
}];

Concurrent traversal


NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
NSMutableArray *iosMutableArray = [NSMutableArray arrayWithArray:iosArray];
[iosMutableArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
  obj = [NSString stringWithFormat:@"_%@", obj];
  [iosMutableArray replaceObjectAtIndex:idx withObject:obj];
  NSLog(@"%@", obj);

  if ([obj isEqualToString:@"_I"]) {
    *stop = YES;
  }
}];

dispatch_apply traversal

dispatch_apply is similar to the for loop. It should be noted here that dispatch_apple is a synchronous call, which returns a result after the call, and because it is implemented by GCD, concurrent queues or serial queues can be used. The code is as follows:


dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
//  dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL); //  Serial queue 
dispatch_apply(array.count, queue, ^(size_t i) {
  Enumerate *enumerate = [array objectAtIndex:i];
  NSLog(@"number: %ld", enumerate.number);
});

Considerations for traversal

Do not modify arrays in an for loop

You can't delete traversed elements casually in the traversal process. If you need to delete elements, you can copy 1 copy first. For example, the following code will have problems:


NSMutableArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"];
for (NSString *obj in iosArray) {
  // Working with data in an array 
  if([@"e" isEqualTo:obj]) {
    [iosArray removeObject:obj];
  }
}

However, removeObject operation can be done inside block by using enumerateBlock. The reason should be related to the characteristics of Block. In Block, the value of variables will be saved and will not change with the change of the value of variables.

Rate of traversal

When the array capacity is very large, if you only traverse the array, using for-in is the fastest, followed by concurrent traversal, which many people think enumerateBlock is the fastest.

Traversal practice tips

Array grouping

In development, it is sometimes necessary to group arrays in some cases, for example, an array with many message models, and we need to group messages according to the month when they were created, so we can use the following methods:


NSMutableSet *set=[NSMutableSet set];
NSArray *array = @[message1, message2, message3, message4, message5, message6, message7];
__block NSArray *tempDataArray = [NSArray arrayWithArray:array];
[tempDataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  [set addObject:obj.month];// Utilization set The characteristic of non-repetition , Get how many groups there are , According to the month attribute of the message in the array 
}];
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {// Traversal set Array 
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.month = %@", obj];// To create a verb filter 
  NSArray *group = [tempDataArray filteredArrayUsingPredicate:predicate];// Using the filtering method of array to get a new array , In the final array added 
}

Reverse traversal

Reverse traversal is also common, which can be realized by using the above reverse traversal.

set sort

This has nothing to do with Emunerate, but it is also very practical. We know that set is unordered, but sometimes it is necessary to implement ordered set, which can be implemented by the following:


// Due to set Disorder, now will set Convert to nsarray
NSArray *sortDescriptor = @[[[NSSortDescriptor alloc] initWithKey:@"self" ascending:NO]];
NSArray *sortSetArray = [set sortedArrayUsingDescriptors:sortDescriptor];

In fact, the principle is to transform set into array.

Summarize

Traversal is common in our daily development. According to the application scenario, choosing the appropriate traversal method is what we need. This article summarizes the types of traversal and matters needing attention, hoping to help students in need.


Related articles: