2015-07-26 33 views
5

Ho creato un'estensione della classe SKSpriteNode. Sto facendo oggetti in mattoni, che hanno un comportamento diverso quando vengono colpitiiOS/Swift - Impossibile impostare Enum Value su Init()

import SpriteKit 

class Brick: SKSpriteNode { 

    enum type { 
     case None, Green, Yellow, Orange, Red 
    } 

    static let colorMap = [ 
     Brick.type.Green : UIColor.greenColor(), 
     Brick.type.Yellow : UIColor.yellowColor(), 
     Brick.type.Orange : UIColor.orangeColor(), 
     Brick.type.Red : UIColor.redColor() 
    ] 

    var brickType = Brick.type.None 

    convenience init (size: CGSize, type: Brick.type) { 
     self.init(color: UIColor.whiteColor(), size: size) 

     // Here I set the initial type and color 
     // The color is assigned just fine, but the brickType 
     // variable is still Brick.type.None 
     self.setType(type) 
    } 

    func gotHit() -> Int { 
     switch (self.brickType) { 
      case Brick.type.Yellow: 
       setType(Brick.type.Green); 
       break; 

      case Brick.type.Orange: 
       setType(Brick.type.Yellow); 
       break; 

      case Brick.type.Red: 
       setType(Brick.type.Orange); 
       break; 

      case Brick.type.Green: // Green 
       self.removeFromParent() 
       return 1 

      default: 
       break 
     } 

     return 0 
    } 

    func setType (typeToSet: Brick.type) { 
     self.brickType = typeToSet // only works when called from gotHit() 
     self.color = Brick.colorMap[typeToSet]! // this works everytime 
    } 
} 

Poi faccio un esempio di questa classe:

let brickPrototype = Brick(size: CGSizeMake(55, 25), type: Brick.type.Green) 

Il mio problema è che, nonostante chiamando setType() all'interno del convenience init(), il valore della variabile brickType pubblica è ancora quella predefinita, Brick.type.None. Il colore è cambiato senza problemi, quindi l'argomento sembra essere passato correttamente.

Se ho impostato la variabile predefinita brickType a Brick.type.Yellow, ed eseguire la funzione gotHit(), la funzione setType() sarà effettivamente cambiare il tipo di mattone per Brick.type.Green, e dopo aver chiamato di nuovo, il nodo viene eliminato dalla vista chiamando self.removeFromParent() . Quindi sono sicuro che il problema è quando chiamo la funzione da convenience init(), anche se non ottengo errori.

+0

Puoi mostrare come stai creando l'oggetto e controllando il tipo? Ho appena incollato il tuo codice in un parco giochi e ha funzionato correttamente – Paulw11

+0

Ancora funziona per me nel parco giochi. – Paulw11

+0

Ho aggiunto un semplice "converti l'enum in una funzione stringa" - https://gist.github.com/paulw11/2010f0474429a679a0b9 e restituisce il valore appropriato – Paulw11

risposta

2

Non è necessario disporre di un valore predefinito se lo si imposta per la prima volta nell'inizializzatore. Non ho provato questo per vedere se risolve il problema, ma ho ripulito il codice un po '.

class Brick: SKSpriteNode { 

enum BrickColorType: UInt { 
    case Red 
    case Orange 
    case Yellow 
    case Green //This order matters for nextColor 

    func color() -> UIColor { 
     switch self { 
     case Green: 
      return .greenColor() //Swift does not need break statements in cases. 
     case Yellow: 
      return .yellowColor() 
     case Orange: 
      return .orangeColor() 
     case Red: 
      return .redColor() 
     } 
    } 

    func nextColor() -> BrickColorType? { 
     return BrickColorType(rawValue: self.rawValue.successor()) //If self = green, this will return nil. 
    } 

} 

var brickType: BrickColorType { 
    didSet { 
     self.color = brickType.color() 
    } 
} 

init (size: CGSize, type: BrickColorType) { 
    brickType = type 
    super.init(texture: nil, color: .whiteColor(), size: size) //Because the earlier one was a convenience init and Xcode was complaining 
    self.color = brickType.color() //Because didSet is not called in initializer 
} 

required init?(coder aDecoder: NSCoder) { //This is just boilerplate required to inherit from any NSObject 
    brickType = .Red //Or whatever else. If you really want to add a None case to the enum, might I suggest instead making brickType optional? 
    super.init(coder: aDecoder) 
} 

func gotHit() -> Int { //Consider making this a Bool 

    if let next = self.brickType.nextColor() { 
     //There is a valid next color 
     brickType = next 
     return 0 
    } 

    //There is no valid next color 
    self.removeFromParent() 
    return 1 

} 
} //Weird formatting because of StackOverflow 
+0

grazie - sicuramente imparato qualcosa! – Heriotza