Pointer to struct?

Suppose I have a data structure dataStruct with a property color. Suppose I also have an array dataArray that contains these structs. I know I can't change the property of one of these array elements by doing this:


var aStruct = dataArray[index]
aStruct.color = UIColor.redColor()


because in Swift, the variable aStruct will contain only a copy of the element I want to modify. Of course, I can modify the array element iself by doing this:


dataArray[index].color = UIColor.redColor()


But this gets tedious if the struct has a lot of different properties that I want to modify at the same time.


Is there some way of getting a pointer to the struct in Swift? Or do I need to make dataStruct a class instead of a struct if I want to do this sort of thing?

You can use `withUnsafeMutablePointer(_:_:)` to retrieve a pointer which can manipulate an element of an array:

        withUnsafeMutablePointer(&dataArray[index]) {aStructPtr in
            aStructPtr.memory.color = UIColor.redColor()
            //aStructPtr.memory.{otherProperties} = ...
        }


Or you can use a local function which takes an `inout` parameter:

        func modifyStruct(inout aStruct: MyStruct) {
            aStruct.color = UIColor.redColor()
            //aStruct.{otherProperties} = ...
        }
        modifyStruct(&dataArray[index])


Local functions can be replaced with closures:

        {(inout aStruct: MyStruct)->Void in
            aStruct.color = UIColor.redColor()
            //aStruct.{otherProperties} = ...
        }(&dataArray[index])

(You may need some caution on making this statement not to be taken as a trailing closure.)


There may be more "Swifty" solutions depending on your actual purpose or higher level app structure.

This needs to be addressed in Swift. Fully qualifying an inner struct in your data model can be very tedious, depending on model complexity. Also, I don't think it's possible to have an elegant solution.


For instance, with proposed solutions, you need to cascade blocks if you need to access multiple inner structs, which doesn't scale:


scopedAccess(&varA) {
     scopedAccess(&varB) {
          // modify varA & varB
     }
}


It's easily done in C/C++ using pointers/references. To make that better, we'd need some kind of language support IMO.

As OOPer showed, there are lots of options here; the best choice really depends on your exact needs. If you post examples of your specific requirements, we can probably suggest more options.

Returning to Albinus’s example, they wrote

But this gets tedious if the struct has a lot of different properties that I want to modify at the same time.

and, yes, they’re right, that can get tedious. However, there are ways to address it within the language already. For example, consider this function:

func scope<T, Result>(inout value: T, body: (inout T) throws -> Result) rethrows -> Result {
    return try body(&value)
}

which calls

body
with the specified
inout
parameter, allowing it to modify arbitrary fields in
value
. Consider these basic structures:
struct Colour {
    var red: Float
    var green: Float
    var blue: Float
    static var red  = Colour(red: 1.0, green: 0.0, blue: 0.0)
    static var white = Colour(red: 1.0, green: 1.0, blue: 1.0)
    static var blue  = Colour(red: 1.0, green: 0.0, blue: 1.0)
}

var france: [Colour] = [.blue, .white, .red]
var italy = france

Here’s an example of how to use this to bulk modify the properties of a struct:

scope(&italy[0]) {
    $0.red = 0.0
    $0.green = 1.0
    $0.blue = 0.0
}

There have been a number of proposals to add direct support for this sort of thing to the language but this hasn’t happened yet. You can get an idea for the sort of interest in this by looking at the list of thread references in the comments at the bottom of SR-160. If you’d like to get involved, head on over to swift-evolution.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you Quinn for this detailed answer, appreciated, and I'll review the SR-160 as you suggest.


I still think however that scoped access doesn't scale well for the general case where you need to modify more than one struct. That would create a scope pyramid, which is what I'd like to avoid. Maybe this kind of language support could solve it (scoping might even not be needed):


mutating var s1 = path.to.struct1, s2 = path.to.struct2 {
     // modify s1, s2
}


We also need a way to iterate through arrays with writable access:


for mutating var car in cars {
     car.color = newColor
}


Because index-based iteration to get write access is both heavy and old fashioned.


I'll try to spend some time in the swift-evolution as you suggest. Thanks!

This really reminds me of Pascal's 'with' statement.

Agree with rsharp. The with ... do statement was very convenient to go deep into structure and keep good readability.


In this case :


dataArray[index].color = UIColor.redColor()


would write


with dataArray[index] do {
     color = UIColor.redColor()
}


No more tedious copy of the full structire and much improved readability.

Pointer to struct?
 
 
Q