我有一个字符串(例如:“这是一些带有特定http://goo.gl/45hz网址的文本”)。我需要找到字符串中的所有 URL(如果有),然后以某种方式转换字符串,以便地址可以点击(如果用户点击它,safari 将打开),我需要在标签中显示带有 URL 的整个字符串(如果可能) .
有谁知道如何做到这一点?
我有一个字符串(例如:“这是一些带有特定http://goo.gl/45hz网址的文本”)。我需要找到字符串中的所有 URL(如果有),然后以某种方式转换字符串,以便地址可以点击(如果用户点击它,safari 将打开),我需要在标签中显示带有 URL 的整个字符串(如果可能) .
有谁知道如何做到这一点?
您可以使用从该位置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
只显示纯文本。
您可以使用 aUITextView
而不是UILabel
. 设置editable
为NO
然后修改该属性@property(nonatomic) UIDataDetectorTypes dataDetectorTypes
以检测 URL。
为了找到一个字符串中的所有 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);
}
}
如果这是来自 UI 标签,请使用 TTTAttributedLabel - https://github.com/mattt/TTTAttributedLabel
非常适合我们。
我在 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
}
它在我的应用程序中经过测试并且运行良好。
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")
}
}
}