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 Object-Oriented Swift 2.0 Classes Building a Tower

Swift 2.0 Structs are still confusing to me

I am watching Swift 2.0 (OOP Swift 2.0 course) and I really don't understand this struct named Point . Custom datatypes are very confusing to me. I get the idea but the syntax is still confusing. We are returning a type of a Point in our method, but why? Could't we just write a tuple like this (Int, Int) and we would still get coordinates in this format. I have a little experience doing code in Xcode but every time I get to UIButton or something like that my head explodes.

Hope someone would explain this to me.

Here is that nasty code

struct Point {
    let x: Int
    let y: Int

    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }

    func surroundingPoints(withRange range: Int = 1) -> [Point] {
        var results: [Point] = []
        for xCoord in (x-range)...(x+range) {
            for yCoord in (y-range)...(y+range) {
                let coordinatePoint = Point(x: xCoord, y: yCoord)
                results.append(coordinatePoint)
            }
        }
        return results
    }
}

3 Answers

Martin Wildfeuer
PLUS
Martin Wildfeuer
Courses Plus Student 11,071 Points
func surroundingPoints(withRange range: Int = 1) -> [Point] { // 1
    var results: [Point] = [] // 2
    for xCoord in (x-range)...(x+range) { // 3
        for yCoord in (y-range)...(y+range) { // 3
            let coordinatePoint = Point(x: xCoord, y: yCoord) // 4
            results.append(coordinatePoint) // 4
        }
    }
    return results
}

1

Once we have initialized a Point object with our coordinates, we want to be able to get all points that surround our point. To restrict the result, we have to pass a range, the max distance to our point, so to say. The function will then return a list of the surrounding points.

[Point] As there are more than one surrounding point, we have to return an array of our custom type Point It is very important that you make yourself familiar with Swifts data types and functions before working on the concept of structs, classes. Please have a look at the preceding courses and Apple Docs: Collection Types

2

This is our empty array of points, this will be filled with instances of our custom type Point and returned at the end of the method.

3

In order to get the surrounding points, we use the x variable of our current point. Given the range, we can simply say: The x coordinate of any surrounding point is our current x-coordinate minus the range up to our x-coordinate plus the given range. The same is true for our y-coordinate. This way we are stepping to every x-coordinate, then create all points for the corresponding y-coordinate and so on.

So let's say our point has the coordinates 5,5 and our range is 5. Then this

for xCoord in (x-range)...(x+range) {
}

would look like this with the values inserted:

for xCoord in 0...10 {
     // xCoord is an int from 0 to 10, as this
     // "loop" will run 11 times 
}

Btw, '...' is called Range Operator and is explained in detail in the preceding courses, also see Apple docs: Range Operators. Apples example:

for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}

4

Here we create instances of our point with the coordinates, given our example that would be (0,0) (0,1) (0,2) and so on. This will end with (10, 10). Then we append this point to our array of surrounding points, as explained in 1

Fun fact: This will not only return the surrounding points, but also the point with the coordinates of our current point. Given this is an example, that's not a problem, but in real life you most probably wouldn't want that.

Hope that clears things up a bit. Make sure you follow the tracks, because each course depends on things learned in previous courses. Cheers :)

Your explanation helped a lot. Nested for loops are a little difficult visualise in my head. So...

    func surroundingPoints(withRange range: Int = 1) -> [Point] {
        var results: [Point] = []
        for xCoord in (x - range)...(x + range) {
            for yCoord in (y - range)...(y + range) {
                let coordinatePoint = Point(x: xCoord, y: yCoord)
                results.append(coordinatePoint)
            }
        }
        return results
    }

let tower = Point(x: 1, y: 1)
tower.surroundingPoints()

For loop would be, in human view:

var results: [Point] = [0.0]
for xCoord in 0...2  { // x - range is whatever we input for x, in my example is 1, decremented by range, default is 1. That is 0. Same for Increment part.
    for 0...2 { // same logic applies here
       let coordinatePoint = Point(x: 0, y: 0)
       results.append(0,0) // yay, our first item in array
    }

}
var results: [Point] = [0.0,0.1]
for xCoord in 0...2  { 
    for 0...2 { 
       let coordinatePoint = Point(x: 0, y: 1)
       results.append(0,1) // yay, our second item in array
    }

}
var results: [Point] = [0.0, 0.1, 0.2]
for xCoord in 0...2  { 
    for 0...2 { 
       let coordinatePoint = Point(x: 0, y: 2)
       results.append(0,2) // yay, our third and last item in array, we exit nested for loop
    }

}

But how Swift continues to add points after we exit nested for loop? There is no append method in our parent for loop.

UPDATE:

I think I figured it out after watching how playground behaves.

So after we exit nested for loop we get (1.0) and all story goes one more round so we get (1.0, 1.1, 1.2), we exit again and enter the last cycle (2.0), repeat the story and get (2.0, 2.1. 2.2).

When everything appends in our array we get [{x 0, y 0}, {x 0, y 1}, {x 0, y 2}, {x 1, y 0}, {x 1, y 1}, {x 1, y 2}, {x 2, y 0}, {x 2, y 1}, {x 2, y 2}]

Did I get it? :)

Martin Wildfeuer
PLUS
Martin Wildfeuer
Courses Plus Student 11,071 Points

You are right, you could also use tuples to define a point:

let point = (x: 100, y: 100)
let x = point.x

As a matter of fact, tuples can be considered kind of a struct. In some cases you might even want to do that, but what if you wanted to add additional functionality to your point? How would you add a convenience method like surroundingPoints to a tuple?

That's where custom data types come in handy, because you can simply add methods and additional variables. This way, your code is more structured, easier to read and your data type can be extended easily later on.

A good example might be Swifts data type String, which also happens to be a struct.

var word: String = "Test"
word.hasPrefix("Te") // true

hasPrefix is a method that is defined in String, designed to check whether the first part of a String matches that of another. It is implemented like this (shortened)

struct String {
    ...
    func hasPrefix(prefix: String) -> Bool {
        ...
    }
}
Conclusion

A custom data type groups variables and methods associated with it, thus making your code easier to read and extendable.

Hope that helps :)

Hey, thanks a lot.

Since you're here, can you explain line by line what this does? I mean, I know what it does, but I can't "visualise" in my head, if that makes any sense.

func surroundingPoints(withRange range: Int = 1) -> [Point] {
        var results: [Point] = []
        for xCoord in (x-range)...(x+range) {
            for yCoord in (y-range)...(y+range) {
                let coordinatePoint = Point(x: xCoord, y: yCoord)
                results.append(coordinatePoint)
            }
        }
        return results
    }

Why brackets?

-> [Point]

... And this is extra super confusing:

for xCoord in (x-range)...(x+range) {
            for yCoord in (y-range)...(y+range) {
                let coordinatePoint = Point(x: xCoord, y: yCoord)
                results.append(coordinatePoint)
            }
        }
return results

The Brackets around [Point] specifies that Point is an array... -> [Point] is saying this function, surroundingPoints, is going to return an array for the values of Point.

As for your other question i have having a little bit of trouble as well, i understand it watching him do it, but when i try to do it on my own I am having difficulty understanding it. Also very new to swift.