5

Ich habe den folgenden Code und möchte Teile meines Textes klickbar machen und einen anderen UIViewController aufrufen (keine Website).Hinzufügen eines Klickereignisses zu einem Text in IOS NSString

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"testing it out @clickhere"]; 
NSInteger length = str.length; 
[str addAttribute:NSForegroundColorAttributeName value:[UIColor bestTextColor] range:NSMakeRange(0,length)]; 

Das NSMutableAttributedString wird wie so zu einem UILabel gesetzt:

label.attributedText = str; 

Was ist der beste Weg, dies zu tun? Ich kann keine gute Antwort finden.

Ein Beispiel dafür, was ich will, ist nehme ich wie so mit dem folgenden Text ein UILabel haben:

This is my label. Click here to go to UIViewController1 and then go to UIViewController1 by this #tag. 

ich den Text „hier“ wollen für den ersten Klick-Ereignis und das Wort „# weitergegeben werden Tag "an dasselbe Click-Ereignis übergeben werden.

+0

Sehen Sie, ob dies er lps: http://stackoverflow.com/questions/8811909/getting-the-word-touched-in-a-uilabel-uitextview/21577829#21577829 Versuchen Sie auch dies: http://stackoverflow.com/questions/15293426/how -Uilabel erstellen-mit-klickbar-erstem Wort – iOSAaronDavid

+1

Warum duplizieren: http://StackOverflow.com/Questions/28018707/add-a-tap-gesture-to-a-part-of-a-uilabel? – Larme

Antwort

7

Was ist, wenn Sie das Wertfeld verwenden, um das Ziel zu übergeben?

[attributedString addAttribute:NSLinkAttributeName 
         value:[@"destinationController1" stringByAppendingString:username] 
         range:range]; 

außer Kraft setzen Sie dann die delegierte Methode:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange 
{ 
    if ([URL.scheme isEqualToString:@"destinationController1"]) { 
     // Launch View controller 
     return NO; 
    } 
    return YES; 
} 
+1

Der wichtige Teil hier ist, ein 'UITextView' anstelle eines' UILabel' zu verwenden. Und vielleicht möchten Sie einige Eigenschaften der Textansicht anpassen, damit sie sich mehr wie eine einfache Beschriftung verhält, wie das Bearbeiten, Auswählen und Scrollen. –

+0

Diese beiden gehen in meiner .m-Datei richtig? – cdub

+0

Ja beide in der .m-Datei, aber stellen Sie sicher, dass Sie die UITextViewDelegate in Ihrer .h-Datei abonnieren, so dass die Methode an erster Stelle aufgerufen wird. – scott

3

Meine Lösung die Verwendung eines UITextView erfordert (was wesentlich einfacher ist, und ich fordere, dass Sie es verwenden, anstatt).

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!); 
    } 
} 

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

Grundsätzlich benötigen Sie einen Gestenerkenner hinzufügen, um den Abgriffspunkt in Ihrem Textview zu erhalten. Dann erhalten Sie das Wort mithilfe der im Erweiterungsbereich bereitgestellten Kategoriemethode. Danach überprüfen Sie, was das Wort ist (wo wir das Wort "hier" wollen). Dann sammeln wir die Hashtags, die Sie bereitgestellt haben.

Sie müssen lediglich eine performSegueWithIdentifier-Methode hinzufügen und diese entsprechend übergeben.

+0

gibt es eine Möglichkeit, dies zu tun, sondern die ganze Linie, anstatt nur das ein Wort klicken, um zu bekommen? – saboehnke

+0

Ich glaube, ersetzen Sie das 'hier' in' Let wordTarget = "hier"; 'mit einem Satz stattdessen. –

+0

Ich gab das eine Chance und es funktioniert nicht. Es nimmt nur ein Wort auf, wenn ich also dasselbe Wort im Text haben muss, wird es den Unterschied nicht erkennen können. – saboehnke

0

Swift 3:

nicht prüfen auf dem URL.scheme Attribut. Bin für mich zurückgekehrt.

tun:

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

Dann nutzen Sie das absoluteString Attribut auf der URL auf diesem Wert zu Ihrer Ansicht der Wahl zu überprüfen:

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 
} 
1

Zusätzlich Antwort auf @Nate Lee, die Erweiterung für Swift 4.0 Version aktualisiert:

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!) 
    } 
} 
Verwandte Themen