将点击事件添加到IOS NSMutableAttributedString

我有一个NSMutableAttributedString,如“鲍勃喜欢你的照片”。

我想知道是否可以添加两个不同的点击事件“鲍勃”和“图片”。 理想情况下,点击“Bob”会显示一个新的视图控制器与鲍勃的configuration文件和点击“图片”会呈现一个新的视图控制器的图片。 我可以做到这一点与NSMutableAttributedString?

我将处理它的方式是在UITextView使用标准的NSString 。 然后利用UITextInput协议方法firstRectForRange: 然后,你可以很容易地在这个矩形覆盖一个不可见的UIButton ,并处理你想要采取的行动。

你可以通过使用CoreText实现一个方法来获取用户select/触摸的字符的索引。 首先,使用CoreText,在自定义UIView子类中绘制属性string。 覆盖drawRect:方法的示例:

 - (void) drawRect:(CGRect)rect { // Flip the coordinate system as CoreText's origin starts in the lower left corner CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, 0.0f, self.bounds.size.height); CGContextScaleCTM(context, 1.0f, -1.0f); UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.bounds]; CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(_attributedString)); if(textFrame != nil) { CFRelease(textFrame); } // Keep the text frame around. textFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path.CGPath, NULL); CFRetain(textFrame); CTFrameDraw(textFrame, context); } 

其次,创build一个查询文本的方法来查找给定点的字符索引:

 - (int) indexAtPoint:(CGPoint)point { // Flip the point because the coordinate system is flipped. point = CGPointMake(point.x, CGRectGetMaxY(self.bounds) - point.y); NSArray *lines = (__bridge NSArray *) (CTFrameGetLines(textFrame)); CGPoint origins[lines.count]; CTFrameGetLineOrigins(textFrame, CFRangeMake(0, lines.count), origins); for(int i = 0; i < lines.count; i++) { if(point.y > origins[i].y) { CTLineRef line = (__bridge CTLineRef)([lines objectAtIndex:i]); return CTLineGetStringIndexForPosition(line, point); } } return 0; } 

最后,您可以覆盖touchesBegan:withEvent:方法来获取用户所在位置,并将其转换为字符索引或范围:

 - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *t = [touches anyObject]; CGPoint tp = [t locationInView:self]; int index = [self indexAtPoint:tp]; NSLog(@"Character touched : %d", index); } 

一定要将CoreText包含到您的项目中,并清理您保留的所有资源(如文本框架),因为该内存不由ARCpipe理。