var
키워드 사용) 또는 저장된 프로퍼티 상수 (constant stored properties) (let
키워드 사용)로 쓸 수 있습니다.FixedLengthRange
라는 구조체를 정의합니다. 이 구조체는 범위 길이가 생성된 후에 변경할 수 없는 정수 범위를 나타냅니다:FixedLengthRange
의 인스턴스는 firstValue
라는 저장된 프로퍼티 변수가 있으며 length
라는 저장된 프로퍼티 상수가 있습니다. 위의 예제에서 length
는 새 범위가 생성될 때 초기화되며 프로퍼티 상수 이므로 변경할 수 없습니다.rangeOfFourItems
는 let
키워드를 사용하여 상수로 선언되어 있기 때문에 firstValue
가 프로퍼티 변수 이지만 firstValue
프로퍼티를 변경할 수 없습니다.lazy
수정자를 붙여 나타냅니다.NOTE 인스턴스 초기화가 완료된 후에도 초기값이 없을 수 있으므로 지연 프로퍼티는var
키워드를 사용하여 변수로 선언해야 합니다. 프로퍼티 상수는 초기화가 완료되기 전에 항상 값을 가지고 있어야 하므로 lazy로 선언할 수 없습니다.
DataImporter
와 DataManager
라는 2개의 클래스를 정의합니다:DataManager
클래스는 String
값의 빈 배열로 초기화 되는 data
라는 저장된 프로퍼티를 가지고 있습니다. 나머지 기능이 보이진 않지만 DataManager
클래스의 목적은 String
데이터의 배열을 관리하고 접근을 제공합니다.DataManager
클래스의 기능적 부분은 파일로 부터 데이터를 가져올 수 있습니다. 이 기능은 DataImporter
클래스로 부터 제공되고 초기화 하는데 시간이 많이 걸린다고 가정합니다. DataImporter
인스턴스가 초기화 될 때 DataImporter
인스턴스는 파일을 열고 메모리로 내용을 읽어야 하기 때문일 수 있습니다.DataManager
인스턴스는 파일로 부터 데이터를 가져올 필요 없이 데이터를 관리할 수 있으므로 DataManager
가 생성될 때 새로운 DataImporter
인스턴스를 생성할 필요가 없습니다. 대신에 DataImporter
인스턴스를 처음 사용하는 경우에 생성하는 것이 더 합리적입니다.lazy
수식어가 붙어 있으므로 importer
프로퍼티의 DataImporter
인스턴스는 filename
프로퍼티를 조회할 때처럼 importer
프로퍼티에 처음 접근될 때 생성됩니다:NOTElazy
수식어가 표시된 프로퍼티는 여러 쓰레드에서 동시에 접근되고 프로퍼티가 아직 초기화되지 않은 경우 프로퍼티가 한번만 초기화 된다는 보장이 없습니다.
Point
는 x, y 좌표의 위치를 캡슐화 합니다.Size
는 width
와 height
를 캡슐화 합니다.Rect
는 원점과 크기로 사각형을 정의합니다.Rect
구조체는 center
라는 계산된 프로퍼티를 제공합니다. Rect
에 현재 중앙 위치는 항상 origin
과 size
로 계산될 수 있고 명시적으로 Point
값으로 저장할 필요가 없습니다. 대신에 Rect
는 center
라는 계산된 변수를 위한 getter와 setter를 정의하고 실제 저장된 프로퍼티 처럼 사각형의 center
를 동작하도록 합니다.square
라는 새로운 Rect
변수를 생성합니다. square
변수는 (0, 0)
의 원점으로 너비와 높이를 10
으로 초기화 됩니다. 이 사각형은 아래의 다이어그램에서 밝은 초록색 사각형으로 표현됩니다.square
변수의 center
프로퍼티는 점 구문 (square.center
)으로 접근되고 center
에 대한 getter를 호출하여 현재 프로퍼티 값을 조회합니다. 존재하는 값을 반환하기 보다 getter는 실질적으로 사각형의 중심을 나타내는 새로운 Point
를 계산하고 반환합니다. 위에 볼 수 있듯이 getter는 (5, 5)
의 중심점을 반환합니다.center
프로퍼티는 (15, 15)
의 새로운 값으로 설정되어 새로운 위치로 사각형이 위와 우측으로 이동합니다. center
프로퍼티 설정은 center
의 setter를 호출하고 origin
프로퍼티에 저장된 x
와 y
값을 변경하고 사각형을 새로운 위치로 이동합니다.newValue
라는 기본 이름이 사용됩니다. 다음은 이러한 짧은 표현의 이점을 가지는 Rect
구조체를 나타냅니다:Rect
구조체를 나타냅니다:return
은 암시적 반환의 함수 (Functions With an Implicit Return) 에서 설명 했듯이 함수의 return
생략 규칙과 동일합니다.NOTE 값이 고정되어 있지 않기 때문에 읽기전용 계산된 프로퍼티를 포함하여 계산된 프로퍼티는var
키워드를 포함하는 프로퍼티 변수로 선언되어야 합니다.let
키워드는 인스턴스 초기화의 부분으로 한번 설정되면 값을 변경할 수 없음을 나타내기 위해 오직 프로퍼티 상수에서만 사용됩니다.
get
키워드와 그것의 중괄호를 삭제하고 읽기전용 계산된 프로퍼티를 간편하게 선언할 수 있습니다:width
, height
, 그리고 depth
프로퍼티를 가지는 3D 사각형 박스를 나타내는 Cuboid
라는 새로운 구조체를 정의합니다. 이 구조체는 직육면체의 현재 부피를 계산하고 반환하는 volume
이라는 읽기전용 계산된 프로퍼티를 가지고 있습니다. 특정 volume
값에 width
, height
, 그리고 depth
의 어떤값을 사용하여야 하는지 모호하므로 volume
을 설정하는 것은 의미가 없습니다. 그럼에도 불구하고 현재 계산된 부피를 알 수 있도록 외부에 읽기전용 계산된 프로퍼티로 제공되는 Cuboid
는 유용합니다.willSet
은 값이 저장되기 직전에 호출됩니다.didSet
은 새로운 값이 저장되자마자 호출됩니다.willSet
관찰자를 구현한다면 상수 파라미터로 새로운 프로퍼티 값이 전달됩니다. willSet
구현의 일부로 이 파라미터에 특정 이름을 가질 수 있습니다. 파라미터 명과 구현 내에 소괄호를 작성하지 않으면 파라미터는 newValue
의 기본 파라미터 명으로 만들어 질 수 있습니다.didSet
관찰자를 구현한다면 예전 프로퍼티 값을 포함한 상수 파라미터가 전달됩니다. 파라미터 명을 사용하거나 oldValue
인 기본 파라미터 명을 사용할 수 있습니다. didSet
관찰자 내의 프로퍼티에 값을 할당한다면 새로운 값으로 방금 설정한 값을 대체합니다.NOTE 수퍼 클래스 프로퍼티의willSet
과didSet
관찰자는 수퍼 클래스 초기화가 호출된 후 하위 클래스 초기화에서 프로퍼티가 설정될 때 호출됩니다. 수퍼 클래스가 초기화 호출되기 전에 클래스 자체 프로퍼티를 설정하는 동안에는 호출되지 않습니다.초기화 위임에 대한 자세한 내용은 값 타입에 대한 초기화 구문 위임 (Initializer Delegation for Value Types) 와 클래스 타입에 대한 초기화 구 위임 (Initializer Delegation for Class Types) 를 참고 바랍니다.
willSet
과 didSet
동작에 대한 예입니다. 아래 예제는 사람이 걷는동안의 걸음 수를 측정하는 StepCounter
라는 새로운 클래스를 정의합니다. 이 클래스는 만보계 또는 다른 걸음 측정기의 입력 데이터와 함께 사용하여 일상생활에서 사람의 운동 루틴을 추적할 수 있습니다.StepCounter
클래스는 Int
타입의 totalSteps
프로퍼티를 선언합니다. 이것은 willSet
과 didSet
관찰자를 가진 저장된 프로퍼티 입니다.totalSteps
의 willSet
과 didSet
관찰자는 새로운 값이 프로퍼티에 할당될 때마다 호출됩니다. 새로운 값이 현재값과 같더라도 항상 호출됩니다.willSet
관찰자는 새로운 값을 위한 newTotalSteps
의 사용자 파라미터 명을 사용합니다. 이 예제는 간단하게 설정된 값을 출력합니다.didSet
관찰자는 totalSteps
값이 업데이트 되고난 후에 호출됩니다. 이것은 오래된 값에 대해 totalSteps
의 새로운 값과 비교합니다. 걸음수가 증가했다면 걸음수가 얼마나 증가하였는지 출력합니다. didSet
관찰자는 오래된 값에 대한 사용자 파라미터 명을 제공하지 않고 대신에 oldValue
의 기본 이름을 사용합니다.NOTE 관찰자를 가진 프로퍼티를 in-out 파라미터로 함수에 전달하면willSet
과didSet
관찰자는 항상 호출됩니다. 이것은 in-out 파라미터에 대한 copy-in-copy-out 메모리 모델 때문에 그렇습니다. 값은 함수 끝에서 프로퍼티에 항상 다시 작성됩니다. in-out 파라미터에 대한 자세한 내용은 In-Out 파라미터 (In-Out Parameters) 를 참고 바랍니다.
wrappedValue
프로퍼티를 정의한 구조체, 열거형 또는 클래스를 만듭니다. 아래 코드에서 TwelveOrLess
구조체는 래핑하는 값이 항상 12와 같거나 더 작은 숫자가 포함됩니다. 더 큰 숫자를 저장하도록 하면 12가 저장됩니다.NOTE 위의 예제에서number
선언부는TwelveOrLess
의 구현에서만number
가 사용될 수 있도록private
로 변수를 표기합니다. 다른곳에서 작성된 코드는wrappedValue
를 위한 getter와 setter를 사용하여 값에 접근하고 직접적으로number
를 사용할 수 없습니다.private
에 대한 정보는 접근 제어 (Access Control) 를 참고 바랍니다.
TwelveOrLess
프로퍼티 래퍼를 사용하여 사각형을 저장하는 구조체입니다:height
와 width
프로퍼티는 TwelveOrLess.number
를 0으로 설정하는 TwelveOrLess
의 정의로 부터 초기값을 얻습니다. rectangle.height
에 숫자 10을 저장하는 것은 그 숫자가 작은 숫자이기 때문에 성공적으로 저장합니다. 24를 저장하려고 하면 24는 프로퍼티 setter의 규칙에 비해 큰 숫자이므로 실질적으로 12가 저장됩니다.@TwelveOrLess
를 작성하는 대신에 TwelveOrLess
구조체에 명시적으로 프로퍼티를 래핑하는 이전 코드 목록으로 부터의 SmallRectangle
입니다:_height
와 _width
프로퍼티는 프로퍼티 래퍼의 인스턴스인 TwelveOrLess
를 저장합니다. height
와 width
에 대한 getter와 setter는 wrappedValue
프로퍼티에 접근합니다.TwelveOrLess
에 정의한 number
초기값으로 래핑된 프로퍼티에 대한 초기값을 설정합니다. 이 프로퍼티 래퍼를 사용한 코드는 TwelveOrLess
로 래핑된 프로퍼티에 다른 초기값을 지정할 수 없습니다. 예를 들어 SmallRectangle
에 정의에 height
와 width
초기값을 지정할 수 없습니다. 초기값 설정을 지원하거나 다른 커스터마이징을 지원하려면 프로퍼티 래퍼는 초기화를 추가해줘야 합니다. 다음은 래핑과 최대값을 설정하는 초기화를 정의하는 SmallNumber
라는 확장된 TwelveOrLess
를 나타냅니다:SmallNumber
의 정의는 init()
, init(wrappedValue:)
, init(wrappedValue:maximum:)
의 3개의 초기화를 포함합니다. 아래는 래핑값과 최대값 설정을 사용하는 예입니다. 자세한 내용은 초기화 (Initialization) 를 참고 바랍니다.init()
을 사용합니다. 예를 들어:height
와 width
를 래핑한 SmallNumber
의 인스턴스는 SmallNumber()
호출로 생성됩니다. 초기화 내부의 코드는 기본값 0과 12을 사용하여 초기 래핑값과 초기 최대값을 설정합니다. 프로퍼티 래퍼는 SmallRectangle
에 TwelveOrLess
를 사용한 이전 예제처럼 모든 초기값을 제공합니다. 예제와 반대로 SmallNumber
는 프로퍼티 선언의 일부분으로 초기값 작성을 제공합니다.init(wrappedValue:)
를 사용합니다. 예를 들어:= 1
을 작성하면 init(wrappedValue:)
초기화 호출에 전달됩니다. height
와 width
를 래핑한 SmallNumber
의 인스턴스는 SmallNumber(wrappedValue: 1)
호출로 생성됩니다. 이 초기화는 래핑된 값을 사용하고 기본 최대값으로 12를 사용합니다.init(wrappedValue:maximum:)
초기화를 사용합니다:height
를 래핑한 SmallNumber
의 인스턴스는 SmallNumber(wrappedValue: 2, maximum: 5)
를 호출하여 생성되고 width
를 래핑한 인스턴스는 SmallNumber(wrappedValue: 3, maximum: 4)
를 호출하여 생성됩니다.wrappedValue
인자처럼 취급하고 이 인자를 받을 수 있는 초기화를 사용합니다. 예를 들어:height
를 래핑한 SmallNumber
의 인스턴스는 기본 최대값은 12를 사용하는 SmallNumber(wrappedValue: 1)
을 호출하여 생성됩니다. width
를 래핑한 이 인스턴스는 SmallNumber(wrappedValue: 2, maximum: 9)
를 호출하여 생성됩니다.flushDatabaseConnection()
메서드를 노출할 수 있습니다. 투영된 값의 이름은 앞에 달러 표시 ($
)가 붙는 것을 제외하면 래핑된 값과 동일합니다. 코드에서 $
로 시작하는 프로퍼티를 정의할 수 없기 때문에 투영된 값은 정의한 프로퍼티를 절대 방해하지 않습니다.SmallNumber
예제에서 프로퍼티에 큰 숫자로 설정하려고 하면 프로퍼티 래퍼가 이전에 저장한 숫자로 변경합니다. 아래의 코드는 새로운 값을 저장하기 전에 프로퍼티 래퍼가 프로퍼티에 새로운 값을 변경하는지 판단하기 위해 SmallNumber
구조체에 projectedValue
프로퍼티를 추가합니다.someStructure.$someNumber
는 래퍼의 투영된 값에 접근합니다. 4와 같은 작은 숫자를 저장한 후에 someStructure.$someValue
의 값은 false
입니다. 그러나 55와 같은 큰 숫자를 저장한 후에 투영된 값은 true
입니다.self
를 반환할 수 있습니다.self.
을 생략할 수 있습니다. 다음 예제의 코드는 $height
와 $width
로 height
와 width
래퍼의 투영된 값을 참조합니다:height
와 width
접근은 다른 프로퍼티 접근과 동일한 동작입니다. 예를 들어 resize(to:)
에 코드는 프로퍼티 래퍼를 사용하는 height
와 width
에 접근합니다. resize(to: .large)
를 호출하면 .large
스위치 케이스가 사각형의 높이와 너비를 100으로 설정합니다. 래퍼는 프로퍼티의 값이 12보다 더 큰 값으로 되는 것을 막고 값이 변경되었다는 사실을 기록하기 위해 투영된 값을 true
로 설정합니다. resize(to:)
끝에서 반환 구문은 프로퍼티 래퍼가 height
또는 width
를 변경했는지 판단하기 위해 $height
와 $width
를 체크합니다.NOTE 전역 상수와 변수는 지연 저장된 프로퍼티 (Lazy Stored Properties) 와 유사한 방법으로 항상 느리게 계산됩니다. 지연 저장된 프로퍼티와 다르게 전역 상수와 변수는lazy
수식어가 필요하지 않습니다.지역 상수와 변수는 절대 느리게 계산되지 않습니다.
myNumber
는 프로퍼티 래퍼로 SmallNumber
를 사용합니다.SmallNumber
를 적용할 때와 마찬가지로 myNumber
값을 10으로 설정하는 것이 유효합니다. 프로퍼티 래퍼는 12보다 큰 값을 허용하지 않기 때문에 myNumber
를 24 대신 12로 설정합니다.NOTE 저장된 인스턴스 프로퍼티와 다르게 저장된 타입 프로퍼티에는 기본값을 항상 주어야 합니다. 이는 초기화 시 저장된 타입 프로퍼티에 값을 할당할 수 있는 초기화를 가지고 있지 않기 때문입니다.저장된 타입 프로퍼티는 처음 접근될 때 느리게 초기화 됩니다. 여러 쓰레드가 동시에 접근할 때도 한번만 초기화 되도록 보장하고lazy
수식어가 필요하지 않습니다.
static
키워드로 타입 프로퍼티를 정의합니다. 클래스 타입의 계산된 타입 프로퍼티의 경우 class
키워드를 대신 사용하여 하위 클래스에서 상위 클래스의 구현을 재정의 할 수 있습니다. 아래의 예제는 저장된 타입 프로퍼티와 계산된 타입 프로퍼티 구문을 보여줍니다:NOTE 위 예제의 계산된 타입 프로퍼티는 읽기전용 계산된 타입 프로퍼티를 위한 것이지만 계산된 인스턴스 프로퍼티와 동일한 구문을 사용하여 읽기 쓰기 계산된 타입 프로퍼티를 정의 할 수도 있습니다.
0
부터 10
까지의 정수인 오디오 레벨을 가지고 있습니다.0
이면 해당 채널의 조명은 켜지지 않습니다. 오디오 레벨이 10
이면 모든 채널의 조명은 켜집니다. 이 그림에서 왼쪽 채널은 현재 9
의 레벨을 가지고 오른쪽 채널은 현재 7
의 레벨을 가집니다:AudioChannel
구조체의 인스턴스로 표현됩니다:AudioChannel
구조체는 기능 제공을 위해 2개의 저장된 타입 프로퍼티를 정의합니다. 첫번째 thresholdLevel
은 오디오 레벨이 가질 수 있는 최대값을 정의합니다. 모든 AudioChannel
인스턴스를 위한 10
의 상수값입니다. 오디오 신호가 10
의 값보다 높게 오면 아래에서 설명된대로 기준값으로 변경합니다.maxInputLevelForAllChannels
라는 저장된 프로퍼티 변수 입니다. 이것은 AudioChannel
인스턴스로 부터 받은 최대 입력값을 추적합니다. 초기값 0
부터 시작합니다.AudioChannel
구조체는 채널의 현재 오디오 레벨을 0
에서 10
으로 표현하는 currentLevel
이라는 저장된 인스턴스 프로퍼티도 정의합니다.currentLevel
프로퍼티는 currentLevel
이 설정될 때마다 값을 체크하는 didSet
프로퍼티 관찰자를 가지고 있습니다. 이 관찰자는 2가지를 체크합니다:currentLevel
의 새로운 값이 thresholdLevel
에 허용된 값보다 크면 프로퍼티 관찰자는 currentLevel
을 thresholdLevel
로 설정합니다.currentLevel
의 새로운 값이 AudioChannel
인스턴스에서 받은 값이 이전 값보다 크면 프로퍼티 관찰자는 새로운 currentLevel
값을 maxInputLevelForAllChannels
타입 프로퍼티에 저장합니다.NOTE 2가지 체크사항 중 첫번째 항목에서didSet
관찰자는currentLevel
을 다른 값으로 설정합니다. 그러나 이것이 관찰자를 다시 호출하진 않습니다.
leftChannel
과 rightChannel
이라 하는 2개의 새로운 오디오 채널을 생성하기 위해 AudioChannel
구조체를 사용할 수 있습니다:currentLevel
을 7
로 설정하면 maxInputLevelForAllChannels
타입 프로퍼티가 7
로 업데이트 된 것을 볼 수 있습니다:currentLevel
을 11
로 설정하면 오른쪽 채널의 currentLevel
프로퍼티가 10
의 최대값으로 변경된 것을 볼 수 있고 maxInputLevelForAllChannels
타입 프로퍼티가 10
으로 업데이트 된 것을 볼 수 있습니다: