source

NSAray를 통해 어떻게 반복해야 하나요?

nicesource 2023. 4. 19. 23:14
반응형

NSAray를 통해 어떻게 반복해야 하나요?

NSAray를 반복할 때 쓰는 표준 관용어를 찾고 있어요내 코드는 OS X 10.4+에 적합해야 합니다.

10.5+/iOS에서는 일반적으로 권장되는 코드입니다.

for (id object in array) {
    // do something with object
}

이 구성은 프로토콜을 준수하는 컬렉션의 개체를 열거하는 데 사용됩니다.이 접근방식은 여러 오브젝트에 대한 포인터를 버퍼에 저장하고(1개의 메서드콜을 통해 취득) 포인터 연산을 사용하여 버퍼를 통과하여 반복하기 때문에 속도상의 이점이 있습니다.이것은 전화보다 훨씬 빠르다.-objectAtIndex:매번 루프를 통과합니다.

또한 기술적으로는 for-in 루프를 사용하여 다음 단계를 밟을 수 있습니다.NSEnumerator이것에 의해, 고속 열거의 속도상의 메리트가 거의 무효가 되는 것을 알았습니다.는 디폴트 " " " 입니다.NSEnumerator실실의 -countByEnumeratingWithState:objects:count:는 각 콜의 버퍼에 오브젝트를 1개만 배치합니다.

는 이것을 에에에 했습니다.radar://6296108(NSEnumerator: 고정되지 않음).그 이유는 고속 열거는 오브젝트 그룹을 프리페치하기 때문에 열거자의 특정 포인트(예를 들어 특정 오브젝트가 발견되거나 조건이 충족될 때까지)에만 열거하고 루프에서 분리된 후 동일한 열거자를 사용하는 경우 여러 오브젝트를 건너뛸 수 있습니다.

OS X 10.6/iOS 4.0 이상으로 코딩하는 경우 블록 기반 API를 사용하여 어레이 및 기타 컬렉션을 열거할 수도 있습니다.

[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    // do something with object
}];

이 경우에도 하실 수 있습니다.-enumerateObjectsWithOptions:usingBlock:NSEnumerationConcurrent "/"/"NSEnumerationReversearguments.로합니다.


10.4 이전

5 는 10.5를 요.NSEnumerator의 루프, 있습니다.

NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
  // do something with object
}

심플하게 하는 것을 추천합니다.을 묶는 , 「어레이 타입」을 사용하면 됩니다.-objectAtIndex:10에는 큰 가 없습니다 Enumeration은 실제로 을 삭제합니다). 10.5+는, 10.5+의 경우이다( 「Fast Enumeration섣부른 최적화는 결코 좋은 생각이 아닙니다.어차피 병목현상이 아닌 문제를 해결하기 위해 코드를 더 복잡하게 만듭니다.

를 사용하면 다른 열거형 컬렉션(예:NSSet 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」의키,NSDictionary또는 로 전환하여 다른 코드 변경 없이 배열을 거꾸로 열거할 수도 있습니다.반복 코드가 메서드에 있는 경우, 어떤 경우에도NSEnumerator그리고 그 코드는 그것이 무엇을 반복하는지에 대해 신경 쓸 필요도 없습니다.또,NSEnumerator(적어도 Apple 코드에 의해 제공되는 것)은 오브젝트가 더 많은 한 열거된 컬렉션을 유지하므로 자동 리뉴얼된 오브젝트가 얼마나 오래 존재할지에 대해 걱정할 필요가 없습니다.

아마도 가장 큰 것은NSEnumerator(또는 고속 열거)는 열거하는 동안 사용자가 모르는 사이에 변경 가능한 컬렉션(어레이 또는 기타)이 사용자 아래에 있는 것을 방지합니다.인덱스로 개체에 액세스하면 문제가 발생한 후 오랜 시간 후에 디버깅하기 어려운 이상한 예외 또는 오프 바이 원 오류가 발생할 수 있습니다.표준 관용구 중 하나를 사용한 열거에는 "fail-fast" 동작이 있기 때문에 변환이 발생한 후 다음 개체에 액세스하려고 하면 (잘못된 코드로 인해) 문제가 즉시 나타납니다.프로그램이 더 복잡해지고 멀티 스레드화되거나 심지어 서드파티 코드가 수정될 수 있는 무언가에 의존함에 따라 취약한 열거 코드가 점점 더 문제가 되고 있습니다.캡슐화 및 추상화 FTW! :-)


OS X 10.4.x 이전 버전의 경우:

 int i;
 for (i = 0; i < [myArray count]; i++) {
   id myArrayElement = [myArray objectAtIndex:i];
   ...do something useful with myArrayElement
 }

OS X 10.5.x(또는 iPhone) 이후의 경우:

for (id myArrayElement in myArray) {
   ...do something useful with myArrayElement
}

다음의 3가지 방법이 있습니다.

        //NSArray
    NSArray *arrData = @[@1,@2,@3,@4];

    // 1.Classical
    for (int i=0; i< [arrData count]; i++){
        NSLog(@"[%d]:%@",i,arrData[i]);
    }

    // 2.Fast iteration
    for (id element in arrData){
        NSLog(@"%@",element);
    }

    // 3.Blocks
    [arrData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
         NSLog(@"[%lu]:%@",idx,obj);
         // Set stop to YES in case you want to break the iteration
    }];
  1. 실행 속도가 가장 빠르며, 3. 자동 완성 시 반복 엔벨로프를 쓰는 것을 잊습니다.

