【问题标题】:Is it possible to detect links within an NSString that have spaces in them with NSDataDetector?是否可以使用 NSDataDetector 检测 NSString 中包含空格的链接?
【发布时间】:2015-08-24 19:56:00
【问题描述】:

首先,我无法控制收到的文本。只是想把它放在那里,这样你就知道我不能更改链接。

我尝试使用NSDataDetector 查找链接的文本包含以下内容:

<h1>My main item</h1>
<img src="http://www.blah.com/My First Image Here.jpg">
<h2>Some extra data</h2>

我用的检测码是这个,但是找不到这个链接:

NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:myHTML options:0 range:NSMakeRange(0, [myHTML length])];

for (NSTextCheckingResult *match in matches) 
{
   if ([match resultType] == NSTextCheckingTypeLink)
   {
      NSURL *url = [match URL];
      // does some stuff
   }
}

这是苹果链接检测的一个错误,它无法检测到带有空格的链接,还是我做错了什么?

有没有人有更可靠的方法来检测链接,无论链接是否包含空格或特殊字符或其他任何内容?

【问题讨论】:

  • 正则表达式呢;例如regularExpressionWithPattern:@"src=(\"|')(.*)(\"|')&gt;" 然后[match rangeAtIndex:2]

标签: ios objective-c regex nsdatadetector


【解决方案1】:

我刚刚收到 Apple 的回复,原因是我对此提出了一个错误:

我们相信这个问题已在最新的 iOS 9 测试版中得到解决。 这是 iOS 9 的预发布更新。

完整安装请参考发行说明 说明。

请使用此版本进行测试。如果您还有问题,请 提供任何可以帮助我们的相关日志或信息 调查。

iOS 9 https://developer.apple.com/ios/download/

我会测试并让大家知道这是否在 iOS 9 中得到修复。

