Programing

서로 의존하는 속성을 초기화하는 방법

crosscheck 2020. 10. 25. 11:37
반응형

서로 의존하는 속성을 초기화하는 방법


사진이 아래로 이동하고 싶습니다. 버튼을 누르면 사진이 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)
}

적어도 나는 "화씨"함수에서 그림을 1만큼 아래로 이동하라고 말했다.

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

그래서 내 문제는 다음과 같습니다. corX 및 corY에 대해 몇 가지 오류가 발생합니다. 그것들이 없으면 완벽하게 작동하지만 일회용 버튼과 같습니다. 오류는 다음과 같습니다. ViewController.Type에는 corX라는 멤버가없고 ViewController.Type에는 멤버 이름 panzer가 없습니다. 내가 만든 오류가 // 어떤 줄에 표시되는지 확인합니다.

추신 : 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);
    }
}

@MartinR은 여기에서 주요 문제를 지적했습니다.

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

문제는 초기화시 속성이 아직 존재하지 않기 때문에 Swift 기본 초기화 프로그램이 다른 속성의 값을 참조 할 수 없다는 것입니다 (인스턴스 자체가 아직 존재하지 않기 때문에). 기본적으로,에서 panzer의 기본 당신은 암시 적으로 언급되지 초기화 self.corX하고 self.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))
    // ...
}

이는 panzer실제 코드에서 처음 참조 될 때까지 초기화되지 않기 때문에 합법적 입니다. 그때까지 self그 속성이 존재합니다.


종속 자산은 다음과 같아야합니다.

  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'

나는 질문의 제목을 언급하고 있습니다.

지연 및 계산 된 속성은 객체가 초기화 될 때까지 속성의 초기 값을 알 수 없는 경우를 처리하는 데 도움이됩니다 . 그러나 몇 가지 차이점이 있습니다. 차이점을 굵게 강조했습니다.

다른 변수가 초기화 된 후 변수를 초기화해야하는 lazy경우, 즉 단순히 지연을 추가하는 것이 중요하다면 (필요한 모든 속성이 이전에 초기화 됨) lazy를 사용하는 것이 올바른 방법입니다. 그것.

그러나 다른 변수를 기반으로 지속적 으로 변수를 변경 해야하는 경우 두 가지 방식으로 작동하는 계산 된 속성이 필요합니다 .

  • 계산 된 속성이 설정 되면 관련 저장된 속성을 변수로 설정합니다.
  • 저장된 속성이 설정 (또는 다시 재설정 )되면 계산 된 속성의 변경을 트리거합니다.

게으른 속성의 값을 변경하면 기반이 된 계층 속성에 영향을주지 않습니다. 여기를 참조 하십시오


당신은 일단 있다는 것 게으른 속성을 사용하는 좋은 예 firstName& lastName다음 유유히를 인스턴스화 할 fullName개체의 이름 성을 가능성 변경 절대은 FULLNAME 님이 만 수행 할 수 있습니다 일회성 만 ... 아니면 뭔가입니다 lazy속성에 의해 속성에 액세스하지 않을 때까지는 초기화되지 않으므로 클래스의 초기화로드 감소 합니다. 무거운 계산을 로드합니다 .

또한 다른 개발자에게 lazy의지 신호사용합니다 . "먼저 다른 속성에 대해 읽어보고 그 속성이 무엇인지 이해 한 다음이 게으른 속성에 도달합니다 ...이 값은 속성을 기반으로하기 때문에 + 너무 일찍 접근하면 안되는 계산 ... "

당신이에 온도 설정하면 좋은 사례가 될 것이다 계산 된 속성으로 화씨 당신은 또한 당신의 원하는 섭씨 온도 값을 변경하는 ... 그리고 당신이 설정 한 경우 섭씨 다시 온도를 당신은 당신의 변경하려는 화씨 값입니다.

결과적으로 계산 된 속성은 추가 계산을 추가 할 것입니다. 계산이 매우 간단하고 너무 자주 호출되지 않으면 걱정할 필요가 없지만 너무 자주 호출되거나 CPU를 많이 소모하는 경우 더 좋을 수 있습니다. 다른 옵션을 생각하려면 ...


//
//  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 샘플

참고 URL : https://stackoverflow.com/questions/25854300/how-to-initialize-properties-that-depend-on-each-other

반응형