4

I'm working with Swift 3.

I would like to have this C syntax :

int myVar;
int *pointer = &myVar;

So modifying pointer or myVar does the same exact same thing. Also I don't know if it makes any difference, but in my case myVar is an array containing elements of a class and pointer is a pointer to one element of this array.

Drakalex
  • 1,488
  • 3
  • 19
  • 39
  • Possible duplicate of [How to do "Deep Copy" in Swift?](https://stackoverflow.com/questions/24754559/how-to-do-deep-copy-in-swift) – Dávid Pásztor Sep 13 '17 at 18:47
  • Have you tried it? In what way does `var selectedRow = rows[0]` not do what you want? (From your description, it seems to me that you don't want a copy at all, just a shared pointer.) – Phillip Mills Sep 13 '17 at 18:49
  • It creates a copy of `rows[0]` but the two variables are different, when I modify `selectedRow` it doesn't affect `rows[0]` at all. And yes I want a shared pointer. – Drakalex Sep 13 '17 at 18:51

4 Answers4

4

The & also exists in Swift but can only be used as part of a parameter list (e.g. init, func, closure).

var i = 5
let ptr = UnsafeMutablePointer(&i)
print(ptr.pointee) // 5

// or
let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
ptr.initialize(to: 5)

// or with a closure
let ptr: UnsafePointer = { $0 }(&i)
nyg
  • 2,380
  • 3
  • 25
  • 40
2

(Assuming I understand what you're asking for....)

Try the following code in a playground. It should print "99" three times.

class Row {
    var rowNumber = 0
}

var rows = [Row]()

let testRow = Row()
testRow.rowNumber = 1

rows.append(testRow)

let selectedRow = rows[0]
selectedRow.rowNumber = 99

print(testRow.rowNumber)
print(selectedRow.rowNumber)
print(rows[0].rowNumber)

By default, there's no copying of objects as part of an assignment statement. If it were a struct, that would be different.


Adding a bit for completeness:

If you want a similar effect with scalar values instead of objects, Swift supplies various types of wrappers.

let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: 8)  // Should be 1, not 8 according to comment re: docs
let other = intPointer
other.pointee = 34

print(intPointer.pointee)

(Warning: I haven't used these wrappers for anything except experimenting in a playground. Don't trust it without doing some research.)

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Okay, I'm missing something here. I thought my code didn't work because this syntax wasn't correct but I tried your code in a playground and it works fine, so my code works too, I must have something wrong elsewhere. Now why this works with a class but not with variables ? for example `var myVar = 5`, `var otherVar = myVar` and `otherVar = 5` doesn't change `myVar` value ? – Drakalex Sep 13 '17 at 19:13
  • 1
    The difference is that objects are referenced through pointers. So, in my case, I have one actual object and three variables containing the one value that points to it. In your `myVar` example, you're changing the actual variable contents; there's no independent object that they both reference. (It would be the same as me typing `let selectedRow = Row()` and expecting its changes to be reflected in `testRow`. People sometimes try that, but it never works. :) ) – Phillip Mills Sep 13 '17 at 19:19
  • I'm pretty sure it should be `.allocate(capacity: 1)`. Doc for the parameter: _The amount of memory to allocate, counted in instances of `Pointee`._ – nyg Sep 13 '17 at 19:55
  • Thanks @nyg. It's definitely not something I've looked at for real use. – Phillip Mills Sep 13 '17 at 19:57
1

Same example as @Phillip. But I used struct. In this example rows[0] won't change:

struct Row {
    var rowNumber = 0
}

var rows = [Row]()

var testRow = Row()
testRow.rowNumber = 1

rows.append(testRow)

var selectedRow = rows[0]
selectedRow.rowNumber = 99

print(testRow.rowNumber) // prints 1
print(selectedRow.rowNumber) // prints 99
print(rows[0].rowNumber)  // prints 1
Vini App
  • 7,339
  • 2
  • 26
  • 43
0

There are no C style pointers (Unsafe Pointer) as the question asks however objects are shared by reference and structures are by value:

Swift assign, pass and return a value by reference for reference type and by copy for Value Type

structures are always copied when they are passed around in your code, but classes are passed by reference.

For example

How to have pointers/ references to objects

class Song {
    
    init(title: String, image: String, file: String, volume: Float, queuePlayer: AVQueuePlayer, playerLooper: AVPlayerLooper?) {
        self.title = title
        self.image = image
        ...
    }
    var title: String
    var image: String
    ...
}

var aSong = Song(title: "", image: "", ...)

var arrOfSongReferences: [Song] = [Song]()
arrOfSongReferences.append(aSong)

var ptrToASong: Song = aSong

aSong = nil
// Due to Swift garbage collection ARC (Automatic Reference Counting), we still have references to the original aSong object so it won't be deleted

If data is struct you cannot do this

struct Song {
    var title: String
    var image: String
    ...
}

var aSong: Song = Song(title: "", image: "", ...)
var copyOfASong: Song = aSong

Method

You can also pass by reference into a function

// this would be inside a class, perhaps Player. It doesn't have to be a static btw
static func playSound(_ sound: inout Song, volume: Float = 0.0) {
        if (sound.playerLooper == nil) {
               ...
        }
}

// usage
Player.playSound(sound: &aSong)
Michael Kaufman
  • 312
  • 3
  • 4