2012-07-17 57 views
2

下面是我使用和模拟器iOS 5以上工作正常,但在模拟器4.3问题中的UITextView beginningOfDocument的的iOS 4.3

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

继给问题的代码是错误的语句:

终止应用程序由于未捕获的异常 'NSInvalidArgumentException',原因: ' - [UITextView的beginningOfDocument]:无法识别的选择发送到实例0x5586050'

有人可以就此提供建议吗?提前致谢!

回答

1

UITextInput协议包括自iOS 3.2以来的beginningOfDocument选择器。
UITextView自iOS 5.0以来只采用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); 

} 
+0

谢谢。但是,这是什么解决方案。任何想法? – Nats 2012-07-17 10:35:51

+0

@Nats我编辑了答案来做可用性检查。现在,我猜你必须编写一些代码才能在iOS 4上执行相同的计算。 – Jilouc 2012-07-17 10:56:09

+0

谢谢......但实际上我的问题是我想要得到文本的矩形,下面是我在iOS 5中工作的代码。 UITextPosition * begin = [self.tvQuestion positionFromPosition:0 offset:nrange.location]; UITextPosition * end = [self.tvQuestion positionFromPosition:begin offset:nrange.length]; UITextRange * textRange = [self.tvQuestion textRangeFromPosition:begin toPosition:end]; CGRect newRect = [self.tvQuestion firstRectForRange:textRange]; 如何在iOS 4中做同样的事情是一个问题:)? – Nats 2012-07-17 11:11:28

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