开发者

Correct way to release object which implements NSOperationQueue and Asynchronous requests

开发者 https://www.devze.com 2023-03-07 03:39 出处:网络
I\'m struggling to figure out a solution to my problem, I have a Download class which handles calls to my api, these calls are added to a NSOperationQueue. Each call is assigned a completed and faile

I'm struggling to figure out a solution to my problem,

I have a Download class which handles calls to my api, these calls are added to a NSOperationQueue. Each call is assigned a completed and failed notifier which post's when the call completes or fails. I can then handle the completion/failure of a request in my view controller gracefully.

The problem i'm having is this, what is the correct way to alloc/init/release my download class. My first approach was like so:

alloc init a new instance of the download class every time i need to run a request, i can then have a unique instance of the cla开发者_如何学编程ss with unique complete and failed notifiers and other params as i so wish. The problem i had with this approach is when/how to release the object. I cannot simply call the fetch request and then release the object within the same call, as the download call has queue's to complete and notifications to post, i know when the instance of the download class has finished it's calls because of the notification, i just don't know the correct way to implement it's release from another function. e.g:

-(void)downloadLists:(int)page featured:(BOOL)featured {

    NSMutableDictionary *postValues = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:page],@"page",@"false",@"is_featured", nil];

    if(featured){
        [postValues setValue:@"true" forKey:@"is_featured"];
    }

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *destination = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"lists_%i.json",page]];

    Download *download = [[Download alloc] init];
    [download setCompleteNotifier:@"listsComplete"];
    [download setFailedNotifier:@"listsFailed"];
    [download downloadPOST:[NSURL URLWithString:@"http://blahblah"] values:postValues destination:destination];

}

Then where do i release download, and ensure i'm releasing the correct instance, downloadLists may be called (n) amount of times in quick succession.

My other approach was to use a singleton of Download, which was great until i needed to add userinfo to the notifications, which of course became jumbled up by the singleton class being called from different places.

Any help will be greatly appreciated, here is the downloadPOST function for your reference:

-(void)downloadPOST:(NSURL *)path values:(NSDictionary *)keyValues destination:(NSString *)destination {

    ASIFormDataRequest *formRequest = [ASIFormDataRequest requestWithURL:path];

    for(id key in keyValues){
        [formRequest setPostValue:[keyValues objectForKey:key] forKey:key];
    }

    [formRequest setDownloadDestinationPath:destination];
    [formRequest setDelegate:self];
    [formRequest setDidFinishSelector:@selector(requestDone:)];
    [formRequest setDidFailSelector:@selector(requestWentWrong:)];
    [queue addOperation:formRequest];

}


The Queue should be the one that handle the release of the object. There's several options here.

  1. You can use an NSNotification to publish your final state, which the queue listens on and remove instances that sends that notification

  2. You can create private delegation between the download & queue where the queue get notified

  3. You can set a boolean @property in you Download class (i.e BOOL completed). The queue retains the download instance and add a listener to the KVC completed. When completed is set to YES, it release the object

AFAK, you are using ASIHTTPRequest that handles all that for you, so I'm not sure why you are redoing this


It seems like you're wrapping functionality already included in ASIHTTPRequest by default. The ASI classes have delegates built in to notify you of completion or failure:

- (void)requestFinished:(ASIHTTPRequest *)request;
- (void)requestFailed:(ASIHTTPRequest *)request;

Is there any other reason you can't just create the request in your main class without creating the download class, then let the delegate let you know when it's done?

0

精彩评论

暂无评论...
验证码 换一张
取 消