//
// MGTextView.swift
// MGSDKDemo
//
// Created by Nicky Y M LIU_SP on 2021/3/9.
// Copyright © 2021 Nicky Y M LIU_SP. All rights reserved.
//
import UIKit
class MGTextView: UITextView {
public var placeHolderTextColor = UIColor.lightGray {
didSet {
placeHolderLabel.textColor = placeHolderTextColor
}
}
public var placeHolderText = "请输入你的文字" {
didSet {
placeHolderLabel.text = placeHolderText
}
}
private let placeHolderLabel = UILabel()
public var linkTextColor: UIColor = UIColor.blue
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
self.linkTextAttributes = [:]
placeHolderLabel.text = "写下你的问题或建议,我们将及时跟进解决(建议上传截图帮助我们解决问题,感谢!)"
placeHolderLabel.numberOfLines = 0
placeHolderLabel.font = UIFont.systemFont(ofSize: 15)
placeHolderLabel.textColor = UIColor.lightGray
placeHolderLabel.sizeToFit()
self.addSubview(placeHolderLabel)
self.setValue(placeHolderLabel, forKeyPath: "_placeholderLabel")
self.font = placeHolderLabel.font
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@discardableResult
func setTextWithLinkAttribute(text: String) -> NSMutableAttributedString? {
// 正则匹配网址
let regulaStr = "((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)"
let regularExpression = try? NSRegularExpression(pattern: regulaStr, options: NSRegularExpression.Options.caseInsensitive)
guard let arrayOfAllMatches: [NSTextCheckingResult] = regularExpression?.matches(in: text, options: NSRegularExpression.MatchingOptions.init(rawValue: 0), range: NSMakeRange(0, text.count)) else { return nil }
var resultArr = [String]()
var rangeArr = [NSValue]()
for match in arrayOfAllMatches {
if let range = text.range(from: match.range) {
let substringForMatch = text.substring(with: range)
resultArr.append(substringForMatch)
}
}
let subStr = text
for str in resultArr {
if let value = self.rangesOfString(searchString: str, inString: subStr) {
rangeArr.append(value)
}
}
let attributedText = NSMutableAttributedString(string: subStr)
for value in rangeArr {
guard let index = rangeArr.firstIndex(of: value) else {
continue
}
let range = value.rangeValue
attributedText.addAttributes([NSAttributedString.Key.link: URL(string: resultArr[index])], range: range)
// self.linkTextAttributes = [NSAttributedString.Key.foregroundColor: self.linkTextColor]
attributedText.addAttributes([NSAttributedString.Key.foregroundColor: self.linkTextColor], range: range)
}
self.attributedText = attributedText
return attributedText
}
// 获取查找字符串在母串中的NSRange
func rangesOfString(searchString: String, inString: String) -> NSValue? {
let searchRange = NSMakeRange(0, inString.count)
// var range?
let range = (inString as NSString).range(of: searchString, options: NSString.CompareOptions.init(rawValue: 0), range: searchRange)
if range.location != NSNotFound {
return NSValue(range: range)
}
return nil
}
/// 使用下标截取字符串 例: "示例字符串"[0..<2] 结果是 "示例"
subscript (r: Range<Int>) -> String {
get {
if (r.lowerBound > count) || (r.upperBound > count) { return "截取超出范围" }
let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
return String(self[startIndex..<endIndex])
}set {
if (r.lowerBound > count) || (r.upperBound > count) { return }
let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
self.replaceSubrange(startIndex..<endIndex, with: newValue)
}
}
}
// MARK: -
public extension String {
/// range转换为NSRange
func nsRange(from range: Range<String.Index>) -> NSRange {
return NSRange(range, in: self)
}
/// NSRange转化为range
func range(from nsRange: NSRange) -> Range<String.Index>? {
guard
let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self)
else { return nil }
return from ..< to
}
}
使用
override func viewDidLoad() {
super.viewDidLoad()
let ideaTextView = MGTextView()
ideaTextView.placeHolderTextColor = UIColor.red
ideaTextView.placeHolderText = "1234567890"
ideaTextView.delegate = self
// ideaTextView.isEditable = false
ideaTextView.isSelectable = true
ideaTextView.dataDetectorTypes = [.phoneNumber, .link]
ideaTextView.backgroundColor = UIColor.orange
ideaTextView.frame = CGRect(x: 20, y: 200, width: 300, height: 200)
ideaTextView.linkTextColor = UIColor.white
// ideaTextView.text = "谷歌搜索好用http://www.google.com搜索用什么https://www.baidu.com百度一下你知道"
ideaTextView.attributedText = NSMutableAttributedString(string: "谷歌搜索好用 http://www.google.com 搜索用什么 https://www.baidu.com 百度一下你知道3453555")
ideaTextView.setTextWithLinkAttribute(text: "谷歌搜索好用http://www.google.com搜索用什么https://www.baidu.com百度一下你知道345355")
self.view.addSubview(ideaTextView)
}
func addClick() {
// 将UITextView中的内容进行调整(主要是在光标所在的位置进行字符串截取,再拼接你需要插入的文字即可)
let content = ideaTextView.text!;
let result = content[0..<location] + "MG123" + content[location..<content.count]
// 将调整后的字符串添加到UITextView上面
ideaTextView.text = result
}