Подтвердить что ты не робот

Метод вызова в текущем контроллере представления из App Delegate в iOS

У меня есть два контроллера вида (BuildingsViewController и RoomsViewController), которые используют функцию в делетете делегата с именем upload. Функция загрузки в основном выполняет HTTP-запрос, и если он успешный или неудачный, запускается uialertview. Это нормально работает.

Часть, с которой я борюсь, - это метод делегата connectionDidFinishLoading. Мне нужно иметь возможность в основном обновлять текущий контроллер представления с помощью метода viewWillAppear этого контроллера представления. Внутри функции viewWillAppear каждого контроллера представления у меня есть код, который определяет кнопки на нижней панели инструментов.

Я хочу, чтобы кнопка "загрузить" на панели инструментов каждого контроллера представления автоматически удалялась при загрузке через делегат приложения.

Я пробовал делать [viewController viewWillAppear:YES] из метода connectionDidFinishLoading делегата приложения, но он никогда не вызывается.

Надеюсь, я достаточно ясен. Любая помощь приветствуется.

Спасибо.

4b9b3361

Ответ 1

Чтобы сделать обновление представления, не вызывайте viewWillAppear, если представление уже отображается. Что вы хотите сделать, это следующее:

Когда метод ConnectionDidFinishLoading запускается после уведомления

[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshView" object:nil];

В своем viewController обратите внимание на это уведомление. Вы делаете это, добавляя этот код к методу init или viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshView:) name:@"refreshView" object:nil];

Теперь реализуем метод -(void)refreshView:(NSNotification *) notification в вашем viewController, чтобы управлять вашим представлением по своему вкусу.

Ответ 2

Если вы настроите iOS 4.0 и более поздние версии, вы можете использовать свойство window rootViewController для получения текущего контроллера вида.

[window.rootViewController viewWillAppear];

Если вы хотите, чтобы ваше приложение запускалось в версиях до iOS 4.0, вы можете добавить переменную экземпляра в делегат приложения, чтобы запомнить, какой контроллер представлений называется методом upload, имея контроллер, отправляемый как параметр.

- (void)upload:(UIViewController *)viewController {
    self.uploadingViewController = viewController; // This is the property you add
    ...
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.uploadingViewController viewWillAppear];
    self.uploadingViewController = nil;
}

Вы также должны рассмотреть возможность использования другого метода для перезагрузки кнопок, что-то вроде reloadButtons, так как оно не связано с представлением, появляющимся в этом случае. Затем вы вызываете этот метод из viewWillAppear.

Ответ 3

Шаг 1:

В вашем делете делегата .h файла вам нужно объявить такой протокол:

@protocol AppConnectionDelegate <NSObject>
@required
   -(void)connectionFinished:(NSObject*)outObject;
@end

В том же файле добавьте ivar так:

id *delegate;

Объявите ivar как свойство:

@property (nonatomic, assign) id<AppConnectionDelegate> delegate;

В файле делегата приложения .m, синтезируйте ivar:

@synthesize delegate;

В файле делегата приложения .m, на connectionDidFinishLoading выполните:

if([self.delegate respondsToSelector:@selector(connectionFinished:)])
{
   [self.delegate connectionFinished:objectYouWantToSend];
}

В вашем файле viewcontroller.h, реализуйте AppConnectionDelegate, импортировав ссылку на файл делегирования приложения:

#import "AppDelegate_iPhone.h" //if using iPhone
#import "AppDelegate_iPad.h" //if using iPad

В том же файле в конце первой строки объявления интерфейса выполните:

@interface AppDelegate_iPhone : AppDelegate_Shared <AppConnectionDelegate>

Объявите ivars соответственно:

AppDelegate_iPhone *appDelegate; //if using iPhone
AppDelegate_iPad *appDelegate; // if using iPad

В вашем файле viewcontroller.m в viewDidLoad() получите ссылку на делегата приложения, используя:

Если iPhone;

appDelegate = (AppDelegate_iPhone*)[[UIApplication sharedApplication] delegate];

Если iPad:

appDelegate = (AppDelegate_iPad*)[[UIApplication sharedApplication] delegate];

Затем установите viewcontroller как делегат в viewDidLoad(), выполнив:

appDelegate.delegate = self;

Теперь вам нужно просто реализовать метод connectionFinished в файле .m:

- (void)connectionFinished:(NSObject*)incomingObject
{
//Do whatever you want here when the connection is finished. IncomingObject is the object that the app delegate sent.
}

Теперь, когда вы вызываете соединение с делегатом connectionDidFinishLoading, контроллер уведомлений будет уведомлен.

[Лучше всего устанавливать appDelegate.delegate = nil, если вы закончили с помощью обратного вызова connectionFinished]

Это проверено и проверено. Если у вас есть вопросы, оставьте комментарий......

- EDIT -
Это надежная альтернатива NSNotification. Я использую оба в зависимости от требований. Процесс, который я использую для выбора между использованием NSNotification или обратным вызовом делегата с использованием протокола, просто:

Для уведомлений:
 Один отправитель, несколько слушателей.
 Нет никакой ссылки между отправителем и слушателем.
 Не нужно отправлять сложные/множественные объекты

Для обратных вызовов делегатов с использованием протоколов:
 Один отправитель, ограниченный (обычно 1) слушатель.
 Возможна ссылка между отправителем и слушателем.
 Сложные/множественные объекты должны быть отправлены (например, объекты ответа, которые необходимо отправить)

Я знаю, что отправка объектов возможна через уведомления, но я предпочитаю протоколы для этого.
--EDIT -

Ответ 4

Хуже всего то, что оба контроллера просмотра придерживаются простого протокола одного метода, который удалит эту кнопку и обновит представление. Затем в вашем методе connectionDidFinishLoading, поскольку вы знаете, что ваш контроллер представления должен придерживаться этого протокола, по вашему дизайну вы просто делаете что-то вроде

ViewController<MyProtocol> curView = (Get the current view controller somehow);
[curview refreshView];