zoukankan      html  css  js  c++  java
  • iOS 自动识别URL(链接)功能的实现

    • 功能需求

        在做“沃迪康”聊天功能时,甲方要求发送的网址要自动识别、并点击能自动跳转

    • 功能难点  

        在实现过程中,所有的文字都是动态获取的,设置富文本属性时,不能按照常规的方法

    • 解决方式
      • 如果只是文字,没有表情的话,可以用UILabel和UITextView来实现
      • 如果有表情的话,目前了解到比较容易的是用UITextView来实现
    • 代码实现
      • UILabelUILabel实现方式:
        本人用的第三方框架:TYAttributedLabel, 可自行去git上下载;
        
        如下,我将以自己的代码实现,讲一下自己是如何使用的,以供参考,注意,只是讲解自己的思路,无法复制使用:
        
        1.导入TYAttributedLabel头文件到自己需要的地方:(本人是在.h 实现下面的代码,读者也可在.m中声明)
            @protected
        
            TYAttributedLabel *_chatText;
        
        2.在.m文件中实例刚声明的_chatText,如下:
            _chatText = [[TYAttributedLabel alloc] init];  //创建实例
            _chatText.backgroundColor = [UIColor clearColor];  //设置背景色
            _chatText.delegate = self;  //设置代理
            
            _chatText.textAlignment = NSTextAlignmentLeft;  //设置显示的格式--居左
            _chatText.numberOfLines = 0;  //设置行数不限
        
        3.给_chatText赋值--这个是个重点,请注意:
            NSString *URLStr = @"http://baidu.com这是一个url,这个url可以点击跳转到http://baidu.com的页面上";   //给URLStr赋值
            NSArray *textArray = [YZTools subStrUseURL: URLStr];  //此处请注意:YZTools是我自己平时积累方法的一个工具类, subStrUseURL这个方法是把URLStr根据URL网址来分隔成一个数组 , 下面会给出里面的代码,请耐心,分隔出来的数组如下@[@"http://baidu.com",@"这是一个url,这个url可以点击跳转到",@"http://baidu.com"]
        for (NSString *text in textArray) { // 根据分隔的数组,判断是否是url再调用TYAttributedLabel的方法来添加URL的颜色属性和字体大小 if ([text hasPrefix:@"http"]) { [_chatText appendLinkWithText:text linkFont:[_msg textFont] linkColor:[UIColor blueColor] linkData:text]; }else { [_chatText appendText:text]; } } 4.在.m中继承TYAttributedLabel的代理 <TYAttributedLabelDelegate>,并实现代理
        #pragma mark - TYAttributedLabelDelegate - (void)attributedLabel:(TYAttributedLabel *)attributedLabel textStorageClicked:(id<TYTextStorageProtocol>)TextRun atPoint:(CGPoint)point { NSLog(@"textStorageClickedAtPoint"); if ([TextRun isKindOfClass:[TYLinkTextStorage class]]) { NSString *linkStr = ((TYLinkTextStorage*)TextRun).linkData; if ([linkStr hasPrefix:@"http:"]) { [ [ UIApplication sharedApplication] openURL:[ NSURL URLWithString:linkStr]]; }else { UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"点击提示" message:linkStr delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; [alertView show]; } } } - (void)attributedLabel:(TYAttributedLabel *)attributedLabel textStorageLongPressed:(id<TYTextStorageProtocol>)textStorage onState:(UIGestureRecognizerState)state atPoint:(CGPoint)point { NSLog(@"textStorageLongPressed"); }
      • 上述代码中,有个 subStrUseURL 的方法,代码如下(可直接复制是使用):***本人用的是类方法,读者也可以使用对象方法***
      •  
        #pragma mark - 根据URL剪切字符串成数组
        /** 根据URL剪切数组 */
        + (NSMutableArray *)subStrUseURL:(NSString *)string
        {
            
            NSError *error;
            
            //可以识别url的正则表达式
            
            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 *arr=[[NSMutableArray alloc]init];
            NSMutableArray *rangeArr=[[NSMutableArray alloc]init];
            for (NSTextCheckingResult *match in arrayOfAllMatches){
                NSString* substringForMatch;
                substringForMatch = [string substringWithRange:match.range];
                [arr addObject:substringForMatch];
                
                [rangeArr addObject:[NSValue valueWithRange:match.range]];
            }
            NSString *subStr=string;
        //    for (NSString *str in arr) {
        //        [rangeArr addObject:[self rangesOfString:str inString:subStr]];
        //    }
            
            UIFont *font = [UIFont systemFontOfSize:20];
            NSMutableAttributedString *attributedText;
            
            attributedText=[[NSMutableAttributedString alloc]initWithString:subStr attributes:@{NSFontAttributeName :font}];
            
            NSMutableArray *urlArray = [NSMutableArray array];
            
            //把字符串根据URL剪切成数组
            NSInteger index = 0;
            NSMutableArray *strArray = [[NSMutableArray alloc] init];
            for (NSInteger i = 0; i < rangeArr.count; i++) {
                NSValue *value = rangeArr[i];
                NSInteger valueLoction = value.rangeValue.location;
                NSInteger valueLength = value.rangeValue.length;
                if (i == 0 && valueLoction != 0) {
                    [strArray addObject:[string substringWithRange:NSMakeRange(0, valueLoction)]];
                    index = valueLoction;
                }
                if (index != valueLoction) {
                    [strArray addObject:[string substringWithRange:NSMakeRange(index, valueLoction - index)]];
                    index = index + valueLength;
                }
                [strArray addObject:[string substringWithRange:NSMakeRange(valueLoction, valueLength)]];
                index = index + valueLength;
                if (i == rangeArr.count - 1 && (valueLoction + valueLength != string.length)) {
                    [strArray addObject:[string substringWithRange:NSMakeRange(valueLength + valueLoction, string.length - valueLength - valueLoction)]];
                }
            }
            if (rangeArr.count == 0) {
                [strArray addObject:string];
            }
            NSLog(@"----strArray = %@", strArray);
            
            //获取string的URL全部链接
            for(NSValue *value in rangeArr) {
                NSInteger index=[rangeArr indexOfObject:value];
                [urlArray addObject:[NSURL URLWithString:[arr objectAtIndex:index]]];
            }
            
            return strArray;
        }
        
        //获取查找字符串在母串中的NSRange
        + (NSValue *)rangesOfString:(NSString *)searchString inString:(NSString *)str {
            NSRange searchRange = NSMakeRange(0, [str length]);
            NSRange range;
            if ((range = [str rangeOfString:searchString options:0 range:searchRange]).location != NSNotFound) {
                searchRange = NSMakeRange(NSMaxRange(range), [str length] - NSMaxRange(range));
            }
            return [NSValue valueWithRange:range];
        }
      •  UITextView的实现方法                   
      • 1. 声明一个_chatText, 在.h
            @protected
            UITextView *_chatText;
        
        2.在.m中实例化,如下:
            //设置链接地址的颜色属性
            NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor     blueColor],
                                             NSUnderlineColorAttributeName: [UIColor blueColor],
                                             NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};
        
            //创建实例化_chatText    
            UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
            textView.backgroundColor = [UIColor clearColor];
            textView.delegate = self;
            textView.editable = NO;   //设置不能编辑
            textView.contentInset = UIEdgeInsetsZero;
            textView.textContainerInset = UIEdgeInsetsZero;
            textView.scrollIndicatorInsets = UIEdgeInsetsZero;
            textView.textContainer.lineFragmentPadding = 0;
            textView.textContainerInset = UIEdgeInsetsMake(5, 0, 0, 0);
            _chatText = textView;
            _chatText.linkTextAttributes= linkAttributes;   //给chatText链接属性赋值
        
        3.给chatText赋值,此处没发动态显示获取的数据,就用一个固定的值来代替:
            本人此处,后台已经将字符串切割出来返回给我们,所以,如果URL(链接)后面带有空格的话,会将空格一起返回。但是因为UITextView本身功能的局限性,无法识别链接待空格的网址,点击跳转时会跳转不过去,在代理方法中,url会返回null。因此做了如下的处理:
            
            NSString *text = @"http://baidu.com ";   //注意com后面有一个空格
            if ([self.text hasPrefix:@"http"]) {
                 //判断如果是http
                NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self.text attributes:@{NSFontAttributeName : [msg textFont], NSForegroundColorAttributeName : [UIColor blueColor]}];
                NSString *str = text;
                if ([self.text hasSuffix:@" "]) {
                    //尾部有空格,那么除掉尾部的空格,这个是指设置属性的时候,去掉空格,并不是在整体的数据源出掉
                    str = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
                }
                [attributedString addAttribute:NSLinkAttributeName
                                         value:str
                                         range:[[attributedString string] rangeOfString:str]];
                //设置下划线
                [attributedString addAttribute:NSUnderlineStyleAttributeName
                                         value:[NSNumber numberWithInteger:NSUnderlineStyleSingle]
                                         range:[[attributedString string] rangeOfString:str]];
                _chatText.attributedText =  attributedString;
        
            }else {
                NSAttributedString *str = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName : [msg textFont], NSForegroundColorAttributeName : [msg textColor]}];
                _chatText.attributedText =  attributedString;
            }
        
         4.设置代理,并实现方法:
        - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
        
            NSLog(@"url :%@",URL);
            if ([[URL scheme] isEqualToString:@"http"]) {
                [ [ UIApplication sharedApplication] openURL:URL];
                return NO;
            }
            return YES;
        }

    (UIText设置的东西略多,本人只能记录当时遇到的问题和解决方法了)

  • 相关阅读:
    协程
    多进程
    多线程
    模块进阶
    内建函数
    内建属性
    属性property
    私有化
    深拷贝、浅拷贝
    ==、is
  • 原文地址:https://www.cnblogs.com/lyz0925/p/8627624.html
Copyright © 2011-2022 走看看