iOS:彼此依赖的循环依赖方法 [英] iOS: circular dependency to call method in each other class

查看:236
本文介绍了iOS:彼此依赖的循环依赖方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在我的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