과제를 하기전에 우선 TVING 클론코딩을 하는데 앞으로 몇주간 이 클론코딩을 이어서한다는 이야기를 들어서 그전에 Font나 color를 design system으로 만들어야겠다는 생각이 들어서 Font를 Custom으로 만들어보려다가 알게된 내용들을 정리해보려한다.
우선 내가 Font를 만들려고 할때 고려했던 상황들을 나열해보면
- 애초에 Font(Pretendard를 사용했음)는 light나 bold나 regular를 사용했었는데 figma로 보니까 숫자로 300이니 500이니 이렇게 되어있어서 이걸 어떻게 해야할까 고민을 해봤다
- 사용하는 글씨 크기가 정해져있었다. 14 15 23포인트만 사용을 하는데 이걸 enum으로 만들어서 사용하면 편하지 않을까? 엔터엔터하면서 빠르게 할수있으니까 편하긴 할거같다
- info.plist에 하나하나 넣어줘야한다는데 그렇게하기 귀찮은데 다른방법이 있을거같아서
우선 1번 2번부터 해결하면 저 bold regular이런걸 숫자로 변환하는 방법을 알아야할거같아서 검색해보니 생각보다 빠르게 찾을수있었다
그러니까 상황이 애초에 figma상으로는 4,5,6,700밖에 안쓰는데 폰트를 다운받아보니 9개의 weight가 들어있었다 100부터 900까지...이건 굳이 이렇게 쓸필요가없으니 400인 regular 500인 medium 600인 semi bold 700인 bold만 쓰면 된다고 생각했다
그래서 우선 Font라는 enum을 만들었다
enum Font {
enum Name: String {
case system
case pretendard = "Pretendard"
}
// 피그마기준 존재하는 font size => 14,15,23
enum Size: CGFloat {
case _14 = 14
case _15 = 15
case _23 = 23
}
enum Weight: String {
case _400 = "Regular"
case _500 = "Medium"
case _600 = "SemiBold"
case _700 = "Bold"
var real: UIFont.Weight {
switch self {
case ._400:
return .regular
case ._500:
return .medium
case ._600:
return .semibold
case ._700:
return .bold
}
}
}
}
애초에 글자크기도 enum으로만들어서 편하게사용할수잇게 만들었는데 저기서 real이라는 계산속성은 뭐냐면 사실 내가 정의한 weight는 내가 정의한 font타입의 weight타입이지 실제의 font의 weight타입이 아니다 그래서 내가 사용하려는 weight를 실제 font.weight로 바꿔는 역할을 하는 녀석이다. 그리고 나는 숫자로 폰트의 굵기를 표현해야한다(내피그마에선 그렇게보이니까....)그런데 내 xcode 에셋에 있는 폰트 파일에는 regular bold이렇게 써있으니 이걸 변환해주는게 필요해서 저렇게 만들었다
그리고 이 enum안에다가 CustomFont라는 구조체를 중첩타입으로 또 만들어준다
struct CustomFont {
private let _name: Name
private let _weight: Weight
init(name: Name, weight: Weight) {
self._name = name
self._weight = weight
}
var name: String {
"\(_name.rawValue)-\(_weight.rawValue)"
}
var `extension`: String {
"ttf"
}
}
저기 있는 extension앞뒤로 ``가 있는 이유는 extension이라는 단어를 자꾸 swift의 extension으로 인식해서 저렇게 써줬다 쓸때는 그냥 .extension이라고 쓰면된다.
이렇게했으면 거의다 왔다. 이제 UIFont에 extension을 추가해주면 우리가 편하게 쓸수있는 pretendard메서드가 완성된다
class func pretendard(weight: Font.Weight, size: Font.Size) -> UIFont {
let font = Font.CustomFont(name: .pretendard, weight: weight)
return ._font(name: font.name, size: size.rawValue)
}
이렇게 사용하면


weight와 size모두 선택을해서 사용할수있다 엔터만 딱딱 누르면되니까 굉장히 편하다
3번항목은 그냥 나도 알게된건데 원래는 font는 info.plist에 넣어줘야한다고한다
그렇게 안해도 되는 방식이 있다고 해서 해봣는데 진짜 그렇길래 좀신기했다. 원리는 나도 모른다...
우선 아까만은 Font enum타입에 해당 static 메서드를 추가해준다
private static func registerFont(fontName: String, fontExtension: String) {
guard let fontURL = Bundle(identifier: "uikit.TvingCloneCoding")?.url(forResource: fontName, withExtension: fontExtension),
let fontDataProvider = CGDataProvider(url: fontURL as CFURL),
let font = CGFont(fontDataProvider) else {
debugPrint("Couldn't create font from filename: \(fontName) with extension \(fontExtension)")
return
}
var error: Unmanaged<CFError>?
CTFontManagerRegisterGraphicsFont(font, &error)
}
그리고 이함수를 활용하는 함수하나를 더 추가해준다
static func registerFonts() {
fonts.forEach { font in
Font.registerFont(fontName: font.name, fontExtension: font.extension)
}
}
그리고 이 함수를 sceneDelegate에 한줄 추가해주면된다. 알아보니 이게 앱을 처음실행할때 등록을 시켜주는거라고 한다
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
Font.registerFonts()
let navigationController = UINavigationController(rootViewController: LoginViewController())
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
저 중간에 있는 Font.registerFonts()를 실행해주면 앱이 실행할때 font를 등록해줘서 info.plist 없이도 사용이가능한거라는데 사실 info.plist도 앱이실행될때 적용시켜주는거라 결과는 동일하지만 모든 파일을 하나하나 붙여넣기 안해도된다는게 조금은 더 편한거같다.