Class object in NSOperationQueue - with asynchronous method using delegate

I created a subclass NSOperation

named DownloadQueue

. And I add all objects one by one to NSOperationQueue

which is appDelegate.queueDownload

.

The problem is when the object is executed DownloadOperation

, and as soon as the download

method is executed DownloadOperation

, my object DownloadOperation

is removed from the queue.

But I have to keep it in memory, because when I make an asynchronous [using downloadFromPath

] call in DownloadOperation.m

and the server responds with the file data, at that time the object is DownloadOperation

freed and liveOperationSucceeded

never called.

Maybe I think this question is a little tricky, so read it twice before flagging it! It is very important for me. Thank you for understanding.

    // Adding to queue

    DownloadOperation *operation = [[DownloadOperation alloc] init];

    operation.delegate = self;

    [operation operationWithFileOrFolderID:dictDocument[@"id"] withParentPath:self.strParentPath download:NO withFileName:dictDocument[@"name"] withDictionary:dictDocument];
    [operation download];

    [operation setQueuePriority:NSOperationQueuePriorityVeryHigh];

    [appDelegate.queueDownload addOperation:operation];

      

DownloadOperation.m (which is a subclass NSOperation

)

@implementation DownloadOperation

-(void)main
{
    [self download];
}

- (void)operationWithFileOrFolderID: (NSString *)strID withParentPath: (NSString *)strParentPath download: (BOOL)isDownload withFileName: (NSString *)strFileName withDictionary: (NSMutableDictionary *)dictInfoLocal
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    self.documentsDirectory = paths[0];

    self.strFileName = strFileName;
    self.strID = strID;
    self.strParentPath = strParentPath;
    self.dictInfo = dictInfoLocal;

    if (self)
    {

    }
}

- (void)download
{
    self.liveClient = [[LiveConnectClient alloc] initWithClientId:CLIENT_ID delegate:self];

    [self.liveClient downloadFromPath:[self.strID stringByAppendingString:@"/content"] delegate:self];

    NSLog(@"DownloadFilesVC : Downloading : %@",self.strFileName);    
}

- (void) liveOperationSucceeded:(LiveOperation *)operation
{

}

- (void) liveOperationFailed:(NSError *)error
                   operation:(LiveOperation *)operation
{

}

- (void) liveDownloadOperationProgressed:(LiveOperationProgress *)progress data:(NSData *)receivedData operation:(LiveDownloadOperation *)operation
{

}

@end

      

+3


source to share


2 answers


You have an async operation inside an operation.

The operational queue does exactly what it is supposed to do and pops the completed one DownloadOperation

when the method completes download

. Don't care if the operation has callbacks.

You need to retain ownership of it by DownloadOperation

adding it to a tightly bound set like NSArray

or NSSet

, and discard it at a later point when it completes LiveConnectClient

. You can add the BOOL property DownloadOperation

to say.

@property BOOL imReallyReallyFinishedAndCanBeDiscardedOK;

EDIT



The API is async / delegate. One easy way is to loop through the contents of the folder and count the responses. After you have received a number of responses that match the number of requests you know, you have completed.

As a very simplified version that doesn't care about recursion or errors.

@interface DownloadManager  : NSObject

@property NSArray *fileRefList;
@property NSUInteger count;
@property (strong) void (^completionBlock)();

@end

@implementation DownloadManager

-(void)downloadAllTheFiles {

    self.count = 0;
    for(NSString *strID in self.fileRefList) {

        LiveConnectClient *liveClient = [[LiveConnectClient alloc] initWithClientId:CLIENT_ID delegate:self];
        [liveClient downloadFromPath:[strID stringByAppendingString:@"/content"] delegate:self];

    }

}

- (void) liveOperationSucceeded:(LiveOperation *)operation
{
    self.count++;
    [self haveIFinished];
}

- (void) liveOperationFailed:(NSError *)error
                   operation:(LiveOperation *)operation
{
    self.count++;
    [self haveIFinished];
}

-(void)haveIFinished {

    if (self.count == self.fileRefList.count) {
        if (self.completionBlock) {
            self.completionBlock();
        }
    }

}

      

Let the API do the queue and background activities for you. An arbitrary block died when it was executed.

+2


source


Do not allocate * DownloadOperation * in method

Make this property in .h file like



@property (non-atomic, strong) DownloadOperation *,

0


source







All Articles