현재 모든 동시 작업이 완료되면 알려주는 dispatch_group을 사용 중입니다. [TWReaderDocument documentFileURL : url withCompletionBlock :] 클래스 메서드 내에서 하나의 동시 대기열에서 일부 무거운 작업을 오프로드하고 있습니다.알림을받지 않음 dispatch_group_notify
다음 코드를 구현했지만 알림을받지 못했습니다. 난 내가 잠재적으로 아래 코드에서 잘못하고있는 무슨 표시되지 않습니다 :
dispatch_group_t readingGroup = dispatch_group_create();
NSFileManager* manager = [NSFileManager defaultManager];
NSString *docsDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Data"];
NSDirectoryEnumerator *dirEnumerator = [manager enumeratorAtURL:[NSURL fileURLWithPath:docsDir]
includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLNameKey,
NSURLIsDirectoryKey,nil]
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:nil];
// An array to store the all the enumerated file names in
NSMutableArray *arrayFiles;
// Enumerate the dirEnumerator results, each value is stored in allURLs
for (NSURL *url in dirEnumerator) {
// Retrieve the file name. From NSURLNameKey, cached during the enumeration.
NSString *fileName;
[url getResourceValue:&fileName forKey:NSURLNameKey error:NULL];
// Retrieve whether a directory. From NSURLIsDirectoryKey, also cached during the enumeration.
NSNumber *isDirectory;
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL];
if (![isDirectory boolValue]) {
dispatch_group_enter(readingGroup);
TWReaderDocument* doc = [TWReaderDocument documentFileURL:url withCompletionBlock:^(BOOL success) {
dispatch_group_leave(readingGroup);
}];
[arrayFiles addObject:doc];
}
else if ([[[fileName componentsSeparatedByString:@"_" ] objectAtIndex:0] isEqualToString:@"XXXXXX"]) {
TreeItem* treeItem = [[TreeItem alloc] init];
arrayFiles = [NSMutableArray arrayWithCapacity:10];
treeItem.child = arrayFiles;
treeItem.nodeName = [[fileName componentsSeparatedByString:@"_" ] lastObject];
[self addItem:treeItem];
}
}
dispatch_group_notify(readingGroup, dispatch_get_main_queue(), ^{ // 4
NSLog(@"All concurrent tasks completed");
});
가 dispatch_group_enter
및 dispatch_group_leave
합니까 동일한 스레드에서 실행될 수있다?
EDIT 내 팩토리 메소드의 코드가 aswell 도움이 될 :
+ (TWReaderDocument *)documentFileURL:(NSURL *)url withCompletionBlock:(readingCompletionBlock)completionBlock{
TWReaderDocument * twDoc = [[TWReaderDocument alloc] init];
twDoc.status = ReaderDocCreated;
twDoc.doc = [ReaderDocument withDocumentFilePath:[url path] withURL:url withLoadingCompletionBLock:^(BOOL completed) {
twDoc.status = completed ? ReaderDocReady : ReaderDocFailed;
completionBlock(completed);
}];
return twDoc;
}
TWReaderDocument 내부 타사 라이브러리의 다음과 같은 방법을 호출 래퍼 클래스입니다 (그것이 PDF 리더입니다)
+ (ReaderDocument *)withDocumentFilePath:(NSString *)filePath withURL:(NSURL*)url withLoadingCompletionBLock:(readingCompletionBlock)completionBlock{
ReaderDocument *document = [[ReaderDocument alloc] initWithFilePath:filePath withURL:url withLoadingCompletionBLock:[completionBlock copy]];
return document;
}
- (id)initWithFilePath:(NSString *)fullFilePath withURL:(NSURL*)url withLoadingCompletionBLock:(readingCompletionBlock)completionBlock {
id object = nil; // ReaderDocument object;
if ([ReaderDocument isPDF:fullFilePath] == YES) // File must exist
{
if ((self = [super init])) // Initialize superclass object first
{
_fileName = [ReaderDocument relativeApplicationFilePath:fullFilePath]; // File name
dispatch_async([ReaderDocument concurrentLoadingQueue], ^{
self.guid = [ReaderDocument GUID]; // Create a document GUID
self.password = nil; // Keep copy of any document password
self.bookmarks = [NSMutableIndexSet indexSet]; // Bookmarked pages index set
self.pageNumber = [NSNumber numberWithInteger:1]; // Start on page 1
CFURLRef docURLRef = (__bridge CFURLRef)url;// CFURLRef from NSURL
self.fileURL = url;
CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateX(docURLRef, self.password);
BOOL success;
if (thePDFDocRef != NULL) // Get the number of pages in the document
{
NSInteger pageCount = CGPDFDocumentGetNumberOfPages(thePDFDocRef);
self.pageCount = [NSNumber numberWithInteger:pageCount];
CGPDFDocumentRelease(thePDFDocRef); // Cleanup
success = YES;
}
else // Cupertino, we have a problem with the document
{
// NSAssert(NO, @"CGPDFDocumentRef == NULL");
success = NO;
}
NSFileManager *fileManager = [NSFileManager new]; // File manager instance
self.lastOpen = [NSDate dateWithTimeIntervalSinceReferenceDate:0.0]; // Last opened
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:fullFilePath error:NULL];
self.fileDate = [fileAttributes objectForKey:NSFileModificationDate]; // File date
self.fileSize = [fileAttributes objectForKey:NSFileSize]; // File size (bytes)
completionBlock(success);
});
//[self saveReaderDocument]; // Save the ReaderDocument object
object = self; // Return initialized ReaderDocument object
}
}
return object;
}
문서는 완료 블록 내에서 호출 할 때 nil을 효과적으로하지만 왜 dispatch_group_leave 관련이 있습니까? – tiguero
무엇 말하자면, TWReaderDocument documentFileURL : withCompletionBlock :]은 사실상 TWReaderDocument의 새로운 인스턴스를 반환하는 factory 메소드입니다. 어떤 이유로 든 인스턴스가 생성되지 않으면 completionBlock은 절대로 앞에서 설명한 것처럼 TWReaderDocument의 내부에 대해 알지 못해서는 알 수 없다. 다른 쪽에서 추론하기 : 만일 당신의'dispatch_group_notify'가 호출되지 않으면'dispatch_group_leave'의 하나 또는 그 이상의 인스턴스가 * 또한 * 호출되지 않음 – ipmcc
내 편집을 참조하십시오. 내 공장 방식을 공개했습니다. 상당히 길지만 ... Btw 문서는 외부가 아닌 완료 블록 내에서만 nil입니다. – tiguero