有使用过新浪微博会发现,微博对发送的消息提供了几个特殊符号标签。
比如:输入“ @+微博用户昵称(即ID)+空格或标点”,那么在这条微博中这个@条目就会表现成超链接形式,点击即可跳转到被@的某人的微博。
又比如话题标签“ #+关键字+#”。表现形式就是点击后会跳转到包含该关键字的微博的搜索结果页面的超链接。
比如:输入“ @+微博用户昵称(即ID)+空格或标点”,那么在这条微博中这个@条目就会表现成超链接形式,点击即可跳转到被@的某人的微博。
又比如话题标签“ #+关键字+#”。表现形式就是点击后会跳转到包含该关键字的微博的搜索结果页面的超链接。
同样的,直接输入“
http://hangge.com”那么微博中会显示为可点击的网页链接。
1,让textview支持特殊符号标签
通常情况下,这些带特殊标签符号内容对于多行文本框(
UITextView
)来说都是视为普通文本,要想让其支持点击,我们可以借助textview的URL检测功能来实现。
(1)首先遍历文本内容,将各种特殊文本替换成我们自定义的一些
URL scheme。比如:用
mention://hangge 表示
@hangge,用
hash://航歌 表示
#航歌#
(2)通过textview的 UITextFieldDelegate 代理的 shouldInteractWithURL 方法,我们可以捕获到这些自定义的 URL scheme 点击,然后通过判断 URL.scheme 来执行不同的操作。
(2)通过textview的 UITextFieldDelegate 代理的 shouldInteractWithURL 方法,我们可以捕获到这些自定义的 URL scheme 点击,然后通过判断 URL.scheme 来执行不同的操作。
2,先看效果图
(1)我们在页面上放置两个 textview,下面一个用来编辑文本。
(1)我们在页面上放置两个 textview,下面一个用来编辑文本。
3,实现步骤
(1)对于用来显示的textview,要将其 Detection Links(链接检测)打勾,去掉 Editable(使其不可编辑)。
(2)扩展UITextView: UITextFieldExtension.swift
(3)测试页面代码:
源码下载:hangge_1096.zip
(1)对于用来显示的textview,要将其 Detection Links(链接检测)打勾,去掉 Editable(使其不可编辑)。
(2)扩展UITextView: UITextFieldExtension.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
import
UIKit
extension
UITextView
{
/**
转换特殊符号标签字段
*/
func
resolveHashTags(){
let
nsText:
NSString
=
self
.text
// 使用默认设置的字体样式
let
attrs = [
NSFontAttributeName
:
self
.font!]
let
attrString =
NSMutableAttributedString
(string: nsText
as
String
,
attributes:attrs)
//用来记录遍历字符串的索引位置
var
bookmark = 0
//用于拆分的特殊符号
let
charactersSet =
NSCharacterSet
(charactersInString:
"@#"
)
//先将字符串按空格和分隔符拆分
let
sentences:[
NSString
] =
self
.text.componentsSeparatedByCharactersInSet(
NSCharacterSet
.whitespaceAndNewlineCharacterSet())
for
sentence
in
sentences {
//如果是url链接则跳过
if
!verifyUrl(sentence
as
String
) {
//再按特殊符号拆分
let
words:[
NSString
] = sentence.componentsSeparatedByCharactersInSet(
charactersSet)
var
bookmark2 = bookmark
for
i
in
0..<words.count{
let
word = words[i]
let
keyword = chopOffNonAlphaNumericCharacters(word
as
String
)
if
keyword !=
""
&& i>0{
//使用自定义的scheme来表示各种特殊链接,比如:mention:hangge
//使得这些字段会变蓝色且可点击
//匹配的范围
let
remainingRangeLength =
min
((nsText.length - bookmark2 + 1),
word.length+2)
let
remainingRange =
NSRange
(location: bookmark2-1,
length: remainingRangeLength)
print
(keyword, bookmark2, remainingRangeLength)
//获取转码后的关键字,用于url里的值
//(确保链接的正确性,比如url链接直接用中文就会有问题)
let
encodeKeyword = keyword
.stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet
.
URLQueryAllowedCharacterSet
())!
//匹配@某人
var
matchRange = nsText.rangeOfString(
"@\(keyword)"
,
options: .
LiteralSearch
,
range:remainingRange)
attrString.addAttribute(
NSLinkAttributeName
,
value:
"mention:\(encodeKeyword)"
,
range: matchRange)
//匹配#话题#
matchRange = nsText.rangeOfString(
"#\(keyword)#"
,
options: .
LiteralSearch
,
range:remainingRange)
attrString.addAttribute(
NSLinkAttributeName
,
value:
"hash:\(encodeKeyword)"
,
range: matchRange)
}
//移动坐标索引记录
bookmark2 += word.length + 1
}
}
//移动坐标索引记录
bookmark += sentence.length + 1
}
print
(nsText.length,bookmark)
//最终赋值
self
.attributedText = attrString
}
/**
验证URL格式是否正确
*/
private
func
verifyUrl(str:
String
) ->
Bool
{
// 创建一个正则表达式对象
do {
let
dataDetector = try
NSDataDetector
(types:
NSTextCheckingTypes
(
NSTextCheckingType
.
Link
.rawValue))
// 匹配字符串,返回结果集
let
res = dataDetector.matchesInString(str,
options:
NSMatchingOptions
(rawValue: 0),
range:
NSMakeRange
(0, str.characters.count))
// 判断结果(完全匹配)
if
res.count == 1 && res[0].range.location == 0
&& res[0].range.length == str.characters.count {
return
true
}
}
catch {
print
(error)
}
return
false
}
/**
过滤部多余的非数字和字符的部分
比如:@hangge.123 -> @hangge
*/
func
chopOffNonAlphaNumericCharacters(text:
String
) ->
String
{
let
nonAlphaNumericCharacters =
NSCharacterSet
.alphanumericCharacterSet().invertedSet
let
characterArray = text.componentsSeparatedByCharactersInSet(nonAlphaNumericCharacters)
return
characterArray[0]
}
}
|
(3)测试页面代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
import
UIKit
class
ViewController
:
UIViewController
,
UITextViewDelegate
{
//展示文本框
@IBOutlet
weak
var
displayTextView:
UITextView
!
//编辑文本框
@IBOutlet
weak
var
editTextView:
UITextView
!
override
func
viewDidLoad() {
super
.viewDidLoad()
//设置展示文本框的代理
displayTextView.delegate =
self
}
//发送消息
@IBAction
func
setMessage(sender:
AnyObject
) {
//设置展示文本框的内容
displayTextView.text = editTextView.text
//对内容中的特殊标签字段做处理
displayTextView.resolveHashTags()
//清空输入框内容
editTextView.text =
""
}
//展示文本框链接点击响应
func
textView(textView:
UITextView
, shouldInteractWithURL
URL
:
NSURL
,
inRange characterRange:
NSRange
) ->
Bool
{
//判断URL scheme
switch
URL
.scheme {
case
"hash"
:
showAlert(
"hash"
, payload:
URL
.resourceSpecifier.stringByRemovingPercentEncoding!)
case
"mention"
:
showAlert(
"mention"
, payload:
URL
.resourceSpecifier.stringByRemovingPercentEncoding!)
default
:
print
(
"这个是普通的url链接"
)
}
return
true
}
//显示消息
func
showAlert(tagType:
String
, payload:
String
){
let
alertController =
UIAlertController
(title:
"检测到\(tagType)标签"
,
message: payload, preferredStyle: .
Alert
)
let
cancelAction =
UIAlertAction
(title:
"确定"
, style: .
Cancel
, handler:
nil
)
alertController.addAction(cancelAction)
self
.presentViewController(alertController, animated:
true
, completion:
nil
)
}
override
func
didReceiveMemoryWarning() {
super
.didReceiveMemoryWarning()
}
}
|
原文出自: www.hangge.com 转载请保留原文链接: http://www.hangge.com/blog/cache/detail_1096.html