需要将UITextView的全部内容渲染成PDF文件

3
我有以下方法,在我的@implementation UIView (SaveToPdf)类中运行良好。
- (NSData *) toPdfData
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];

// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, self.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();


// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[self.layer renderInContext:pdfContext];

// remove PDF rendering context
UIGraphicsEndPDFContext();

return pdfData;
}

我使用这种方法将我的视图打印到PDF中,它运行良好,除了一个问题。我的视图包含一个UITextView,但PDF只打印该UITextView的可见区域。我需要PDF呈现全部内容(即可滚动文本)。
我是iOS开发的新手,如果有人能指点我正确的方向,我将不胜感激。
*请注意,我在UIView中还有其他子视图(标签、文本框等)需要打印到PDF中。目前这个功能已经正常工作,并且通过使用[self.layer renderInContext:pdfContext];保留布局,因为主视图将循环遍历所有子视图。
谢谢。

你需要创建PDF绘制线条和矩形,然后可以保存为PDF文件。你可以得到这个。 - Nitin Gohel
为什么会有踩票?试图对新手友好。为了补偿踩票而进行点赞... - Srikar Appalaraju
3个回答

1
如果您希望在页面上绘制尽可能多的文本,并且您遇到了UITextView中的文本被截断的问题,那么您需要禁用UITextView的滚动。可以在Interface Builder或以编程方式实现:
textview.scrollEnabled = NO;

当scrollEnabled设置为YES时,我的PDF文本被截断了。没有滚动,我可以得到整个文本 - 至少尽可能多地适合一页的内容。
如果您需要在多个页面上生成文本,则我认为您必须采用其他答案所示的方法将元素单独绘制到PDF绘图上下文中。

1

我知道两种方法 -

  1. 我看过一些代码,其中使用了 [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];。当我尝试时,我发现它会导致文本清晰度降低。所以我不能使用这种方法。
  2. 这是更传统的方法。即提取文本并绘制它。这段代码非常可靠,并且已经被使用过。所以你只需要从你的 uitextview 中获取所有文本并将其传递到这里...

希望这可以帮助你。

#define kBorderInset 25.0
#define kMarginInset 15.0

- (void) drawText
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(currentContext, 0.0, 0.0, 0.0, 1.0);

NSString *textToDraw = @"YOUR TEXT FROM UITEXTVIEW HERE";
UIFont *font = [UIFont systemFontOfSize:16.0];

CGSize stringSize = [textToDraw sizeWithFont:font
                           constrainedToSize:CGSizeMake(pageSize.width - 2*kBorderInset-2*kMarginInset, pageSize.height - 2*kBorderInset - 2*kMarginInset) 
                               lineBreakMode:UILineBreakModeWordWrap];

CGRect renderingRect = CGRectMake(kBorderInset + kMarginInset, kBorderInset + kMarginInset + 350.0, pageSize.width - 2*kBorderInset - 2*kMarginInset, stringSize.height);

[textToDraw drawInRect:renderingRect 
              withFont:font
         lineBreakMode:UILineBreakModeWordWrap
             alignment:UITextAlignmentLeft];
return;
}

感谢您的快速回答,Srikar。我需要注意的一件事是,我的UIView除了UITextView之外还有其他东西...我有标签、文本字段等等... [self.layer renderInContext:pdfContext]; 递归地打印所有子视图,这使得事情变得容易。话虽如此,当UITextView即将被渲染时,我该如何触发此代码...并保留其余子视图不变呢? - hhaddad

0
我已经编写了这段代码,可以从UIView内容生成PDF。希望这能帮到你。
#define kBorderInset            20.0
#define kBorderWidth            1.0
#define kMarginInset            10.0

//Line drawing
#define kLineWidth              1.0

    - (IBAction)generatePdfButtonPressed
{
 pageSize = CGSizeMake(612, 792);
 NSString *fileName = @"profileInfo.pdf";
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];

 [self generatePdfWithFilePath:pdfFileName];
}

