데모로 바로 들어가보자
내가 이야기했던 두가지를 할건데
인터페이스 빌더(Interface Builder)와 모델(Model)이야
모델은 FaceViewController에 쓰일 얼굴의 표정이 될거야
놀랍지도 않지
여긴 지난 시간에 끝냈던 FaceView야
지금부터 빠르게 FaceView를 업그레이드할거야
조금 더 멋지게 만들기 위해서지
지난 시간을 기억해보면 우리 FaceView엔 입이 있었지
입을 약간 변형해 줄 수 있었는데
웃거나 찡그리게 할 수 있었어
그리고 눈이 두 개 있었지
두가지를 추가해 볼건데
첫번째는 두 눈을 감게 할거야
나머지 하나는 눈썹을 추가할거야
굉장히 빨리할거야
이것을 만들 코드를 통해 배울게 많이 없거든
하지만 우리가 그동안 해왔던 것들보단 훨씬 많은 내용이야
자, 몇개의 public var를 만들거야
설정 가능한 것들이 될거니까
하나는 눈을 뜨거나 감거나니까 Bool이 될 것이고
눈을 뜬 상태로 시작할거야
이게 기본값이 될거야
또 eyeBrowTilt(눈썹 기울기)라는 걸 만들거야
Double 타입이 될거고 0.0부터 시작하자
전에 만들었던 입의 곡률과 비슷하지
-1은 완전히 주름지게 할거고
1은 눈썹을 완전히 풀리게 할거야
우리가 만들었던 입의 곡률 설정과 비슷하지
먼저 눈을 뜨거나 감는 기능부터 시작하자
꽤 간단해
여기 있는 pathForEye 안에서
pathForCircle를 사용하고 있는 걸 볼 수 있어
떠진 눈은 원래 원형이기 때문이지
만약 눈이 떠진 상태라면
이 부분이 계속 실행되도록 할거야
하지만 눈이 감긴다면
대신 내가 할 것은
이렇게 할건데 기본적으로 선을 사용할거야
눈이 감긴다면 수평선을 그릴거야
매우 간단하지
BezierPath 만들고 moveToPoint로 경로잡고 선을 긋는거야
그리고 눈썹을 조정하려면
pathForEye, pahtForMouth를 가진 것처럼
pathForBrow 메소드를 만들거야
내가 미리 만들어 둔게 여기 있지
여기 pathForBrow가 있어
이건 꽤 단순해
선을 그릴 뿐이지만
얼마나 기울이고 싶은지에 따라 이 선들이 기울어질거야
물론 위로 올라가서 Ratios 구조체에 있는 static 상수가 필요해
두개골의 반경에 따른 눈썹의 상대적인 위치말이야
여기 위에 있는 반경과 관계있는 것들처럼 말이지
pathForEye와 pathForMouth같이 pathForBrow를 만들었어
이제 아래로 가서 선을 그을거야
pathForBrow(.Left).stroke( ) 로 왼쪽 눈썹 그리고
pathForBrow(.Right).stroke( ) 로 오른쪽 눈썹 마저 그릴거야
눈썹을 제대로 보이는지 실행해보자
오 눈썹을 가지고 있고 꽤 귀여운데!
또한 눈을 감을 수 있게 해야지
eyeOpen을 false로 바꾸고 실행해볼거야
됐네, 눈을 감았어!
눈썹의 기울임 정도를 설정 할 수도 있어
-0.5로 해볼까
이렇게 하면 어떻게 보일지 확인해보자
눈썹이 이렇게 삐딱하게 기울었지
눈썹과 함께 더 많은 표정을 볼 수 있어
그래서 이걸 내가 넣은거야
얼굴 표정과 관련해서 더 많은 여지가 생긴거야
몇가지 다른 것들을 해볼 건데
우선 여기에 상수로 값을 고정시켜 놓은게 몇 개 있지
얼굴 색을 항상 파란색으로 설정한 것처럼 말야
그렇게 하고 싶지 않으니까 이걸 변수로 바꿔볼꺼야
그래서 이걸 color라고 부를거고
여기 위에 변수를 만들어보자
color라는 이름에 타입은 UIColor로 하고
파란색을 기본색으로 둘거야
UIColor.blueColor( ) 기본값으로 해놓고
또 선 너비를 설정하기위한 변수를 만들거야
현재 선 너비는 늘 0.5로 되어있지
하지만 기본값이 5.0가 되게 할거야
모든 선 너비를 이 변수를 사용해 5.0로 만들거야
5.0 대신에 lineWidth 변수로 하나씩 바꿔줄거란 뜻이야
선 너비를 설정한 곳이 눈썹, 눈, 입, 두개골 4곳이지
이렇게 해서 FaceView를 만들었어
이 FaveView는 외부에서 가져와 사용하기에도 꽤 좋지
이런 모든 전역함수 같은 것들을 컨트롤러가 사용하기 쉽지
왜냐하면 FaceView는 뷰(View)의 일부이니까
FaceView는 얼굴을 그리는 일반적인 뷰이고
FaceView는 어떤 컨트롤러든지 얼굴을 그릴 때 사용될 수 있어
우리가 지금 가지고 있는 컨트롤러에서 말야
얼굴을 그리는 컨트롤러이니까
여기 있는 컨트롤러를 살펴보면
얼굴을 그리는기는 하는데 얼굴을 그렇게 많이 건들진 않아
여기에 얼굴을 넣을 수 있는 스토리보드로 된 뷰가 있거든
하지만 여기선 많은 것을 하고 있진 않아
이건 잠시후에 고칠거야
성가신 하나 있는데 여기 스토리보드를 보면
여기 스토리보드가 있지
여기선 얼굴이 보이지 않아
우리 앱에서는 MVC가 하나뿐이고
우린 그게 얼굴이고 보이지 않을 거라는 걸 알고 있어
근데 만약 20개의 뷰컨트롤러를 가지고 있다면 어떨까
이건 얼굴이지만 얼굴말고 다른 것들도 있다고 생각해봐
여기에 얼굴이 보이면 정말 좋겠지
인터페이스 빌더에서 얼굴을 볼 수 있게 하는거지
사실, 정말 쉬워
View, 그러니까 커스텀 UIView로 가서 여기선 FaceView지
그리고 앞에 @IBDesignable을 넣어
@IBDesignable을 앞에 넣어주면
인터페이스 빌더가 자동으로 판단할거야
오, 이걸 내가 그려주었으면 하는구나 하고 말야
컴파일 하고나면 여기에도 그림을 그릴거야
여기 스토리보드에 얼굴이 나타났지
꽤 멋지지!
하지만 아직 아쉬운 건
FaceView를 클릭하고 오른편에 나오는 Inspector 설정창에는
UIView에서 상속받은 속성들로만 FaceView를 설정할 수 있어
Background Color처럼 일반적인 속성들 말이야
눈썹 기울기, 입의 곡률, 그리고 색깔, 크기를
지정할 수 있다면 진짜 멋져질거야
인터페이스 빌더에서 그런 설정을 할 수 있다면 정말 멋질거야
그래서 내가 원하는 얼굴을 설정할 수 있겠지
그럼 처음엔 설정한게 인터페이스 빌더에서 보이겠지
그렇게도 할 수 있어
FaceView로 돌아가서
여기에 있는 모든 것들을 설정할 수 있어
그냥 이것들 앞에 @IBInspectable을 넣을 수 있어
inspector 설정창에서도 볼 수 있다는 뜻이야
그리고 여기 있는 모든 것들을 inspectable로 만들거야
모든 걸 inspectable로 만들고
인터페이스 빌더로 가자
여기로 와서 유틸리티를 보이게 하면
이제 볼 수 있지
뷰에 관련된 모든 것들도 여전히 있지만
이젠 FaceView에 관한 뷰 속성들이 보이지
크기(scale)를 2.5로 설정할 수 있어
작게 만들어졌지
아니면 색을 주황으로 설정할 수도 있어
샌프란시스코를 뜻하는 거대한 색깔이지
선의 너비를 2로 설정 할 수 있어
5 대신에 더 얇게 한거야
여기서 입의 곡률도 설정 할 수 있어
-0.5로 설정해볼까
눈도 뜨게 하고
보이지?
다시 원래 크기로 바꾸고
지금까지 멋진 걸 해봤어
사실 처음 앱을 실행하면
이 값들을 사용하게 될거야
그럼 한번 실행해보자
여기서 변하지 않은 얼굴을 볼 수 있을거야
선의 색상, 선의 굵기같은 모든 것들 말이야
여기에 또다른 attribute(속성)를 설정했었지
Background Color(배경색)같은 것들이지
실행하면 이러한 속성들이 적용되서 작동이 될거야
이러한 것들을 하는 동안 조심해야하는 나머지 하나는
이 @IBinspectable 변수들은 명시적으로 타입을 적어주어야 해
대부분의 경우에는 타입을 별도로 명시해 줄 필요가 없었어
여기에 Double을 추론할 수 있었지
하지만 @IBInspectable을 쓴다면 타입을 명시적으로 적어야 해
기본적으로 인터페이스 빌더는 타입을 추론할 수 없어
스위프트는 가능하지만 인터페이스 빌더는 할 수 없지
그래서 명시적으로 만들어야 해
작은 댓가가 필요한 셈이지
여기서 뷰에 대해 이야기 하고 싶은 하나는
누군가가 코드로 scale 값을 무언가로 설정한다면
FaceViewController에
FaceView의 scale을 설정하는 코드가 있다고 해보자
그것들은 사실 아무 것도 하지 않을거야
화면에선 아무것도 바뀌지 않을거야
왜그럴까?
이 scale을 0.5로 설정했을 때
이 변수값을 한번 설정한게 전부야
다른 일을 하지 않았지
그래서 저 변수는 0.5로 설정이 될거야
그리고 얼굴이 다시 그려질 때
다시 작게 그려지겠지만
얼굴을 다시 그리게 만드는 건 아무것도 없어
설정할 수 있는 public 변수를 가지고 있을 땐 언제든
이 값들이 변했을 땐 뷰가 다시 그려질 수 있도록 만들어줘야 해
어떻게 할 수 있을까
전에 이야기 했던 프로퍼티 옵저버
(property observer, 프로퍼티 관찰자) 를 사용할거야
didSet, willSet으로 기억할거야
이것들은 코드의 한 부분인데
여기선 'scale = 0.90'이 set될 때마다 실행돼
이게 만약 어떤 값으로 set(설정)되면
didSet 안에서 다시 그리고 싶은데 어떻게 그릴까?
아마 나는 self.drawRect( )라고 말할거야
정말 이렇게 할까?
아니야 이렇게 하면 실패할거야
절대 drawRect을 부르면 안돼
대신 setNeedsDisplay( )를 부를거야
setNeedsDisplay는 우리가 시스템에게 말하는 것과 같아
"부탁인데 나 다시 그려져야 해" 라고 말야
언젠가 미래에 일어날거야
아주 가까운 미래에
하지만 미래 언젠가가 되겠지
이건 매우 흔한 일이야
보통은 여기에서 줄바꿈을 하지 않고
모두 같은 줄에 넣지
이렇게 말이지
그리고 이걸 다른 변수들 뒤에도 붙일거야
주석이 있는 자리에 넣자
여기도 그렇게 해주고
화면 공간이 좁으니까 오른쪽 메뉴는 잠시 숨겨두자
그래서 누군가가 여기 모든 변수 중 하나를 설정하면
그것이 다시 그려지게 될거야
정말 멋진 것은 3~4개를 연달아 설정한다고 해도
그때마다 세네번 그리지 않는다는 점이야
단지 "나 화면에 보여져야 해" 라고 반복적으로 말할 뿐이지
어느정도 시간이 지날때까지는 변화를 매번 표시하지는 않아
한번에 화면에 표시하지
이렇게 약간의 딜레이를 줘서 훨씬 더 좋은 성능을 낼 수 있어
그게 이런 방식을 하는 주된 이유는 아니야
하지만 하나의 이유가 될 수 있지
모두들 이해되니?
우린 거의 항상 이 didSet을 사용할거야
FaceViewController에서도 didSet을 보게 될거야
약간 다른 용도로 사용하긴하지만
어쨌든 didSet 정말 편리해
'연습 > swift개발' 카테고리의 다른 글
4.10 제스처는 어떻게 만들까 (0) | 2022.01.20 |
---|---|
4.9 얼굴앱 - 모델과 컨트롤러 분리 (0) | 2022.01.20 |
4.7 얼굴앱 - 눈 넣기 (0) | 2022.01.20 |
4.6 얼굴앱 - 스토리보드 연결 (0) | 2022.01.20 |
4.5 얼굴앱-얼굴형 (0) | 2022.01.20 |