개발하면서 경험했던 이슈를 공유겸 기록하려고합니다
Tuist를 사용해서 개발하면서 UI모듈을 나누게됬어요
UI가 분리되었으니
리소스에 해당하는
이미지, 컬러, 폰트같은 요소들이 UI모듈에 정의되고
다른곳에서 꺼내쓰는 방식으로 사용하죠
위의 그림기준으로
Feature에서
평소와같이 UI를 import해서 사용하게된다면
실행에 오류는없지만
원하는 리소스를 가져올 수 없는걸 확인할 수 있어요
이유는
프레임워크를 분리했기때문에
번들이 분리되어있기때문이에요
먼저 컬러와 이미지에 대해서 정리할게요
결론부터 말하자면 컬러와 이미지는 해결방법이 동일해요
Bundle을 정하고 가져오는 방식이에요
우선 일반적으로 UI모듈에 정의된 컬러에 접근하게된다면
아래와 같은 로그를 만날 수 있습니다.
No color named 'nsColor' found in asset catalog for main bundle
// UI모듈
public extension Color {
static var nsColor: Color { Color("nsColor") }
}
// Main 모듈
struct MainView: View {
var body: some View {
VStack {
Color.nsColor.frame(height: 100)
Text("Hello, World!")
}
.border(.red)
}
}
색이 아무것도 안뜨는걸 볼 수 있어요
앱을 실행하면 main으로 시작하면서 리소스를 불러올 때 기본적으로 main번들에서 가져오려고하죠
하지만 UI모듈은 다른 프레임워크고 고유한 identifier도 있고, main과 다른번들을 사용해요
모듈을 만들때
타겟을만들면서 다 정의해줬죠
UI번들에 있는 컬러로 접근하기위해 UI번들아이디를 이용해서
아래와같이 코드를 작성하면
정상적으로 색이 뜨는걸 볼 수 있어요
public extension Color {
static var nsColor: Color {
Color("nsColor", bundle: Bundle(identifier: "ns.NSWorkspace.UI"))
}
}
UI모듈에 폰트를 정의해두고 사용하는 방법
폰트도 마찬가지로
정의를 해서 잘 썼지만
실제로 구현한 UI를 보면 폰트가 쏙 빠져서 미워보이는 경우를 만나실수있습니다
폰트를 프로젝트파일에 끌어다놔서 저장돼있고, plist설정 했다 가정하고 시작할게요
for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
print("Family: \(family) Font names: \(names)")
}
우선 위의 코드를 실행시켜서
폰트가 존재하고
이름을 올바르게 사용했는지 확인해야해요
파일이름과 내부에서 사용하는 이름이 다를수 있어요
만약에 폰트가 제대로 적용됬다면
로그에 이렇게
"Pretendard-Regular" 이라고 뜨고
사용할땐 이 문자열을 그대로 넣어야해요
하지만
UI모듈에 폰트를 정의해두고
메인모듈에서 사용한다면
폰트가 적용되지 않는 현상을 볼 수 있어요
위코드로 로그를 찍어도 보이지않죠
Font는 Bundle로 접근해서 가져올 수가 없는데
어케하지...?
방법이 다 있었습니다
CTFontManagerRegisterFont~~~ 함수가 있어요
CoreText...!
폰트매니저에게 폰트를 등록시켜준다네요
여러개중 하나를 골라봤는데 ~ForURL 함수는 입력값으로
url: 폰트가 존재하는 URL
scope: 수명을 정의함
process - 세션유지기간동안 사용가능
persistent - 등록을 해제하지않으면 계속사용가능
이렇게 있네요
Font Type을 정의해서 썼기때문에
해당 타입을 순회하면서
UI모듈 번들에 접근해서
각 폰트파일의 URL을 가져와서
등록시키는 방식으로 해결할 수 있어요
public extension Font {
enum PretendardWeight: String, CaseIterable {
case regular = "Pretendard-Regular"
case medium = "Pretendard-Medium"
case semiBold = "Pretendard-SemiBold"
case bold = "Pretendard-Bold"
case black = "Pretendard-Black"
}
static func pretendard(size: CGFloat, weight: PretendardWeight = .regular) -> Font {
.custom(weight.rawValue, size: size)
}
static func registerFont() {
Font.PretendardWeight.allCases.forEach {
guard let url = Bundle.uiBundle?.url(forResource: "\($0.rawValue)", withExtension: ".otf"),
CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil) else {
print("fail register font")
return
}
}
}
}
그러면 AppDelegate나
시작하는 곳에서 최초1번 폰트을 등록해주는
registerFont함수를 실행시킴으로써
모든폰트를 등록하고 정상적으로 사용할 수 있어요
참고
'iyOmSd > Title: SwiftUI' 카테고리의 다른 글
[SwiftUI] Charts 이론편 (feat. iOS16+ apple framework) (0) | 2023.06.29 |
---|---|
[SwiftUI] NavigationStack (0) | 2023.05.29 |
[SwiftUI] Widget LiveActivity (feat. Dynamic Island) 잠금화면 기능 (2) | 2023.01.14 |
[SwiftUI] @FocusState (0) | 2022.10.27 |
[SwiftUI] TextField Placeholder (0) | 2022.10.26 |