将click事件添加到ios NSString中的某些文本
我有以下代码,并希望使我的文本的一部分可以点击并调用另一个UIViewController(而不是一个网站)。
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"testing it out @clickhere"]; NSInteger length = str.length; [str addAttribute:NSForegroundColorAttributeName value:[UIColor bestTextColor] range:NSMakeRange(0,length)];
NSMutableAttributedString被设置为UILabel,如下所示:
label.attributedText = str;
什么是最好的方法呢? 我似乎无法找到一个好的答案。
我想要的一个例子是假设我有一个UILabel,如下所示:
This is my label. Click here to go to UIViewController1 and then go to UIViewController1 by this #tag.
我希望第一次单击事件传递“here”文本,并将“#tag”一词传递给同一个click事件。
如果您使用值字段传入目的地该怎么办?
[attributedString addAttribute:NSLinkAttributeName value:[@"destinationController1" stringByAppendingString:username] range:range];
然后覆盖委托方法:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { if ([URL.scheme isEqualToString:@"destinationController1"]) { // Launch View controller return NO; } return YES; }
我的解决方案需要使用UITextView
(这非常简单,我敦促您使用它)。
迅速
class ViewController: UIViewController { @IBOutlet weak var textView:UITextView!; override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let gestureRecognizer = UITapGestureRecognizer(target: self, action: "textViewTapped:"); gestureRecognizer.numberOfTapsRequired = 1; gestureRecognizer.numberOfTouchesRequired = 1; self.textView.addGestureRecognizer(gestureRecognizer); } func textViewTapped(sender: UITapGestureRecognizer) { let wordTarget = "here"; let word = UITextView.getWordAtPosition(sender.locationInView(self.textView), textView: self.textView); if word == wordTarget { let plainString = self.textView.attributedText.string; let substrings = NSMutableArray(); let scanner = NSScanner(string: plainString); scanner.scanUpToString("#", intoString: nil); while !scanner.atEnd { var substring:NSString? = nil; scanner.scanString("#", intoString: nil); let space = " "; if scanner.scanUpToString(space, intoString: &substring) { // If the space immediately followed the #, this will be skipped substrings.addObject(substring!); } scanner.scanUpToString("#", intoString: nil); //Scan all characters before next # } println(substrings.description); //Now you got your substrings in an array, so use those for your data passing (in a segue maybe?) ... } } } extension UITextView { class func getWordAtPosition(position: CGPoint!, textView: UITextView!) -> String? { //Remove scrolloffset let correctedPoint = CGPointMake(position.x, textView.contentOffset.y + position.y); //Get location in text from uitextposition at a certian point let tapPosition = textView.closestPositionToPoint(correctedPoint); //Get word at the position, will return nil if its empty. let wordRange = textView.tokenizer.rangeEnclosingPosition(tapPosition, withGranularity: UITextGranularity.Word, inDirection: UITextLayoutDirection.Right.rawValue); return textView.textInRange(wordRange!); } }
Objective-C的
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textViewTapped:)]; gestureRecognizer.numberOfTouchesRequired = 1; gestureRecognizer.numberOfTapsRequired = 1; [self.textView addGestureRecognizer:gestureRecognizer]; } - (void)textViewTapped:(UITapGestureRecognizer *)sender { NSString *wordTarget = @"here"; NSString* word = [self getWordAtPosition:[sender locationInView:self.textView] textView:self.textView]; if ([word isEqualToString:wordTarget]) { NSString *plainString = self.textView.attributedText.string; NSMutableArray* substrings = [[NSMutableArray alloc]init]; NSScanner *scanner = [[NSScanner alloc]initWithString:plainString]; [scanner scanUpToString:@"#" intoString:nil]; while (![scanner isAtEnd]) { NSString* substring = nil; [scanner scanString:@"#" intoString:nil]; NSString* space = @" "; if ([scanner scanUpToString:space intoString:&substring]) { [substrings addObject:substring]; } [scanner scanUpToString:@"#" intoString:nil]; } //Now you got your substrings in an array, so use those for your data passing (in a segue maybe?) ... } } - (NSString*)getWordAtPosition:(CGPoint)position textView:(UITextView *)textView { //remove scrollOffset CGPoint correctedPoint = CGPointMake(position.x, textView.contentOffset.y + position.y); UITextPosition *tapPosition = [textView closestPositionToPoint:correctedPoint]; UITextRange *wordRange = [textView.tokenizer rangeEnclosingPosition:tapPosition withGranularity:UITextGranularityWord inDirection:UITextLayoutDirectionRight]; return [textView textInRange:wordRange]; }
基本上,您需要添加手势识别器才能获得textview中的分接点。 然后,您可以使用扩展区域中提供的类别方法获取单词。 之后,你检查这个词是什么(我们想要“这里”这个词)。 然后,我们收集您提供的主题标签。
您所要做的就是添加performSegueWithIdentifier方法,并相应地传递它。
除了@Nate Lee的回答,更新了Swift 4.0版本的扩展:
extension UITextView { class func getWordAtPosition(position: CGPoint!, textView: UITextView!) -> String? { //Remove scrolloffset let correctedPoint = CGPoint(x: position.x, y: (textView.contentOffset.y + position.y)) //Get location in text from uitextposition at a certian point let tapPosition = textView.closestPosition(to: correctedPoint) //Get word at the position, will return nil if its empty. let wordRange = textView.tokenizer.rangeEnclosingPosition(tapPosition!, with: .word, inDirection: UITextLayoutDirection.right.rawValue) return textView.text(in: wordRange!) } }
斯威夫特3:
不要检查URL.scheme
属性。 我没有回来。
做这个:
attributedString.addAttribute(NSLinkAttributeName, value: "openToViewController", range: range)
然后使用URL上的absoluteString
属性将该值检查到您选择的视图:
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool{ if (URL.absoluteString == "openToViewController") { let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as! UIViewController self.present(viewController, animated: true, completion: nil) return false } return true }