1

I'm trying to fill my arrays with datas in JSONArray that i get from server and I'm doing that with this code(swift 3 Xcode 8):

 func parseReservationJson(_ anyObject:Array<AnyObject>){
            nodes.removeAll()
            reservations.removeAll()
            for anyObj in anyObject{
                let client_name = (anyObj["client_name"] as? String) ?? ""
                let client_family  =  (anyObj["client_family"] as? String) ?? ""
                let ft_of_time = ((anyObj["ft_of_time"] as AnyObject as! NSString).substring(to: 5) as NSString)
            }
    }

But I'm getting this error for the last line of for statement :

Could not cast value of type '_SwiftValue' (0x112d8a898) to 'NSString' (0x11003eab8).

what is wrong?

Amir_P
  • 8,322
  • 5
  • 43
  • 92
  • What is `_SwiftValue`? You are going to cast the result of `anyObj["ft_of_time"]` to `NSString` and the compiler says you can't. And use the native Swift `substringTo`. I know it's more difficult to get the appropriate index but it's more reliable. – vadian Sep 17 '16 at 08:31
  • I wouldn't ask if i knew the answer! i don't have any idea why I'm getting that error for converting `AnyObject` to `NSString` @vadian – Amir_P Sep 17 '16 at 08:33
  • OK, next question: What is the actual type of the result of `anyObj["ft_of_time"]`? – vadian Sep 17 '16 at 08:35
  • A string like "10:20:25" @vadian – Amir_P Sep 17 '16 at 08:36
  • I wrote an answer – vadian Sep 17 '16 at 08:46
  • I'm getting this in console `Optional(10:30:00)` @Hamish – Amir_P Sep 17 '16 at 08:52
  • 1
    @Amir_P Yes, I realised after posting my comment that it'd be an optional. The problem is that Swift has no idea how to bridge optionals to Objective-C, so it falls back on boxing it with `_SwiftValue` – which isn't castable to `NSString`. See [this Q&A](http://stackoverflow.com/questions/39033194/anyobject-not-working-in-xcode8-beta6) for more info about `_SwiftValue`. – Hamish Sep 17 '16 at 08:58
  • thanks that was the problem and solved @Hamish – Amir_P Sep 17 '16 at 09:00

4 Answers4

2

The bad point resides here:

anyObj["ft_of_time"] as AnyObject

(Please check this.)

If you are sure anyObj["ft_of_time"] is of type NSString, simply use as!, else you should use Optional binding:

if let rawFt_of_time = anyObj["ft_of_time"] as? NSString {
    let ft_of_time = Utils.convert_string(string: rawFt_of_time.substring(to: 5) as NSString)
    //Use ft_of_time here...
}

Do not use as AnyObject to silence the compiler...

Community
  • 1
  • 1
OOPer
  • 47,149
  • 6
  • 107
  • 142
1

The error reason is that Swift 3 AnyObject? cannot be cast directly to Foundation NSString.

You could write

let ft_of_time = ((anyObj["ft_of_time"] as! String as NSString).substring(to: 5) as NSString)

But I recommend to replace the entire line with

let ftOfTime = anyObj["ft_of_time"] as! String
let ft_of_time = ftOfTime.substring(to:ftOfTime.index(ftOfTime.startIndex, offsetBy: 5)) as NSString

It does the same but it uses native Swift API. Except the final cast to NSString (if needed at all) there is no type casting back and forth.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • the code was working with swift 2 but after converting to swift 3 it stopped working – Amir_P Sep 17 '16 at 08:58
  • `NSString` is foundation but `String` isn't? then what is `String`? – mfaani Sep 17 '16 at 13:20
  • `String` is a native Swift type, a struct with value type semantics (unlike Foundation's `NSString` which is reference type). It's quite similar to `NSString` but has a few different functions. For compatibility `String` can be easily bridged to `NSString`. – vadian Sep 17 '16 at 14:02
0

You can convert String to NSString like

let swiftString:String = "Swift style string"
let objCString:NSString = NSString(string:swiftString)

so first cast your string to nsstring properly then you can use methods of nsstring

Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
-1

This problem (Could not cast value of type '_SwiftValue' to 'NSString') can be solved like this too:

    let price = "\(String(describing: single_product_dict.value(forKey: "total_price_format") ?? ""))"
    cell.lblPrice.text = price
Shivam Tripathi
  • 1,405
  • 3
  • 19
  • 37