我试图从AppDelegate中向我的标签式应用中的所有ViewControllers注入一个依赖关系(到数据存储),而不是通过回到appDelegate中访问数据存储。我使用的是一个故事板。
我在application:didFinishLaunchingWithOptions:中这样做,代码执行起来没有错误。
然而,当任何一个viewControllers呈现时,我注入数据存储的属性包含nil。我希望它能有一个对数据存储的引用。
我想也许我的数据存储在application:didFinishLaunchingWithOptions返回后超出了范围,导致数据存储变成了nil。但据我所知,ARC应该可以防止这种情况发生。
我开始怀疑,也许在application:didFinishLaunchingWithOptions:完成运行后,VC可能会消失。所以我给视图控制器添加了一个dealloc方法,看看它是否被调用,瞧,它被调用了。这就解释了为什么我之前注入的依赖关系不再存在。
现在我被卡住了,因为我不知道如何将依赖注入到视图控制器中。我剩下的唯一想法是在AppDelegate中添加属性,并使用它们来保留视图控制器,但这感觉有点危险,因为我现在干扰了iOS对视图控制器的管理。
下面是AppDelegate中的代码。
//AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
//AppDelegate.m
#import "AppDelegate.h"
#import "InjectedViewController.h"
#import "InjectedDataStore.h"
@interface AppDelegate ()
@property (strong, nonatomic) InjectedDataStore *myDataStore;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIStoryboard *storyBoard;
storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
if (!_myDataStore) {
self.myDataStore = [[InjectedDataStore alloc]init];
NSLog(@"alloc inited %@", self.myDataStore);
}
UITabBarController *tabBarController = (UITabBarController *)initViewController;
for (InjectedViewController *ivc in tabBarController.viewControllers) {
ivc.dataStore = self.myDataStore;
NSLog(@"dataStore injected into ivc: %@", ivc.dataStore);
}
NSLog(@"application:didFinishLaunching... done");
return YES;
}
@end
这是我的视图控制器子类,里面有我想注入的属性。
//InjectedViewController.h
#import <UIKit/UIKit.h>
#import "InjectedDataStore.h"
NS_ASSUME_NONNULL_BEGIN
@interface InjectedViewController : UIViewController
@property (strong, nonatomic) InjectedDataStore *dataStore;
@end
NS_ASSUME_NONNULL_END
InjectedViewController.m是锅炉模板,其他都是空的。InjectedDataStore.m和.h是一个锅炉模板的Cocoa Touch类,没有任何属性或方法。
而这里是其中一个视图控制器--它被嵌入到一个标签视图中。另一个标签页的视图控制器是相同的。
//FirstViewController.h
#import <UIKit/UIKit.h>
#import "InjectedViewController.h"
@interface FirstViewController : InjectedViewController
@end
//FirstViewController.m
#import "FirstViewController.h"
@interface FirstViewController ()
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"data store for FirstVC: %@", self.dataStore);
}
- (void) dealloc {
NSLog(@"First VC dealloc called");
}
@end
最后,是控制台输出。
alloc inited <InjectedDataStore: 0x600001d483a0>
dataStore injected into ivc: <InjectedDataStore: 0x600001d483a0>
dataStore injected into ivc: <InjectedDataStore: 0x600001d483a0>
application:didFinishLaunching... done
First VC dealloc called ///this is what causes the injected element to disappear.
Second VC dealloc called ///causes the injected element to disappear.
data store for FirstVC: (null)
data store for SecondVC: (null)
(我最终会实现一个协议,但现在因为我被困在了注入工作中,所以我就不说了。)
在我看来,我在这里所做的和@juanignaciosi的回答非常相似。这个 问题。
感谢任何反馈,我对iOS是个相对新手。
你的窗口属性是 nil
.由于iOS 13系统采用的是 window
从场景委托人中删除场景委托人和 UIApplicationSceneManifest
如果你不需要,可以从plist中获取。