如何在UITextView中为协议文本添加可点击链接并唤起SafariViewController?
实现UITextView内协议文本的点击跳转功能
嘿,这个需求我太熟了!要在UITextView里实现点击《用户协议》和《隐私政策》唤起SafariViewController打开对应链接,咱们用富文本就能轻松搞定,我给你一步步拆解:
核心思路
通过给指定文本段添加链接属性,再拦截TextView的链接点击事件,自定义打开SafariViewController,替代系统默认的外部浏览器跳转行为。
具体实现步骤(Swift版本)
- 导入必要框架:先导入
SafariServices,用来创建内嵌的Safari浏览器页面。 - 构建带链接的富文本:定位到协议文本的位置,给它们添加链接属性。
- 配置TextView属性:关闭编辑功能,开启可选状态,设置代理以拦截点击事件。
- 拦截链接点击事件:实现代理方法,自定义打开SafariViewController。
import UIKit import SafariServices class AgreementViewController: UIViewController, UITextViewDelegate { @IBOutlet weak var agreementTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() // 基础文本内容 let baseText = "使用本应用,即表示您同意我们的《用户协议》和《隐私政策》" let attributedText = NSMutableAttributedString(string: baseText) // 给《用户协议》添加链接属性 let agreementRange = (baseText as NSString).range(of: "《用户协议》") attributedText.addAttribute(.link, value: "https://yourdomain.com/agreement", range: agreementRange) // 给《隐私政策》添加链接属性 let privacyRange = (baseText as NSString).range(of: "《隐私政策》") attributedText.addAttribute(.link, value: "https://yourdomain.com/privacy", range: privacyRange) // 给协议文本加粗(可选,让可点击文本更醒目) let boldFont = UIFont.boldSystemFont(ofSize: agreementTextView.font?.pointSize ?? 16) attributedText.addAttribute(.font, value: boldFont, range: agreementRange) attributedText.addAttribute(.font, value: boldFont, range: privacyRange) // 配置TextView agreementTextView.attributedText = attributedText agreementTextView.isEditable = false agreementTextView.isSelectable = true agreementTextView.delegate = self // 自定义链接的颜色和下划线样式 agreementTextView.linkTextAttributes = [ .foregroundColor: UIColor.systemBlue, .underlineStyle: NSUnderlineStyle.single.rawValue ] } // 拦截链接点击,打开SafariViewController func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { let safariVC = SFSafariViewController(url: URL) present(safariVC, animated: true) return false // 返回false阻止系统默认打开外部浏览器的行为 } }
Objective-C版本参考
如果你的项目是用Objective-C开发的,也可以按这个逻辑实现:
#import "AgreementViewController.h" #import <SafariServices/SafariServices.h> @interface AgreementViewController () <UITextViewDelegate> @property (weak, nonatomic) IBOutlet UITextView *agreementTextView; @end @implementation AgreementViewController - (void)viewDidLoad { [super viewDidLoad]; NSString *baseText = @"使用本应用,即表示您同意我们的《用户协议》和《隐私政策》"; NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:baseText]; // 设置用户协议链接 NSRange agreementRange = [baseText rangeOfString:@"《用户协议》"]; [attributedText addAttribute:NSLinkAttributeName value:@"https://yourdomain.com/agreement" range:agreementRange]; // 设置隐私政策链接 NSRange privacyRange = [baseText rangeOfString:@"《隐私政策》"]; [attributedText addAttribute:NSLinkAttributeName value:@"https://yourdomain.com/privacy" range:privacyRange]; // 给协议文本加粗(可选) UIFont *boldFont = [UIFont boldSystemFontOfSize:self.agreementTextView.font.pointSize]; [attributedText addAttribute:NSFontAttributeName value:boldFont range:agreementRange]; [attributedText addAttribute:NSFontAttributeName value:boldFont range:privacyRange]; // 配置TextView self.agreementTextView.attributedText = attributedText; self.agreementTextView.editable = NO; self.agreementTextView.selectable = YES; self.agreementTextView.delegate = self; // 自定义链接样式 self.agreementTextView.linkTextAttributes = @{ NSForegroundColorAttributeName: [UIColor systemBlueColor], NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) }; } - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction { SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:URL]; [self presentViewController:safariVC animated:YES completion:nil]; return NO; } @end
关键注意事项
- 必须把
isEditable设为NO,避免用户编辑文本;isSelectable要设为YES,否则无法触发链接点击事件。 - 如果是通过Storyboard/XIB创建的TextView,记得把
delegate关联到对应的ViewController。 - 自定义样式时,除了加粗,还可以调整颜色、下划线等,让可点击文本更显眼。
内容的提问来源于stack exchange,提问作者Aleksandar
相关产品推荐
相关产品推荐

