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

Попытка понять блоки на iOS

Я пытаюсь понять, как использовать блоки в iOS. Я читал документы Apple, но, как обычно, они расплывчаты и неполны, и несколько существенных бит информации не упоминаются. Я тоже без искажений googled. Это то, что я пытаюсь понять как упражнение, чтобы понять это.

Я создал блок для чтения строки и сравнивает строку с предыдущим чтением. Если строки не совпадают, верните YES, если они совпадают, верните NO.

Вот как я это сделал:

Я объявил это на .h

BOOL (^differentStrings)(void);

Я объявил это на .m, внутри viewDidLoad в viewController

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

Вот как я использую: у меня есть поток, который делает это:

if (differentStrings)
  NSLog (@"strings are different);

Это проблемы, которые у меня есть:

  • блок всегда возвращает ДА ​​(строки разные)
  • Мне неудобно объявлять об этом внутри videDidLoad. Как мне объявить это, поэтому я могу использовать его глобально как метод? Должен ли я поместить это, как я бы, с помощью метода?
  • Я вызываю метод "getString" внутри блока. Все в порядке?
  • Мне кажется странным объявлять блок-переменные на .m. Как я вижу, я должен объявить блок-переменные на .h, а затем просто использовать их на .m. Я попытался это сделать, но получил сообщение об ошибке.
  • Я установил точку отладки в первой строке блока, но она не останавливается там;
  • Строка NSlog внутри блока ничего не печатает. Не называется ли блок?

Можете ли вы, ребята, помочь мне с этим?

4b9b3361

Ответ 1

Вы не понимаете, как работают блоки. (Хорошо, так что очевидно.) Точно так же, как previousString - это переменная, указывающая на NSString, differentStrings - это переменная, указывающая на блок. Не результат работы блока, а скорее сам блок. То есть, после этого:

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

differentStrings - это переменная, указывающая на блок. Таким образом, когда вы это делаете:

if (differentStrings)

... вы просто проверяете, содержит ли differentStrings что-то отличное от 0 или NULL. Поскольку он содержит блок, он не пуст, поэтому он принимает значение true.

Помните: differentStrings - это блок-переменная, а не переменная BOOL. Он содержит блок (функция, если хотите), который при вызове возвращает bool. Таким образом, чтобы фактически запустить блок, вам нужно вызвать его. Вот так:

differentStrings();

или, в вашем случае:

if (differentStrings()) {
    NSLog (@"strings are different");
}

Изменить: Как указано в комментариях, поскольку differentStrings - это переменная экземпляра, вам нужно copy это, как вы бы назовёте retain на любом другом объекте, назначенном к переменной экземпляра. (По техническим причинам я не буду сейчас вдаваться, вы всегда должны использовать copy с блоками вместо retain.) Аналогично, вам нужно будет вызвать release на нем в какой-то момент позже, возможно, в вашем dealloc.

Ответ 2

Я не верю, что вы на самом деле выполняете блок. Я думаю, что ваш код должен быть

if (differentStrings())
{
    NSLog (@"strings are different);
}

Обработать блок как функцию. Я думаю, вы просто проверяли, был ли блок определен, а не выполнял его.

Кроме того, если вам не нужен доступ к NSString за пределами блока, вы можете избавиться от квалификатора __block и переместить объявление currentString внутри блока.

Если вам нужен другой ресурс в блоках, я расскажу об этом на осенней сессии моего продвинутого курса развития iOS на iTunes U. Я описываю синтаксис блока в разделе "Поднимание" Cocoa и их использование в Grand Central Dispatch в сеансе многопоточности. Заметки курса также содержат ссылки на некоторые примеры приложений, которые используют блоки по-разному.

Я также не могу рекомендовать достаточно высоко, чтобы вы смотрели видео-сессии WWDC 2010 206 - Знакомство с блоками и Grand Central Dispatch на iPhone и 211 - Упрощение разработки приложений для iPhone с помощью Grand Central Dispatch.