سؤال

وأنا أعلم أنه إذا كان لديك حلقة بتعديل عدد من البنود في حلقة باستخدام NSEnumerator على مجموعة هو أفضل طريقة للتأكد من التعليمات البرمجية يفجر, ومع ذلك أود أن أفهم أداء المفاضلات بين NSEnumerator الصف و المدرسة القديمة للحلقة

هل كانت مفيدة؟

المحلول

استخدام جديدة for (... in ...) بناء الجملة في الهدف-C 2.0 عموما أسرع طريقة تكرار عبر مجموعة لأنه لا يمكن الحفاظ على منطقة عازلة على المكدس و الحصول على دفعات من البنود في ذلك.

باستخدام NSEnumerator عموما أبطأ طريقة لأنه غالبا ما نسخ جمع يجري يتحرك;بالنسبة ثابتة مجموعات وهذا يمكن أن تكون رخيصة (أي ما يعادل -retain) ولكن قابلة للتغيير مجموعات يمكن أن يسبب ثابتة نسخ المراد إنشاؤه.

بفعل التكرار الخاصة بك — على سبيل المثال ، استخدام -[NSArray objectAtIndex:] — عموما سوف تقع في مكان ما بين لأنه في حين لن يكون لديك إمكانية نسخ النفقات العامة ، كما لن يكون الحصول على دفعات من الكائنات من وراء جمع.

(PS - هذا السؤال ينبغي أن يوصف الهدف-C وليس C, منذ NSEnumerator هو الكاكاو الطبقة الجديدة for (... in ...) بناء جملة غير محددة الهدف-C.)

نصائح أخرى

بعد تشغيل الاختبار عدة مرات ، والنتيجة هي نفسها تقريبا.كل قياس كتلة يعمل 10 مرات متتالية.

النتيجة في حالة من الأسرع إلى الأبطأ:

  1. أجل..في (testPerformanceExample3) (0.006 ثانية)
  2. في حين (testPerformanceExample4) (0.026 ثانية)
  3. For(;;) (testPerformanceExample1) (0.027 ثانية)
  4. التعداد كتلة (testPerformanceExample2) (0.067 ثانية)

أما عن حلقة في حين هو نفسه تقريبا.

comparation between iterations

على tmp هو NSArray الذي يحتوي على 1 مليون الكائنات من 0 إلى 999999.

- (NSArray *)createArray
{
    self.tmpArray = [NSMutableArray array];
    for (int i = 0; i < 1000000; i++)
    {
        [self.tmpArray addObject:@(i)];
    }
    return self.tmpArray;
}

كل رمز:

ViewController.ح

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (strong, nonatomic) NSMutableArray *tmpArray;
- (NSArray *)createArray;

@end

ViewController.م

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createArray];
}

- (NSArray *)createArray
{
    self.tmpArray = [NSMutableArray array];
    for (int i = 0; i < 1000000; i++)
    {
        [self.tmpArray addObject:@(i)];
    }
    return self.tmpArray;
}

@end

MyTestfile.م

#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>

#import "ViewController.h"

@interface TestCaseXcodeTests : XCTestCase
{
    ViewController *vc;
    NSArray *tmp;
}

@end

@implementation TestCaseXcodeTests

- (void)setUp {
    [super setUp];
    vc = [[ViewController alloc] init];
    tmp = vc.createArray;
}

- (void)testPerformanceExample1
{
    [self measureBlock:^{
        for (int i = 0; i < [tmp count]; i++)
        {
            [tmp objectAtIndex:i];
        }
    }];
}

- (void)testPerformanceExample2
{
    [self measureBlock:^{
        [tmp enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
           obj;
        }];
    }];
}

- (void)testPerformanceExample3
{
    [self measureBlock:^{
        for (NSNumber *num in tmp)
        {
            num;
        }
    }];
}

- (void)testPerformanceExample4
{
    [self measureBlock:^{
        int i = 0;
        while (i < [tmp count])
        {
            [tmp objectAtIndex:i];
            i++;
        }
    }];
}

@end

لمزيد من المعلومات زيارة: التفاح "حول اختبار مع كسكودي"

فهي مشابهة جدا.مع الهدف-C 2.0 معظم التعدادات الآن التقصير ، NSFastEnumeration مما يخلق منطقة عازلة من عناوين كل كائن في المجموعة التي يمكن أن ثم يسلم.خطوة واحدة أن تقوم بحفظ أكثر من الكلاسيكية للحلقة هو عدم الاضطرار إلى الاتصال objectAtIndex:i في كل مرة داخل الحلقة.الداخلية من جمع أنت تعداد تنفيذ سريع التعداد مع الدعوة objectAtIndex:i method.

المخزن المؤقت هو جزء من السبب في أنك لا يمكن أن يتحور مجموعة كما يمكنك تعداد, عنوان الأشياء سوف تتغير و المخزن المؤقت الذي تم بناؤه لم يعد من المباراة.

كمكافأة الشكل 2.0 تبدو لطيفة مثل الكلاسيكية للحلقة:

for ( Type newVariable in expression ) { 
    stmts 
}

قراءة ما يلي documentaion أن تذهب أعمق:NSFastEnumeration البروتوكول المرجعية

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top