Силното прихващане на „find“ в този блок вероятно ще доведе до цикъл на задържане

Имам тази част от кода:

- (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