我在视图中有一些代码,它使用CoreText绘制一些属性文本.在这里,我正在搜索网址并将其设为蓝色.我们的想法是不要UIWebView
为了获得可点击链接而带来所有开销.一旦用户点击该链接(而不是整个表视图单元格),我想触发一个委托方法,然后该方法将用于呈现一个模态视图,其中包含一个转到该URL的Web视图.
我将路径和字符串本身保存为视图的实例变量,并且绘图代码发生在-drawRect:
(我为了简洁而将其遗漏).
然而,我的触摸处理程序虽然不完整,却没有打印出我期望它的内容.它在下面:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; CGContextRef context = UIGraphicsGetCurrentContext(); NSLog(@"attribString = %@", self.attribString); CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attribString); CTFrameRef ctframe = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, self.attribString.length), attribPath, NULL); CFArrayRef lines = CTFrameGetLines(ctframe); for(CFIndex i = 0; i < CFArrayGetCount(lines); i++) { CTLineRef line = CFArrayGetValueAtIndex(lines, i); CGRect lineBounds = CTLineGetImageBounds(line, context); // Check if tap was on our line if(CGRectContainsPoint(lineBounds, point)) { NSLog(@"Tapped line"); CFArrayRef runs = CTLineGetGlyphRuns(line); for(CFIndex j = 0; j < CFArrayGetCount(runs); j++) { CTRunRef run = CFArrayGetValueAtIndex(runs, j); CFRange urlStringRange = CTRunGetStringRange(run); CGRect runBounds = CTRunGetImageBounds(run, context, urlStringRange); if(CGRectContainsPoint(runBounds, point)) { NSLog(@"Tapped run"); CFIndex* buffer = malloc(sizeof(CFIndex) * urlStringRange.length); CTRunGetStringIndices(run, urlStringRange, buffer); // TODO: Map the glyph indices to indexes in the string & Fire the delegate } } } } }
这不是目前最漂亮的代码,我仍然试图让它工作,所以原谅代码质量.
我遇到的问题是当我点击链接之外时,我预期会发生什么,发生:什么都没有被解雇.
但是,我希望"Tapped line"
,如果我点击同一行链路上,这不会发生,而且我希望既得到印刷"Tapped line"
及"Tapped run"
如果我在URL上点击来获得打印.
我不确定在哪里进一步采取这种方式,我为解决这个问题而考虑的资源是Cocoa特定的(几乎完全不适用),或者缺乏关于这个特定情况的信息.
我很乐意接受文档的指示,详细说明如何正确地检测是否在代码的核心文本绘图范围内发生了触摸,但此时,我只是想解决这个问题,所以任何帮助都会很大赞赏.
更新:我已将问题缩小到一个坐标问题.我已经翻转了坐标(而不是如上所示),我得到的问题是按照我的预期触及寄存器,但是坐标空间被翻转,我似乎无法将其翻转.
我刚刚完成此操作以从触摸位置获取字符串字符索引.在这种情况下,行号将是i:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"touch ended"); UITouch* touch = [touches anyObject]; CGPoint pnt = [touch locationInView:self]; CGPoint reversePoint = CGPointMake(pnt.x, self.frame.size.height-pnt.y); CFArrayRef lines = CTFrameGetLines(ctFrame); CGPoint* lineOrigins = malloc(sizeof(CGPoint)*CFArrayGetCount(lines)); CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins); for(CFIndex i = 0; i < CFArrayGetCount(lines); i++) { CTLineRef line = CFArrayGetValueAtIndex(lines, i); CGPoint origin = lineOrigins[i]; if (reversePoint.y > origin.y) { NSInteger index = CTLineGetStringIndexForPosition(line, reversePoint); NSLog(@"index %d", index); break; } } free(lineOrigins); }