Summary of the Method of iOS Traversing Sets of NSArray NSDictionary NSSet

  • 2021-11-24 03:05:36
  • OfStack

Preface

Set traversal is one of the most common operations in development. From the classic for loop of C language to traversal using the advantages of multi-core cpu, there are several set traversal methods in development of ios. This paper compares the efficiency and advantages of each operation method through research and test, and summarizes several small skills of using set traversal.

Think of looping through common collections such as arrays and dictionaries, The first reaction in everyone's mind is for cycle and fast traversal, and these methods are used with relish. These are enough to meet all the similar needs in development, and there seems to be nothing to summarize. In fact, if you don't believe in looking down, don't waste time if you know the great God.

Mode 1: for loop

Objective-C is based on the C language, so it is natural to use the for loop

Traversing an array:


NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

for (int i = 0; i < iosArray.count; i++) {

// Processing data in an array 

NSLog(@"%@", iosArray[i]);

}

Traversing the array is very simple. No problem. Traversing the dictionary below

Traversing the dictionary:


NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

NSArray *keysArray = [dict allKeys];

for (int i = 0; i < keysArray.count; i++) {

// Processes each in the dictionary according to the key value 1 Items 

NSString *key = keysArray[i];

NSString *value = dict[key];

NSLog(@"%@", value);

}

We know that dictionaries and set are unordered, so we can't directly access the values according to specific integer subscripts, so we need to get the keys in the dictionary or all the objects in set first, so that we can traverse on the obtained ordered array. However, creating an array requires extra overhead, and one more array object will be created, which will retain all the objects in collection and occupy memory.

Summarize the advantages and disadvantages:

Advantages: Widely used, easy to accept and simple to operate;

Disadvantages: Traversing dictionaries and set is cumbersome and takes up more system resources.

Mode 2: NSEnumerator

NSEnumerator is an abstract base class that defines two methods so that its subclasses implement:


- (nullable ObjectType)nextObject;

@property (readonly, copy) NSArray*allObjects;

nextObject is the key method, which returns the next 1 object in the enumeration. Every time a method is called, its internal structure is updated so that the next object can be returned when the next method is called. After all the objects in the enumeration have been returned, nil will be returned on the call, indicating that the end of the enumeration has been reached.

collection in the Foundation framework implements this traversal, for example:


NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

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);

}

The dictionary and set are implemented in a similar way, but the difference is that there are key and value in the dictionary, and value should be extracted according to the specific key. Both forward traversal and reverse traversal are provided.

Summarize the advantages and disadvantages:

Advantages: The code is easier to read and does not need to define additional arrays;

Disadvantages: 1. It is impossible to directly obtain the subscript of traversal operation, and it is necessary to declare variable records separately;

2. It is a little troublesome to create NSEnumerator objects by yourself.

Mode 3: Fast traversal

Objective-C 2.0 introduces the function of fast traversal, which is similar to NSEnumerator, but the syntax is more concise. It opens in keyword for for loop, which simplifies the syntax required to traverse collection, such as traversing arrays:


NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

for (NSString *obj in iosArray) {

// Working with data in an array 

NSLog(@"%@", obj);

}

Traversing the dictionary is equally simple:


NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

for (NSString *key in dict) {

// Dealing with dictionary key values 

NSString *value = dict[key];

NSLog(@"%@", value);

}

Reverse traversal can be used for (NSString *obj in [iosArray reverseObjectEnumerator])

Summarize the advantages and disadvantages:

Advantages: concise grammar, convenient use and high efficiency;

Disadvantages: 1. It is impossible to obtain the subscript of the current traversal conveniently;

2. The traversed collection cannot be modified during traversal, otherwise it will cause crash.

Mode 4: Block-based traversal mode

This is the focus of this article, and it is also the method highly recommended by the author. Apple has packaged such an efficient, elegant and easy-to-use socket without much waste.

Traversing an array:


NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

[iosArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

NSLog(@"%@", obj);

if ([obj isEqualToString:@"E"]) {

*stop = YES;

}

}];

Parameter description: obj represents the element in the array, idx represents the subscript of the element, * stop can control when the traversal stops, when it needs to stop *stop = YES That's enough (don't forget the previous *).

