작은 매듭을 두루 겪다.

9747 단어
demo 다운로드
첫 번째 방식: for 순환
Objective-C는 C 언어를 기반으로 하는 것으로 for 순환을 자연스럽게 사용할 수 있다
배열 반복:
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

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

//       

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

}

컴포지팅 배열은 간단합니다. 문제 없습니다. 다음 컴포지팅 사전 ** 컴포지팅 사전: **
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

NSArray *keysArray = [dict allKeys];

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

//             

NSString *key = keysArray[i];

NSString *value = dict[key];

NSLog(@"%@", value);

}

우리는 사전과 set이 순서가 없다는 것을 알고 있기 때문에 특정한 정수에 따라 그 값에 직접 접근할 수 없습니다. 따라서 사전의 키나 set의 모든 대상을 먼저 가져와야 합니다. 그러면 얻은 질서수조를 두루 훑어볼 수 있습니다.그러나 그룹을 만드는 데는 추가 비용이 들 뿐만 아니라, 하나의 그룹을 더 만들 수도 있다. 그는 콜렉션의 모든 대상을 보존하고 메모리를 차지할 것이다.
요약 장단점:
장점: 광범위하게 사용되고 받아들이기 쉬우며 조작이 간단하다.
단점: 사전과 set을 두루 훑어보는 것은 비교적 번거롭고 시스템 자원을 많이 차지한다.
두 번째 방법: NSEnumerator
NSEnumerator는 하위 클래스를 구현하는 두 가지 방법을 정의하는 추상적인 기본 클래스입니다.
- (nullable ObjectType)nextObject;

@property (readonly, copy) NSArray*allObjects;

여기서 nextObject는 열거의 다음 대상을 되돌려주는 관건적인 방법입니다.매번 방법을 바꿀 때마다 내부 구조가 업데이트되어 다음 방법을 호출할 때 다음 대상을 되돌릴 수 있습니다.매거 중의 모든 대상이 이미 되돌아온 후에 호출하면nil로 되돌아와 매거의 끝에 도달했다는 것을 나타낸다.
Foundation 프레임워크의 collection은 다음과 같은 반복 방식을 구현합니다.
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

NSEnumerator *enumerator = [iosArray objectEnumerator];//    

NSEnumerator *enumerator = [iosArray reverseObjectEnumerator];//    

id object;

while ((object = [enumerator nextObject]) != nil) {

//         

NSLog(@"%@", object);


사전과 set이 실현되는 방식은 비슷하지만 사전에는 키와value가 있기 때문에 구체적인 키에 따라value를 추출해야 한다.정방향 범람과 반방향 범람을 동시에 제공하였다.
요약 장단점:
장점: 코드가 더 읽기 쉬워서 추가 그룹을 정의할 필요가 없다.
단점: 1. 반복 작업의 하표를 직접 얻을 수 없으며 변수 기록을 따로 설명해야 한다.2. NSEnumerator 객체를 직접 작성해야 하므로 번거롭습니다.
세 번째 방식: 빠르게 훑어보기
Objective-C 2.0은 빠른 스트리밍이라는 기능을 도입했다. 빠른 스트리밍은 NSEnumerator와 차이가 많지 않지만 문법이 더욱 간결하다. for 순환에 in 키워드를 개설하여collection을 스트리밍하는 데 필요한 문법을 간소화했다. 예를 들어 스트리밍 수조:
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];

for (NSString *obj in iosArray) {

//        

NSLog(@"%@", obj);

}


사전을 두루 훑어보는 것도 마찬가지로 간단하다.
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};

for (NSString *key in dict) {

//       

NSString *value = dict[key];

NSLog(@"%@", value);

}

역방향 이동 사용 가능for (NSString *obj in [iosArray reverseObjectEnumerator])요약 장단점:
장점: 문법이 간결하고 사용이 편리하며 효율이 높다.
단점: 1、현재 훑어보는 아래 표시를 쉽게 얻을 수 없음;
2. 반복하는 과정에서 반복되는collection을 수정할 수 없습니다. 그렇지 않으면 붕괴를 초래할 수 있습니다.
네 번째 방식: 블록 기반 스트리밍 방식
이것이야말로 본고의 중점이자 필자가 극력 추천하는 방법이다. 애플은 이렇게 효율적이고 우아하며 사용하기 쉬운 인터페이스를 봉하여 놓았으니 그리 낭비할 필요가 없다.
배열 반복:
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;

}

}];

