Kodeco Forums

Getting to Know Enums, Structs and Classes in Swift

Learn about the difference between enums, structs, and classes in Swift, when to use each, and how they work!


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1314-getting-to-know-enums-structs-and-classes-in-swift
1 Like

this tutorial was enlightening. please keep this way, using playground and examples that gives immediate feedback, as drawable objects. thank you :]

1 Like

One topic that fell on the cutting room floor was to using the ClosedShapeType protocol as a Type constraint.

Because ClosedShapeType doesn’t have a associated type or Self constraint it can be used the way it is in the article. Any model type 
 class, enum, struct can be used almost like a base class. I think the fancy name for this is a heterogeneous protocol.

func totalPerimeter(shapes: [ClosedShapeType]) -> Double {
  return shapes.reduce(0) { $0 + $1.perimeter }
}

On the other hand, if ClosedShapeType had an associated type or Self requirement you could only use it as a constraint. T is locked down to a particular type. This is a homogeneous protocol.

func totalPerimeter<T: ClosedShapeType>(shapes: [T]) -> Double {
    return shapes.reduce(0) { $0 + $1.perimeter }
}
totalPerimeter([rectangle,rectangle])

Incidentally, you can define both of these functions and it is not an error. The compiler will always resolve to the heterogeneous definition. (I’m not sure how to make it call the second one without renaming the function.)

Hi, Ray, I’m a Chinese, I’m tring to translate this article into Chinese, but I met a problem, can you help me?

What’s the meaning of backing store in dark green Color? i can’t understand it, thanks!:blush:

Thanks for the question!

It refers to the actual type used to represent the enum. So for

enum SideOfCoin: String {
  case Heads, Tails
}

This is a RawRepresentable of type String. In other words, String is the “backing store” or the memory representation of the enum.

1 Like

I got it, thank you very much.

1 Like

Thank you for this great Tutorial.Benefit a lot.
Thank your work again !!

1 Like

I think that SVGContext’s SVGString could have been expressed more elegantly as
return commands.reduce("<svg width='\(width)' height='\(height)'>") { $0 + $1 } + "</svg>"

1 Like

Nice tip! I was reluctant to use reduce, although I did manage to sneak one in right at the end with totalPerimeter :slight_smile:

On the other hand, reduce used in this case will produce a lot of String temporaries. Usually this is not of big concern unless you have large data sets. The simple mutating version runs 30% faster on my machine.

    func testPerformanceReduce() {
        let strings = Array(count: 1000000, repeatedValue: "This is html string<br/>")        
        self.measureBlock {
            let _ = strings.reduce("<html>") { $0 + $1 } + "</html>"
        }
    }
    
    func testPerformanceMutate() {        
        let strings = Array(count: 1000000, repeatedValue: "This is html string<br/>")        
        self.measureBlock {
            var html = "<html>"
            for string in strings {
                html += string
            }
            html += "</html>"
        }
    }

That’s absolutely true, but I’d still go for the more compact and elegant code and worry about performance when/if issues arise :smiley:

1 Like

Thanks for this tutorial @rayfix. It really helped me get a better understanding of enums and what I can do with them.

1 Like

Really good tutorial. Thanks.

1 Like

Quite helpful, thanks!

Very nice tutorial !

Note: the playground does not display circle and rectangle.

To fix it – in the code right above “Using Classes”

is:

let view = 
 width: 100, height: 100))

should be:

let view = 
 width: 250, height: 250))

Thanks James! I updated the tutorial text. I guess it was correct in the final playground download already. :sweat_smile:

Using latest XCode 8.3.

Error in “Struct Circle : Drawable”

Playground execution failed: error: Shapes.playground:57:22: error: missing argument label ‘circle:’ in call
context.draw(self)
^
circle:

Should be “context.draw(circle: self)” instead of “context.draw(self)”.

Correction again
 so here’s the problem with this


This “context.draw(self)” is actually correct
 only when you get to the Rectangle part since you will now be updating the protocol DrawingContext to below:

protocol DrawingContext {
func draw(_ circle: Circle)
func draw(_ rectangle: Rectangle)
}

So this “context.draw(circle: self)” becomes an error in “struct Rectangle : Drawable”.

I think you just need to add a notice when the learner is on “Struct Circle : Drawable” that “context.draw(self)” will throw an error since the protocalDrawingContext is still

protocol DrawingContext {
func draw(circle: Circle)
// more primitives will go here 

}

Also, there’s an exra "" in cy='(circle.center.y)'.

Error in “struct SVGDocument” in this line: “drawable.draw(context)”. Should be “drawable.draw(with: context)”.

Playground execution failed: error: Shapes.playground:116:27: error: missing argument label ‘with:’ in call
drawable.draw(context)
^
with:

Final error: “Shapes[26679:700685] Failed to obtain sandbox extension for path=/var/folders/vc/_d1p_t8n1j7g_k25txw3qhr00000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.Shapes-C8B14ED7-522C-4E13-B3D9-8E85B445A645/Library/Caches/com.apple.dt.playground.stub.iOS_Simulator.Shapes-C8B14ED7-522C-4E13-B3D9-8E85B445A645.”.

Add this after “import PlaygroundSupport” for the error to go away:

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

1 Like

I get the “Failed to obtain sandbox extension for path” (same as the poster above), except when I run the final version of the playground downloaded from the site. Even if I copy and paste the code exactly into a separate playground file, I get the error (and the shapes are drawn much smaller than they’re supposed to be). I can’t figure out why the downloaded file doesn’t have the error, even if the source code is exactly the same.

This tutorial is more than six months old so questions regarding it are no longer supported for the moment. We will update it as soon as possible. Thank you! :]