'(NSObject, AnyObject)' is not convertible to 'String'

11,556

Solution 1

A String is not an object, so you do need to cast it to an NSString. I would recommend the following syntax to cast it and unwrap it at the same time. Don't worry about comparing it to a variable of type String! since they are compatible. This will work:

func formatPlacemark(placemark: CLPlacemark) -> (String, String) {
    if let street = placemark.addressDictionary["Street"] as? NSString {
        if placemark.name == street {
            // Do something
        }
    }
}

This has the added benefits that if "Street" is not a valid key in your dictionary or if the object type is something other than NSString, this will not crash. It just won't enter the block.

If you really want street to be a String you could do this:

if let street:String = placemark.addressDictionary["Street"] as? NSString

but it doesn't buy you anything in this case.

Solution 2

The return type from looking up via subscript for a swift dictionary has to be an optional since there may be no value for the given key.

Therefor you must do:

as String?

Solution 3

I think it may have to do with addressDictionary being an NSDictionary.

If you convert addressDictionary to a Swift dictionary, it should work.

let street = (placemark.addressDictionary as Dictionary<String, String>)["String"]
Share:
11,556
ma11hew28
Author by

ma11hew28

Updated on August 17, 2022

Comments

  • ma11hew28
    ma11hew28 over 1 year

    How do I convert an object of type (NSObject, AnyObject) to the type String?

    At the end of the first line of the method below, as String causes the compiler error:

    '(NSObject, AnyObject)' is not convertible to 'String'
    

    Casting street to NSString instead of String compiles, but I'm casting street to String because I want to compare it to placemark.name, which has the type String!, not NSString.

    I know name and street are optionals, but I'm assuming they're not nil for now because all the places returned from MKLocalSearch seem to have non-nil names and streets.

    func formatPlacemark(placemark: CLPlacemark) -> (String, String) {
        let street = placemark.addressDictionary["Street"] as String
        if placemark.name == street {
            // Do something
        }
    }
    
  • ma11hew28
    ma11hew28 over 9 years
    How do you know I can do placemark.name == street instead of street.isEqualToString(placemark.name)? I want to make sure I'm checking for string equality (isEqualToString), not object identity (==).
  • ma11hew28
    ma11hew28 over 9 years
    But, is this slower than @vacawama's solution? Because isn't Dictionary completely different than NSDictionary? So, would that mean by casting the NSDictionary to Dictionary, the program will have to create a completely new Dictionary object and fill it with the keys & values of the original NSDictionary? That sounds like more work than just a simple cast.
  • vacawama
    vacawama over 9 years
    Swift automatically bridges between the two types, and == is the Swift way of testing string equality. See: developer.apple.com/library/prerelease/mac/documentation/Swi‌​ft/…
  • vacawama
    vacawama over 9 years
    Try this in a Playground:var a:NSString = "abcdefg" var b:String = "abc" + "defg" if a == b { println("yep they're the same") }
  • vacawama
    vacawama over 9 years
    This isn't safe. If any value in the dictionary is an object other than an NSString, this will crash the app. You'd only do this if you were 100% sure all of the objects were NSStrings, and then you'd do it only once, when the data is first created. If you are calling an API external to your app to get the NSDictionary, it would be safer to check each object with the optional form of the type cast operator (as?).