[swift] 속성 게터와 세터

이 간단한 클래스를 사용하면 컴파일러 경고가 나타납니다.

x자체 setter / getter 내 에서 수정 / 액세스 시도

내가 이것을 이렇게 사용할 때 :

var p: point = Point()
p.x = 12

EXC_BAD_ACCESS를 얻습니다. ivar을 명시 적으로 백업하지 않고 어떻게해야합니까?

class Point {

    var x: Int {
        set {
            x = newValue * 2 //Error
        }
        get {
            return x / 2 //Error
        }
    }
    // ...
}



답변

세터와 게터는 다음에 적용됩니다 computed properties. 이러한 속성에는 인스턴스에 스토리지가 없습니다. 게터의 값은 다른 인스턴스 속성에서 계산됩니다. 귀하의 경우 x할당 할 필요 가 없습니다 .

명시 적으로 : “명백한 ivar을 지원하지 않고 어떻게해야합니까?” 할 수 없습니다- 계산 된 속성을 백업하기 위해 무언가 가 필요 합니다. 이 시도:

class Point {
  private var _x: Int = 0             // _x -> backingX
  var x: Int {
    set { _x = 2 * newValue }
    get { return _x / 2 }
  }
}

특히 Swift REPL에서 :

 15> var pt = Point()
pt: Point = {
  _x = 0
}
 16> pt.x = 10
 17> pt
$R3: Point = {
  _x = 20
}
 18> pt.x
$R4: Int = 10


답변

스위프트의 세터 / 게터는 ObjC와 매우 다릅니다. 이 속성은 계산 된 속성이되므로 ObjC에서 와 같이 지원 변수 가 없습니다_x .

아래 솔루션 코드에서는 아무것도 저장 xTimesTwo하지 않고 단순히 결과를 계산 하는 것을 볼 수 있습니다 x.

계산 된 속성에 대한 공식 문서를 참조하십시오 .

원하는 기능은 속성 관찰자 일 수도 있습니다 .

필요한 것은 :

var x: Int

var xTimesTwo: Int {
    set {
       x = newValue / 2
    }
    get {
        return x * 2
    }
}

setter / getter 내에서 다른 속성을 수정할 수 있습니다.


답변

속성 관찰기를 사용하여 설정 값을 사용자 정의 할 수 있습니다. 이렇게하려면 ‘set’대신 ‘didSet’을 사용하십시오.

class Point {

var x: Int {
    didSet {
        x = x * 2
    }
}
...

게터에 관해서는 …

class Point {

var doubleX: Int {
    get {
        return x / 2
    }
}
...


답변

GoZoner의 답변을 자세히 설명하려면 다음을 수행하십시오.

여기서 진짜 문제는 게터를 재귀 적으로 호출한다는 것입니다.

var x:Int
    {
        set
        {
            x = newValue * 2 // This isn't a problem
        }
        get {
            return x / 2 // Here is your real issue, you are recursively calling
                         // your x property's getter
        }
    }

위의 코드 주석과 같이 x 속성의 getter를 무한대로 호출하면 EXC_BAD_ACCESS 코드를 얻을 때까지 계속 실행됩니다 (Xcode 놀이터 환경의 오른쪽 하단에서 스피너를 볼 수 있음).

Swift 문서 의 예제를 고려하십시오 .

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

중심 계산 속성이 변수 선언에서 어떻게 수정되거나 자신을 반환하지 않는지 확인하십시오.


답변

재정의 setter하고 getter신속한 변수를 위해 아래 주어진 코드를 사용하십시오.

var temX : Int?
var x: Int?{

    set(newX){
       temX = newX
    }

    get{
        return temX
    }
}

getter / setter가 재정의되는 동일한 변수에 액세스하려고하면 무한 루프가 발생하므로 변수 값을 임시 변수에 유지해야합니다.

이렇게 간단하게 setter를 호출 할 수 있습니다

x = 10

주어진 코드 줄 아래에서 Getter가 실행됩니다.

var newVar = x


답변

재귀 적으로 정의 x하고 x있습니다. 누군가가 당신에게 몇 살을 묻는 것처럼? 그리고 당신은 “나의 나이 두 배입니다”라고 대답합니다. 의미가 없습니다.

당신은 내가 두 번 존의 연령이나 다른 변수입니다 말을해야 하지만 자신.

계산 된 변수는 항상 다른 변수에 의존합니다.


엄지 손가락의 규칙은 getter 에서 속성 자체에 절대 액세스 하지 않습니다 . 왜냐하면 다른 트리거 될 것이고 다른 트리거 될 것이다. . . 인쇄조차하지 마십시오. 인쇄는 인쇄하기 전에 값을 ‘얻어야’하기 때문에 필요합니다!getget

struct Person{
    var name: String{
        get{
            print(name) // DON'T do this!!!!
            return "as"
        }
        set{
        }
    }
}

let p1 = Person()

따라서 다음과 같은 경고가 나타납니다.

자체 getter 내에서 ‘name’에 액세스하려고합니다.

오류는 다음과 같이 모호합니다.

여기에 이미지 설명을 입력하십시오

대안으로 사용하고 싶을 수도 있습니다 didSet. 함께 didSet하기 전에 설정되고 단지로 설정되었다 값에 보류를 얻을 것이다. 자세한 내용은 이 답변을 참조하십시오 .


답변

업데이트 : Swift 4

아래 클래스에서 setter와 getter가 변수에 적용됩니다. sideLength

class Triangle: {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) { //initializer method
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
        get { // getter
            return 3.0 * sideLength
        }
        set(newValue) { //setter
            sideLength = newValue / 4.0
        }
   }

객체 생성

var triangle = Triangle(sideLength: 3.9, name: "a triangle")

얻는 사람

print(triangle.perimeter) // invoking getter

세터

triangle.perimeter = 9.9 // invoking setter