将click事件添加到ios NSString中的某些文本

时间:2015-01-19 22:27:52

标签: ios iphone uibutton nsattributedstring uitapgesturerecognizer

我有以下代码,想要使我的文本部分可以点击并调用另一个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"传递给相同的点击事件。

4 个答案:

答案 0 :(得分:7)

如果您使用值字段传入目的地该怎么办?

[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;
}

答案 1 :(得分:3)

我的解决方案需要使用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!);
    }
}

<强>目标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];
}

基本上,您需要添加手势识别器才能在文本视图中获取分接点。然后,您可以使用扩展区域中提供的类别方法获取单词。之后,你检查单词是什么(我们想要单词&#34; here&#34;)。然后,我们收集您提供的主题标签。

您只需添加performSegueWithIdentifier方法,然后相应地传递它。

答案 2 :(得分:1)

除了@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 :(得分:0)

斯威夫特3:

不要检查URL.scheme属性。我没有回来。

这样做:

attributedString.addAttribute(NSLinkAttributeName, value: "openToViewController", range: range)

然后使用网址上的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
}