Static and Mutating Methods with self

Welcome to Lesson 2 of Advanced Enum. You will learn how to utilize properties and methods within enums to produce safe and beautiful code. The examples will include UIStoryboard, Cell Identifier, and UIColor.

Problem

Let’s make it practical

Practical with Storyboard

Create an enum called Storyboard with raw value, String. It contains a computed property called, identifier whose type is String.

  1. enum Storyboard: String {
  2. case profile
  3. case setting
  4. case newsfeed
  5. var identifier: String {
  6. return self.rawValue
  7. }
  8. }

You no longer have to type manually.

  1. let profile = Storyboard.profile
  2. profile.identifier // "profile"

API Guideline Goal

Hypothetically, you may need to create a function with a parameter whose type is Storyboard.

  1. func describeStoryboard(storyboard: Storyboard) -> String {
  2. switch storyboard {
  3. case .profile:
  4. return "\(storyboard.identifier): Profile picture, followers"
  5. case .setting:
  6. return "\(storyboard.identifier): Logout, invite"
  7. case .newsfeed:
  8. return "\(storyboard.identifier): videos, texts"
  9. }
  10. }

Instead of typing manually, you are able to pick and choose any cases within Storyboard. Look familar?

  1. describeStoryboard(storyboard: .profile)

Mutating Method

You may create a mutating function that mutates its own case.

  1. enum MealProcess: String {
  2. case breakfast, lunch , dinner
  3. var description: String {
  4. return self.rawValue
  5. }
  6. mutating func nextMeal() {
  7. print("Time to move on from \(self.description)")
  8. switch self {
  9. case .breakfast:
  10. self = .lunch
  11. print("I had a nice lunch")
  12. case .lunch:
  13. self = .dinner
  14. print("I had a nice dinner")
  15. case .dinner:
  16. self = .breakfast
  17. print("I had a nice breakast")
  18. }
  19. }
  20. }

Important: self refers to the initialized enum object with a defined case.

Let us initialize an object with the breakfast case and call the nextMeal() function.

  1. var currentMeal = MealProcess.breakfast
  2. currentMeal.nextMeal() // .lunch
  3. currentMeal.nextMeal() // .dinner

The nextMeal function modifies the case of currentMeal.

Static Method

Create an enum called, AppleDevices. It contains a static function which returns AppleDevices based on the name of the parameter used in the function.

  1. enum AppleDevices {
  2. case iWatch, iPhone, iMac, MacPro
  3. static func getAppleDevice(name: String) -> AppleDevices? {
  4. switch name {
  5. case "iWatch":
  6. return .iWatch
  7. case "iPhone":
  8. return .iPhone
  9. case "iMac":
  10. return .iMac
  11. case "MacPro":
  12. return .MacPro
  13. default:
  14. return nil
  15. }
  16. }
  17. }

You may return an initialized enum object by calling getAppleDevice.

  1. let userProduct = AppleDevices.getAppleDevice(name: "iWatch")
  2. print(userProduct) // AppleDevices.iWatch

Let us refactor using raw value.

  1. enum AppleDevices: String {
  2. case iWatch, iPhone, iMac, MacPro
  3. static func getProduct(name: String) -> AppleDevices? {
  4. return AppleDevices(rawValue: name)
  5. }
  6. static func getAppleDevice(enterName: String) -> AppleDevices? {
  7. switch enterName {
  8. case "iWatch", "iPhone", "iMac", "MacPro":
  9. return getProduct(name: enterName)
  10. default:
  11. return nil
  12. }
  13. }
  14. }

Looks nice and zen.

Custom Init

You may add a custom init method to create an object you wish.

  1. enum AppleDevice: String {
  2. case iWatch, iPhone, iMac, MacPro
  3. init?(name: String) {
  4. if name == "iWatch" {
  5. self = .iWatch
  6. } else {
  7. return nil
  8. }
  9. }
  10. }
  11. AppleDevice(name: "iWatch")
  12. AppleDevice(rawValue: "iWatch")

Another example with number category.

  1. enum IntCategory {
  2. case small
  3. case medium
  4. case big
  5. case weird
  6. init(number: Int) {
  7. switch number {
  8. case 0..<1000 :
  9. self = .small
  10. case 1000..<100000:
  11. self = .medium
  12. case 100000..<1000000:
  13. self = .big
  14. default:
  15. self = .weird
  16. }
  17. }
  18. }
  19. IntCategory(number: 12413423432) // .weird

Practical Usage

HTTP Request

You may organize a group of HTTP instructions using enums instead of multiple tuples.

  1. //: HTTP Request
  2. enum HttpError: String {
  3. case Code400 = "Bad Request"
  4. case Code401 = "Unauthorized"
  5. case Code402 = "Payment Required"
  6. case Code403 = "Forbidden"
  7. case Code404 = "Page Not Found"
  8. var description: String {
  9. return self.rawValue
  10. }
  11. }
  12. HttpError.Code400.description

Cell Identifier

Like Storyboard, you want to limit typing with your fingers. Instead, pick and choose.

  1. enum CellType: String {
  2. case ButtonValueCell = "ButtonValueCell"
  3. case UnitEditCell = "UnitEditCell"
  4. case LabelCell = "LabelCell"
  5. case ResultLabelCell = "ResultLabelCell"
  6. var name: String {
  7. return self.rawValue
  8. }
  9. }

UIColor

No more typing. It is useful both for your teammates with effective communication.

  1. import UIKit
  2. enum NavigationTheme {
  3. case Placid
  4. case Warning
  5. case Danger
  6. var barTintColor: UIColor {
  7. switch self {
  8. case .Placid: return UIColor.clear
  9. case .Warning: return UIColor.blue
  10. case .Danger: return UIColor.red
  11. }
  12. }
  13. }

You may get barTintColor based on the enum case.

  1. let colorSituation = NavigationTheme.Placid
  2. colorSituation.barTintColor

Enums also support extension. Let us add a custom init.

  1. extension NavigationTheme {
  2. init(numberOfTasks: Int) {
  3. switch numberOfTasks {
  4. case 0...3:
  5. self = .Placid
  6. case 4...9:
  7. self = .Warning
  8. default:
  9. self = .Danger
  10. }
  11. }
  12. }

The example above is useful for coloring a to-do list app.

Let us retrieve barTintColor based on numberOfTasks.

  1. let currentColor = NavigationTheme(numberOfTasks: 10).barTintColor

Source Code

7002_stating_mutating_self.playground

Conclusion

You’ve tasted the power of enums. Again, no more typing. In your head, you should be thinking how to deploy enums to beautify your previous projects. If the iOS engineers have not used enums for any APIs, for instance, UIColor, we, developers, have to memorize and type all day while checking the documentation unlimited times. Use it for your advantage as well.

In the following lesson, you will learn how to add multiple enums within a single enum.

Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.