연습/swift개발

4.4 텍스트를 넣으려면

TimeSave 2022. 1. 20. 21:54

 

텍스트를 그리는 경우는 어떨까?

 

우리는 UIBezierPath로 텍스트를 그리지 않아

 

텍스트는 폰트로 표현되는 UIBezierPath의 모음일 뿐이야

 

폰트는 UIBezierPath의 모음으로 된 각각의 문자를 정의해

 

새겨진 문자 말이야

 

그러니까 우리는 텍스트를 그리는 높은 수준의 방법이 있는거야

 

여기 문자열이 있으니까 그려보라고 하는 것처럼 말야

 

UIBezierPath가 그려지는 높은 수준의 방법이지

 

너흰 분명 UIBezierPath 수준으로 문자를 표현하고 싶지 않겠지

 

하지만 대부분은 drawRect로도 텍스트를 직접 그리지 않아

 

이미 익숙한 UILabel을 사용해서 문자를 그려내지

 

직사각형이 있으면 여기 놓일거고

 

이 친구 이마에 Hello라고 적고 싶으면

 

저기에 ULabel을 얹어놓고 Hello라고 하면 되

 

하지만 drawRect로 텍스트를 그리고 싶다면 어떨까?

 

이 안에 텍스트를 넣고 싶지만

 

FaceView에 UILabel을 하위뷰로 얹고 싶지 않다면?

 

그럴 땐 NSAttributedString 클래스를 사용하면 되

 

이런 구조로 생성할 수 있는데 보통은 여기에 텍스트를 넘겨줘

 

AttributedString이라는 건 String은 String인데

 

각각의 문자는 어떻게 그릴 지에 대한

 

속성으로 구성된 Dictionary을 가지고 있어

 

그 속성이란 건 예를 들면 문자의 색상이나

 

글꼴 같은 것도 분명 있지

 

배경 색상 같은 것들이지

 

모든 문자에 대한 설정값이 담긴 Dictionary를 갖고 있는거야

 

보통은 같은 색상과 글꼴을 가진 문자가 길게 나열되는 형태이지

 

그래서 모든 문자에 대해 하나의 Dictionary를 갖는게 보통이지

 

하지만 이게 AttributedString이 작동하는 기본적인 방식이야

 

일단 AttributedString을 갖게 되면

 

문자에 대한 Dictionary를 설정하게 되고

 

drawRect안에서 그려주면 되는데 이렇게 적으면 되

 

AttributedString인 text에 drawAtPoint 메소드를 호출하고

 

포인트(CGPoint)값을 주면

 

텍스트를 왼쪽 상단이 저 포인트가 되는 지점에 그려낼거야

 

Hello를 여기에 그려내고 싶으면

 

Hello가 이것처럼 나타날거야

 

이 지점이 왼쪽 상단 기준점이 되고 텍스트가 이렇게 보이겠지

 

이해하겠니?

 

이게 얼마나 클지도 알아낼 수 있어

 

이 AttributedString의 size 프로퍼티를 사용하면 되지

 

이렇게 텍스트를 그릴 수 있어

 

사실 몇가지 이유에서 NSAttributedString를

 

사용하기 조금 지저분한 점이 있는데

 

그건 이게 Objective-C 클래스이기때문에 그런 것일 뿐이야

 

아직은 스위프트로 그렇게 좋은 성능이 나오지 않고 있어

 

스위프트에서 사용하는 것을 약간 복잡하게 만드는

 

주요한 두가지 차이점이 있어

 

하나는 값이 변할 수 있는 특성이 var와 let으로 할 수 없어

 

보통은 Array에 뭔가를 추가하고 싶다면

 

Array 타입의 변수 x를 생성하면 변수 var니까 추가할 수 있어

 

Array 타입으로 상수 x를 생성하면 추가할 수 없겠지

 

하지만 NSAttributedString에는 해당되지 않는 이야기야

 

NSAttributedString를 변수 var로 선언해도 값은 바뀔 수 없어

 

값을 바꿀 수 있는 방법은

 

NSMutableAttributedString 이라는 다른 클래스를 써야 해

 

그래서 AttributedString를 만들고

 

속성에 대한 설정을 하기 시작했다면

 

