3

我有一个字符串(例如:“这是一些带有特定http://goo.gl/45hz网址的文本”)。我需要找到字符串中的所有 URL(如果有),然后以某种方式转换字符串,以便地址可以点击(如果用户点击它,safari 将打开),我需要在标签中显示带有 URL 的整个字符串(如果可能) .

有谁知道如何做到这一点?

4

6 回答 6

2

您可以使用从该位置NSRange 查找第http://一个和和,丢弃之前的文本http://,最后您可以使用空格分隔剩余的字符串,获取剩余字符串的第一部分,其中将包含 URL。

NSString *givenStr = @"This is some text with specific http://goo.gl/45hz web address in it";
NSRange range = [givenStr rangeOfString:@"http://" options:NSCaseInsensitiveSearch];


if (range.location != NSNotFound) {

  NSString *urlString = [givenStr substringFromIndex:range.location]; 
   // urlString="http://goo.gl/45hz web address in it"

  NSArray *urlStrArray = [urlString componentsSeparatedByString:@" "];

  NSURL *finalURL=[NSURL URLWithString:[urlStrArray objectAtIndex:0]];
   // [urlStrArray objectAtIndex:0]="http://goog.gl/45hz"
}

如@calampunay 所说,为了使 URL 可点击,您应该使用UITextView而不是UILabel因为UILabel只显示纯文本。

于 2013-04-23T14:57:43.237 回答
1

您可以使用 aUITextView而不是UILabel. 设置editableNO然后修改该属性@property(nonatomic) UIDataDetectorTypes dataDetectorTypes以检测 URL。

于 2013-04-23T14:50:26.793 回答
1

为了找到一个字符串中的所有 URL

NSError *error = NULL;

NSString *string = @"This is some text with specific http://goo.gl/45hz web adress in it";
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];
NSArray *matches = [detector matchesInString:string
                                     options:0
                                       range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
    if ([match resultType] == NSTextCheckingTypeLink) {
        NSURL *url = [match URL];
        NSLog(@"url...%@", url);
    }
}
于 2013-04-23T14:50:52.003 回答
0

如果这是来自 UI 标签,请使用 TTTAttributedLabel - https://github.com/mattt/TTTAttributedLabel

非常适合我们。

于 2013-04-23T17:26:21.850 回答
0

我在 swift 3 中实现了相同的功能。下面是检测字符串中的 url 并使其可点击的完整代码:

//put these lines of code inside your function
//add Tap Gesture
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapLabel))
    myLabel?.addGestureRecognizer(tapGesture)

    let input = “tap on url http://www.google.com, to go to google search”
    myLabel?.attributedText = getAttributedString(input: input);


/*** functions to perform complete task ***/

//function to get attributed string with url
func getAttributedString(input : String) -> NSMutableAttributedString {

    let matches = getURLRange(input: input)
    let attributedString = NSMutableAttributedString(string:input)

    for match in matches {
        let url = (input as NSString).substring(with: match.range)
        print(url)

        let linkText = NSMutableAttributedString(string:url, attributes:[NSForegroundColorAttributeName : UIColor.blue] as [String : Any])
        attributedString.replaceCharacters(in: match.range, with: linkText)
    }

    return attributedString
}


//function to get urls range
func getURLRange(input : String) -> [NSTextCheckingResult] {

    let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
    let matches = detector.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))

    return matches
}


// function to check if URL is taped
func tapLabel(gesture: UITapGestureRecognizer) {

    let matches = getURLRange(input: (myLabel?.text)!)

    let tapLocation = gesture.location(in: myLabel)


    let indexOfCharacter = didTapAttributedTextInLabel(label: myLabel!, tapLocation: tapLocation)

    for match in matches {

        if NSLocationInRange(indexOfCharacter, match.range) {

            //open selected URL
            let mainText = myLabel?.text as NSString?
            let urlToOpen = URL(string: (mainText?.substring(with: match.range))!)
            UIApplication.shared.open(urlToOpen!)
            break;
        }else {
            print("Tapped none")
        }

    }

}

