我正在迅速学习。我想使用一个自定义类来循环[能够在...循环中]像Array一样。下面是给定的示例代码,到目前为止,我已经尝试过了。有问题的类是“GuestManager”,它持有私人的客人集合[类Guest的对象]
import Foundation
class Guest{
var guestId: String
var guestName: String
init(gId: String, name: String){
self.guestId = gId
self.guestName = name
}
}
class GuestManager: GeneratorType, SequenceType{
private var guests = [Guest]?()
private var nextIndex: Int
init(guests: [Guest]){
self.guests = guests
self.nextIndex = 0
}
func next() -> Guest? {
if self.nextIndex > (self.guests?.count)! - 1 {
self.nextIndex = 0
return nil
}
let currentGuest = self.guests![self.nextIndex]
self.nextIndex += 1
return currentGuest
}
subscript(aGuestId gID: String) -> Guest{
return (self.guests?.filter({$0.guestId == gID}).first)!
}
}
我不想创建符合GeneratorType&的单独类。 SequenceType协议。相反,我创建了一个符合这两种协议的类。
以下是我的一些问题:
我想知道这是否是一种自定义集合类型的正确方法?
我们可以使用下标作为基于属性执行搜索的方法,例如上面的示例代码中的“下标(aGuestId gID:String)”吗?
从上面示例代码中的next()函数实现的代码中可以清楚地看到,当迭代到达时,重置了“nextIndex”。如何处理我们在for ... in循环中使用break语句的情况,如下所示:
for aGuest in guestManager{//guestManager an instance of GuestManager class instantiated with several guest objects
print(aGuest.guestName)
}
for aG in guestManager{
print(aG.guestId)
break
}
在第二个for循环中,代码在获取第一个Element [Guest对象(在本例中)之后)中断。后续for循环将从集合中的索引1开始而不是0.是否仍然处理此中断情况,以便对于每个后续循环,索引始终设置为0?
由于
编辑:似乎可以使用以下代码[在GuestManager类中添加]修复“nextIndex”重置问题,以便生成()方法实现
func generate() -> Self {
self.nextIndex = 0
return self
}
答案 0 :(得分:2)
您不应将nextIndex
存储在课程中。您可以在generate
方法中使用局部变量,然后让您传递给在该方法中创建的生成器的闭包捕获该变量。这就是你需要采用SequenceType
:
class GuestManager: SequenceType{
private var guests: [Guest]
init(guests: [Guest]) {
self.guests = guests
}
func generate() -> AnyGenerator<Guest> {
var nextIndex = 0
return AnyGenerator {
guard nextIndex < self.guests.endIndex else {
return nil
}
let next = self.guests[nextIndex]
nextIndex += 1
return next
}
}
}
对于下标,您应该采用Indexable
。实际上,满足所有要求的最简单方法是将尽可能多的SequenceType
,Indexable
和最终(如果您想支持它)CollectionType
的逻辑传递给您的数组,已经具备这些功能。我会这样写:
class GuestManager {
private var guests: [Guest]
init(guests: [Guest]){
self.guests = guests
}
}
extension GuestManager: SequenceType {
typealias Generator = IndexingGenerator<GuestManager>
func generate() -> Generator {
return IndexingGenerator(self)
}
}
extension GuestManager: Indexable {
var startIndex: Int {
return guests.startIndex
}
var endIndex: Int {
return guests.endIndex
}
subscript(position: Int) -> Guest {
return guests[position]
}
}
更多观察结果:
guests
属性不应是可选的。它使代码更复杂,没有任何好处。我在代码中相应地更改了它。Guest
类应该是值类型(结构)。 GuestManager
也是结构的一个很好的候选者,除非你需要一个类的引用语义(标准库中的所有集合类型都是结构)。答案 1 :(得分:0)
我认为你在这里尝试的下标方法有点令人费解。就个人而言,为了清楚起见,我会使用一个函数来执行此操作。
guestManager[aGuestId: guestId]
guestManager.guestWithID(guestId)
所以风格上我可能会落在这样的东西上
import Foundation
class Guest{
var guestId: String
var guestName: String
init(guestId: String, guestName: String){
self.guestId = guestId
self.guestName = guestName
}
}
class GuestManager: GeneratorType, SequenceType{
private var guests: [Guest]
private var nextIndex = 0
init(guests: [Guest]){
self.guests = guests
}
func next() -> Guest? {
guard guests.count < nextIndex else {
nextIndex = 0
return nil
}
let currentGuest = guests[nextIndex]
nextIndex += 1
return currentGuest
}
func guestWithID(id: String) -> Guest? {
return guests.filter{$0.guestId == id}.first ?? nil
}
}