1

I’m fairly new to Swift, and I’ve stumbled across this problem today which will help me a lot if answered. The code below explains my issue:

struct Foo {
  var x: Float
  mutating func change() {
    x += 1
  }
}

struct Bar {
  var y: Float
}

var foo = Foo(x: 1)
let bar = Bar(y: foo.x)

foo.change()

print(foo.x) // 2.0
print(bar.y) // 1.0 (how can I make this 2.0 as well?)

I thought I might have to use pointers but I have no idea how to, and I have no clue if that’d even work. Any ideas will help!

3
  • 1
    Unclear what the question is. You cannot change anything about bar because you declared it with let. And you are not doing anything that would change bar in any case, so what would change it? Commented Nov 27, 2016 at 21:49
  • Pretend it was var. Bad example Commented Nov 28, 2016 at 3:05
  • Programming is not about pretending. :) Commented Nov 28, 2016 at 3:29

2 Answers 2

2

One way to get what you want here is to define Bar to keep a reference to Foo. And since you want a change to an instance of Foo to carry over to the reference held by a Bar, you would need to make Foo a class instead of a struct.

Here's one possible solution:

class Foo {
    var x: Float

    init(x: Float) {
        self.x = x
    }

    func change() {
        x += 1
    }
}

struct Bar {
    var foo : Foo
    var y : Float { return foo.x }

    init(foo: Foo) {
        self.foo = foo
    }
}

var foo = Foo(x: 1)
let bar = Bar(foo: foo)

foo.change()

print(foo.x) // 2.0
print(bar.y) // 2.0 as asked
Sign up to request clarification or add additional context in comments.

2 Comments

So there's no way to do it without a class?
If Foo is a struct, then each assignment gives you a new copy.
0

When you write

let bar = Bar(y: foo.x)

the value foo.x (1) is copied inside Bar.

So doesn't exist no further connection between foo.x and bar.x.

This happens because in Swift params are passed by value.

Solution

First of all we need a generic wrapper

class Wrapper<Element> {
    var element: Element
    init(element: Element) {
        self.element = element
    }
}

now we can redefine Foo and Bar

struct Foo {
    var x: Wrapper<Float>
    mutating func change() {
        x.element += 1
    }
}

struct Bar {
    var y: Wrapper<Float>
}

As you can see now Foo and Bar doesn't hold the Float value but a reference to a Float value. We will use this to make the foo and bar value to reference the same Float value.

Finally we can test that the value is changed across both structures

var foo = Foo(x: Wrapper<Float>(element: 1))
let bar = Bar(y: foo.x)
foo.change()

print(foo.x.element) // prints 2.0
print(bar.y.element) // prints 2.0

2 Comments

The OP seems to understand this. The question is asking how to get around this.
@rmaddy: Ok I added a possible solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.