2014-10-22 2 views
6

Я пытаюсь извлечь значение значка из словаря userInfo удаленного уведомления. Я прочитал много сообщений и нашел решение моей проблемы, но я очень недоволен!Swift: '(NSObject, AnyObject)' не имеет члена с именем 'subscript'

Так вот моя структура данных (я удалил ненужные строки): { aps = { badge = 7 } }

Чтобы извлечь этот номер «7» из моего userInfo я хотел бы сделать следующее:

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

Но Конечно, я получаю следующее сообщение об ошибке:

Swift: «(NSObject, AnyObject)» не имеет член с именем «подстрочный»

Если я не ошибаюсь, это потому, что [] возвращает AnyObject, который нельзя интерпретировать как другой словарь.

рабочий раствор будет сделать следующее:

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 
} 

Но серьезно ... я мог сделать это в более сексуально? меньше строк, меньше, если клаузулы, меньше бросков и т. д.? Это такое «кодовое комплексное» решение простой вещи.

Благодаря

ответ

9

Самый короткий из них:

// 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) 
    } 
} 

? между ["aps"] и ["badge"] называется "Optional Chaining". Вам это нужно, потому что userInfo["aps"] может вернуть nil. И вам не нужно указывать его на [String : AnyObject], потому что каждый AnyObject имеет «подстрочный» член.

И зачем нам нужно [ ... ][0] в Xcode 6.0.1 это ... Я не знаю :(.a ошибка, может быть.

+1

Большое спасибо!Я не имел понятия об этом «Необязательном цепочке». Спасибо за ваше решение и ссылку! –

3

Вы можете использовать ноль coleascing оператора и сделать его коротким, но вы можете потерять читаемость. Если есть одна версия строки метода, как это,

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

Вы можете typealias [String: AnyObject] и сделать его немного более удобным для чтения.

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

Спасибо за ваш ответ, это на самом деле работает отлично, как хорошо, но есть, как вы говорите, менее читабельны. Ответ, который дал @rintaro, мне кажется лучше, но, может объяснить или поделиться ссылкой об этом «nil coleascing operator»? », я понятия не имею, что это такое. –

+0

' nil коалесцирующий оператор: ?? 'подробно объясняется в iBook от Apple. Я не могу представить его в комментариях SO, но вот прямая копия того, что написано в книге: nil-коалесцирующий оператор' (a ?? b) 'разворачивает необязательный a, если он содержит значение, или возвращает значение по умолчанию b, если a равно nil. Выражение a всегда имеет необязательный тип. Выражение b должно соответствовать типу s хранится внутри a. Оператор коалесценции nil является сокращенным для кода ниже: 'a! = Nil? а! : b' – ArtSabintsev

Смежные вопросы