IOS-CoreText and ios-coretext
1. Determine whether the clicked position is within the range of a specified nsange.
# Pragma mark determines whether the clicked position is within the range/** converts the clicked position to the offset of the string. If no value is found,-1 view: view point is returned: click frameRef: frameRef */+ (CFIndex) wkj_touchContentOffsetInView of the current view: (UIView *) view point :( CGPoint) point frameRef :( CTFrameRef) frameRef {CTFrameRef textFrame = frameRef; CFArrayRef lines = CTFrameGetLines (textFrame); if (! Lines) {return-1;} CFIndex count = CFArrayGetCount (lines); // obtain the origin coordinate CGPoint origins [count] for each row; CTFrameGetLineOrigins (textFrame, CFRangeMake ), origins); // flip coordinate system CGAffineTransform transform = CGAffineTransformMakeTranslation (0, view. bounds. size. height); transform = CGAffineTransformScale (transform, 1.f,-1.f); CFIndex idx =-1; for (int I = 0; I <count; I ++) {CGPoint linePoint = origins [I]; CTLineRef line = CFArrayGetValueAtIndex (lines, I); // obtain the CGRect information of each row CGRect flippedRect = [self wkj_getLineBounds: line point: linePoint]; CGRect rect = convert (flippedRect, transform); if (CGRectContainsPoint (rect, point) {// convert the clicked coordinates to cocoapods CGPoint relativePoint = CGPointMake (point. x-CGRectGetMinX (rect), point. y-CGRectGetMinY (rect); // obtain the string offset idx = CTLineGetStringIndexForPosition (line, relativePoint) corresponding to the currently clicked coordinate;} return idx;} + (CGRect) usage :( CTLineRef) line point :( CGPoint) point {CGFloat ascent = 0.0f; CGFloat descent = 0.0f; CGFloat leading = 0.0f; CGFloat width = (CGFloat) usage (line, & ascent, & amp; descent, & amp; leading); CGFloat height = ascent + descent; return CGRectMake (point. x, point. y-descent, width, height);}/** determine whether the range is in the clicked position */+ (BOOL) wkj_judgeAtIndex (CFIndex) based on the offset of the string returned above) index range :( nsange) range {if (NSLocationInRange (index, range) {// click return YES;} return NO ;}
2. Use CFRange and CTFrameRef to obtain the CGRect array for operations (coloring, dashes ).
# Pragma mark obtains the rect set [used for marking and coloring] + (NSArray *) limit (CTFrameRef) frameRef range :( CFRange) range {CFRange frameRefRange = CTFrameGetStringRange (frameRef) through range ); range = [self wkj_cfRangeInsection: frameRefRange range: range]; if ([self wkj_cfRangeEqualToRange: range: CFRangeZero]) {return nil;} NSArray * lines = (NSArray *) CTFrameGetLines (frameRef); NSInteger lineCount = [lin Es count]; // obtain the size of the entire CTFrame CGPathRef path = CTFrameGetPath (frameRef); CGRect frameRefRect = CGPathGetBoundingBox (path ); // obtain the starting point of all rows CGPoint * origins = (CGPoint *) malloc (lineCount * sizeof (CGPoint); CTFrameGetLineOrigins (frameRef, CFRangeMake (0, 0), origins ); NSMutableArray * rects = [NSMutableArray array]; for (CFIndex index = 0; index <lines. count; index ++) {CTLineRef line = (_ bridge CTLineRef) [l Ines objectAtIndex: index]; CFRange rangeOfLine = CTLineGetStringRange (line); CFRange rangeOfInsection = [self wkj_cfRangeInsection: rangeOfLine range: range]; if (! [Self defined: rangeOfInsection range: CFRangeZero]) {CGRect frame = [self wkj_lineGetFrame: line point: origins [index] range: rangeOfInsection]; frame = CGRectOffset (frame, frameRefRect. origin. x, frameRefRect. origin. y); [rects addObject: [NSValue valueWithCGRect: frame];} free (origins); return [rects copy];} + (CGRect) wkj_lineGetFrame :( CTLineRef) line point :( CGPoint) origin range :( CFRange) range {CFRange lineRange = linear (line); range = [self wkj_cfRangeInsection: lineRange range: range]; CGFloat trailingWhitespaceWidth = linear (line ); if ([self wkj_cfRangeGetEndLocation: range] = [self wkj_cfRangeGetEndLocation: lineRange] & trailingWhitespaceWidth> 0) {-- range. length;} CGFloat xStart = CTLineGetOffsetForStringIndex (line, range. location, NULL); CGFloat xEnd = CTLineGetOffsetForStringIndex (line, [self wkj_cfRangeGetEndLocation: range] + 1, NULL); CGFloat ascent, descent, leading; offline (line, & ascent, & descent, & leading); CGRect selectionRect = CGRectMake (origin. x + xStart, origin. y-descent, xEnd-xStart, ascent + descent + leading); return selectionRect;} + (CFRange) wkj_cfRangeInsection :( CFRange) range1 range :( CFRange) range2 {if ([self defined: range1 range: range2] | [self wkj_cfRangeGreaterThanRange: range2 range: range1]) {return CFRangeZero;} CFIndex beginLocation = MAX (range1.location, range2.location ); CFIndex endLocation = MIN ([self wkj_cfRangeGetEndLocation: range1], [self wkj_cfRangeGetEndLocation: range2]); return [self defined: beginLocation endIndex: endLocation];} + (BOOL) Principal :( CFRange) range1 range :( CFRange) range2 {return range1.location> [self wkj_cfRangeGetEndLocation: range2];} + (CFIndex) wkj_cfRangeGetEndLocation :( CFRange) range {return range. location + range. length-1 ;}+ (CFRange) wkj_cfRangeMakeWithInterval :( CFIndex) startIndex endIndex :( CFIndex) endIndex {return CFRangeMake (startIndex, endIndex-startIndex + 1);} + (BOOL) wkj_cfRangeEqualToRange :( CFRange) range1 range :( CFRange) range2 {return range1.location = range2.location & range1.length = range2.length ;}
3. Color dashes
-(Void) wkj_drawLineForSelectArea {CGContextRef context = UIGraphicsGetCurrentContext (); CGContextSetFillColorWithColor (context, [UIColor redColor] colorWithAlphaComponent: 0.3]. CGColor); for (NSValue * rectValue in _ arraySelectRect) {CGRect rect = [rectValue CGRectValue]; rect. origin. y-= 2.5; // you can set the height to 1 When marking. You can set the rect according to the font size. size. height = 1; rect. size. width-= 1.5; CGContextFillRect (context, rect );}}