使用 webView Objective C 加载到另一个 VC 的可点击条款和政策

Posted

技术标签:

【中文标题】使用 webView Objective C 加载到另一个 VC 的可点击条款和政策【英文标题】:Clickable Terms and Policy that loads to up to another VC with webView ObjectiveC 【发布时间】:2018-04-18 17:05:58 【问题描述】:

我有这个UILabel I agree to the Terms and Policy。我希望分别使条款和政策可点击。我已设法将属性添加到条款和政策,使它们成为蓝色和下划线。但是如何使它们分别可点击。单击条款时,我希望推送到一个新的VC,它会加载 webView,策略也是如此。我熟悉使用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

【问题讨论】:

看看这个帖子***.com/questions/20541676/…。也许这就是你想要的 我做了,但不知道他们在哪里或如何加载网络视图。 关于如何加载网页视图,你可以查看RB1509的回答或者问他。我想他知道该怎么做。 IndexOfCharacter 不断返回零值,非常感谢任何帮助。 @HansheungCheah 您尝试像许多应用程序一样弹出一个视图控制器(包含 webview)以获取条款和政策。对不对? 【参考方案1】:

您可以使用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;

@结束

【讨论】:

如何创建UITextView extension .hUITextView extension .m 如何导入#import "UITextView+Link.h" 您能否详细说明如何创建所有这些?它是 UITextView 的子类吗? @HanzCheah 我不明白您需要什么澄清,这是一个类别,code.tutsplus.com/tutorials/… 以及如何使用它,如果您有任何疑问,请告诉我【参考方案2】:

要实现这一点,您应该使用 UITextView 并使其可选择。向 textview 添加属性将使链接可点击。所以你不需要添加手势。

不要忘记设置 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

【讨论】:

这不是 OP 所要求的,他想在用户单击链接时启动视图控制器,而不是直接启动链接本身。【参考方案3】:

您可以将UITapGestureRecognizer 实例添加到您的 UILabel。

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://***.com/"]];
    else if(NSLocationInRange(indexOfCharacter, policyLinkRange))
       // Open an URL, or handle the tap on the text POLICY
       [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://***.com/"]];
    

我同意条款和政策 = 条款 NSMakeRange(15, 5) 和政策 NSMakeRange(25, 6) *请相应地更改范围。

【讨论】:

但我有 2 个链接。条款和政策。如果您输入UITapGestureRecognizer,它将适用于整个 UILabel @HansheungCheah 我已经更新了答案!现在检查并告诉我:)

以上是关于使用 webView Objective C 加载到另一个 VC 的可点击条款和政策的主要内容,如果未能解决你的问题,请参考以下文章

Objective C iOS 预加载视图

webView中的按钮执行Objective C方法

在应用程序 IOS Objective C 启动时添加新的视图控制器

iOS Swift Webview 在加载时显示图像

使用 Ajax 从 UIWebView 调用 Objective C 函数

Objective C-使用其中的对象加载 UIPickerview