Актуализиране на изображението от контролера за вторичен изглед

Трябва да актуализирам изображение на главния контролер за изглед от изскачащ контролер за изглед.

Бутонът се нарича „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
Можете да използвате решението, дадено от daniel, или можете да използвате метод за делегиране на протокол, за да постигнете резултата. Кажете ми, ако имате нужда от помощ за това как да постигнете това. - person Kunal; 25.03.2013
comment
Опитах начина на Даниел и получавам много грешки. Сигурно правя нещо нередно... Как бих го направил с помощта на метода за делегат на протокол? - person nobbsy; 25.03.2013
comment
наясно ли сте с писането на протоколи и делегати. АКО не вижте theappcodeblog.com/2011/04/15/ Трябва да напишете протокол в popviewcontroller, за да получавате известията за промените, направени в popviewcontroller, и трябва да го обработвате в mainviewcontroller. Така че MainViewcontroller ще бъде делегат, който да обработва известието. След като протоколът и делегатът са зададени, извикайте метода delegates (методът на протокола, реализиран от 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