UITextView在iOS 7+截图不完整

2014-04-08 Xiaosong Gao 更多博文 » 博客 » GitHub »

iOS

原文链接 https://gaoxiaosong.github.io/2014/04/08/uitextview-crop-image.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


在使用iOS 7.1 SDK开发的时候,有一个ShareViewController,在viewDidLoad中需要添加一个UITextView控件,并且已经设置好了一段比较长的文本。代码如下:

- (void)viewDidLoad
{
  CGRect rcShareTextView = CGRectMake(0, 0, 290, 150);
  self.shareTextView = [self defaultShareTextView];
  _shareTextView.frame = rcShareTextView;
  [self.view addSubview:_shareTextView];
}

其中defaultShareTextView方法返回一个初始化并设置参数的UITextView。

而在另外一个方法中,需要Present出来这个ShareViewController,为了实现动画效果,需要在Present方法中实际操作之前先对ShareViewController进行截图,截图方法如下:

- (UIImage *)cropViewToImage:(UIView *)v
{
  UIGraphicsBeginImageContextWithOptions(v.bounds.size, NO, 0.0);
  [v.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return image;
}

但是截出来的图中UITextView控件中的文字只显示了一部分,而在移走截图并且进行实际的Present操作之后UITextView控件中文字又显示全了,所以现实情况是整个Present动画UITextView文字先显示上面一部分,后显示全部。

这个问题在iOS 7.0+的设备上才有,而在iOS 6.x的设备上却没有。

通过在ShareViewController中的viewDidLoad方法中添加断点,并输出UITextView控件的子视图,发现了问题:

(lldb) po [_shareTextView subviews]
<__NSArrayM 0xc8f7b90>(
<<_UITextContainerView: 0xc86d490; frame = (0 0; 290 67); layer = <_UITextTiledLayer: 0xc877de0>>
minSize = {290, 0}, maxSize = {3.4028235e+38, 3.4028235e+38}, textContainer = <NSTextContainer:
0xc890820 size = (290.000000,340282346638528859811704183484516925440.000000); widthTracksTextView
= YES; heightTracksTextView = NO>; exclusionPaths = 0x0; lineBreakMode = 0>
)

从这里,我们可以看出UITextView的frame高度为150,但是其内部的_UITextContainerView对象的高度仅有67,而在实际Present操作之后,_UITextContainerView对象的高度会自动调整到150,这样就会出现截图只有一部分文字的情况了。

在ShareViewController的viewDidLoad方法中继续添加如下代码,用来调整_UITextContainerView子控件的高度:

// 这段代码是在截图的时候调整UITextView内部的组件_UITextContainerView的大小
// 否则在iOS 7.0以上的时候,UITextView高度为150,而_UITextContainerView高度还不到其一半
// 这样会导致截图中文字只是一部分,所以需要手动修改_UITextContainerView的高度
NSArray * shareTextViewSubviews = [_shareTextView subviews];
for (UIView * subv in shareTextViewSubviews) {
  NSString * subvClass = NSStringFromClass([subv class]);
  if ([subvClass isEqualToString:@"_UITextContainerView"]) {
    CGRect rcSubV = subv.frame;
    rcSubV.size.height = SHARE_TEXT_VIEW_HEIGHT;
    subv.frame = rcSubV;
  }
}

这样就使得截图时的文字高度和实际Present操作后文字高度一致了,不会出现显示不连贯的问题。