2015-02-10 77 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 

Plugin.swift:176點到:

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

我想念什麼嗎?我認爲這個代碼應該是安全的。

如果contactImagesByEmails is Array<String>返回true,爲什麼contactImagesByEmails as Array<String>失敗?

請幫幫忙,

[編輯]

command有型的CDVInvokedUrlCommand

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

你期望'var obj:AnyObject = command.arguments [0]作爲AnyObject!'做什麼?我可以看到它是如何編譯的,但我無法想象它如何做到有用。投射到「AnyObject!」是一個非常奇怪的沮喪。 – 2015-02-10 20:15:36

+0

@RobNapier'obj [「getContactImagesByEmails」]'返回可選的,所以我解開它,並承諾'theData'不是'nil',否則它會在之前崩潰。我該如何寫這個? – snaggs 2015-02-10 20:17:46

+0

你真正期望'command.arguments [0]'是什麼類型?你期望它是一個字典嗎?它是一個字典嗎?什麼類型是'命令?' – 2015-02-10 20:18:27

回答

2

我不知道這是否可以真正解決問題,但有一點冗餘在2 if和以下let。它可以簡單地寫爲:調用getImagesByEmailAsWmContactImage

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

末時

if let contactImagesByEmails = obj["emails"] as? Array<String> { 
    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 {0} { 靜態讓實例= WmSqliteImagesModel() } 回報Singleton.instance }' – snaggs 2015-02-10 20:22:27

+0

名稱中的動詞通常表明它的東西,即它是一種方法 - 我將其重命名爲'instance'爲清楚 - 但是這只是一個文體的東西 – Antonio 2015-02-10 20:28:12

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充滿了各種類型的東西,你必須鍵入檢查是非常危險的,並且是一個嚴重的設計問題的跡象。如果真的有幾種類型的話,你應該使用enum而不是像[String:AnyObject]這樣的隨機事物進行類型檢查。這就是枚舉明確要求的。 (如果這是從ObjC橋接的;枚舉在這裏可能是不可能的,但即使在ObjC中,正確的答案也很少有一個填充了異構類型的NSArray。您在那裏創建一個類來保存它們而不是枚舉。)

+0

謝謝你的詳細描述。我會嘗試這種方法,並會接受。在cordova中,我從Javascript獲得對象(命令)(無類型變量) – snaggs 2015-02-10 21:09:06