2015-10-28 8 views
8

Il seguente codice lanci un messaggio che dice 'Initializer per condizionale vincolante deve avere tipo opzionale, non e 'ANYOBJECT''Initializer per condizionale vincolante deve avere tipo opzionale, non e 'ANYOBJECT - Approccio

func parseData2(){ 
     var data:NSData? 


     if let data2 = data { 
      do { 
       let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) 

       if let actualDetails = details where actualDetails.isKindOfClass(NSDictionary) { 
        print("Parse Data") 
       } 

      }catch { 
       print("Error \(error)") 
      } 
     } 

    } 

Per risolvere il sopra l'errore ho usato il seguente codice.

func parseData2(){ 
     var data:NSData? 


     if let data2 = data { 
      do { 
       let details:AnyObject = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) 

       if let actualDetails:AnyObject = details where actualDetails.isKindOfClass(NSDictionary) { 
        print("Parse Data") 
       } 

      }catch { 
       print("Error \(error)") 
      } 
     } 

    } 

C'è un approccio migliore di quanto sopra o il mio codice potrebbe bloccarsi?

C'è un codice più che voglio aggiungere considerando nil controllare, tipo di controllo e quinditipo di controllo getto. Il motivo per cui Swift offre una grande flessibilità ma un po 'difficile da risolvere. Diciamo che ho un dizionario, cityDetails e sto cercando di ottenere dati per self.cityZipCode e self.cityIdentifier, che sono facoltativi, definiti come var cityZipCode: Int? e var cityIdentifier: Int?

if let cityBasic = cityDetails["basicDetails"] where 
cityBasic!.isKindOfClass(NSDictionary) { 

self.cityZipCode = (cityBasic as! NSDictionary)["zip"].integerValue ?? 0 

self.cityIdentifier = (cityBasic as! NSDictionary)["cityId"].integerValue ?? 0 

} 
+0

Non capisco cosa stai chiedendo nell'aggiornamento della tua domanda? O chiarire come si riferisce alla prima parte o porre una nuova domanda per la nuova parte. Al momento il tuo titolo si riferisce ad un problema di 'Optional Binding', la tua prima parte riguarda' do try catch' e ora si tratta di 'down casting 'e' nil coalescing operator' –

+0

Sono un po' confuso con il controllo nullo, controllo del tipo e poi downcasting, come funzionano tutte queste cose insieme? Un codice semplice ma richiede molta comprensione. – andyPaul

+1

[is and as] (http://www.codingexplorer.com/type-casting-swift/), [collegamento facoltativo] (http://www.codingexplorer.com/multiple-optional-bindings-swift-1- 2 /), [prova a catturare] (https://www.hackingwithswift.com/new-syntax-swift-2-error-handling-try-catch). Google è tuo amico per domande di lingua generale. Soprattutto quando riguarda il più scritto su roba –

risposta

5

Non c'è bisogno di scartare il risultato da try. Non è un optional. È necessario trasmettere il risultato da try a NSDictionary. Utilizzare as? per declassarlo.

Best practice: accesso completo al di errore restituito per una buona gestione degli errori

func parseData2(){ 
    var data:NSData? 

    if let data2 = data { 
     do { 
      let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) 

      if let detailsDict = details as? NSDictionary { 
       print("Parse Data") 
      } else if let detailsArray = details as? NSArray { 
       print("array") 
      } 

     } catch { 
      print("Error \(error)") 
     } 
    } 
} 

rapido e sporco: gestione degli errori non è per me!

func parseData2(){ 
    var data:NSData? 

    if let data2 = data { 

     let details = try? NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) 

     if let detailsDict = details as? NSDictionary { 
      print("Parse Data") 
     } else { 
      print("details might be nil, or not an NSDictionary") 
     } 
    } 
} 

Bad Ass Modo: crash sono caratteristiche

func parseData2(){ 
    var data:NSData? 

    if let data2 = data { 

     let details = try! NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) as! NSDictionary 

    } 
} 

qualche informazione in più su più scarta: goccia il codice qui sotto in un parco giochi.

struct SomeStruct { 
    var anOptional : Int? 
    init() { 
    } 
} 

func unwrapWithIfLet() { 

    if let unWrappedStruct = myStruct, let unWrappedSomething = unWrappedStruct.anOptional { 
     print("multiple optional bindings succeeded") 
     // both unWrappedStruct and unWrappedSomething are available here 
    } else { 
     print("something is nil") 
    } 
} 

func unwrapWithGuard() { 

    guard let unWrappedStruct = myStruct, let unWrappedSomething = unWrappedStruct.anOptional else { 
     print("something is nil") 
     return 
    } 
    print("multiple optional bindings succeeded") 
    // both unWrappedStruct and unWrappedSomething are available here 
} 


var myStruct : SomeStruct? 

//unwrapWithGuard() 
//unwrapWithIfLet() 

myStruct = SomeStruct() 
myStruct!.anOptional = 1 

unwrapWithGuard() 
unwrapWithIfLet() 
+0

Ok, nel caso in cui non voglio usare try catch e controlla due cose, object is not nil e isKindOfClass NSArray. Come può essere fatto nel modo più semplice. – andyPaul

+0

@andyPaul aggiornato: ordinato dal salvataggio al semplice –

+2

Punti bonus per la modalità Bad Ass. –

1

Siete alla ricerca di as?, che tenta di convertire la cosa a sinistra per il tipo a destra, e ritorna NIL se la conversione non è possibile:

let details = try NSJSONSerialization.JSONObjectWithData(data2, options: .AllowFragments) 

if let actualDetails = details as? NSDictionary { 
    print("Parse Data") 
} 

Raramente è necessario utilizzare isKindOfClass in Swift. Se ti accorgi di usarlo, chiedi perché, e considera se as o as? funzionerà invece.

+0

Cosa succede se i dettagli non sono nulli e sembra essere un NSArray? – andyPaul

+0

Il codice originale stava verificando esplicitamente NSDictionary, quindi ho pensato che fosse necessario un dizionario per l'analisi per funzionare. Se puoi lavorare con un dizionario _o_ un array, allora non hai affatto bisogno del controllo del tipo; basta rimuovere '.AllowFragments', e consentirà solo dizionari e array. Si prega di descrivere più in dettaglio cosa si sta cercando di realizzare. –

+0

[Rispondi al commento eliminato da R Menke]: Dal codice originale sembrava che il richiedente cercasse di lavorare con un dizionario, nel qual caso hanno bisogno di una variabile di tipo "NSDictionary", nel qual caso "come?" In uno scartare condizionale è l'approccio corretto. Se il loro codice parser dovrebbe procedere _only_ se il risultato è un 'NSDictionary', ma in realtà non ha bisogno di alcuna chiamata specifica per il dizionario (che è improbabile ma possibile), allora' is' sarebbe davvero appropriato. –

Problemi correlati