테스트 결과 및 소스 코드는 아래와 같습니다(반복 횟수를 앱에서 설정할 수 있습니다).시간은 밀리초 단위로 각 엔트리는 테스트를 5~10회 실행한 평균 결과입니다.일반적으로 유효 자릿수는 2~3자리까지 정확하며, 그 이후에는 실행마다 다르다는 것을 알게 되었습니다.따라서 오차범위는 1% 미만입니다.테스트는 아이폰 3G에서 실행 중이었고, 그것이 제가 관심 있는 대상 플랫폼이었습니다.

numberOfItems   NSArray (ms)    C Array (ms)    Ratio
100             0.39            0.0025          156
191             0.61            0.0028          218
3,256           12.5            0.026           481
4,789           16              0.037           432
6,794           21              0.050           420
10,919          36              0.081           444
19,731          64              0.15            427
22,030          75              0.162           463
32,758          109             0.24            454
77,969          258             0.57            453
100,000         390             0.73            534

데이터 세트(NSDictionary, NSAray, NSSet 등)를 처리하기 위해 Coco가 제공하는 클래스는 메모리 관리, 재할당 등의 번거로움 없이 정보를 관리하기 위한 매우 좋은 인터페이스를 제공합니다.물론 이것은 대가가 따른다.NS Number의 NSAray를 사용하는 것이 C 어레이의 플로트보다 더 느릴 것이라고 말하는 것은 당연하다고 생각합니다.그래서 몇 가지 테스트를 해보기로 했습니다만, 결과는 매우 충격적이었습니다.이렇게까지 심할 줄은 몰랐어요.주의: 이 테스트는 iPhone 3G를 대상으로 하고 있습니다.그것이 제가 관심을 가지고 있던 플랫폼입니다.

이 테스트에서는 NSNumber의 C float*와 NSArray를 매우 간단하게 랜덤 액세스 퍼포먼스를 비교합니다.

