Можно ли обнаружить ссылки в NSString с пробелами в них с помощью NSDataDetector?

Во-первых, я не могу контролировать текст, который я получаю. Просто хотел поместить это там, чтобы вы знали, что я не могу изменить ссылки.

Текст, который я пытаюсь найти в использовании 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
   }
}

Является ли это ошибкой с обнаружением ссылок Apple здесь, где он не может обнаружить ссылки с пробелами, или я делаю что-то неправильно?

Есть ли у кого-нибудь более надежный способ обнаружения ссылок независимо от того, имеют ли они пробелы или специальные символы или что-то в них?

Ответ 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)];
    }
}

Ответ 3

Я нашел очень хакерский способ решить мою проблему. Если кто-то придумает лучшее решение, которое можно применить ко всем URL-адресам, сделайте это.

Потому что я только забочусь о URL-адресах, заканчивающихся на .jpg, у которых есть эта проблема, я смог найти узкий способ отслеживания этого.

По существу, я разбиваю строку на компоненты, основанные на них, начиная с "http:// в массив. Затем я прохожу через этот массив, который еще раз разыскивает поиск .jpg">. Счетчик внутреннего массива будет > 1, когда будет найдена строка .jpg">. Затем я сохраняю как строку, которую я нахожу, так и строку, которую я исправляю с заменой %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

Попробуйте этот шаблон регулярного выражения: @"<img[^>]+src=(\"|')([^\"']+)(\"|')[^>]*>" с игнорированием case... Match index = 2 для исходного URL.

regex demo в javascript: (попробуйте для любой помощи)

Демо

Ответ 6

Попробуйте этот фрагмент (я получил регулярное выражение от вашего первого комментатора 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 на текстовых узлах, чтобы найти вещи, не помеченные, не загрязняя строку тегами.

Ответ 8

URL-адреса действительно не должны содержать пробелов. Я удаляю все пробелы из строки, прежде чем делать что-то связанное с ним 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
}