Property 는 class , structure, enumeration 과 값을 연결합니다.
Stored property 는 객체의 일부분으로 상수 또는 변수값을 저장합니다.
Computed property 는 값을 저장하는 것이 아니라 계산합니다.
스토어드 프로퍼티는 class , structure, enumeration 모두에서 사용이 가능하나 컴퓨티드 프로퍼티는 class , structure에서만 사용이 가능합니다.
프로퍼티는 보통 특정 타입의 객체와 연관됩니다.
프로퍼티는 또한 타입 그자체와 연관될 수 있습니다. 타입 자체와 연관된 프로퍼트를 type property 라고 합니다.
추가로 프로퍼티 값의 변화를 감시하기위해 property observer 를 사용할 수 있습니다. 프로퍼티 옵저버는 커스텀한 action 에 반응합니다. 프로퍼티 옵저버는 스토어드 프로퍼티에 추가될 수 있으며, 또한 부모 클래스로 부터 상속된 하위 클래스의 프로퍼티에도 추가될 수 있습니다.
property wrapper 를 사용해서 getter 와 setter 구문을 여러개의 프로퍼티에 대해 재상용 할 수 있습니다.
Stored Properties
스토어드 프로퍼티는 상수 또는 변수로서 사용이 가능합니다.
스토어드 프로퍼티에 초기값을 설정해줄 수 있습니다.
초기화 도중에 스토어드 프로퍼티의 초기값을 변경해줄 수도 있습니다.
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8
Swift
복사
Stored Properties of Constant Structure Instances
객체를 생성해 이를 상수에 할당하면, 해당 객체의 프로퍼티를 변경할 수 없습니다.
var 로 선언된 프로퍼티도 마찬가지입니다!!
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property
Swift
복사
이는 structure 가 value 타입이기 때문입니다. value 타입의 객체가 상수로 선언되면, 객체의 프로퍼티 또한 변경이 불가능해집니다.
class 는 reference 타입이므로 다릅니다. 상수에 객체를 할당해도 이는 상수가 객체를 저장하는 것이 아닌 참조하는 것이므로, 프로퍼티가 변경이가능해집니다. 참조할 대상을 변경하는 것이 불가능할 뿐입니다.
Lazy Stored Properties
lazy stored property 란 해당 프로퍼티가 사용되기 전까지 초기값을 계산하지 않는 프로퍼티를 의미합니다. lazy modifier 를 사용하여 스토어드 프로퍼티를 lazy stored property 로 사용하세요
lazy property 는 항상 변수로 선언해야합니다. 객체 생성이 완료될 때 까지도 초기값이 구해지지 않을 수 있기 때문입니다. constant property 는 객체 초기화가 완료되기 전에 항상 값을 가집니다. 따라서 lazy 로 선언할 수 없습니다.
Lazy 프로퍼티는 초기값이 외부 요인에 의해 결정될 때 유용합니다. 객체 생성이 완료된 후에도 프로퍼티의 초기값을 구하지 못할 때 주로 사용됩니다.
또한 Lazy 프로퍼티는 복잡하거나 비용이 많이 들어가는 계산이 요구되는 초기설정에 유용합니다. 필요할 때 까지 계산을 미룸으로써 앱의 반응성을 높일 수 있습니다.
아래의 예시에서는 복잡한 클래스에서의 불필요한 초기화를 피하는데에 lazy 스토어드 프로퍼티가 사용되었습니다.
class DataImporter {
/*
외부로 부터 데이터를 가져오는 클래스
적지 않은 시간이 요구됨
*/
var filename = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager {
// 외부로 부터 데이터를 가져오는 것이 아닌 자체 데이터를 사용할 수도 있기 때문에 lazy 로 선언 >> 데이터를 가져올 필요가 없다면 아래 프로퍼티는 초기화되지 않는다.
lazy var importer = DataImporter()
var data: [String] = []
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// importer property 의 DataImporter instance는 아직 생성되지 않았습니다.
Swift
복사
lazy modifier 로 선언 되었기 때문에 ,importer 프로퍼티는 처음 접근될때 처음 생성됩니다.
print(manager.importer.filename)
//접근과 동시에 객체 생성
// Prints "data.txt"
Swift
복사
lazy 로 선언된 프로퍼티가 초기화 되지 않았을 때, 동시에 여러개의 스레드가 이 프로퍼티에 접근하는 경우 해당 프로퍼티는 여러번 초기화될 가능성이 존재합니다. synchronization을 제공하지 않습니다.
Stored Properties and Instance Variables
Objective-C에서는 클래스 인스턴스의 일부로 값과 참조를 저장하는 방법이 있습니다. 또한 프로퍼티에 저장된 값에 대한 백업 저장소로 인스턴스 변수를 사용할 수 있습니다.
Swift는 이러한 개념을 single property declaration(단일 프로퍼티 선언)으로 통합했습니다. Swift의 프로퍼티는 인스턴스 변수가 없고 프로퍼티의 백업 저장소에 바로 접근하지 않습니다. 이렇게 됨으로써 값을 여러 곳에서 접근하려고 할 때 혼란을 피할 수 있고 프로퍼티 선언을 하나의 명확한 코드로 단순화할 수 있게 되었습니다. 즉 이름, 타입, 메모리 관리 특성 등 프로퍼티의 모든 정보는 타입을 선언할 때 단일 위치에서 정의됩니다.
Computed Properties
컴퓨티드 프로퍼티는 클래스 , 구조체 열거형에서 사용이 가능합니다. 컴퓨티드 프로퍼티는 실제로 값을 저장하지 않습니다. 대신 getter 와 setter를 활용, 다른 프로퍼티와 값으로부터 간접적으로 값을 가져옵니다. ( setter 문은 생략가능)
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
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(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0) // set 블럭 호출
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0)"
square.center = Point(xjldnwl)
Swift
복사
위 예시에서 3개의 구조체는 기하학적 모양에 대한 정보를 정의합니다.
•
Point : x 와 y 좌표를 캡슐화
•
Size : width 와 height 를 캡슐화
•
Reck : 원점과 size 를 이용해 직사각형에 대한 정보를 정의
Rect 구조체에서 center라는 이름의 컴퓨티드 프로퍼티를 볼 수 있습니다. 현재 Rect 의 중심위치는 항상 origin 과 size 에 의해서 결정됩니다. 따라서 중심점에 대한 정보를 명시해줄 필요가 없습니다.
중심값을 변경하는 경우, center 프로퍼티에는 저장이 불가능하므로, 다른 프로퍼티를 수정함으로써 get 문 호출시에 올바른 값을 리턴하도록 해야합니다.
위 예시에서는 origin.x , origin.y의 값을 수정해 넣는 모습입니다.
lazy 프로퍼티와 비슷하게 계산 프로퍼티 또한 값에 접근을 시도할 때, get 문이 호출 됩니다. get 문은 새로운 Point 를 계산하여 리턴합니다. 값을 저장하지 않기 때문에 접근을 시도할 때마다 이러한 계산이 일어납니다.
Shorthand Setter Declaration
newValue라는 예약된 새 값의 기본값을 활용해 새 값의 이름을 정의하지 않아도 됩니다
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)
}
}
}
Swift
복사
Shorthand Getter Declaration
get 문이 하나의 표현식으로 이루어진 경, return 키워드를 생략할 수 있습니다.
struct CompactRect {
var origin = Point()
var size = Size()
var center: Point {
get {
Point(x: origin.x + (size.width / 2),
y: origin.y + (size.height / 2))
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
Swift
복사
이는 함수에서 return 을 생략하는 규칙과 동일합니다.
Read-Only Computed Properties
setter 를 구현하지 않은 컴퓨티드 프로퍼티를 read-only computed property(읽기 전용 계산 프로퍼티) 라고 합니다. 읽기 전용 계산 프로퍼티는 항상 값을 리턴하며, . 구문을 활용해 접근이 가능하지만, 다른 값을 설정하지 못합니다.
계산 프로퍼티(읽기전용 포함)는 항상 var 키워드로 선언되어야 합니다.
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// Prints "the volume of fourByFiveByTwo is 40.0"
Swift
복사
위 예시에서 width, height , depth 정보를 통해 volume 을 계산할 수 있다. 하지만 반대의 과정은 불가능하다. volume 에 대한 정보 만으로는 width height depth 를 유추할 수 없기 떄문이다. 이러한경우 read-only 로 구현하는 것이 바람직하다.
Property Observers
프로퍼티 옵저버들은 프로퍼티의 값의 변화를 감시하고 이에 반응합니다. 프로퍼티 옵저버들은 프로퍼티의 값이 설정될 때마다 호출됩니다.
새로운 값이 현재 값과 동일할 때도 호출됩니다.
프로퍼티 옵저버는 아래의 프로퍼티에 적용이 가능합니다.
•
정의된 stored property
•
상속된 stored property
•
상속된 computed property
상속된 프로퍼티에 대해서는 해당 프로퍼티를 override 함으로써 프로퍼티 옵저버 적용이 가능합니다. 정의된 계산 프로퍼티에 한해서는 setter 문을 옵저버 대신 활용하면됩니다.
프로퍼티 옵저버를 정의하는 데에는 2가지 옵션이 존재합니다.
•
willSet : 값이 저장되기 전에 호출
•
didSet : 값이 저장된 후에 호출
만약 willSet 을 옵저버로서 구현하면, 상수 파라미터로서 새 프로퍼티 값이 전달됩니다. 이 파라미터의 이름을 구체화 할 수 있습니다. 만약 파라미터 이름을 작성하지 않는다면 기본값인 newValue 로 이 파라미터의 이름을 사용할 수 있습니다.
유사하게 didSet 을 옵저버로서 구현하면, 상수 파라미터로서 이전 프로퍼티 값이 전달됩니다. 마찬가지로 파라미터의 이름을 구체화 할 수 있으며, 작성하지 않으면 이는 기본값인 oldValue 로 사용이 가능합니다.
부모 클래스의 willSet didSet 은 자식 클래스의 initializer 내에서 프로퍼티값이 설정될 때도 호출됩니다. 이 시점은 부모 클래스의 initializer 가 호출된 이후입니다. 자기 자신의 프로퍼티를 설정할 때는 호출되지 않습니다.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
Swift
복사
willset didSet 옵저버는 프로퍼티에 새 값이 할당 될 때마다 호출되며, 이는 새로 할당되는 값이 현재 값과 같은 값이어도 마찬가지입니다.
만약 옵저버가 달린 프로퍼티를 함수에 in out 파라미터로 전달해주게 되면, willSet 과 didSet 옵저버는 항상 호출됩니다. 이는 in-out 매개변수에 대한 copy in copy out 메모리 모델 때문입니다. in-out 매개변수에 대한 자세한 설명은 In-Out Parameters 를 참고.
Property Wrappers
프로퍼티 래퍼를 활용하면 프로퍼티가 저장되고 정의 되는 방식을 관리하는 코드를 분리할 수 있습니다 만약 thread-safety 체크를 제공하거나 데이베이스에 근본적인 데이터를 저장하는 프로퍼티들이 존재한다면 , 이 코드를 모든 프로퍼티마다 일일히 작성해주어야 합니다. 하지만 프로퍼티 래퍼를 활용하면 management code 한 번작성하여 이를 여러 프로퍼티에 적용함으로써 재사용이 가능해집니다.
프로퍼티를 사용하기위해서는 wrappedValue 프로퍼티를 가지는 구조체, 열거형, 클래스 중 하나를 만들어야합니다.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
Swift
복사
setter 가 12 이하의 값만이 저장될 수 있게끔 보장하는 것을 볼 수 있습니다.
private 키워드로 선언된 number 변수는 해당 구조체 내에서만 사용됩니다. getter setter 구문이 아닌 고서야 number 에는 직접적인 접근이 불가능해 집니다.
이렇게 만든 wrapper 를 프로퍼티 선언의 앞에 attribute 로서 작성해줌으로서 wrapper 를 사용할 수 있습니다.
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"
rectangle.height = 10
print(rectangle.height)
// Prints "10"
rectangle.height = 24
print(rectangle.height)
// Prints "12"
Swift
복사
wrapper 를 프로퍼티에 적용하면, 컴파일러는 wrapper 와 프로퍼티에 대한 접근을 제공하는 코드를 위한 저장공간을 제공하는 코드를 종합합니다. ( 프로퍼티 래퍼는 래핑된 값을 저장할 책임이 있습니다.
위의 구문적인 이득을 사용하지 않으면서도 프로퍼티래퍼를 사용할 수 있습니다.
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
Swift
복사
_height 와 _width 프로퍼티가 프로퍼티 래퍼의 객체를 저장합니다.. getter 와 setter 문이 wrappedValue 프로퍼티에 접근합니다.
Setting Initial Values for Wrapped Properties
wrapping 된 프로퍼티에 초기값을 부여할 수도 있습니다. 이 프로퍼티 래퍼를 적용되는 프로퍼티는 다른 초기값을 사용할 수 없습니다. 예를 들어 SmallRectangle 의 height 와 width 에는 초기값을 정의할 수 없습니다. 다른 초기값을 설정하기 위해서는, 프로퍼티 래퍼에 initializer 를 구현해야합니다.
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
Swift
복사
3개의 initializer 를 구현한 모습입니다.
프로퍼티에 어떠한 초기값도 사용하지 않는다면, Swift 는 init() initializer 를 호출합니다.
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
// Prints "0 0"
Swift
복사
초기값을 사용한다면, Swift 는 init(wrappedValue:) initializer 를 호출합니다.
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
var unitRectangle = UnitRectangle()
print(unitRectangle.height, unitRectangle.width)
// Prints "1 1"
Swift
복사
custom attribute 의 뒤에 괄호와 함께 인자를 작성하면, Swift 는 주어진 인자에 기반에 적절한 initializer 를 호출하고 이 인자들을 사용하여 초기설정을 진행합니다.
struct NarrowRectangle {
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
// Prints "2 3"
narrowRectangle.height = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowRectangle.width)
// Prints "5 4"
Swift
복사
프로퍼티의 초기값 뿐만아니라 해당 wrapper 의 초기 조건또한 수정할 수 있음을 보여주는 예시입니다. 이를 활용해 더 유연하게 wrapper 를 사용할 수 있게 됩니다.
또한 프로퍼티 래퍼에 인자를 포함시킬 때, 초기값을 할당연산자를 활용함으로써 구체화 할 수 있습니다.
struct MixedRectangle {
@SmallNumber var height: Int = 1
@SmallNumber(maximum: 9) var width: Int = 2
}
var mixedRectangle = MixedRectangle()
print(mixedRectangle.height)
// Prints "1"
mixedRectangle.height = 20
print(mixedRectangle.height)
// Prints "12"
Swift
복사
@SmallNumber(maximum: 9) var width: Int = 2 는
@SmallNumber(wrappedValue: 2, maximum: 9) var width: Int
와 기능적으로 동일한 코드입니다.
Projecting a Value From a Property Wrapper
wrapping 된 값 말고도 프로퍼티 래퍼는 projected value 이라는 추가 기능을 제공합니다. projected value 는 $ 로 시작하는 점만 제외하면 wrapping 된 값과 동일합니다.
@propertyWrapper
struct SmallNumber {
private var number: Int
private(set) var projectedValue: Bool
var wrappedValue: Int {
get { return number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
init() {
self.number = 0
self.projectedValue = false
}
}
struct SomeStructure {
@SmallNumber var someNumber: Int
}
var someStructure = SomeStructure()
someStructure.someNumber = 4
print(someStructure.$someNumber)
// Prints "false"
someStructure.someNumber = 55
print(someStructure.$someNumber)
// Prints "true"
Swift
복사
projectedValue 프로퍼티를 추가하여 프로퍼티 래퍼가 값에 초기화를 진행하였는지 확인할 수 있습니다. 예를들어 4를 저장할 경우, 프로퍼티 래퍼가 새 값을 할당해주지 않았기 때문에 projectedValue 는 false 가 저장되지만, 55 를 저장할 경우 프로퍼티 래퍼가 값을 조정하여 12 를 저장하게 되기 때문에 이땐 true 가 저장되게 됩니다. 물론 Bool 타입이 아닌 모든 타입의 값을 반환 가능합니다.
enum Size {
case small, large
}
struct SizedRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
mutating func resize(to size: Size) -> Bool {
switch size {
case .small:
height = 10
width = 20
case .large:
height = 100
width = 100
}
return $height || $width
}
}
Swift
복사
내부에서 projectedValue 에 접근할 때 self 생략가능합니다. 단 $ 는 반드시 사용해야합니다.
프로퍼티 래퍼 구문은 별개의 기능적 이득이 존재하는 게 아닙니다. 단지 getter setter 가 존재하는 프로퍼티의 구문적 이득을 제공할 뿐입니다. 따라서 프로퍼티 접근방식은 프로퍼티래퍼를 사용하지 않은 경우와 동일합니다.
Global and Local Variables
프로퍼티를 계산하고 감시하는 기능은 전역변수 지역변수에도 사용이 가능합니다.
앞서 배운 모든 변수들은 Stored variable입니다. 이는 stored property 와 유사합니다.
Computed variable 또한 사용이 가능합니다. 계산 변수는 값을 저장하기보다 계산합니다. 계산 변수는 계산 프로퍼티와 동일하게 작성하면됩니다.
전역 변수와 상수는 항상 lazy 하게 계산됩니다. 이는 lazy 프로퍼티와 유사합니다. 하지만 lazy 프로퍼티와는 달리 전역 변수와 상수는 lazy 키워드를 사용하지 않아도 됩니다.
프로퍼티 래퍼를 지역 변수에도 적용이 가능합니다.
전역 변수 또는 계산 변수에는 사용이 불가능합니다.
func someFunction() {
@SmallNumber var myNumber: Int = 0
myNumber = 10
// now myNumber is 10
myNumber = 24
// now myNumber is 12
}
Swift
복사
프로퍼티 래퍼는 프로퍼티에 적용하는 방식과 동일하게 적용 가능합니다.
Type Properties
객체 프로퍼티들은 특정 타입의 객체에 해당하는 프로퍼티입니다. 타입의 새 객체를 생성할 때마다, 자신만의 프로퍼티 값을 설정하고, 다른 객체로부터 이를 분리합니다.
하지만 Type Property는 특정 타입 자체에 속하는 프로퍼티를 만들어 특정 타입의 인스턴스를 몇 개를 만들어도 같은 프로퍼티에 접근할 수 있도록 할 수 있습니다.
타입 프로퍼티는 이렇게 특정 타입의 객체에 보편적인 값을 정의하고자 할 때 유용합니다. 예를들어 모든 객체가 사용할 수 있는 상수 프로퍼티(static constant) 또는 모든 객체에 대해 전역으로 값을 저장하는 프로퍼티(static variable)가 있습니다.
타입 프로퍼티는 어떠한 타입의 모든 인스턴스에 필요한 값들을 정의할 때 사용하면 유용합니다. 이를 사용할 때 Stored type property(저장 타입 프로퍼티)를 만들면 항상 값이 존재해야 합니다. 타입 자체에는 생성자가 없기 때문입니다. 또한 저장 타입 프로퍼티에 처음 접근될 때는 lazy 형태로 초기화됩니다. 여러 스레드가 동시에 접근해도 한 번만 초기화되도록 보장되며 lazy를 명시적으로 표시할 필요는 없습니다.
Type Property Syntax
타입 프로퍼티를 정의하기 위해선 static 키워드를 사용하면 됩니다.
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
}
}
Swift
복사
위 예시에서는 계산 타입 프로퍼티가 read only 로 선언되었지만 일반적인 계산프로퍼티처럼 쓰기 또한 간으한 계산 타입 프로퍼티를 정의할 수 있습니다.
Querying and Setting Type Properties
타입 프로퍼티도 . 으로 접근이 가능합니다만 인스턴스의 프로퍼티가 아닌 타입에 대한 프로퍼티로 접근해야합니다.
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"
Swift
복사
타입에 대한 프로퍼티이므로 객체의 생성여부와는 관계가 없으며, 타입 자체의 이름으로 접근해야합니다.
위와 같이 왼쪽 오른쪽 스피커의 볼륨을 나타내는 struct 를 만들어보자.
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
}
}
}
}
Swift
복사
위 예시에서 두개의 타입 프로퍼티를 볼 수 있다.
thresholdLevel 은 모든 객체에서 사용되는 스피커 볼륨의 임계값으로 이 값보다 큰 값은 currentLevel 변수에 할당될 수 없다.
maxInputLevelForAllChannels 는 모든 객체의 스피커 볼륨 중 가장 큰 값이 저장되는 값이다.
두개의 객체를 생성하여 위 예시를 살펴보자
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
leftChannel.currentLevel = 7
print(leftChannel.currentLevel)
// Prints "7"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "7"
rightChannel.currentLevel = 11
print(rightChannel.currentLevel)
// Prints "10"
print(AudioChannel.maxInputLevelForAllChannels)
// Prints "10"
Swift
복사
위 예시에서 currentLevel 의 값을 변경하였을 때 타입 프로퍼티인 maxInputLevelForAllChannels 또한 수정되는 것을 볼 수 있습니다. 이는 didSet 옵저버 때문입니다. 또한 객체를 통해 프로퍼티에 접근하는 것이 아닌 타입을 통해 프로퍼티에 접근하는 모습을 볼 수 있습니다.