stm
stm

Reputation: 121

Swift 5: How to test an AnyObject? variable for it's value's type?

I'm currently porting an iOS app from Objective-C to Swift. While doing that I just stumbled across a problem I'm struggling with.

I have a variable ("value") which can bet set to AnyObject?, especially can it be of type String, Array, Dictionary and Set. Now, in my previous code I was testing my "value" variable for its value's type in order to further work with it:

id value = [myDatahandler getValue];

if (([value isKindOfClass:[NSSet class]] || [value isKindOfClass:[NSArray class]]) && [value count] > 0) {
        // do something
}

Trying to do the same in Swift seems not to work...

var value: AnyObject? = myDatahandler.getValue()

if (value is Set || value is Array) && value!.count > 0 {
        // Error:
        // Generic parameter 'Element' could not be inferred in cast to 'Array'
        // Generic parameter 'Element' could not be inferred in cast to 'Set'
}

After a couple of hours searching for the right way to do this but not finding anything helpful, I hope the community can come to my rescue here...

Any suggestions how this could work?

Upvotes: 0

Views: 929

Answers (3)

Kiel
Kiel

Reputation: 235

Use Any rather than AnyObject because from HackingWithSwift page

AnyObject refers to any instance of a class, and is equivalent to id in Objective-C. It’s useful when you specifically want to work with a reference type, because it won’t allow any of Swift’s structs or enums to be used. AnyObject is also used when you want to restrict a protocol so that it can be used only with classes.

Any refers to any instance of a class, struct, or enum – literally anything at all. You’ll see this in Swift wherever types are unknown or are mixed in ways that can be meaningfully categorized:

Then, you can use a guard for unwrapping an optional value

guard let value =  myDatahandler.getValue() as? [YourClass], !value.isEmpty {
   return
}

Upvotes: 1

Pete Morris
Pete Morris

Reputation: 1562

The problem is that Set and Array are both generic types. You must provide the element type.

For example, if you're expect they contain Strings:

if (value is Set<String> || value is Array<String>) && value!.count > 0 {

}

If you just care that it's an array or set (and you don't care about the element type), you could use Any as the element type:

if (value is Set<Any> || value is Array<Any>) && value!.count > 0 {

}

Upvotes: 0

Harsh
Harsh

Reputation: 2908

I feel like you can use a guard to do this.. Hope the following piece of code works.

guard let value =  myDatahandler.getValue() as? [Element] , value.count > 0 else {
    return
}

print(value)

Upvotes: 1

Related Questions