QuietUnrar/Carthage/Checkouts/UnrarKit/Example/Classes/UnrarExampleViewController.m

232 lines
7.6 KiB
Objective-C

//
// UnrarExampleViewController.m
// UnrarExample
//
//
#import "UnrarExampleViewController.h"
@import UnrarKit;
@interface UnrarExampleViewController ()
@property (strong) NSURL *largeArchiveURL;
@property (strong) NSProgress *currentExtractionProgress;
@end
static void *ProgressObserverContext = &ProgressObserverContext;
@implementation UnrarExampleViewController
- (void)awakeFromNib {
[super awakeFromNib];
self.extractionStepLabel.text = @"";
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *docsDir = [[fm URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] firstObject];
self.largeArchiveURL = [docsDir URLByAppendingPathComponent:@"large-archive.rar"];
}
- (IBAction)listFiles:(id)sender {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Test Archive (Password)" ofType:@"rar"];
NSError *archiveError = nil;
URKArchive *archive = [[URKArchive alloc] initWithPath:filePath error:&archiveError];
archive.password = self.passwordField.text;
if (!archive) {
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"Failed to create archive"
message:@"Error creating the archive"
preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:controller animated:YES completion:nil];
return;
}
NSError *error = nil;
NSArray *filenames = [archive listFilenames:&error];
if (!filenames) {
self.fileListTextView.text = error.localizedDescription;
return;
}
NSMutableString *fileList = [NSMutableString string];
for (NSString *filename in filenames) {
[fileList appendFormat:@"• %@\n", filename];
}
self.fileListTextView.text = fileList;
}
- (IBAction)extractLargeFile:(id)sender {
NSProgress *progress = [NSProgress progressWithTotalUnitCount:1];
self.currentExtractionProgress = progress;
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionInitial
context:ProgressObserverContext];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self updateExtractionStep:@"Creating large archive…"];
NSURL *archiveURL = [self createLargeArchive];
if (!archiveURL) {
return;
}
[self updateExtractionStep:@"Extracting archive…"];
NSError *initError = nil;
URKArchive *archive = [[URKArchive alloc] initWithURL:archiveURL
error:&initError];
if (!archive) {
[self reportError:[NSString stringWithFormat:@"Failed to create URKArchive: %@", initError.localizedDescription]];
return;
}
NSString *firstFile = [[archive listFilenames:nil] firstObject];
[progress becomeCurrentWithPendingUnitCount:1];
NSError *extractError = nil;
NSData *data = [archive extractDataFromFile:firstFile
error:&extractError];
self.currentExtractionProgress = nil;
[progress removeObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
context:ProgressObserverContext];
[progress resignCurrent];
if (!data) {
[self reportError:[NSString stringWithFormat:@"Failed to extract archive: %@", extractError.localizedDescription]];
return;
}
// On extraction completion:
[self updateExtractionStep:[NSString stringWithFormat:@"Extracted %lub", (unsigned long)data.length]];
});
}
- (IBAction)cancelExtraction:(id)sender {
if (self.currentExtractionProgress) {
[self.currentExtractionProgress cancel];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context
{
if (context == ProgressObserverContext) {
NSProgress *progress = object;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.extractionProgressView setProgress:progress.fractionCompleted
animated:YES];
}];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)reportError:(NSString *)message {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.fileListTextView.text = message;
}];
}
- (void)updateExtractionStep:(NSString *)message {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.extractionStepLabel.text = message;
}];
}
- (void)updateProgress:(float)progress {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.extractionProgressView setProgress:progress animated:YES];
}];
}
- (NSURL *)createLargeArchive {
[self reportError:@""];
[self updateExtractionStep:@"Creating large text file…"];
[self updateProgress:0];
NSURL *largeFile = [self randomTextFileOfLength:100000000];
if (!largeFile) {
[self reportError:@"Failed to create large text file"];
return nil;
}
[self updateProgress:0];
[self updateExtractionStep:@"Compressing large text file…"];
// Create archive
NSURL *archiveURL = self.largeArchiveURL;
if (![archiveURL checkResourceIsReachableAndReturnError:nil]) {
[self updateExtractionStep:@"No archive"];
[self reportError:
@"The large archive has not been created yet. A Terminal command "
"has been copied to the clipboard. Press ⌘C to copy it out "
"of the Simulator. From a prompt at the UnrarKit/Example "
"directory, paste it and run"];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = largeFile.path;
return nil;
}
return archiveURL;
}
- (NSURL *)randomTextFileOfLength:(NSUInteger)numberOfCharacters {
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *docsDir = [[fm URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] firstObject];
NSString *filename = [NSString stringWithFormat:@"long-random-str-%lu.txt", (unsigned long)numberOfCharacters];
NSURL *fileURL = [docsDir URLByAppendingPathComponent:filename];
if ([fileURL checkResourceIsReachableAndReturnError:nil]) {
return fileURL;
}
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 .,?!\n";
NSUInteger letterCount = letters.length;
NSMutableString *randomString = [NSMutableString stringWithCapacity:numberOfCharacters];
for (NSUInteger i = 0; i < numberOfCharacters; i++) {
uint32_t charIndex = arc4random_uniform((uint32_t)letterCount);
[randomString appendFormat:@"%C", [letters characterAtIndex:charIndex]];
float progress = i / (float)numberOfCharacters;
[self updateProgress:progress];
}
NSError *error = nil;
if (![randomString writeToURL:fileURL atomically:YES encoding:NSUTF16StringEncoding error:&error]) {
return nil;
}
return fileURL;
}
@end