0

I am new to Objective-C from iOS 8, so knowing a little about ARC, and my code is under ARC.

Say I have a class UserModel has properties like NSArray and NSString. I have initWithDataSource:data to alloc init a UserModel.

Is it safe to set a property inside block, from memory perspetive? I feel my code will cause any retain cycle. want to know should I use something like weak self or other things to set property?

//in HomeViewController.m

@interface HomeViewController() <UICollectionViewDataSource>
@property (strong, nonatomic) IBOutlet UILabel *HomeLabel;
@property (strong, nonatomic) IBOutlet UICollectionView *ProjectCollectionView;
@property (strong, nonatomic) UserModel * HomeViewUserModel;
@end


/**
 *  fetch latest projects from remote side
 */
- (void) fetchUserModelFromRemote {
    [MySharedInstance getProjectDataOnSuccess:^(id result) {

        NSDictionary *data = result[@"data"];
        self.HomeViewUserModel = [[UserModel alloc] initWithDataSource:data];

        [[NSNotificationCenter defaultCenter] postNotificationName:@"alertCountUpdate" object:self userInfo:@{@"count": (NSNumber *)data[@"unread"]}];

    }onFailure:^(id error) {}];

    [MyCache cacheProjectListWithData:self.HomeViewUserModel];
}
Wingzero
  • 9,644
  • 10
  • 39
  • 80
  • I feel there is a retain cycle because I am accessing self inside a block, so I should use weak self. Is there any best practice to set a property insisde block? – Wingzero Jan 12 '15 at 06:24

2 Answers2

2

it should only be an issue if self keeps a reference to the block its accessed in. but if you would like to be safe, just outside the block you can assign a weak variable of self's type to self, so that you are accessing a weak version of self, mitigating any doubts, eg:

__weak TypeOfSelf weakSelf = self;

//use weakSelf in block

also maybe add some nil checks to make sure its still alive before doing anything to it

Fonix
  • 11,447
  • 3
  • 45
  • 74
  • how do I tell if self keeps a reference to a block? – Wingzero Jan 12 '15 at 07:09
  • 1
    well in this case you arent, but if you implemented a property in `HomeViewController` that kept a reference to the block, then self would have a reference to the block, and the block would have a reference to self. but maybe the singleton `MySharedInstance` doesnt let go of the block ever, and that would also cause an issue – Fonix Jan 12 '15 at 07:20
  • `but maybe the singleton MySharedInstance doesnt let go of the block ever, and that would also cause an issue` that's exactly what I think is happening here. – HAS Jan 12 '15 at 08:30
  • This is not a question about "safe" or not. In the OP's sample, there is no retain cycle and using `weak` does not make it safer. When using a weak reference, though, the _logic_ and _semantic_ of the handler changes. You might want to choose _weak_ only in order to prevent the block to retain the reference so that the object _can_ be destroyed before the block finishes. And, likewise, you might want to choose a strong refernece to prevent the object to be destroyed _before_ the block gets executed. – CouchDeveloper Jan 12 '15 at 19:29
  • but one folk told me that using weak self is a good habbit, even though in this scenario, self might got dealloc or something else when it is not on the screen (since it is a view controller), but the block might hold this self until it fetches some data from internet and return. – Wingzero Jan 13 '15 at 00:31
  • that may not necessarily be a bad thing, its up to you decide whether or not that is the behaviour you want, but generally with ui elements it usually tends to be an undesired effect such as with a viewController, since if a ui element is meant to be gone forever, you wouldnt need to continue to do processing on it, so rather make the block not hold on to it – Fonix Jan 13 '15 at 01:50
  • @Wingzero You should really read this http://stackoverflow.com/questions/21987067/using-weak-self-in-dispatch-async-function/21988407#21988407 which explains all the subtleties. – CouchDeveloper Jan 14 '15 at 20:00
  • sure I will go through it – Wingzero Jan 15 '15 at 00:31
1

Your concerns are valid, but there is no retain cycle:

The anonymous block will not be referenced by self itself - thus, there's no cyclic reference.

See also: Using weak self in dispatch_async function

Community
  • 1
  • 1
CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67
  • How to tell if it is anonymous block? – Wingzero Jan 12 '15 at 06:57
  • 1
    @Wingzero When you define a block _inline_ in the same way you defined your completion handler in your sample, you do not have a variable in your code referencing this block. You could however have a property of a class which references a block. Then, instances of that class may be assigned a block by some client and `self` could call that block. In this case, self references the block. Then, when this block references `self`, then yes you get a retain cycle. – CouchDeveloper Jan 12 '15 at 19:23