Detection and response of url in iOS UITextView

Style

1. Custom url Style

+ (NSDictionary *)getURLAttributeDict{

    NSMutableDictionary *attributes = (NSMutableDictionary *)[StringTools getContentAttributeDict];
    [attributes setObject:[UIColor blueColor] forKey:NSForegroundColorAttributeName];
    [attributes setObject:@1 forKey:NSUnderlineStyleAttributeName];
    [attributes setObject:@7 forKey:NSBaselineOffsetAttributeName];
    [attributes setObject:@(YES) forKey:@"TAG"];

    return attributes;
}

2. Get range of url

//Web address matching,
+ (NSArray *)rangesOfUrlInString:(NSString *)string
{
    NSError *error;
    NSString *regulaStr = @"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)";
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regulaStr options:NSRegularExpressionCaseInsensitive error:&error];
    NSArray *arrayOfAllMatches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];

    NSMutableArray *arrayM = [NSMutableArray array];
    for (NSTextCheckingResult *match in arrayOfAllMatches)
    {
        NSString* substringForMatch = [string substringWithRange:match.range];
        //Nslog (@ "URL link in text:% @ --- range: (% LD,% LD)", substringformatch, match.range.location, match.range.length);
        [arrayM addObject:[NSValue valueWithRange:match.range]];
    }
    return arrayM;
}

3. Set textView all text styles

// If the content contains a url address, it needs to be processed as a link
+ (NSMutableAttributedString *)getContentURLAttributeStr:(NSString * )string
{
    NSRange wholeRange = [string rangeOfString:string];
    NSArray *urlRanges = [self rangesOfUrlInString:string];  //range of website

    NSMutableAttributedString *resultStr = [[NSMutableAttributedString alloc]initWithString:string];

    NSMutableDictionary *contentAttriDict = (NSMutableDictionary *)[StringTools getContentAttributeDict];

    NSMutableDictionary *urlAttriDict = (NSMutableDictionary *)[StringTools getURLAttributeDict];

    [resultStr addAttributes:contentAttriDict range:wholeRange];

    for (NSValue *rangeValue in urlRanges) {

        NSRange range = [rangeValue rangeValue];
        [urlAttriDict setObject:[string substringWithRange:range] forKey:@"URL"];
        [resultStr addAttributes:urlAttriDict range:range];
    }
    return resultStr;
}

Method 1 use gestures

Disadvantages: in IOS 11 and above, you can't cancel after selecting the text.

#pragma mark -- click the text details URL to jump
- (void)handleTap:(UITapGestureRecognizer *)tapGest
{
    UITextView *textView = (UITextView *)tapGest.view;

    NSLayoutManager *layoutManager = textView.layoutManager;

    CGPoint location = [tapGest locationInView:textView];
    location.x -= textView.textContainerInset.left;

tmpCell.contentTextView.attributedText = [StringTools getContentURLAttributeStr:Content];

UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
[tmpCell.contentTextView addGestureRecognizer:tapGR];
    location.y -= textView.textContainerInset.top;

    NSUInteger characterIndex = [layoutManager characterIndexForPoint:location inTextContainer:textView.textContainer fractionOfDistanceBetweenInsertionPoints:NULL];
    if (characterIndex < textView.textStorage.length)
    {
        NSRange range;
        NSDictionary *attributes = [textView.textStorage attributesAtIndex:characterIndex effectiveRange:&range];
        if ([attributes objectForKey:@"TAG"]) //Click on the link
        {
            NSString *urlStr = [attributes objectForKey:@"URL"];
            NSLog(@"url - %@",urlStr);

            WebViewController *webVC = [[WebViewController alloc]init];
            webVC.url = [NSURL URLWithString:urlStr];
            [self.superVC.navigationController pushViewController:webVC animated:YES];
        }
    }

Method 2: using textView's proxy method

Disadvantages: it takes a long press to jump. The tap did not respond.

 _txView.delegate = self;
-(BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction{

    NSLog(@"url:%@",URL.absoluteString);

    //Methods to be implemented
    if (_blockTextViewDidTapURL) {
        _blockTextViewDidTapURL(URL.absoluteString);
    }

    return NO; //If yes is returned, safari is turned on by default.
}
  NSMutableAttributedString *resultStr = [[NSMutableAttributedString alloc]initWithString:self.nrModel.Content];

        [resultStr addAttributes:[StringTools getContentAttributeDict] range:NSMakeRange(0, self.nrModel.Content.length)];

        NSMutableDictionary *linkAttributes = (NSMutableDictionary *)[StringTools getURLAttributeDict];
        NSArray *urlRanges = [StringTools rangesOfUrlInString:self.nrModel.Content];
        for (NSValue *rangeValue in urlRanges) {

            NSRange range = [rangeValue rangeValue];
            NSString *urlString = [self.nrModel.Content substringWithRange:range];
            [resultStr addAttribute:NSLinkAttributeName value:urlString range:range];
        }

        tmpCell.contentTextView.txView.linkTextAttributes = linkAttributes;
        tmpCell.contentTextView.txView.attributedText = resultStr;
        tmpCell.contentTextView.txView.editable = NO;
        [tmpCell.contentTextView setBlockTextViewDidTapURL:^(NSString *string) {
            [weakSelf jumpToURL:string];
        }];

Keywords: ftp iOS

Added by evolve4 on Sat, 02 May 2020 14:26:06 +0300