This has nothing to do with circular dependencies.
As you've been told, the method doSomething
is never called because you are saying
[self.mainView doSomething];
...at a time when self.mainView
has never been given a value. Merely declaring a property
@property (strong,nonatomic) ViewController *mainView;
...does not point the variable mainView
at your actual ViewController instance; it is nil
, and a message to nil
generates no error and causes nothing at all to happen.
You could fix this by having the ViewController set a reference to itself by adding one line to your code:
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
self.delegate.mainView = self; // <--
}
But don't! The simple truth is that your entire approach here is wrong. There should be no need whatever to keep a reference to your ViewController inside your app delegate. Your app has, at every moment, a view controller hierarchy. The app delegate should know where the ViewController is within that hierarchy.
Here we are in your app delegate when a link message comes in:
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
At that moment, it is the app delegate's job to know where the ViewController is in the view controller hierarchy, and even to arrange the view controller hierarchy so that the ViewController's scene is showing if it wasn't already, in response to the link message.
How you do that depends on the structure of your view controller hierarchy. You start at the top of the hierarchy, which, for the app delegate, is [[self window] rootViewController]
, and work your way down to the existing view controller you want to talk to.
You have not told us your view controller hierarchy structure, so it's impossible to help in detail. But let's say, for example, that your app revolves around a navigation controller interface. Then, for the app delegate, [[self window] rootViewController]
is the navigation controller, and so you can cast to that class: (UINavigationController*)[[self window] rootViewController]
. Then, if the ViewController is the navigation controller's root view controller, you take its viewControllers[0]
to reach it, and again you cast as needed:
UINavigationController* nav = (UINavigationController*)[[self window] rootViewController];
ViewController* vc = (ViewController*)nav.viewControllers[0];
Now you can send the doSomething
message to vc
. But that's just an illustration; the precise details will depend on where the ViewController really is, within the view controller hierarchy. And of course you might also want to pop view controllers so that the ViewController's scene is actually showing, since you likely cannot guarantee that it is showing at the time the link message comes in.
Another completely different way of handling this situation is to use the NSNotificationCenter to post a notification for which the ViewController instance has registered. That is often a solution when you do not know exactly where in the view controller hierarchy your view controller is. But in this situation, you should know that.
mainView
? If not themainView
instance variable is probably not initialized. – Capuchin