Objective-C: нужна помощь, чтобы понять, почему два метода по-разному реагируют на доступ к UIView двумя разными способами.

Я чувствую себя плохо, задавая три вопроса в течение двух дней, но я застрял и ищу форум, я не мог найти ответ, поэтому я надеюсь, что кто-то может мне помочь - все это часть удовольствия от обучения, я полагаю!

В моей программе есть три представления, которые идут в порядке GridScreen -> GameScreen -> CorrectScreen. На CorrectScreen у меня есть кнопка, которая возвращается к GridScreen.

На GridScreen у меня есть куча кнопок, которые пользователь может нажать, чтобы перейти к GameScreen. Когда пользователь правильно отвечает на вопрос, он перемещается с GameScreen на CorrectScreen для подтверждения, а затем обратно на GridScreen.

В предыдущем вопросе я спрашивал, как отследить кнопку, которая была нажата на GridScreen, чтобы, когда я вернусь к ней с CorrectScreen, я мог заменить значок на галочку. Это было решено ранее, но тем самым я создал еще одну проблему.

В CorrectScreen, когда пользователь нажимает кнопку для возврата, вызываются следующие две функции:

[self.gridScreen updateUserIcon:buttonThatWasPressed];
[self.gridScreen updatePoints:accumulatedpoints];

где updateUserIcon:

-(void)updateUserIcon:(UIButton *)button
{
UIButton *buttonPressed = button; 
self.button1 = buttonPressed;
[self.button1 setImage:[UIImage imageNamed:@"tick.png"] forState:UIControlStateNormal];
}

и updatePoints:

-(void)updatePoints:(int)points
{
    self.currentPoints.text = [[NSString alloc]initWithFormat:@"Current points: %d", points];
}

где button1 — это UIButton, а currentPoints — это UILabel.

Теперь, когда я возвращаюсь к GridScreen, используя следующий код после вызова двух функций, галочка появляется на нужной мне кнопке, но метка не обновляется правильно: ПЕРВЫЙ СЛУЧАЙ:

[[[self presentingViewController]presentingViewController] dismissModalViewControllerAnimated:YES];

тогда как, если я использую этот следующий способ, галочка вообще не появляется, но метка обновляется идеально: ВТОРОЙ СЛУЧАЙ:

GridScreen *screen = [[GridScreen alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:screen animated:YES];

(Я обычно загружаю представления, используя второй случай).

В первом случае, даже если бы я сделал следующий код:

-(void)updatePoints:(int)points
{
    self.currentPoints.text = @"A";
    NSLog(@"Current Points %@", self.currentPoints.text);
}

Мой NSLog возвращает текущие точки (ноль).

Решение связано с моим первым методом возврата к GridScreen. Я на самом деле не загружаю представление снова, но во втором методе я это делаю, но я не могу понять, что мне нужно сделать, чтобы правильно обновить оценку и клещ.

Если кто-нибудь может помочь, я хотел бы знать - я новичок в программировании на Objective-C, поэтому, если что-то из этого является "плохим кодом", я буду рад узнать, что не так, поэтому в будущем я не делаю подобных ошибок.

Еще раз спасибо всем вам, этот сайт отлично помогает, и заранее я ценю советы.

Энди.


person user1309044    schedule 03.06.2012    source источник
comment
похоже, что ваше представление еще не загружено должным образом (для уверенности установите точку останова на viewDidLoad), поэтому currentPoints является нулевым объектом.   -  person Michael Dautermann    schedule 04.06.2012
comment
Привет, Майкл - может быть, это ответ на ваш вопрос - когда я запускаю viewDidLoad в части GridScreen, функция устанавливает текст CurrentPoints, который в начальном случае равен «Current Points: 0», как я и ожидал (NSLog подтверждает это). Конечно, при использовании метода «Случай 1» возврата к GridScreen это не вызывает viewDidLoad во второй раз. Это означает, что в моем вопросе я фактически дважды устанавливаю self.currentPoints.text, используя второй метод, поскольку я устанавливаю его в viewDidLoad и в updatePoints, но на самом деле это просто для иллюстрации вопроса.   -  person user1309044    schedule 04.06.2012


Ответы (1)


Хорошо, глупый вопрос, но почему вы просто не используете уведомления для сообщений на экранах?

Это самый простой и безопасный подход.

В GridScreen добавьте это уведомление:

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

перед нажатием нового экрана.

Теперь в CorrectScreen запустите это уведомление перед отображением представления:

[[NSNotificationCenter defaultCenter] postNotificationName:@"CorrectAnswerNotification" object:self userInfo:nil];

Передайте любую информацию, которую вы хотите, в словаре userInfo (это может быть словарь, чтобы вы могли передавать любую информацию, которая вам нужна)

А в GridScreen всем управлять в методе toggleLabel:

-(void)toggleLabel:(NSNotification *)notification {

    //read the documentation dictionary
    NSDictionary *infoDictionary = [notification userInfo];
    //remove the notification first

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"CorrectAnswerNotification" object:nil];

    //now change the buttons...
    [self updateUserIcon:buttonThatWasPressed];
    [self updatePoints:accumulatedpoints];

}

