Обновить изображение из вторичного контроллера просмотра

Мне нужно обновить изображение на контроллере основного представления из контроллера всплывающего окна.

Кнопка называется «Feature2btn» в главном представлении (EraViewController), но когда я пытаюсь выполнить следующий код в контроллере всплывающего окна, это не сработает.

Это должно быть немедленное обновление, поскольку основное представление все еще отображается в фоновом режиме и не перезагружается, поэтому изменение должно быть непосредственно вызвано действием во всплывающем представлении.

- (IBAction)purchase:(id)sender {
 HomeController = [[EraViewController alloc] initWithNibName:@"EraViewController" bundle:nil];
    UIImage *image = [UIImage imageNamed:@"ico_plan.png"];
    [(EraViewController*)HomeController setFeature2Btn:[feature2Btn setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
 }

person nobbsy    schedule 25.03.2013    source источник
comment
Я попытаюсь добавить селектор на свою кнопку, которая запускает метод (в основном), отвечающий за обновление изображения.   -  person OutOfBoundsException    schedule 25.03.2013


Ответы (3)


Есть (по крайней мере) два способа сделать это:

  1. Вы используете уведомление, которое прослушивает один контроллер, а другой отправляет в нужное время.
  2. Вы создаете протокол делегата, который реализует первый контроллер, а второй — при вызовах.

Делегат немного сложнее, но обычно считается хорошим стилем. Уведомление тоже неплохое, но чуть менее «элегантное». Я опишу уведомление на основе здесь, потому что это кажется подходящим для вашего случая, а также позволит реагировать на покупку в нескольких местах, просто зарегистрировавшись для получения уведомления там.

В контроллере, который имеет образ для обновления, зарегистрируйте уведомление в viewDidAppear::

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

Реализуйте метод updateImage::

-(void)updateImage:(NSNotification*)note
{
    NSString* newImageName = note.userInfo[@"imageFileKey"];
    // ... update UI with the new image
}

Также не забудьте отменить регистрацию для этого уведомления, когда представление исчезнет:

-(void)viewWillDisappear:(BOOL)animated
{
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     [super viewWillDisappear:animated];
}

В другом контроллере, который запускает обновление, запустите уведомление в соответствующем месте:

-(IBAction)purchase:(id)sender
{
    // ...

    NSDictionary* userInfo = @{@"imageFileKey" : newImageName};
    [[NSNotificationCenter defaultCenter]
                postNotificationName:@"UpdateImageNotification"
                              object:self userInfo:userInfo];
    // ...
}

Параметр object в контексте уведомления должен использоваться для указания, хотите ли вы прослушивать уведомления от любого объекта или только от очень определенного экземпляра. Во многих случаях фактический экземпляр не имеет значения, но вы просто различаете уведомления по их имени (например, «UpdateImageNotification» в этом случае).

Словарь userInfo предназначен для хранения любой информации, которую необходимо предоставить вместе с уведомлением. Вот почему я ввел ключ «imageFileKey», связанный с новым именем изображения.

person Daniel Schneller    schedule 25.03.2013

Я думаю, вы сделали небольшую ошибку. Но прежде чем двигаться дальше, я просто хочу подтвердить, является ли следующий сценарий. Поправьте меня, если я ошибаюсь 1. У вас есть mainViewController/HomeViewController (типа EraViewController), где вы хотите обновить изображение 2. На mainViewController у вас есть всплывающее окно, в котором написан вышеприведенный код. Код предназначен для изменения изображения кнопки на mainViewController/HomeViewController.

Если выше сценарий, я предлагаю следующее решение.

ВЫ СДЕЛАЛИ ОШИБКУ

Вы создаете новый объект EraViewController в коде, который вы разместили выше, и меняете изображение. В соответствии с концепциями OOPS будет создан новый экземпляр этого контроллера (второй экземпляр, который не виден на экране), и вы применяете новое изображение в этом экземпляре. Теперь, когда этот экземпляр вообще не виден, создается впечатление, что экран не обновляется.

РЕШЕНИЕ

Есть по крайней мере 3 решения этой проблемы 1. Одно решение будет дано Даниэлем Шнеллером в ответ (вероятно, с небольшими изменениями) 2. Достичь этого через делегатов. - Вы должны написать протокол в PopViewController и реализовать его в HomeViewController/mainViewController. - Когда изображение изменяется в PopViewController, об этом необходимо уведомить mainViewController, используя метод делегата и протокола. - Чтобы mainViewController получил уведомление и метод протокола был выполнен. В этом методе у вас должен быть код для обновления изображения на кнопке. 3. (Это не рекомендуется, так как это не очень хороший дизайн). Вы поддерживаете экземпляр фактического viewController, который виден на экране (в переменной, скажем, homeViewController). Затем вы можете использовать следующий код в popupViewController

- (IBAction)purchase:(id)sender {
    UIImage *image = [UIImage imageNamed:@"ico_plan.png"];
    [(EraViewController*)homeViewController setFeature2Btn:[feature2Btn setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
 }

Хоуп, это помогает.

Спасибо

person Kunal    schedule 25.03.2013
comment
Да, вы правы в идее. На самом деле я использую MJPopupViewController из следующего github. github.com/martinjuhasz/MJPopupViewController, но я использую его для покупок в приложении, поэтому я нужно обновить изображение, так как мне нужно удалить отображаемое изображение замка. - person nobbsy; 25.03.2013
comment
Вы можете использовать решение, данное Даниэлем, или вы можете использовать метод делегирования протокола для достижения результата. Скажите мне, если вам нужна помощь в том, как этого добиться. - person Kunal; 25.03.2013
comment
Я попробовал способ Даниэля, и я получаю множество ошибок. Должно быть, я делаю что-то не так... Как мне это сделать, используя метод делегата протокола? - person nobbsy; 25.03.2013
comment
знаете ли вы о написании протоколов и делгейтов. ЕСЛИ не см. theappcodeblog.com/2011/04/15/ Вам нужно написать протокол в popviewcontroller, чтобы получать уведомления об изменениях, сделанных в popviewcontroller, и вы должны обрабатывать его в главный видконтроллер. Таким образом, MainViewcontroller будет делегатом для обработки уведомления. После того, как протокол и делегат установлены, вызовите метод делегатов (метод протокола, реализованный mainviewcontroller). И в этом методе обновите свой экран. - person Kunal; 25.03.2013

Попробуй это,

 - (IBAction)purchase:(id)sender 
 {
       [[NSNotificationCenter defaultCenter] postNotificationName:@"updateimage"        object:imageName];
  }

в mainviewcontroller

-(void)viewDidLoad

{
 [[NSNotificationCenter defaultCenter] removeObserver:self];
 [[NSNotificationCenter defaultCenter] addObserver:self    selector:@selector(updateiimage:) name:@"updateimage" object:nil];

 }

- (void) updateiimage:(NSNotification *)notification
{
  NSString * text =[notification object];
   //update Image
 }
person Kalpesh    schedule 25.03.2013
comment
Это не правильно. Параметр объекта не предназначен для использования таким образом. - person Daniel Schneller; 25.03.2013
comment
Это работает отлично. Если я ошибаюсь, то как правильно это сделать. - person Kalpesh; 25.03.2013
comment
Смотрите мой ответ. Ваше решение действительно работает, но это скорее случайно, чем намеренно. Параметр объекта не предназначен для передачи информации о пользователе, но определяет, какой экземпляр отправил уведомление. - person Daniel Schneller; 25.03.2013
comment
это не будет работать, так как ViewDidLoad не вызывается при отклонении другого контроллера представления, поскольку основное представление остается в фоновом режиме и, следовательно, не перезагружается. - person nobbsy; 25.03.2013