objective-c clang objective-c-literals

objective c - ¿Se pueden redirigir los nuevos literales Clang Objective-C a clases personalizadas?



objective-c-literals (2)

Los comentarios lo tienen todo correcto, pero solo para resumir:

  • No.

Los significados de los literales @{} , @[] y @"" de Apple están codificados en Clang. Puede verlo aquí: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?view=markup Todo es bastante modular, lo que significa que no sería difícil para un Clang hacker para agregar su propia sintaxis literal ... pero "modular" no significa "accesible desde el exterior". Agregar una nueva sintaxis o incluso redirigir la sintaxis existente a nuevas clases definitivamente requeriría la reconstrucción del Clang por tu cuenta.

Aquí hay una publicación del blog sobre la adición de los literales NSURL a Clang mediante piratería en sus partes internas: http://www.stuartcarnie.com/2012/06/llvm-clang-hacking-part-3.html (Gracias @Josh Caswell)

Si está dispuesto a usar Objective-C ++ con las extensiones de C ++ 11, puede tener "literales definidos por el usuario", que le permiten escribir cosas como

NSURL *operator ""URL (const char *s) { return [NSURL URLWithString: @(s)]; } int main() { ... NSURL *myurl = "ftp://foo"URL; ... }

Esto fue mencionado en los comentarios en el blog de Mike Ash. mikeash.com/pyblog/… Pero esto no se ve muy Objective-C-ish (o muy C ++ ish!) , y funciona solo con un compilador de Objective-C ++ 11, y en general no hagas esto. :)

Aunque la sobrecarga de @ comienza a pisar un territorio peligroso, me encanta la adición de los nuevos literales Objective-C en Clang 3.1. Desafortunadamente los nuevos literales son de uso limitado para mí. Excepto en los casos en que el código debe interactuar con AppKit, principalmente he dejado de usar las clases de Foundation en favor de mi propio marco personalizado (por una variedad de razones, la mayoría de las cuales es que necesito un control directo sobre los patrones de asignación de memoria utilizados) por objetos).

Siempre podría usar algunos trucos de ejecución para pasar el objeto recién creado como mi clase personalizada (y es lo que ya tengo que hacer con los literales de los objetos de cadena, ya que solo el tiempo de ejecución de GCC que no es de Apple admite la -fconstantstring=class flag), pero este es un truco en el mejor de los casos y arroja todos los beneficios que obtuve al reemplazar la clase de Foundation equivalente, para empezar.

A diferencia de los literales de objeto de cadena, los nuevos literales Los implementos de Clang no son en realidad clases constantes (donde el diseño de la memoria está codificado); en su lugar, los mensajes apropiados se envían a sus respectivas clases para crear e inicializar un nuevo objeto en tiempo de ejecución. El efecto no es diferente si hubieras creado el objeto tú mismo. En teoría, significa que las clases utilizadas y los métodos llamados por los nuevos literales no están codificados. En la práctica, no puedo encontrar una manera de cambiarlos para que apunten a mis propias clases y métodos personalizados (de hecho, me encantaría simplemente señalar una clase personalizada; señalar un método ficticio a un método real en tiempo de ejecución no es difícil ).

Cuando lo vi por primera vez, realmente esperaba encontrar un conjunto de banderas que pudieran usarse para hacer lo que pido, pero como no he encontrado ninguna, espero que alguien tenga una solución.


Puede sustituir la clase por algunos literales de Objective-C con @compatibility_alias keyword trick.

Aquí hay un ejemplo.

@compatibility_alias NSNumber AAA;

Por supuesto, debe proporcionar la implementación adecuada para la nueva clase.

#import <Foundation/NSObject.h> @interface AAA : NSObject + (id)numberWithInt:(int)num; @end @implementation AAA + (id)numberWithInt:(int)num { return @"AAAAA!!!"; // Abused type system just to check result. } @end @compatibility_alias NSNumber AAA;

Ahora Clang hará el trabajo por ti. Confirmé que esto está funcionando para números, matrices, literales de diccionarios. Desafortunadamente, los literales de cuerdas parecen emitirse estáticamente, por lo que no funcionará.

Para obtener más información sobre la palabra clave @compatibility_alias , consulte aquí .

Nota

Debido a que la palabra clave @compatibility_alias es una directiva de compilación que se aplica a la unidad de compilación actual, debe separar la unidad de compilación para evitar la duplicación de símbolos con la clase NSObject en el Kit de Fundación de Apple. Así es como lo hice.

main.m

#import "test.h" // Comes before Foundation Kit. #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"return of test = %@", test()); // insert code here... NSLog(@"Hello, World!"); } return 0; }

prueba.h

id test();

test.m

#import "test.h" #import <Foundation/NSObject.h> @interface AAA : NSObject + (id)numberWithInt:(int)v; + (id)arrayWithObjects:(id*)pobj count:(int)c; + (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c; @end @implementation AAA + (id)numberWithInt:(int)v { return @"AAAAA as number!!!"; } + (id)arrayWithObjects:(id*)pobj count:(int)c { return @"AAAAA as array!!!"; } + (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c { return @"AAAAA as dictionary!!!"; } @end @compatibility_alias NSDictionary AAA; @compatibility_alias NSArray AAA; @compatibility_alias NSNumber AAA; id test() { // return @{}; // return @[]; return @55; }

Resultado.

2013-03-23 08:54:42.793 return of test = AAAAA!!! 2013-03-23 08:54:42.796 Hello, World!