quanguyen
quanguyen

Reputation: 1463

Swift 2.0 - variable copied in closure?

I have an array of dictionaries class instance, outlined below:

class SomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    private var array = [[String: AnyObject]]()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    // tableview delegates

    func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
        print(“array address: \(unsafeAddressOf(array))”) // 0x000000015cf0ebd0

        let option = UITableViewRowAction(style: .Default, title: “Option”, handler: { [weak self] (_, _) in
            guard let strongSelf = self else { return }

            print(“array address1: \(unsafeAddressOf(strongSelf.array))” // 0x000000015cd10c50
        })

        return [option]
    }    
}

why is the address of array is changed (0x000000015cf0ebd0 vs 0x000000015cd10c50) as I just capture it in UITableViewRowAction initialization?

Thanks,

Upvotes: 1

Views: 48

Answers (2)

OOPer
OOPer

Reputation: 47886

It's a nature of unsafeAddressOf and Swift Arrays.

A simplified example you can test in the Playground. (No closure, no strongSelf...)

import Foundation

var str = "Hello, playground"
class MyClass {
    var array = [[String: AnyObject]]()

}

let obj1 = MyClass()

let ptr1 = unsafeAddressOf(obj1.array)
let ptr2 = unsafeAddressOf(obj1.array)

print(ptr1 == ptr2)

Tested in Xcode 7.3.1 (Swift 2.2.1) a few times and all printed "false".

The signature of unsafeAddressOf is:

func unsafeAddressOf(object: AnyObject) -> UnsafePointer<Void>

As you know Swift Arrays are value types and you cannot pass them to AnyObject. So, when "bridging to Objective-C" feature is available, your array is converted to NSArray. This conversion is done in a "hard-to-predict" manner, which means, at any time this conversion is made, Swift may allocate a new NSArray instance.

In general, you should not expect something "firm" from unsafeAddressOf when applied to Swift Arrays or other value types.

Upvotes: 2

Alonso Urbano
Alonso Urbano

Reputation: 2264

Because you are assigning self to variable strongSelf, causing the value of self to be copied to the new variable.

Remember that when you assign a variable to another, it's the value that's copied from one to another, not the reference to the memory allocation.

You can try this by printing exactly the same way you are doing the first time:

print("array address: \(unsafeAddressOf(self.array))")

You need to add self in order to access the array class member when inside a closure block.

Upvotes: 0

Related Questions