Search
Duplicate

(SwiftUI) @어쩌구를 내가 직접 만들 수 있는 거라고?

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
SwiftUI
Scrap
태그
9 more properties
Swift 샘플 코드를 보다보면, 아래의 @State와 같이 생긴 annotation을 자주 볼 수 있다.
@State private var isPlaying: Bool = false
Swift
복사
내장되어 있는 옵션과 같이 생긴 이 annotation이, 사실 우리가 직접 정의해서 사용할 수 있는 부분이다!! 예를들어,
@Suhshin private var isCoding: Bool = false
Swift
복사
이런 식으로도 사용 가능하다는 것이다. 아니 그렇다면 대체 저게 뭐길래 우리가 마음대로 설정할 수 있는 걸까?

Property Wrapper

SwiftUI로 개발을 진행할 때, 자주 보이는 @State @Binding 등등이 모두 Property Wrapper이다!
그렇다면 Property Wrapper가 대체 뭘까?
간단하게 설명하자면, 프로퍼티 래퍼를 쓰는 프로퍼티들은 미리 정의해둔 연산들을 활용할 수 있다는 것이다. 아직은 이해하기 어려우니 코드를 살펴보자!

Property Wrapper를 왜 써야할까?

예를들어 저금을 위한 구조체와 오늘 사용할 돈 구조체가 있다고 생각해보자. 이 구조체는 모두 won 저장 프로퍼티를 가지고 있고, getWon이라는 연산 프로퍼티를 가지고 있다.
struct MoneyToSave { var won: String var getWon: String { won } } struct MoneyToUse { var won: String var getWon: String { won } }
Swift
복사
만약 해당 프로퍼티들이 "1,000"과 같이 숫자만 가지고 오는 상황에서 getWon을 했을 때 "1,000원"과 같이 표현하고 싶다면 어떻게 만들 수 있을까?
가장 기초적인 방법은 아래와 같이 각각 연산 프로퍼티에 won + "원"을 해주는 것이다.
struct MoneyToSave { var won: String var getWon: String { won + "원"} } struct MoneyToUse { var won: String var getWon: String { won + "원"} }
Swift
복사
하지만 이렇게 반복 작업을 요구하는 프로퍼티들이 많아진다면, 코드는 점점 길어지고 직관성도 떨어질 것이다. 이 때, 우리는 PropertyWrapper를 사용해서 이 작업을 단순화 시킬 수 있다.

Property Wrapper 만들기!

그렇다면 Custom Property Wrapper를 만들어보자. 원하는 이름의 구조체를 선언하고 선언부 앞에 @propertyWrapper를 붙여주면 된다.
@propertyWrapper struct AddWon { }
Swift
복사
이렇게 만들고 나면 아래와 같은 에러가 나온다.
wrappedValue라는 이름의 프로퍼티를 가지고 있지 않아서 나는 오류인데, 이 프로퍼티는 아래와 같이 정의되어 있다.
우리는 이 wrappedValue 프로퍼티를 활용해서 로직을 구현하면 된다. wrappedValue는 연산 프로퍼티이니, 저장프로퍼티인 result를 선언해준다.
@propertyWrapper struct AddWon { private var result: String = "" var wrappedValue: String { get { self.result } set { self.result = newValue + "원" } } init(wrappedValue initialValue: String) { self.wrappedValue = initialValue } }
Swift
복사
init으로는 initialValue가 연산 프로퍼티를 통해 set이 되도록 연결해준다. 이렇게만 하면 프로퍼티 래퍼를 만드는 것은 끝났다.
이제 만들어둔 프로퍼티 래퍼를 활용해서 코드를 리팩토링 해보자.

Property Wrapper 사용하기!

예제 코드 등에서 많이 봐왔듯이 Property Wrapper를 사용하는 방법은 간단하다. 사용할 변수 앞에 Annotation을 붙여주면 된다.
@AddWon var won: String
Swift
복사
우리가 필요한 두 구조체 내부 변수에 모두 Annotation을 붙여주도록 하자!
struct MoneyToSave { @AddWon var won: String var getWon: String { won } } struct MoneyToUse { @AddWon var won: String var getWon: String { won } }
Swift
복사
이제 원하는 로직이 잘 적용되었는지 확인해보자. 각 구조체마다 하나씩 인스턴스를 만들어준다.
let moneyToUse = MoneyToUse(won: "1,000") let moneyToSave = MoneyToSave(won: "2,000") print(moneyToUse.getWon) // 1,000원 print(moneyToSave.getWon) // 2,000원
Swift
복사
아래와 같은 결과를 확인할 수 있다.
이렇게 PropertyWrapper를 사용하면, 특정 연산이 필요한 프로퍼티들이 많을때, 손쉽게 관리하고 수정할 수 있다. 추가로 코드를 조금 더 직관적으로 설계할 수 있는 것이 가장 큰 장점인 것 같다.

추가 예시 코드

Property Wrapper를 처음 사용하면서 만들었던 예제 코드이다. 어떤 값을 넣어도 무조건 true만 반환하는 Wrapper를 만들었다. (그래서 항상 나의 CodingStatue가 true로 나온다 ㅎㅎ)
import UIKit extension Bool { func studying() -> Bool { return true } } @propertyWrapper struct Suhshin { private var isCoding: Bool = false var wrappedValue: Bool { get { self.isCoding } set { self.isCoding = newValue.studying() } } init(wrappedValue initialValue: Bool) { self.wrappedValue = initialValue } } struct Test { @Suhshin var isCoding: Bool var getCodingStateOfSuhshin: Bool { self.isCoding } } let test = Test(isCoding: false) print(test.getCodingStateOfSuhshin)
Swift
복사

Reference