매개 변수 설명:obj는 수조의 원소를 표시하고, idx는 원소의 하표를 표시하며, stop은 언제 멈추는지 제어할 수 있으며, 정지가 필요할 때stop=YES를 명령하면 된다(앞의 *를 잊지 마라).
이런 방법은 수조원소, 하표를 직접 얻을 수 있고 언제 멈추는지도 쉽게 실현할 수 있으며break도 퇴직할 수 있고 사전을 두루 훑어보는 것도 마찬가지로 간단하다.
사전을 옮겨다니기:
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;

}

}];

잘못 보지 않았어. 이렇게 간단해. Block은 사전의 키와value를 우리에게 직접 주었어. 더 이상 직설적이고 번거로운 코드를 쓸 필요가 없어.
참고:
collection에 있는 대상의 데이터 형식을 알면 블록 서명을 수정할 수 있으며, 대상의 정확한 유형을 알면 컴파일러는 개발자가 대상이 가지고 있지 않은 방법을 호출했는지 확인하고, 문제의 타임슬립 오류를 발견할 수 있습니다.
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;

}

}];

코드와 같이 키와value의 유형을 NSString 형식으로 직접 수정합니다.역방향 이동:
역방향으로 옮겨다니는 것도 마찬가지로 편리하다. 다른 방법을 사용하면 된다.
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;

}

}];

이 방법은 정방향 스트리밍에 비해 하나의 매개 변수인 NSEnumerationReverse가 많습니다. 이 옵션을 열면 역방향으로 스트리밍할 수 있습니다.
동시 스트리밍:
이 매거 유형의 매개 변수를 따라 블록 매거의 또 다른 큰 매개 변수를 끌어낼 수 있다. 병발 반복, 매개 변수는 NSEnumerationConcurrent이다.즉,collection 중의 몇 개의 매개 변수를 동시에 훑어볼 수 있으며, 구체적인 수량은 시스템 자원에 따라 결정된다.이렇게 하면 시스템 자원을 충분히 이용하고 신속하고 효율적으로 데이터를 완성할 수 있다. 시스템 밑바닥은 GCD를 통해 병발 업무를 처리할 것이다. 개발자는 메모리와 라인을 걱정할 필요가 없다. 다른 방식으로 병발 업무를 효율적으로 처리하려면 매우 어렵다. 블록 매거진을 통해collection을 바꾸면 충돌을 일으키지 않는다. 코드는 다음과 같다.

    NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"];
    
    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(@"thread = %@,obj = %@",[NSThread currentThread],obj);
        
        if ([obj isEqualToString:@"_V"]) {
            
            *stop = YES;
        }
    }];
    

동시 스트리밍임을 어떻게 증명합니까? 여러 번의 실행을 통해 프린트 결과는 다음과 같습니다. f([obj isEqual Tostring:@"V"]){*stop = YES;},그러나 데이터가 모두 범람되었다. 그것은 여러 라인을 열었기 때문이다. 인쇄된 숫자의 순서도 다르고 여러 라인을 열었음을 검증할 수 있다.
------------------------------   -----------------------
2017-02-13 16:08:55.879 traverse[7243:582574] thread = {number = 1, name = main},obj = _L
2017-02-13 16:08:55.880 traverse[7243:582574] thread = {number = 1, name = main},obj = _I
2017-02-13 16:08:55.880 traverse[7243:582574] thread = {number = 1, name = main},obj = _O
2017-02-13 16:08:55.880 traverse[7243:582574] thread = {number = 1, name = main},obj = _S
2017-02-13 16:08:55.879 traverse[7243:582623] thread = {number = 3, name = (null)},obj = _O
2017-02-13 16:08:55.879 traverse[7243:582625] thread = {number = 4, name = (null)},obj = _V
2017-02-13 16:08:55.880 traverse[7243:582622] thread = {number = 5, name = (null)},obj = _E
2017-02-13 16:08:55.881 traverse[7243:582574] iosMutableArray = (
    "_L",
    "_O",
    "_V",
    "_E",
    "_I",
    "_O",
    "_S"
)

