본문 바로가기
아이폰 개발/ios 개념&튜토리얼

swift 프로퍼티 정리 1

by 인생여희 2022. 10. 24.

swift 프로퍼티 정리 1

 

 종류

 1.저장 프로퍼티 - 인스턴스의 변수 또는 상수를 의미한다. (클래스, 구조체에서 사용)

 

 2.연산 프로퍼티 - 값을 저장하는것이 아니라 특정 연산을 실행한 결과값을 의미한다. (클래스, 구조체, 열거형에 사용)

 

 3.타입 프로퍼티 - 타입에 사용되는 프로퍼티

 

 참고

 프로퍼티 감시자 - 프로퍼티의 값이 변하는 것을 감시한다. 값이 변할때 값의 변화에 따른 특정 작업을 실행한다.

 (저장 프로퍼티에 적용가능)

 

 저장프로퍼티

 var 키워드 - 변수 저장 프로퍼티

 let 키워드 - 상수저장 프로퍼티

 

 저장 프로퍼티를 정의할 때 프로퍼티 기본값과 초깃값을 지정해 줄 수 있다.

 

 

 참고

 *구조체의 저장 프로퍼티가 옵셔널이 아닐때 - 구조체는 저장 프로퍼티를 모두 포함하는 이니셜라이저를 자동으로 생성한다.

 *클래스의 저장 프로퍼티가 옵셔널이 아닐때 - 프로퍼티 기본값을 지정해주거나 사용자 정의 이니셜라이저를 통해 초기화 필요함.

 

struct Person{
    var name: String        //저장 프로퍼티
    var age: Int            //저장 프로퍼티
}


//구조체에는 기본적으로 저장프로퍼티를 매개변수로 갖는 이니셜라이저가 있습니다.
var son : Person = Person(name: "손흥민", age: 30)



class Animal{
    var name: String    //저장 프로퍼티
    var age: Int

    // 클래스는 프로퍼티 기본값을 지정해 주지 않는다면 이니셜라이저를 따로 정의해 주어야 한다.
    // 만약 프로퍼티에 초기값이 할당되어 있다면 이니셜라이저를 따로 정의해줄 필요는 없다.
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}


//인스턴스를 생성할 때 사용자 지정 이니셜라이저를 호출해야 한다.
//그렇지 않으면 초기값을 할당 할 수 없기 때문에 인스턴스 생성이 불가능하다.
var tom:Animal = Animal(name: "tom", age: 12)

 

인스턴스를 생성할 때 이니셜라이저를 통해 초기값을 보내야 하는 이유는 프로퍼티가 옵셔널이 아닌 값으로 선언되어 있기 때문이다.

 

그러므로 인스턴스는 생성할 때 프로퍼티에 값이 꼭 있는 상태여야 한다.

 

그런데 저장 프로퍼티의 값이 있어도 그만, 없어도 그만인 옵셔널이라면 굳이 초기값을 넣어주지 않아도 된다.

 

즉, 이니셜라이저에서 옵셔널 프로퍼티에 꼭 값을 할당해 주지 않아도 된다.

 

//좌표
struct Point{
    // 위치 값이 모두 있어야 하므로 옵셔널이면 안된다.
    var x: Int
    var y: Int
}


//사람의 위치 정보{
class Position{
    //현재 사람의 위치를 모를 수도 있음
    var point: Point?
    
    let name: String
    
    init( name: String) {
        self.name = name
    }
}

//이름은 필수지만 위치는 모를 수 있다.
let kimPosition = Position(name: "kim")

//위치를 알게되면 그 때 위치 값을 할당해 준다.
kimPosition.point = Point(x: 10, y: 10)

 

 

지연 저장 프로퍼티 - 호출이 있어야 값을 초기화 하며, 이때 lazy 키워드를 사용합니다.

 

상수 키워드 let은 인스턴스가 완전히 생성되기 전에 초기화 해야 하는 키워드므로 필요할 때 값을 할당하는 지연 저장 프로퍼티와는 맞지 않습니다.

 

따라서 지연 저장 프로퍼티는 var 키워드를 사용해서 변수로 저장한다.

 

언제사용하나?

클래스 인스턴스의 저장 프로퍼티에 다른 클래스 인스턴스나 구조체 인스턴스를 할당해야 할 때가 있습니다.

이럴 때 인스턴스를 초기화 하면서 저장 프로퍼티로 쓰이는 인스턴스들이 한 번에 생성되어야 한다면?

 

또, 굳이 모든 저장 프로퍼티를 사용할 필요가 없다면?

 

왜 사용하나?

지연 저장 프로퍼티를 잘 사용하면 불필요한 성능 저하나 공간 낭비를 줄일 수 있습니다.

 

//사람의 위치 정보{
class PositionLazy{
    
    //지연 저장 프로퍼티
    lazy var point: Point = Point(x: 15, y: 13)
    
    let name: String
    
    init( name: String) {
        self.name = name
    }
}


let hongPosition = PositionLazy(name: "hong")


// 이 코드를 통해 point 프로퍼티로 처음 접근할 때
// point 프로퍼티의 Point 가 생성됩니다.
print(hongPosition.point)
//Point(x: 15, y: 13)

 

[참고]

다중 스레드와 지연 저장 프로퍼티

! 다중 스레드 환경에서 지연 저장 프로퍼티에 동시다발적으로 접근할 때는 한번만 초기화 된다는 보장이 없다.

! 생성되지 않은 지연 저장 프로퍼티에 많은 스레드가 비슷한 시점에 접근한다면, 여러번 초기화될 수 있다.

 

연산 프로퍼티의 정의와 활용

struct CoordinatePoint{
    
    var x:Int //저장프로퍼티
    var y:Int
    
    
    // 연산 프로퍼티
    var oppositePoint: CoordinatePoint{
    
        // 접근자 - 읽기전용
        get{
            return CoordinatePoint(x: -x, y: -y)
        }
        
        // 설정자 - 쓰기 전용
        // 설정자의 매개변수로 원하는 이름을 소괄호에 넣어주면
        // set 메서드 내부에서 전달 받은 전달 인자를 사용할 수 있다.
        set(opposite){
            x = -opposite.x
            y = -opposite.y
        }
    }
}

var choiPosition = CoordinatePoint(x: 10, y: 20)

//현재 좌표
print(choiPosition)
//CoordinatePoint(x: 10, y: 20)


//대칭좌표 출력
print(choiPosition.oppositePoint)
//CoordinatePoint(x: -10, y: -20)


//연산프로퍼티에 대칭좌표를 설정하고
choiPosition.oppositePoint = CoordinatePoint(x: 40, y: 50)

//대칭좌표 출력
print(choiPosition)
//CoordinatePoint(x: -40, y: -50)

 

test.zip
0.02MB