6

I am trying to implement a login-scheme in WatchKit (whether or not having the user type data into his Watch shouldn't be of concern here) which means that after logging in, the user should see a view that doesn't let him go back to the login screen (no < at the top left corner)

If users get kicked out of their session (e.g. when not paying their subscription) I want the app to go back to the login screen.

Redirecting from the login screen to the main screen works fine using

DispatchQueue.main.async() { [weak self] in
                    WKInterfaceController.reloadRootControllers(
                        withNames: ["mainController"], contexts: [values]
                    )
                }

but then when I try to do the same in the main controller using

DispatchQueue.main.async() { [weak self] in
                    WKInterfaceController.reloadRootControllers(
                        withNames: ["loginController"], contexts: [message]
                )
}

the loginScreen gets displayed BUT the view controller from the main screen stays alive, keeps receiving Notifications from other objects and keeps spawning new loginControllers. I've already tried

    self?.pop()
    self?.dismiss()
    self?.popToRootController()
    self?.presentController(withName: 

none of which seem to deactivate the mainController. What can I do in this situation?

I do not need ANYTHING from the mainController as I will create a new one after successful login so how can I make sure to destroy the object entirely? I don't want to take care of all the references, listeners, timers, ... in the mainController which is why I am perfectly fine with destroying it.

user2875404
  • 3,048
  • 3
  • 25
  • 47
  • I think you just keeping a reference to the `mainController` somewhere. May be it has a retain cycle. – kelin Mar 11 '18 at 11:13
  • How would references like this look like in Swift? – user2875404 Mar 12 '18 at 11:53
  • 1
    Well, if you store some class instance in a variable, that instance becomes referenced by the variable. And if the variable is `strong`, the instance is retained. All classes are passed by reference in Swift. There are also `weak` and `unowned` variables. [Read more](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html). – kelin Mar 12 '18 at 13:10
  • This is happening to me too. Just curious, when you go into memory debug graph, is your controller being kept in memory by `NSMutableDictionary (Storage)` ? – Joey Slomowitz Aug 29 '19 at 01:35
  • Same problem. @JoeySlomowitz did you manage to find the problem? I am reloading the root with a ViewModel instance. The interface controllers are deallocated as expected, but the "contexts" are not (aka the view models). I am even keeping weak references to them – Alexandru Motoc Dec 30 '20 at 20:29

3 Answers3

0

It's not easy to answer such question without having your main controller code. @kelin is probably right.

Have you tried to use the Memory Graph tool?

Debug Navigator -> Debug Area Separator -> The 3 connected circles icon

XCode Debug Area Separator

It gives you a state of the retains at a given time and can sometimes be. very helpful.

I would put a break in the login controller didAppear ( among other possibilities ) and inspect the graph.

Moose
  • 2,607
  • 24
  • 23
0

Without seeing any of your code for the value you're trying to pass into the context, I would say that it's your context which is responsible for keeping some object in memory, which in turn is keeping your controller in memory. You can confirm this by checking the memory graph if you see NSMutableDictionary (Storage) holding onto the object that you're trying to pass around. - this is the context.

One messy solution is to just create an optional global var for whatever value you want to keep a reference to, and just assign it whatever value when needed and set it to nil when you want it deallocated. It's quite messy but it will solve your problem.

Joey Slomowitz
  • 179
  • 1
  • 12
0

This seems to be a relevant thread:

https://developer.apple.com/forums/thread/659778?answerId=654730022#654730022

Looks like the call to WKInterfaceController.reloadRootPageControllers is keeping the objects into memory, regardless of how you hold a reference to them (could be weak, etc.)

Alexandru Motoc
  • 582
  • 7
  • 14