AnyObject vs. Struct (Any)
Asked Answered
D

4

8

I would like to create a method like this for my projects:

func print(obj: AnyObject) {
    if let rect = obj as? CGRect {
        println(NSStringFromCGRect(rect))
    }
    else if let size = obj as? CGSize {
        println(NSStringFromCGSize(size))
    }

    //...
}

But I can't because CGRect and CGSize are structs and do not conform to the AnyObject protocol. So, any ideas on how this could be done?

Dartboard answered 1/4, 2015 at 13:18 Comment(0)
E
6

@nkukushkin's answer is correct, however, if what you want is a function that behaves differently depending on whether it’s passed a CGRect or a CGStruct, you are better off with overloading:

func print(rect: CGRect) {
    println(NSStringFromCGRect(rect))
}

func print(size: CGSize) {
    println(NSStringFromCGSize(size))
}

In comparison, the Any will be both inefficient (converting your structs to Any and back, could have a big impact if you do this a lot in a tight loop), and non-typesafe (you can pass anything into that function, and it will only fail at runtime).

If your intention is to coerce both types into a common type and then do the same operation on it, you can create a 3rd overload that takes that type, and have the other two call it.

Enterprise answered 1/4, 2015 at 13:25 Comment(0)
L
11

Use Any instead of AnyObject.

Swift provides two special type aliases for working with non-specific types:

AnyObject can represent an instance of any class type.
Any can represent an instance of any type at all, including function types.

The Swift Programming Language

Longfellow answered 1/4, 2015 at 13:19 Comment(0)
E
6

@nkukushkin's answer is correct, however, if what you want is a function that behaves differently depending on whether it’s passed a CGRect or a CGStruct, you are better off with overloading:

func print(rect: CGRect) {
    println(NSStringFromCGRect(rect))
}

func print(size: CGSize) {
    println(NSStringFromCGSize(size))
}

In comparison, the Any will be both inefficient (converting your structs to Any and back, could have a big impact if you do this a lot in a tight loop), and non-typesafe (you can pass anything into that function, and it will only fail at runtime).

If your intention is to coerce both types into a common type and then do the same operation on it, you can create a 3rd overload that takes that type, and have the other two call it.

Enterprise answered 1/4, 2015 at 13:25 Comment(0)
D
2

Just discovered a much better method of doing this. Swift has a method called dump, and it works with a lot of kinds of data.

For example:

dump(CGRectMake(0, 5, 30, 60))

Will print:

{x 0 y 5 w 30 h 60}
Dartboard answered 3/4, 2015 at 14:54 Comment(0)
A
1

If you just need to print a CGRect or CGSize, you could use:

println(rect)

or

println(size)

You left a '...' at the end of your function so I assume there are more types that you need to print. To do that you need to make those types conform to the Printable protocol (unless they already do). Here's an example of how -

class Car { 
    var mileage = 0
}

extension Car : Printable {
    var description: String { 
        return "A car that has travelled \(mileage) miles."
    }
}

The you can use:

let myCar = Car()
println(myCar)

Also, you may want to change the format of the way a type is currently printed. For example, if you wanted println(aRect) in the same format as returned by NSStringFromCGRect you could use the extension:

extension CGRect : Printable {
    public var description: String {
        return "{\(origin.x), \(origin.y)}, {\(size.width), \(size.height)}"
    }
}
Aceous answered 3/4, 2015 at 16:47 Comment(3)
Yes, that's true. But I think "dump" and "NSStringFromCGRect" produces a format that's easier to read. Do you know why?Dartboard
Are you using Playgrounds to test your code? I believe your code dump(CGRectMake(0, 5, 30, 60)) is actually just showing you a preview of the CGRect by the playground. Try the code let rect = CGRect(x: 0, y: 5, width: 30, height: 60); dump(rect) and you should get the same format as println(rect).Aceous
I have updated my answer to talk about how you could change the format when using println though.Aceous

© 2022 - 2024 — McMap. All rights reserved.