web-dev-qa-db-fra.com

Comment initialiser des propriétés qui dépendent les unes des autres

Je veux une image à déplacer vers le bas. Si j'appuie sur un bouton, la photo devrait descendre de 1. 

J'ai ajouté la photo et un bouton:

var corX = 0
var corY = 0

var runter: UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton

var image = UIImage(named: "panzerBlau.jpg");
var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40));  //

override func viewDidLoad() {
    super.viewDidLoad()

    panzer.image = image;    //
    self.view.addSubview(panzer);    //

    runter.frame = CGRectMake(100, 30, 10 , 10)
    runter.backgroundColor = UIColor.redColor()
    view.addSubview(runter)
    runter.addTarget(self, action: "fahren", forControlEvents:UIControlEvents.TouchUpInside)
}

Au moins, j’ai dit dans la fonction "fahren" de déplacer l’image de 1 en bas.

func fahren(){
    corY += 1
    panzer.frame = CGRectMake(corX, corY, 30, 40) //
    self.view.addSubview(panzer);
}

Mon problème est donc le suivant: plusieurs erreurs se produisent avec ces logiciels CorX et CorY. Sans eux, cela fonctionne parfaitement, mais c'est comme un bouton à usage unique. Les erreurs sont les suivantes: ViewController.Type n'a pas de membre nommé corX et ViewController.Type n'a pas de panzer de noms de membres. Où j'obtiens les erreurs que j'ai commises // pour montrer en quelles lignes.

PS: J'utilise Xcode Beta5

Voici le code complet sans rien d'autre:

import UIKit

class ViewController: UIViewController {

    var corX = 0
    var corY = 0
    var runter: UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
    var image = UIImage(named: "panzerBlau.jpg");
    var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40));

    override func viewDidLoad() {
        super.viewDidLoad()
            panzer.image = image;
            self.view.addSubview(panzer);

        runter.frame = CGRectMake(100, 30, 10 , 10)
        runter.backgroundColor = UIColor.redColor()
        view.addSubview(runter)
        runter.addTarget(self, action: "fahren", forControlEvents:UIControlEvents.TouchUpInside)
    }

    func fahren(){
        corY += 100
        panzer.frame = CGRectMake(corX, corY, 30, 40)
        self.view.addSubview(panzer);
    }
}
64
Lukas Köhl

@MartinR a souligné le problème majeur ici:

var corX = 0
var corY = 0
var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40))

Le problème est qu’un initialiseur par défaut Swift ne peut pas faire référence à la valeur d’une autre propriété, car au moment de l’initialisation, la propriété n’existait pas encore (car l’instance elle-même n’existait pas encore). En gros, dans l'initialiseur par défaut de panzer, vous vous référez implicitement à self.corX et self.corY - mais il n'y a pas de self car self est exactement ce que nous sommes en train de créer.

Une solution consiste à rendre l'initialiseur paresseux:

class ViewController: UIViewController {
    var corX : CGFloat = 0
    var corY : CGFloat = 0
    lazy var panzer : UIImageView = UIImageView(frame: CGRectMake(self.corX, self.corY, 30, 40))
    // ...
}

C’est légal, car panzer ne sera initialisé que plus tard, quand il est référencé pour la première fois par votre code réel. À cette époque, self et ses propriétés existent.

55
matt

Votre propriété dépendante doit être:

  1. lazy
  2. Avoir un : Type explicite
  3. Utilisez self. pour accéder à d'autres propriétés

Exemple:

let original = "foo"

// Good:
lazy var depend: String = self.original

// Error:
     var noLazy: String = self.original // Error: Value of type '(NSObject) -> () -> URLData' has no member 'original'
lazy var noType         = self.original // Error: Value of type '(NSObject) -> () -> URLData' has no member 'original'
lazy var noSelf: String = original      // Error: Instance member 'original' cannot be used on type 'YourClass'
6
pkamb
//
//  ViewController.Swift
//
//  Created by Shivank Agarwal on 19/05/18.
//  Copyright © 2018 Shivank Agarwal. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    var corX = 0
    var corY = 0
    var runter: UIButton = UIButton()
    var image = UIImage(named: "panzerBlau.jpg")
    var panzer = UIImageView()

    override func viewDidLoad() {
        super.viewDidLoad()
        panzer.image = image;
        self.view.addSubview(panzer);
        panzer.frame = CGRect(x: CGFloat(corX), y: CGFloat(corY), width: 30, height: 40)
        runter.backgroundColor = UIColor.red
        view.addSubview(runter)
        view.addSubview(panzer)
        runter.addTarget(self, action: Selector(("fahren")), for:UIControlEvents.touchUpInside)
    }

    private func fahren(){
        corY += 100
    }

    private func updatePanzerFrame(){
        panzer.frame = CGRect(x: CGFloat(corX), y: CGFloat(corY), width: 30, height: 40)
    }
}

Note: Do not add panzer imageView every time when user tap only add it on viewDidLoad()

 Xcode sample

0
CrazyPro007