Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize properties that depend on each other

I want a picture to move to the bottom. If I press a button the pic should move down by 1.

I added the picture and a button:

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) } 

At least I said in function "fahren" to move the picture down by 1.

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

So my problem is: I get several errors with these corX and corY thing. Without them it works perfectly but than its like a single-use button. The errors are: ViewController.Type does not have a member named corX and ViewController.Type does not have a member names panzer Where I get the errors I made // to show in which lines.

PS: I use Xcode Beta5

Here's the complete code without anything else:

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);     } } 
like image 724
Lukas Köhl Avatar asked Sep 15 '14 18:09

Lukas Köhl


People also ask

What is convenience initializer?

Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer's parameters set to default values.

What is init() in Swift?

Swift init() Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that is required before the new instance is ready for use.

How to initialize object Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }


2 Answers

@MartinR has pointed out the major issue here:

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

The problem is that a Swift default initializer cannot refer to the value of another property, because at the time of initialization, the property doesn't exist yet (because the instance itself doesn't exist yet). Basically, in panzer's default initializer you are implicitly referring to self.corX and self.corY - but there is no self because self is exactly what we are in the middle of creating.

One workaround is to make the initializer lazy:

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

That's legal because panzer doesn't get initialized until later, when it is first referred to by your actual code. By that time, self and its properties exist.

like image 176
matt Avatar answered Oct 20 '22 07:10

matt


Your dependent property needs to be:

  1. lazy
  2. Have an explicit : Type
  3. Use self. to access other properties

Example:

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' 
like image 28
pkamb Avatar answered Oct 20 '22 07:10

pkamb