C如何自己实现一个for

我们在用Objective-C编写程序时,很多时候会用到NSArray来作为线性列表来使用。我们在枚举这个数组所有元素的使用可以通过下列方法进行:

for(id obj in anArray)
{

}

这种方式在编程语言术语中也被称为for-each形式。在C++11以及Java 5中,上述的in使用冒号:来表示。


那么我们在Objective-C中是否可以自己定义一个类来实现for-each形式呢?当然可以!我们可以通过两种方式来实现这种简单的for-each语法形式。

1、通过继承NSEnumerator类,并且重写其- (NSArray*)allObjects方法以及- (id)nextObject方法来实现。

2、通过实现NSFastEnumeration协议,并实现其- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id*)stackbuf count:(NSUInteger)len方法。


由于NSEnumerator类比较简单,我们可以通过看下面的代码示例即可理解。但是由于Objective-C只有单继承,因此使用对NSFastEnumeration协议的实现会更加灵活。而且这里比较复杂的是countByEnumeratingWithState方法的实现。下面先对这个方法做个简单介绍。

首先,当你的类实现了NSFastEnumeration协议并实现了countByEnumeratingWithState之后,在用for-each时,这个countByEnumeratingWithState可能需要被执行多次,依赖于你所要枚举的元素个数。因此,这个方法的返回值指示了当前所要枚举的数组的元素个数,如果返回0,则说明枚举全部完成。

参数stackbuf是指向方法调用者(即消息发送者)所分配的栈空间。这个是由编译器自动分配的,一般不需要程序员自己干涉。

参数len表示栈空间分配的大小(sizeof(id) * len个字节),也就是说单次枚举最大能放多少元素。

参数state指向由编译器给我们分配好的一个NSFastEnumerationState结构体变量地址。这个参数需要我们实现中自己来设置。我们先看这个结构体的定义:

typedef struct {
    unsigned long state;    // 表示当前状态,初始为0
    id __unsafe_unretained *itemsPtr;    // 指向当前所要枚举的数组首地址
    unsigned long *mutationsPtr;    // 用于检测,所要枚举的对象是否发生了改变
    unsigned long extra[5];    // 这里可以由实现者随意存放必要的额外数据
} NSFastEnumerationState;

对于这个结构体变量,itemsPtr与mutationsPtr必须进行设置,并且不能为空,除非,此次枚举直接返回0。


下面我们通过代码示例来详细描述这两种方法的使用:

//
//  main.m
//  objCTest
//
//  Created by Zenny Chen on 12-2-7.
//  Copyright (c) 2014年 Neon Media Studio. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface MyIterator : NSEnumerator
{
@private
   
    NSArray *mArray;
    int mCurrIndex;
}

@end

@implementation MyIterator

- (instancetype)init
{
    self = [super init];
   
    mArray = [@[@1, @2, @3, @4, @5, @6, @7, @8] retain];
   
    return self;
}

- (void)dealloc
{
    if(mArray != nil)
    {
        [mArray release];
        mArray = nil;
    }
   
    [super dealloc];
}

- (NSArray*)allObjects
{
    return mArray;
}

- (id)nextObject
{
    if(mCurrIndex == [mArray count])
        return nil;
   
    return [mArray objectAtIndex:mCurrIndex++];
}

@end


@interface MyFastIterator : NSObject<NSFastEnumeration>
{
@private
   
    NSArray *mArray;
    NSNumber* mNumbers[100];
}

@end

@implementation MyFastIterator

- (instancetype)init
{
    self = [super init];
   
    // 先对mArray进行初始化
    mArray = [@[@100, @200, @300, @400, @-1, @-2, @-3, @-4,
                @1, @2, @3, @4, @5, @6, @7, @8,
                @11, @12, @13, @14, @15, @16, @17, @18] retain];
   
    int i = 0;
    for(NSNumber *num in mArray)
        mNumbers[i++] = num;
   
    return self;
}

- (void)dealloc
{
    if(mArray != nil)
    {
        [mArray release];
        mArray = nil;
    }
   
    [super dealloc];
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2cf275bee1245aca1ecaaad434b7728d.html