0

Here's a little example of using weak arguments:

@interface MYTestObject : NSObject

@end

@implementation MYTestObject {
   void(^_block)(void);
}

- (void)dealloc {
   NSLog(@"DEALLOC!");
}

- (id)init {
   if (self = [super init]) {
      [self doSomethingWithObject:self];
   }
   return self;
}

- (void)doSomethingWithObject:(id __weak /* <- weak argument! */)obj {
   _block = ^{
      NSLog(@"%p", obj);
   };
}

@end

And it works: -dealloc is called! Also, if you remove __weak you'll get a retain-cycle and it's absolutely correct.

Wonder, if that's just a side-effect and it's completely unsafe to use weak arguments? Or is it a specified behavior and I'm just a bad google-user?

i_am_mushroom
  • 79
  • 1
  • 4

1 Answers1

5

Two observations:

  1. I'd be inclined to make a local __weak reference within doSomethingWithObject, rather than make it a __weak argument as illustrated in Avoid Strong Reference Cycles when Capturing self.

    I don't think that it is, as you asked, "completely unsafe to use weak arguments." But if nothing else, it's the more common pattern to have a local __weak variable and strikes me as more appropriate as an implementation detail of doSomethingWithObject rather than part of the method's public interface.

  2. I'd also make block a property with the copy memory qualifier. As the docs say

    You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it's best practice for the property attribute to show the resultant behavior.

Thus:

@interface MYTestObject : NSObject
@property (nonatomic, copy) void(^block)(void);
@end

@implementation MYTestObject

- (void)dealloc {
    NSLog(@"DEALLOC!");
}

- (id)init {
    if (self = [super init]) {
        [self doSomethingWithObject:self];
    }
    return self;
}

- (void)doSomethingWithObject:(MYTestObject *)obj { 
    
    typeof(obj) __weak weakObj = obj;
    
    self.block = ^{
        NSLog(@"%p", weakObj);
    };
}

@end
Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • thanks, @Rob! i know about alternative solutions, but my question is from the category of "what if?" questions =) – i_am_mushroom Aug 20 '13 at 07:42
  • @i_am_mushroom Understood. The answer is that you _can_, but that you probably _should not._ It's technically fine, but in my opinion not great stylistically (hence my suggestion of a preferred pattern). – Rob Aug 20 '13 at 13:17
  • you know, i asked some co-workers about subj and they were quite scared =) ...so may be it's not ok even if it's a proven technique. Anyway i also sent the question to [Clang Front End Users List](http://lists.cs.uiuc.edu/mailman/listinfo/cfe-users). – i_am_mushroom Aug 20 '13 at 17:28