如何初始化彼此依赖的属性

Luk*_*öhl 74 xcode frame cgrectmake swift

我想要一张图片移到底部.如果按下按钮,图片应向下移动1.

我添加了图片和一个按钮:

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)
}
Run Code Online (Sandbox Code Playgroud)

至少我在函数"fahren"中说过将图片向下移动1.

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

所以我的问题是:我用这些corX和corY的东西得到了几个错误.如果没有它们,它可以完美地工作,但不像是一次性按钮.错误是:ViewController.Type没有名为corX的成员,ViewController.Type没有成员名称panzer我在哪里得到错误//显示哪些行.

PS:我使用Xcode Beta5

这是完整的代码,没有别的东西:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

mat*_*att 63

@MartinR在这里指出了主要问题:

var corX = 0
var corY = 0
var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40))
Run Code Online (Sandbox Code Playgroud)

问题是Swift默认初始值设定项不能引用另一个属性的值,因为在初始化时,该属性尚不存在(因为实例本身尚不存在).基本上,在panzer的默认初始值,你是隐指的是self.corXself.corY-但没有self,因为self这正是我们正在创建的中间.

一种解决方法是使初始化程序变得懒惰:

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

这是合法的,因为panzer直到稍后,当您的实际代码首次引用它时才会初始化.到那时,self它的属性存在.

  • 你试过编译吗?首先,在当前的Xcode版本中,它是`lazy`而不是`@`,即便如此,我仍然会收到相同的错误消息. (6认同)
  • @matt,你的指示不起作用,只是接受它.只有**pkamb**讲述了删除编译器错误应该满足的3个条件:`lazy`,`.self`和`:Type`.虽然你使用`:Type`但你并没有说这很重要.你回答的时间更长,更难阅读.我认为它有更多的赞成是不公平的. (3认同)
  • @MikeS听起来你输入它而不是复制和粘贴.你不能遗漏任何东西.例如,如果省略UIImageView类型声明,则会收到该错误.或者,如果省略惰性声明,您将收到该错误.这一切都是必要的.立即从浏览器中复制并粘贴到您的代码中.它在当前版本的Xcode(Xcode 6 GM)中编译得很好. (2认同)

pka*_*amb 9

您的受抚养财产需要是:

  1. lazy
  2. 有一个明确的 : Type
  3. 使用self.访问其他属性

例:

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'
Run Code Online (Sandbox Code Playgroud)