2015-02-10 3 views
1

я следующие фрагменты кода, где у меня есть аварии на некоторых устройствах:Swift: Downcast приводит к сбою приложения, почему?

Crashed: com.apple.root.default-qos 
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x00000000cbd 

Код:

var obj:AnyObject = command.arguments[0] as AnyObject! 
var theData:AnyObject = obj["getContactImagesByEmails"] as AnyObject! 

if let contactImagesByEmails:AnyObject = obj["emails"]{ 
    if contactImagesByEmails is Array<String>{ 
/*line 176*/ let array:Array<String> = 
        contactImagesByEmails as Array<String> // CRASH happens here 

     results = WmSqliteImagesModel.getInstance.getImagesByEmailAsWmContactImage(array) as Dictionary<String,AnyObject> 
      } 
     } 

Полных трассировки стека

Thread : Crashed: com.apple.root.default-qos 
0 libswiftCore.dylib    0x0000000100559794 swift_unknownRetain + 32 
1 MyApp      0x000000010017c8a0 MyApp.Plugin.(getContactImagesByEmails (MyApp.Plugin) -> (ObjectiveC.CDVInvokedUrlCommand) ->()).(closure #1) (Plugin.swift:176) 
2 MyApp      0x000000010017c8a0 MyApp.Plugin.(getContactImagesByEmails (MyApp.Plugin) -> (ObjectiveC.CDVInvokedUrlCommand) ->()).(closure #1) (Plugin.swift:176) 
3 MyApp      0x00000001001790b0 partial apply forwarder for reabstraction thunk helper from @callee_owned() -> (@unowned()) to @callee_owned (@in()) -> (@out()) with unmangled suffix "125" (Plugin.swift:62) 
4 MyApp      0x0000000100179120 partial apply forwarder for reabstraction thunk helper from @callee_owned (@in()) -> (@out()) to @callee_owned() -> (@unowned()) with unmangled suffix "128" (Plugin.swift:62) 
5 libdispatch.dylib    0x00000001937e13ac _dispatch_call_block_and_release + 24 
6 libdispatch.dylib    0x00000001937e136c _dispatch_client_callout + 16 
7 libdispatch.dylib    0x00000001937ed40c _dispatch_root_queue_drain + 1152 
8 libdispatch.dylib    0x00000001937ee75c _dispatch_worker_thread3 + 108 
9 libsystem_pthread.dylib  0x00000001939bd2e4 _pthread_wqthread + 816 

The Plugin.swift:176 точка по:

let array:Array<String> = contactImagesByEmails as Array<String> 

Пропустить что-нибудь? Я думаю, что этот код должен быть безопасным.

если contactImagesByEmails is Array<String> возвращает true, почему contactImagesByEmails as Array<String> не удается?

Пожалуйста, помогите,

[EDIT]

command имеет тип CDVInvokedUrlCommand

@interface CDVInvokedUrlCommand : NSObject { 
    NSString* _callbackId; 
    NSString* _className; 
    NSString* _methodName; 
    NSArray* _arguments; 
} 
+0

Что вы ожидаете? Var obj: AnyObject = command.arguments [0] как AnyObject! 'Делать? Я вижу, как он компилируется, но я не могу себе представить, как он делает что-нибудь полезное. Кастинг в 'AnyObject!' - очень странный downcast. –

+0

@RobNapier 'obj [" getContactImagesByEmails "]' возвращает Необязательно, поэтому я развожу его и обещаю, что 'theData' не' nil', иначе он будет аварийно завершен. Как мне это написать? – snaggs

+0

Какой тип вы действительно ожидаете 'command.arguments [0]' быть? Вы ожидаете, что это словарь? Это словарь? Какой тип 'command?' –

ответ

2

Я не знаю, может ли это на самом деле исправляет эту проблему, но есть немного избыточности в 2 if и следующих let. Это просто можно записать в виде:

if let contactImagesByEmails = obj["emails"] as? Array<String> { 
    results = WmSqliteImagesModel.getInstance.getImagesByEmailAsWmContactImage(contactImagesByEmails) as Dictionary<String,AnyObject> 
} 

Кроме того, было бы безопаснее, чтобы объединить дополнительные обязательные и необязательные потупив при вызове getImagesByEmailAsWmContactImage

if let results = WmSqliteImagesModel.getInstance.getImagesByEmailAsWmContactImage(contactImagesByEmails) as? Dictionary<String,AnyObject> { 
    ... 
} 

последнее, вы уверены, что getInstance этого свойства, а не метод ? Не должен быть:

if let results = WmSqliteImagesModel.getInstance().getImagesByEmailAsWmContactImage(contactImagesByEmails) as? Dictionary<String,AnyObject> { 
    ... 
} 
+0

' getInstance' является экземпляром Singelton: 'class var getInstance: WmSqliteImagesModel { struct Singleton { статический экземпляр пусть = WmSqliteImagesModel() } возвращение Singleton.instance } ' – snaggs

+0

глагол в имени обычно указывает на то, что-то делает, то это метод - я бы переименовать его в' instance' для ясности - но это просто стилистическая вещь – Antonio

1

Возможен попробовать альтернативный подход к получению с приведением значения:

if let contactImagesByEmails = obj["emails"] as? [String] { 
     results = WmSqliteImagesModel.getInstance.getImagesByEmailAsWmContactImage(contactImagesByEmails) as Dictionary<String,AnyObject> 
    } 

Я также задаюсь вопрос, если ваш крах не из именования переменного «массива» в исходном коде ...

1

Упростите это шаг за шагом с меньшим количеством ссылок на AnyObject (и, конечно же, не AnyObject!). Компилятор, вероятно, пропускает что-то незаконное, потому что когда вы начинаете вытаскивать AnyObject, вы говорите: «Я точно знаю, что я делаю, не проверяйте это».

Вы ожидали бы, что этот код будет что-то вроде:

let obj = command.arguments[0] 
if let contactImagesByEmails = obj["emails"] as? [String] { 
    results = WmSqliteImagesModel.getInstance.getImagesByEmailAsWmContactImage(array) as? [String: AnyObject] 
} 

В конце results будет [String:AnyObject]?

Ключевым моментом здесь является то, что вы должны избавиться от как можно большего числа ссылок на AnyObject как вы можете, и вы должны использовать if-let-as?, чтобы определить, являются ли типы ожидаемыми.

Дело в том, что command.arguments заполнено вещами различного типа, которые вы должны вводить с проверкой, довольно опасно и является признаком серьезной проблемы с дизайном. Если там действительно несколько типов, вы должны использовать перечисление, а не проверку типов от случайных вещей, таких как [String:AnyObject]. Вот для чего явно перечислены перечисления. (Если это перемычка из ObjC, перечисления могут быть невозможны здесь, но даже в ObjC, правильный ответ редко состоит из NSArray, заполненного разнородными типами. Вы создаете класс для их хранения, а не enum.)

+0

Благодарим вас за подробное описание. Я попробую этот подход и соглашусь. В кордове я получаю объект (команду) от Javascript (no-type-variable) – snaggs

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