1

So I have this snippet here which involves a block:

NSArray<Class> *acceptableClasses = @[[DesktopEntity class]];
    __block NSInteger insertIdx = row;
    
    
    [info enumerateDraggingItemsWithOptions:0 forView:_tableView classes:acceptableClasses searchOptions:nil usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop)
     {
        
        
        DesktopEntity *entity = draggingItem.item;
        
       
        [_tableContents insertObject:entity atIndex: insertIdx];
        [_tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:insertIdx] withAnimation:NSTableViewAnimationEffectGap];
        
    
        draggingItem.draggingFrame = [_tableView frameOfCellAtColumn:0 row: insertIdx];
        ++insertIdx;
    }];

it compiles fine but I'm getting a warning:

Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

I'm having some trouble understanding what it means. I managed to make the warning disappear by just typing the self keyword before the variables:

[self.tableContents insertObject:entity atIndex: insertIdx];
[self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:insertIdx] withAnimation:NSTableViewAnimationEffectGap];


draggingItem.draggingFrame = [self.tableView frameOfCellAtColumn:0 row: insertIdx];
++insertIdx;

But I've also seen people using constructs such as

__weak typeof(self) weakSelf = self;

and then using this 'weakSelf' instead, what's the difference here and is my first approach wrong?

5
  • 1
    Doesn't use instance variables anyway. Use properties instead. Instance variable should be used only in initialisers. Commented Nov 27, 2024 at 12:47
  • @Cy-4AH I am using properties though Commented Nov 27, 2024 at 16:49
  • _tableContents and _tableView are instance variables though. Commented Nov 28, 2024 at 7:07
  • @Cy-4AH I don't think so, they are declared as @property NSMutableArray* tableContents; and @property (weak) IBOutlet NSTableView *tableView; am I missing something? Commented Nov 28, 2024 at 10:43
  • Yes. Property is self.tableContents, but _tableContents is it's instance variable. It's just compiler declaring ivars automatically for you. Commented Nov 28, 2024 at 13:28

1 Answer 1

1

The block does retain self the way you're doing it.

If you know for a fact that the block is not being stored for later use by the runtime, that's fine; but if you cannot be sure that the block is not being stored for later use, you risk a retain cycle: the block retains self but perhaps, behind the scenes, someone is retaining the block, thus preventing self from ever going out of existence.

And in that case, you should use the "weak-strong dance", as illustrated in the code at the end of your question, which breaks the retain cycle by referring to self with a weak reference.

But which is the case? Is this block retained behind the scenes or not? Alas, the runtime's behavior behind the scenes is opaque. One way to find out experimentally whether there is a retain cycle is to implement dealloc on self to log to the console, and try running the app with the code your way. If the printing in dealloc never happens, then self is never being deallocated because you've created a retain cycle and you know that the weak-strong dance is needed.

Personally, I'd be inclined just to do the weak-strong dance and let it go at that. It is over-used in a knee-jerk way by a lot of programmers, so you are right to doubt its necessity here; but it does no harm and can do good, so it might be best to err on the side of caution.

Sign up to request clarification or add additional context in comments.

3 Comments

just one more question, in this same file I have other blocks for implementing my NSTableView, am I supposed to get a weak reference to self before each one of these blocks, or is it ok to declared the weak reference as a global once and use it across all the blocks?
like I'm unsure on whether to declare a macro like #define WEAKSELF __weak typeof(self) weakSelf = self; or just declare it as a global
I ended up doing it like this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.