使用 webView Objective C 加载到另一个 VC 的可点击条款和政策
Clickable Terms and Policy that loads to up to another VC with webView ObjectiveC
我有这个UILabel
I agree to the Terms and Policy
。我希望分别使条款和政策可点击。我已经设法为条款和政策添加属性,使它们成为蓝色和下划线。但是如何使它们分别可点击。单击 Terms 时,我希望推送到加载 webView 的新 VC
,Policy 也是如此。我熟悉使用 segue
推送到另一个 VC 但如何在单击条款或政策时初始化流程>
已编辑
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize label;
@synthesize layoutManager;
@synthesize textContainer;
@synthesize textStorage;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullString = @"I agree to the Terms and Policy";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:fullString];
//For underline
[attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:[fullString rangeOfString:@"Terms"]];
[attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:[fullString rangeOfString:@"Policy"]];
//For Blue Colour
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0] range:[fullString rangeOfString:@"Terms"]];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0] range:[fullString rangeOfString:@"Policy"]];
// Setting attributed string to textview
label.attributedText = attributedString;
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
//=====What does this part do, Do I really need it?======
// Configure layoutManager and textStorage
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
// Configure textContainer
textContainer.lineFragmentPadding = 0.0;
textContainer.lineBreakMode = label.lineBreakMode;
textContainer.maximumNumberOfLines = label.numberOfLines;
//======================================================
label.userInteractionEnabled = YES;
[label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel:)]];
}
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:self.textContainerfractionOfDistanceBetweenInsertionPoints:nil];
NSRange termsLinkRange = NSMakeRange(15, 5); // it's better to save the range somewhere when it was originally used for marking link in attributed string
NSRange policyLinkRange = NSMakeRange(25, 6);
//=========THE FOLLOWING PART IS NOT WORKING =====================
if (NSLocationInRange(indexOfCharacter, termsLinkRange)) {
NSLog(@"This is terms");
[self performSegueWithIdentifier:@"Terms" sender:self];
}else if(NSLocationInRange(indexOfCharacter, policyLinkRange)){
NSLog(@"This is policy");
[self performSegueWithIdentifier:@"Policy" sender:self];
}
}
//======================================================================
@end
我不断得到 indexOfCharacter
等于 0
为此,您应该使用 UITextView 并使其可选择。向文本视图添加属性将使链接可点击。所以你不需要添加手势。
不要忘记设置 textview 的这些属性:
textview.isSelectable = true
textview.isEditable = false
textview.isUserInteractionEnabled = true
同时实现 UITextViewDelegate 方法:
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
//open the link here
if URL.absoluteString == "YOUR_TERMS_URL" {
//open terms
} else if URL.absoluteString == "YOUR_PRIVACY_URL" {
//open privacy
}
return false
}
您可以向您的 UILabel 添加一个 UITapGestureRecognizer
实例。
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel)];
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.delegate =self;
[myLabel addGestureRecognizer:tapGestureRecognizer];
myLabel.userInteractionEnabled = YES;
然后正如@RB1509所说
- (void)handleTapOnLabel:(UITapGestureRecognizer *)gestureRecognizer {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
secondVC *VC = [storyboard instantiateViewControllerWithIdentifier:@"secondVC"];
VC.GetString=@"https://www.vbgov.com/Pages/default.aspx";
[self presentViewController:VC animated:YES completion:nil];
}
更新:
所以现在您需要检测对文本的触摸
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:self.textContainer
fractionOfDistanceBetweenInsertionPoints:nil];
NSRange termsLinkRange = NSMakeRange(15, 5); // it's better to save the range somewhere when it was originally used for marking link in attributed string
NSRange policyLinkRange = NSMakeRange(25, 6);
if (NSLocationInRange(indexOfCharacter, termsLinkRange)) {
// Open an URL, or handle the tap on the text TERMS
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://whosebug.com/"]];
}else if(NSLocationInRange(indexOfCharacter, policyLinkRange)){
// Open an URL, or handle the tap on the text POLICY
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://whosebug.com/"]];
}
}
我同意条款和政策 = 条款 NSMakeRange(15, 5)
和政策 NSMakeRange(25, 6)
*请相应地更改范围。
您可以使用 UITextView
来实现这一点,我在以前的项目中使用这种方式实现了这一点,使用此扩展可以更轻松地创建这些链接
代码
UITextView 扩展.h
#import <UIKit/UIKit.h>
@interface UITextView (Link)
- (void)setTextAsLink:(NSString*)text url:(NSURL*)linkurl attributtes:(NSDictionary*)attributes;
@end
UITextView 扩展.m
#import "UITextView+Link.h"
@implementation UITextView (Link)
- (void)setTextAsLink:(NSString*)text url:(NSURL*)linkurl attributtes:(NSDictionary*)attributes {
NSMutableAttributedString * theString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
NSRange theRange = [theString.mutableString rangeOfString:text];
if(theRange.location != NSNotFound) {
[theString addAttribute:NSLinkAttributeName value:linkurl range:theRange];
self.attributedText = theString;
}
self.linkTextAttributes = attributes;
}
@end
使用它
#import "ViewController.h"
#import "UITextView+Link.h"
@interface ViewController () <UITextViewDelegate>
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.textView.editable = false;
self.textView.contentInset = UIEdgeInsetsZero;
self.textView.textContainerInset = UIEdgeInsetsZero;
self.textView.attributedText = [[NSAttributedString alloc] initWithString:@"I agree to the Terms and Policy" attributes:nil];
self.textView.delegate = self;
NSDictionary * linkAttributes = @{NSForegroundColorAttributeName:[UIColor redColor]};
[self.textView setTextAsLink:@"Terms" url:[NSURL URLWithString:@"terms://"] attributtes:linkAttributes];
[self.textView setTextAsLink:@"Policy" url:[NSURL URLWithString:@"policy://"] attributtes:linkAttributes];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark UITextViewDelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
return false;
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction {
if([URL.absoluteString isEqualToString:@"terms://"]) {
NSLog(@"TERMS SHOULD BE OPENED");
}
if([URL.absoluteString isEqualToString:@"policy://"]) {
NSLog(@"POLICY SHOULD BE OPENED");
}
return false;
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
if([URL.absoluteString isEqualToString:@"terms://"]) {
NSLog(@"TERMS SHOULD BE OPENED");
}
if([URL.absoluteString isEqualToString:@"policy://"]) {
NSLog(@"POLICY SHOULD BE OPENED");
}
return false;
}
@end
我有这个UILabel
I agree to the Terms and Policy
。我希望分别使条款和政策可点击。我已经设法为条款和政策添加属性,使它们成为蓝色和下划线。但是如何使它们分别可点击。单击 Terms 时,我希望推送到加载 webView 的新 VC
,Policy 也是如此。我熟悉使用 segue
推送到另一个 VC 但如何在单击条款或政策时初始化流程>
已编辑
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize label;
@synthesize layoutManager;
@synthesize textContainer;
@synthesize textStorage;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullString = @"I agree to the Terms and Policy";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:fullString];
//For underline
[attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:[fullString rangeOfString:@"Terms"]];
[attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:[fullString rangeOfString:@"Policy"]];
//For Blue Colour
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0] range:[fullString rangeOfString:@"Terms"]];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0] range:[fullString rangeOfString:@"Policy"]];
// Setting attributed string to textview
label.attributedText = attributedString;
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
//=====What does this part do, Do I really need it?======
// Configure layoutManager and textStorage
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
// Configure textContainer
textContainer.lineFragmentPadding = 0.0;
textContainer.lineBreakMode = label.lineBreakMode;
textContainer.maximumNumberOfLines = label.numberOfLines;
//======================================================
label.userInteractionEnabled = YES;
[label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel:)]];
}
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:self.textContainerfractionOfDistanceBetweenInsertionPoints:nil];
NSRange termsLinkRange = NSMakeRange(15, 5); // it's better to save the range somewhere when it was originally used for marking link in attributed string
NSRange policyLinkRange = NSMakeRange(25, 6);
//=========THE FOLLOWING PART IS NOT WORKING =====================
if (NSLocationInRange(indexOfCharacter, termsLinkRange)) {
NSLog(@"This is terms");
[self performSegueWithIdentifier:@"Terms" sender:self];
}else if(NSLocationInRange(indexOfCharacter, policyLinkRange)){
NSLog(@"This is policy");
[self performSegueWithIdentifier:@"Policy" sender:self];
}
}
//======================================================================
@end
我不断得到 indexOfCharacter
等于 0
为此,您应该使用 UITextView 并使其可选择。向文本视图添加属性将使链接可点击。所以你不需要添加手势。
不要忘记设置 textview 的这些属性:
textview.isSelectable = true
textview.isEditable = false
textview.isUserInteractionEnabled = true
同时实现 UITextViewDelegate 方法:
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
//open the link here
if URL.absoluteString == "YOUR_TERMS_URL" {
//open terms
} else if URL.absoluteString == "YOUR_PRIVACY_URL" {
//open privacy
}
return false
}
您可以向您的 UILabel 添加一个 UITapGestureRecognizer
实例。
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel)];
tapGestureRecognizer.numberOfTapsRequired = 1;
tapGestureRecognizer.delegate =self;
[myLabel addGestureRecognizer:tapGestureRecognizer];
myLabel.userInteractionEnabled = YES;
然后正如@RB1509所说
- (void)handleTapOnLabel:(UITapGestureRecognizer *)gestureRecognizer {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
secondVC *VC = [storyboard instantiateViewControllerWithIdentifier:@"secondVC"];
VC.GetString=@"https://www.vbgov.com/Pages/default.aspx";
[self presentViewController:VC animated:YES completion:nil];
}
更新:
所以现在您需要检测对文本的触摸
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:self.textContainer
fractionOfDistanceBetweenInsertionPoints:nil];
NSRange termsLinkRange = NSMakeRange(15, 5); // it's better to save the range somewhere when it was originally used for marking link in attributed string
NSRange policyLinkRange = NSMakeRange(25, 6);
if (NSLocationInRange(indexOfCharacter, termsLinkRange)) {
// Open an URL, or handle the tap on the text TERMS
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://whosebug.com/"]];
}else if(NSLocationInRange(indexOfCharacter, policyLinkRange)){
// Open an URL, or handle the tap on the text POLICY
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://whosebug.com/"]];
}
}
我同意条款和政策 = 条款 NSMakeRange(15, 5)
和政策 NSMakeRange(25, 6)
*请相应地更改范围。
您可以使用 UITextView
来实现这一点,我在以前的项目中使用这种方式实现了这一点,使用此扩展可以更轻松地创建这些链接
代码
UITextView 扩展.h
#import <UIKit/UIKit.h>
@interface UITextView (Link)
- (void)setTextAsLink:(NSString*)text url:(NSURL*)linkurl attributtes:(NSDictionary*)attributes;
@end
UITextView 扩展.m
#import "UITextView+Link.h"
@implementation UITextView (Link)
- (void)setTextAsLink:(NSString*)text url:(NSURL*)linkurl attributtes:(NSDictionary*)attributes {
NSMutableAttributedString * theString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
NSRange theRange = [theString.mutableString rangeOfString:text];
if(theRange.location != NSNotFound) {
[theString addAttribute:NSLinkAttributeName value:linkurl range:theRange];
self.attributedText = theString;
}
self.linkTextAttributes = attributes;
}
@end
使用它
#import "ViewController.h"
#import "UITextView+Link.h"
@interface ViewController () <UITextViewDelegate>
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.textView.editable = false;
self.textView.contentInset = UIEdgeInsetsZero;
self.textView.textContainerInset = UIEdgeInsetsZero;
self.textView.attributedText = [[NSAttributedString alloc] initWithString:@"I agree to the Terms and Policy" attributes:nil];
self.textView.delegate = self;
NSDictionary * linkAttributes = @{NSForegroundColorAttributeName:[UIColor redColor]};
[self.textView setTextAsLink:@"Terms" url:[NSURL URLWithString:@"terms://"] attributtes:linkAttributes];
[self.textView setTextAsLink:@"Policy" url:[NSURL URLWithString:@"policy://"] attributtes:linkAttributes];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark UITextViewDelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
return false;
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction {
if([URL.absoluteString isEqualToString:@"terms://"]) {
NSLog(@"TERMS SHOULD BE OPENED");
}
if([URL.absoluteString isEqualToString:@"policy://"]) {
NSLog(@"POLICY SHOULD BE OPENED");
}
return false;
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
if([URL.absoluteString isEqualToString:@"terms://"]) {
NSLog(@"TERMS SHOULD BE OPENED");
}
if([URL.absoluteString isEqualToString:@"policy://"]) {
NSLog(@"POLICY SHOULD BE OPENED");
}
return false;
}
@end