iOS 앱 개발에서 사용자 경험을 결정짓는 중요한 요소 중 하나는 텍스트 렌더링입니다. 기본 UILabel은 간단한 텍스트 표시에 적합하지만, 링크 삽입, 특정 단어의 스타일링, 데이터 자동 감지 등 복잡한 요구사항을 충족하기에는 부족함이 있습니다. TTTAttributedLabel은 이러한 한계를 극복하기 위해 설계된 오픈 소스 라이브러리로, UILabel과 완벽하게 호환되면서도 강력한 기능을 제공합니다.
TTTAttributedLabel이 제공하는 핵심 기능
- 자동 데이터 검출: URL, 전화번호, 주소, 날짜 등을 자동으로 인식하여 링크로 변환합니다.
- 사용자 정의 링크: 텍스트의 특정 범위(Range)를 지정하여 클릭 가능한 링크를 삽입할 수 있습니다.
- 고급 스타일링: 링크의 하이라이트 색상, 밑줄 스타일 등을 개별적으로 설정 가능합니다.
- 세밀한 레이아웃 제어: 행간(Line Spacing), 단락 간격, 수직 정렬 등을 손쉽게 조정합니다.
자주 발생하는 런타임 오류 및 해결 방안
1. attributedText 직접 할당 시 발생하는 크래시
많은 개발자들이 UILabel을 사용하던 방식 그대로 attributedText 속성에 직접 값을 할당하곤 합니다. 하지만 TTTAttributedLabel에서는 이 방식이 내부의 링크 관리 메커니즘을 손상시켜 앱이 예기치 않게 종료되는 원인이 될 수 있습니다.
// 위험한 방법: 크래시가 발생할 수 있음
NSAttributedString *styledString = [[NSAttributedString alloc] initWithString:@"Hello World"];
richLabel.attributedText = styledString;
// 권장되는 방법: setText 메서드 활용
[richLabel setText:styledString];
헤더 파일 명세에 기술된 바와 같이, 반드시 setText: 메서드를 호출해야만 내부 링크 데이터가 정상적으로 갱신됩니다.
2. 링크 클릭 이벤트가 작동하지 않는 경우
텍스트에 링크는 표시되지만 클릭해도 반응이 없다면 다음 세 가지를 확인해야 합니다.
delegate설정 여부userInteractionEnabled활성화 여부enabledTextCheckingTypes설정 확인
// 링크 동작을 위한 필수 설정
richLabel.userInteractionEnabled = YES;
richLabel.delegate = self;
richLabel.enabledTextCheckingTypes = NSTextCheckingTypeLink;
3. 텍스트 생략(Truncation) 처리 문제
여러 줄의 텍스트를 표시할 때 끝부분이 잘리는 현상을 커스텀하고 싶다면 attributedTruncationToken을 사용할 수 있습니다.
// 생략 기호 커스터마이징
NSDictionary *tokenAttrs = @{NSForegroundColorAttributeName: [UIColor grayColor]};
NSAttributedString *moreToken = [[NSAttributedString alloc] initWithString:@"...더보기" attributes:tokenAttrs];
richLabel.numberOfLines = 2;
richLabel.lineBreakMode = NSLineBreakByTruncatingTail;
richLabel.attributedTruncationToken = moreToken;
고급 스타일 적용 기법
블록 기반의 복합 스타일링
setText:afterInheritingLabelAttributesAndConfiguringWithBlock: 메서드를 사용하면 기존 라벨의 속성을 유지하면서 특정 부분만 동적으로 스타일링할 수 있습니다.
NSString *content = @"개인정보 처리방침 및 이용약관에 동의합니다.";
[richLabel setText:content afterInheritingLabelAttributesAndConfiguringWithBlock:^NSMutableAttributedString *(NSMutableAttributedString *mutableString) {
// '이용약관' 부분에 굵은 글씨와 색상 적용
NSRange targetRange = [content rangeOfString:@"이용약관"];
if (targetRange.location != NSNotFound) {
UIFont *boldFont = [UIFont boldSystemFontOfSize:15.0f];
[mutableString addAttribute:NSFontAttributeName value:boldFont range:targetRange];
[mutableString addAttribute:NSForegroundColorAttributeName value:[UIColor systemRedColor] range:targetRange];
}
return mutableString;
}];
단락 및 레이아웃 조정
텍스트 내부의 여백이나 줄 간격을 미세하게 조정하여 가독성을 높일 수 있습니다.
// 텍스트 인셋 및 줄 간격 설정
richLabel.textInsets = UIEdgeInsetsMake(8, 12, 8, 12);
richLabel.lineSpacing = 6.0;
richLabel.verticalAlignment = TTTAttributedLabelVerticalAlignmentCenter;
성능 최적화 가이드
리스트(UITableView 등) 내에서 많은 수의 TTTAttributedLabel을 사용하는 경우 성능 이슈가 발생할 수 있습니다. 이를 방지하기 위한 팁은 다음과 같습니다.
- 필요한 검출기만 활성화:
NSTextCheckingTypeLink등 실제로 필요한 타입만 지정하여 연산량을 줄입니다. - 속성 업데이트 최소화: 셀이 재사용될 때 속성을 한 번에 몰아서 변경하는 것이 좋습니다.
- 사전 계산: 텍스트 높이 계산이 복잡하다면 백그라운드 스레드에서
NSAttributedString을 미리 생성해 두는 방식을 고려하십시오.
Interface Builder 관련 팁
Storyboard나 XIB에서 TTTAttributedLabel을 사용할 때 IB Designables 오류가 발생한다면, 프로젝트 구성 방식에 따라 대응이 필요합니다. use_frameworks!를 사용하는 CocoaPods 환경에서는 동적 프레임워크 임포트가 정상적으로 되었는지 확인하고, 필요시 소스 파일을 직접 프로젝트에 포함하여 렌더링 문제를 해결할 수 있습니다.