- (void) generatePdfWithFilePath: (NSString *)thefilePath
{
 UIGraphicsBeginPDFContextToFile(thefilePath, CGRectZero, nil);

 NSInteger currentPage = 0;
 BOOL done = NO;
 do
 {
  // Mark the beginning of a new page.
  UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, pageSize.width, pageSize.height), nil);

  // Draw a page number at the bottom of each page.
  currentPage++;
  [self drawPageNumber:currentPage];

  //Draw a border for each page.
  [self drawBorder];

  //Draw text fo our header.
  [self drawHeader];

  //Draw a line below the header.
  [self drawLine];

  //Draw some text for the page.
  if (profileInfo!=nil) 
  {
   NSString *stringwithInfo=[NSString stringWithFormat:@"Headline: %@\nFirstname: %@\nLastName : %@\nSiteStandardProfileRequest:\n%@",[profileInfo valueForKey:@"headline"],[profileInfo valueForKey:@"firstName"],[profileInfo valueForKey:@"lastName"],[[profileInfo valueForKey:@"siteStandardProfileRequest"]valueForKey:@"url"]];


   [self drawText:stringwithInfo];
  }

  //Draw an image
  [self drawImage];
  done = YES;
 }
 while (!done);

 // Close the PDF context and write the contents out.
 UIGraphicsEndPDFContext();
}

- (void) drawBorder
{
 CGContextRef    currentContext = UIGraphicsGetCurrentContext();
 UIColor *borderColor = [UIColor brownColor];
 CGRect rectFrame = CGRectMake(kBorderInset, kBorderInset, pageSize.width-kBorderInset*2, pageSize.height-kBorderInset*2);
 CGContextSetStrokeColorWithColor(currentContext, borderColor.CGColor);
 CGContextSetLineWidth(currentContext, kBorderWidth);
 CGContextStrokeRect(currentContext, rectFrame);
}


- (void) drawLine
{
 CGContextRef    currentContext = UIGraphicsGetCurrentContext();

 CGContextSetLineWidth(currentContext, kLineWidth);

 CGContextSetStrokeColorWithColor(currentContext, [UIColor blueColor].CGColor);

 CGPoint startPoint = CGPointMake(kMarginInset + kBorderInset, kMarginInset + kBorderInset + 40.0);
 CGPoint endPoint = CGPointMake(pageSize.width - 2*kMarginInset -2*kBorderInset, kMarginInset + kBorderInset + 40.0);

 CGContextBeginPath(currentContext);
 CGContextMoveToPoint(currentContext, startPoint.x, startPoint.y);
 CGContextAddLineToPoint(currentContext, endPoint.x, endPoint.y);

 CGContextClosePath(currentContext);
 CGContextDrawPath(currentContext, kCGPathFillStroke);
}


- (void) drawText:(NSString*)txtTodraw
{
 CGContextRef    currentContext = UIGraphicsGetCurrentContext();
 CGContextSetRGBFillColor(currentContext, 0.0, 0.0, 0.0, 1.0);

 UIFont *font = [UIFont systemFontOfSize:14.0];

 CGSize stringSize = [txtTodraw sizeWithFont:font
                            constrainedToSize:CGSizeMake(pageSize.width - 2*kBorderInset-2*kMarginInset, pageSize.height - 2*kBorderInset - 2*kMarginInset)
                                lineBreakMode:UILineBreakModeWordWrap];

 CGRect renderingRect = CGRectMake(kBorderInset + kMarginInset, kBorderInset + kMarginInset + 50.0, pageSize.width - 2*kBorderInset - 2*kMarginInset, stringSize.height);

 [txtTodraw drawInRect:renderingRect
               withFont:font
          lineBreakMode:UILineBreakModeWordWrap
              alignment:UITextAlignmentLeft];
}


- (void) drawImage
{
 UIImage * demoImage = [UIImage imageNamed:@"demo.png"];
 [demoImage drawInRect:CGRectMake( (pageSize.width - demoImage.size.width/2)/2, 350, demoImage.size.width/2, demoImage.size.height/2)];
}