NSMutableAttributedString 을 대신 써야 하는 거야

 

"some string" 값으로 같은 방식으로 해줄 수 있고

 

이젠 속성들을 설정하거나 뭐든 해줄 수 있는 거야

 

이게 좀 스위프트에서 이상한 부분 중 하나야

 

바꿀 수 있는 버전을 따로 써야 한다는 것이지

 

그건 그렇고 NSAttributedString은 스위프트 String도 아니고

 

Objective-C의 NSString도 아니야

 

별개의 것이야

 

string과 mutableString이라는 프로퍼티가 있는데

 

이것들로 String이나 NSString을 돌려줄거야

 

브리징(연결) 같은 걸 사용해서 말이지

 

하지만 그것 자체로는 String이 아니야

 

String 타입을 받는 인자로 넘겨줄 수 없어

 

NSAttributedString은 아에 다른 거야

 

스위프트에서 NSAttributedString이 까다로운 두번째 이유는

 

Range(범위)에 대한 것이야

 

attribute를 설정하고 싶을거야

 

이런 식으로 설정하면 되

 

Dictionary가 있는데 여기에 뭐가 들어갈지 잠시후에 말해줄게

 

또 문자열에 있는 문자의 범위를 설정하려고 할거야

 

특정 범위의 문자에만 색상이나 글꼴을 설정해 줄 수 있을테니까

 

여기 들어가는 범위는 Range가 아니라 NSRange야

 

NSRange는 Range와는 달라

 

NSRange안에는 index가 있고

 

기본적으로 범위를 표현하는 구조체로 되어있어

 

그 범위는 일정 거리를 두고 시작하지

 

하지만 이 index들은 Objective-C의 NSString에 있어

 

NSString과 스위프트의 String에는 어떤 차이가 있지?

 

전에 말했듯이 스위프트의 String은 완전히 유니코드를 따르지

 

이모지 같은 것들은 다수의 문자가 될거야

 

NSString의 문자길이는 String의 문자길이와 다를지도 몰라

 

스위프트의 String은 수많은 유니코드가 있는 반면

 

NSString은 유니코드 전부를 반드시 다루지 않을지도 모르거든

 

그래서 근본이 좀 다른거야

 

일반적인 텍스트가 있는데 그걸 나타내길 주저한다면

 

너희가 만든 앱을 전세계에서 사용하길 바랄테니까

 

하지만 유니코드가 없이 긴 문자로만 된 텍스트가 있다면

 

이모지 같은게 없다면 말야

 

그럼 Range나 NSRange가 꽤 비슷할 수 있어

 

그렇지 않다면 범위(range)가 NSString의 range로 되는지

 

매우 조심해서 확인할 필요가 있어

 

가지고 있는 스위프트의 String을 받아서

 

NSString으로 변환하는 거야

 

자동으로 브리징해주기 때문에 매우 쉽지

 

그리곤 NSString을 보면서 얼마나 긴지 어디있는지를 보는거지

 

내가 사과할게

 

애플사에서 일한 적이 없기때문에 사실 아무 상관은 없지만

 

이렇게 돌아가는게 사실이야

 

언제가는 애플이 스위프트에 친화적인 방법을 내놓을거라 믿어

 

그건 그렇고 숙제에서 이 부분을 내진 않을거니까

 

너무 걱정하지 마

 

여기있는 Dictionary에 넣을 속성들엔 뭐가 있을까?

 

너희가 기대하는 바대로야

 

foregroundColor는 텍스트의 색깔을 말하고

 

strokeWidth는 텍스트를 얼마나 두껍게 그려낼건지야

 

fontAttributeName은 말 그대로 폰트야

 

UIFont라는 글꼴을 다루는 클래스가 있지

 

이런 속성들을 Dictionary에 넣어줄 수 있고

 

너희가 만든 attributedString의 어떤 문자에든 설정할 수 있어

 

그건 그렇고 Font(폰트,글꼴)에 대해서 이야기 해보자

 

Font는 iOS에서 엄청 중요해

 

iOS를 보고 느끼는데 매우 중요한 역할을 하지

 

여기 모든 종류의 폰트가 있어

 

볼드체나 헤딩폰트나 시스템 폰트같은게 보이지

 

