iOS 12.x에서 UILabel의 Text가 짤리는 현상 기록.
안녕하세요 :) Zedd입니다.
기록용 글입니다.
# 상황
평범한 UILabel입니다.
(제가 12는 있는게 12.2밖에 없어서 12.2로 설명하겠습니다. )
iOS 12.2와 iOS 14.2입니다.
우측 상단의 "펼치기"를 누르면, Text가 애니메이션과 함께 보여지는 스펙입니다.
하지만 이상하게 iOS 12.2에서 텍스트가 짤리는군요. (iOS 13.5에서도 안짤려요)
# 분석
1. 높이를 늘린다.
위에서 보시다시피, Label에 높이가 지정이 되어있습니다.
그럼 이렇게 생각할 수 있겠죠!
높이가 부족해서 짤리는구나? 높이를 늘리자.
높이를 늘렸더니 더이상 짤리지 않습니다.
자 이렇게 해결해버리면,
1. 다음에 이런 상황이 일어났을 때 또 높이를 늘리는 방식으로 해결해야할까요?
2. 높이로 인해 디자인이 깨진다면?
3. iOS 13, iOS 14에서는 발생안하는데..분기칠것도 아니잖아요????
여러 문제들이 생깁니다. 그러니 왜 이런 문제가 발생하는지 알아봅시다.
2. 코드 분석 - lineSpacing
한글이 꽤나 말썽을 부리니..한글에서만 이러는지 확인해볼 수 있겠죠.
영어로 수정해보겠습니다.
영어에서는 iOS 12에서도 잘 나오는군요.
한글만 문제가 된다는 힌트를 얻었습니다.
View Debugger로 본 상태입니다.
묘하게 한글 && iOS 12.2에서..Text가 아래에서 조금 들떠있는 것을 볼 수 있습니다.
코드를 봅시다.
우측 상단 "펼치기"를 눌렀을 때 실행되는 코드입니다.
의심가는 코드가 있네요!
let style = NSMutableParagraphStyle()
style.lineSpacing = 4
NSMutableParagraphStyle입니다.
lineSpacing값을 넣어주고 있고, NSAttributedString의 attribute로 넣어주고 있습니다.
lineSpacing을 제거해보겠습니다.
오! 해결 되었군요.
iOS 13 ~ 14는 lineSpacing 최적화(?)를 해주는 걸까요?
똑같이 lineSpacing을 줬는데 iOS 13, 14에서는
lineSpacing이 한 줄 일땐 전혀 먹히지 않은(?) 상태로 보입니다.
자..그럼 여기서 해결하고 넘어가야 할까요?
지금은 한줄이라 크게 영향없지만, 만약 여러줄이라면?
디자이너가 원한 lineSpacing을 적용하지 않아 Text가 빽빽보일 수 있을 것 같습니다.
2. 코드분석 - Animation
지금 알 수 있는 사실은
1. 한글일 때만 발생(다른 언어는 제외하고)
2. Label의 Height와 lineSpacing을 유지해야함.
정도네요.
그럼 조금 더 분석해봅시다.
Height와 lineSpacing을 유지하고, Animation없이 그냥 표시되도록 해보겠습니다.
짤리지 않네요!
왼쪽은 Animation, 오른쪽은 Animation을 없앤겁니다.
Animation이 문제였을거라고는 생각하지 못했는데요.
이상한 점 하나는.. View Debugger에서는 짤리게 나오는데
실제 View에서는 안짤리게 나온다는 거...
아무튼 Animation과 연관이 있다는 사실을 알아냈습니다.
그렇다면 애니메이션을 제거해야할까요?
저같은 경우에는 제거를 해도 큰 상관이 없을 것 같은데...
iOS 13, 14에서는 잘 되고 있는 애니메이션을 iOS 12때문에 지우는 건 좀 마음이 아픕니다.
3. 코드 개선 - Layout
1. lineSpacing제거시 안짤렸음.
2. Animation제거시 안짤렸음.
➞ 위 2가지 사실로 볼 때...ParagraphStyle과 Animation이 뭔가가...맞지 않는다는 생각이 드네요.
iOS12에서는 PragraphStyle의 값이 UILabel에 최적화(???)되기 전에 Animation이 끝나는건가..?
추측입니다...
label의 constraint가 없데이트 되었으면,
label의 레이아웃을 확실히 하고 애니메이션을 시작하면 좋겠다는 생각을 했습니다.
labelHeight업데이트 후, Label에 대해 layoutIfNeeded()를 호출해주었습니다.
잘 나오는군요!
하지만 14.2에서 확인 결과
높이가 샤라락 업데이트 되어야 하는데, 높이 업데이트 다 된 Label이 그냥 내려오는 느낌..????
이게 gif에 잘 담긴지 모르겠는데;;;
사실 잘 생각해보면..
layoutIfNeeded의 특성상 높이가 업데이트 된 채로 애니메이션 되는게 정상 동작인 것 같아요!
하지만 마음에 안듭니다..
3. 코드 개선 2 - Layout
Label에 대한 layoutIfNeeded코드를 Animation closure에 함께 넣어줬습니다.
오른쪽이 layoutIfNeeded를 Animation closure에서 같이 한 결과입니다.
차이점이 조금 보이시나요???
# 결과
높이와 lineSpacing, 그리고 Animation을 유지하면서 해결했습니다.
# 후기
제가 수정한 방법이..elegant한 방식이 아닐지도 모르겠네요!
솔직히 마음에 안듭니다 ㅠㅠ..UIView 애니메이션 블럭 안에 myLabel에 대한 layoutIfNeeded를 해주다니..
혹시나 다른 방법을 알고계시다면, 댓글로 알려주시면 감사하겠습니다.
Height와 lineSpacing, 애니메이션을 모두 유지하면서 iOS 12, 13, 14 모두 예쁘게 나오는 법...
+ 궁금하실까봐 추가하자면..애니메이션 블럭 안에
UIView.animate(withDuration: 0.2, animations: {
self.myLabel.layoutIfNeeded()
})
이렇게 myLabel에 대해서만 layoutIfNeeded를 하면..
애니메이션이 안되거나 이상하게 됩니다.