Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Enumerations and Optionals in Swift Introduction to Enumerations Enum Methods

Not to sure what to do

Can someone please walk me step by step as to how to move forward from this?

buttons.swift
// Example of UIBarButtonItem instance
// let someButton = UIBarButtonItem(title: "A Title", style: .plain, target: nil, action: nil)

enum BarButton {
    case done(title: String)
    case edit(title: String)
}


 let done = BarButton.done(title: "save")

3 Answers

Alphonso Sensley II
Alphonso Sensley II
8,514 Points

Hi Eddie,

On this challenge they give a pretty good example that is commented out at the top of the editor. Also keep in mind to access a types member we use the . syntax. For example for type BarButton we can access "done" by entering BarButton.done.

read the example given in at the top of the editor and I think you should be able to get it!

Jaroslaw Adamowicz
Jaroslaw Adamowicz
11,634 Points

Hi Eddie,

challange accepted!

I agree, there are some huge hops in this challange. Also I think there should be UIBarButtonItemStyle not UIBarButtonStyle.

But lets start form beginning.

First:

add a method to the enum named button that returns an instance of the class UIBarButtonItem configured properly.

Let's do just that for now:

enum BarButton {
    case done(title: String)
    case edit(title: String)

    func button() -> UIBarButtonItem {

    }
}

Ok, our method (or function) is not working yet, but that is the "shell" for it. One of the things you need to figure out, how to distinguish which case we have in enum itself?

Normally I would have something like this:

let MyButton: BarButton = BarButton.done

switch MyButton {
    case BarButton.done:
        print("My button is done")
    case BarButton.edit:
        print("My button can edit something!")
}

Ok, but inside enum I'm lacking of this first thing called MyButton for which I can switch, right? But here comes magic word: self.

Let's see how it will look like:

enum BarButton {
    case done(title: String)
    case edit(title: String)

    func button() -> UIBarButtonItem {
        switch self {
            case .done:
                print("I now how to check for done inside enum!")
            case .edit:
                print("same as above but for edit")
        }
    }
}

Two things still missing, as we read in description:

In the method, using the associated values as titles for the button, return a button with style

We still don't have button and do not use associated values whatsoever.

Let's talk about this associated values for a moment.

This one is tricky and it is to show the power of Swift (over for example C or Java) :)

In less powerfull language, maximum of what enum can do is this:

enum BarButton {
    case done
    case edit
}

But in Swift here we can have something like this:

enum BarButton {
    case done(title: String)
    case edit(title: String)
}

Using associated value is easy if you remember that syntax is similar to constant declaration:

switch self {
    case .done(let title):
        print("Hi, my name is \(title)")
    case .edit(let title):
        print("Hi, my name is \(title)")
}

I do strongly recommend to play around with such code scraps in your own playground in XCode :)

Ok, now we need to actually create button using function mentioned in comment.

// let someButton = UIBarButtonItem(title: "A Title", style: .plain, target: nil, action: nil)

Of course we don't need constat to hold button because we will return it right away, let's try to put it all together:

enum BarButton {
    case done(title: String)
    case edit(title: String)

    func button() -> UIBarButtonItem {
      switch self {
        case .done(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.done, target: nil, action: nil)
        case .edit(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.plain, target: nil, action: nil)
      }
    }
}

Our enum looks like it is ready (but it won't compile yet).

Let's add button constant as in this request:

Once you have a method, call it on the value we created in the previous task and assign it to a constant named button.

We have already our enum instance called done. So we can simply try to run our method on it:

let done: BarButton = .done(title: "Save")
let button = done.button()

Whole code looks like this now:

// Example of UIBarButtonItem instance
// let someButton = UIBarButtonItem(title: "A Title", style: .plain, target: nil, action: nil)

enum BarButton {
    case done(title: String)
    case edit(title: String)

    func button() -> UIBarButtonItem {
      switch self {
        case .done(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.done, target: nil, action: nil)
        case .edit(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.plain, target: nil, action: nil)
      }
    }
}

let done: BarButton = .done(title: "Save")
let button = done.button()

This should be right solution (at least considering description), but it isn't. We have bummer here. When we check using Preview button, we can see that UIBarButtonStyle.done and UIBarButtonStyle.plain is not right:

swift_lint.swift:53:55: error: use of unresolved identifier 'UIBarButtonStyle'
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.done, target: nil, action: nil)
                                                      ^~~~~~~~~~~~~~~~
swift_lint.swift:27:7: note: did you mean 'UIBarButtonItem'?
class UIBarButtonItem {
      ^
swift_lint.swift:22:6: note: did you mean 'UIBarButtonItemStyle'?
enum UIBarButtonItemStyle : Int {
     ^
swift_lint.swift:55:55: error: use of unresolved identifier 'UIBarButtonStyle'
          return UIBarButtonItem(title: title, style: UIBarButtonStyle.plain, target: nil, action: nil)
                                                      ^~~~~~~~~~~~~~~~
swift_lint.swift:27:7: note: did you mean 'UIBarButtonItem'?
class UIBarButtonItem {
      ^
swift_lint.swift:22:6: note: did you mean 'UIBarButtonItemStyle'?
enum UIBarButtonItemStyle : Int {

We can fix it in one of two ways: 1) Get rid of UIBarButtonStyle in UIBarButtonStyle.done and UIBarButtonStyle.plain:

return UIBarButtonItem(title: title, style: .done, target: nil, action: nil)

and

return UIBarButtonItem(title: title, style: .plain, target: nil, action: nil)

2) Or use UIBarButtonItemStyle instead:

return UIBarButtonItem(title: title, style: UIBarButtonItemStyle.done, target: nil, action: nil)

and

return UIBarButtonItem(title: title, style: UIBarButtonItemStyle.plain, target: nil, action: nil)

My final solution looked like this:

// Example of UIBarButtonItem instance
// let someButton = UIBarButtonItem(title: "A Title", style: .plain, target: nil, action: nil)

enum BarButton {
    case done(title: String)
    case edit(title: String)

    func button() -> UIBarButtonItem {
      switch self {
        case .done(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonItemStyle.done, target: nil, action: nil)
        case .edit(let title):
          return UIBarButtonItem(title: title, style: UIBarButtonItemStyle.plain, target: nil, action: nil)
      }
    }
}

let done: BarButton = .done(title: "Save")
let button = done.button()

I hope it helps!

Cheers!

BR, Jarek

switch self { case .done(let title): print("Hi, my name is (title)") case .edit(let title): print("Hi, my name is (title)") }

Why do we use "(let title)"? I cant get it. How did you come up with it?