Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift dynamic cast failed with HTTP GET request

After creating an app with RubyMotion, this is my first experience with developing apps in Swift with xCode.

I use the following code to get all the posts from an Rails API, the request is successful but parsing the JSON gives an error.

The code:

func loadData() {
    let url = NSURL(string: "http://localhost:3000/api/posts")
    let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {(data, response, error) in
        var err: NSError?
        var json =  NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as NSDictionary
    })
    task.resume()
}

The error:

libswift_stdlib_core.dylib`swift_dynamicCastObjCClassUnconditional:
0x103dbae20:  pushq  %rbp
0x103dbae21:  movq   %rsp, %rbp
0x103dbae24:  pushq  %rbx
0x103dbae25:  pushq  %rax
0x103dbae26:  movq   %rsi, %rcx
0x103dbae29:  movq   %rdi, %rbx
0x103dbae2c:  xorl   %eax, %eax
0x103dbae2e:  testq  %rbx, %rbx
0x103dbae31:  je     0x103dbae4d               ;     swift_dynamicCastObjCClassUnconditional + 45
0x103dbae33:  movq   0x72b66(%rip), %rsi       ; "isKindOfClass:"
0x103dbae3a:  movq   %rbx, %rdi
0x103dbae3d:  movq   %rcx, %rdx
0x103dbae40:  callq  *0x5e212(%rip)            ; (void *)0x0000000105b6f000: objc_msgSend
0x103dbae46:  testb  %al, %al
0x103dbae48:  movq   %rbx, %rax
0x103dbae4b:  je     0x103dbae54               ;     swift_dynamicCastObjCClassUnconditional +     52
0x103dbae4d:  addq   $0x8, %rsp
0x103dbae51:  popq   %rbx
0x103dbae52:  popq   %rbp
0x103dbae53:  retq   
0x103dbae54:  leaq   0xe427(%rip), %rax        ; "Swift dynamic cast failed"
0x103dbae5b:  movq   %rax, 0x7974e(%rip)       ; gCRAnnotations + 8
0x103dbae62:  int3   
0x103dbae63:  nopw   %cs:(%rax,%rax)

Thanks in advance!

like image 419
Matt Dice Avatar asked Jul 25 '14 13:07

Matt Dice


2 Answers

From your URL http://localhost:3000/api/posts I can assume that you receive an array of objects, so you should be casting the result to NSArray.

Code should be:

var json =  NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as NSArray

However as mentioned by Yatheesha, you can receive nil so it is better to cast to nullable array and check in if let...:

if let json =  NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSArray { 
    ... 
}
like image 112
Keenle Avatar answered Sep 28 '22 01:09

Keenle


In your case data may be nil then you will get nil from NSJSONSerialization.JSONObjectWithData() so type casting leads to crash, Try this

 func loadData() {
     let url = NSURL(string: "http://localhost:3000/api/posts")
     let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {(data, response, error) in
         var err: NSError?
         if let json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSArray {

               //Valid NSArray object
          }
         else {
            //NSArray is nil
         }
           })
        task.resume()
        }
like image 41
Yatheesha Avatar answered Sep 28 '22 02:09

Yatheesha