μλ νμΈμ. μ§λ ν¬μ€ν μ μ΄μ΄ μ€λμ **νλ‘νΌν°(Properties)**μ λν΄ μμλ³΄κ² μ΅λλ€. νλ‘νΌν°λ ν΄λμ€, ꡬ쑰체, μ΄κ±°νμμ κ°μ μ μ₯νκ³ κ³μ°νλ λ°©λ²μ μ 곡νλ Swiftμ μ€μν κ΅¬μ± μμμ λλ€.
π νλ‘νΌν°λ?
νλ‘νΌν°λ νΉμ ν΄λμ€, ꡬ쑰체, λλ μ΄κ±°νκ³Ό μ°κ²°λ κ°μ λλ€. Swiftμμλ λ€μν μ’ λ₯μ νλ‘νΌν°λ₯Ό μ§μν©λλ€:
- μ μ₯λ νλ‘νΌν°(Stored Properties): μΈμ€ν΄μ€μ μΌλΆλ‘ κ°μ μ μ₯
- κ³μ°λ νλ‘νΌν°(Computed Properties): κ°μ μ μ₯νμ§ μκ³ κ³μ°
- νμ νλ‘νΌν°(Type Properties): νμ μ체μ μνλ νλ‘νΌν°
- νλ‘νΌν° κ΄μ°°μ(Property Observers): νλ‘νΌν° κ° λ³νλ₯Ό κ΄μ°°
- νλ‘νΌν° λνΌ(Property Wrappers): νλ‘νΌν° μ½λλ₯Ό μ¬μ¬μ©
π μ μ₯λ νλ‘νΌν° (Stored Properties)
μ μ₯λ νλ‘νΌν°λ κ°μ₯ κΈ°λ³Έμ μΈ ννμ νλ‘νΌν°λ‘, ν΄λμ€λ ꡬ쑰체 μΈμ€ν΄μ€μ μΌλΆλ‘ μμλ λ³μ κ°μ μ μ₯ν©λλ€.
struct FixedLengthRange {
var firstValue: Int // λ³μ μ μ₯ νλ‘νΌν°
let length: Int // μμ μ μ₯ νλ‘νΌν°
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6 // κ° λ³κ²½ κ°λ₯
// rangeOfThreeItems.length = 4 // μλ¬! μμ νλ‘νΌν°λ λ³κ²½ λΆκ°
μ μ₯λ νλ‘νΌν°(Stored Property): μΈμ€ν΄μ€μ μΌλΆλ‘ κ°μ μ μ₯νλ λ³μλ μμμ λλ€.
ꡬ쑰체μ μμ
ꡬ쑰체λ κ° νμ μ΄λ―λ‘, ꡬ쑰체 μΈμ€ν΄μ€λ₯Ό μμλ‘ μ μΈνλ©΄ κ·Έ μμ λͺ¨λ νλ‘νΌν°(λ³μ νλ‘νΌν° ν¬ν¨)λ λ³κ²½ν μ μκ² λ©λλ€.
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// rangeOfFourItems.firstValue = 6 // μλ¬! κ΅¬μ‘°μ²΄κ° μμμ΄λ―λ‘ λ³κ²½ λΆκ°
κ° νμ κ³Ό μ°Έμ‘° νμ μ μ°¨μ΄: ꡬ쑰체λ κ° νμ μΌλ‘, μμλ‘ μ μΈ μ λͺ¨λ νλ‘νΌν°κ° λΆλ³μ΄ λ©λλ€. λ°λ©΄ ν΄λμ€λ μ°Έμ‘° νμ μΌλ‘, μμλ‘ μ μΈν΄λ λ³μ νλ‘νΌν°λ λ³κ²½ κ°λ₯ν©λλ€.
μ§μ° μ μ₯λ νλ‘νΌν° (Lazy Stored Properties)
μ§μ° μ μ₯λ νλ‘νΌν°λ μ²μ μ¬μ©λ λκΉμ§ μ΄κΈ°κ°μ΄ κ³μ°λμ§ μλ νλ‘νΌν°μ λλ€. μ΄κΈ°ν λΉμ©μ΄ ν° λ¦¬μμ€λ μ€μ μ μ μ©ν©λλ€.
class DataImporter {
// μ΄κΈ°νμ μκ°μ΄ λ§μ΄ κ±Έλ¦°λ€κ³ κ°μ
var filename = "data.txt"
}
class DataManager {
lazy var importer = DataImporter() // μ²μ μ¬μ©λ λκΉμ§ μμ±λμ§ μμ
var data = [String]()
}
let manager = DataManager()
// μμ§ importerλ μμ±λμ§ μμ
manager.data.append("Some data")
// importer νλ‘νΌν°μ μ²μ μ κ·Όν λ DataImporter μΈμ€ν΄μ€κ° μμ±λ¨
print(manager.importer.filename) // "data.txt"
μ§μ° νλ‘νΌν°(Lazy Property): lazy ν€μλλ‘ μ μΈλλ©°, μ²μ μ κ·Όν λκΉμ§ μ΄κΈ°νλμ§ μμ΅λλ€. λ°λμ λ³μ(var)λ‘ μ μΈν΄μΌ ν©λλ€.
π κ³μ°λ νλ‘νΌν° (Computed Properties)
κ³μ°λ νλ‘νΌν°λ μ€μ κ°μ μ μ₯νμ§ μκ³ , getterμ 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))
print(square.center) // Point(x: 5.0, y: 5.0)
square.center = Point(x: 15.0, y: 15.0)
print(square.origin) // Point(x: 10.0, y: 10.0)
κ³μ°λ νλ‘νΌν°(Computed Property): μ€μ κ°μ μ μ₯νμ§ μκ³ getterμ setterλ₯Ό ν΅ν΄ κ°μ κ³μ°ν©λλ€. νμ varλ‘ μ μΈν©λλ€.
κ°μνλ Getter μ μΈ
κ³μ°λ νλ‘νΌν°μ getterκ° λ¨μΌ ννμμΌλ‘ ꡬμ±λλ©΄, 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)
}
}
}
μ½κΈ° μ μ© κ³μ°λ νλ‘νΌν°
setter μμ΄ getterλ§ κ΅¬ννλ©΄ μ½κΈ° μ μ© κ³μ°λ νλ‘νΌν°κ° λ©λλ€. get ν€μλμ μ€κ΄νΈλ₯Ό μλ΅ν μλ μμ΅λλ€.
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
// μ½κΈ° μ μ© κ³μ°λ νλ‘νΌν°
var volume: Double {
return width * height * depth
}
}
let cuboid = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print(cuboid.volume) // 40.0
μ½κΈ° μ μ© κ³μ°λ νλ‘νΌν°: setter μμ΄ getterλ§ κ°μ§ κ³μ°λ νλ‘νΌν°μ λλ€. get ν€μλμ μ€κ΄νΈλ₯Ό μλ΅νμ¬ λ κ°κ²°νκ² μμ±ν μ μμ΅λλ€.
π νλ‘νΌν° κ΄μ°°μ (Property Observers)
νλ‘νΌν° κ΄μ°°μλ νλ‘νΌν° κ°μ λ³νλ₯Ό κ΄μ°°νκ³ μλ΅ν©λλ€. willSetκ³Ό didSet λ κ°μ§ κ΄μ°°μλ₯Ό μ 곡ν©λλ€.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("κ³§ totalStepsκ° \(newTotalSteps)λ‘ λ³κ²½λ©λλ€.")
}
didSet {
if totalSteps > oldValue {
print("\(totalSteps - oldValue)κ±Έμ μΆκ°λ¨")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// μΆλ ₯: "κ³§ totalStepsκ° 200λ‘ λ³κ²½λ©λλ€."
// μΆλ ₯: "200κ±Έμ μΆκ°λ¨"
stepCounter.totalSteps = 360
// μΆλ ₯: "κ³§ totalStepsκ° 360λ‘ λ³κ²½λ©λλ€."
// μΆλ ₯: "160κ±Έμ μΆκ°λ¨"
willSet: κ°μ΄ μ μ₯λκΈ° μ§μ μ νΈμΆλ©λλ€. μ κ°μ΄ newValue(λλ μ¬μ©μ μ§μ λ§€κ°λ³μ μ΄λ¦)λ‘ μ 곡λ©λλ€.
didSet: μ κ°μ΄ μ μ₯λ μ§ν νΈμΆλ©λλ€. μ΄μ κ°μ΄ oldValueλ‘ μ 곡λ©λλ€.
π νλ‘νΌν° λνΌ (Property Wrappers)
νλ‘νΌν° λνΌλ νλ‘νΌν° μ½λμ μ¬μ¬μ©μ±μ λμ΄κ³ μμ±μ λν κ΄λ¦¬ μ½λλ₯Ό μΊ‘μνν©λλ€.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
rectangle.height = 10 // μ μ μ€μ
rectangle.width = 24 // 12λ‘ μ νλ¨
print(rectangle.height, rectangle.width) // 10 12
νλ‘νΌν° λνΌ(Property Wrapper): @propertyWrapper μμ±μΌλ‘ μ μλλ©°, μ¬λ¬ νλ‘νΌν°μ λν μ½λ μ€λ³΅μ μ€μ΄κ³ κ΄λ¦¬ λ‘μ§μ μ¬μ¬μ©ν μ μκ² ν©λλ€.
νλ‘νΌν° λνΌ μ΄κΈ°κ° μ€μ
νλ‘νΌν° λνΌλ μ΄κΈ°ν ꡬ문μ ν΅ν΄ μΆκ° μ€μ μ μ 곡ν μ μμ΅λλ€.
@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)
}
}
// μ΄κΈ°ν λ°©λ² 1: κΈ°λ³Έ μ΄κΈ°ν
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
// μ΄κΈ°ν λ°©λ² 2: μ΄κΈ°κ° μ§μ
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
// μ΄κΈ°ν λ°©λ² 3: μΆκ° λ§€κ°λ³μ μ 곡
struct NarrowRectangle {
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
let narrowRect = NarrowRectangle()
print(narrowRect.height, narrowRect.width) // 2 3
ν¬μλ κ° (Projected Value)
νλ‘νΌν° λνΌλ projectedValue νλ‘νΌν°λ₯Ό ν΅ν΄ μΆκ° μ 보λ₯Ό λ ΈμΆν μ μμ΅λλ€.
@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 someStruct = SomeStructure()
someStruct.someNumber = 4
print(someStruct.$someNumber) // false - κ°μ΄ μ νλμ§ μμ
someStruct.someNumber = 55
print(someStruct.$someNumber) // true - κ°μ΄ 12λ‘ μ νλ¨
ν¬μλ κ°(Projected Value): νλ‘νΌν° λνΌκ° μΆκ° μ 보λ₯Ό λ ΈμΆνλ λ°©λ²μ λλ€. $ μ λμ¬λ₯Ό μ¬μ©νμ¬ μ κ·Όν©λλ€.
π νμ νλ‘νΌν° (Type Properties)
νμ νλ‘νΌν°λ μΈμ€ν΄μ€κ° μλ νμ μ체μ μνλ νλ‘νΌν°μ λλ€. λͺ¨λ μΈμ€ν΄μ€κ° 곡μ νλ κ°μ μ μ₯νλ λ° μ μ©ν©λλ€.
struct AudioChannel {
// νμ
νλ‘νΌν°
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
// μΈμ€ν΄μ€ νλ‘νΌν°
var currentLevel: Int = 0 {
didSet {
// μ΅λ μκ³κ° μ ν
if currentLevel > AudioChannel.thresholdLevel {
currentLevel = AudioChannel.thresholdLevel
}
// μ΅λ μ
λ ₯ λ 벨 μ
λ°μ΄νΈ
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
leftChannel.currentLevel = 7
print(AudioChannel.maxInputLevelForAllChannels) // 7
rightChannel.currentLevel = 11 // 10μΌλ‘ μ νλ¨
print(AudioChannel.maxInputLevelForAllChannels) // 10
νμ νλ‘νΌν°(Type Property): static ν€μλλ‘ μ μΈλλ©°, μΈμ€ν΄μ€κ° μλ νμ μ체μ μν©λλ€. λͺ¨λ μΈμ€ν΄μ€κ° 곡μ νλ κ°μ μ μν λ μ μ©ν©λλ€.
ν΄λμ€μμμ νμ νλ‘νΌν°: ν΄λμ€μμλ staticλΏλ§ μλλΌ class ν€μλλ₯Ό μ¬μ©ν μ μμΌλ©°, class ν€μλλ νμ ν΄λμ€μμ μ¬μ μ κ°λ₯ν νμ νλ‘νΌν°λ₯Ό λ§λλλ€.
π μ μ λ° μ§μ λ³μ
Swiftμμλ νλ‘νΌν°μ μ μ¬νκ² μ μ λ° μ§μ λ³μμλ κ³μ°λ λ³μλ κ΄μ°°μλ₯Ό μΆκ°ν μ μμ΅λλ€.
// μ μ κ³μ° λ³μ
var globalComputedValue: Int {
return 42
}
func someFunction() {
// μ§μ λ³μμ νλ‘νΌν° λνΌ μ μ©
@SmallNumber var localNumber: Int = 0
localNumber = 10 // μ μ μ€μ
localNumber = 24 // 12λ‘ μ νλ¨
print(localNumber) // 12
}
μ μ λ³μ(Global Variable): ν¨μ, λ©μλ, ν΄λ‘μ , νμ 컨ν μ€νΈ μΈλΆμ μ μλ λ³μμ λλ€.
μ§μ λ³μ(Local Variable): ν¨μ, λ©μλ, ν΄λ‘μ λ΄λΆμ μ μλ λ³μμ λλ€.
μμ½
Swiftμ νλ‘νΌν° μμ€ν μ κ°λ ₯νκ³ μ μ°ν©λλ€. λ¨μν κ° μ μ₯λΆν° κ³μ°, κ΄μ°°, νμ λ³ κ³΅μ κ°κΉμ§ λ€μν κΈ°λ₯μ μ 곡ν©λλ€.
- μ μ₯λ νλ‘νΌν°λ κ°μ μ§μ μ μ₯νλ©°, lazy ν€μλλ‘ μ§μ° μ΄κΈ°νκ° κ°λ₯ν©λλ€.
- κ³μ°λ νλ‘νΌν°λ κ°μ μ μ₯νμ§ μκ³ λ€λ₯Έ νλ‘νΌν°λ₯Ό κΈ°λ°μΌλ‘ κ³μ°ν©λλ€.
- νλ‘νΌν° κ΄μ°°μλ‘ κ° λ³νλ₯Ό κ°μ§νκ³ λμν μ μμ΅λλ€.
- νλ‘νΌν° λνΌλ νλ‘νΌν° κ΄λ¦¬ μ½λλ₯Ό μ¬μ¬μ© κ°λ₯νκ² ν©λλ€.
- νμ νλ‘νΌν°λ λͺ¨λ μΈμ€ν΄μ€κ° 곡μ νλ κ°μ μ μν©λλ€.
μ΄λ¬ν λ€μν νλ‘νΌν° μ νμ μ μ ν νμ©νλ©΄ Swiftλ‘ λ ν¨μ¨μ μ΄κ³ μμ ν μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
'π₯ Bread Basics > Swift' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Swift 곡μ λ¬Έμ μ 리 - μ΄κΈ°ν (Initialization) (0) | 2025.04.11 |
---|---|
Swift 곡μ λ¬Έμ μ 리 - μμ (Inheritance) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - μλΈ μ€ν¬λ¦½νΈ (Subscripts) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - λ©μλ (Methods) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - ꡬ쑰체μ ν΄λμ€ (Structures and Classes) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - μ΄κ±°ν (Enumerations) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - ν΄λ‘μ (Closures) (0) | 2025.04.11 |
Swift 곡μ λ¬Έμ μ 리 - ν¨μ (Functions) (0) | 2025.04.11 |