0

I need to print custom UI in a cross-platform application. On Windows, the work flow is like:

  1. Choose what to print
  2. Open the Windows Print dialog/print preview. This only queries for print pages as they are needed.
  3. Begin printing and report progress as each page prints.

I am trying to replicate this workflow on iOS, but it seems that all the print pages need to be print-ready before opening the iOS print dialog (UIPrintInteractionController). This is a big problem because the user may be printing a lot of pages, and each page can take awhile to prepare for printing. Therefore it takes too long to prepare and open the UIPrintInteractionController.

Is there any way on iOS to have it lazily query for the print pages one (or even a few) at a time as they are being previewed or printed? Or do they all have to be prepared ahead of presenting the UIPrintInteractionController?

EDIT: It's a major problem when printing many pages because it can easily run out of memory holding that many UIImages in memory at the same time.

I tried using the PrintItems property with UIImages, as well as a UIPrintPageRenderer. I am using Xamarin.iOS so pardon the C# syntax, but you get the idea. An answer in Swift or Objective C would be fine. Here is my sample pseudo-code:

//Version 1

public void ShowPrintUI_UsingPrintingItems()
{
    UIPrintInfo printOptions = UIPrintInfo.PrintInfo;
    InitializePrintOptions(printOptions);
    _printer.PrintInfo = printOptions;

    var printRect = new CGRect(new CGPoint(), _printer.PrintPaper.PaperSize);

    //Each of these is horribly slow. 
    //Can I have it render only when the page is actually needed (being previewed or printed) ?
    for (uint i = 0; i < numPrintPages; i++)
    {
        _printPages[i] = RenderPrintPage(i, printRect);
    }

    _printer.PrintingItems = _printPages;

    _printer.Present(true, (handler, completed, error) =>
    {
        //Clean up, etc.
    });
}

//Version 2
public void ShowPrintUI_UsingPageRenderer()
{

    UIPrintInfo printOptions = UIPrintInfo.PrintInfo;
    InitializePrintOptions(printOptions);
    _printer.PrintInfo = printOptions;

    //This still draws every page in the range and is just as slow
    _printer.PrintPageRenderer = new MyRenderer();

    _printer.Present(true, (handler, completed, error) =>
    {
        //Clean up, etc.
    });
}

private class MyRenderer : UIPrintPageRenderer
{
    public MyRenderer(IIosPrintCallback callback)
    {
        _callback = callback;
    }

    public override void DrawPage(nint index, CGRect pageRect)
    {
        DrawPrintPage(i, printRect);
    }

    public override nint NumberOfPages => _numPrintPages;
}
J Nelson
  • 138
  • 1
  • 1
  • 12
  • Have you looked at how other apps behave? If you try to print a large document in Word, does it use the standard print dialogs and/or appear to pre-proocess document? – Jason Feb 21 '20 at 21:25
  • @Jason good idea to compare. I just tried it with a 68 page word doc. It sat there with a spinner saying "Preparing Document for Printing..." for awhile before the OS print dialog appeared, and then all the pages were already rendered. So I guess that's their solution. It's a crappy user experience IMO. – J Nelson Feb 24 '20 at 11:32

0 Answers0