objective c - programar - ¿Cómo se puede implementar esta macro literal de cadena multilínea en Swift?
swift(lenguaje de programación) (2)
En mi código de Objective-C para mi marco GPUImage, tengo la siguiente macro:
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define SHADER_STRING(text) @ STRINGIZE2(text)
lo que me permite alinear vértices multilínea y sombreadores de fragmentos como literales NSString dentro de mis subclases de filtros personalizados, como este:
NSString *const kGPUImagePassthroughFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);
GPUImage necesita esto para proporcionar sombreadores de vértices y fragmentos formateados que se incluyen en el texto del cuerpo de las subclases de filtro. Enviarlos como archivos separados haría que el marco no se pueda compilar en una biblioteca estática. Utilizando la macro anterior, puedo hacer que estos sombreadores puedan copiarse y pegarse entre el código de estructura y los archivos de sombreado externos sin una cantidad ridícula de trabajo de reformateo.
Swift elimina las macros de compilación, y la documentación dice lo siguiente :
Las macros complejas se usan en C y Objective-C, pero no tienen contraparte en Swift. Las macros complejas son macros que no definen constantes, incluidas las macros parecidas a funciones entre paréntesis. Utiliza macros complejas en C y Objective-C para evitar restricciones de verificación de tipos o para evitar volver a escribir grandes cantidades de código repetitivo. Sin embargo, las macros pueden dificultar la depuración y la refactorización. En Swift, puede usar funciones y genéricos para lograr los mismos resultados sin ningún compromiso. Por lo tanto, las macros complejas que se encuentran en los archivos fuente C y Objective-C no están disponibles para su código Swift.
Según la línea "En Swift, puede usar funciones y genéricos para lograr los mismos resultados sin ningún compromiso", ¿hay alguna manera en Swift de proporcionar literales de cadenas de varias líneas sin recurrir a una cadena de operaciones de concatenación?
¿Parece que su objetivo final es evitar incluir archivos de sombreado independientes?
Si es así, una técnica sería escribir una utilidad rápida de línea de comandos que genere un archivo .swift de constantes de cadena que representen las funciones del sombreador en una determinada carpeta.
Incluya el archivo .swift resultante en su proyecto y no tendrá penalizaciones de tiempo de ejecución, e incluso una depuración más sencilla si genera el código correctamente.
Probablemente llevaría menos de una hora, nunca más necesitaría macros para sombreadores.
Las cuerdas multilínea Alas Swift aún no están disponibles, por lo que yo sé. Sin embargo, al hacer algunas investigaciones sobre esto, encontré una solución que podría ser útil. Es una combinación de estos elementos:
- Un truco rápido para citar Swift Strings en un patio de recreo - Describiendo cómo hacer un servicio reemplazando y arreglando textos
- El comentario de pyrtsa, con respecto al uso de
"/n".join(...)
para emular las cadenas multilínea
Configurar un servicio automatizado
Con Automator puede configurar un servicio adicional con las siguientes propiedades:
- Una sola acción de "Ejecutar script de shell"
- Marque "La salida reemplaza el texto seleccionado"
- Cambiar shell a
/usr/bin/perl
- Agregue el fragmento de código a continuación a la ventana de acción
- Guardar como algo así como "Reemplazar con la combinación rápida de varias líneas"
Extracto del código
print "/"//n/".join([/n"; # Start a join operation
# For each line, reformat and print
while(<>) {
print " "; # A little indentation
chomp; # Loose the newline
s/([///"])///$1/g; # Replace / and " with escaped variants
print "/"$_/""; # Add quotes around the line
print "," unless eof # Add a comma, unless it is the last line
print "/n"; # End the line, preserving original line count
}
print " ])"; # Close the join operation
Por supuesto, puede usar el shell y el código que desee, elegí Perl porque me resulta familiar, y aquí hay algunos comentarios:
- Utilicé la versión
"/n".join(...)
para crear la cadena multilínea, se podía usar la respuesta de extensión de Swift - Separar cadena sobre múltiples líneas , o incluso la variante+
, lo dejo como ejercicio para el usuario - Opté por una pequeña sangría con espacios, y para reemplazar el
/
y"
para hacerlo un poco más robusto" - Los comentarios son, por supuesto, opcionales, y probablemente puedas acortar el código. Traté de optar por claridad y legibilidad
- El código, como está, conserva espacios, pero podría editarse si eso no se desea. También se dejó como ejercicio para el usuario
Uso del servicio
Abra su patio de recreo o editor de código, e inserte / escriba un texto de línea múltiple:
- Marque el bloque de texto
- Ejecutar Xcode (o similar)> Servicios> Reemplazar con una combinación rápida de varias líneas
Ahora tiene una cadena multilínea en la codificación rápida adecuada. Aquí hay un ejemplo de antes y después del texto:
Here is my multiline text
example with both a " and
a / within the text
"/n".join([
"Here is my multiline text ",
"example with both a /" and",
"a // within the text"
])