0

I declared NSBlockOperation with an object declared inside that operation. My app constantly is crashing because of memory issue. Appreciate any hint with a great explanation on this spent several hours still no success.

runtime: Memory Issues - (5 leaked types): 1 instance of NSExactBlockVariable leaked

- (EMUserInfoOperation*)loadingLocalModelOperationWithColor:(EMOutfitColor)outfitColor gender:(EMGender)gender {

__block EMUserInfoOperation* operation = [EMUserInfoOperation blockOperationWithBlock:^{
    NSURL* remoteURL = [NSURL URLWithString:self.settings[kEMRemoteUrlKey]];

    EMOutfitModel* model = nil;

    if (remoteURL == nil) {
        model = [[EMDomainDataLoader sharedLoader] loadEmbededOutfitNamed:self.name gender:gender];
    } else {
        model = [[EMDomainDataLoader sharedLoader] loadCachedOutfitNamed:self.name withVersion:self.version gender:gender];
    }
    [model syncApplyTextureFromPath:[self texturePathForColor:outfitColor] textureSampler:EMTextureSamplerColor];

    NSString *alphaPath = [self texturePathForAlpha];
    if(alphaPath.length > 0) {
        [model syncApplyTextureFromPath:alphaPath textureSampler:EMTextureSamplerAlpha];
    }

    operation.userInfo = model;
}];

return operation;
}
Atalyk
  • 495
  • 1
  • 5
  • 11
  • Show the implementation of `EMUserInfoOperation` (at least its initializers, dealloc, and any overrides of superclass methods) and the code which makes use of the object returned from this `-loadingLocalModelOperationWithColor:gender:` method. Without that info, there's no way we can guess what's going on. Also, run the app with the Leaks instrument template and show the retain/release history of the leaked object. – Ken Thomases May 27 '18 at 14:07

1 Answers1

0

I am guessing that your EMUserInfoOperation object has a strong reference to the block that the operation is created with. And this block also has a strong reference to the EMUserInfoOperation object because it captures the operation variable. So you have a retain cycle.

You can have the block only weakly reference the EMUserInfoOperation object by doing the following:

EMUserInfoOperation* operation;
__block __weak typeof(operation) weakOperation;
weakOperation = operation = [EMUserInfoOperation blockOperationWithBlock:^{
    typeof(operation) strongOperation = weakOperation;
    if (strongOperation) {

        // ...

        strongOperation.userInfo = model;
    }
}];
return operation;
newacct
  • 119,665
  • 29
  • 163
  • 224