iPhoneレシピ5:zipファイルを解凍する
ポイント
iPhoneにはzlibが入っているので、それを利用して解凍する。
zlibを使うためには、libz***.dylibへのリンクが必要。そのためには、xcodeで「グループとファイル」ビュー上で右クリック→「追加」→「既存のフレームワークを追加」でibz***.dylibを追加すればよい。
生のzlibをそのまま使うのはちょっと面倒だが、zlibと一緒に配布されているminizipをさらにObjective-Cでラップした「HetimaUnZip.framework」をHetimaさんが公開している。
HetimaUnZipはCocoaを使っているため、iPhoneで利用できるよう、Cocoaへの依存部分および不要なminizipファイルの削除と、メモリ上ではなく、直接ファイルに解凍するメソッドを追加したものを利用する。
オリジナルのFrameworkをiPhone上で使う方法が分からないため、とりあえず直接ソースのまま取り込んで使う。
改変したHetimaUnZipはここからダウンロードできる。
ソース
NSString *filePath = @"zipファイルへのパス"; HetimaUnZipContainer *unzipContainer = [[HetimaUnZipContainer alloc] initWithZipFile:filePath]; [unzipContainer setListOnlyRealFile:YES]; HetimaUnZipItem *item; NSEnumerator *contentsEnum = [[unzipContainer contents] objectEnumerator]; // プログレスバー表示用に全ファイルのサイズを取得 expectedUmcompressedContentSize = 0; for (item in contentsEnum) { expectedUmcompressedContentSize += [item uncompressedSize]; LOG(@"zip\tpath:%@\t%d", [item path], [item uncompressedSize]); } // 解凍 contentsEnum = [[unzipContainer contents] objectEnumerator]; for (item in contentsEnum) { NSString *path = [[NSFileManager defaultManager] suggestFilePath:[APPLICATION_DOC_DIR stringByAppendingPathComponent:[item path]]]; BOOL result = [item extractTo:path delegate:self]; if (!result) { NSString *err = [NSString stringWithFormat:NSLocalizedString(@"Failed to extract %@.", nil), [item path]]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:err delegate:actionSheet cancelButtonTitle:nil otherButtonTitles:@"OK",nil]; [alert show]; [alert release]; } } // HetimaUnZipItemDelegate // HetimaUnZipItem#extractTo:delegate:の解凍状況はdelegateのメソッドで取得できる。 - (void)item:(HetimaUnZipItem *)item didExtractDataOfLength:(NSUInteger)length { progressBar.progress = progressBar.progress + ((long double)length / (long double)expectedUmcompressedContentSize) * 0.5f; LOG(@"Extracting %f", progressBar.progress); }