Правильный способ освободить объект, который реализует NSOperationQueue и асинхронные запросы - PullRequest
2 голосов
/ 18 мая 2011

Я изо всех сил пытаюсь найти решение моей проблемы,

У меня есть класс Download, который обрабатывает вызовы моего API, эти вызовы добавляются в NSOperationQueue.Каждому вызову присваивается уведомление о завершении и сбое, которое отправляется после завершения или сбоя вызова.Затем я могу изящно обработать завершение / сбой запроса в моем контроллере представления.

У меня проблема в том, как правильно распределить / инициализировать / выпустить мой класс загрузки.Мой первый подход был таким:

alloc init новый экземпляр класса загрузки каждый раз, когда мне нужно выполнить запрос, я могу иметь уникальный экземпляр класса с уникальными завершенными и неудачными уведомителями и другими параметрамикак я так хочу.Проблема, с которой я столкнулся при таком подходе, заключается в том, когда / как освободить объект.Я не могу просто вызвать запрос на выборку и затем освободить объект в рамках того же вызова, так как вызов загрузки имеет очередь для завершения и уведомления для публикации, я знаю, когда экземпляр класса загрузки завершил свои вызовы из-за уведомления, я простоне знаю, как правильно реализовать его освобождение от другой функции.Например:

-(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];

}

Тогда где я освобождаю загрузку и гарантирую, что выпускаю правильный экземпляр, списки скачивания могут быть вызваны (n) несколько раз подряд.

Мой другойподход состоял в том, чтобы использовать синглтон Download, что было замечательно, пока мне не понадобилось добавить информацию о пользователе в уведомления, что, конечно, стало мешать синглтон-классом, вызываемым из разных мест., вот функция downloadPOST для вашей справки:

-(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];

}

Ответы [ 2 ]

2 голосов
/ 18 мая 2011

Очередь должна быть той, которая обрабатывает освобождение объекта.Здесь есть несколько вариантов.

  1. Вы можете использовать NSNotification для публикации вашего окончательного состояния, которое прослушивает очередь, и удаления экземпляров, отправляющих это уведомление

  2. Вы можете создатьчастное делегирование между загрузкой и очередью, где очередь получает уведомление

  3. Вы можете установить логический @property в вашем классе загрузки (т.е. BOOL completed).Очередь сохраняет экземпляр загрузки и добавляет прослушиватель в KVC.Когда для параметра «Завершено» задано значение «ДА», объект

AFAK освобождается, вы используете ASIHTTPRequest, который обрабатывает все это для вас, поэтому я не уверен, почему вы повторяете этот

0 голосов
/ 19 мая 2011

Похоже, вы упаковываете функциональность, уже включенную в ASIHTTPRequest по умолчанию.Классы ASI имеют встроенные делегаты, чтобы уведомить вас о завершении или сбое:

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

Есть ли какая-либо другая причина, по которой вы не можете просто создать запрос в своем основном классе, не создав класс загрузки, затем позвольтеделегат, сообщит, когда это будет сделано?

...