//function to get index Of selected Character in string
func didTapAttributedTextInLabel(label: UILabel, tapLocation: CGPoint) -> Int  {


    //here myLabel is the object of UILabel
    //added this from @warly's answer
    //set font of attributedText
    let attributedText = NSMutableAttributedString(attributedString: myLabel!.attributedText!)
    attributedText.addAttributes([NSFontAttributeName: myLabel!.font], range: NSMakeRange(0, (myLabel!.attributedText?.string.characters.count)!))

    // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    let layoutManager = NSLayoutManager()
    let textContainer = NSTextContainer(size: CGSize(width: (myLabel?.frame.width)!, height: (myLabel?.frame.height)!+100))
    let textStorage = NSTextStorage(attributedString: attributedText)

    // Configure layoutManager and textStorage
    layoutManager.addTextContainer(textContainer)
    textStorage.addLayoutManager(layoutManager)

    // Configure textContainer
    textContainer.lineFragmentPadding = 0.0
    textContainer.lineBreakMode = myLabel!.lineBreakMode
    textContainer.maximumNumberOfLines = myLabel!.numberOfLines
    let labelSize = myLabel!.bounds.size
    textContainer.size = labelSize

    // get the index of character where user tapped
    let indexOfCharacter = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

    return indexOfCharacter
}

它在我的应用程序中经过测试并且运行良好。

于 2017-02-03T11:33:58.453 回答
0

Ankur答案的Swift 4 实现:

let messageLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 0
        label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.regular)
        label.isUserInteractionEnabled = true

        return label
    }()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        self.addSubview(messageLabel)
        // setup messageLabel constraints 

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapLabel))
        messageLabel.addGestureRecognizer(tapGesture)


    }

//function to get attributed string with url
    func getAttributedString(input : String) -> NSMutableAttributedString {

        let matches = getURLRange(input: input)
        let attributedString = NSMutableAttributedString(string:input)

        for match in matches {
            let url = (input as NSString).substring(with: match.range)

            let linkText = NSMutableAttributedString(string:url, attributes:[NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue) : UIColor.appleBlue()])
            attributedString.replaceCharacters(in: match.range, with: linkText)
        }

        return attributedString
    }

    func getURLRange(input : String) -> [NSTextCheckingResult] {

        let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
        let matches = detector.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))

        return matches
    }

    //function to get index Of selected Character in string
    func didTapAttributedTextInLabel(label: UILabel, tapLocation: CGPoint) -> Int  {


        //here myLabel is the object of UILabel
        //added this from @warly's answer
        //set font of attributedText
        let attributedText = NSMutableAttributedString(attributedString: messageLabel.attributedText!)
        attributedText.addAttributes([NSAttributedString.Key.font: messageLabel.font], range: NSMakeRange(0, (messageLabel.attributedText?.string.count)!))

        // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
        let layoutManager = NSLayoutManager()
        let textContainer = NSTextContainer(size: CGSize(width: messageLabel.frame.width, height: messageLabel.frame.height+100))
        let textStorage = NSTextStorage(attributedString: attributedText)

        // Configure layoutManager and textStorage
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)

        // Configure textContainer
        textContainer.lineFragmentPadding = 0.0
        textContainer.lineBreakMode = messageLabel.lineBreakMode
        textContainer.maximumNumberOfLines = messageLabel.numberOfLines
        let labelSize = messageLabel.bounds.size
        textContainer.size = labelSize

        // get the index of character where user tapped
        let indexOfCharacter = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

        return indexOfCharacter
    }


    // function to check if URL is taped
    @objc func tapLabel(gesture: UITapGestureRecognizer) {

        let matches = getURLRange(input: (messageLabel.text)!)

        let tapLocation = gesture.location(in: messageLabel)


        let indexOfCharacter = didTapAttributedTextInLabel(label: messageLabel, tapLocation: tapLocation)

        for match in matches {

            if NSLocationInRange(indexOfCharacter, match.range) {

                //open selected URL
                let mainText = messageLabel.text as NSString?
                if let urlToOpen = URL(string: (mainText?.substring(with: match.range))!) {
                    UIApplication.shared.open(urlToOpen)
                } else {
                    print("We have error with URL")
                }
                break
            } else {
                print("Tapped none")
            }

        }

    }
于 2019-03-23T21:24:13.060 回答