我们在Swift编程语言中常常会用到for-in循环(在编程语言术语中又被称为for-each)。此外,从Swift 2.2版本起,for循环将只支持for-in形式,而不支持for i = 0; i < n; i+=1 { }这种形式了,若要使用这种形式的话,只得用while或repeat-while来代替,或想办法转为for-in。

在Swift中,标准库已经定义了许多类型可直接支持for-in循环形式,比如Range、Array、Set、Dictionary等等。那么我们是否能自己定义一个类或结构体来支持for-in这种迭代形式呢?当然可以!我们要实现这个目标需要分两步走。

第一步,我们要使用for-in循环的类或结构体需要实现SequenceType这个协议。SequenceType包含了许多容器相关的接口方法,但如果我们只需要简单实现for-in循环的话,那么只需要实现其 public func generate() -> Self.Generator 接口方法即可。这里的Self只能用在protocol的定义内,相当于self,但是这里又不能用self,因为self是对对象的引用,协议不是一个对象,所以Swift编程语言中引入了Self(注意S是大写的)表示引用本协议内定义的类型。generate方法用于生成所需迭代的每个元素的列表。此外,Generator的本体是GeneratorType,它也是一个protocol,表示所需迭代的每个元素对象,所以我们要做第二步。

第二步,实现GeneratorType协议。这个协议比较简单,就一个 public mutating func next() -> Self.Element 接口方法。这里的Element可用来指定每个元素的类型。

下面我们就看一下一个实例代码:

//
// ViewController.swift
// SwiftTest
//
// Created by Zenny Chen on 16/4/1.
// Copyright © 2016年 GreenGames Studio. All rights reserved.
// import Cocoa class MyIterContainer<T> : SequenceType { // 容器本身包含一个数组对象mElemArray
private var mElemArray: [T]? init() {
mElemArray = [T]()
} init(elems: [T]) {
mElemArray = elems;
} func generate() -> MyIterGenerator<T> { // 这里返回一个GeneratorType对象
return MyIterGenerator(elems: mElemArray!)
}
} class MyIterGenerator<T> : GeneratorType { private var mCurrentIndex: Int = 0
private var mElemArray: [T]? init(elems: [T]) { mElemArray = elems
} func next() -> T? { guard let list = mElemArray else { return nil } if mCurrentIndex < list.count { let element = list[mCurrentIndex]
mCurrentIndex += 1
return element }
else {
return nil
}
}
} class ViewController: NSViewController { override func viewDidLoad() {
super.viewDidLoad() // Do any additional setup after loading the view. let container = MyIterContainer(elems: [1, 2, 3, 4]) var sum = 0
for i in container {
sum += i
}
print("sum = \(sum)") sum = 0 // 上述的for-in迭代就相当于以下代码:
let generator = container.generate()
var elem: Int? = nil repeat {
elem = generator.next()
if let value = elem {
sum += value
}
}
while elem != nil print("second sum = \(sum)")
} override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}

上述示例代码先定义了一个容器类MyIterContainer<T>,然后定义了与之相关的生成器类MyIterGenerator<T>,这里用了泛型,可使得后面的实现更为灵活。然后在viewDidLoad方法中描述了for-in的使用方法,并且在最后描述了其内部实现机制。

