2

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.

Dren
  • 2,017
  • 21
  • 18

4 Answers4

6

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.

Community
  • 1
  • 1
Jakub Vano
  • 3,833
  • 15
  • 29
  • Yes, but with NSAssert looks will course problems. I was interested in "self" naming of local vars, and was afraid of some problems. Now I am calm of local using of "self". – Dren May 18 '15 at 13:36
2

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).

Sverrisson
  • 17,970
  • 5
  • 66
  • 62
  • Usually do so, but without check. Nice practice, thanks. In subj question the variable name self was interested. – Dren May 18 '15 at 13:33
2

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.

newacct
  • 119,665
  • 29
  • 163
  • 224
1

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");
        }
    }
}
fluidsonic
  • 4,655
  • 2
  • 24
  • 34
  • Did not understand cleary how to use it, but looks great – Dren May 18 '15 at 13:30
  • Every reference to `self` in a `WeakSelf` block is weak (like your `__weak typeof …`). So a weak reference to `self` will be passed to the block which prevents a retain cycle. -- `RecoverSelf` does the opposite and the reference to `self` inside becomes strong again. Also the code will only be executed if `self` is still in memory and didn't become `nil`. -- So it's basically the same you did in your initial example just with a nicer syntax. – fluidsonic May 18 '15 at 13:32