UIMarkupTextPrintFormatter druckt keine HTML <img>

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

Aufgrund der Corona-Krise: Die Veröffentlichung von Stellenangeboten und -gesuchen ist bis 31.12.2020 kostenfrei. Das beinhaltet auch Angebote und Gesuche von und für Freischaffende und Selbstständige.

  • UIMarkupTextPrintFormatter druckt keine HTML <img>

    Hallo zusammen,

    ich bin ganz neu hier im Forum weil ich schon öfter bei der Problemlösung von Objective-C auf das Forum gestoßen bin und nun selber an einer Stelle nicht weiter komme.
    Ich arbeite gerade an einer iPad App, mit der man einen Warenkorb befüllen kann und am Ende die Möglichkeit haben soll sich über AirPrint eine Bestellbestätigung ausdrucken zu können. Da man das ganze eventuell auch per E-Mail senden soll, gehe ich einen kleinen "Umweg" über PDF.

    Ich habe mir eine eigene Subclass von UIPrintPageRenderer gebaut, in die ich im Header und Footer einzelne Objekte zeichnen kann und im Content Bereich verwende ich ein HTML Template zum generieren der Positionen des Warenkorbs.

    Das HTML Template ist eine ganz einfache HTML-Table in der dann einfach Strings ersetzt werden.

    Hier die Methode die das PDF generiert und dann dieses an den Drucker übergibt:

    HTML-Quellcode

    1. - (IBAction)startPDFPrinting:(id)sender {
    2. // Controller for pdf generating
    3. UIPrintInfo *printInfo = [UIPrintInfo printInfo];
    4. printInfo.jobName = [NSString stringWithFormat:@"Druck von Beleg: %@ - %@", AppDelegateX.currentBelegNr, [AppDelegateX returnCurrentGermanDateString]];
    5. printInfo.duplex = UIPrintInfoOrientationPortrait;
    6. printInfo.outputType = UIPrintInfoOutputGeneral;
    7. //> !IMPORTANT! all the printing stuff have to be done in cm not in points or pixels
    8. // Renderer
    9. PrintRenderer *printer = [[PrintRenderer alloc] initWithHeaderSize:13.3 andFooter:2.3 andSize:CGSizeMake(21.0, 29.7) andInset:0.0];
    10. //> now we have to add all the stuff that we want to print
    11. // create header objects
    12. [printer.headerObjects addObject:[[DrawImage alloc] initImage:[UIImage imageWithContentsOfFile:[[[[AppDelegateX returnDocumentsPath] stringByAppendingPathComponent:kMainMediaFolder] stringByAppendingPathComponent:@"icons"] stringByAppendingPathComponent:@"overlay_header.png"] ] inRect:CGRectMake(0, 0, 20.5, 7.8)]];
    13. [printer.headerObjects addObject:[[DrawLineText alloc] initText:@"Ich bin ein Text im \nHeader" atPoint:CGPointMake(2.2, 5.2) ofFont:[UIFont systemFontOfSize:11.0] forWidth:8.0 inColor:[UIColor blackColor] withAlignment:NSTextAlignmentLeft]];
    14. // create footer objects
    15. [printer.footerObjects addObject:[[DrawImage alloc] initImage:[UIImage imageWithContentsOfFile:[[[[AppDelegateX returnDocumentsPath] stringByAppendingPathComponent:kMainMediaFolder] stringByAppendingPathComponent:@"icons"] stringByAppendingPathComponent:@"overlay_footer.png"] ] inRect:CGRectMake(0, 0, 20.5, 2.3)]];
    16. // generate html content
    17. NSError *error;
    18. NSString *printPath = [[[AppDelegateX returnDocumentsPath] stringByAppendingPathComponent:kMainMediaFolder] stringByAppendingPathComponent:kMainPrintFolder];
    19. NSString *html = @"<!DOCTYPE html><html><body>";
    20. html = [html stringByAppendingString: [NSString stringWithContentsOfFile:[printPath stringByAppendingPathComponent:@"css.html"] encoding:NSUTF8StringEncoding error:&error]];
    21. NSString *rowHtml = [NSString stringWithContentsOfFile:[printPath stringByAppendingPathComponent:@"tpl.html"] encoding:NSUTF8StringEncoding error:&error];
    22. if (!error) {
    23. // create the rows on html base
    24. //float gesamtwert = 0.00;
    25. //int gesamtanzahl = 0;
    26. NSString *colums = @"artikelnr, icaauftrag";
    27. NSString* firmaForThisOrder = [AppDelegateX retrunFirmaForOrderID:AppDelegateX.currentBelegNr];
    28. NSString *sqlStatement = [NSString stringWithFormat:@"select %@ from auftragsposition where firma = '%@' AND auftragsnr = '%@' %@", colums, firmaForThisOrder, AppDelegateX.currentBelegNr, sortCondition];
    29. sqlite3_stmt *warenKorbLevel1;
    30. if(sqlite3_prepare_v2(AppDelegateX.database, [sqlStatement UTF8String], -1, &warenKorbLevel1, NULL) == SQLITE_OK) {
    31. int i = 1;
    32. //[Base64 initialize];
    33. while(sqlite3_step(warenKorbLevel1) == SQLITE_ROW) {
    34. NSString *artikelNr = [AppDelegate checkNullString:(char *)sqlite3_column_text(warenKorbLevel1, 0)];
    35. int artikelNrAsInteger = [artikelNr intValue];
    36. int icaNummer = sqlite3_column_int(warenKorbLevel1, 1);
    37. NSString *filledICA = [NSString stringWithFormat:@"%05d", icaNummer];
    38. UIImage *img = [AppDelegateX returnContentImageByName:[NSString stringWithFormat:@"produktbilder/th/%@.png", artikelNr]];
    39. NSString *imgStr = [QSStrings encodeBase64WithData:UIImagePNGRepresentation(img)];
    40. NSString *icaArtNr = [NSString stringWithFormat:@"%@.%07d.%@", [filledICA substringToIndex:3], artikelNrAsInteger, [filledICA substringFromIndex:3]];
    41. // Replace HTML
    42. NSString *row = rowHtml;
    43. row = [row stringByReplacingOccurrencesOfString:@"{POS}" withString:[NSString stringWithFormat:@"%03d", i]]; // POS
    44. row = [row stringByReplacingOccurrencesOfString:@"{IMG}" withString:[NSString stringWithFormat:@"<img src='data:image/png;base64,%@' />", imgStr]]; // IMG
    45. row = [row stringByReplacingOccurrencesOfString:@"{ARTICLE}" withString:icaArtNr]; // ARTICLE
    46. html = [html stringByAppendingString:row];
    47. i++;
    48. }
    49. }
    50. else {[AppDelegateX logDatabaseError:_cmd];}sqlite3_finalize(warenKorbLevel1);
    51. }
    52. else {
    53. NSLog(@"Error Loading Print Templates: %@", error);
    54. }
    55. html = [html stringByAppendingString:@"</body></html>"];
    56. // set the print formatter
    57. UIMarkupTextPrintFormatter *viewFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html];
    58. viewFormatter.startPage = 0;
    59. viewFormatter.contentInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    60. [printer addPrintFormatter:viewFormatter startingAtPageAtIndex:0];
    61. // Create a PDF
    62. NSString *fileName = [NSString stringWithFormat:@"beleg_%@_%@.pdf", AppDelegateX.currentBelegNr, [AppDelegateX returnCurrentGermanDateString]];
    63. NSString *pdfPath = [[[[AppDelegateX returnDocumentsPath] stringByAppendingPathComponent:kMainMediaFolder] stringByAppendingPathComponent:kMainBelegeFolder] stringByAppendingPathComponent:fileName];
    64. UIGraphicsBeginPDFContextToFile(pdfPath, CGRectZero, nil);
    65. for (NSInteger i=0; i < [printer numberOfPages]; i++) {
    66. UIGraphicsBeginPDFPage();
    67. CGRect bounds = UIGraphicsGetPDFContextBounds();
    68. [printer drawPageAtIndex:i inRect:bounds];
    69. }
    70. UIGraphicsEndPDFContext();
    71. NSLog(@"PDF created");
    72. Class printInteractionController = NSClassFromString(@"UIPrintInteractionController");
    73. if ((printInteractionController != nil) && [printInteractionController isPrintingAvailable])
    74. {
    75. NSURL *fileURL = [NSURL fileURLWithPath:pdfPath]; // Document file URL
    76. UIPrintInteractionController* printInteraction = [printInteractionController sharedPrintController];
    77. if ([printInteractionController canPrintURL:fileURL] == YES)
    78. {
    79. UIPrintInfo *printInfo = [NSClassFromString(@"UIPrintInfo") printInfo];
    80. printInfo.duplex = UIPrintInfoDuplexLongEdge;
    81. printInfo.outputType = UIPrintInfoOutputGeneral;
    82. printInfo.jobName = pdfPath;
    83. printInteraction.printInfo = printInfo;
    84. printInteraction.printingItem = fileURL;
    85. printInteraction.showsPageRange = YES;
    86. [printInteraction presentFromRect:[sender frame] inView:[sender superview] animated:YES completionHandler:
    87. ^(UIPrintInteractionController *pic, BOOL completed, NSError *error)
    88. {
    89. if ((completed == NO) && (error != nil)) {
    90. UIAlertView* printAlert = [[UIAlertView alloc] initWithTitle:@"Drucken" message:[NSString stringWithFormat:@"%s %@", __FUNCTION__, error] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    91. [printAlert show];
    92. }
    93. else if ( completed ) {
    94. UIAlertView* printAlert = [[UIAlertView alloc] initWithTitle:@"Drucken" message:@"Der Druckauftrag wurde an den Drucker gesendet!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    95. [printAlert show];
    96. NSString *update = [NSString stringWithFormat:@"UPDATE auftragskopf set druck = 'J' where auftragsnr = '%@'", AppDelegateX.currentBelegNr];
    97. [AppDelegateX performDatabaseQueryByString:update];
    98. }
    99. else if (error) {
    100. UIAlertView* printAlert = [[UIAlertView alloc] initWithTitle:@"Drucken" message:[NSString stringWithFormat:@"%s %@", __FUNCTION__, error] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    101. [printAlert show];
    102. }
    103. }
    104. ];
    105. }
    106. }
    107. }
    Alles anzeigen


    Mit der SQL-Abfrage werden einfach die Positionen generiert und sollen als HTML dargestellt werden, das funktioniert auch ohne Probleme.
    Das Problem ist das vor jeder Position ein Bild des Artikels angezeigt werden soll, die Bilder liegen alle im Library verzeichnis, ([AppDelegateX returnDocumentsPath] <-- Diese Funktion geht auf das Library Verzeichnis)
    Ich habe schon probiert mit file:// , den Pfad als String oder BASE64 codiert das Image anzuzeigen und leider funktioniert nicht von allem :(

    Zur Base 64 Generierung habe ich die QSStrings Klasse eingebunden.

    Ich hoffe es jemand eine Idee.

    Danke
    H1990
  • Ich habe das Problem mittlerweile gelöst.
    Man kann dem Formatter zwar HTML-Code übergeben, dieser wird auch interpretiert, allerdings eben nur bis auf Bilder.
    Damit Bilder vom Renderer angezeigt werden müssen diese wohl im Web-Cache vorliegen. Daher habe ich eine versteckte WebView gebaut und lade den HTML-Code einmal dort hinein, speichere den zusätzlich in einer gloabelen Variable um dann in der Delegate Methode:
    -(void)webViewDidFinishLoad:(UIWebView *)webView

    mein PDF zu generieren.
    Das klappt dann ohne Probleme.

    Ich hoffe ich kann jemandem so ebenfalls weiterhelfen.