0

I've got a function downloading something from the internet. Then it maps the items and returns everything to the controller. The problem is that there may be a lot of items (facebook don't let to divide them) and i have to map them in the background. However the user can quit the controller already and i don't know how to check if my success() owner still exists.

Is it a good solution to put the mapping in the dispatch at all...?

Call:

[[MyHTTPClient sharedInstance] getSomethingWithAbc:abc successBlock:^{
  [self reloadMyView];
} failureBlock:^(NSError *error) {
  //nothing atm
}];

where:

@interface MyHTTPClient : AFHTTPClient
+ (OHTTPClient *)sharedInstance;
- (void)getSomethingWithAbc:(ABC *)abc successBlock:(void (^)())success failureBlock:(void (^)(NSError *error))failure;

Method implementation:

- (void)getSomethingWithAbc:(ABC *)abc successBlock:(void (^)())success failureBlock:(void (^)(NSError *error))failure {
    // request something from facebook API, wait for response then run:
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        // here map these items - there may be a lot of them so i have to do it in background
        dispatch_async(dispatch_get_main_queue(), ^{
            success(); // this may call a function from controller that does not exist already
        });
}
Nat
  • 12,032
  • 9
  • 56
  • 103

3 Answers3

0

This is fine, but you should have a cancel operation so that, before calling success, you can check if the operation has been cancelled.

Guy Kogus
  • 7,251
  • 1
  • 27
  • 32
  • The problem is that it is sharedInstance, so i can't just set a flag and cancel because i may cancel different method :/ What is more, the cancel is not on `succeed();` but when it comes back to the controller which should be deallocated (what means there was a retain on this block and i won't have my memory released) and tries `[self.tableView reloadData]`. – Nat Nov 05 '13 at 11:52
  • Then you'll need to come up with a way to identify the request being cancelled. This is typically where you'd want to use `NSOperationQueue` and `NSOperation`. – Guy Kogus Nov 05 '13 at 11:54
  • Hm, what with the problem of retain/release (2nd part of my previous comment)? – Nat Nov 05 '13 at 11:55
  • That's when you should be using weak references. If you have a weak reference to self, it will be set to `nil` for you if the controller is deallocated, in which case you can ignore the rest of the completion code. – Guy Kogus Nov 05 '13 at 15:09
0

You'd better write a network processing module is independent of your controller,and set delegate method as - (void)didSuccessWithResult:(NSDictionary*)result; - (void)didFailWithError:(NSError*)error;

or Send Notification

In you network processing module you can define download work with MyHTTPClient to complete the proxy method

Hope helpful

wormlxd
  • 514
  • 3
  • 7
  • Well it is independent of my controller - it is sharedInstance, same on whole app. As far as i understood your solution it will work the same as my solution. – Nat Nov 05 '13 at 12:07
0

However the user can quit the controller already and i don't know how to check if my success() owner still exists.

What do you mean if the owner "still exists"?

self is retained by the block. That means that the "owner" will "still exist" as long as the block exists. So if you call success() and the controller is no longer showing, well, it will reloadMyView, which (depending on what your functions do) will "reload" a view that is no longer showing. Which probably doesn't matter.

What if you want to not call reloadMyView at all? Well, you can let the block capture a weak reference to the "owner". That won't prevent it from being deallocated as it normally would. Then, when you call the success block, and the object is deallocated, the weak reference you are using will have value nil, and sending a message to nil does nothing.

You can choose which way you want.

newacct
  • 119,665
  • 29
  • 163
  • 224