2011-12-06 3 views
4

웹에서 데이터를 다운로드하는 싱글 톤 클래스가 있습니다. 나는 GCD 대기열 안에서 다른 클래스 'A'로부터 싱글 톤 클래스의 다운로드 메서드를 호출하고 다운로드가 시작된다. 같은 시간에 GCD Queue의 'B'클래스에서이 다운로드 메소드를 실행하고 있습니다. 이 상황에서 클래스 'B'에 다운로드가 완료 될 때까지 기다리라고 알리고 싶습니다. 그리고 다운로드가 완료되면 다운로드 된 데이터의 사본을 클래스 'B'에 제공하십시오. 여기에 두 클래스 A와 B에서 동일한 파일을 다운로드하려고합니다. 그렇지 않으면 구현시 아무런 문제가 없습니다. 그게 어떻게 가능해?다운로드가 끝날 때까지 대기 할 스레드를 신호로 알릴 수 있습니까?

의미 다른 스레드에서 같은 메서드를 호출합니다. 어떻게 내가 같은 파일 다운로드가 스레드 A에서 진행하고 완료되면 B도

- (NSData *)Download:(NSString *)urlString{ 

    // here I am doing all the downloading operations 
    return data; 
} 

답변

5

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

스레드에 데이터를 전달하는 스레드 B 신호를 보낼 수
// 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 

희망이

+0

매우 감사 충분히 분명하다 ... –

관련 문제