objective c - objc - Cómo anotar las API de Objective-C para su uso en Swift(por ejemplo, tipos de devolución)
swift 3 to swift 4 converter (2)
Xcode 6.3 / Swift 1.2
Xcode 6.3 agregó soporte oficial para anotar la nulabilidad en Objective-C.
Nulabilidad
La nulabilidad de un valor se puede declarar anotando el tipo con las palabras clave __nullable
, __nonnull
y __null_unspecified
(el valor predeterminado). En propiedades y métodos, las palabras clave son nullable
, no nonnull
y null_unspecified
.
Ejemplos de las notas de lanzamiento de Xcode
- (void)registerNib:(nonnull UINib *)nib
forCellReuseIdentifier:(nonnull NSString *)identifier;
- (nullable UITableViewCell *)cellForRowAtIndexPath:(nonnull NSIndexPath)indexPath;
@property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;
Cambiando el valor predeterminado
null_unspecified
(que se traduce a T!
) es el valor predeterminado para todo el código existente. Una característica útil es la capacidad de cambiar el valor predeterminado para las secciones de su API.
NS_ASSUME_NONNULL_BEGIN
// nonnull is the default here
NS_ASSUME_NONNULL_END
Esto elimina una gran cantidad de ruido, ya que los métodos que aceptan y manejan cero generalmente son la excepción, no la regla. Personalmente, usaría esto para todas las API auditadas.
null_resettable
null_resettable
es una anotación adicional que se usa para el caso poco común en el que puede establecer una propiedad en nulo, pero nunca será nulo (porque se restablece a un valor predeterminado).
@property (nonatomic, retain, null_resettable) UIColor *tintColor;
Personalmente, evitaría este comportamiento para el nuevo código. La naturaleza híbrida de tales propiedades no es un buen ajuste para Swift.
Xcode 7 / Swift 2 (Beta)
Xcode 7 agrega soporte para anotar tipos genéricos en Objective-C.
Anotaciones de tipo genérico para colecciones.
NSArray
, NSSet
y NSDictionary
(que se NSSet
automáticamente a la Array
, el Set
y el Dictionary
Swift se pueden anotar con el tipo de su contenido).
@property NSArray<NSString *> *stringArray;
@property NSSet<NSString *> *stringSet;
@property NSDictionary<NSString *, NSString *> *stringDict;
También está la palabra clave __kindof
que le dice al compilador de Objective-C que sea menos estricto y que permita el downcasting. Pero no afecta al lado Swift.
Anotaciones de tipo genérico para clases personalizadas.
@interface MyArray1<__covariant T> : NSObject
- (void)addObject:(T)object;
@end
@interface MyArray2<__covariant T : NSObject *> : NSObject
- (void)addObject:(T)object;
@end
@interface MyArray3<__covariant T : id<NSCopying>> : NSObject
- (void)addObject:(T)object;
@end
La @implementation
no sabe acerca de T
y usa id
/ NSObject *
/ id<NSCopying>
como siempre lo hizo.
De acuerdo con las notas de la versión de Xcode, Apple ha estado "auditando" sus API existentes para eliminar las opciones implícitamente desenvueltas. Eso significa que en lugar de T!
, sus APIs devolverán T
o T?
donde corresponda.
¿Dónde hacen esto? ¿Cómo puedo anotar / envolver mi código existente de Objective-C (especialmente las bibliotecas) para que sea más fácil de usar desde Swift?
Creo que hay una manera de hacer esto en este momento. Parece que la información se está compilando para
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator
en archivos como
UIKit.apinotesc
UIKit.swiftdoc
UIKit.swiftmodule
Las clases de *.swiftmodule
son generadas por Xcode como parte de la compilación swift pero la información adicional puede estar en el archivo .apinotesc
, que no parece haber una forma documentada de generarla en este momento.
Sin embargo, el comando swift
tiene una opción -apinotes
, que se utiliza para generar esto. Puede ver en /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/UIKit.apinotesc
que puede analizar esto con:
xcrun swift -apinotes -binary-to-yaml -o=- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/UIKit.apinotesc
Esto genera un archivo YAML que se parece a:
Classes:
- Name: NSFileProviderExtension
Availability: available
AvailabilityMsg: ''''
Methods:
- Selector: ''URLForItemWithPersistentIdentifier:''
MethodKind: Instance
Nullability: [ N ]
NullabilityOfRet: U
Availability: available
AvailabilityMsg: ''''
Si fuera un apostador (y no lo soy), diría que MethodKind determina si se trata de una Instance
o una Class
y que Swift está utilizando la capacidad de nulidad para determinar si es opcional o no. Yo sospecharia
-
U
- (implícitamente) sin envoltura opcional -
O
- opcional -
N
- no opcional?
Estas son suposiciones salvajes sin embargo.