[iOS | Swift] Custom Font 적용하기(+ 앱 내 폰트 변경 기능)

Minji Kim·2022년 4월 25일
2

iOS | Swift

목록 보기
11/13
post-thumbnail

1. 폰트 파일을 프로젝트에 넣기

이때 중요한 점은 프로젝트를 타겟으로 해줘야 한다. Add to targets에 프로젝트명 체크해 주기!

2. Info.plist에 폰트 파일 추가하기

Info.plist로 가서 Fonts provided by application 아래에 방금 추가한 폰트 파일명을 그대로 복사해서 Item으로 넣어준다. 이때! 확장자명까지 입력해야 한다.

⚠️ 주의!
Info.plist에 Fonts provided by application 아래에 넣어야 한다! Fonts provided by application를 추가하면 자동으로 아래에 Item이 있을 것이다. 거기에 값으로 폰트 파일명을 넣는다.

3. 폰트 이름 확인하기

폰트 파일명을 그대로 사용했을 때 적용이 안될 때가 있다. 그 이유는 바로! 폰트의 진짜 이름이 아니기 때문이다. 즉, 파일명이 폰트명이 아닐 때가 있다는 것이다. 그럼 진짜 이름은 어떻게 확인할까..? 아래 코드로 확인 가능하다.

// 폰트 체크 하기
UIFont.familyNames.sorted().forEach { familyName in
	print("*** \(familyName) ***")
	UIFont.fontNames(forFamilyName: familyName).forEach { fontName in
		print("\(fontName)")
	}
	print("---------------------")
}

폰트마다 Family Name이 있는데 Family Name을 통해 Font Name을 알아올 수 있다. 앱을 실행시켰을 때 바로 진입하는 뷰에 이 코드를 붙여 넣는다. 그러면 이렇게 터미널에서 폰트의 진짜 이름을 알아낼 수 있다.

4. 폰트 적용하기

Storyboard에서는 UIComponent 속성창에서 글씨체를 쉽게 바꿀 수 있으므로 코드를 이용한 방법만 설명할 것이다. 먼저, UIFont에 폰트 이름을 입력해서 적용하는 방법이 있다.

titleLabel.font = UIFont(name: "SuncheonR", size: 12.0)

<기본 폰트일 때>

<커스텀 폰트 적용했을 때>

+ 폰트 변경 기능

만약 앱 내 폰트 변경 기능을 구현하려고 한다면 유지 보수를 위해 별도의 파일을 만들어 거기서 폰트를 관리하는 것을 추천한다. 물론, 더 좋은 방법이 있을 수도 있고, 각자의 상황에 따라 제일 알맞은 방법이 있을 수 있다. 설명하려는 방법은 필자 상황에 맞게 구현한 내용임을 참고하길 바란다.

Font와 FontSize를 열거형으로 만든다. 이때 Font 열거형의 타입은 Int로 rawValue로 관리할 것이다.

enum FontSize: CGFloat {
    case small = 12
    case medium = 14
    case large = 16
    case extraLarge = 18
}

enum Font: Int {
    case kyobo      // 교보손글씨2019
    case leeseoyun  // 이서윤체

    /// 아이폰 작은 글씨(size: 12)
    var smallFont: UIFont {
        switch self {
        case .kyobo:
            return UIFont(name: "KyoboHandwriting2019", size: FontSize.small.rawValue)!
        case .leeseoyun:
            return UIFont(name: "LeeSeoyun", size: FontSize.small.rawValue)!
        }
    }
}

let fontKey = "Font"

class FontManager {
    /// 저장된 폰트 가져오기
    static func getFont() -> Font {
        if let font = (UserDefaults.standard.value(forKey: fontKey) as AnyObject).integerValue {
            return Font(rawValue: font)!
        } else {
            // 저장된 폰트가 없으면 기본 폰트로
            return .leeseoyun
        }
    }
    /// 폰트 저장하기
    static func setFont(font: Font) {
        UserDefaults.standard.setValue(font.rawValue, forKey: fontKey)
        UserDefaults.standard.synchronize()
    }
}

FontManager를 사용해서 폰트를 변경하려면 먼저, getFont로 UserDefaults에 저장된 폰트를 가져온다. 이때, UserDefaults에는 폰트의 rawValue가 저장되어 있기 때문에 이 값을 이용해서 Font를 가져온다. 그리고 Font 열거형에 선언한 smallFont 변수로 UIFont 값을 가져와서 UIComponents에 적용한다.

let font = FontManager.getFont()

titleLabel.font = font.smallFont

⁉️ 질문 있습니다!
폰트 변경 화면을 TableView로 구현할 때, TableView의 numberOfRowsInSection 값을 Font 열거형에 넣어둔 폰트의 개수만큼 설정하려고 합니다. enum case의 개수를 어떻게 가져오나요?
➜ enum 안에 static let으로 모든 case를 담은 배열을 만들고 원소 개수로 가져오면 됩니다!

enum Font: Int {
    case kyobo      
    case leeseoyun
	static let allValues = [kyobo, leeseoyun]
}
...
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
	return Font.allValues.count
}

💙 참고한 블로그
https://bugtypekr.tistory.com/18
https://abhimuralidharan.medium.com/maintaining-a-colour-theme-manager-on-ios-swift-178b8a6a92

profile
iOS Developer

3개의 댓글

comment-user-thumbnail
2023년 1월 26일

안녕하세요 민지님 앱 제작중에 폰트 설정 참고하여 잘보았습니다.
동기화관련 문제인듯한데, 앱 종료후 재시작하면 폰트가 잘 적용되지만, 종료하지않고 다른 view로 이동하면 unwrapping optional value 경고가 뜨네요 혹시 어떻게 하면 좋을지 알고계실까 해서 여쭤봅니다!

1개의 답글