iOS:彼此依赖的循环依赖方法 [英] iOS: circular dependency to call method in each other class
问题描述
我试图在我的 AppDelegate
和我的 ViewController
之间实现循环依赖,以从 AppDelegate
到我的 ViewController
,但是它不起作用。
I'm trying to implement circular dependency between my AppDelegate
and my ViewController
to call methods from my AppDelegate
to my ViewController
but it's not working.
查看我的代码如下:
AppDelegate.h:
@class ViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong,nonatomic) ViewController *mainView;
@end;
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
[self.mainView doSomething];
return YES;
}
ViewController.h:
#import <UIKit/UIKit.h>
@class AppDelegate;
@interface ViewController : UIViewController
@property (strong,nonatomic) AppDelegate *delegate;
-(void)doSomething;
@end;
ViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
}
- (void)doSomething
{
NSLog(@"doing something");
}
我没有任何错误或警告,但方法 doSomething
从未被调用过。你们中的任何人都知道为什么或我做错了吗?
I don't have any errors or warnings but the method doSomething
has never been call. Any of you knows why or what I'm doing wrong?
我将非常感谢您的帮助。
I'll really appreciate your help.
推荐答案
这与循环依赖无关。
正如您所知,方法 doSomething
从未被调用,因为您在说
As you've been told, the method doSomething
is never called because you are saying
[self.mainView doSomething];
...同时 self.mainView
从未被赋予 value 。仅仅声明一个属性
...at a time when self.mainView
has never been given a value. Merely declaring a property
@property (strong,nonatomic) ViewController *mainView;
...不指向变量 mainView
在您的 actual ViewController实例中;它是 nil
,并且发给 nil
的消息不会产生错误,也不会导致任何事情发生。
...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.
您可以 通过在代码中添加一行来使ViewController设置对自身的引用来解决此问题:
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; // <--
}
但不要!一个简单的事实是,您的整个方法都是错误的。在您的应用程序委托中,无需保留对ViewController的引用。您的应用随时都有一个视图控制器层次结构。应用程序委托应该知道ViewController在该层次结构中的位置。
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 {
那时,知道,其中ViewController在视图控制器层次结构中,甚至排列视图控制器层次结构,以便响应链接消息,显示ViewController的场景是否还存在。
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.
如何执行此操作取决于视图控制器层次结构的结构。您从层次结构的顶部开始,对于应用程序委托,该层次结构为 [[[self window] rootViewController]
,然后逐步查找所需的现有视图控制器
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.
您还没有告诉我们您的视图控制器层次结构,因此无法提供详细帮助。例如,假设您的应用围绕导航控制器界面运行。然后,对于应用程序委托, [[self window] rootViewController]
是导航控制器,因此可以强制转换为该类:(UINavigationController * )[[self window] rootViewController]
。然后,如果ViewController是导航控制器的根视图控制器,则使它的 viewControllers [0]
到达它,然后根据需要再次投射:
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];
现在,您可以将 doSomething
消息发送至 vc
。但这只是一个例证;具体的细节取决于ViewController层次结构中ViewController的实际位置。当然,您可能还希望弹出视图控制器,以使ViewController的场景实际显示为 ,因为您可能无法保证在链接消息进入时就显示了该场景。
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.
处理这种情况的另一种完全不同的方法是使用NSNotificationCenter 发布一个已注册ViewController实例的通知。当您不确切知道您的视图控制器在视图控制器层次结构中的什么位置时,通常这是一种解决方案。但是在这种情况下,您应该知道这一点。
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.
这篇关于iOS:彼此依赖的循环依赖方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!