인스턴스 프로퍼티는 특정 타입의 인스턴스에 속하는 프로퍼티이다. 타입의 새로운 인스턴스를 만들 때마다 다른 인스턴스와는 별도로 고유한 프로퍼티 값을 설정한다.
또한 해당 타입의 인스턴스가 아닌 타입 자체에 속하는 프로퍼티를 정의할 수도 있다. 생성하는 해당 타입의 인스턴스 수에 관계없이 이러한 프로퍼티의 복사본은 하나만 있다. 이런 프로퍼티의 종류를 타입 프로퍼티 (type properties) 라고 한다.
타입 프로퍼티는 C에서 static 상수 처럼 모든 인스턴스에서 사용할 수 있는 상수 프로퍼티나 C에서 static 변수 처럼 타입의 모든 인스턴스에 전역인 값을 저장하는 프로퍼티 변수와 같은 특정 타입에 모든 인스턴스에 보편적인 값을 정의하는 데 유용하다.
저장된 타입 프로퍼티는 변수 또는 상수 일 수 있다. 계산된 타입 프로퍼티는 계산된 인스턴스 프로퍼티와 같은 방식으로 항상 프로퍼티 변수로 선언된다.
Note
저장된 인스턴스 프로퍼티와 다르게 저장된 타입 프로퍼티에는 기본값을 항상 주어야 한다. 이는 초기화 시 저장된 타입 프로퍼티에 값을 할당할 수 있는 초기화를 가지고 있지 않기 때문이다.
저장된 타입 프로퍼티는 처음 접근될 때 느리게 초기화된다. 여러 쓰레드가 동시에 접근할 때도 한번만 초기화 되도록 보장하고 lazy 수식어가 필요하지 않다.
C와 Objective-C에서 전역 static 변수로 타입과 연관된 static 상수와 변수를 정의한다. 그러나 Swift에서 타입 프로퍼티는 타입의 외부 중괄호 내에 타입의 정의 부분으로 작성되고 각 타입 프로퍼티는 지원되는 타입으로 명시적으로 범위가 지정된다.
static 키워드로 타입 프로퍼티를 정의한다. 클래스 타입의 계산된 타입 프로퍼티의 경우 class 키워드를 대신 사용하여 하위 클래스에서 상위 클래스의 구현을 재정의 할 수 있다. 아래의 예제는 저장된 타입 프로퍼티와 계산된 타입 프로퍼티 구문을 보여 준다:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
Note
위 예제의 계산된 타입 프로퍼티는 읽기 전용 계산된 타입 프로퍼티를 위한 것이지만 계산된 인스턴스 프로퍼티와 동일한 구문을 사용하여 읽기 쓰기 계산된 타입 프로퍼티를 정의 할 수도 있다.
타입 프로퍼티는 인스턴스 프로퍼티처럼 점 구문으로 조회되고 설정한다. 그러나 타입 프로퍼티는 해당 타입의 인스턴스가 아닌 타입에 대해 조회되고 설정한다.
예를 들어:
print(SomeStructure.storedTypeProperty)
// Prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// Prints "Another value."
print(SomeEnumeration.computedTypeProperty)
// Prints "6"
print(SomeClass.computedTypeProperty)
// Prints "27"
다음 예제는 여러개의 오디오 채널에 대해 오디오 레벨 미터를 모델링 하는 구조체에 일부분으로 2개의 저장된 타입 프로퍼티를 사용한다. 각 채널은 0 부터 10 까지의 정수인 오디오 레벨을 가지고 있다.
아래 그림은 이러한 오디오 채널 중 2개를 결합하여 스테레오 오디오 레벨 미터를 모델링하는 방법을 보여 준다. 채널의 오디오 레벨이 0이면 해당 채널의 조명은 켜지지 않는다. 오디오 레벨이 10이면 모든 채널의 조명은 켜진다. 이 그림에서 왼쪽 채널은 현재 9의 레벨을 가지고 오른쪽 채널은 현재 7의 레벨을 가진다:

위에 설명한 오디오 채널은 AudioChannel 구조체의 인스턴스로 표현된다:
struct AudioChannel {
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// cap the new audio level to the threshold level
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// store this as the new overall maximum input level
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
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 구조체를 사용할 수 있다:
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
왼쪽 채널의 currentLevel 을 7 로 설정하면 maxInputLevelForAllChannels 타입 프로퍼티가 7 로 업데이트 된 것을 볼 수 있다:
leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
// Prints "7"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "7"
오른쪽 채널의 currentLevel 을 11 로 설정하면 오른쪽 채널의 currentLevel 프로퍼티가 10 의 최대값으로 변경된 것을 볼 수 있고 maxInputLevelForAllChannels 타입 프로퍼티가 10 으로 업데이트 된 것을 볼 수 있다:
rightChannel.currentLevel = 11
print(rightChannel.currentLevel)
// Prints "10"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "10"