티스토리 뷰

반응형

 

안녕하세요 :) Zedd입니다.

제가 zeddios.tistory.com/1100

 

iOS 14 + ) UILabel - lineBreakStrategy 실험👀

안녕하세요 :) Zedd입니다. UILabel에 lineBreakStrategy라는 프로퍼티가 생겼습니다. 물론 지금은 Beta (4) 이므로 언제 사라질지 모름 ㅎ 만약 사라지면 글에 메모 해둘게요 ㅎㅎ... ✔️ 제 환경은 Xcode 12

zeddios.tistory.com

이런글을 썼었어요.

오늘 글 역시 제 실험글입니다. 틀린 부분이 있을 수 있습니다 ⚠️ 

위 글을 읽고오시면 더 이해가 잘 가실겁니다!

 

# 들어가기 전에

왼쪽은 iOS 13.5이고 오른쪽은 iOS 14.0이다. 

14.0에서는 한글 word wrap이 예쁘게 되고 있는 것을 볼 수 있다.

따로 lineBreakStrategy를 지정을 안했는데,

이 글에서 말했듯이

lineBreakStrategy는 이렇게 3가지가 있다. 

내 추측은

1. UILabel에 lineBreakStrategy 따로 지정 안함.

2. standard로 들어감

3. standard로 지정되어있어도 한글 wrod wrap이 잘 된다.

4. 언어를 보고 자기가 알아서 지정을 해주는것이 아닐까? 추측.

 

# 문제

자. 그럼 나는 iOS 14.0에서 따로 작업해줘야할 게 있을까?

없다.

왜냐하면 iOS 14.0에서는 lineBreakStrategy가 standard로 들어가는 것 같고,

한글 word wrap이 잘 되고 있기 때문이다.

그런데 한가지 문제가 발생한다.

바로 이거다. 위쪽을 보면 알겠지만, iOS 14.0 시뮬레이터이다. 그런데 지금

블라인
드를 걷어

이런식으로 한글 word wrap이 예쁘게 안되고있다.

 

# 원인

왼쪽과 오른쪽의 차이점은 하나다.

lineSpacing. 딱 봐도 오른쪽이 더 넓다. 

 

왼쪽

self.myLabel.attributedText = NSAttributedString(string: text)

오른쪽

let style = NSMutableParagraphStyle()
style.lineSpacing = 5

self.myLabel.attributedText = NSAttributedString(string: text,
                                                 attributes: [.paragraphStyle: style])

lineSpacing이 문제일까? 

let style = NSMutableParagraphStyle()

self.myLabel.attributedText = NSAttributedString(string: text,
                                                 attributes: [.paragraphStyle: style])

그냥 NSMutableParagraphStyle()만 해서 넣어줘도 한글 word wrap이 안되는 상황이 발생한다.

 

# 해결

이상하지만 그렇게 이상한 상황은 아니라고 본다.

ParagraphStyle이 먹여지면...안될 수도 있지...그래..

+ paragraphStyle을 사용했을 때 lineBreakStrategy가 안되는 이유를 찾았다.

NSParagraphStyle / NSMutableParagraphStyle에 lineBreakStrategy라는 프로퍼티가 있다@!!!!!

기본값은 NSLineBreakStrategyNone이라고 한다.

그래서 안먹는 듯 하다.

override func viewDidLoad() {
    super.viewDidLoad()
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 5
    
    if #available(iOS 14.0, *) {
        style.lineBreakStrategy = .hangulWordPriority
    } else {
        // Fallback on earlier versions
    }
    
    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.paragraphStyle: style])
}

14.0이상에서는 style의 lineBreakStrategy에 hangulWordPriority를 줬다. 

 

그리고 그 다음에 myLabel에 attributedText를 줬다.

그럼 한글 word wrap이 잘 되는 것을 볼 수 있다.

 

# 이상한점.

이상한점이 있다.

위에서 처럼 ParagraphStyle에 있는 lineBreakStrategy를 수정할 수도 있지만,

UILabel의 lineBreakStrategy를 지정해서 되게 하고싶었다. 

바로

override func viewDidLoad() {
    super.viewDidLoad()
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 5
    
    if #available(iOS 14.0, *) {
        self.myLabel.lineBreakStrategy = .hangulWordPriority
    } else {
        // Fallback on earlier versions
    }

    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.paragraphStyle: style])
}

이 코드다. 

이 코드만 보면

왼쪽처럼 lineSpacing + 한글 word wrap이 잘된 상태로 나와야 할 것 같지만, 오른쪽 처럼 나온다.

Q : self.myLabel.lineBreakStrategy = .hangulWordPriority 해줬잖아;;; 근데 왜안돼?

A : 

