编写高质量代码的52个有效方法

52个有效方法(48) - 多用块枚举,少用for循环

2018-10-09  本文已影响44人  SkyMing一C

在编程中经常需要列举collection中得元素,在当前的Objective-C语言中又多重办法实现此功能。

for循环
//Array
NSArray *anArray = /*...*/;
    for (int i = 0; i < anArray.count; i++)
    {
        id object = anArray[i];
        //Do something with 'object'
    }
//Dictionary
    NSDictionary *aDictionary = /*...*/;
    NSArray *keys = [aDictionary allKeys];
    for (int i = 0; i < keys.count; i++)
    {
        id key = keys[i];
        id value = aDictionary[key];
        //Do something with 'key' and 'value'
    }
//Set
NSSet *aSet = /*...*/;
NSArray *objects = [aSet allObjects];
for (int i = 0; i < objects.count; i++)
{
    id object = objects[i];
    //Do something with 'object'
}
NSEnumerator

用Objective-C 1.0中的 NSEnumerator 来遍历NSEnumerator 是个抽象基类,其中只定义了两个方法,供其具体子类来实现:

-(NSAraay *)allObjects;

-(id)nextObject;
//Array
NSArray *anArray = /* ... */;
NSEnumerator *enumerator = [anArray objectEnumerator];
id object;
while ((object = [enumerator nextObject]) != nil)
{
    // Do something with 'object'
}
// Dictionary
NSDictionary *aDictionary = /* ... */;
NSEnumerator *enumerator = [aDictionary keyEnumerator];
id key;
while ((key = [enumerator nextObject]) != nil)
{
    id value = aDictionary[key];
    // Do something with 'key' and 'value'
}

快速遍历

快速遍历for...in大幅简化了遍历collection所需的语法。

NSArray *anArray = /* ... */;
    for (id object in anArray)
    {
        // Do something with 'object'
    }
// Dictionary
    NSDictionary *aDictionary = /* ... */;
    for (id key in aDictionary)
    {
        id value = aDictionary[key];
        // Do something with 'key' and 'value'
    }
// Set
    NSSet *aSet = /* ... */;
    for (id object in aSet)
    {
        // Do something with 'object'
    }
基于block的遍历方式
//Array
- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
//Dictionary
- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(KeyType key, ObjectType obj, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
//Set
- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
NSArray *anArray = /* ... */;
    [anArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop)
     {
         // Do something with 'object'
         if (shouldStop)
         {
             *stop = YES;
         }
     }];
// Dictionary
    NSDictionary *aDictionary = /* ... */;
    [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop)
     {
         // Do something with 'key' and 'object'
         if (shouldStop)
         {
             *stop = YES;
         }
     }];
// Set
    NSSet *aSet = /* ... */;
    [aSet enumerateObjectsUsingBlock:^(id object, BOOL *stop)
     {
         // Do something with 'object'
         if (shouldStop)
         {
             *stop = YES;
         }
     }];
NSDictionary *aDictionary = /* ... */;
    for (NSString *key in aDictionary)
    {
        NSString *object = (NSString*)aDictionary[key];
        // Do something with 'key' and 'object'
    }
[aDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop)
     {
         // Do something with 'key' and 'obj'
     }];
执行反向遍历
//Array
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
//Dictionary
- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(KeyType key, ObjectType obj, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
//Set
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
要点
  1. 遍历collection有四种方式。最基本的办法是for循环,其次是NSEnumeratior遍历法及快速遍历法,最新、最先进的方式则是“块枚举法”。

  2. “块枚举法”本身就能通过GCD来并发执行遍历操作,无须另行编写代码。而采用其他遍历方式则无法轻易实现这一点。

  3. 若提前知道待遍历的collection含有何种对象,则应修改块签名,指出对象的具体类型。

上一篇 下一篇

猜你喜欢

热点阅读