How can I signal a single thread to wait for the download to complete and after that transfer data to the waiting thread

I have a singleton class to download some data from the Internet. I call the method to load the singleton class from another class "A" inside the GCD queue and the download starts. At the same time, I also execute this boot method from class "B" in the GCD queue. In this situation, I want to tell class "B" to wait for the download to complete. And when the download is complete, you will also receive a copy of the downloaded data into class "B". Here I am trying to load the same file from two classes A and B, otherwise there are no problems in my implementation. How is this possible?

Here I call the same method on different threads. So, how can I signal thread B that the same file download is being performed on stream A, and when the transfer of data to stream B is also completed

- (NSData *)Download:(NSString *)urlString{ // here I am doing all the downloading operations return data; } 
+4
source share
1 answer

Downloader.h

 // Signature of a block that is called with the downloaded data from a URL // when the download is complete typedef (void)(^)(NSData *) DownloadCompletedBlock; // Public interface of a class that downloads data from URLs // Downloads take place on a private dispatch queue, which // downloads URLs one at a time // Previously downloaded URLs are cached in a dictionary // Every so often the cache should be processed to discard old // entries. This will stop the cache from growing too large. // Since all downloads happen on the same dispatch queue, // accesses to the cache are naturally serialized without the need // for a lock @interface Downloader : NSObject // Download the contents of a URL // When the download is complete downloadCompleted will // be executed on the callbackQueue to pass the downloaded // data as a result // This is the method that thread A should call - (void)download:(NSString *)URLString calbackQueue:(dispatch_queue_t)callbackQueue completionBlock:(DownloadCompletedBlock)downloadCompleted; // Download the contents of a URL blocking the thread that calls the // method - (NSData *)downloadBlocking:(NSString *)URLString; @end 

Downloader.m

 // Private implementation interface @interface Downloader () // The thread/queue on which all downloads take place @property (readwrite, atomic) dispatch_queue_t downloadQueue; // A cache of previously downloaded URLs @property (readwrite, atomic) NSMutableDictionary *cachedDownloads; // Download the contents of a URL and cache them - (NSData *)downloadAndCacheUrl:(NSString *)URLString; @end // Implementation @implementation Downloader // Create the download queue and cache - (id)init { self = [super init]; if (self) { downloadQueue = dispatch_queue_create("downloadQueue", NULL); self.cachedDownloads = [NSMutableDictionary dictionary]; } return self; } // Download the URL aynchronously on the download queue. // When the download completes pass the result to the callback queue // by calling downloadCompleted on the callback queue - (void)download:(NSString *)URLString calbackQueue:(dispatch_queue_t)callbackQueue completionBlock:(DownloadCompletedBlock)downloadCompleted { dispatch_async(self.downloadQueue, ^{ NSData *downloadedData = [self downloadAndCacheUrl:URLString]; dispatch_async(callbackQueue, ^{ downloadCompleted(downloadedData); }); }); } // Download the data blocking the calling thread // Use a block variable to store the result // Since the downloaded data is immutable, we do not need // to worry about synchronizing it or copying it // Use dispatch_sync to wait until the result is available // If the data is already in the cache because thread A downloaded it // then the cached data is used. // Since downloads happen serially, there is only ever one download happening // at a time so the download will only happen once - (NSData *)downloadBlocking:(NSString *)URLString { __block NSData *downloadedData = nil; dispatch_sync(self.downloadQueue, ^{ downloadedData = [self downloadAndCacheUrl:URLString]; }); return downloadedData; } // Download the content of a URL. If the data has already been // downloaded and cached, then use the cached value - (NSData *)downloadAndCacheUrl:(NSString *)URLString { NSURL *URL = [NSURL URLWithString:*)URLString]; NSData *downloadedData = [self.cachedDownloads objectForKey:URL]; if (downloadedData) { return downloadedData; } downloadedData = [NSData dataWithContentsOfURL:URL]; if (downloadedData) { [self.cachedDownloads setObject:downloadedData forKey:URL]; } } @end 

Hope this is clear enough

+5
source

Source: https://habr.com/ru/post/1384865/


All Articles