2014-10-22 15 views
6

Sto cercando di estrarre il valore del badge dal dizionario utenteInfo di una notifica remota. Ho letto molti post e ho trovato una soluzione al mio problema ma non sono assolutamente soddisfatto!Swift: '(NSObject, AnyObject)' non ha un membro denominato 'subscript'

Così qui è la mia struttura dati (ho tolto le linee inutili): { aps = { badge = 7 } }

Per estrarre questo numero '7' fuori dalla mia userInfo vorrei fare quanto segue:

self.updateAppIcon(userInfo["aps"]["badge"] as? Int) 

Ma naturalmente ottengo il seguente errore:

Swift: '(NSObject, ANYOBJECT)' non ha un membro denominato 'pedice'

Se non sbaglio, è perché [] restituisce un oggetto AnyObject che non può essere interpretato come un altro dizionario.

Una soluzione lavoro sarebbe quello di effettuare le seguenti operazioni:

func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) { 

    if let aps: AnyObject = userInfo["aps"] { 
     if let apsDict = aps as? [String : AnyObject]{ 
      if let badge: AnyObject = apsDict["badge"] { 
       self.updateAppIconBadgeNumber(badge as? Int) 
      } 
     } 
    } 
} 

func updateAppIconBadgeNumber(number: Int?) { 
    // do stuff here 
} 

Ma sul serio ... potrei farlo in un modo più sexy? meno linee, meno se clausole, meno cast, ecc? Questa è una soluzione "complessa come il codice" di una cosa facile.

Grazie

risposta

9

Il più breve è:

// Xcode 6.0.1 
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) { 
    if let badge = [userInfo["aps"]?["badge"]][0] as? Int { 
     self.updateAppIconBadgeNumber(badge) 
    } 
} 

// Xcode 6.1 
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) { 
    if let badge = userInfo["aps"]?["badge"] as? Int { 
     self.updateAppIconBadgeNumber(badge) 
    } 
} 

? tra ["aps"] e ["badge"] si chiama "Optional Chaining". È necessario perché userInfo["aps"] può restituire nil. E non è necessario trasmetterlo a [String : AnyObject] perché ogni AnyObject ha un membro 'subscript'.

E, Perché abbiamo bisogno [ ... ][0] in Xcode 6.0.1 è ... non lo so :(.a bug, forse.

+1

Grazie mille!Non avevo idea di questo "Concatenamento opzionale". Grazie per entrambe la soluzione e il collegamento! –

3

si potrebbe usare nullo operatore coleascing e rendere più breve, ma si può perdere la leggibilità. Se avere una sola versione a linea del metodo come questo,

func handleRemoteNotification(userInfo: [NSObject : AnyObject]) { 
    if let badge = ((userInfo["aps"] as? [String: AnyObject]) ?? ([String: AnyObject]()))["badge"] as? Int{ 
     self.updateAppIconBadgeNumber(badge) 
    } 
} 

Si potrebbe typealias [String: ANYOBJECT] e farlo sembrare poco più leggibile.

typealias Dict = [String: AnyObject] 
func handleRemoteNotifiation(userInfo: [NSObject : AnyObject]) { 
    if let badge = ((userInfo["aps"] as? Dict) ?? Dict())["badge"] as? Int{ 
     self.updateAppIconBadgeNumber(badge) 
    } 
} 
+0

Grazie per la risposta, questo in realtà funziona perfettamente così, ma è, come tu dici, meno leggibile, la risposta data da @rintaro mi sembra migliore, ma, potrei spiegarmi o condividere un link su questo 'operatore di nilocollegamento' ', non ho idea di cosa si tratti. –

+0

nil coalescing operator: ?? 'è spiegato in dettaglio nell'iBook di Apple: non riesco a bloccarlo in un commento SO, ma qui c'è una copia diretta di ciò che dice il libro: l'operatore coalescente nullo' (a ?? b) 'scava un facoltativo a se contiene un valore o restituisce un valore predefinito b se a è nil. L'espressione a è sempre di tipo facoltativo.L'espressione b deve corrispondere al tipo che è s organizzato all'interno di a. L'operatore a coalescenza nil è una scorciatoia per il seguente codice: 'a! = Nil? un! : b' – ArtSabintsev