안되는 상황 1 : viewDidLoad에서 lineBreakStrategy를 hangulWordPriority지정 + attributedText지정.

안되는 상황 2 : viewDidLoad에서 lineBreakStrategy를 hangulWordPriority지정 + viewWillAppear에서 attributedText지정.

위 2가지 상황일 때 안된다.

위 상황에 대해 이렇게 대답할 수 있다.

Q : paragraphStyle의 lineBreakStrategy가 None이니까 안되지 이 바보야

그렇다면 다음 상황을 보자.

override func viewDidLoad() {
   super.viewDidLoad()
   
   if #available(iOS 14.0, *) {
       self.myLabel.lineBreakStrategy = .hangulWordPriority
   } else {
       // Fallback on earlier versions
   }
}

override func viewDidAppear(_ animated: Bool) {
   super.viewDidAppear(animated)
   
   let style = NSMutableParagraphStyle()
   style.lineSpacing = 5
   self.myLabel.attributedText = NSAttributedString(string: text,
                                                    attributes: [.paragraphStyle: style])
}

viewDidAppear에서 attributedText를 주거나, (이때 viewDidAppear에서 같이 UILabel의 lineBreakStrategy를 줘도 잘 동작한다.)

이렇게

override func viewDidLoad() {
    super.viewDidLoad()
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 5
    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.paragraphStyle: style])
    if #available(iOS 14.0, *) {
        self.myLabel.lineBreakStrategy = .hangulWordPriority
    } else {
        // Fallback on earlier versions
    }
}

attributedText를 먼저 지정하고;;;;;  그 다음에 lineBreakStrategy를 지정하니 잘 나왔다.

이 부분은 도대체 왜 이런건지;;;;잘 이해가 안간다.

Q : 나는 paragraphStyle의 lineBreakStrategy를 건들이지도 않았는데

1. viewController 라이프 사이클에 따라 결과가 달라짐

2. viewDidLoad에서 lineBreakStrategy를 지정하는 순서에 따라 결과가 달라짐 

이 잘 이해가 안간다. 

2번은 attributedText지정 후에 myLabel을 업데이트 한거니까..잘 되는게 맞는것 같기도 하다. 

근데 1번은 뭐지...? 내 Xcode버전은 12.0.1이다. 

 

 # 참고. lineBreakStrategy의 rawValue.

lineBreakStrategy의 rawValue를 찍어보면 

override func viewDidLoad() {
    super.viewDidLoad()
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 5
    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.paragraphStyle: style])
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 0)
}

처음 myLabel의 lineBreakStrategy의 rawValue는 65535가 나온다.

근데 attributedText를 넣은 후에는 0으로 나온다.

attribute없이 그냥 넣어보자.

override func viewDidLoad() {
    super.viewDidLoad()
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)

    self.myLabel.attributedText = NSAttributedString(string: text)
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)
}

이렇게 paragraphStyle을 주던 걸 없애보았다. 그럼 rawValue가 65535에서 바뀌지 않는다.

또한 paragraphStyle이 아닌 다른 attribute를 넣어도

override func viewDidLoad() {
    super.viewDidLoad()
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)

    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.foregroundColor: UIColor.cyan])
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)
}

65535에서 바뀌지 않는다.

 

Q : 65535가 뭐야??

A :  standard의 rawValue이다.

standard의 rawValue는 0xFFFF인데,

https://decimal.info/hex-to-decimal/F/how-to-convert-0XFFFF-to-decimal.html

0xFFFF는 65535이다.

override func viewDidLoad() {
    super.viewDidLoad()
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 65535)
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 5
    self.myLabel.attributedText = NSAttributedString(string: text,
                                                     attributes: [.paragraphStyle: style])
    
    print(self.myLabel.lineBreakStrategy) // NSLineBreakStrategy(rawValue: 0)
}

처음에 65535로 나온 이유는, 기본적으로 UILabel의 lineBreakStrategy가 standard이기 때문이고,

attributedText지정 후 rawValue가 0이 나온 이유는,

위에서 말했듯이 ParagraphStyle의 lineBreakStrategy가 NSLineBreakStrategyNone이기 때문이다. 

다른것들은 이런식이다. (각각 1, 2)

그러니 rawValue의 65535를 봐도 당황하지 말자. 

 

 

반응형

'iOS' 카테고리의 다른 글

iOS ) Snapshot Testing  (0) 2020.11.20
Coordinator Pattern  (3) 2020.11.15
iOS ) DarkMode에서의 CGColor(resolvedColor(with:))  (1) 2020.11.09
iOS ) iOS 14+에서 UIPageControl 좌우 패딩  (0) 2020.11.02
iOS ) UIColor비교 실험🔬  (1) 2020.10.29