Frage

ich einige Code in einer Ansicht haben, die etwas zurück Text mit Core zieht. Dabei Ich suche Urls und macht sie blau. Die Idee ist, nicht nur in all den Overhead eines UIWebView bringen anklickbare Links zu bekommen. Sobald ein Benutzer Taps auf diesem Link (nicht die gesamte Tabelle Ansicht Zelle), mag ich Feuer aus einem Delegatmethode der dann verwendet werden, um eine modale Ansicht zu präsentieren, die eine Web-Ansicht zu dieser URL gehen enthält.

Ich spare den Pfad und den String selbst als Instanzvariablen der Ansicht, und die Zeichnung Code geschieht in -drawRect: (ich habe es links der Kürze halber out).

aber meine Touch-Handler, während unvollständig, Druck ist nicht das, was ich zu erwarten habe. Es ist unter:

- (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
                }
            }
        }
    }
}

Es ist nicht der schönste Code im Moment, ich versuche immer noch, nur es funktioniert, so die Codequalität vergeben.

Das Problem, das ich habe, ist, dass, wenn ich außerhalb des Link tippen, was ich passieren würde erwarten, geschieht. Nichts wird ausgelöst,

Allerdings würde ich erwarten "Tapped line" gedruckt zu bekommen, wenn ich die gleiche Linie tippen Sie auf den Link auf, das nicht geschieht, und ich würde sowohl "Tapped line" und "Tapped run" erwarten erhalten gedruckt, wenn ich tippen Sie auf die URL.

Ich bin nicht sicher, wo diese weiter zu nehmen, die Ressourcen, die ich auf für die Auflösung sind spezifische Cocoa zu diesem Thema habe gesucht (die fast vollständig nicht anwendbar ist), oder fehlende Informationen zu diesem speziellen Fall.

Ich werde gerne Hinweise auf Unterlagen nehmen, die detailliert, wie man richtig über Erkennung gehen, wenn eine Berührung innerhalb der Grenzen eines Kerntextes aufgetreten Code Zeichnung über, aber an diesem Punkt, ich will nur dieses Problem beheben, so dass jede Hilfe wäre sehr dankbar.

UPDATE : Ich habe mein Problem zu einem Koordinaten Problem verengt. Ich habe die Koordinaten umgedreht (und nicht wie oben gezeigt) und das Problem, das ich habe, ist immer, dass Berührungen registrieren, wie ich erwarten würde, aber der Koordinatenraum wird umgedreht, und ich kann scheine es nicht zurück zu kippen.

War es hilfreich?

Lösung

Ich habe gerade dies getan, um den Zeichenfolge Index aus der Berührungsposition zu erhalten. Die Zeilennummer würde ich in diesem Fall sein:

- (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);
}

Andere Tipps

Sie könnten versuchen, Ihren Text Zeichnung in eine CALayer hinzuzufügen, fügen Sie diese neue Ebene als Unterschicht Ihrer Ansichten Schicht und hittest dagegen in Ihrem touchesEnded? Wenn Sie dies tun, sollten Sie in der Lage sein, einen größeren berührbaren Bereich zu schaffen, indem die Schicht größer als der gezeichneten Text zu machen.

// hittesting 
UITouch *touch = [[event allTouches] anyObject];
touchedLayer = (CALayer *)[self.layer hitTest:[touch locationInView:self]];

Swift 3-Version von Nick H247 Antwort:

var ctFrame: CTFrame?

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, let ctFrame = self.ctFrame else { return }

    let pnt = touch.location(in: self.view)
    let reversePoint = CGPoint(x: pnt.x, y: self.frame.height - pnt.y)
    let lines = CTFrameGetLines(ctFrame) as [AnyObject] as! [CTLine]

    var lineOrigins = [CGPoint](repeating: .zero, count: lines.count)
    CTFrameGetLineOrigins(ctFrame, CFRange(location: 0, length: 0), &lineOrigins)

    for (i, line) in lines.enumerated() {
        let origin = lineOrigins[i]

        if reversePoint.y > origin.y {
            let index = CTLineGetStringIndexForPosition(line, reversePoint)
            print("index \(index)")
            break
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top