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.