4

Update Swift arrays are too weird. I think it's more reliable to just use NSMutableArrays instead if this behaviour is needed.

I understand that Swift typically passes array by value rather than by reference, but I need to be able to pass a reference in code like this:

var arr1 = [1, 2, 4]
var arr2 = [4, 6, 3]
var result = pickOne() ? arr1 : arr2
result[2] = 7
// one of these should be updated, currently they are just as initialized
println(arr1)
println(arr2)

I want to dynamically select one of the two arrays, and make changes to that array. Both arrays are the same size and content type, and I would only be changing elements, not appending or removing. How can I achieve this?

Edit: Is the answer to just use NSMutableArray instead?

Just to clarify: pickOne() is a function that I already have, and based on results of that function I want to modify either first or second array. So I don't need help deciding which to choose. I need help figuring out how to make modifications (and there will be several) to that desired array without having to check which array to use for every modification.

I could do something like this:

if pickOne() {
    // work on arr1
    // ...
} else {
    // work on arr2
    // ...
}
// do some other work
// ...
if pickOne() {
    // work more on arr1
    // ...
} else {
    // work more on arr2
    // ...
}
// do yet another set of things
// ...
if pickOne() {
    // work again on arr1
    // ...
} else {
    // work again on arr2
    // ...
}

But this gets old fast.

Edit So far I have reached some progress here

var result = pickOne() ? UnsafeMutableBufferPointer(start: &arr1, count: arr1.count) : UnsafeMutableBufferPointer(start: &arr2, count: arr2.count)

I don't care too much that the reference is unowned because the arrays are actually strongly held properties of self so should not really get released unexpectedly, but the usage sure looks ugly. It's pretty disappointing that you need to call functions with scary names Unsafe when trying to do something so primitive.

9
  • Are you actually asking how to pass an array by reference so it can be modified (as there are already many past questions and reference material on that readily available) or how to dynamically choose which one to pass? Commented May 22, 2015 at 20:13
  • How to pass by reference. All the examples I've seen rely on inout keyword and use of additional functions, which gets quite bulky, and so far I've had no luck actually making it work for this use case. Commented May 22, 2015 at 20:27
  • Looks like UnsafeMutableBufferPointer is doing the trick, but damn, it's ugly. Commented May 22, 2015 at 20:42
  • @SaltyNuts: Arrays are value types and therefore not reference counted, that makes it difficult to use a pointer in a safe way. Using a helper function might be the cleanest solution. – It is called "Unsafe"MutableBufferPointer because the pointer does not extend the lifetime and it can easily be used to bypass the range check. – Do you agree that this can be closed as a duplicate? Commented May 22, 2015 at 20:49
  • The name is scary because what you're doing is scary. You're creating aliases, and aliases are a common cause of bugs, and a very common optimization problem. A lot of compiler optimizations are possible if the system can prove that there are no aliases, but it's very hard in arbitrary C code to prove that. Swift makes proving that much easier by forcing you to go Unsafe if you want to break it. Commented May 22, 2015 at 20:54

1 Answer 1

1

You cannot do this with Swift Array structures, see below:

“Assignment and Copy Behavior for Strings, Arrays, and Dictionaries Swift’s String, Array, and Dictionary types are implemented as structures. This means that strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.

This behavior is different from NSString, NSArray, and NSDictionary in Foundation, which are implemented as classes, not structures. NSString, NSArray, and NSDictionary instances are always assigned and passed around as a reference to an existing instance, rather than as a copy”

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/ca/jEUH0.l

Sign up to request clarification or add additional context in comments.

1 Comment

In some ways they are like structs, in some ways they are not. Not a fan of the way Apple handled this. See devforums.apple.com/thread/228695?start=0&tstart=0 for more discussion (must be registered Apple dev to log in).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.