각 배열의 내용을 요약하고 mach_absolute_time()을 사용하여 시간을 재는 간단한 루프를 만듭니다.NSMutable Array는 평균 400배 더 오래 걸립니다!!(400%가 아니라 400배만 더 길어요! 40,000% 더 길어요.

머리글:

// Array_Speed_TestViewController.h

// 어레이 속도 테스트

// Mehmet Akten에 의해 2009년 5월 2일에 작성되었습니다.

// Copyright MSA Visuals Ltd. 2009.무단 전재 금지.

#import <UIKit/UIKit.h>

@interface Array_Speed_TestViewController : UIViewController {

    int                     numberOfItems;          // number of items in array

    float                   *cArray;                // normal c array

    NSMutableArray          *nsArray;               // ns array

    double                  machTimerMillisMult;    // multiplier to convert mach_absolute_time() to milliseconds



    IBOutlet    UISlider    *sliderCount;

    IBOutlet    UILabel     *labelCount;


    IBOutlet    UILabel     *labelResults;

}


-(IBAction) doNSArray:(id)sender;

-(IBAction) doCArray:(id)sender;

-(IBAction) sliderChanged:(id)sender;


@end

구현:

// Array_Speed_TestViewController.m

// 어레이 속도 테스트

// Mehmet Akten에 의해 2009년 5월 2일에 작성되었습니다.

// Copyright MSA Visuals Ltd. 2009.무단 전재 금지.

    #import "Array_Speed_TestViewController.h"
    #include <mach/mach.h>
    #include <mach/mach_time.h>

 @implementation Array_Speed_TestViewController



 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {

    NSLog(@"viewDidLoad");


    [super viewDidLoad];


    cArray      = NULL;

    nsArray     = NULL;


    // read initial slider value setup accordingly

    [self sliderChanged:sliderCount];


    // get mach timer unit size and calculater millisecond factor

    mach_timebase_info_data_t info;

    mach_timebase_info(&info);

    machTimerMillisMult = (double)info.numer / ((double)info.denom * 1000000.0);

    NSLog(@"machTimerMillisMult = %f", machTimerMillisMult);

}



// pass in results of mach_absolute_time()

// this converts to milliseconds and outputs to the label

-(void)displayResult:(uint64_t)duration {

    double millis = duration * machTimerMillisMult;


    NSLog(@"displayResult: %f milliseconds", millis);


    NSString *str = [[NSString alloc] initWithFormat:@"%f milliseconds", millis];

    [labelResults setText:str];

    [str release];

}




// process using NSArray

-(IBAction) doNSArray:(id)sender {

    NSLog(@"doNSArray: %@", sender);


    uint64_t startTime = mach_absolute_time();

    float total = 0;

    for(int i=0; i<numberOfItems; i++) {

        total += [[nsArray objectAtIndex:i] floatValue];

    }

    [self displayResult:mach_absolute_time() - startTime];

}




// process using C Array

-(IBAction) doCArray:(id)sender {

    NSLog(@"doCArray: %@", sender);


    uint64_t start = mach_absolute_time();

    float total = 0;

    for(int i=0; i<numberOfItems; i++) {

        total += cArray[i];

    }

    [self displayResult:mach_absolute_time() - start];

}



// allocate NSArray and C Array 

-(void) allocateArrays {

    NSLog(@"allocateArrays");


    // allocate c array

    if(cArray) delete cArray;

    cArray = new float[numberOfItems];


    // allocate NSArray

    [nsArray release];

    nsArray = [[NSMutableArray alloc] initWithCapacity:numberOfItems];



    // fill with random values

    for(int i=0; i<numberOfItems; i++) {

        // add number to c array

        cArray[i] = random() * 1.0f/(RAND_MAX+1);


        // add number to NSArray

        NSNumber *number = [[NSNumber alloc] initWithFloat:cArray[i]];

        [nsArray addObject:number];

        [number release];

    }


}



// callback for when slider is changed

-(IBAction) sliderChanged:(id)sender {

    numberOfItems = sliderCount.value;

    NSLog(@"sliderChanged: %@, %i", sender, numberOfItems);


    NSString *str = [[NSString alloc] initWithFormat:@"%i items", numberOfItems];

    [labelCount setText:str];

    [str release];


    [self allocateArrays];

}



//cleanup

- (void)dealloc {

    [nsArray release];

    if(cArray) delete cArray;


    [super dealloc];

}


@end

From : 메모.텔레비전

////////////////////

블록이 도입된 이후 사용할 수 있는 이 기능을 사용하면 블록으로 배열을 반복할 수 있습니다.이 구문은 빠른 열거형만큼 훌륭하지는 않지만, 한 가지 매우 흥미로운 기능이 있습니다. 동시 열거형입니다.열거 순서가 중요하지 않고 잠금 없이 작업을 병렬로 수행할 수 있는 경우 멀티 코어 시스템에서 상당한 속도를 높일 수 있습니다.그것에 대한 자세한 내용은 동시 열거 섹션을 참조하십시오.

[myArray enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
    [self doSomethingWith:object];
}];
[myArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    [self doSomethingWith:object];
}];

//////// NSFastEnumerator

고속 열거의 배후에 있는 아이디어는 고속 C 어레이 액세스를 사용하여 반복을 최적화하는 것입니다.기존 NSEnumerator보다 빠를 뿐만 아니라 Objective-C 2.0은 매우 간결한 구문을 제공합니다.

id object;
for (object in myArray) {
    [self doSomethingWith:object];
}

/////////////////

NSE numerator

이것은 외부 반복 형식입니다.[ myArray objectEnumerator ]는 개체를 반환합니다.이 개체에는 nextObject 메서드가 있으며 nero를 반환할 때까지 루프에서 호출할 수 있습니다.

NSEnumerator *enumerator = [myArray objectEnumerator];
id object;
while (object = [enumerator nextObject]) {
    [self doSomethingWith:object];
}

/////////////////

objectAt인덱스: 열거

정수를 증가시키는 for 루프를 사용하고 [myArray objectAtIndex:index]를 사용하여 객체를 조회하는 것은 열거의 가장 기본적인 형식입니다.

NSUInteger count = [myArray count];
for (NSUInteger index = 0; index < count ; index++) {
    [self doSomethingWith:[myArray objectAtIndex:index]];
}

//////////// 발신인 : darkdust.net

문자열 배열을 선언하고 그 위에 반복하는 방법은 다음과 같습니다.

NSArray *langs = @[@"es", @"en", @"pt", @"it", @"fr"];

for (int i = 0; i < [langs count]; i++) {
  NSString *lang = (NSString*) [langs objectAtIndex:i];
  NSLog(@"%@, ",lang);
}

eachNSArray category

ObjectiveSugar에서 가져온 코드

- (void)each:(void (^)(id object))block {
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        block(obj);
    }];
}

다음을 수행합니다.-

for (id object in array) 
{
        // statement
}

Swift의 경우

let arrayNumbers = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

// 1
for (index, value) in arrayNumbers.enumerated() {
    print(index, value)
    //... do somthing with array value and index
}


//2
for value in arrayNumbers {
    print(value)
    //... do somthing with array value
}

언급URL : https://stackoverflow.com/questions/992901/how-do-i-iterate-over-an-nsarray

반응형