FLEXFileBrowserSearchOperation.m 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //
  2. // FLEXFileBrowserSearchOperation.m
  3. // FLEX
  4. //
  5. // Created by 啟倫 陳 on 2014/8/4.
  6. // Copyright (c) 2014年 f. All rights reserved.
  7. //
  8. #import "FLEXFileBrowserSearchOperation.h"
  9. @implementation NSMutableArray (FLEXStack)
  10. - (void)flex_push:(id)anObject {
  11. [self addObject:anObject];
  12. }
  13. - (id)flex_pop {
  14. id anObject = self.lastObject;
  15. [self removeLastObject];
  16. return anObject;
  17. }
  18. @end
  19. @interface FLEXFileBrowserSearchOperation ()
  20. @property (nonatomic) NSString *path;
  21. @property (nonatomic) NSString *searchString;
  22. @end
  23. @implementation FLEXFileBrowserSearchOperation
  24. #pragma mark - private
  25. - (uint64_t)totalSizeAtPath:(NSString *)path {
  26. NSFileManager *fileManager = NSFileManager.defaultManager;
  27. NSDictionary<NSString *, id> *attributes = [fileManager attributesOfItemAtPath:path error:NULL];
  28. uint64_t totalSize = [attributes fileSize];
  29. for (NSString *fileName in [fileManager enumeratorAtPath:path]) {
  30. attributes = [fileManager attributesOfItemAtPath:[path stringByAppendingPathComponent:fileName] error:NULL];
  31. totalSize += [attributes fileSize];
  32. }
  33. return totalSize;
  34. }
  35. #pragma mark - instance method
  36. - (id)initWithPath:(NSString *)currentPath searchString:(NSString *)searchString {
  37. self = [super init];
  38. if (self) {
  39. self.path = currentPath;
  40. self.searchString = searchString;
  41. }
  42. return self;
  43. }
  44. #pragma mark - methods to override
  45. - (void)main {
  46. NSFileManager *fileManager = NSFileManager.defaultManager;
  47. NSMutableArray<NSString *> *searchPaths = [NSMutableArray new];
  48. NSMutableDictionary<NSString *, NSNumber *> *sizeMapping = [NSMutableDictionary new];
  49. uint64_t totalSize = 0;
  50. NSMutableArray<NSString *> *stack = [NSMutableArray new];
  51. [stack flex_push:self.path];
  52. //recursive found all match searchString paths, and precomputing there size
  53. while (stack.count) {
  54. NSString *currentPath = [stack flex_pop];
  55. NSArray<NSString *> *directoryPath = [fileManager contentsOfDirectoryAtPath:currentPath error:nil];
  56. for (NSString *subPath in directoryPath) {
  57. NSString *fullPath = [currentPath stringByAppendingPathComponent:subPath];
  58. if ([[subPath lowercaseString] rangeOfString:[self.searchString lowercaseString]].location != NSNotFound) {
  59. [searchPaths addObject:fullPath];
  60. if (!sizeMapping[fullPath]) {
  61. uint64_t fullPathSize = [self totalSizeAtPath:fullPath];
  62. totalSize += fullPathSize;
  63. [sizeMapping setObject:@(fullPathSize) forKey:fullPath];
  64. }
  65. }
  66. BOOL isDirectory;
  67. if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDirectory] && isDirectory) {
  68. [stack flex_push:fullPath];
  69. }
  70. if ([self isCancelled]) {
  71. return;
  72. }
  73. }
  74. }
  75. //sort
  76. NSArray<NSString *> *sortedArray = [searchPaths sortedArrayUsingComparator:^NSComparisonResult(NSString *path1, NSString *path2) {
  77. uint64_t pathSize1 = [sizeMapping[path1] unsignedLongLongValue];
  78. uint64_t pathSize2 = [sizeMapping[path2] unsignedLongLongValue];
  79. if (pathSize1 < pathSize2) {
  80. return NSOrderedAscending;
  81. } else if (pathSize1 > pathSize2) {
  82. return NSOrderedDescending;
  83. } else {
  84. return NSOrderedSame;
  85. }
  86. }];
  87. if ([self isCancelled]) {
  88. return;
  89. }
  90. dispatch_async(dispatch_get_main_queue(), ^{
  91. [self.delegate fileBrowserSearchOperationResult:sortedArray size:totalSize];
  92. });
  93. }
  94. @end