¿Cómo funcionan las imágenes vectoriales en Xcode (es decir, archivos pdf)?

176

¿Cómo funciona el soporte de vectores en Xcode 6?

Cuando intento cambiar el tamaño de una imagen, parece irregular, ¿qué da?

Sensato
fuente

Respuestas:

351

Cómo usar vectores en Xcode (7 y 6.3+):

  1. Guarde una imagen como un archivo .pdf con el tamaño @ 1x adecuado (por ejemplo, 24x24 para un botón de barra de herramientas ).
  2. En su archivo Images.xcassets , cree un nuevo conjunto de imágenes .
  3. En el Inspector de atributos , configure los factores de escala en un solo vector .
  4. Arrastre y suelte su archivo pdf en la sección Todos, Universal .
  5. Ahora puede referirse a su imagen por su nombre, tal como lo haría con cualquier archivo .png .

    UIImage(named: "myImage")

Cómo usar vectores en versiones anteriores de Xcode (6.0 - 6.2):

  • Siga los pasos anteriores, excepto el paso 3, establezca Tipos en Vectores .

Cómo funcionan los vectores en Xcode

El soporte de vectores es confuso en Xcode, porque cuando la mayoría de las personas piensan en vectores, piensan en imágenes que pueden escalar hacia arriba y hacia abajo y aún lucir bien. Sin embargo, Xcode 6 y 7 no tienen soporte completo de vectores para iOS, por lo que las cosas funcionan de manera un poco diferente.

El sistema vectorial es realmente simple . Toma su .pdfimagen, y crea @1x.png, @2x.pngy @3x.pngactivos en el tiempo de construcción . (Puede usar una herramienta para examinar el contenido de Assets.car para verificar esto).

Por ejemplo, suponga foo.pdfque tiene un activo vectorial de 44x44. En el momento de la compilación generará los siguientes archivos:

Esto funciona igual para cualquier imagen de tamaño. Por ejemplo, si tiene bar.pdfcuál es 100x100, obtendrá:


Trascendencia:

  • No puede elegir un nuevo tamaño para la imagen ; solo se verá bien si lo mantiene en el tamaño 44x44. La razón es que no se implementa el soporte completo de vectores . Lo único que hacen estos vectores es ahorrarle el tiempo de guardar sus activos de imagen. Si tiene una herramienta (por ejemplo, un script de Photoshop) que ya lo convierte en un proceso de un solo paso, lo único que obtendrá mediante el uso de vectores pdf es un soporte a prueba de futuro (por ejemplo, si en iOS 9 Apple comienza a requerir activos @ 4x, estos simplemente funcionarán), y tendrá menos archivos para mantener .
  • Debe solicitar todos sus activos en el tamaño @ 1x, guardados como archivos PDF . Entre otras cosas, esto permitirá que UIImageViews tenga el tamaño de contenido intrínseco correcto.

Por qué (probablemente) funciona de esta manera:

  • Esto lo hace compatible con versiones anteriores de iOS.
  • Cambiar el tamaño de los vectores puede ser una tarea computacional intensiva en tiempo de ejecución; Al implementarlo de esta manera, no hay golpes de rendimiento .
Sensato
fuente
8
Agradable escribir. Esto se discutió en la Sesión 411 de WWDC 2014 - "Novedades en el Creador de interfaces" en el momento 44:13. Tenga en cuenta que dicen que la rasterización se realiza en el momento de la compilación. También curiosamente en el MAC usará vectores en tiempo de ejecución. Con suerte, en algún momento distante del futuro, iOS también lo hará.
Mike Vosseller
15
Desafortunadamente, no escala los valores de corte. Entonces, si corta las esquinas en 5, no lo escalará a 10 y 15 para las imágenes 2x y 3x.
Jesse
55
@Jesse si desea escalar los valores de corte, puede hacerlo usted mismo en código usando resizableImageWithCapInsets:y dividiendo sus valores de corte por[UIScreen mainScreen].scale
Arie Litovsky
1
Para aclarar la sugerencia de @ArieLitovsky sobre el corte: debe eliminar el corte del activo y moverlo al código, algo así comoCGFloat scale = [UIScreen mainScreen].scale; UIImage *image = [[UIImage imageNamed:@"my_unsliced_asset"] resizableImageWithCapInsets:UIEdgeInsetsMake(10 * scale, 11 * scale, 12 * scale, 13 * scale)];
glyuck
66
¿Cómo hago esto para XCode 8? ¡La opción parece haber desaparecido!
Gerald
26

En Xcode 8, aún puede agregar un pdf, crear un nuevo conjunto de imágenes y, en el Inspector de atributos, establecer la opción Escalas en Escala única. ingrese la descripción de la imagen aquí

Maria
fuente
15