This method is clear and clear, array elements and subscripts can be obtained directly, even when to stop is easy to realize, break can be retired, and traversing dictionaries is equally simple.

Traversing the dictionary:


NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

[dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {

NSLog(@"%@", obj);

if ([obj isEqualToString:@"22"]) {

*stop = YES;

}

}];

You are not mistaken, it is as simple as that. block directly gave us key and value of the dictionary, and no longer had to write straightforward and tedious code.

Note:

If the data type of the object in collection is known, the block signature can be modified. After knowing the exact type of the object, the compiler can detect whether the developer called a method that the object does not have, and report an error when problems are found.


NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

[dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL * _Nonnull stop) {

NSLog(@"%@", obj);

if ([obj isEqualToString:@"22"]) {

*stop = YES;

}

}];

Such as code, directly modify the types of key and value to NSString.

Reverse traversal:

Reverse traversal is also convenient, just call another method:


NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

[iosArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {

NSLog(@"%@", obj);

if ([obj isEqualToString:@"E"]) {

*stop = YES;

}

}];

This method has one more enumeration type parameter NSEnumerationReverse than forward traversal, so you can reverse traversal by turning on this option.

Concurrent traversal:

Following the parameters of this enumeration type leads to another major advantage of block enumeration: concurrent traversal. The parameter is NSEnumerationConcurrent, which means that several elements in collection can be traversed at the same time, depending on system resources. This will make full use of system resources and complete collection traversal efficiently and quickly. The bottom layer of the system will handle concurrent matters through GCD. Developers do not need to worry about memory and threads. It is difficult to achieve efficient concurrent traversal by 10 points in other ways. Through block enumeration traversal, changing collection does not cause a crash. The code is as follows:


NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

NSArray *keysArray = [dict allKeys];

for (int i = 0; i < keysArray.count; i++) {

// Processes each in the dictionary according to the key value 1 Items 

NSString *key = keysArray[i];

NSString *value = dict[key];

NSLog(@"%@", value);

}
0

Summary of advantages and disadvantages:

Advantages:

1. All functions of for cycle can be perfectly realized;

2. It is convenient to obtain every element in the collection;

3. The parameters of loop traversal are provided, and NSEnumerationReverse is used to realize reverse loop. NSEnumerationConcurrent is used to realize concurrent traversal, and two parameters can be used at the same time;

4. This loop is efficient and can improve program performance. Developers can focus on business logic without worrying about memory and threads;

5. When the NSEnumerationConcurrent option is turned on, the concurrent loop function that for loop and fast traversal cannot be easily realized can be realized. The bottom layer of the system will handle concurrent matters through GCD, which can make full use of system and hardware resources and achieve the best traversal effect;

6. The block signature can be modified. When we have made clear the element type in the collection, we can modify the default signature id type to a known type, such as the common NSString, which can not only save the system resource overhead, but also prevent the crash caused by mistakenly sending nonexistent methods to objects.

Disadvantages:

1. Many developers don't know this traversal method;

2. block is used here, so it is necessary to pay attention to the reserved ring problem easily caused in block. For example, when using self to call methods, self can be converted into a reserved ring that can be broken if referenced. Such as: __weak __typeof(self)weakSelf = self Or __weak MyController *weakSelf = self; Use weakSelf in block.

Note:

Using block-based traversal can modify traversal elements, which will not lead to collapse. However, if you want to delete traversal elements, it will lead to the collapse of subsequent elements that cannot be traversed. There are two solutions, 1, 1 is to copy a copy of the original set, operate on the copy, find out the elements to be operated, and then deal with the original set; 2. Use reverse traversal, which will not cause crash after deleting elements.

Summarize

When we were ignorant students, When we don't know what a program is and what development is, we have a question: Why is Apple's device configuration parameter not high and it runs smoothly? Looking at the win machine configured against the sky, the huge and heavy body, the buzzing fan, the hot temperature, the plummeting power and the ugly appearance, we are even more curious about how Apple can achieve beauty and performance. Now we can see some reasons from a simple traversal that users can't even notice. One subtle point is that Apple pursues efficiency and elegance. This is just the tip of the iceberg, but we have already seen a great spirit of pursuing perfection. We are lucky to be Apple developers, and thank God for giving mankind such a great company as Apple.


Related articles: