Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying Swift Cookbook
  • Table Of Contents Toc
Swift Cookbook

Swift Cookbook - Third Edition

By : Keith Moon, Chris Barker, Daniel Bolella, Nathan Lawlor
5 (3)
close
close
Swift Cookbook

Swift Cookbook

5 (3)
By: Keith Moon, Chris Barker, Daniel Bolella, Nathan Lawlor

Overview of this book

Unlock the full potential of Swift and elevate your iOS development skills with this new edition of Swift Cookbook, highlighting the latest features in Swift 5.9. This cookbook will take your Swift programming skills to the next level, boosting your productivity and efficiency step by step through a plethora of practical recipes. Although this book is primarily for experienced iOS developers, it provides an introductory overview of Swift 5.9, including its basic building blocks, syntax, and the functionalities of Swift constructs, to get you warmed up. Once you’ve mastered the fundamentals, you’ll get down to business. Unless you’re completely new to Swift, this recipe-based guide doesn’t need to be read in order; you can jump to whichever topic takes your fancy, from UIKit and SwiftUI to advanced UI techniques, from Swift’s control flow and generics to machine learning with Vision, CoreML, and augmented reality with ARKit. By the end of this book, you’ll be fully up to speed with Swift’s capabilities and be able to develop amazing applications across a wide variety of domains.
Table of Contents (15 chapters)
close
close

Subscripts for custom types

By using collection types, we have seen that their elements are accessed through subscripts. However, it’s not just collection types that can have subscripts; your own custom types can provide subscript functionality too.

Getting ready

In this recipe, we will create a simple game of tic-tac-toe, also known as noughts and crosses. To do this, we need a three-by-three grid of positions, with each position being filled by either a nought from player 1, a cross from player 2, or nothing. We can store these positions in an array of arrays.

The initial game setup code uses the concepts we’ve already covered in this book, so we won’t go into its implementation. Enter the following code into a new playground so that we can see how subscripts improve its usage:

enum GridPosition: String {
 case player1 = "o"
 case player2 = "x"
 case empty = " "
}
struct TicTacToe {
 var gridStorage: [[GridPosition]] = []
 init() {
  gridStorage.append(Array(repeating: .empty,
    count: 3))
  gridStorage.append(Array(repeating: .empty,
    count: 3))
  gridStorage.append(Array(repeating: .empty,
    count: 3))
 }
 func gameStateString() -> String {
  var stateString = "\n"
  stateString += printableString(forRow: gridStorage[0])
  stateString += "\n"
  stateString += printableString(forRow: gridStorage[1])
  stateString += "\n"
  stateString += printableString(forRow: gridStorage[2])
  stateString += "\n"
  return stateString
 }
 func printableString(forRow row: [GridPosition]) -> String {
  var rowString = "| \(row[0].rawValue) "
  rowString += "| \(row[1].rawValue) "
  rowString += "| \(row[2].rawValue) |\n"
  return rowString
 }
}

How to do it...

Let’s run through how we can use the tic-tac-toe game defined previously, as well as how we can improve how it is used, using a subscript. We will also examine how this works:

  1. Let’s create an instance of our TicTacToe grid:
    var game = TicTacToe()
  2. For a player to make a move, we need to change the GridPosition value that’s been assigned to the relevant place in the array of arrays. This is used to store the grid positions. Player 1 will place a nought in the middle position of the grid, which would be row position 1 and column position 1 (since it’s a zero-based array):
    // Move 1
    game.gridStorage[1][1] = .player1
    print(game.gameStateString())
    /*

|

|

|

|

|

|

o |

|

|

|

|

|

*/

Figure 2.9 – The grid positions

3. Then, player 2 places their cross in the top-right position, which is row position 0 and column position 2:

// Move 2
game.gridStorage[0][2] = .player2
print(game.gameStateString())
/*
||| x |
|| o ||
||||
*/

We can make moves in our game. We can do this by adding information directly to the gridStorage array, which isn’t ideal. The player shouldn’t need to know how the moves are stored, and we should be able to change how we store the game information without having to change how the moves are made. To solve this, let’s create a subscript of our game struct so that making a move in the game is just like assigning a value to an array.

4. Add the following subscript method to the TicTacToe struct:

struct TicTacToe {
 var gridStorage: [[GridPosition]] = []
 //...
 subscript(row: Int, column: Int) -> GridPosition {
  get {
   return gridStorage[row][column]
  }
  set(newValue) {
   gridStorage[row][column] = newValue
  }
 }
 //...
}

5. So, now, we can change how each player makes their move and finish the game:

// Move 1
game[1, 1] = .player1 print(game.gameStateString())
/*

|

|

|

|

|

|

o |

|

|

|

|

|

*/

// Move 2
game[0, 2] = .player2
print(game.gameStateString())
/*
||| x |
|| o ||
||||
*/
// Move 3
game[0, 0] = .player1
print(game.gameStateString())
/*
| o || x |
|| o ||
||||
*/
// Move 4
game[1, 2] = .player2
print(game.gameStateString())
/*
| o || x |
|| o | x |
||||
*/
// Move 5
game[2, 2] = .player1
print(game.gameStateString())
/*
| o || x |
|| o | x |
||| o |
*/

6. Just like when using an array, we can use a subscript to access the value, as well as assign a value to it:

let topLeft = game[0, 0]
let middle = game[1, 1]
let bottomRight = game[2, 2]
let p1HasWon = (topLeft == .player1) && (middle == .player1) && (bottomRight == .player1)

How it works...

Subscript functionality can be defined within a class, struct, or enum, or declared within a protocol as a requirement. To do this, we can define subscript (which is a reserved keyword that activates the required functionality) with input parameters and an output type:

subscript(row: Int, column: Int) -> GridPosition

This subscript definition works like a computed property, where get can be defined to allow you to access values through subscript, and set can be defined to assign values using subscript:

subscript(row: Int, column: Int) -> GridPosition {
 get {
  return gridStorage[row][column]
 }
 set(newValue) {
  gridStorage[row][column] = newValue
 }
}

Any number of input parameters can be defined, and these should be provided as comma-separated values in the subscript:

game[1, 2] = .player2 // Assigning a value
let topLeft = game[0, 0] // Accessing a value

There’s more...

Just like parameters defined in a function, subscript parameters can have additional labels. If defined, these become required at the call site, so the subscript we added can alternatively be defined as follows:

subscript(atRow row: Int, atColumn column: Int) -> GridPosition

In this case, when using subscript, we would also provide the labels in it:

game[atRow: 1, atColumn: 2] = .player2 // Assigning a value
let topLeft = game[atRow: 0, atColumn: 0] // Accessing a value

See also

Further information about subscripts can be found in Apple’s documentation on the Swift language at http://swiftbook.link/docs/subscripts.

CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
Swift Cookbook
notes
bookmark Notes and Bookmarks search Search in title playlist Add to playlist download Download options font-size Font size

Change the font size

margin-width Margin width

Change margin width

day-mode Day/Sepia/Night Modes

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY

Submit Your Feedback

Modal Close icon
Modal Close icon
Modal Close icon