سؤال

I was wondering about all the boiler plate necessary to create a __weak version of a type to be used inside a block in order to avoid retain cycles. The classic way I use is:

__weak typeof(self) weakSelf = self;

My immediate solution would be to define a new function like:

#define weakTypeof(type) __weak typeof(type)

Ok, this is not a great improvement but we loose to have to type __weak everywhere as in:

weakTypeof(self) weakSelf = self;

Is there any reason why I shouldn't do that?
Is there a better/more efficient way of doing this?

هل كانت مفيدة؟

المحلول

I just use code snippets in Xcode http://nshipster.com/xcode-snippets/

I've set one to when I type weakSelf to the code that you've pasted and it's a real time saver.

نصائح أخرى

I think it's probably just as easy to write:

__weak typeof(self) weakSelf = self;

It's a single line of boilerplate code that does something that anybody who reads your code can understand immediately. And if you use snippets it hardly takes any appreciable time to write.

If you use a macro, you end up with code of almost the same length as the original statement so you haven't gained much time and you've sacrificed readability, as you still need to know what the macro does.

So, In my opinion (and you know what I'm like with my opinions), it's not something you need to worry about. And you gain nothing by trying to streamline it.

Edit

To add to my assertion. I'm sure you have many lines along the lines of:

@property (strong, nonatomic) UIView *someSubview;
@property (weak, nonatomic) id<SomeDelegateProtocol> delegate;
@property (copy, nonatomic) NSString *someString;

If you think that it's a good idea to have macros for these so you can write:

propStrong UIView *someSubview;
propWeak id<SomeDelegateProtocol> delegate;
propCopy NSString *someString;

Then go ahead and implement a macro for your weakSelf declarations.

But if you think that the original version is just common boilerplate that is perfectly readable if a bit longer to write, and everybody understands at first glance then I don't think you need to worry about the un-adorned weakSelf declaration.

Although I agree with @abizern answer on the fact that readability of the code trumps speed of writing I found an interesting approach from this project and for the sake of argument I thought would be a good idea to post it.
The author here creates a macro to make a weak copy of a variable like so @weakify(<a_variable>) and then reference it inside the block using @weakify(<a_variable>). This project is also included and widely used inside ReactiveCocoa.

There are plenty of macros in the source files, mostly to deal with the fact that you can actually call @weakify() and @strongify() with multiple variables as arguments, but I manage to reduce all the code on this example here:

#define metamacro_concat(A, B) A ## B
#define weakify(VAR) \
  autoreleasepool {} \
  __weak __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR)
#define strongify(VAR) \
  autoreleasepool {} \
  _Pragma("clang diagnostic push") \
  _Pragma("clang diagnostic ignored \"-Wshadow\"") \
  __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_)\
  _Pragma("clang diagnostic pop")

...

NSString *string = @"test";

@weakify(string);

[anyObject asyncBlock:^{

    @strongify(string);
    NSLog(@"%@", string);
}];
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top