Пара вещей ...
Во-первых, во время генерации CoreGraphics PDF в iOS существует ошибка, которая приводит к повреждению PDF-файлов. Я знаю, что эта проблема существует вплоть до iOS 4.1 (включая iOS 4.2). Эта проблема связана со шрифтами и появляется только в том случае, если вы включили текст в свой PDF. Симптом заключается в том, что при создании PDF вы увидите ошибки в консоли отладки, которые выглядят так:
<Error>: can't get CIDs for glyphs for 'TimesNewRomanPSMT'
Сложный аспект заключается в том, что полученный PDF-файл будет хорошо отображаться в некоторых программах чтения PDF-файлов, но не будет отображаться в других местах. Таким образом, если у вас есть контроль над программным обеспечением, которое будет использоваться для открытия вашего PDF-файла, вы можете игнорировать эту проблему (например, если вы намереваетесь отображать PDF-файл только на настольных компьютерах iPhone или Mac, тогда у вас должно получиться CoreGraphics). Однако, если вам нужно создать PDF-файл, который работает где угодно, вам следует более внимательно изучить эту проблему. Вот дополнительная информация:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/15505-pdf-font-problem-cant-get-cids-glyphs.html#post97854
В качестве обходного пути я успешно использовал libHaru на iPhone в качестве замены для создания CoreGraphics PDF. Сначала было сложно создать libHaru с моим проектом, но как только я правильно настроил свой проект, он отлично работал для моих нужд.
Во-вторых, в зависимости от формата / макета вашего PDF, вы можете рассмотреть возможность использования Interface Builder для создания представления, которое служит «шаблоном» для вывода PDF. Затем вы должны написать код для загрузки представления, заполнить любые данные (например, задать текст для UILabels и т. Д.), А затем отобразить отдельные элементы представления в PDF. Другими словами, используйте IB для указания координат, шрифтов, изображений и т. Д. И пишите код для рендеринга различных элементов (например, UILabel
, UIImageView
и т. Д.) В общем виде, так что вам не придется трудо закодируйте все Я использовал этот подход, и он отлично подошел для моих нужд. Опять же, это может иметь или не иметь смысла для вашей ситуации в зависимости от потребностей форматирования / макета вашего PDF.
РЕДАКТИРОВАТЬ: (ответ на 1-й комментарий)
Моя реализация является частью коммерческого продукта, то есть я не могу поделиться полным кодом, но могу дать общую схему:
Я создал файл .xib с представлением и изменил размер представления до 850 x 1100 (мой PDF был нацелен на 8,5 x 11 дюймов, так что это облегчает перевод в / из координат времени разработки).
В коде загружаю вид:
- (UIView *)loadTemplate
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ReportTemplate" owner:self options:nil];
for (id view in nib) {
if ([view isKindOfClass: [UIView class]]) {
return view;
}
}
return nil;
}
Затем я заполняю различные элементы. Я использовал теги, чтобы найти соответствующие элементы, но вы могли бы сделать это другими способами. Пример: * +1028 *
UILabel *label = (UILabel *)[templateView viewWithTag:TAG_FIRST_NAME];
if (label != nil) {
label.text = (firstName != nil) ? firstName : @"None";
Затем я вызываю функцию для рендеринга представления в файл PDF. Эта функция рекурсивно обходит иерархию представления и отображает каждое подпредставление. Для моего проекта мне нужно поддерживать только Label, ImageView и View (для вложенных представлений):
- (void)addObject:(UIView *)view
{
if (view != nil && !view.hidden) {
if ([view isKindOfClass:[UILabel class]]) {
[self addLabel:(UILabel *)view];
} else if ([view isKindOfClass:[UIImageView class]]) {
[self addImageView:(UIImageView *)view];
} else if ([view isKindOfClass:[UIView class]]) {
[self addContainer:view];
}
}
}
В качестве примера, вот моя реализация addImageView (функции HPDF_ из libHaru):
- (void)addImageView:(UIImageView *)imageView
{
NSData *pngData = UIImagePNGRepresentation(imageView.image);
if (pngData != nil) {
HPDF_Image image = HPDF_LoadPngImageFromMem(_pdf, [pngData bytes], [pngData length]);
if (image != NULL) {
CGRect destRect = [self rectToPDF:imageView.frame];
float x = destRect.origin.x;
float y = destRect.origin.y - destRect.size.height;
float width = destRect.size.width;
float height = destRect.size.height;
HPDF_Page page = HPDF_GetCurrentPage(_pdf);
HPDF_Page_DrawImage(page, image, x, y, width, height);
}
}
}
Надеюсь, это даст вам идею.