Odpowiedzi:
Aktualizacja: od ios10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
Z ios7a Later UITextView
ma metodę delegata:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
przechwytywania kliknięć prowadzących do linków. I to jest najlepszy sposób na zrobienie tego.
Dla ios6a wcześniej dobrym sposobem na zrobienie tego jest UIApplication
utworzenie podklasy i nadpisanie-(BOOL)openURL:(NSURL *)url
@interface MyApplication : UIApplication {
}
@end
@implementation MyApplication
-(BOOL)openURL:(NSURL *)url{
if ([self.delegate openURL:url])
return YES;
else
return [super openURL:url];
}
@end
Będziesz musiał zaimplementować openURL:
w swoim delegacie.
Teraz, aby aplikacja zaczęła się z nową podklasą UIApplication
, zlokalizuj plik main.m w swoim projekcie. W tym małym pliku, który ładuje Twoją aplikację, zwykle znajduje się następująca linia:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Trzeci parametr to nazwa klasy Twojej aplikacji. Tak więc, zamieniając tę linię na:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
To załatwiło sprawę dla mnie.
UIApplication
i zastępować implementację openURL. Chociaż w ten sposób odniesienie do oryginalnej implementacji jest trudne (ale nie niemożliwe).
W iOS 7 lub nowszym
Możesz użyć następującej metody delegata UITextView:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
Widok tekstowy wywołuje tę metodę, jeśli użytkownik dotknie lub długo naciśnie łącze URL. Wdrożenie tej metody jest opcjonalne. Domyślnie widok tekstowy otwiera aplikację odpowiedzialną za obsługę typu adresu URL i przekazuje jej adres URL. Możesz użyć tej metody, aby wyzwolić alternatywną akcję, taką jak wyświetlenie treści WWW pod adresem URL w widoku sieci Web w bieżącej aplikacji.
Ważny:
Łącza w widokach tekstu są interaktywne tylko wtedy, gdy widok tekstu jest wybieralny, ale nie można go edytować. Oznacza to, że jeśli wartość UITextView, wybieralna właściwość to TAK, a właściwość isEditable ma wartość NO.
UIWebView
jeśli chcesz, aby jakiś inny tekst był linkiem, a nie samym adresem URL. W takim przypadku <a>
tag jest nadal najlepszym rozwiązaniem.
Dla Swift 3
textView.delegate = self
extension MyTextView: UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
GCITracking.sharedInstance.track(externalLink: URL)
return true
}
}
lub jeśli celem jest> = IOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
W Swift 5 i iOS 12 możesz użyć jednego z trzech poniższych wzorców w celu interakcji z linkami w UITextView
.
UITextView
z dataDetectorTypes
właściwości.Najprostszym sposobem interakcji z numerami telefonów, adresami URL lub adresami w domenie UITextView
jest użycie dataDetectorTypes
własności. Poniższy przykładowy kod pokazuje, jak go zaimplementować. Za pomocą tego kodu, gdy użytkownik stuka w numer telefonu, UIAlertController
pojawi się ikona.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
UITextViewDelegate
'stextView(_:shouldInteractWith:in:interaction:)
metodyJeśli chcesz wykonać niestandardową akcję zamiast tworzyć plik UIAlertController
wyskakujące okienko po dotknięciu numeru telefonu podczas korzystania dataDetectorTypes
, musisz UIViewController
dostosować się do UITextViewDelegate
protokołu i zaimplementować textView(_:shouldInteractWith:in:interaction:)
. Poniższy kod pokazuje, jak to zaimplementować:
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.delegate = self
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
/* perform your own custom actions here */
print(URL) // prints: "tel:+33687654321"
return false // return true if you also want UIAlertController to pop up
}
}
NSAttributedString
iNSAttributedString.Key.link
Alternatywnie możesz użyć NSAttributedString
i ustawić URL
dla jego NSAttributedString.Key.link
atrybutu. Przykładowy kod poniżej pokazuje możliwą implementację tego atrybutu. W przypadku tego kodu, gdy użytkownik dotyka przypisanego ciągu, UIAlertController
pojawia się ikona.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let attributedString = NSMutableAttributedString(string: "Contact: ")
let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
let attributes = [NSAttributedString.Key.link: phoneUrl]
let phoneAttributedString = NSAttributedString(string: "phone number", attributes: attributes)
attributedString.append(phoneAttributedString)
let textView = UITextView()
textView.attributedText = attributedString
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
Wersja Swift:
Twoja standardowa konfiguracja UITextView powinna wyglądać mniej więcej tak, nie zapomnij o delegacie i dataDetectorTypes.
var textView = UITextView(x: 10, y: 10, width: CardWidth - 20, height: placeholderHeight) //This is my custom initializer
textView.text = "dsfadsaf www.google.com"
textView.selectable = true
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.delegate = self
addSubview(textView)
Po zakończeniu zajęć dodaj ten fragment:
class myVC: UIViewController {
//viewdidload and other stuff here
}
extension MainCard: UITextViewDelegate {
func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
//Do your stuff over here
var webViewController = SVModalWebViewController(URL: URL)
view.presentViewController(webViewController, animated: true, completion: nil)
return false
}
}
Swift 4:
1) Utwórz następującą klasę (podklasę UITextView):
import Foundation
protocol QuickDetectLinkTextViewDelegate: class {
func tappedLink()
}
class QuickDetectLinkTextView: UITextView {
var linkDetectDelegate: QuickDetectLinkTextViewDelegate?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex: Int? = layoutManager.glyphIndex(for: point, in: textContainer, fractionOfDistanceThroughGlyph: nil)
let index: Int? = layoutManager.characterIndexForGlyph(at: glyphIndex ?? 0)
if let characterIndex = index {
if characterIndex < textStorage.length {
if textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil {
linkDetectDelegate?.tappedLink()
return self
}
}
}
return nil
}
}
2) Gdziekolwiek ustawisz widok tekstu, zrób to:
//init, viewDidLoad, etc
textView.linkDetectDelegate = self
//outlet
@IBOutlet weak var textView: QuickDetectLinkTextView!
//change ClassName to your class
extension ClassName: QuickDetectLinkTextViewDelegate {
func tappedLink() {
print("Tapped link, do something")
}
}
Jeśli używasz scenorysu, upewnij się, że widok tekstu wygląda tak w inspektorze tożsamości w prawym okienku:
Voila! Teraz otrzymujesz natychmiastowe dotknięcie łącza zamiast tego, kiedy adres URL powinienInteractWith URL
Nie jestem pewien, jak przechwycić wykryte łącze danych lub jakiego typu funkcji musisz uruchomić. Ale możesz skorzystać z metody didBeginEditing TextField, aby przeprowadzić test / skanowanie przez pole tekstowe, jeśli wiesz, czego szukasz, na przykład porównując ciągi tekstowe zgodne z formatem ### - ### - ####, lub zacznij od „www”. aby pobrać te pola, ale musiałbyś napisać mały kod, aby przeszukać łańcuch textfields, zrekonstruować to, czego potrzebujesz, a następnie wyodrębnić go do użycia przez funkcję. Nie sądzę, żeby to było takie trudne, gdy już zawęzisz dokładnie to, czego chciałeś, a następnie skupisz filtry instrukcji if () do bardzo konkretnego wzoru dopasowania tego, czego potrzebujesz.
Oczywiście oznacza to, że użytkownik ma zamiar dotknąć pola tekstowego, aby aktywować didBeginEditing (). Jeśli nie jest to typ interakcji użytkownika, którego szukałeś, możesz po prostu użyć wyzwalacza Timer, który uruchamia się na ViewDidAppear () lub innym w zależności od potrzeb i przechodzi przez ciąg tekstowy, a na końcu przebiega przez ciąg pola tekstowego metod, które stworzyłeś, po prostu wyłączasz Timer.
application:handleOpenURL:
jest wywoływana, gdy inna aplikacja otwiera plik aplikację, otwierając adres URL ze schematem obsługiwanym przez Twoją aplikację. Nie jest wywoływana, gdy aplikacja zaczyna otwierać adres URL.
Myślę, że jedynym sposobem na zrobienie tego, czego chce Vladimir, jest użycie UIWebView zamiast UITextView. Spraw, aby kontroler widoku zaimplementował UIWebViewDelegate, ustaw delegata UIWebView na kontroler widoku oraz w implementacji kontrolera widoku, webView:shouldStartLoadWithRequest:navigationType:
aby otworzyć [request URL]
w widoku zamiast zamykania aplikacji i otwierania jej w Mobile Safari.