Захват «найти» в этом блоке, вероятно, приведет к циклу удержания.

У меня есть этот кусок кода:

- (void) resotreEntitySelectionForHistoryObject:(CoreDataHistoryObject *)historyObject {
    OutlineViewNode *(^__block find)(OutlineViewNode *, NSString *) = ^OutlineViewNode *(OutlineViewNode *node, NSString *title) {
        if ([node.title isEqualToString:title]) {
            return node;
        }

        for (OutlineViewNode *child in node.childs) {
            OutlineViewNode *result = find(child, title);
            if (result) {
                return result;
            }
        }

        return nil;
    };

    OutlineViewNode *node = find(self.rootNode, historyObject.name);

    if (node) {
        [self.dataSourceList selectRowIndexes:[NSIndexSet indexSetWithIndex:[self.dataSourceList rowForItem:node]] byExtendingSelection:NO];
    }
}

И я получаю это предупреждение компилятора:

  • CoreDataUtility/CoreDataUtil/MFLMainWindowController.m:230:39: строгий захват «find» в этом блоке, вероятно, приведет к циклу сохранения *

Именно в этой строке "OutlineViewNode *result = find(child, title);"

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

Для справки вы можете просмотреть полный исходный код здесь:

https://github.com/yepher/CoreDataUtility/blob/master/CoreDataUtil/MFLMainWindowController.m#L224


person Yepher    schedule 10.12.2013    source источник


Ответы (1)


Блок захватывает переменную find, которая указывает на блок. Таким образом, блок имеет сильную ссылку на себя, поэтому у него есть цикл сохранения.

Чтобы сделать это правильно, вам нужны две переменные, указывающие на блок, одна слабая и одна сильная. Блок захватит слабый, чтобы не иметь сильной ссылки на себя. Сильный нужен, чтобы вообще поддерживать ссылку на блок.

OutlineViewNode *(^find)(OutlineViewNode *, NSString *);
__block OutlineViewNode *(^ __weak findWeak)(OutlineViewNode *, NSString *);
findWeak = find = ^OutlineViewNode *(OutlineViewNode *node, NSString *title) {
    if ([node.title isEqualToString:title]) {
        return node;
    }

    for (OutlineViewNode *child in node.childs) {
        OutlineViewNode *result = findWeak(child, title);
        if (result) {
            return result;
        }
    }

    return nil;
};

OutlineViewNode *node = find(self.rootNode, historyObject.name);
person newacct    schedule 11.12.2013
comment
Я попробовал код выше, но он генерирует ошибки компиляции. Если я добавлю ';' символы возвращаются к тому же предупреждению. - person Yepher; 17.12.2013
comment
@Yepher: отредактировано. кажется, что он придирчив к порядку заданий (хотя это не должно быть) - person newacct; 18.12.2013