SwiftGen을 간단하게 소개하자면
이해하기 쉽게 시나리오로 설명을 해보려고 한다.
UIColor(named:)
를 통해 Asset에 지정한 문자열 상수를 넣어 불러와야 한다.let customColor = UIColor(named: "customRed")!
해당 방법은 문자열을 하드코딩 한다는 점에서, 실수가 발생할 여지가 있고, 또 런타임에 에러가 결정되기 때문에 컴파일 타임에 해당 실수를 잡아내기 어렵다.
그래서 보완책으로 아래 처럼 사용해볼 수 있었다.
enum Constans: String {
let customRed = "customRed"
}
extension UIColor {
static var customRed: UIColor {
UIColor(named: Constans.customRed.rawValue) ?? UIColor()
}
}
let customRed: UIColor = .customRed
추가한 에셋이 많을 경우는 매크로 코드를 짜서 일괄로 생성하는 방법도 썼었다.
이 부분을 간편하게 해주도록 나온 것이 바로 SwiftGen이다.
SwiftGen은 위 과정을 템플릿을 통해 일괄적으로 작업할 수 있게 해주고,
하드코딩에 의한 실수, 또 컴파일 타임에 에러를 잡을 수 있도록 도와준다.
어떻게 사용하는지 알아보자.
설치 전에 나의 작업 환경은 다음과 같다.
1. m1 macbook pro 16g
2. Xcode 13.2
3. Monterey 12.1
설치 방법
github에 잘 소개 되어있기도 한데 여러 방법마다 장단이 있는 것 같다.
1. Download the ZIP
2. CocoaPods
3. Homebrew
4. Mint
Zip과 CocoaPods는 프로젝트 별로 따로 적용하는데 이용하기 편하고
Homebrew와 Mint는 시스템 전체적으로 사용할 수 있기 때문에,프로젝트 마다 일일이 설정하기 싫은 경우 선택할 수 있다.
나는 Homebrew를 선택했고, Homebrew로 설치했지만, 프로젝트마다 다르게 swiftgen.yml을 다르게 적용해보려고 한다.
terminal에서 brew로 swiftgen을 설치한다.
brew update
brew install swiftgen
이 경우 hoem directory에 기본적으로 swiftgen.yml이 위치하게 된다.
swiftgen의 기본 사용 방법은 swiftgen.yml을 통해 템플릿을 작성하고
swiftgen으로 템플릿을 파싱하는 식이다.
swiftgen.yml에서는 번들의 Assets.xcassets
를 파싱해서
Asset+Generated.swift
(예시 이름)를 생성한다.
Asset+Generated.swift
에는 열거형으로 Asset에 정의한 것들을 접근할 수 있게 한다.
예를들어
let customRed: UIColor = Asset.Color.customRed.color
위와같이 쓸 수 있다. 타입 어노테이션은 참고하라고 써둔 것이고 필수가 아니다.
일단은 저게 어떻게 돌아가는지 간단하게 테스트 해보자.
터미널에서 다음과 같이 입력한다.
cd ~/Desktop
swiftgen config init
만약 여기서 에러 났으면 brew로 swiftgen이 설치가 안된거다.
우선 사용하기 편하게 데스크톱 디렉토리로 이동 한 뒤 작업한다.
위 명령어는 swiftgen.yml을 생성하는 명령어이다.
Dekstop 디렉토리로 가면 swiftgen.yml이 생성되어 있을 것이다.
아마 swiftgen config init
명령어를 입력하면 swiftgen.yml 파일이 자동으로 편집기로 열릴 것이다.
swiftgen.yml
내용을 보면 주석으로 사용법이 자세하게 적혀있는게 나중에 디테일 하게 사용하고 싶다면 꼭 읽어보자
우리는 우선 asset에만 집중해보자.
swiftgen.yml
을 가져오자.릴리즈 하고 나면 swiftgen이 실행 될 일이 없기 때문에, 따로 가져올 필요가 없지만, 설명에 편의를 위해 가져왔다. 프로젝트에 따로 추가하지 않아도 되고 필요한 디렉토리 위치시켜 두고 위치만 지정하면 된다.
yml내용을 보면
# xcassets:
# inputs:
# - Main.xcassets
# - ProFeatures.xcassets
# outputs:
# - templateName: swift5
# params:
# forceProvidesNamespaces: true
# output: XCAssets+Generated.swift
이 부분이 Asset을 파싱 후 컨버팅 해주는 부분으로, 조리해서 사용하면 된다.
사용해보려고 하는 부분은 Color Asset을 별도로 만들어 볼려고 한다.
Asset Catalog
를 하나 새로 만든다.
이름은 Color 로
Color Asset안에 커스텀 컬러 몇개 저장 후
swiftgen.yml에 다음과 같이 내용을 추가한다.
xcassets:
inputs:
- Color.xcassets
outputs:
- templateName: swift5
params:
enumName: Colors
output: Color+Generated.swift
내용을 찬찬히 뜯어보면
작성이 끝났으면 terminal로 해당 yml이 있는 디렉토리로 찾아간다.
그리고 아래 명령어를 입력
swiftgen config run
성공적으로 명령어가 동작했다면
File written: Color+Generated.swift
이라고 표시된다.
지금은 아무것도 보이지 않을텐데 해당 디렉토리로 가 보면
Color+Generated.swift
파일이 생성 되어 있을 것이다.
이를 프로젝트에 추가한다.
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.padding()
.foregroundColor(Colors.customRed.color)
}
}
extension View {
func foregroundColor(_ uicolor: UIColor) -> some View {
self.foregroundColor(Color(uicolor))
}
}
실제로 컬러는
Color.customRed.color
로 접근할 수 있다. 형태는 Color
는 yml에서 작성한 enumName이다.
여기까지가 기본적인 작업 플로우로, 정리해보면
swiftgen config run
여기서 좀더 생각해보면, Asset Catalog에 새 Asset이 추가될 때 마다 terminal 키고 swiftgen config run
하면 너무 귀찮은데? 라는 생각이 들 수 있다. 이부분을 자동화 시켜줄 수 있는것이 바로 Run Script
이다.
프로젝트 -> 타겟 -> 빌드 페이즈(Build Phases)로 이동한 뒤
Run Script를 하나 추가하자.
run script는 빌드 할 때 자동으로 터미널 켜서 스크립트 안에 적힌 내용을 실행시켜 주는 기능이라고 생각하면 된다.
요 Shell 안에 내용을 작성할 것인데
여기서 앞서 우리가 터미널에서 했던
swiftgen config run
을 작성해주면
빌드 될 때 마다 파싱해서 Generated.swift
를 생성해 줄 것이다.
위 내용을 넣고 빌드해보면~
에러가 난다.
별 내용은 아니고 terminal에서 swiftgen 실행시키려고 하는데 없어서 그러는 거다.
brew에 설치된 swiftgen을 실행시켜야 해서 패스를 지정해 준다.
PATH=/opt/homebrew/bin:$PATH
swiftgen config run
여기서 실행 시켜보면 또 에러가 난다.
이번에는 swiftgen.yml을 찾을 수가 없다고 나온다. 엥?
그래서 해당 명령어를 실행하기 전에 위치한 디렉터리가 어딘지 보자
PATH=/opt/homebrew/bin:$PATH
pwd
ls
swiftgen config run
스크립트에 위 내용으로 변경후 발생하는 에러를 보면
프로젝트 폴더에는 가있는데 타겟 폴더에 안들어가 있다.
타겟 폴더 안으로 들어가면 되겠다.
PATH=/opt/homebrew/bin:$PATH
cd SwiftGenPractice
swiftgen config run
이제 빌드해보면 에러가 발생하지 않고 정상 빌드 될 것이다!
이 경우는 swfitgen.yml을 찾고 내용대로 파싱해서 파일을 생성하는 방식인데 사실 예제처럼 파싱할 내용이 많지 않으면 yml없이 인라인으로 작성할 수도 있다.
swiftgen xcassets Resources/Images.xcassets --templateName swift5 --output "Constants/Assets+Generated.swift"