이렇게 폰트가 얼마나 중요하게 쓰이는 지를 보라고

 

그러니까 폰트는 정말 중요해

 

좋은 앱을 만들고 싶다면 폰트에 신경을 써야 해

 

그럼 어떻게 내가 원하는 폰트를 선택하거나 가져올 수 있을까?

 

폰트를 선택하는데 3가지 방법이 있는데

 

첫번째 방법은 preferredFont라는 걸 사용하는 거야

 

preferredFont는 사용자의 컨텐츠를 보여줄 때 사용하는 폰트야

 

캘린더 앱에서 사용자의 일정 같은 것처럼 사용자의 텍스트로 써

 

날씨 앱이라면 온도가 되겠지

 

이런 것들이 사용자의 컨텐츠가 되는 부분이야

 

대부분은 이걸 스토리보드에서 가져오곤 하는데

 

Atrributed Inspector로 가서 폰트를 선택하고

 

우린 지금까지 시스템 폰트(System Font)만 썼었지

 

시스템 폰트를 쓰는 버튼같은 것만 썼으니까

 

하지만 컨텐츠로는 거기에서 preferredFont를 고를거야

 

잠시후 preferredFont 스타일에 어떤 것들이 있는지 알아볼거야

 

코드로는 UIFont의 static 타입 함수를 쓸건데

 

preferredFontForTextStyle이라는 함수고

 

어떤 스타일의 폰트를 원하는지를 묻고 UIFont를 반환할거야

 

텍스트 스타일(TextStyle)이 뭐냐고?

 

여덜 아홉개가 있는데

 

예를 들면 Headline, Body, Footnote

 

UI가 그 시점에 뭐를 하는지에 따라 적정한 스타일을 선택해야 해

 

Caption 같은 다른 것들도 있어

 

가끔 Caption과 Footnote의 차이점으로 고민하게 될 수도 있어

 

미묘한 차이가 있으니까 둘다 써보고 어떤게 최적인지 봐야겠지

 

멋진 UI를 만들기위해 다양한 preferredFont를 사용하게 될거야

 

아름다운 폰트들이야

 

두번째 폰트 종류로 시스템 폰트(system font)가 있어

 

systemFontOfSize나 boldsystemFontOfSize가 있는데

 

계산기에도 사용해 볼 수 있겠지

 

버튼같은 시스템 요소에 사용되지

 

시스템 폰트는 이런데 사용되는거야

 

계산기 앱에서 디스플레이의 폰트는 시스템폰트를 사용해선 안되

 

디스플레이에 들어갈 텍스트는 사용자의 컨텐츠 같은 것이거든

 

거기엔 preferredFont를 사용해야겠지만

 

아직 슬라이드를 다 보여주지 않았으니까 한꺼번에 줄일 수 있어

 

아무튼 그땐 preferredFont를 쓰는게 더 나을거야

 

또 가끔은 거기에 다른 폰트를 쓰고 싶을 수도 이겠지

 

특정한 폰트를 쓰고 싶을 수도 있을테니까

 

특정한 폰트를 쓰기위한 세번째 방법은

 

예를 들어 계산기의 디스플레이 텍스트를

 

LED 부속 같은 모양으로 하고 싶을 수 있지

 

옛날 스타일의 재밌는 모양의 계산기 있잖아

 

LED 모양으로 된 디스플레이 말이지

 

그래서 우린 폰트를 LED 폰트로 만들려는 거야

 

그럴 땐 UIFont하고 특히 UIFontDescriptor를 잘 봐야 하는데

 

특정한 폰트 패밀리에서 특정한 폰트를 선택하는 법을 제공하지

 

예를 들어 LED 폰트 패밀리가 되겠지

 

정리하면 폰트엔 3가지 방법이 있는거야

 

preferred과 system 그리고 커스터마이징한 폰트 이렇게 말야

 

이미지를 그리는 과정을 알아보자

 

텍스트를 그리기위해 UILabel이 있었던 것처럼

 

이미지를 그리려면 UIImageView가 필요해

 

이미지를 넣고 싶다면

 

예를 들어 이 친구 이마에 이미지를 넣고 싶다면

 

여기에 UIImage를 두고 내가 넣고 싶은 이미지를 넣어주면 되

 

