개발+IT

Swift OptionSet으로 뷰 테두리 선 구현하기

Enum만으로는 뭔가 부족할 때가 있다

모바일 앱 개발자로 일하면서 디자인 요구사항을 받다보면 어딜 가든 꼭 받게 되는 요청이 여럿 있는데, 특정 뷰에 경계선을 그리는 것 역시 그 중 하나다. 일반적으로 Border라고 부르는데, 특정 화면, 혹은 커스텀 뷰의 상태 등에 따라서 상하좌우 각각에 경계선을 그릴 수 있어야 한다. 어려운 작업은 아니지만 매번 새로 그리자니 귀찮을 수 밖에 없기 때문에 이를 해결하기 위해 UIView의 확장 함수를 고안해보기로 했다. 조건은 단순하다.

  1. UIView를 상속하는 어떤 클래스에서도 쓸 수 있을것: 이것은 UIView 확장 함수를 고안한다는 것에서 이미 달성한 조건이다.
  2. 뷰의 상하좌우 어디에든 원하는대로 경계선을 그릴 수 있을 것
  3. 색상과 경계선 두께를 설정할 수 있을 것

2번을 해결하기 위해 어떤 방법을 쓸까 했을 때 우선적으로 떠오른 것은 enum이었다. swift의 enum이 워낙에 써먹기가 편하다보니 우선 enum부터 떠오르는게 습관화가 된 것 같은데, 안타깝게도 이 경우에는 enum이 최선의 방안이 되기는 어려웠다. 상하좌우 어디든 편하게 그릴수 있어야 하는데, 각각의 조건을(none, left, leftright, right, top, topleft, ...) 모두 조합한 case를 만들어야 한다는 것이 그다지 달갑게 느껴지지 않았기 때문이다. 그냥 단순히 기본값을 제공하는 함수를 만들까 하는 생각도 들었는데 이 역시 달갑게 느껴지지는 않았다. 나쁜 방법은 아니지만 뭔가 더 그럴싸한 구현을 해보고 싶었달까?(다시 생각해보니 이 함수가 오히려 나을수도 있겠다는 생각도 든다)

(지금 보니 훨씬 간단하네...)

여튼 기분상의 문제로 단순 Bool값을 사용하는 함수를 만드는 안도 폐기했다. 그렇다면 어떤 선택지가 있을까? 싶어 찾아보는데 딱 그럴싸한 해결책이 있었다. 바로 OptionSet 프로토콜을 사용하는 것이다.

위의 링크를 들어가서 첫 문장만 봐도 알겠지만, OptionSet은 bitset 타입을 나타내기 위한 프로토콜이다. OptionsSet의 구현체는 단일 값으로도 표현되고, Set 형태로도 표현될 수 있기 때문에 위의 경계선을 그리는 방법의 조건 2번에 아주 잘 부합한다고 할 수 있다. 실제 구현된 코드를 보면서 얘기해보자.

경계선을 그리기 위한 구현체이기 때문에, BorderOptions라는 이름을 붙였다. rawValue는 OptionSet의 구현체가 지니고 있을 실제 값으로, OptionSet을 구현하기 위한 필수 구현이다. 그 아래로는 static 선언된 let 변수가 있는데, 생성자를 보면 비트연산자로 값을 넣어주는 것을 알 수 있다. horizontal과 vertical은 각각 좀 더 편하게 사용하기 위해 만든 임의의 값이다. 위에서 언급한 바와 같이 BorderOptions.top과 같은 개별값 역시 BorderOptions이며, [.left, .right]와 같이 Set 형태로 표현해도 역시 BorderOptions 형태로 인정된다(애시당초 애플 개발자 문서의 목차를 보면 OptionSet이 Collections > Sets 항목에 들어가있다).

이것으로 경계선 그리기 조건의 2번 항목은 완료된 것이나 다름없다. 이제 실제로 BorderOptions로 경계선을 그리는 함수를 만들자.

다음과 같은 과정을 통해 경계선이 그려지도록 할 수 있다. 다만 이 방법의 경우 경계선을 그리려는 UIView가 적절한 레이아웃 과정을 거쳐 본인의 크기 등을 계산하기 전이라면 제대로 동작하지 않는다. 그러나 보통 경계선을 그리는 작업은 레이아웃 과정 이후가 되기 때문에 큰 문제는 없다고 본다.

위와 같이 경계선을 그렸다면 지우는 방법도 알아야겠지? 이거는 훨씬 더 쉽다. 위의 addBorder 함수에서 경계선을 그리기 전에 이미 그려진 서브레이어를 찾아서 지우는 부분을 응용하면 된다.

이런 방법을 쓰면 된다. 실제로 적용할때는 다음과 같은 방법으로 쓸 수 있다.

이런 식으로 구현된다. 어때요 참 쉽죠?

GAE BAL JA

구구리 님의 창작활동을 응원하고 싶으세요?

hell yeah, world
hell yeah, world
구독자 110
멤버십 가입

0개의 댓글

SNS 계정으로 간편하게 로그인하고 댓글을 남겨주세요.
새로운 알림이 없습니다.