Поскольку меня спрашивали о Центре уведомлений, вот некоторые подробности прямо из Документация Apple:

Объект NSNotificationCenter (или просто центр уведомлений) предоставляет механизм для широковещательной передачи информации внутри программы. Объект NSNotificationCenter по сути является таблицей отправки уведомлений.

Объекты регистрируются в центре уведомлений для получения уведомлений (объекты NSNotification) с помощью методов addObserver:selector:name:object: или addObserverForName:object:queue:usingBlock:. Каждый вызов этого метода указывает набор уведомлений. Следовательно, объекты могут регистрироваться как наблюдатели разных наборов уведомлений, вызывая эти методы несколько раз.

Когда объект (известный как отправитель уведомления) публикует уведомление, он отправляет объект NSNotification в центр уведомлений. Затем центр уведомлений уведомляет любых наблюдателей, для которых уведомление соответствует критериям, указанным при регистрации, отправляя им указанное сообщение уведомления, передавая уведомление в качестве единственного аргумента.

Центр уведомлений поддерживает таблицу отправки уведомлений, в которой указывается набор уведомлений для конкретного наблюдателя. Набор уведомлений — это подмножество уведомлений, отправленных в центр уведомлений. Каждая запись таблицы содержит три элемента:

Notification observer: Required. The object to be notified when qualifying notifications are posted to the notification center.

Notification name: Optional. Specifying a name reduces the set of notifications the entry specifies to those that have this name.

Notification sender: Optional. Specifying a sender reduces the set of notifications the entry specifies to those sent by this object.
person Lefteris    schedule 03.06.2012
comment
Привет, Лефтерис, я сделал то, что вы сказали, и это сработало - хотя, честно говоря, я понятия не имею, почему, поскольку я никогда раньше не слышал о NSNotificationCenter! Не могли бы вы объяснить по-человечески, что здесь происходит? Я чувствую, что это то, что я должен знать! Когда я проснусь завтра (сейчас 1:40), я тоже прочитаю об этом - спасибо за решение! - person user1309044; 04.06.2012
comment
Сейчас 3:40 утра, так что я тоже отвечу завтра. Кстати, вы должны принять ответ, если он работает! - person Lefteris; 04.06.2012
comment
Спасибо - я с нетерпением жду вашего ответа - и теперь принято :) спокойной ночи! - person user1309044; 04.06.2012
comment
Я обновил вопрос, добавил некоторую документацию и исправил функцию toggleLabel, чтобы она также принимала уведомление, чтобы вы могли читать словарь. - person Lefteris; 04.06.2012
comment
спасибо, Лефтерис, - большое спасибо - я уверен, что это окажется очень полезным для меня сейчас и в будущем! - person user1309044; 04.06.2012