2013-01-18 2 views
0

그곳에는 파일과 폴더가있는 간단한 트리 구조가 있습니다. 가상 폴더를 다운로드 할 수있는 클라이언트 - 서버 응용 프로그램의 일부입니다. 어쨌든^블록을 사용하여 비동기 프로그래밍을하는 것을 좋아합니다. 나는 3 개의 URL을 가지고있다. 첫 번째는 폴더 설명을 다운로드하고, 두 번째는 파일을 다운로드하고, 세 번째는 폴더 내용을 다운로드하기위한 것이다. DSFolder는 폴더 설명이고 DSFile은 DSFolder에서 상속되며 다운로드 결과에 대한 NSData 필드를 포함합니다.iPhone 재귀 완료 블록

- (void)loadFolderData:(DSFolder *)folder 
       finished:(void(^)(DSFolder *))finished 
       error:(void(^)(NSError *))error { 

    if (!folder) { 
     return; 
    } 
    for (DSFolder* fileOrFolder in folder.children) { 
     if ([fileOrFolder isFolder]) { 
      [self loadFolderData:fileOrFolder 
         finished:^(DSFolder * folder) { 

         // ********************************* 
         // Next folder level would be a copy 
         // of the whole for loop in here 
         // ********************************* 

        } error:^(NSError * err) { 
         if (error) { 
          error(err); 
         } 
        }]; 
     } else { 
      [self loadFile:fileOrFolder.name 
        folder:folder.name 
        finished:^(NSData * data) { 
         ((DSFile *) fileOrFolder).data = data; 
        } error:^(NSError * err) { 
         if (error) { 
          error(err); 
         } 
        }]; 
     } 
    } 
} 

그럼 난 그냥 몇 번 내부 루프를 복사하여 트리 수준의 깊이를 제한 할 수 있지만, 매우 추한 것 같다 폴더 다운로드 코드는 다음과 같습니다. 나는이 질문이 합리적이라고 희망한다.

답변

1

재귀 이미 당신을 위해 "루프의 사본을"실행 :

- (void)loadFolderData:(DSFolder *)folder 
       finished:(void(^)(DSFolder *))finished 
       error:(void(^)(NSError *))error { 

    if (!folder) { 
     return; 
    } 
    for (DSFolder* fileOrFolder in folder.children) { 
     if ([fileOrFolder isFolder]) { 
      [self loadFolderData:fileOrFolder finished:nil error:error]; 
     } else { 
      [self loadFile:fileOrFolder.name 
        folder:folder.name 
        finished:^(NSData * data) { 
         ((DSFile *) fileOrFolder).data = data; 
        } error:error]; 
     } 
    } 
} 

을 내가 -loadFile:finished:error: 올바르게 전무 오류 블록을 처리하는 있으리라 믿고있어.

다른 몇 가지 : 하위 디렉토리가있는 경우는 잘못된 일을하는 것처럼

  • [self loadFile:fileOrFolder.name folder:folder.name ...] 보이는 : a/b/cc의 파일 이름과 b의 폴더 이름이 경로를 가정하면, b/c를로드 나타납니다 .
  • error마다 오류로 호출됩니다. 이것은 아마도 당신이 원하는 것이 아닙니다. 또한 오류를 유발 한로드를 리턴하지 않습니다.
  • 단일 콜백을 사용하는 것이 더 일반적입니다 (예 : void(^)(DSFolder*,NSError*).
  • finished는 사용하지 않습니다. 전체 계층 구조가로드를 완료하면 호출되는 것처럼 보이지만 약간 까다 롭습니다.
+0

오류 블록은 nil 값에는 아직 안전하지 않지만이를 지적 해 주셔서 감사합니다. 그리고 오류 처리가 수행되지 않습니다. 모든 파일과 폴더가 완료되면 finish 블록을 호출해야합니다. 이것이 어떻게 프로그램 될 수 있는지 알고 있습니까? 경로의 문제는 정확합니다. 파일 계층 구조에는 실제/b/c 구조가 없으며, 데이터베이스 항목으로 만들어지고, 서버는이를 처리하는 방법을 알고 있습니다. –