Drakalex
Drakalex

Reputation: 1538

How to create a pointer in Swift?

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.

Upvotes: 4

Views: 4083

Answers (4)

Michael Kaufman
Michael Kaufman

Reputation: 442

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)

Upvotes: 0

nyg
nyg

Reputation: 2542

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)

Upvotes: 4

Phillip Mills
Phillip Mills

Reputation: 31016

(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.)

Upvotes: 2

Vini App
Vini App

Reputation: 7485

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

Upvotes: 1

Related Questions