Swift编程语言中如何实现自定义类型的for-in循环(基于Swift 2.2)的更多相关文章

  1. Swift编程语言中的方法引用

    由于Apple官方的<The Swift Programming Guide>对Swift编程语言中的方法引用介绍得不多,所以这里将更深入.详细地介绍Swift中的方法引用. Swift与 ...

  2. Swift编程语言学习9—— 存储属性和计算属性

    属性将值跟特定的类.结构或枚举关联.存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值.计算属性能够用于类.结构体和枚举里,存储属性仅仅能用于类和结构体. 存储属性和计算属性通经 ...

  3. struts2自定义类型转换器

    首先,何为struts2的类型转换器? 类型转换器的作用是将请求中的字符串或字符串数组参数与action中的对象进行相互转换. 一.大部分时候,使用struts2提供的类型转换器以及OGNL类型转换机 ...

  4. 关于 Swift 4 中内存安全访问

    前言 本文主要翻译今年 The Swift Programming Language (Swift 4) 中新出的章节 -<Memory Safety>.在 Swift 4 中,内存安全访 ...

  5. 浅谈 Swift 2 中的 Objective-C 指针

    浅谈 Swift 2 中的 Objective-C 指针 2015-09-07  499 文章目录 1. 在 Swift 中读 C 指针 2. 在 Swift 中创建 C 指针 3. 总结 作者:Ja ...

  6. Android进阶AIDL使用自定义类型

    原文首发于微信公众号:jzman-blog,欢迎关注交流! 上篇文章中主要介绍从 AIDL 的使用方式以及 Android 开发中不同进程之间的通信,遗留的问题是如何在 AIDL 中使用自定义类型,具 ...

  7. iOS Swift编程语言

    Swift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C*共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序. Swift是一款易学易用的编程 ...

  8. iOS中生成并导入基于Swift编程语言的Framework

    从iOS 8.0开始就引入了framework打包方式以及Swift编程语言.我们可以主要利用Swift编程语言将自己的代码打包成framework.不过当前Xcode 7.x在自动导入framewo ...

  9. Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其它一些编程语言中的 lambdas 比較类似。

    闭包是功能性自包括模块,能够在代码中被传递和使用. Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其它一些编程语言中的 lambdas 比較相似.  闭包能够 捕获 和 ...

随机推荐

  1. 利用yum下载rpm包并批量安装

    一.下载rpm包 方法一:downloadonly 1.yum自动下载RPM包及其所有依赖的包至/root/rpm目录: yum install yum-plugin-downloadonly yum ...

  2. 17,Flask-admin后台管理系统总结

    导入包 from flask_admin import Admin,BaseView,expose,AdminIndexView from flask_admin.contrib.sqla impor ...

  3. mysql应用

    1.  简述 MySQL是开源的关系型数据库.官网:https://dev.mysql.com/. 2.  安装及应用 可通过https://dev.mysql.com/downloads/下载MyS ...

  4. 计算机网络基础之IP地址详解

    计算机网络基础之IP地址详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.IP地址概述 1>.什么是IP地址 我们为什么要使用逻辑地址(IP地址)来标识网络设备,而不采 ...

  5. 洛谷 P2725 邮票题解

    题目背景 给一组 N 枚邮票的面值集合(如,{1 分,3 分})和一个上限 K —— 表示信封上能够贴 K 张邮票.计算从 1 到 M 的最大连续可贴出的邮资. 题目描述 例如,假设有 1 分和 3 ...

  6. 两个好的k8s周边项目,mark

    这段时间没有应用, 但应该过段时间就可以派上用场了. 1,像写shell脚本一样写一个operator. https://github.com/flant/shell-operator 2,多集群的k ...

  7. 【云栖社区001-数据结构】如何实现一个高效的单向链表逆序输出(Java版)

    如题 动手之前,发现自己很擅长用C语言来写链表. 不过,既然自己做的是Java开发,那么还是用Java实现这个算法吧:毕竟,以后的若干年里都差不多要跟Java打交道了. 于是,先将Java版的链表自学 ...

  8. ajax、axios、fetch 对比

    前言 今天在看到一个比较好的插件,写一个示例时,由于需要请求在线数据,官方给的是用 $.get(),就为了一个示例使用 JQuery 没必要. 又找了找,发现有用 fecth 的,挺方便,这里就做一个 ...

  9. 《exception》第九次团队作业:Beta冲刺与验收准备(第一天)

    一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件黑盒测试技术:2.学会编制软件项目 ...

  10. solidworks 学习 (四)

    旋钮三维建模