7.8 C
London
Friday, April 26, 2024

iOS Orphaned Phrases difficulty


I’ve expandable label. Once I tapped to "daha fazla" label, I present to full textual content in label. Usually it really works nicely however on this case it does not work. Once I present to attributed string in label, it exhibits third and final lane completely different than CTFrame.
That is how textual content seems in my label.
enter image description here

Right here is my ctFrame log. Once I logged, third and final lane it seems completely different than label.
enter image description here

Right here is my calculating code.

func characterIndex(at touchPoint: CGPoint) -> Int {

    guard let attributedString = attributedText, bounds.comprises(touchPoint) else {
        return NSNotFound
    }

    let textRect = self.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
    
    if !textRect.comprises(touchPoint) {
        return NSNotFound
    }

    // Offset faucet coordinates by textRect origin to make them relative to the origin of body
    // Convert faucet coordinates (begin at prime left) to CT coordinates (begin at backside left)
    let level = CGPoint(x: touchPoint.x - textRect.origin.x,
                        y: textRect.dimension.top - (touchPoint.y - textRect.origin.y))
    
    let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
    let suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
                                                                     CFRangeMake(0, attributedString.size),
                                                                     nil,
                                                                     CGSize(width: textRect.width, top: CGFloat.greatestFiniteMagnitude),
                                                                     nil)

    let path = CGMutablePath()
    path.addRect(CGRect(x: 0, y: 0, width: suggestedSize.width, top: CGFloat(ceilf(Float(suggestedSize.top)))))

    let ctFrame = CTFramesetterCreateFrame(framesetter, CFRange(), path, nil)
    let frameLines = CTFrameGetLines(ctFrame)
    let linesCount = numberOfLines > 0 ? min(numberOfLines, CFArrayGetCount(frameLines)) : CFArrayGetCount(frameLines)

    if linesCount.cgFloatValue.isZero {
        return NSNotFound
    }

    var lineOrigins = [CGPoint](repeating: .zero, depend: linesCount)
    CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, linesCount), &lineOrigins)

    for (idx, lineOrigin) in lineOrigins.enumerated() {
        var newLineOrigin = lineOrigin
        let lineIndex = CFIndex(idx)
        let line = unsafeBitCast(CFArrayGetValueAtIndex(frameLines, lineIndex), to: CTLine.self)

        // Get bounding info of line
        var ascent: CGFloat = 0.0
        var descent: CGFloat = 0.0
        var main: CGFloat = 0.0
        let width = CGFloat(CTLineGetTypographicBounds(line, &ascent, &descent, &main))
        let yMin = CGFloat(ground(lineOrigin.y - descent))
        let yMax = CGFloat(ceil(lineOrigin.y + ascent))

        // Apply penOffset utilizing flushFactor for horizontal alignment to set lineOrigin since that is the horizontal offset from drawFramesetter
        let flushFactor = flushFactorForTextAlignment(textAlignment: textAlignment)
        let penOffset = CGFloat(CTLineGetPenOffsetForFlush(line, flushFactor, Double(textRect.dimension.width)))
        newLineOrigin.x = penOffset

        // Examine if we have already handed the road
        if level.y > yMax {
            return NSNotFound
        }

        // Examine if the purpose is inside this line vertically
        if level.y >= yMin && level.x >= lineOrigin.x && level.x <= lineOrigin.x + width {
            // Convert CT coordinates to line-relative coordinates
            let relativePoint = CGPoint(x: level.x - lineOrigin.x, y: level.y - lineOrigin.y)
            return Int(CTLineGetStringIndexForPosition(line, relativePoint))
        }
    }

    return NSNotFound
}
Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here