-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVSWordDetector.m
189 lines (146 loc) · 6.26 KB
/
VSWordDetector.m
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//
// VSWordDetector.m
// VSWordDetector
//
// Created by TheTiger on 05/02/14.
// Copyright (c) 2014 TheTiger. All rights reserved.
//
#import "VSWordDetector.h"
@interface VSWordDetector ()
@property (strong, nonatomic) id <VSWordDetectorDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *words;
@property (strong, nonatomic) NSMutableArray *wordAreas;
@end
@implementation VSWordDetector
@synthesize delegate = _delegate;
@synthesize words = _words;
@synthesize wordAreas = _wordAreas;
#pragma mark - Initializaiton
-(id)initWithDelegate:(id<VSWordDetectorDelegate>)delegate
{
self = [super init];
if (self)
{
self.delegate = delegate;
}
return self;
}
#pragma mark - Adding Detector on view
-(void)addOnView:(id)view
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
if ([view isKindOfClass:[UITextView class]])
{
[view addGestureRecognizer:tapGesture];
UITextView *textView = (UITextView *)view;
textView.userInteractionEnabled = YES;
textView.editable = NO;
textView.scrollEnabled = NO;
}
else if ([view isKindOfClass:[UILabel class]])
{
[view addGestureRecognizer:tapGesture];
UILabel *label = (UILabel *)view;
label.userInteractionEnabled = YES;
}
}
#pragma mark - Tapped
-(void)tapped:(UIGestureRecognizer *)recognizer
{
if ([recognizer.view isKindOfClass:[UITextView class]])
{
UITextView *textView = (UITextView *)recognizer.view;
NSLayoutManager *layoutManager = textView.layoutManager;
CGPoint location = [recognizer locationInView:textView];
location.x -= textView.textContainerInset.left;
location.y -= textView.textContainerInset.top;
// FIND THE CHARACTER WHICH HAVE BEEN TAPPED
NSInteger characterIndex = [layoutManager characterIndexForPoint:location inTextContainer:textView.textContainer fractionOfDistanceBetweenInsertionPoints:NULL];
if (characterIndex < textView.textStorage.length)
{
NSString *word = [self tappedWordInTextView:textView fromIndex:characterIndex];
if ([self.delegate respondsToSelector:@selector(wordDetector:detectWord:)])
{
[self.delegate wordDetector:self detectWord:word];
}
}
}
else if ([recognizer.view isKindOfClass:[UILabel class]])
{
UILabel *label = (UILabel *)recognizer.view;
CGPoint location = [recognizer locationInView:label];
// GETTING ALL WORDS OF LABEL
self.words = nil;
self.words = [[[label text] componentsSeparatedByString:@" "] mutableCopy];
self.wordAreas = nil;
self.wordAreas = [[NSMutableArray alloc] init];
__block CGPoint drawPoint = CGPointMake(0, 0);
CGRect rect = [label frame];
CGRect spaceRect = [@" " boundingRectWithSize:rect.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:label.font}
context:nil];
CGSize space = spaceRect.size;
// GETTING AREA OF EACH WORD OF LABEL
[self.words enumerateObjectsUsingBlock:^(NSString *word, NSUInteger idx, BOOL *stop) {
UIFont *font = [label font];
CGSize size = [word sizeWithAttributes:@{NSFontAttributeName:font}];
if(drawPoint.x + size.width > rect.size.width) {
drawPoint = CGPointMake(0, drawPoint.y + size.height);
}
[self.wordAreas addObject:[NSValue valueWithCGRect:CGRectMake(drawPoint.x, drawPoint.y, size.width, size.height)]];
drawPoint = CGPointMake(drawPoint.x + size.width + space.width, drawPoint.y);
}];
// NOW FINDING THE WORD OF TAPPED AREA
[self.wordAreas enumerateObjectsUsingBlock:^(NSValue *obj, NSUInteger idx, BOOL *stop) {
CGRect area = [obj CGRectValue];
if (CGRectContainsPoint(area, location)) {
if([self.delegate respondsToSelector:@selector(wordDetector:detectWord:)]){
NSString *word = [self.words objectAtIndex:idx];
[self.delegate wordDetector:self detectWord:word];
}
*stop = YES;
}
}];
}
}
// ONLY FOR TEXT VIEW
-(NSString *)tappedWordInTextView:(UITextView *)textView fromIndex:(NSUInteger)index
{
NSMutableString *fString = [[NSMutableString alloc] init];
NSMutableString *sString = [[NSMutableString alloc] init];
// GET STRING BEFORE TAPPED CHARACTER UNTIL SPACE
for (NSInteger i=index; i>=0; i--)
{
unichar character = [textView.text characterAtIndex:i];
NSInteger asciiValue = [[NSString stringWithFormat:@"%d", character] integerValue];
if (asciiValue == 32)
{
// THIS IS SPACE
break;
}
[fString appendFormat:@"%c", character];
}
// REVERSE fString
NSMutableString *reversedString = [NSMutableString stringWithCapacity:[fString length]];
[fString enumerateSubstringsInRange:NSMakeRange(0,[fString length])
options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
[reversedString appendString:substring];
}];
fString = reversedString;
// GET STRING AFTER TAPPED CHARACTER UNTIL SPACE
for (NSInteger i=index+1; i<textView.text.length; i++)
{
unichar character = [textView.text characterAtIndex:i];
NSInteger asciiValue = [[NSString stringWithFormat:@"%d", character] integerValue];
if (asciiValue == 32)
{
// THIS IS SPACE
break;
}
[sString appendFormat:@"%c", character];
}
return [NSString stringWithFormat:@"%@%@", fString, sString];
}
@end