【讨论】:

    【解决方案2】:

    您可以使用空格将字符串拆分为多个片段,这样您就有了一个没有空格的字符串数组。然后,您可以将这些字符串中的每一个输入数据检测器。

    // assume str = <img src="http://www.blah.com/My First Image Here.jpg">
    NSArray *components = [str componentsSeparatedByString:@" "];
    for (NSString *strWithNoSpace in components) {
        // feed strings into data detector
    }
    

    另一种选择是专门查找该 HTML 标记。不过,这是一个不太通用的解决方案。

    // assume that those 3 HTML strings are in a string array called strArray
    for (NSString *htmlLine in strArray) {
        if ([[htmlLine substringWithRange:NSMakeRange(0, 8)] isEqualToString:@"<img src"]) {
            // Get the url from the img src tag
            NSString *urlString = [htmlLine substringWithRange:NSMakeRange(10, htmlLine.length - 12)];
        }
    }
    

    【讨论】:

    • 这需要是动态的,而不仅仅是硬编码到这个 URL。在这个字符串中可能有多个不同长度的 URL,并且所有 URL 中都可能有空格。
    【解决方案3】:

    我找到了一种非常老套的方法来解决我的问题。如果有人提出了可以应用于所有 URL 的更好的解决方案,请这样做。

    因为我只关心以 .jpg 结尾的有此问题的 URL,所以我能够想出一个狭窄的方法来追踪此问题。

    本质上,我将字符串分解为基于它们的组件,以"http:// 开头为一个数组。然后我循环遍历那个数组做另一个突破来寻找.jpg"&gt;。只有在找到.jpg"&gt; 字符串时,内部数组的计数才会是&gt; 1。然后我保留我找到的字符串和我用%20 替换修复的字符串,并使用它们对原始字符串进行最终的字符串替换。

    它并不完美,可能效率低下,但它可以完成我需要的工作。

    - (NSString *)replaceSpacesInJpegURLs:(NSString *)htmlString
    {
        NSString *newString = htmlString;
    
        NSArray *array = [htmlString componentsSeparatedByString:@"\"http://"];
        for (NSString *str in array)
        {
            NSArray *array2 = [str componentsSeparatedByString:@".jpg\""];
    
            if ([array2 count] > 1)
            {
                NSString *stringToFix = [array2 objectAtIndex:0];
                NSString *fixedString = [stringToFix stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
    
                newString = [newString stringByReplacingOccurrencesOfString:stringToFix withString:fixedString];
            }
        }
    
        return newString;
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用NSRegularExpression 来修复所有 URL,方法是使用一个简单的正则表达式来检测链接,然后对空格进行编码(如果您需要更复杂的编码,您可以查看CFURLCreateStringByAddingPercentEscapes,那里有很多示例)。如果您之前没有使用过NSRegularExpression,唯一可能需要您一些时间的是如何迭代结果并进行替换,下面的代码应该可以解决问题:

      NSError *error = NULL;
      NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"src=\".*\"" options:NSRegularExpressionCaseInsensitive error:&error];
      if (!error)
      {
          NSInteger offset = 0;
          NSArray *matches = [regex matchesInString:myHTML options:0 range:NSMakeRange(0, [myHTML length])];
          for (NSTextCheckingResult *result in matches)
          {
              NSRange resultRange = [result range];
              resultRange.location += offset;
      
              NSString *match = [regex replacementStringForResult:result inString:myHTML offset:offset template:@"$0"];
              NSString *replacement = [match stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
      
              myHTML = [myHTML  stringByReplacingCharactersInRange:resultRange withString:replacement];
              offset += ([replacement length] - resultRange.length);
          }
      }
      

      【讨论】:

        【解决方案5】:

        试试这个正则表达式模式: @"&lt;img[^&gt;]+src=(\"|')([^\"']+)(\"|')[^&gt;]*&gt;" 忽略大小写...匹配 index=2 的源网址。

        javascript 中的正则表达式演示:(尝试任何帮助)

        Demo

        【讨论】:

          【解决方案6】:

          试试这个 sn-p(我从你的第一个评论员 user3584460 那里得到了正则表达式):

          NSError *error = NULL;
          NSString *myHTML = @"<http><h1>My main item</h1><img src=\"http://www.blah.com/My First Image Here.jpg\"><h2>Some extra data</h2><img src=\"http://www.bloh.com/My Second Image Here.jpg\"><h3>Some extra data</h3><img src=\"http://www.bluh.com/My Third-Image Here.jpg\"></http>";
          NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"src=[\"'](.+?)[\"'].*?>" options:NSRegularExpressionCaseInsensitive error:&error];
          
          NSArray *arrayOfAllMatches = [regex matchesInString:myHTML options:0 range:NSMakeRange(0, [myHTML length])];
          
          NSTextCheckingResult *match = [regex firstMatchInString:myHTML options:0 range:NSMakeRange(0, myHTML.length)];
          
          
          
          for (NSTextCheckingResult *match in arrayOfAllMatches) {
              NSRange  range = [match rangeAtIndex:1];
          
              NSString* substringForMatch = [myHTML substringWithRange:range];
              NSLog(@"Extracted URL : %@",substringForMatch);
          
          }
          

          在我的日志中,我有:

          Extracted URL  : http://www.blah.com/My First Image Here.jpg
          Extracted URL  : http://www.bloh.com/My Second Image Here.jpg
          Extracted URL  : http://www.bluh.com/My Third-Image Here.jpg
          

          【讨论】:

            【解决方案7】:

            您不应将 NSDataDetector 与 HTML 一起使用。它旨在解析普通文本(由用户输入),而不是计算机生成的数据(事实上,它有许多启发式方法来实际确保它不会检测到可能与用户无关的计算机生成的东西)。

            如果您的字符串是 HTML,那么您应该使用 HTML 解析库。有许多开源工具包可以帮助您做到这一点。然后只需获取锚点的 href 属性,或在文本节点上运行 NSDataDetector 以查找未标记的内容,而不会用标签污染字符串。

            【讨论】:

            • 我很欣赏这个答案,但你能告诉我一些文档中说NSDataDetector 不应该在 HTML 上使用吗?就这样我知道这是真的。
            • 这个答案真的很好……但我想你不知道你对上一条评论的印象是什么。
            • 由于您在 Apple 工作,我恳请您更新文档以反映您的答案中的详细信息。我不知道 NSDataDetector 是“用于解析普通文本”(无论“正常”是什么)并且“有许多启发式方法来实际确保它不会检测到计算机生成的东西”,Apple 没有描述这真正意味着什么或者……什么是“计算机生成的东西”?请将此推送到您的文档中。当适当的文档可以救我时,我已经浪费了几个小时。
            • @Zero 我知道他所说的“普通文本”是什么意思,但是当有人谈论非常技术性的逻辑软件开发时,你不能用模糊的陈述来解释它。我需要 Apple 明确告诉我在使用检测器时允许什么和不允许什么。这就是我的答案问题。我可能会让一家小公司滑落,但苹果是世界上最有价值的公司……这里没有任何借口。
            • 我已经提交了一个错误来改进文档。
            【解决方案8】:

            网址确实不应该包含空格。在执行与 URL 相关的任何操作之前,我会从字符串中删除所有空格,如下所示

            // Custom function which cleans up strings ready to be used for URLs
            func cleanStringForURL(string: NSString) -> NSString {
                var temp = string
                var clean = string.stringByReplacingOccurrencesOfString(" ", withString: "")
                return clean
            }
            

            【讨论】:

            • 不行...字符串是一个巨大的 HTML 页面。我无法删除整个页面中的所有空格。我只需要为 URL 修复此问题。而且,许多网站的 URL 中都带有空格,无论它们是否不应该。就我而言,我无法控制 HTML 的来源。
            猜你喜欢
            • 1970-01-01
            • 2010-12-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-11
            • 1970-01-01
            • 2011-06-09
            相关资源
            最近更新 更多