Con Xcode 6.3, se introdujeron nuevas anotaciones para expresar mejor la intención de las API en Objective-C (y para garantizar un mejor soporte de Swift, por supuesto). Esas anotaciones eran, por supuesto nonnull
, nullable
y null_unspecified
.
Pero con Xcode 7, aparecen muchas advertencias como:
Al puntero le falta un especificador de tipo de nulabilidad (_Nnnull, _Nullable o _Null_unspecified).
Además de eso, Apple usa otro tipo de especificadores de nulabilidad, marcando su código C ( fuente ):
CFArrayRef __nonnull CFArrayCreate(
CFAllocatorRef __nullable allocator, const void * __nonnull * __nullable values, CFIndex numValues, const CFArrayCallBacks * __nullable callBacks);
En resumen, ahora tenemos estas 3 anotaciones de nulabilidad diferentes:
nonnull
`nullable
`null_unspecified
_Nonnull
`_Nullable
`_Null_unspecified
__nonnull
`__nullable
`__null_unspecified
Aunque sé por qué y dónde usar qué anotación, me confundo un poco qué tipo de anotaciones debo usar, dónde y por qué. Esto es lo que podría reunir:
- Para las propiedades que debe utilizar
nonnull
,nullable
,null_unspecified
. - Para los parámetros del método que debe utilizar
nonnull
,nullable
,null_unspecified
. - Para los métodos de C I deberán utilizar
__nonnull
,__nullable
,__null_unspecified
. - Para otros casos, como punteros dobles que debería utilizar
_Nonnull
,_Nullable
,_Null_unspecified
.
Pero todavía estoy confundido sobre por qué tenemos tantas anotaciones que básicamente hacen lo mismo.
Entonces mi pregunta es:
¿Cuál es la diferencia exacta entre esas anotaciones, cómo colocarlas correctamente y por qué?
fuente
Respuestas:
De la
clang
documentación :y
Por lo tanto, para las devoluciones de métodos y los parámetros, puede usar las versiones con doble subrayado
__nonnull
/__nullable
/ en__null_unspecified
lugar de las versiones con subrayado simple o en lugar de las que no están subrayadas. La diferencia es que los subrayados simples y dobles deben colocarse después de la definición del tipo, mientras que los que no están subrayados deben colocarse antes de la definición del tipo.Por lo tanto, las siguientes declaraciones son equivalentes y son correctas:
Para parámetros:
Para propiedades:
Sin embargo, las cosas se complican cuando se involucran dobles punteros o bloques que devuelven algo diferente a vacío, ya que los que no están subrayados no están permitidos aquí:
Similar a los métodos que aceptan bloques como parámetros, tenga en cuenta que el calificador
nonnull
/nullable
se aplica al bloque y no a su tipo de retorno, por lo tanto, los siguientes son equivalentes:Si el bloque tiene un valor de retorno, entonces estás obligado a una de las versiones de subrayado:
Como conclusión, puede usar cualquiera de ellos, siempre que el compilador pueda determinar el elemento al que asignarle el calificador.
fuente
_Null_unspecified
en Swift esto se traduce en opcional? no opcional o qué?Del blog de Swift :
fuente
Realmente me gustó este artículo , así que simplemente estoy mostrando lo que escribió el autor: https://swiftunboxed.com/interop/objc-nullability-annotations/
null_unspecified:
puentes a un Swift implícitamente desenvuelto opcional. Este es el valor predeterminado .nonnull
: el valor no será nulo; puentes a una referencia regular.nullable
: el valor puede ser nulo; puentes a un opcional.null_resettable
: el valor nunca puede ser nulo cuando se lee, pero puede establecerlo en nulo para restablecerlo. Solo se aplica a propiedades.Las anotaciones anteriores, luego difieren si las usa en el contexto de propiedades o funciones / variables:
El autor del artículo también proporcionó un buen ejemplo:
fuente
Muy útil es
y cerrando con
Esto anulará la necesidad del nivel de código 'nullibis' :-) ya que tiene sentido suponer que todo no es nulo (o
nonnull
o_nonnull
o__nonnull
) a menos que se indique lo contrario.Lamentablemente, hay excepciones a esto también ...
typedef
No se supone que s__nonnull
(nota,nonnull
no parece funcionar, tiene que usar su medio hermano feo)id *
necesita un nullibi explícito pero wow the sin-tax (_Nullable id * _Nonnull
<- adivina lo que eso significa ...)NSError **
siempre se supone nulableEntonces, con las excepciones a las excepciones y las palabras clave inconsistentes que generan la misma funcionalidad, quizás el enfoque sea usar las versiones feas
__nonnull
/__nullable
/__null_unspecified
e intercambiar cuando el cumplidor se queja ...? ¿Quizás es por eso que existen en los encabezados de Apple?Curiosamente, algo lo puso en mi código ... Aborrezco los guiones bajos en el código (tipo de la vieja escuela Apple C ++), así que estoy absolutamente seguro de que no los escribí pero aparecieron (un ejemplo de varios):
Y aún más interesante, donde insertó el __nullable está mal ... (¡eek @!)
Realmente desearía poder usar la versión que no es de subrayado, pero aparentemente eso no vuela con el compilador ya que esto se marca como un error:
fuente