Не удается заставить iOS Print Renderer правильно рисовать

ХОРОШО. Кажется, что примеров по этому поводу не хватает, и я довольно озадачен.

Я пытаюсь создать собственный рендеринг страницы печати; тип, который полностью настраивает вывод, а не тот, который использует существующее представление.

Действительно странно то, что я смог сделать это в ObjC пару лет назад, и я не могу сделать то же самое в Swift.

Я должен упомянуть, что я использую предварительный выпуск (бета-версия 5) Xcode и Swift 4 (который почти не отличается от Swift 3 в моем проекте).

Проект здесь.

Это проект с полностью открытым исходным кодом, так что ничего не скрыто; тем не менее, он все еще находится в стадии разработки и является движущейся целью.

Это класс рендеринга страницы.

Кстати: игнорируйте класс делегата. Я просто метался, пытаясь что-то сообразить. Я [пока] не планирую делать какие-либо делегаты. В частности, мой вопрос касается того, что происходит здесь:

override func drawContentForPage(at pageIndex: Int, in contentRect: CGRect) {
    let perMeetingHeight: CGFloat = self.printableRect.size.height / CGFloat(self.actualNumberOfMeetingsPerPage)
    let startingPoint = max(self.maxMeetingsPerPage * pageIndex, 0)
    let endingPointPlusOne = min(self.maxMeetingsPerPage, self.actualNumberOfMeetingsPerPage)
    for index in startingPoint..<endingPointPlusOne {
        let top = self.printableRect.origin.y + (CGFloat(index) * perMeetingHeight)
        let meetingRect = CGRect(x: self.printableRect.origin.x, y: top, width: self.printableRect.size.width, height: perMeetingHeight)
        self.drawMeeting(at: index, in: meetingRect)
    }
}

и здесь:

func drawMeeting(at meetingIndex: Int, in contentRect: CGRect) {
    let myMeetingObject = self.meetings[meetingIndex]
    var top: CGFloat = contentRect.origin.y
    let topLabelRect = CGRect(x: contentRect.origin.x, y: 0, width: contentRect.size.width, height: self.meetingNameHeight)
    top += self.meetingNameHeight
    let meetingNameLabel = UILabel(frame: topLabelRect)
    meetingNameLabel.backgroundColor = UIColor.clear
    meetingNameLabel.font = UIFont.boldSystemFont(ofSize: 30)
    meetingNameLabel.textAlignment = .center
    meetingNameLabel.textColor = UIColor.black
    meetingNameLabel.text = myMeetingObject.name
    meetingNameLabel.draw(topLabelRect)
}

Все это вызывается из здесь:

@IBAction override func actionButtonHit(_ sender: Any) {
    let sharedPrintController = UIPrintInteractionController.shared
    let printInfo = UIPrintInfo(dictionary:nil)
    printInfo.outputType = UIPrintInfoOutputType.general
    printInfo.jobName = "print Job"
    sharedPrintController.printPageRenderer = BMLT_MeetingSearch_PageRenderer(meetings: self.searchResults)
    sharedPrintController.present(from: self.view.frame, in: self.view, animated: false, completionHandler: nil)
}

Что происходит, так это то, что все на странице сваливается вверху. Я пытаюсь распечатать последовательный список совещаний на странице, но все они рисуются в точке y=0, например так:

Отображение беспорядочного текста

Это должен быть список названий встреч, идущий вниз по странице.

Чтобы добраться сюда, нужно запустить приложение, подождать, пока оно не подключится к серверу, а затем нажать большую кнопку. Вы получите список и нажмите кнопку «Действие» в верхней части экрана.

Я не удосужился выйти за рамки предварительного просмотра, так как это даже не работает. Список - единственный, который я подключил прямо сейчас, и я как раз нахожусь на этапе простой печати названий встреч, чтобы убедиться, что у меня правильный базовый макет.

Чего я, очевидно, не делаю.

Любые идеи?


person Chris Marshall    schedule 13.08.2017    source источник
comment
Интересно. Если я использую drawText(in: CGRect), это работает. Похоже, это проблема контекста рисования.   -  person Chris Marshall    schedule 13.08.2017
comment
Однако даже это не является исправлением. Мне нужно посмотреть, смогу ли я найти какие-либо реальные примеры Swift.   -  person Chris Marshall    schedule 13.08.2017
comment
ХОРОШО. Похоже, я понял это (по сравнению с тем, что я сделал пару лет назад). Мне нужно провести дополнительное тестирование и реализацию, прежде чем я отвечу на свой вопрос.   -  person Chris Marshall    schedule 14.08.2017


Ответы (1)


Хорошо. Я понял, в чем дело.

Я пытался сделать это, используя подпрограммы UIKit, которые предполагают довольно высокоуровневый контекст рисования. DrawText(in: CGRect) был моей лампочкой.

Мне нужно сделать все, используя более низкоуровневый контекстно-ориентированный рисунок, и не использовать UIKit.

Вот как я сейчас реализую подпрограмму drawMeeting (я изменил то, что я рисую, чтобы отображать более релевантную информацию). Я все еще работаю над этим, и он станет больше:

func drawMeeting(at meetingIndex: Int, in contentRect: CGRect) {
    let myMeetingObject = self.meetings[meetingIndex]
    var remainingRect = contentRect

    if (1 < self.meetings.count) && (0 == meetingIndex % 2) {
        if let drawingContext = UIGraphicsGetCurrentContext() {
            drawingContext.setFillColor(UIColor.black.withAlphaComponent(0.075).cgColor)
            drawingContext.fill(contentRect)
        }
   }

    var attributes: [NSAttributedStringKey : Any] = [:]
    attributes[NSAttributedStringKey.font] = UIFont.italicSystemFont(ofSize: 12)
    attributes[NSAttributedStringKey.backgroundColor] = UIColor.clear
    attributes[NSAttributedStringKey.foregroundColor] = UIColor.black

    let descriptionString = NSAttributedString(string: myMeetingObject.description, attributes: attributes)
    let descriptionSize = contentRect.size
    var stringRect = descriptionString.boundingRect(with: descriptionSize, options: [NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading], context: nil)
    stringRect.origin = contentRect.origin
    descriptionString.draw(at: stringRect.origin)

    remainingRect.origin.y -= stringRect.size.height
}
person Chris Marshall    schedule 14.08.2017