3
class UserDataStore {
}

class ProfileInteractor {

    var userDataStore: UserDataStore?

    init(userDataStore: UserDataStore?) {
        self.userDataStore = userDataStore
    }
}

var profileInteractor = ProfileInteractor(userDataStore: UserDataStore())
var userDataStore = profileInteractor.userDataStore
profileInteractor.userDataStore = nil

print(profileInteractor.userDataStore == nil) // prints: true
print(userDataStore == nil) // prints: false
print(userDataStore === profileInteractor.userDataStore) // prints: false
  • Can anyone please explain, why userDataStore doesn't point to profileInteractor.userDataStore !?
  • What must I do, that userDataStore points to it?
twofish
  • 354
  • 4
  • 16

3 Answers3

2

I think that you are misunderstanding the purpose of assigning nil to userDataStore.

Assigning userDataStore to nil means that it will not point to anything, i.e it will be destroyed; That should not leads to let profileInteractor.userDataStore to be also nil. nil in Swift means that there is nothing at all, it does not mean that it is a pointer to an empty space in the memory.

To make it more clear, check the following code snippet:

class UserDataStore: CustomStringConvertible {
    var title: String?

    var description: String {
        return "\(title)"
    }

    init(_ title: String) {
        self.title = title
    }
}

class ProfileInteractor {

    var userDataStore: UserDataStore?

    init(userDataStore: UserDataStore?) {
        self.userDataStore = userDataStore
    }
}

var profileInteractor = ProfileInteractor(userDataStore: UserDataStore("Hello"))
var userDataStore = profileInteractor.userDataStore

print(userDataStore === profileInteractor.userDataStore) // prints: true
print(profileInteractor.userDataStore) // prints: Optional(Optional("Hello"))

userDataStore?.title = "Bye"

print(profileInteractor.userDataStore) // prints: Optional(Optional("Bye"))

userDataStore = nil

print(profileInteractor.userDataStore) // prints: Optional(Optional("Bye"))

Hope this helped.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
1

why userDataStore doesn't point to profileInteractor.userDataStore !?

In this line:

var profileInteractor = ProfileInteractor(userDataStore: UserDataStore())

You created a new ProfileInteractor object and a new UserDataStore object. Then, you made profileInteractor refer to the ProfileInteractor object.

In the next line:

var userDataStore = profileInteractor.userDataStore

You are making userDataStore refer to the same object as profileInteractor.userDataStore. Now anything you do to the UserDataStore object by using userDataStore will be reflected on profileInteractor.userDataStore because they are essentially the same thing.

However, this line changes everything:

profileInteractor.userDataStore = nil

You made profileInteractor.userDataStore refer to nothing. This DOES NOT mean that the UserDataStore object is destroyed. This just means that you no longer can use profileInteractor.userDataStore to access the UserDataStore object. But guess what is still referring to the UserDataStore object? userDataStore!

So the answer to your question is that userDataStore did point to the same object as profileInteractor.userDataStore, until you set profileInteractor.userDataStore to nil.

What must I do, that userDataStore points to it?

Well, you already did. You just made profileInteractor.userDataStore point to something else in the next line of code.

If you want a local variable to always point to the same thing that another local variable points to, your code can get quite messy, like in Ankit Thakur's answer, with unsafe pointers and stuff. If you are passing the variable to a method, you can use the inout keyword.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

Copying a reference, implicitly creates a shared instance. After a copy, two variables then refer to a single instance of the data, so modifying data in the second variable also affects the original

class UserDataStore {
    var inst:String?


    init(obj: String?) {
        self.inst = obj
    }

}

class ProfileInteractor {

    var userDataStore: UserDataStore?

    init(userDataStore: UserDataStore?) {
        self.userDataStore = userDataStore
    }
}

var profileInteractor = ProfileInteractor(userDataStore: UserDataStore(obj: "10"))
var userDataStore = profileInteractor.userDataStore

withUnsafePointer(to: &(profileInteractor.userDataStore)) {
    print(" profileInteractor.userDataStore has address: \($0)")
}
withUnsafePointer(to: &userDataStore) {
    print("userDataStore has address: \($0)")
}

withUnsafePointer(to: &(((profileInteractor.userDataStore) as! UserDataStore).inst)) {
    print(" profileInteractor.userDataStore value inst has address: \($0)")
}
withUnsafePointer(to: &(((userDataStore) as! UserDataStore).inst)) {
    print("userDataStore value inst has address: \($0)")
}

print(userDataStore)
print(profileInteractor.userDataStore)

profileInteractor.userDataStore = nil

print(profileInteractor.userDataStore == nil) // prints: true
print(userDataStore == nil) // prints: false

print(userDataStore === profileInteractor.userDataStore) // prints: false

Output:

 profileInteractor.userDataStore has address: 0x0000610000031230
userDataStore has address: 0x000000010e8103e0
 profileInteractor.userDataStore value inst has address: 0x000061000004f5b0
userDataStore value inst has address: 0x000061000004f5b0
Optional(__lldb_expr_35.UserDataStore)
Optional(__lldb_expr_35.UserDataStore)
true
false
false

Here is the nice reference of pass by value and pass by reference: https://developer.apple.com/swift/blog/?id=10

Ankit Thakur
  • 4,739
  • 1
  • 19
  • 35