2

Structs in Swift can contain functions and can have extensions. Cool! Looks like a neat way to make this function available to more classes and to reduce argument passing. Here's the way the function originally looked in a map view controller:

    func expandTrackRectToCoordinate(coordinate : CLLocationCoordinate2D) {

    let point = MKMapPointForCoordinate(coordinate)
    let newRect = MKMapRectMake(point.x, point.y, 0.0, 0.0)

    if MKMapRectIsNull(trackRect) {
        trackRect = MKMapRectMake(point.x, point.y, 0.0, 0.0)
    } else {
        trackRect = MKMapRectUnion(trackRect, newRect)
    }
}

trackRect was a MKMapRect member of the class.

The MKMapRect expands to include each point so that the map can be reset to the entire region as required, showing all points.

I tried to make this an extension on MKMapRect (partial - shown up until the error):

extension MKMapRect {

func expandToIncludeCoordinate(coordinate : CLLocationCoordinate2D) {

    let point = MKMapPointForCoordinate(coordinate)
    let newRect = MKMapRectMake(point.x, point.y, 0.0, 0.0)

    if MKMapRectIsNull(self) {
        self.origin = point       <-------- Cannot assign to 'origin' in 'self'
        self.size = CGSizeZero
    } else {

I did not expect to be able to just assign to self but I did expect to be able to assign to the struct's members. How can this be done?

Adam Eberbach
  • 12,309
  • 6
  • 62
  • 114
  • add `mutating` keyword before `func` so you can mutate the struct – Bryan Chen Feb 23 '15 at 04:35
  • That's it - I want to have a MKMapRect and to have it expand its own boundaries (mutate self) rather than return a new one. My code sample was confusing - sorry, cut and paste. Fixed now. – Adam Eberbach Feb 23 '15 at 04:48

1 Answers1

5

Structs in Swift generally are considered to be immutable, unless you specifically mark their methods as mutating:

extension MKMapRect {

    mutating func expandToIncludeCoordinate(coordinate : CLLocationCoordinate2D) {

        let point = MKMapPointForCoordinate(coordinate)
        let newRect = MKMapRectMake(point.x, point.y, 0.0, 0.0)

        if MKMapRectIsNull(self) {
            self.origin = point

            // Another problem here is that CGSize is not the same as MKMapSize
            self.size = MKMapSize(width: 0, height: 0)
        } else {
            ...
            ...
        }
    }
}

Reference

cjwirth
  • 2,015
  • 1
  • 15
  • 24
  • 2
    Well in that case, he has to decide what he wants to do. Given his attempted use of `self`, it appeared to me that he wanted to mutate it. Good point though, I should fix the sample code – cjwirth Feb 23 '15 at 04:42