需顯示一段文本,其中多處不定長子串可點擊響應事件(如超鏈接、@用戶、#話題#)。
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| UIWebView + HTML | 實現簡單,原生支持超鏈接、CSS 樣式 | 性能差,內存佔用高,iOS 12+ 棄用,App Store 審核風險 | 快速原型、簡單靜態富文本 |
| UITextView + NSAttributedString | 原生控件,性能好,支持自定義屬性(如 link)、長按菜單 | 需手動解析文本生成屬性字符串,多鏈接佈局複雜 | 標準 App 富文本展示 |
| TTTAttributedLabel / ActiveLabel | 開源成熟,自動檢測 URL/提及/話題,支持自定義正則 | 引入第三方依賴,Swift 版需橋接 | 社交類、評論類複雜富文本 |
| Core Text 排版 | 完全控制佈局、字形、動畫,極致性能 | 開發難度極高,維護成本大 | 雜誌排版、特殊藝術字體 |
- (void)configureTextViewWithText:(NSString *)text {
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:text];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(@\\w+|#\\w+#|https?://\\S+)" options:0 error:nil];
[regex enumerateMatchesInString:text options:0 range:NSMakeRange(0, text.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range = result.range;
[attrStr addAttribute:NSLinkAttributeName value:[self actionURLForRange:range] range:range];
[attrStr addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:range];
[attrStr addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
}];
self.textView.attributedText = attrStr;
self.textView.delegate = self;
self.textView.editable = NO;
self.textView.dataDetectorTypes = UIDataDetectorTypeNone; // 禁用系統自動檢測
}
- (NSURL *)actionURLForRange:(NSRange)range {
NSString *substring = [self.textView.text substringWithRange:range];
// 自定義 scheme 路由,如 myapp://mention/username
return [NSURL URLWithString:[NSString stringWithFormat:@"myapp://action?text=%@", [substring stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]];
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction {
// 解析 URL scheme 分發業務邏輯
return NO; // 阻止默認打開
}
struct RichTextView: View {
let text: String
var body: some View {
Text(parseAttributedString(text))
.environment(\.openURL, OpenURLAction { url in
handleCustomURL(url)
return .handled
})
}
func parseAttributedString(_ string: String) -> AttributedString {
var attr = AttributedString(string)
// 使用正則或 Scanner 添加 .link 屬性
return attr
}
}
綜上,棄用 UIWebView,優先選擇 UITextView + 正則屬性字符串,或引入 ActiveLabel 等成熟庫,兼顧性能、維護性與合規性。