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?

iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
Paulo Cesar
  • 2,250
  • 1
  • 25
  • 35

4 Answers4

10

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

Nikita Kukushkin
  • 14,648
  • 4
  • 37
  • 45
5

@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.

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
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}
Paulo Cesar
  • 2,250
  • 1
  • 25
  • 35
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)}"
    }
}
ABakerSmith
  • 22,759
  • 9
  • 68
  • 78
  • Yes, that's true. But I think "dump" and "NSStringFromCGRect" produces a format that's easier to read. Do you know why? – Paulo Cesar Apr 03 '15 at 20:48
  • 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)`. – ABakerSmith Apr 03 '15 at 22:11
  • I have updated my answer to talk about how you could change the format when using `println` though. – ABakerSmith Apr 03 '15 at 22:12