내가 만든 페이스뷰의 하위뷰로 넣는 것이지

 

이렇게 하는 게 여러 방법 중 하나야

 

하지만 UIImage를 drawRect안에 그려넣고 싶다면

 

텍스트랑 매우 비슷해

 

일단 UIImage를 가져올거야

 

가져오는 방법엔 여러가지가 있는데

 

가장 많이 쓰는 방식은 파일 이름으로 가져오는 거야

 

Images.xcassets에 이미지를 넣어 놓고

 

지금까지 supporting file에 옮겨났던거 기억하지

 

Images.xcassets 라고 말야

 

이미지를 거기로 드래그해서 넣고 이름을 준 다음에

 

UIImage(named: 이미지 이름)라고 하면 UIImage를 가져오지

 

이미지를 가져오는데 실패할지도 모르니까 이건 옵셔널이야

 

이미지를 드래그해서 넣는 것을 까먹는다던지 뭐든 말이지

 

일단 이미지를 가져왔으면

 

그건 그렇고 다른 방법으로도 UIImage 객체를 생성할 수 있어

 

파일이나 인터넷에서 가져온 이미지 데이터로도 가능하지

 

Core Graphics로 이미지를 그려내는 것도 가능해

 

일단 이미지를 가져왔으면 이렇게 변수 image가 있을거고

 

텍스트를 한 것과 동일하게 그려줄 수 있어

 

drawAtPoint는 왼쪽 상단을 기준으로 하고

 

drawInRect는 이미지를 그리긴 하는데

 

Rect에 맞춰서 비율을 조정할거야

 

또 drawAsPatternInRect로 타일을 까는 효과를 줄 수 있어

 

Rect를 받아서 직사각형 안을 타일 형태로 채울거야

 

이 코드들이 drawRect에 있을 것들이야

 

뷰에서 마지막 내용인데

 

bounds가 바꼈을 때 다시 그려내는 상황을 보자

 

뷰의 bounds가 바뀌면 이 안에 얼굴은 어떻게 될까?

 

이 얼굴이 세로 화면에서 이렇게 보인다고 했을 때

 

기기를 돌리면 뷰의 bounds가 이렇게 가로 화면으로 바뀌겠지

 

너흰 얼굴이 다시 그려져도 똑같이 보일거라고 생각할지도 몰라

 

하지만 그렇지 않아

 

얼굴은 이렇게 보이게 될거야

 

이렇게 가로로 길게 늘어날거야

 

왜냐하면 bounds를 바꿨을 때 기본 설정이

 

다시 그려내지 않기 위해

 

모든 비트의 크기를 조정하는 걸로 되어 있어

 

너희가 생각하듯이 퍼포먼스에 관련된 거야

 

훨씬 간단한 방식이지

 

비트를 일단 늘려놓고 다시 그려달라고 요청하면 되니까

 

이런건 UIIView의 contentMode라는 프로퍼티로 고칠 수 있어

 

contentMode의 값으로 컨텐트를 이동시킬 수 있지

 

왼쪽, 오른쪽, 위, 아래, 오른쪽 위, 왼쪽 위 등으로 말야

 

컨텐트를 늘리는 게 아니라 새 bounds의 장소로 이동하는 거야

 

크기를 조정할 수 도 있는데 기본값은 ScaleToFill이야

 

영역을 채우기 위해 늘리는 행동 등을 하지

 

아니면 아예 다시 그려버릴 수도 있겠지 (Redraw)

 

UIContentMode를 Redraw라고 설정하면

 

drawRect를 다시 호출할거야

 

자주 그렇게 하고 싶어질거야

 

거의 항상 Redraw를 쓰고 싶을지도 모르고

 

데모에서 한번 써볼거니까 그때 보면 되

 

'연습 > swift개발' 카테고리의 다른 글

4.6 얼굴앱 - 스토리보드 연결  (0) 2022.01.20
4.5 얼굴앱-얼굴형  (0) 2022.01.20
4.3 그림을 그려보자  (0) 2022.01.20
4.2 뷰는 어떻게 만들까  (0) 2022.01.20
4.1 화면의 기본, 뷰를 알아보자  (0) 2022.01.20