2012-04-04 1 views
2

Отказ от ответственности: я iOS noob.viewWillAppear не вызывается в моем контроллере просмотра, когда приложение становится активным

Я создал приложение на основе представления, используя шаблон Xcode, который загружает фотографии на веб-сайт. Xcode создал AppDelegate.m (& .h) и ViewController.m, а также раскадровку для меня автоматически. Приложение запускается с веб-сайта с использованием схемы URL-адресов, и я использую эту информацию в контроллере просмотра. У меня есть два вопроса:

1) Это хороший способ передать строки запроса из моего AppDelegate в контроллер вида?
У меня есть свойство NSDictionary в моем AppDelegate, называемое queryStrings, которое хранит строки запроса. Тогда в viewWillAppear на мой взгляд контроллера я использую следующий код для доступа к нему:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSDictionary *queryStrings = appDelegate.queryStrings; 
    wtID = [queryStrings valueForKey:@"wtID"]; 

2) Когда приложение уже запущен, но в фоновом режиме, а пользователь открывает приложение снова через URL на веб-странице (с различными строка запроса), я внедрил openURL в AppDelegate, который заполняет свойство queryStrings в AppDelegate. Проблема в том, что метод viewWillAppear контроллера вида никогда не вызывается, поэтому вышеуказанный код не выполняется. Как получить данные строки запроса в контроллер вида? Как контроллер просмотра знает, что приложение только что стало активным?

ПРИМЕЧАНИЕ. Поскольку проект был создан с использованием шаблона приложения на основе представления в Xcode, единственным свойством, которым обладает приложение AppDelegate, является свойство окна. Я не могу сказать, где в коде, что мой контроллер просмотра когда-либо даже упоминается 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; 
} 

Заранее спасибо!

+0

Для 2: Не могли бы вы, возможно, поместить код в 'applicationWillEnterForeground'? – sooper

+0

Отсутствует код в контроллере, а не делегат приложения ... – HackyStack

ответ

0

Хм, так почему нет UIViewController, заявленного в вашем AppDelegate?

UPDATE

При создании нового проекта, вы должны иметь, как это л в вашем 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 
+0

Это мой вопрос! Я знаю, это потому, что я использовал шаблон приложения на основе представления, когда я создал проект в Xcode, который, я полагаю, подключил его за кулисами, что является реальной PITA, когда я сейчас пытаюсь получить доступ к контроллеру моего представления из делегат приложения. Вы в значительной степени суммировали мою проблему ... – HackyStack

+1

Настройка нового проекта с помощью раскадровки не дает вам UIViewController в делегате приложения. Он обрабатывает все настройки этого при разгрузке раскадровки, как я объяснил в вопросе @HackyStack. – jmstone617

+0

Хорошо, но теперь я застрял с полнофункциональным приложением на 99%, имеющим раскадровку. Мне нужен доступ к контроллеру представления, поэтому, когда приложение становится активным (запущено по URL с новой строкой запроса), и openURL вызывается в моем делете приложения, мне нужно сообщить контроллеру представления, что строка запроса была изменена ... – HackyStack

1

Итак, раскадровки начинают нервничать, и я даже не строю свое приложение! :)

Как я уже говорил в вашем другом вопросе (из которого это дубликат, но эй), отсутствие ссылки на контроллер вида связано с раскадными версиями. viewDidAppear и viewWillAppear вызывается, когда представление добавляется в иерархию. Переход на задний план и на передний план не может быть добавлен в иерархию. К счастью, ваше приложение отправляет уведомления, соответствующие методам в AppDelegate. Просто зарегистрируйтесь как наблюдатель уведомления UIApplicationWillEnterForegroundNotification. Затем вы можете обновить свой интерфейс в методе, который запускается в результате получения этого уведомления!

EDIT: Добавление ссылки на дублированный вопрос для хорошей меры: How do I access my viewController from my appDelegate? iOS

+0

Для справки я задал два тесно связанных вопроса в этом посте. Один из них похож на тот, который я попросил в другом посте, но я переформулировал его в этом вопросе, чтобы уточнить, в чем проблема. Спасибо за ваши комментарии и попытки внести свой вклад! К сожалению, никто не имеет большого ответа ... – HackyStack

+0

Ответ на этот вопрос (почему viewWillAppear не получает вызов при возврате из фона) был дан ответ. Существует также ответ на вопрос, как получать уведомления об изменениях, когда вы возвращаетесь с фона. Дайте мне знать, если я смогу сделать мой ответ более ясным. – jmstone617