2016-06-28 18 views
6

Ho una classe modello come segue, che si trova in una libreria scritta in Objective-C. Sto consumando questa lezione nel mio rapido progetto. In rapido diventa proprietà di tipo String!. A volte quella proprietà sarà nulla. Così, sto testando la convalida nil come segue:Swift - Controlla zero di una variabile facoltativa non confezionata

Vendor.h

@interface Vendor: NSObject { 

@property (nonatomic, strong) NSString *firstName; 
@property (nonatomic, strong) NSString *lastName; 
@property (nonatomic, strong) NSString *middleName; 
} 

Nel mio progetto Swift, sto controllando la convalida pari a zero per la proprietà middleName come di seguito:

if anObject.middleNam != nil { // Here, It throws runtime error: fatal error: Unexpectedly found nil while unwrapping an Optional value 
} 

mi lancia un seguito errore di runtime:

fatal error: unexpectedly found nil while unwrapping an Optional value 

Se le caratteristiche di Objective-C esposti in s wift come String? poi mi avrebbe usato il seguente:

if let middleName = anObject.middleName { 

} 

Come dovrei verificare la variabile facoltativa da scartare.

Grazie in anticipo.

+0

È possibile utilizzare 'Se let' con gli optionals implicitamente non aperti - anche se il controllo'! = nil' dovrebbe funzionare erly con 'middleName', come viene definito' anObject'? – Hamish

risposta

5

Se si desidera proprietà ObjectiveC di essere esposti a Swift come optional, segnarlo con _Nullable tag come

@property (nonatomic, strong) NSString * _Nullable middleName; 

Ora nome middleName sarebbe facoltativo di tipo String? invece di String! e si poteva condizionale scartarlo .

Leggi di più riguardo Nullability in ObjC

+0

Nota che la proprietà dell'OP è già esposta in Swift come facoltativo (è solo implicitamente non disponibile) e può usare lo scostamento condizionale su di esso. In Swift 3, un facoltativo facoltativo da scartare è esattamente lo stesso tipo di un normale opzionale: ha solo un attributo che dice al compilatore che ha la possibilità di forzarlo a scartarlo in determinate situazioni. E queste situazioni non includono assegni 'nil' o scartoni condizionali. Il codice dell'OP sta funzionando bene per me - sospetto che il suo problema è che "anObject" è definito come un IUO ed è questo che sta facendo scattare la forza. – Hamish

+0

Anche se sono assolutamente d'accordo sul fatto che aggiungere tag nullability a tipi obj-c è un buon modo per andare, specialmente quando si interfaccia con Swift. – Hamish

+0

@ originaluser2 Sono d'accordo con il tuo punto.sarà implicitamente da scartare facoltativo, e può ancora usare lo scostamento condizionale su di esso ma il compilatore non si lamenterà se non lo si sta facendo e questo potrebbe causare crash in situazioni come '' let middleName: String = object.middleName'. Quindi è una buona pratica contrassegnare con il tag nullable, quindi chi lo userà riceverà l'avviso del compilatore e potrà gestirlo in sicurezza. –

2

Come detto Anil, la soluzione migliore sarebbe quella di modificare il codice Objective-C per aggiungere un po '_Nullable. Ma, come ho capito, il tuo codice Objective-C è una libreria che non puoi modificare. Quindi, devi occuparti di questi String! che può essere nil.

Ma si può semplicemente utilizzare if let tecnica in questo modo:

if let firstName = vendor.firstName { 
    print("Here is my firstName: \(firstName)") 
} else { 
    print("I have no firstName") 
} 
if let middleName = vendor.middleName { 
    print("Here is my middleName: \(middleName)") 
} else { 
    print("I have no middleName") 
} 

if let lastName = vendor.lastName { 
    print("Here is my name: \(lastName)") 
} else { 
    print("I have no lastName") 
} 

Con questo codice Vendor, restituisce il seguente risultato:

@interface Vendor: NSObject 
    @property (nonatomic, strong) NSString *firstName; 
    @property (nonatomic, strong) NSString *lastName; 
    @property (nonatomic, strong) NSString *middleName; 
@end 
@implementation Vendor 
- (instancetype)init 
{ 
    self = [super init]; 
    if (self) { 
     self.firstName = @"Julien"; 
     self.middleName = nil; 
     self.lastName = @"Quere"; 
    } 

    return self; 
} 
@end 

Risultato:

Here is my firstName: Julien 
I have no middleName 
Here is my name: Quere 
Problemi correlati