2016-05-05 4 views
0

Я учусь быстро. Я хотел бы использовать собственный класс, который должен быть закодирован в [...] для [...]. Ниже приведен образец кода, который до сих пор пробовал. Класс в вопросе «GuestManager», который держит частную коллекцию гостей [объекты класса Гостя]Пользовательская коллекция в быстрой: это правильный путь?

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. Вместо этого я создал один класс, соответствующий обеим протоколам.

Ниже приведены некоторые из моих вопросов:

  1. Я хотел бы знать, если это правильный путь, чтобы иметь пользовательский тип коллекции?

  2. Можем ли мы использовать индекс как способ выполнить поиск на основе свойства, например «subscript (aGuestId gID: String)» в примере кода выше?

  3. Это ясно из кода для реализации функции next() в приведенном выше примере кода, который сбрасывает «nextIndex», когда итерация достигнута в конце. Как будет справиться с ситуацией, в которой мы используем заявление разрыва внутри для ... в цикле, как показано ниже:

    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 
    } 
    

    В 2 для цикла кода разразиться после получения первого элемента [объекта гостя в этом случае ]. Последующий цикл будет начинаться с индекса 1 в коллекции, а не на 0. Есть ли в любом случае для обработки этой ситуации разрыва, так что для каждого последующего цикла для цикла всегда устанавливается значение 0?

Благодаря

Edit: Это кажется "NEXTINDEX" перезагрузки проблема может быть исправлена ​​с ниже кодом [добавлен внутри класса GuestManager] для генерации() реализация метода

func generate() -> Self { 
     self.nextIndex = 0 
     return self 
    } 

ответ

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 
    } 
} 
+0

По подписке, я хочу сделать гостевойManager доступным для поиска по определенным ключевым свойствам, хотя верно, что мы можем создавать функции, но то, что я ищу, является более чистым способом выполнения поиска. – user2788672

1

Вы не должны хранить 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] 
    } 
} 

еще несколько наблюдений:

  1. Ваш guests свойство не должно быть обязательным. Это делает код более сложным, без каких-либо преимуществ. Я изменил его в своем коде.
  2. Ваш класс Guest должен, вероятно, быть типом значения (a struct). GuestManager также является хорошим кандидатом на структуру, если вам не нужна эталонная семантика класса (все типы коллекций в стандартной библиотеке являются структурами).