Este es un complemento de la excelente respuesta de @Senseful.

Cómo hacer imágenes vectoriales en formato .pdf

Diré cómo hacer esto en Inkscape, ya que es gratuito y de código abierto, pero otros programas deberían ser similares.

En Inkscape:

  1. Crea un nuevo proyecto.
  2. Vaya a Archivo> Propiedades del documento y establezca el tamaño de página personalizado en el tamaño @ 1x (44x44, 100x100, etc.) con las unidades en px.
  3. Haz tu obra de arte.
  4. Vaya a Archivo> Guardar como ...> Formato de documento imprimible (* .pdf)> Guardar> Aceptar. (Alternativamente, puede ir a Imprimir> Imprimir a archivo> Formato de salida: PDF> Imprimir, pero no hay tantas opciones).

Notas:

  • Como se menciona en la respuesta aceptada, no puede cambiar el tamaño de su imagen porque Xcode aún produce las imágenes rasterizadas en el momento de la compilación. Si necesita cambiar el tamaño de su imagen, debe crear un nuevo archivo .pdf con un tamaño diferente.
  • Si ya tiene una imagen .svg que tiene el tamaño de página incorrecto, haga lo siguiente:

    1. Cambiar el tamaño de página (Inkscape> Archivo> Propiedades del documento)
    2. Seleccione todos los objetos (Ctrl + A) en el espacio de trabajo y cambie su tamaño para que se ajusten al nuevo tamaño de página. (Mantenga presionada la tecla Ctrl para mantener el tamaño del aspecto).
  • Para convertir un archivo .svg en un .pdf, también puede encontrar utilidades en línea para hacer el trabajo por usted. Aquí hay un ejemplo de esta respuesta . Esto tiene el beneficio de permitirle configurar el tamaño .pdf fácilmente.

Otras lecturas

Suragch
fuente
12

Para aquellos que aún no se actualizaron, hubo cambios en Xcode 9 (iOS 11).

Novedades de Cocoa Touch (WWDC 2017 Sesión 201) (@ 32: 55) https://developer.apple.com/videos/play/wwdc2017/201/

En pocas palabras, el Catálogo de activos ahora incluye la nueva casilla de verificación en el Inspector de atributos llamada "Preservar datos vectoriales". Cuando se marca, los datos PDF se incluirán en el binario compilado, lo que aumenta su tamaño, por supuesto. Pero le da la oportunidad a iOS de escalar los datos vectoriales en ambas direcciones y proporcionar buenas imágenes (con sus propias dificultades). Para iOS por debajo de 11, se utilizan los antiguos mecanismos de escala descritos en las respuestas hacia arriba.

Dren
fuente
1

Puede usar archivos PDF normales dentro de su proyecto como imágenes vectoriales y renderizar imágenes de cualquier tamaño con esta extensión. De esta manera, es mucho mejor porque iOS no generará imágenes .PNG de sus archivos PDF, además puede renderizar imágenes con el tamaño que desee:

    extension UIImage {

    static func fromPDF(filename: String, size: CGSize) -> UIImage? {
        guard let path = Bundle.main.path(forResource: filename, ofType: "pdf") else { return nil }
        let url = URL(fileURLWithPath: path)
        guard let document = CGPDFDocument(url as CFURL) else { return nil }
        guard let page = document.page(at: 1) else { return nil }

        let imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(size: size)
            let img = renderer.image { ctx in
                UIColor.white.withAlphaComponent(0).set()
                ctx.fill(imageRect)
                ctx.cgContext.translateBy(x: 0, y: size.height)
                ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
                ctx.cgContext.concatenate(page.getDrawingTransform(.artBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                ctx.cgContext.drawPDFPage(page);
            }

            return img
        } else {
            // Fallback on earlier versions
            UIGraphicsBeginImageContextWithOptions(size, false, 2.0)
            if let context = UIGraphicsGetCurrentContext() {
                context.interpolationQuality = .high
                context.setAllowsAntialiasing(true)
                context.setShouldAntialias(true)
                context.setFillColor(red: 1, green: 1, blue: 1, alpha: 0)
                context.fill(imageRect)
                context.saveGState()
                context.translateBy(x: 0.0, y: size.height)
                context.scaleBy(x: 1.0, y: -1.0)
                context.concatenate(page.getDrawingTransform(.cropBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                context.drawPDFPage(page)
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image
            }
            return nil
        }
    }

}
Bruno Paulino
fuente
1
Intenté esto, pero parece que no escala la imagen a píxeles más grandes. El UIImage en sí que estoy obteniendo es del tamaño correcto; es solo que la imagen vectorial está centrada y aún en el tamaño de píxel original del PDF. (Quería escalarlo al tamaño del UIImage). ¿Sabes si esto sería posible?
DivideByZer0