iOS设计模式-迭代器

来源:互联网 发布:软件销售提成比例 编辑:程序博客网 时间:2024/06/08 08:06

一、介绍
迭代器:提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示.(遍历集合中元素的只能从集合本身转移到迭代器对象。迭代器定义了一个用于访问集合元素并记录当前元素的接口。不同的迭代器可以执行不同的遍历策略。提供一种方法顺序访问一个聚合对象中得各个元素,而又不需暴露该对象的内部表示。)
分类
外部迭代器:让客户端直接操作迭代过程,所以客户端需要知道外部迭代器才能使用。
内部迭代器:集合对象(被迭代的目标对象)在其内部维护并操作一个外部迭代器。提供内部迭代器的典型的集合对象为客户端定义一个接口,或者从底层的集合一次访问一个元素,或者向每个元素发送消息。

何时使用: (1)需要访问组合对象的内容,又不想暴露其内部表示
(2)需要使用多种方式遍历组合对象
(3)需要提供统一的接口来遍历各种类型的组合对象
关系图
这里写图片描述

二、在Cocoa Touch框架中使用迭代器模式

基础框架中的NSEnumerator类实现了迭代器模式。抽象NSEnumerator类的私有具体子类返回枚举器对象,能够顺序遍历各种集合——数组、集合、字典,把集合中的对象返回给客户端。

1.NSEnumerator

我们可以使用NSEnumerator来枚举NSArray、NSDictionary和NSSet对象中的元素。NSEnumerator本身是个抽象类,它有依靠几个工厂方法,如objectEnumrator或keyEnumerator,来创建并返回相应的具体枚举器对象。 使用NSEnumerator对数组进行遍历,当调用[itemEnumerator nextObject]会返回nil,然后枚举过程就结束了。
代码如下:

 NSArray *array = @[@"小丽", @"李明", @"王子"]; NSEnumerator *itemEnumerator = [array objectEnumerator];  NSString *item;  while (item = [itemEnumerator nextObject]) {      NSLog(@"item is :%@", item);  }

2015-08-28 16:48:05.463 NSEnumatroDemo[55301:3712762] item is :小丽
2015-08-28 16:48:05.463 NSEnumatroDemo[55301:3712762] item is :李明
2015-08-28 16:48:05.464 NSEnumatroDemo[55301:3712762] item is :王子

2.基于块的枚举

从iOS4.0后,在NSArray、NSDictionary和NSSet对象中引入了新方法,用于基于块的枚举。其中一个方法叫enumerateObjectsUsingBlock:(void(^)(id obj, NSUInteger idx, BOOL *stop))block。我们可以把自己的算法定义在内嵌到消息调用的块里,或者在别的什么地方预定义一个块,然后作为参数传给消息调用。如下代码:

 NSArray *array = @[@"小丽", @"李明", @"王子"]; NSString *str = @"李明";[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {  NSLog(@"item is :%@", obj);  if ([obj localizedStandardCompare:str] == NSOrderedSame) {      *stop = YES;      NSLog(@"停止遍历");  }

}];

2015-08-28 17:10:03.556 NSEnumatroDemo[55478:3723216] item is :小丽
2015-08-28 17:10:03.557 NSEnumatroDemo[55478:3723216] item is :李明
2015-08-28 17:10:03.557 NSEnumatroDemo[55478:3723216] 停止遍历

如果array数组中有字符串”李明”,那么就把指针*stop设置为YES,以通知array对象提前停止遍历。

NSSet对象中基于块的枚举与NSArray中的非常类似,只是在块的参数中没有idx参数。因为集合中的元素是无序的。

使用NSArray、NSDictionary和NSSet的内部迭代器的一个重要好处是,处理其内容的算法可以在其他地方由其他开发人员来定义。与传统的for循环中定义的算法不同,定义清晰的块可以被复用。当块逐渐变大时,可把它们放到单独的实现文件中,不跟其他代码挤在一起。

3.快速枚举

从iOS2.0后提供了一种枚举,快速枚举,也是苹果推荐的枚举方法。它允许把集合对象的枚举直接用作for循环的一部分,无需使用其他枚举对象,而且比传统的机遇索引的for循环效率更高。现在枚举循环使用指针运算,让它比使用NSEnumerator的标准方法效率更高。

要使用快速枚举,集合类需要实现NSFastEnumeration协议,以向运行库提供关于集合的必要信息。基础框架中的所有集合类与NSEnumerator类都支持快速枚举。因此不必使用while循环从NSEnumerator枚举每个元素,直到nextObject返回nil。代码如下:

NSArray *array = @[@"小丽", @"李明", @"王子"]; for (id item in array) {     NSLog(@"item is :%@", item); }

2015-08-28 17:28:18.619 NSEnumatroDemo[55596:3730966] item is :小丽
2015-08-28 17:28:18.620 NSEnumatroDemo[55596:3730966] item is :李明
2015-08-28 17:28:18.620 NSEnumatroDemo[55596:3730966] item is :王子

4.内部枚举

NSArray有个实例方法叫(void)makeObjectsPerformSelector:(SEL)aSelector,它允许客户端向数组中每个元素发送一个消息,让每个元素执行指定的aSelector。可以用前面提到的任何一种枚举方法让每个元素执行相同的选择器,达到相同的目的。这个方法在内部枚举集合并向每个元素发送performSelector:消息。这种方式的缺点是如果集合中任何元素不响应选择器,就会抛出异常。因此它主要使用于不需要太多运行时检查的简单操作。

0 0
原创粉丝点击