Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将单击事件添加到ios NSString中的某些文本_Ios_Iphone_Uibutton_Nsattributedstring_Uitapgesturerecognizer - Fatal编程技术网

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

将单击事件添加到ios NSString中的某些文本,ios,iphone,uibutton,nsattributedstring,uitapgesturerecognizer,Ios,Iphone,Uibutton,Nsattributedstring,Uitapgesturerecognizer,我有以下代码,希望我的部分文本可以点击,并调用另一个UIViewController(而不是网站) NSMutableAttributeString设置为UILabel,如下所示: label.attributedText = str; 最好的方法是什么?我似乎找不到一个好答案 我想要的一个例子是假设我有一个这样的UILabel,带有以下文本: This is my label. Click here to go to UIViewController1 and then go to UIV

我有以下代码,希望我的部分文本可以点击,并调用另一个UIViewController(而不是网站)

NSMutableAttributeString设置为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”传递给同一个单击事件。

如果使用值字段传递给目标,会怎么样

[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
(这要简单得多,我建议您改用它)

Swift

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];
}
基本上,您需要添加一个手势识别器来获取文本视图中的点击点。然后,使用扩展区域中提供的category方法获取单词。之后,检查单词是什么(我们想要单词“here”的位置)。然后,我们收集您提供的hashtag

您只需添加一个performsguewithidentifier方法,并相应地传递它。

Swift 3:

不要检查
URL.scheme
属性。我的回答是零

这样做:

attributedString.addAttribute(NSLinkAttributeName,值:“openToViewController”,范围:范围)

然后使用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
}

除了@Nate Lee answer,还更新了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!)
    }
}

看看这是否有帮助:还可以试试这个:为什么重复:?这里的重要部分是使用
UITextView
而不是
UILabel
。。您可能需要调整textview的某些属性,使其更像一个普通标签,例如禁用编辑、选择和滚动。在.m文件中都可以,但请确保在.h文件中订阅UITextViewDelegate,以便首先调用该方法。如果我的viewcontroller中有手势,那么这是否有效?在属性文本中添加值时不要添加空格,否则shouldInteractWithURL将检测不到空格。如果你传递一个不包含任何URL的ant字符串值,然后比较URL.absoluteString而不是URL.schemeis有没有办法做到这一点,但是可以得到整行内容,而不仅仅是你点击的一个单词?我相信是这样,在
let wordTarget=“here”中替换
here
改为一句话。我试了一下,但它不起作用。它只拾取一个单词,因此如果我必须在文本中输入相同的单词,它将无法分辨差异。textView.closestPositionToPoint(correctedPoint)始终返回零
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!)
    }
}