Dren
Dren

Reputation: 2107

Is it correct to use local variable name "self" in blocks?

I`ve found that construction __strong typeof(self)self = weakSelf.

It allows remove NSAssert macro self catching, but I am in doubt is it right to use it in that way?

__weak typeof(self)weakSelf = self;
self.signupBlock = ^{
    __strong typeof(self)self = weakSelf;
    NSLog (@"%d", self.property)
    NSAssert((self.property > 5), @"Some message");
}

Pls advice.

Sorry, I had to say first that using of __strong typeof(self)strongSelf = weakSelf;

construction results to warnings and I suppose to mem cycle, when NSAssert macro used, because it contains self in.

Upvotes: 2

Views: 314

Answers (4)

newacct
newacct

Reputation: 122429

NSAssert is only supposed to be used in Objective-C methods, and as such it uses self and _cmd. A block is not an Objective-C method, and so you should not use NSAssert in it. You should probably use NSCAssert instead.

Upvotes: 2

fluidsonic
fluidsonic

Reputation: 4676

Yeah using self as variable name in ObjC is fine.

I made a fancy macro for such cases where you need to break a retain cycle caused by a stored block:

#define StrongSelf  __strong  __typeof__((__typeof__(self))self)
#define WeakSelf    __weak    __typeof__((__typeof__(self))self)

#define RecoverSelf  for (BOOL _continue_loop = YES; _continue_loop; _continue_loop = NO)              \
                     for (StrongSelf this = self; this != nil && _continue_loop; _continue_loop = NO)  \
                     for (StrongSelf self = this; _continue_loop; _continue_loop = NO)
#define WeakenSelf   for (BOOL _continue_loop = YES; _continue_loop; _continue_loop = NO) \
                     for (WeakSelf   this = self;  _continue_loop; _continue_loop = NO)   \
                     for (WeakSelf   self = this;  _continue_loop; _continue_loop = NO)

which you can use like that:

WeakenSelf {
    _signupBlock = ^{
        RecoverSelf {
            NSLog (@"%d", self.property)
            NSAssert((self.property > 5), @"Some message");
        }
    }
}

Upvotes: 1

Sverrisson
Sverrisson

Reputation: 18157

Change the code to, so that it´s clear that you are referring only to strongSelf in the block:

__weak typeof(self) weakSelf = self;
self.signupBlock = ^{
    typeof(weakSelf) strongSelf = weakSelf;
    if strongSelf {
        NSLog (@"%d", strongSelf.property)
        NSAssert((strongSelf.property > 5), @"Some message");
    }
}

Your code sets up a weak connection to self __weak typeof(self) weakSelf = self;. Then when it needs to call self later, it sets up a strong connection to self typeof(weakSelf) strongSelf = weakSelf; and checks if self is still around (has not been released) if strongSelf {. If so the strong connection will keep it alive while the rest of the code is run, which might in many instances involve another block to call on the main thread (i.e. hence the strong connection).

Upvotes: 2

Jakub Vano
Jakub Vano

Reputation: 3873

self is just an variable name, so it's perfectly fine to redefine it locally. It might be even preferred to

__strong typeof(weakSelf) strongSelf = weakSelf;

because

  • it makes for easily readable code
  • it prevents you for mistakenly referencing "real" self and potentially creating retain cycles.

Additionally, you might want to look at answers to this question for discussion when to use weak / strong self in blocks, and libextobjc library for neat @weakify / @strongify macros.

Upvotes: 6

Related Questions