当应用程序处于活动状态时,不会在我的视图控制器中调用 viewWillAppear
Posted
技术标签:
【中文标题】当应用程序处于活动状态时,不会在我的视图控制器中调用 viewWillAppear【英文标题】:viewWillAppear is not called in my view controller when the app becomes active 【发布时间】:2012-04-04 18:40:14 【问题描述】:免责声明:我是 ios 新手。
我使用 Xcode 的模板创建了一个基于视图的应用程序,可以将图片上传到网站。 Xcode 自动为我创建了 AppDelegate.m (& .h) 和 ViewController.m 以及一个故事板。该应用程序是从使用 URL 架构的网站启动的,我在视图控制器中使用该信息。我有两个问题:
1) 这是将查询字符串从我的 AppDelegate 传递到视图控制器的好方法吗? 我的 AppDelegate 中有一个名为 queryStrings 的 NSDictionary 属性,用于存储查询字符串。然后在我的视图控制器中的 viewWillAppear 中,我使用以下代码来访问它:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *queryStrings = appDelegate.queryStrings;
wtID = [queryStrings valueForKey:@"wtID"];
2) 当应用程序已经启动但在后台并且用户通过网页上的 url 再次打开应用程序(使用不同的查询字符串)时,我在 AppDelegate 中实现了 openURL,它在 AppDelegate 中填充了我的 queryStrings 属性。问题是:视图控制器的 viewWillAppear 方法永远不会被调用,所以上面的代码不会被执行。如何将查询字符串数据获取到视图控制器?视图控制器如何知道应用程序刚刚激活?
注意:因为项目是使用 Xcode 中的“基于视图的应用程序”模板创建的,所以我的 AppDelegate 拥有的唯一属性是 window 属性。我不知道 AppDelegate 甚至在代码中的哪个位置引用了我的视图控制器......它从来没有设置为 rootViewController 或代码中的任何东西......我想这只是我看不到的一些 IB 魔法.
如果有帮助,这是我的 AppDelegate.h:
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NSDictionary *queryStrings;
@end
这是我的 didFinishLoadingWithOptions、openURL 和我的辅助方法:parseQueryString:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// Override point for customization after application launch.
[[JMC sharedInstance] configureJiraConnect:@"https://cmsmech.atlassian.net/" projectKey:@"WTUPLOAD" apiKey:@"7fc060e1-a795-4135-89c6-a7e8e64c4b13"];
if ([launchOptions objectForKey:UIApplicationLaunchOptionsURLKey] != nil)
NSURL *url = [launchOptions objectForKey: UIApplicationLaunchOptionsURLKey];
NSLog(@"url received: %@", url);
NSLog(@"query string: %@", [url query]);
NSLog(@"host: %@", [url host]);
NSLog(@"url path: %@", [url path]);
queryStrings = [self parseQueryString:[url query]];
NSLog(@"query dictionary: %@", queryStrings);
else
queryStrings = [self parseQueryString:@"wtID=nil"];
return YES;
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
NSLog(@"openURL executed");
if (!url)
return NO;
NSLog(@"query string: %@", [url query]);
queryStrings = [self parseQueryString:[url query]];
mainViewController.wtID = [queryStrings valueForKey:@"wtID"];
return YES;
-(NSDictionary *)parseQueryString:(NSString *)query
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:6];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for (NSString *pair in pairs)
NSArray *elements = [pair componentsSeparatedByString:@"="];
NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dictionary setObject:val forKey:key];
return dictionary;
提前致谢!
【问题讨论】:
For 2: 你能把代码放到applicationWillEnterForeground
吗?
没有问题的代码是在控制器而不是应用程序委托...
【参考方案1】:
所以,故事板开始让我感到紧张,我什至没有构建你的应用程序! :)
正如我在您的另一个问题中所述(这是重复的,但是嘿),缺少对视图控制器的引用是由于情节提要。 viewDidAppear 和 viewWillAppear 在视图添加到层次结构时被调用。往返于背景和前景并不符合添加到层次结构的条件。幸运的是,您的应用会发送与 AppDelegate 中的方法相对应的通知。只需注册为 UIApplicationWillEnterForegroundNotification 通知的观察者。然后,您可以在收到通知后触发的方法中更新您的 UI!
编辑: 将链接添加到重复的问题中以获得良好的衡量标准:How do I access my viewController from my appDelegate? iOS
【讨论】:
为了记录,我在这篇文章中问了两个密切相关的问题。其中一个与我在另一篇文章中提出的类似,但我在这篇文章中对其进行了重新组合,以更具体地说明问题所在。感谢您的 cmets 并尝试做出贡献!不幸的是,没有人有一个很好的答案...... 这个问题的答案(为什么 viewWillAppear 在从后台返回时不会被调用)已经得到解答。当您从后台返回时,如何获得更改通知还有一个答案。让我知道我是否可以在这里更清楚地回答。【参考方案2】:嗯,那为什么你的AppDelegate
中没有声明UIViewController
?
更新
当你创建一个新项目时,你的AppDelegate
中应该有这样的东西:
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UIViewController *viewController;
@end
//
#import "ViewController.h"
@implementation AppDelegate
@synthesize window, viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] init];
[self.window setRootViewController:self.viewController];
[self.window makeKeyAndVisible];
return YES;
//...
@end
【讨论】:
这是我的问题!我知道这是因为我在 Xcode 中创建项目时使用了“基于视图的应用程序”模板,我相信它是在幕后连接起来的,当我现在尝试从应用委托。你几乎总结了我的整个问题...... 使用 Storyboards 设置新项目不会在应用程序委托中为您提供 UIViewController。正如我在@HackyStack 开始的问题中解释的那样,它在情节提要的卸载过程中处理所有这些设置。 好的,但现在我被一个 99% 功能齐全的应用程序困住了,它有一个故事板。我需要访问视图控制器,因此当应用程序变为活动状态(由带有新查询字符串的 URL 启动)并且在我的应用程序委托中调用 openURL 时,我需要告诉视图控制器查询字符串已更改... 没有。那肯定不存在,jmstone 已经说过,我同意这是因为它使用了我开始想要称之为“那个愚蠢的故事板”的东西......所以现在我们知道它没有添加那个代码...... . 我该怎么办?我应该手动将上面的代码添加到我的 appDelegate 吗?添加vc属性?这会导致两种情况吗?一个是我明确创建的,一个是在故事板幕后创建的 IB?这是废话!隐藏定义 rootViewController 的代码是 CRAP! 老实说,我以前从未使用过故事板。上面的代码,我在每个项目中都有,一直有效。以上是关于当应用程序处于活动状态时,不会在我的视图控制器中调用 viewWillAppear的主要内容,如果未能解决你的问题,请参考以下文章
如何确定当前视图控制器是不是处于活动状态,如果处于活动状态则执行代码
当 UIAlertController 处于活动状态时,VoiceOver Z 手势不会触发
当 UISearchController 处于活动状态时呈现 UIAlertController
从 UIViewController 切换到另一个时如何保持 UILongPressGestureRecognizer 处于活动状态