How to Convert Tuple to Anyobject in Swift

How to convert Tuple to AnyObject in Swift

How can I cast/convert a Tuple to AnyObject?

Simply put, you can't. Only class types (or types that are bridged to Foundation class types) can be cast to AnyObject. A tuple is not a class type.

Of course there may be lots of other ways to accomplish whatever you're really trying to accomplish. But as for your particular question, you can't do it.

Tuple upcasting in Swift

Tuples cannot be cast, even if the types they contain can. For example:

let nums = (1, 5, 9)
let doubleNums = nums as (Double, Double, Double) //fails

But:

let nums : (Double, Double, Double) = (1, 5, 9) //succeeds

The workaround in your case is to cast the individual element, not the Tuple itself:

let tuple = ("String", true)
let anyTuple = (tuple.0, tuple.1 as Any)
// anyTuple is (String, Any)

This is one of the reasons the Swift documentation notes:

Tuples are useful for temporary groups of related values. They are not suited to the creation of complex data structures. If your data structure is likely to persist beyond a temporary scope, model it as a class or structure, rather than as a tuple.

I think this is an implementation limitation because Tuples are compound types like functions. Similarly, you cannot create extensions of Tuples (e.g. extension (String, Bool) { … }).


If you're actually working with an API that returns (String, Any), try to change it to use a class or struct. But if you're powerless to improve the API, you can switch on the second element's type:

let tuple : (String, Any) = ("string", true)

switch tuple.1 {

case let x as Bool:
print("It's a Bool")
let boolTuple = (tuple.0, tuple.1 as! Bool)

case let x as Double:
print("It's a Double")
let doubleTuple = (tuple.0, tuple.1 as! Double)

case let x as NSDateFormatter:
print("It's an NSDateFormatter")
let dateFormatterTuple = (tuple.0, tuple.1 as! NSDateFormatter)

default:
print("Unsupported type")
}

If the API returns Any and the tuple isn't guaranteed to be (String, Any), you're out of luck.

Custom class as AnyObject in tuple

You are trying to add a tuple of a different type, because it's (Float, MyClass) and not (Float, AnyObject).

Just change this:

let instance = MyClass()

into:

let instance: AnyObject = MyClass()

and it should work.

Alternatively, you can perform an explicit downcast when creating the tuple

array += [(number, instance as AnyObject)]
array.append((number, instance as AnyObject))

AnyObject' is not a subtype of 'Custom Tuple'

You can cast class types to [Anyobject] (link), but the tuple type has compound type, which is not class type.

How to cast a swift array of tuples to NSMutableArray?

Since swift types like Tuple or Struct have no equivalent in Objective-C they can not be cast to or referenced as AnyObject which NSArray and NSMutableArray constrain their element types to.

The next best thing if you must return an NSMutableArray from a swift Array of tuples might be returning an Array of 2 element Arrays:

let itemsTuple = [("Pheonix Down", "Potion"), ("Elixer", "Turbo Ether")]
let itemsArray = itemsTuple.map { [$0.0, $0.1] }
let mutableItems = NSMutableArray(array: itemsArray)

Cannot convert value of type '(key: String, value: AnyObject)' to expected argument type '[String : AnyObject]'

  • First of all classes are supposed to be named in singular form Post / ThumbImage. The datasource array e.g. posts contains Post instances and each Post instance contains an array thumbnailImages of ThumbImage instances. These semantics make it easier to understand the design.
  • Second of all JSON dictionaries in Swift 3+ are [String:Any]
  • Third of all according to the initialization rules the super call must be performed after initializing all stored properties.

The value of key thumbnail_images is a dictionary containing dictionaries. The error occurs because you are using the array enumeration syntax which treats the dictionary as an array of tuples.

The dictionary can be parsed to use the key as size name and the value to pass the parameters.

I have no idea why you are using NSObject subclasses but I'm sure you have your reasons.


This is the Thumbnail class

class ThumbImage: NSObject {

let size: String
var url : URL?
let width : Int
let height : Int

init(size : String, parameters: [String: Any]) {

self.size = size
if let urlString = parameters["url"] as? String {
self.url = URL(string: urlString)
}
self.width = parameters["width"] as? Int ?? 0
self.height = parameters["height"] as? Int ?? 0
super.init()
}
}

and this the Post class

class Post: NSObject {

var title: String
var excerpt: String
var content: String
var thumbnailImages = [ThumbImage]()

init(dict: [String: Any])
{
self.title = dict["title"] as? String ?? ""
self.excerpt = dict["excerpt"] as? String ?? ""
self.content = dict["content"] as? String ?? ""
super.init()
if let images = dict["thumbnail_images"] as? [String: [String:Any] ] {
for (key, value) in images {
thumbnailImages.append(ThumbImage(size: key, parameters: value))
}
}
}
}

Passing tuple to AFNetworkingRequestManger.GET in Swift

It seems that it is not possible to pass a tuple as parameter values to objective-c code.

Cast / convert dictionary in Swift

You can convert the key/values of the dictionary into an array containing tuples like so:

var dict = [ "1" : 1, "2" : 2, "3" : 3 ]
var array = Array(Zip2(dict.keys, dict.values))

array now has the type [ (String, Int) ].



Related Topics



Leave a reply



Submit