2016-10-11 3 views
0

Ich habe versucht, eine benutzerdefinierte Iterator zu schaffen, die Wrapper abcContainer über Rohdaten-Klasse gibt abcSwift 3 - Sequenz vieldeutig, ohne mehr Kontext

// raw data class 
class abc { 
    var name : String = ""; 
    init(_ value : String) { 
     name = value; 
    } 
} 

// with container, only "name" is to be visible 
class abcContainer { 
    private var _abc : abc; 
    init(_ obj : abc) { 
     _abc = obj; 
    } 
    // + extra methods here 
    func getName() -> String { 
     return _abc.name 
    } 
} 

Der Punkt wäre, dass das Wörterbuch Instanzen abcContainer anstatt nur die zurückkehren einfach roh abc Klasse.

Ich wollte das Sequenz-Protokoll verwendet die Umwandlung automatische zu machen, aber ich war nicht in der Lage, die [String:abc] in [String:abcContainer] automatisch wie folgt zu transformieren:

// the iterator is implemented just iterating the inner basic dict 
// but wrapping the result value as abcContainer 
class abcIterator : Sequence, IteratorProtocol { 

    private var __source : [String:abc]?; 
    var index = 0 
    var myIterator : DictionaryIterator<String, abc>; 

    init(_ ctxArray: [String:abc]) { 
     self.__source = ctxArray 
     index = 0; 
     myIterator = (__source?.makeIterator())! 
    } 

    func next() -> abcContainer? { 
     let nextItem = myIterator.next(); 
     if(nextItem != nil) { 
      return abcContainer((nextItem?.value)!); 
     } 
     return nil; 
    } 
} 

// this was supposed to be the wrapper over the collection 
class abcCollection : Sequence { 

    private var __source : [String:abc]?; 

    init(_ list: [String:abc]) { 
     self.__source = list 
    } 

    func makeIterator() -> abcIterator { 
     return abcIterator(self.__source!); 
    } 
} 

ich wahrscheinlich hier etwas sehr Grundlegendes fehlt bin. Wenn ich versuche, die Sammlung wie folgt zu verwenden:

var dict : [String:abc] = [String:abc](); 
    dict["abba"] = abc("John Smith"); 

    for (key,value) in abcCollection(dict) { 
     print(key, value.getName()); 
    } 

ich Fehler: Expression Typ „abcCollection“ ist mehrdeutig, ohne mehr Kontext

jemand Idee Hat, wie es funktioniert? Was fehlt? Ich habe das Gefühl, dass diese Antwort die Informationen, die ich brauche ...

Swift 2 to 3 Migration for Swift Sequence Protocol

Antwort

2

Das Problem in Ihrem ursprünglichen Code ist, dass abcCollection(dict) eine Folge von abcContainer Objekten zurückgegeben, und diejenigen, die nicht können ein (key, value) Tupel zugeordnet werden.

Sie können Ihr Ziel erreichen mit

class abcCollection : Sequence { 

    private var __source : [String:abc] 

    init(_ list: [String:abc]) { 
     self.__source = list 
    } 

    public func makeIterator() -> AnyIterator<(AnyObject,abcContainer)> { 
     let mapped = self.__source.lazy.map { 
      ($0.key as AnyObject, abcContainer($0.value)) 
     } 
     return AnyIterator(mapped.makeIterator()) 
    } 
} 

machen __source nicht-optional macht den (optional) unwrappings überflüssig und lazy.map { ... } gibt eine träge ausgewertet Folge von Schlüssel/Wert-Paare, die dann Typ- gelöscht.

+0

Danke! Schöne subtile Punkte. –

2

Ok, vielleicht die Antwort war abcIterator nicht notwendig war, konnte man den Iterator direkt nur in der verknüpften Antwort getan mag definiert haben wie this:

class abcCollection : Sequence { 

    private var __source : [String:abc]?; 

    init(_ list: [String:abc]) { 
     self.__source = list 
    } 

    public func makeIterator() -> AnyIterator<(AnyObject,abcContainer)> { 

     var it = self.__source?.makeIterator(); 
     return AnyIterator { 
       let n = it?.next(); 
       if n == nil { return nil } 
       return (n?.key as AnyObject, abcContainer((n?.value)!)) 
     } 

    } 
} 

Danach zurückgegeben die benutzerdefinierte Sammlung eingewickelte Objekte korrekt.

Verwandte Themen