Можно ли отображать NSLayoutConstraints с десятичными константами?

#ios #swift #uiview #pdf-generation #nslayoutconstraint

#iOS #swift #uiview #генерация pdf #nslayoutconstraint

Вопрос:

Я создал несколько пользовательских представлений внутри UIScrollView, которые изменяют размер динамически на основе значений, которые я ввожу в текстовые поля Height и Width. После изменения размера UIView я сохраняю содержимое UIScrollView в виде данных PDF.

Я обнаружил, что размеры пользовательского интерфейса в формате PDF (при измерении в Adobe Illustrator) всегда округляются до трети.

Например:

1.5 -> 1.333

1.75 -> 1.666

Я проверяю значения констант каждый раз перед обновлением ограничений, и они точны. Кто-нибудь может объяснить, почему UIViews имеют неправильные размеры после отображения в формате PDF?

 @IBAction func updateDimensions(_ sender: Any) {

        guard let length = NumberFormatter().number(from:
            lengthTextField.text ?? "") else { return }

        guard let width = NumberFormatter().number(from:
            widthTextField.text ?? "") else { return }

        guard let height = NumberFormatter().number(from:
            heightTextField.text ?? "") else { return }

        let flapHeight = CGFloat(truncating: width)/2

        let lengthFloat = CGFloat(truncating: length)
        let widthFloat = CGFloat(truncating: width)
        let heightFloat = CGFloat(truncating: height)

        UIView.animate(withDuration: 0.3) {
            self.faceAWidthConstraint.constant = lengthFloat
            self.faceAHeightConstraint.constant = heightFloat
            self.faceBWidthConstraint.constant = widthFloat
            self.faceA1HeightConstraint.constant = flapHeight
            self.view.layoutIfNeeded()
        }
    }

    func createPDFfrom(aView: UIView, saveToDocumentsWithFileName fileName: String)
    {
        let pdfData = NSMutableData()
        UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
        UIGraphicsBeginPDFPage()

        guard let pdfContext = UIGraphicsGetCurrentContext() else { return }

        aView.layer.render(in: pdfContext)
        UIGraphicsEndPDFContext()

        if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
            let documentsFileName = documentDirectories   "/"   fileName
            debugPrint(documentsFileName)
            pdfData.write(toFile: documentsFileName, atomically: true)
        }
    }
  

Ответ №1:

Вы не должны использовать layer.render (в:) для отображения вашего pdf. Причина, по которой он всегда является третьим, заключается в том, что вы должны быть на устройстве 3x (это было бы 1/2 на устройстве 2x и просто 1 на устройстве 1x), поэтому на точку приходится по 3 пикселя. Когда iOS преобразует ваши ограничения в пиксели, лучшее, что он может сделать, это округлить до ближайшей трети, потому что он выбирает целочисленный пиксель. PDF-файл может иметь гораздо более высокую плотность пикселей (или использовать векторное изображение с бесконечным разрешением), поэтому вместо использования layer.render (в:), который загружает пиксели из растрированного векторного слоя в ваш PDF-файл, вам следует на самом деле отрисовать содержимое в контексте PDF вручную (т. Е. Использовать UIBezier curve, UIImage.draw и т.д.). Это позволит pdf сохранять полное разрешение любых имеющихся у вас растрированных изображений и позволит ему захватывать любые используемые вами векторы, не превращая их в растрированные пиксели, которые ограничены экраном устройства, на котором вы находитесь.