UITextView에서 사용자가 자동 감지 된 전화 링크를 터치하면 사용자 지정 작업을 수행 할 수 있습니까? 대신 UIWebView를 사용하도록 조언하지 마십시오.
그리고 애플 클래스 레퍼런스의 텍스트를 반복하지 마십시오. 확실히 이미 읽었습니다.
감사.
답변
업데이트 :부터 ios10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
에서 IOS 7나중에 UITextView
위임 메서드가 있습니다.
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
링크 클릭을 가로 챌 수 있습니다. 이것이 최선의 방법입니다.
에 대한 ios6이전에이 작업을 수행하는 좋은 방법은 하위 클래스를 UIApplication
만들고 덮어 쓰는 것입니다.-(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
openURL:
대리인에서 구현해야합니다 .
이제 응용 프로그램을의 새 하위 클래스로 시작 UIApplication
하려면 프로젝트에서 main.m 파일을 찾습니다. 앱을 부트 스트랩하는이 작은 파일에는 일반적으로 다음 줄이 있습니다.
int retVal = UIApplicationMain(argc, argv, nil, nil);
세 번째 매개 변수는 애플리케이션의 클래스 이름입니다. 따라서이 줄을 다음으로 대체합니다.
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
이것은 나를 위해 트릭을했습니다.
답변
iOS 7 이상
다음 UITextView 대리자 메서드를 사용할 수 있습니다.
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
사용자가 URL 링크를 탭하거나 길게 누르면 텍스트보기에서이 메서드를 호출합니다. 이 메서드의 구현은 선택 사항입니다. 기본적으로 텍스트보기는 URL 유형을 처리하는 응용 프로그램을 열고 URL을 전달합니다. 이 메서드를 사용하여 현재 응용 프로그램 내의 웹보기에서 URL에 웹 콘텐츠를 표시하는 등의 대체 작업을 트리거 할 수 있습니다.
중대한:
텍스트보기의 링크는 텍스트보기를 선택할 수 있지만 편집 할 수없는 경우에만 대화 형입니다. 즉, UITextView의 값이 선택 가능한 속성이 YES이고 isEditable 속성이 NO 인 경우입니다.
답변
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
}
}
또는 타겟이> = IOS 10 인 경우
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
답변
Swift 5 및 iOS 12에서는 다음 세 가지 패턴 중 하나를 사용하여 UITextView
.
#1. UITextView
의 dataDetectorTypes
속성을 사용 합니다.
전화 번호, URL 또는 주소와 상호 작용하는 가장 간단한 방법 UITextView
은 dataDetectorTypes
속성 을 사용 하는 것 입니다 . 아래 샘플 코드는이를 구현하는 방법을 보여줍니다. 이 코드를 사용하면 사용자가 전화 번호를 탭하면 UIAlertController
팝업이 나타납니다.
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
}
}
# 2. 사용 UITextViewDelegate
의 textView(_:shouldInteractWith:in:interaction:)
방법을
당신이 대신이 만드는 일부 사용자 지정 작업을 수행 할 경우 UIAlertController
사용하는 동안 전화 번호를 누를 때 팝업 dataDetectorTypes
, 당신은 당신이 할 필요가 UIViewController
준수 UITextViewDelegate
프로토콜 및 구현 textView(_:shouldInteractWith:in:interaction:)
. 아래 코드는이를 구현하는 방법을 보여줍니다.
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
및 사용NSAttributedString.Key.link
대안 으로 속성에 대해를 사용 NSAttributedString
하고 설정할 수 있습니다. 아래 샘플 코드는 가능한 구현을 보여줍니다 .The sample code below shows a possible implementation of it. 이 코드를 사용하면 사용자가 속성 문자열을 탭하면 팝업이 나타납니다.URL
NSAttributedString.Key.link
UIAlertController
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
}
}
답변
Swift 버전 :
표준 UITextView 설정은 다음과 같아야합니다. 대리자와 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)
수업이 끝나면 다음 부분을 추가하십시오.
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
}
}
답변
스위프트 4 :
1) 다음 클래스 (서브 클래 싱 된 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) 텍스트 뷰를 설정할 때마다 다음을 수행하십시오.
//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")
}
}
스토리 보드를 사용하는 경우 오른쪽 창 ID 검사기에서 텍스트보기가 다음과 같은지 확인합니다.
짜잔! 이제 URL이 InteractWith URL 메서드가 아닌 즉시 링크 탭을 얻습니다.
답변
직접 시도하지는 않았지만 application:handleOpenURL:
응용 프로그램 대리자에서 메서드 를 구현할 수 있습니다. 모든 openURL
요청이이 콜백을 통과 하는 것처럼 보입니다 .