- (void) drawHeader
{
 CGContextRef    currentContext = UIGraphicsGetCurrentContext();
 CGContextSetRGBFillColor(currentContext, 0.3, 0.7, 0.2, 1.0);

 NSString *textToDraw = @"LinkedIn Profile Info";

 UIFont *font = [UIFont systemFontOfSize:24.0];

 CGSize stringSize = [textToDraw sizeWithFont:font constrainedToSize:CGSizeMake(pageSize.width - 2*kBorderInset-2*kMarginInset, pageSize.height - 2*kBorderInset - 2*kMarginInset) lineBreakMode:UILineBreakModeWordWrap];

 CGRect renderingRect = CGRectMake(kBorderInset + kMarginInset, kBorderInset + kMarginInset, pageSize.width - 2*kBorderInset - 2*kMarginInset, stringSize.height);

 [textToDraw drawInRect:renderingRect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
}


- (void)drawPageNumber:(NSInteger)pageNumber
{
 NSString* pageNumberString = [NSString stringWithFormat:@"Page %d", pageNumber];
 UIFont* theFont = [UIFont systemFontOfSize:12];

 CGSize pageNumberStringSize = [pageNumberString sizeWithFont:theFont
                                            constrainedToSize:pageSize
                                                lineBreakMode:UILineBreakModeWordWrap];

 CGRect stringRenderingRect = CGRectMake(kBorderInset,
                                         pageSize.height - 40.0,
                                         pageSize.width - 2*kBorderInset,
                                         pageNumberStringSize.height);

 [pageNumberString drawInRect:stringRenderingRect withFont:theFont lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentCenter];
}

-(void)fillInformationInform:(NSDictionary*)dics
{
 headLineLabel.text=[dics valueForKey:@"headline"];
 NSURL *picUrl=[NSURL URLWithString:[dics valueForKey:@"pictureUrl"]];
 profileImageView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:picUrl]];

 phoneNoLabel.text=[[[[dics valueForKey:@"phoneNumbers"] valueForKey:@"values"] objectAtIndex:0] valueForKey:@"phoneNumber"];

 cityLabel.text=[[dics valueForKey:@"location"] valueForKey:@"name"];
 emailAddressLabel.text=[dics valueForKey:@"emailAddress"];
 nameLabel.text=[NSString stringWithFormat:@"%@ %@",[dics valueForKey:@"firstName"],[dics valueForKey:@"lastName"]];

 dateOfBirthLabel.text=[NSString stringWithFormat:@"%@-%@-%@",[[dics valueForKey:@"dateOfBirth"]valueForKey:@"day"],[[dics valueForKey:@"dateOfBirth"]valueForKey:@"month"],[[dics valueForKey:@"dateOfBirth"]valueForKey:@"year"]];

 NSDictionary *eduDic=[[NSDictionary alloc] initWithDictionary:[[[dics valueForKey:@"educations"]valueForKey:@"values"]objectAtIndex:0]];

// NSLog(@"education dic is %@",eduDic);

 degreeLabel.text=[eduDic valueForKey:@"degree"];
 durationLabel.text=[NSString stringWithFormat:@"From %@ To %@",[[eduDic valueForKey:@"startDate"]valueForKey:@"year"],[[eduDic valueForKey:@"endDate"]valueForKey:@"year"]];
 fieldOfStudyLabel.text=[eduDic valueForKey:@"fieldOfStudy"];
 collegeLabel.text=[eduDic valueForKey:@"schoolName"];


 destinationLabel.text=[[[[dics valueForKey:@"positions"] valueForKey:@"values"] objectAtIndex:0] valueForKey:@"title"];

 NSArray *skillsArray=[[NSArray alloc] initWithArray:[[dics valueForKey:@"skills"]valueForKey:@"values"]];


 NSString *skillStr=[[NSString alloc] initWithFormat:@""];

 for (NSDictionary *skillDic in skillsArray) 
 {
  if (![skillStr isEqualToString:@""]) {
   skillStr=[skillStr stringByAppendingFormat:@","];
  }
  skillStr=[skillStr stringByAppendingFormat:@"%@",[[skillDic valueForKey:@"skill"]valueForKey:@"name"]];
 }

 NSLog(@"skill string is %@",skillStr);

 skillsLable.text=[NSString stringWithFormat:@"%@",skillStr];

}

谢谢Hercules。我可能会退而求其次,但我希望避免的唯一问题是手动渲染PDF的每个元素。我的视图包含图像、标签、文本等...这样做意味着我需要自己重新绘制整个布局在PDF中,并将所有内容按照视图中的方式进行排列/定位...对吗? - hhaddad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接