44

how can i convert any object type to a string?

let single_result = results[i]
var result = ""
result = single_result.valueForKey("Level")

now i get the error: could not assign a value of type any object to a value of type string.

and if i cast it:

result = single_result.valueForKey("Level") as! String

i get the error: Could not cast value of type '__NSCFNumber' (0x103215cf0) to 'NSString' (0x1036a68e0).

How can i solve this issue?

2
  • of what type is single_result.valueForKey(“Level”) Have you tried using String(single_result.valueForKey(“Level”)) Commented May 16, 2015 at 19:43
  • 1
    What is results of type? Commented May 16, 2015 at 19:49

4 Answers 4

45

You can't cast any random value to a string. A force cast (as!) will fail if the object can't be cast to a string.

If you know it will always contain an NSNumber then you need to add code that converts the NSNumber to a string. This code should work:

if let result_number = single_result.valueForKey("Level") as? NSNumber
{
  let result_string = "\(result_number)"
}

If the object returned for the "Level" key can be different object types then you'll need to write more flexible code to deal with those other possible types.

Swift arrays and dictionaries are normally typed, which makes this kind of thing cleaner.

I'd say that @AirSpeedVelocity's answer (European or African?) is the best. Use the built-in toString function. It sounds like it works on ANY Swift type.

EDIT:

In Swift 3, the answer appears to have changed. Now, you want to use the String initializer

init(describing:)

Or, to use the code from the question:

result = single_result.valueForKey("Level")
let resultString = String(describing: result)

Note that usually you don't want valueForKey. That is a KVO method that will only work on NSObjects. Assuming single_result is a Dictionary, you probably want this syntax instead:

result = single_result["Level"]
Sign up to request clarification or add additional context in comments.

2 Comments

Or you can use result_number.stringValue
You can just use toString directly on the value without casting it.
33

This is the documentation for the String initializer provided here.

let s = String(describing: <AnyObject>)

Nothing else is needed. This works for a diverse range of objects.

4 Comments

This looks like the start of a useful answer, but it ended up in the review queues because it lacked enough explanation. Please edit the answer to add some more information.
Is that long enough?
I get error "No exact matches in call to initializer"
@Curtis, sorry for the super late response, did you figure this out? What object were you passing to the initializer?
7

The toString function accepts any type and will always produce a string.

If it’s a Swift type that implements the Printable protocol, or has overridden NSObject’s description property, you’ll get whatever the .description property returns. In the case of NSNumber, you’ll get a string representation of the number.

If it hasn’t, you’ll get a fairly unhelpful string of the class name plus the memory address. But most standard classes, including NSNumber, will produce something sensible.

import Foundation

class X: NSObject {
    override var description: String {
        return "Blah"
    }
}

let x: AnyObject = X()
toString(x)  // return "Blah"
"\(x)"  // does the same thing but IMO is less clear

struct S: Printable {
    var description: String {
        return "asdf"
    }
}

// doesn't matter if it's an Any or AnyObject
let s: Any = S()
toString(s) // reuturns "asdf"

let n = NSNumber(double: 123.45)
toString(n)    // returns "123.45"
n.stringValue  // also works, but is specific to NSNumber

(p.s. always use toString rather than testing for Printable. For one thing, String doesn’t conform to Printable...)

3 Comments

So is string interpolation just calling toString?
I didn't know that toString was implemented in all Swift classes. Thanks for that. (Voted)
Note that toString was removed in Swift 3. use String(describing:) instead
6

toString() doesn't seem to exist in Swift 3 anymore.

Looks like there's a failable initializer that will return the passed in value's description.

init?(_ description: String)

Docs here https://developer.apple.com/reference/swift/string/1540435-init

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.