2

以下は、シミュレータiOS 5以降で使用して正常に動作しているコードですが、シミュレータ4.3で問題が発生しています

UITextPosition *begin = [self.tvQuestion positionFromPosition:self.tvQuestion.beginningOfDocument offset:nrange.location];

以下はエラーステートメントです。

キャッチされない例外 'NSInvalidArgumentException'、理由: '-[UITextView beginOfDocument]: 認識されないセレクターがインスタンス 0x5586050 に送信されたため、アプリを終了しています

誰かがこれについてアドバイスできますか?前もって感謝します!

4

2 に答える 2

1

UITextInputプロトコルには、beginningOfDocumentiOS 3.2 以降のセレクターが含まれています。
ただし、iOS 5.0 以降UITextViewでのみ採用されています。UITextInput以前はUITextInputTraitsプロトコルに準拠していました。

ソース: ここで UITextView を検索してくださいhttp://developer.apple.com/library/ios/#releasenotes/General/iOS50APIDiff/index.html

iOS 4.x 以降で動作させたい場合は、チェックを実行し、iOS 4 で自分で計算を行う必要があります。

CGRect newRect = CGRectZero;

if ([UITextView conformsToProtocol:@protocol(UITextInput)]) {

    // iOS 5 and later
    UITextPosition *begin = [self.tvQuestion positionFromPosition:self.tvQuestion.beginningOfDocument offset:nrange.location]; 
    UITextPosition *end = [self.tvQuestion positionFromPosition:begin offset:nrange.length]; 
    UITextRange *textRange = [self.tvQuestion textRangeFromPosition:begin toPosition:end]; 
    newRect = [self.tvQuestion firstRectForRange:textRange];

} else {

    // iOS 3.2 to 4.3
    // Compute text position manually

#define TEXT_VIEW_PADDING 8.f

    NSString *textContent = [self.tvQuestion.text substringToIndex:NSMaxRange(nrange)];

    NSDictionary *ctFontDescriptorAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                                self.tvQuestion.font.familyName, kCTFontFamilyNameAttribute,
                                                // Uncomment for bold fonts
                                                // [NSDictionary dictionaryWithObjectsAndKeys:
                                                // [NSNumber numberWithInt:kCTFontBoldTrait], kCTFontSymbolicTrait,
                                                // nil], kCTFontTraitsAttribute,
                                                nil];

    CTFontDescriptorRef ctFontDescriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)ctFontDescriptorAttributes);
    CTFontRef ctFont = CTFontCreateWithFontDescriptor(ctFontDescriptor, self.tvQuestion.font.pointSize, NULL);

    NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:textContent
                                                                         attributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                                                 (id)ctFont, kCTFontAttributeName,
                                                                                 nil]];

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedText);
    CFRange globalRange = CFRangeMake(0, [attributedText length]);

    CGRect textRect = CGRectInset((CGRect){CGPointZero, self.tvQuestion.contentSize}, TEXT_VIEW_PADDING, TEXT_VIEW_PADDING);
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, globalRange, CGPathCreateWithRect((CGRect){CGPointZero, textRect.size}, NULL), NULL);

    CFArrayRef lines = CTFrameGetLines(frame);
    NSInteger nbLines = CFArrayGetCount(lines);
    CGPoint *lineOrigins = calloc(sizeof(CGPoint), nbLines);
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);

    CGFloat ascent = CTFontGetAscent(ctFont);
    CGFloat descent = CTFontGetDescent(ctFont);
    CGFloat leading = CTFontGetLeading(ctFont);

    if (leading < 0) {
        leading = 0;
    }
    leading = floor(leading + 0.5);

    CGFloat lineHeight = floor(ascent + 0.5) + floor(descent + 0.5) + leading;
    CGFloat firstLineYOffset = 0.f;

    for (NSInteger i = 0; i < nbLines; i++) {

        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CFRange lineRange = CTLineGetStringRange(line);
        CGPoint lineOrigin = lineOrigins[i];
        CGFloat ascent, descent, leading, width;
        width = CTLineGetTypographicBounds(line, &ascent,  &descent, &leading);

        if (i == 0) {
            firstLineYOffset = lineOrigin.y;
        }
        lineOrigin.y = (lineOrigin.y - firstLineYOffset) * -1.f;


        if (nrange.location >= lineRange.location && nrange.location < lineRange.location + lineRange.length) {

            CGFloat secOffset;
            CGFloat startOffset = CTLineGetOffsetForStringIndex(line, nrange.location, &secOffset);

            CGFloat rectWidth;
            if (nrange.location + nrange.length <= lineRange.location + lineRange.length) {
                CGFloat endOffset = CTLineGetOffsetForStringIndex(line, nrange.location + nrange.length, &secOffset);
                rectWidth = endOffset - startOffset;
            } else {
                rectWidth = width - 5 - startOffset;
            }

            newRect = (CGRect)
            {
                {
                    lineOrigin.x + TEXT_VIEW_PADDING + startOffset,
                    lineOrigin.y + TEXT_VIEW_PADDING + i
                }, {
                    rectWidth,
                    lineHeight
                }
            };

            break;
        }
    }

    free(lineOrigins);
    CFRelease(frame);
    CFRelease(framesetter);
    CFRelease(ctFont);
    CFRelease(ctFontDescriptor);

}
于 2012-07-17T10:24:53.557 に答える
0

UITextView は iOS 4.x の UITextInput プロトコルに準拠していませんが、そのサブビューは準拠しています。次のコードは iOS 4.x 以降で動作します。

UIView<UITextInput> *t = [textView.subviews objectAtIndex:0];
assert([t conformsToProtocol:@protocol(UITextInput)]);
// use t for the view conforming to UITextInput
UITextPosition *beginning = t.beginningOfDocument; // OK
于 2012-09-26T06:13:00.863 に答える