iOS:在字符串中找到url,并将字符串更改为可点击(可点击)

hwamh0ep  于 2023-01-06  发布在  iOS
关注(0)|答案(8)|浏览(266)

我有一个字符串(例如:“这是一些文本与特定的http://goo.gl/45hz网址在它”)。我需要找到字符串内的所有网址,如果有的话,然后以某种方式转换字符串,使地址将tapable(野生动物园将打开,如果用户点击它),我需要显示整个字符串与标签中的网址理想(如果可能的话)。
有没有人知道怎样才能做到这一点?

um6iljoc

um6iljoc1#

您可以使用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"
}

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

23c0lvtd

23c0lvtd2#

可以使用UITextView代替UILabel。将editable设置为NO,然后修改属性@property(nonatomic) UIDataDetectorTypes dataDetectorTypes以检测URL。

4urapxun

4urapxun3#

为了查找字符串中的所有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);
    }
}
wfauudbj

wfauudbj4#

如果来自UI标签-https://github.com/mattt/TTTAttributedLabel,则使用TTTAttributedLabel
对我们很有用。

wh6knrhe

wh6knrhe5#

我已经在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
}

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

flmtquvp

flmtquvp6#

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")
            }

        }

    }
dwbf0jvd

dwbf0jvd7#

Swift 5分机

extension String {
    func extractUrl() -> URL? {
        let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
        let matches = detector.matches(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count))

        for match in matches {
            guard let range = Range(match.range, in: self) else { continue }
            let url = self[range]
            return URL(string: String(url))
        }
        return nil
    }
}
iyr7buue

iyr7buue8#

#在swift 5中,您将尝试这样查找URL

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

for match in matches {
guard let range = Range(match.range, in: input) else { continue }
let url = input[range]
print(url)
}

相关问题