------------------------------   -----------------------

2017-02-13 16:11:59.023 traverse[7265:585825] thread = {number = 1, name = main},obj = _L
2017-02-13 16:11:59.023 traverse[7265:585825] thread = {number = 1, name = main},obj = _I
2017-02-13 16:11:59.023 traverse[7265:585892] thread = {number = 5, name = (null)},obj = _E
2017-02-13 16:11:59.024 traverse[7265:585825] thread = {number = 1, name = main},obj = _O
2017-02-13 16:11:59.023 traverse[7265:585889] thread = {number = 3, name = (null)},obj = _O
2017-02-13 16:11:59.023 traverse[7265:585890] thread = {number = 4, name = (null)},obj = _V
2017-02-13 16:11:59.024 traverse[7265:585892] thread = {number = 5, name = (null)},obj = _S
2017-02-13 16:11:59.026 traverse[7265:585825] iosMutableArray = (
    "_L",
    "_O",
    "_V",
    "_E",
    "_I",
    "_O",
    "_S"
)

장단점 요약:
이점:
1. for순환의 모든 기능을 완벽하게 실현할 수 있다.
2. 집합 중의 모든 요소를 쉽게 얻을 수 있다.
3. 역순으로 순환하는 매개 변수를 제공하고 NSEnumerationReverse는 역순으로 순환하는 데 사용된다.NSEnumerationConcurrent는 두 매개변수를 동시에 사용할 수 있는 동시 스트리밍을 위해 사용됩니다.
4. 이런 순환 방식은 효율이 높고 프로그램 성능을 향상시킬 수 있으며 개발자는 업무 논리에 전념할 수 있으며 메모리와 라인의 문제를 걱정할 필요가 없다.
5. NSEnumerationConcurrent 옵션을 열 때 for 순환과 쉽게 실현할 수 없는 병행 순환 기능을 신속하게 누적할 수 있다. 시스템 밑바닥은 GCD를 통해 병행 업무를 처리하고 시스템과 하드웨어 자원을 충분히 활용하여 가장 좋은 병행 효과를 얻을 수 있다.
6. 블록 서명을 수정할 수 있다. 우리가 집합 중의 요소 유형을 명확히 했을 때 기본 서명 id 유형을 이미 알고 있는 유형으로 수정할 수 있다. 예를 들어 흔히 볼 수 있는 NSString을 사용하면 시스템 자원 비용을 절약할 수 있을 뿐만 아니라 대상에게 존재하지 않는 방법으로 충돌을 방지할 수 있다.
단점:
1. 많은 개발자들이 이런 스트리밍 방식을 모른다.
2. 여기에 Block을 사용했는데 Block에서 쉽게 발생하는 보존링 문제에 주의해야 한다. 예를 들어self 호출 방법을 사용할 때self를 인용하면 보존링을 깨뜨릴 수 있다.예:weak __typeof(self) weakSelf = self 또는weak MyController *weakSelf = self; Block에서 weakSelf를 사용하면 됩니다.
참고:
블록 기반 스트리밍을 사용할 때 스트리밍된 원소를 수정할 수 있어 붕괴를 초래하지 않는다. 그러나 스트리밍된 원소를 삭제하면 뒤의 원소가 스트리밍하지 못하고 붕괴될 수 있다. 해결 방법은 2가지가 있다. 1. 하나는 원래 집합된 부본을 복제하고 부본을 조작하여 조작할 원소를 찾아낸 후에 원래 집합을 처리하는 것이다.2. 원소를 삭제한 후 붕괴되지 않도록 역방향으로 옮겨다니기를 사용한다.출처:http://www.jianshu.com/p/d6ef96c862ca

좋은 웹페이지 즐겨찾기