Com o Xcode 6.3, foram introduzidas novas anotações para expressar melhor a intenção das APIs no Objective-C (e para garantir melhor suporte Swift, é claro). Essas anotações eram nonnull
, é claro , nullable
e null_unspecified
.
Mas com o Xcode 7, existem muitos avisos, como:
O ponteiro está ausente em um especificador de tipo de nulidade (_Nonnull, _Nullable ou _Null_unspecified).
Além disso, a Apple usa outro tipo de especificadores de nulidade, marcando seu código C ( fonte ):
CFArrayRef __nonnull CFArrayCreate(
CFAllocatorRef __nullable allocator, const void * __nonnull * __nullable values, CFIndex numValues, const CFArrayCallBacks * __nullable callBacks);
Então, para resumir, agora temos essas três anotações de nulidade diferentes:
nonnull
,nullable
,null_unspecified
_Nonnull
,_Nullable
,_Null_unspecified
__nonnull
,__nullable
,__null_unspecified
Embora eu saiba por que e onde usar qual anotação, estou ficando um pouco confuso com o tipo de anotação que devo usar, onde e por que. Isto é o que eu pude reunir:
- Para propriedades que eu deveria usar
nonnull
,nullable
,null_unspecified
. - Para os parâmetros do método devo usar
nonnull
,nullable
,null_unspecified
. - Para os métodos c I deve usar
__nonnull
,__nullable
,__null_unspecified
. - Para outros casos, como ponteiros duplos devo usar
_Nonnull
,_Nullable
,_Null_unspecified
.
Mas ainda estou confuso sobre o motivo pelo qual temos tantas anotações que basicamente fazem a mesma coisa.
Então, minha pergunta é:
Qual é a diferença exata entre essas anotações, como colocá-las corretamente e por quê?
fonte
Respostas:
A partir da
clang
documentação :e
Portanto, para retornos e parâmetros de método, você pode usar as versões com sublinhado duplo
__nonnull
/__nullable
/ em__null_unspecified
vez das com sublinhado único ou das não-sublinhadas. A diferença é que os sublinhados simples e duplo precisam ser colocados após a definição de tipo, enquanto os não sublinhados precisam ser colocados antes da definição de tipo.Portanto, as seguintes declarações são equivalentes e corretas:
Para parâmetros:
Para propriedades:
As coisas, no entanto, complicam quando ponteiros duplos ou blocos retornando algo diferente de nulo estão envolvidos, pois os não sublinhados não são permitidos aqui:
Semelhante aos métodos que aceitam blocos como parâmetros, observe que o
nonnull
/nullable
qualificador se aplica ao bloco, e não ao seu tipo de retorno; portanto, o seguinte é equivalente:Se o bloco tiver um valor de retorno, você será forçado a uma das versões de sublinhado:
Como conclusão, você pode usar qualquer um deles, desde que o compilador possa determinar o item ao qual atribuir o qualificador.
fonte
_Null_unspecified
no Swift isso se traduz em opcional? não opcional ou o quê?Desde o blog Swift :
fonte
Gostei muito deste artigo , por isso estou apenas mostrando o que o autor escreveu: https://swiftunboxed.com/interop/objc-nullability-annotations/
null_unspecified:
pontes para um opcional Swift implicitamente desembrulhado. Esse é o padrão .nonnull
: o valor não será nulo; pontes para uma referência regular.nullable
: o valor pode ser nulo; pontes para um opcional.null_resettable
: o valor nunca pode ser nulo quando lido, mas você pode configurá-lo como nulo para redefini-lo. Aplica-se apenas a propriedades.As anotações acima diferem se você as utiliza no contexto de propriedades ou funções / variáveis:
O autor do artigo também forneceu um bom exemplo:
fonte
Muito útil é
e fechando com
Isso anulará a necessidade do nível de código 'nullibis' :-), pois meio que faz sentido supor que tudo é não nulo (ou
nonnull
ou_nonnull
ou__nonnull
), a menos que indicado de outra forma.Infelizmente, também há exceções ...
typedef
Não se supõe que s__nonnull
(note,nonnull
não parece funcionar, tem que usar seu meio-irmão feio)id *
precisa de um nullibi explícito, mas wow o imposto do pecado (_Nullable id * _Nonnull
<- adivinhe o que isso significa ...)NSError **
é sempre assumido nuloPortanto, com as exceções às exceções e as palavras-chave inconsistentes que provocam a mesma funcionalidade, talvez a abordagem seja usar as versões feias
__nonnull
/__nullable
/__null_unspecified
e trocar quando o complacente reclama ...? Talvez seja por isso que eles existem nos cabeçalhos da Apple?Curiosamente, algo colocou isso no meu código ... Eu detesto sublinhados no código (cara do estilo Apple C ++ da velha escola), por isso estou absolutamente certo de que não os digitei, mas eles apareceram (um exemplo de vários):
E ainda mais interessante, onde inseriu o __nullable está errado ... (eek @!)
Eu realmente gostaria de poder usar apenas a versão sem sublinhado, mas aparentemente isso não ocorre com o compilador, pois isso é sinalizado como um erro:
fonte