Swift 3: Cannot convert value of type 'NSMutableDictionary' to expected argument type '[AnyHashable : Any]!'
If that Flurry.logEvent(_:withParameters:)
takes [AnyHashable: Any]
, why don't you use it as your local userData
?
func logEvent(_ eventName: String, userData: NSMutableDictionary?) {
// Use <userData> or create new one?
var userData = userData as NSDictionary? as? [AnyHashable: Any] ?? [:]
// Set base properties
userData["Num Tofus"] = gUser.tofus.count
userData["Num Lifetime Tofus"] = gUser.getLifetimeTofus()
// Call Flurry
DispatchQueue.main.async {
Flurry.logEvent(eventName, withParameters: userData)
}
}
UPDATE
Xcode 8.1 GM seed including SE-0139 and SE-0140 is out, so the list below is updated.
These are the Objective-C safe types, when set to a [AnyHashable: Any]
dictionary (or set in a [Any]
array, or simply passed to Any
which is a non-null id
in Objective-C) in which is passed to Objective-C world:
Swift 3.0.1/Xcode 8.1
- Optional values including
nil
nil
is converted to NSNull
, all non-nil Optionals are unwrapped.
(NSNull
may not be what you want. Still be careful about nil-checking.)
- All numeric types and
Bool
Int8
, UInt8
, Int16
, UInt16
, Int32
, UInt32
, Int64
, UInt64
, as well asInt
, UInt
, Double
, Float
, CGFloat
and Bool
. These are converted to NSNumber
.
String
Converted to NSString
.
Array
, whereElement
is Objective-C safe
Converted to NSArray
.
Dictionary
, whereKey
andValue
are Objective-C safe
Converted to NSDictionary
.
Set
, whereElement
is Objective-C safe
Converted to NSSet
NSObject
descendent types
Not converted, used as is.
- Value types which have counter-part reference types
See the list here.
- Value types where
NSValue
has an initializer for
NSRange
,CGPoint
,CGVector
,CGSize
,CGRect
,CGAffineTransform
,UIEdgeInsets
,UIOffset
,CATransform3D
,CMTime
,CMTimeRange
,CMTimeMapping
,CLLocationCoordinate2D
,MKCoordinateSpan
,SCNVector3
,SCNVector4
,SCNMatrix4
.
These types are converted to NSValue
. (NSRange
was already convertible to NSValue
in older Swifts, but not well-documented.)
Bad things (example)
Still some values may be converted to _SwiftValue
even in Swift 3.0.1.
- Swift only types such as (Swift-only)enum, struct, tuple...
(See this list.)
I haven't checked all wrapper enums and structs, but some of them (for example, Notification.Name
to NSString
) seem to be safely converted.
Swift 3.0.0/Xcode 8.0
- Non-Optional numeric types and
Bool
Int
, UInt
, Double
, Float
, CGFloat
and Bool
. These are converted to NSNumber
.
- Non-Optional
String
Converted to NSString
.
- Non-Optional
Array
, whereElement
is Objective-C safe
Converted to NSArray
.
- Non-Optional
Dictionary
, whereKey
andValue
are Objective-C safe
Converted to NSDictionary
.
- Non-Optional
Set
, whereElement
is Objective-C safe
Converted to NSSet
- Non-Optional
NSObject
descendent types
Not converted, used as is.
- Non-Optional value types which have counter-part reference types
See the list here. (The linked article is updated for Swift 3.0.1.)
Bad things (example)
These may be converted to _SwiftValue
, which is completely useless and disastrous in Objective-C world.
Int8
,UInt8
,Int16
,UInt16
,Int32
,UInt32
,Int64
,UInt64
- Any Optional values including
nil
- Swift only types such as (Swift-only)enum, struct, tuple...
Cannot convert value of type NSMutableDictionary? to expected argument type [NSObject: AnyObject]!
You need to make a variable to hold your NSMutableDictionary
then pass it to send()
method.
let dictionary = (builder?.build())! as NSMutableDictionary
tracker?.send(dictionary as [NSObject: AnyObject]!)
UPDATE: Another clean way to use in Swift 3
guard let tracker = GAI.sharedInstance().defaultTracker else { return }
tracker.set(kGAIScreenName, value: "ViewController")
guard let builder = GAIDictionaryBuilder.createScreenView() else {
return }
tracker.send(builder.build() as [NSObject:AnyObject])
Cannot convert value of type 'NSMutableDictionary' to expected argument type '[String: AnyObject]?'
Unlike immutable NSDictionary
the mutable NSMutableDictionary
is not related to a Swift Dictionary
and cannot be bridged nor casted.
There is a simple rule to avoid those problems:
In Swift use always Swift native collection types whenever possible.
var addressDict = [String:AnyObject]()
...
addressDict[kSubAdministrativeArea] = self.subAdministrativeArea
...
Cannot convert value of type 'NSArray' to expected argument type '[Any]!'
- Replace NSArray with [NSValue], as @vadian suggested
- Use optional conversion
as?
, since it is more reliable and you won't get a crash if conversion fails. - Use subscript instead of
valueForKey
method.
Here is the code:
if let antiAliasing = dict["antAliasing"] as? [NSValue] {
UIBezierPath.interpolateCGPoints(withHermite: antiAliasing, closed: true)
}
How to convert [AnyHashable: Any] to NSmutableDictionary
It is very straight forward
var d = [AnyHashable: Any]()
d["name"] = "Jay"
d[0] = "Jay"
print(d)
//[AnyHashable(0): "Jay", AnyHashable("name"): "Jay"]
let nsD = NSDictionary(dictionary: d)
print(nsD)
//{
// 0 = Jay;
// name = Jay;
//}
let nsMD = NSMutableDictionary(dictionary: d)
print(nsMD)
//{
// 0 = Jay;
// name = Jay;
//}
Bridging example:
Your swift class may look like this
@objc class Swft: NSObject {
@objc var d = [AnyHashable: Any]()
override init() {
super.init()
d["name"] = "jay"
}
@objc func method() ->[AnyHashable: Any] {
return d
}
}
And your Objective-C class may look like this, .m
#import "Objc.h"
#import "{Your_project_name}-Swift.h"
@interface Objc ()
@end
@implementation Objc
- (void)someMethod {
Swft *s = [[Swft alloc] init];
NSLog(@"1234567890 %@", s.d);
// 1234567890 {
// name = jay;
// }
NSLog(@"0987654321 %@", [s method]);
// 0987654321 {
// name = jay;
// }
}
@end
Swift 3.0 passing NSArray as Any
This code seems to be working in playgrounds and not showing any errors
func someFunc(nsarray: NSArray) {
/// some implementation
}
let array = [Any]()
someFunc(nsarray: array as NSArray)
Swift - Cannot convert value of type 'Any?' to expected argument type 'String'
If it is ok to crash
let temp = json["srvFile0"]! as! String
But much better would be to avoid that
if let temp = json["srvFile0"], let serverFile = temp as? String {
Cannot convert value of type
In swift 3 some things have changed and one of those is that id
from objective c is now Any
in swift instead of AnyObject
. Change your idContext
to type Any
.
Also you must also change the type of your dictionary and the string to an optional. So it becomes String?
and [AnyHashable: Any]?
.
For-in loop requires '[UserVehicles]?' to conform to 'Sequence'; did you mean to unwrap optional? Swift
You need to supply a default value for optional as a good practise instead of force unwrap
for i in vehicleList?._embedded.userVehicles ?? [] { }
Related Topics
Accessing Self from Instance Properties Which Are Closures
How to Install Package in Xcode via Swift Package Manager
Swift Tableview Cell Set Accessory Type
How to Add Caching to Asyncimage
How to Select a Contact with Abpeoplepickernavigationcontroller in Swift
One-Way Platform Collisions in Sprite Kit
How to Highlight a Uitextview's Text Line by Line in Swift
Button Border with Transparent Background in Swift
How to Insert an Image Inline Uilabel in iOS 8 Using Swift
Swift Error When Trying to Access Dictionary: 'Could Not Find Member 'Subscript''
Swift Only -- Reading from Nsinputstream
Unsafemutablepointer<Uint8> to [Uint8] Without Memory Copy
What Is Import Func, Struct, Class, and @_Exported in Swift
Function Taking a Variable Number of Arguments