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);
}
}
@MartinR has pointed out the major issue here:
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 toself.corX
andself.corY
- but there is noself
becauseself
is exactly what we are in the middle of creating.One workaround is to make the initializer lazy:
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.I'm addressing the title of the question:
Both lazy and computed properties help you deal with when the initial value for a property is not known until after the object is initialized. But there are some differences. I've highlighted the differences with bold.
If you simply need to initialize a variable after some other variable(s) is initialized then you should use
lazy
ie if the point is to simply add a delay (so all required properties get initialized before) then using lazy is the right way to go for it.But if you need to constantly change a variable based on another, then you need a computed property that would work both ways:
if you change the lazy property's value it won't affect the storied properties that it was based on. see here
A good example for using a lazy property would be that once you have
firstName
&lastName
then you would lazily instantiate afullName
and likely you would never change the firstName lastName of your object your fullName is a onetime only... Or perhaps something that can only be done bylazy
properties is that up until you don't access the property it won't ever get initialized, therefore this would decrease the initialization load of your class. Loading a heavy calculation.Additionally using the
lazy
will signal to other developers: "Hey first go read about the other properties and understand what they are...then come to this lazy property...since the value of this is based on them + this is likely a heavy computation that shouldn't be accessed too early..."As for computed property a good example would be if you set the temperature to Fahrenheit then you also want your celsius temperature to change its value...and if you set the celsius temperature then again you want to change your Fahrenheit value.
As a result computed property would add extra computation...and if your computation is very simple and isn't called too frequently then it's nothing to worry about but if it get's called too often or is very CPU-consuming then it might be better to think of other options...
Your dependent property needs to be:
lazy
: Type
self.
to access other propertiesExample: