32YB SOPT/swift 문법 스터디

[SOPT] 야우쓰_6주차 (속성, 프로퍼티)

신_이나 2023. 5. 31. 19:47

 

야우쓰란? "야 우리도 스위프트 할 수 있어"

in SOPT iOS

 

 

 

 

 

 

 

 

6주차의 키워드는 속성이다. 

 

 

 

- 프로퍼티

 우선 프로퍼티가 무엇일까 ? 프로퍼티는 클래스, 구조체, 열거형과 관련된 값이다. 코드를 짜면서 선언했던 변수나 상수가 프로퍼티라는 것이다. swift 에서 프로퍼티는 3가지로 구분된다.

 

 

1. 저장 프로퍼티

 저장 프로퍼티는 단순히 값을 저장하는 프로퍼티다. 내가 흔히 생각했던 프로퍼티가 이에 해당한다. let 이나 var 를 사용하여 상수, 변수를 선언한다. let을 사용한다면, 구조체나 클래스 안에서 let의 값을 변경할 수 없다. lazy는 지연 저장 프로퍼티로, 그 값이 사용되기 전까진 값을 갖지 않는다. 후에 값이 정해지기 때문에 보통 lazy와 var 를 같이 사용한다.

 

 

2. 연산 프로퍼티

연산 프로퍼티는 추가적으로 계산된 프로퍼티를 선언할 수 있다. 실제 값을 저장하고 있는 것이 아니라 getter와 optional한 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)
        }
    }
}

 

origin.x 라는 값 자체를 선언하지는 않았지만 origin.x라는 변수를 이용해 상수를 선언하고 있다. 이렇듯 get은 값을 직접 대입하는 것이 아닌 연산 프로퍼티를 이용하여 프로퍼티를 선언한다. 또한 newCenter 를 직접 선언하지 않았더라도, set으로 선언해주고 있다. 읽기 전용 계산된 프로퍼티는 read-only 로 작성된 프로퍼티다. 아래와 같은 예시가 있다.

var volume: Double {
        return width * height * depth
    }

volum 은 쓰거나 하지 못하고 return 값만을 반환하며 오직 읽기만 가능하다.

 

3. 타입 프로퍼티

 타입 프로퍼티는 주로 static 과 class 로 부르는 형태를 말한다. 타입 프로퍼티로 선언된 프로퍼티를 아래와 같이 이용할 수 있다.

struct jiwon {
	static let jiwonIs = "beautiful"
    static var age = 24
}

var a = jiwon()
var b = jiwon()

a.age = 20
print(jiwon.age) //20

 

Q1. 아래 코드가 왜 잘못되었는지 판단하고 어떻게 코드를 바꿔야 될지 공부해보세요

class Person {
	var nickName: String {
    get {
    	return nickName
    }
    set (nickName) {
    	self.nickName = nickName
    }
}

A1. 

 우선 모든 중괄호가 잘 선언되지 못하였다,, 머쓱   그렇다치고! 가장 중요한 이유는 get 과 set은 연산프로퍼티인데 연산값이 아닌 위에서 선언한 상수값만을 넣고 있다. 

 

 

Q2. 아래 코드가 왜 잘못되었는지 판단하고 어떻게 코드를 바꿔야 될지 공부해보세요

let hidi: Human = .init()
hidi.name // 아니구요

 

A2. 

 

hidi 가 Human 이라는 타입을 취하고 있기 때문에  Human이라는 타입 프로퍼티가 선언되어야 한다. 또한 당연히 Human 안에는 name 이라는 변수가 선언되어야 한다.

 

 

 

Q3. 해당 코드는 출력결과를 작성해주세요!

class Human {
    var name: String = "이름 없음" {
        willSet(newName) {
            print("현재 이름은 \(name)이지만 이제는 \(newName)입니다!")
        }
        didSet(oldName) {
            print("현재 이름은 \(name)이지만 예전에는 \(oldName)입니다!")
        }
    }
    var age: Int = 200 {
        didSet {
            print("예전에 내 나이는 \(oldValue)라고!!!")
        }
    }
}

let hidi: Human = .init()
print("값 변경 전에 나의 이름은 \(hidi.name)")
hidi.name = "안뇽히디"
print("값 변경 후에 나의 이름은 \(hidi.name)")
hidi.age = 24

A3. 

//Prints

값 변경 전에 나의 이름은 이름 없음

현재 이름은 이름 없음이지만 이제는 안뇽히디입니다!

현재 이름은 안뇽히디이지만 예전에는 이름 없음입니다!

값 변경 후에 나의 이름은 안뇽히디

예전에 내 나이는 200라고!!!

 

 

 

Q4. 프로퍼티 옵저버를 활용한 코드를 작성해주세요!

A4. 

 먼저 프로퍼티 옵저버에 대해서 알아보자! 프로퍼티 옵저버란 말그대로 프로퍼티를 감시하는 역할을 수행한다. 아무때나 감시하는 것은 아니고 새 값이 설정될 때마다 이벤트를 감지하는 역할을 한다. 새 값이 이전값과 변동이 없다하더라도 호출되며, lazy 지연 저장 프로퍼티에서는 사용할 수 없다. 옵저버의 종류에는 willset, didset 과 같은 것들이 있는데, 내갸 한동안 고생했던 textFieldDidBeginEditing 과 같은 것들이 그 예다.  아니다. 정확하게 willset, didset 이라는 것들이 있다!

var name: String = "jiwon" {
    didSet(oldname) {
        print("현재이름 = \(name), 전 이름 = \(oldname)")
    }
    willSet {
            print("현재 이름 = \(name), 후 이름 = \(newValue)")
    }
}

name = "queen"

//Prints
현재 이름 = jiwon, 후 이름 = queen
현재이름 = queen, 전 이름 = jiwon

willSet 을 선언하면 newValue 라는 값이 자동적으로 선언된다.

 

 

 

Q5. 공부한 모든 프로퍼티를 사용해서 Sopt 멤버에 관한 구조체 혹은 클래스를 만들어주세요!

A5. 

import Foundation

struct GoSOPT {
    var name : String
    var part : String
    var age : Int = 24 {
        willSet {
            print("현재 \(age)살이지만 6월부터 \(newValue)살이 될 예정입니다.\n")
        }
    }
    var haveMac : Bool
    
    func Print(){
        print("제 이름은 무려 \(self.name) 입니다. 파트는 \(self.part) 이며, 당연히 맥북 가지고있다? \(self.haveMac) 입니다!")
    }
}

var jiwon = GoSOPT(name: "jiwon", part: "iOS", haveMac: true)
jiwon.Print()
jiwon.age = 23

var hidi = GoSOPT(name: "hidi", part: "iOS", haveMac: false)
hidi.Print()
hidi.age = 22

//Prints
제 이름은 무려 jiwon 입니다. 파트는 iOS 이며, 당연히 맥북 가지고있다? true 입니다!
현재 24살이지만 6월부터 23살이 될 예정입니다.

제 이름은 무려 hidi 입니다. 파트는 iOS 이며, 당연히 맥북 가지고있다? false 입니다!
현재 24살이지만 6월부터 22살이 될 예정입니다.