Swift 2.0 'Inout' Function Parameters and Computed Properties

Swift 2.0 'inout' function parameters and computed properties

Your confusion might be caused by choosing someString both as the
name of a global variable, and as the name of a parameter of the
someFunc() function.

print(someString) inside someFunc() prints the
value of the (local) function parameter, which is completely unrelated
(and hides) the global someString variable.

It becomes easier to understand if you rename the function parameter

private func someFunc(inout localString: String) {
print("Inside \'someFunc()\'")
print(localString)
localString = "Some another string"
}

which is semantically identical (and therefore produces the same output).

You can think of

someFunc(&someString)

as the following:

  • The value of someString is retrieved (using the getter method).
  • someFunc() is executed, with the local parameter localString
    set to the value of someString.
  • On return from someFunc(), someString is set (using the
    setter method) to the (possibly changed) value of the local parameter
    localString.

More information can be found in https://devforums.apple.com/thread/230567 from the Apple Developer Forum,
for example:

Given the guarantee of a getter and setter, inout follows naturally:
when calling a function with an inout argument, logically it calls the
getter on the var/subscript and copies the value into a stack
temporary which is guaranteed to have physical addressability. The
physical address of the temporary is passed to the inout argument of
the function ... . The callee does
whatever it wants with that memory location (and never knows whether
the thing passed in was computed or not). When the callee returns,
the setter is invoked to copy the value back into place.

and

It also guarantees that the getter/setter of a property passed inout
will have its getter and setter called once regardless of what the
callee does (this is important if the accessors have side effects or
are expensive).

but it is also stated that the temporary copy is avoided if necessary.

Using inout keyword: is the parameter passed-by-reference or by copy-in copy-out (/call by value result)

The next two paragraphs in the Language Reference describes it more in detail:

In-Out Parameters


This behavior is known as copy-in copy-out or call by value result. For
example, when a computed property or a property with observers is
passed as an in-out parameter, its getter is called as part of the
function call and its setter is called as part of the function return.

As an optimization, when the argument is a value stored at a physical
address in memory, the same memory location is used both inside and
outside the function body. The optimized behavior is known as call by
reference
; it satisfies all of the requirements of the copy-in
copy-out model while removing the overhead of copying. Do not depend
on the behavioral differences between copy-in copy-out and call by
reference.

So it's de facto "pass by reference"

Inout parameters in swift 3

By moving s into s1 you are making a copy of it since String is a struct, and all structs are pass by value. So in the end you're only changing s1 and not the passed in string, s. Just remove it:

func removeFromString( _ s: inout String, Character c:Character) -> Int {
var nRemoved = 0

while let ix = s.characters.index(of: c) {
s.removeSubrange(ix...ix)
nRemoved += 1

}
return nRemoved
}

Sending property as a reference param to a function in iOS?

You cannot pass an argument by reference in (Objective-)C. What you probably mean is to
pass the address of a variable as an argument to the method, so that the method can
set the value of the variable via the pointer.

However, this does not work with properties.
self.obj1 is just a convenient notation for the method call [self obj1], which returns
the value of the property. And taking the address of a return value is not possible.

What you can do is

  • Pass the address of the corresponding instance variables:

    [SomeClass someFuncWithParam1:&_obj1 param2:&_obj2];

    The disadvantage is that the property accessor methods are bypassed. That may or may not be
    relevant in your case.

  • Pass the address of temporary local variables:

    NSObject *tmpObj1;
    NSObject *tmpObj2;
    [SomeClass someFuncWithParam1:&tmpObj1 param2:&tmpObj2];
    self.obj1 = tmpObj1;
    self.obj2 = tmpObj2;

Both solutions are not very nice. Alternatively, you could pass the entire object (self) to the helper method, which then initializes both properties.

Or you define a custom class with just the properties obj1 and obj2, and make the helper method return an instance of this custom class.

Getter unexpectedly called a second time for inout parameter

I am guessing you are writing this code in the playground!?

If you put it into a regular project and run it on the simulator, you will not see that behavior.

It only occurs in the playground.

On the device both methods print the expected

get

f

set



Explanation:

The playground execution looks like this:

Sample Image

Notice the A in the last line printed on the right side? The Playground tries to display the value of the x and for it to display it, it accesses its getter! If you have multiple parameters Xcode does not attempt to print anything -> adding a second parameter causes Xcode to not get any value.

Is there a way to implement substring getters and setters for a computed property?

I did some digging and found the solution. Setting using a subscript on a computed array property provides a newValue containing the original array, but with the relevant index changed according to the subscript that was used. To illustrate:

var actualArray: [String] = []

var computedArray: [String] {
get {
return actualArray
}

set(setTo) {
actualArray = setTo
}
}

computedArray.append("Hello")
computedArray.append("Matt")
computedArray.append("World")

// computedArray and actualArray are now both ["Hello", "Matt", "World"]

computedArray[1] = "Jacob"

// computedArray and actualArray are now both ["Hello", "Jacob", "World"]

Why I can set private field in playground

Swift private is slightly semantically different than in other OO languages, it is private to the source file.

In Swift Access Control:

Private access restricts the use of an entity to its own defining
source file. Use private access to hide the implementation details of
a specific piece of functionality.



Related Topics



Leave a reply



Submit