diff --git a/FileExplorer.podspec.json b/FileExplorer.podspec.json index 40aac70..e84d3a1 100644 --- a/FileExplorer.podspec.json +++ b/FileExplorer.podspec.json @@ -1,6 +1,6 @@ { "name": "FileExplorer", - "version": "1.0.4", + "version": "1.1.0", "summary": "FileExplorer is a powerful iOS file browser with the possiblity to choose and remove files and/or directories", "homepage": "https://github.com/Augustyniak/FileExplorer", "screenshots": "https://raw.github.com/Augustyniak/FileExplorer/master/Resources/Directories.gif", @@ -12,8 +12,8 @@ "Rafal Augustyniak": "rafalaugustyniak@gmail.com" }, "source": { - "git": "https://github.com/Augustyniak/FileExplorer.git", - "tag": "v1.0.4" + "git": "https://github.com/GitHubKsti/FileExplorer.git", + "tag": "v1.1.0" }, "platforms": { "ios": "9.0" diff --git a/FileExplorer/FileExplorer.xcodeproj/project.pbxproj b/FileExplorer/FileExplorer.xcodeproj/project.pbxproj index 7868b0e..698a6d4 100644 --- a/FileExplorer/FileExplorer.xcodeproj/project.pbxproj +++ b/FileExplorer/FileExplorer.xcodeproj/project.pbxproj @@ -426,7 +426,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = "RafaƂ Augustyniak"; TargetAttributes = { 0634DDB31DBD28AD0053C454 = { @@ -436,7 +436,7 @@ }; 06A2082D1D85871A00E51C13 = { CreatedOnToolsVersion = 8.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 1010; ProvisioningStyle = Automatic; }; 06CB0D4B1DBD32C7008321AD = { @@ -685,6 +685,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7DF52393DC5099B7570C90BD /* Pods-FileExplorerTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = FileExplorerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -700,6 +701,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = B431DCC35D281FBEA3FDBBA3 /* Pods-FileExplorerTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = FileExplorerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -720,15 +722,24 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -755,7 +766,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos10.1; + SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = ""; @@ -774,15 +785,24 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -802,7 +822,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos10.1; + SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = ""; TARGETED_DEVICE_FAMILY = "1,2"; @@ -831,7 +851,8 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -853,7 +874,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/FileExplorer/FileExplorer.xcodeproj/xcshareddata/xcschemes/FileExplorer.xcscheme b/FileExplorer/FileExplorer.xcodeproj/xcshareddata/xcschemes/FileExplorer.xcscheme index 1ae4be0..18ae95c 100644 --- a/FileExplorer/FileExplorer.xcodeproj/xcshareddata/xcschemes/FileExplorer.xcscheme +++ b/FileExplorer/FileExplorer.xcodeproj/xcshareddata/xcschemes/FileExplorer.xcscheme @@ -1,6 +1,6 @@ + allowLocationSimulation = "YES"> Bool { switch self { case .`extension`(let `extension`): - return `extension` == (lastPathComponent as NSString).pathExtension + return `extension`.lowercased() == (lastPathComponent as NSString).pathExtension.lowercased() case .type(let t): return t == type case .lastPathComponent(let lastPathComp): diff --git a/FileExplorer/FileExplorer/DirectoryContentViewController.swift b/FileExplorer/FileExplorer/DirectoryContentViewController.swift index 30fe08c..3945fd3 100644 --- a/FileExplorer/FileExplorer/DirectoryContentViewController.swift +++ b/FileExplorer/FileExplorer/DirectoryContentViewController.swift @@ -30,6 +30,7 @@ protocol DirectoryContentViewControllerDelegate: class { func directoryContentViewController(_ controller: DirectoryContentViewController, didSelectItem item: Item) func directoryContentViewController(_ controller: DirectoryContentViewController, didSelectItemDetails item: Item) func directoryContentViewController(_ controller: DirectoryContentViewController, didChooseItems items: [Item]) + func directoryContentViewController(_ controller: DirectoryContentViewController, shouldRemoveItems: [Item], removeItemsHandler: @escaping (([Item])->Void)) } final class DirectoryContentViewController: UICollectionViewController { @@ -111,6 +112,24 @@ final class DirectoryContentViewController: UICollectionViewController { activeNavigationItemTitle = viewModel.title view.isUserInteractionEnabled = viewModel.isUserInteractionEnabled setEditing(viewModel.isEditing, animated: true) + //get the selection states from the view model and syncronize them + let selectedCellPaths = viewModel.indexPathsOfSelectedCells + for i in 0...viewModel.numberOfItems(inSection: 0) + { + guard let collectionView = collectionView else { return } + let searchIndexPath = IndexPath(item: i, section: 0) + let selectedIndexPath = selectedCellPaths.index(of: searchIndexPath) + let selected = selectedIndexPath != nil ? true : false + if selected + { + collectionView.selectItem(at: searchIndexPath, animated: true, scrollPosition: UICollectionView.ScrollPosition.left) + } + else + { + collectionView.deselectItem(at: searchIndexPath, animated: false) + } + } + } override func setEditing(_ editing: Bool, animated: Bool) { @@ -145,33 +164,46 @@ final class DirectoryContentViewController: UICollectionViewController { selectActionButton, UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), deleteActionButton - ].flatMap { $0 } + ].compactMap { $0 } } // MARK: Actions - func handleSelectButtonTap() { + @objc func handleSelectButtonTap() { viewModel.chooseItems { selectedItems in delegate?.directoryContentViewController(self, didChooseItems: selectedItems) } } - func handleDeleteButtonTap() { + @objc func handleDeleteButtonTap() { showLoadingIndicator() - viewModel.deleteItems(at: viewModel.indexPathsOfSelectedCells) { [weak self] result in - guard let strongSelf = self else { return } - strongSelf.hideLoadingIndicator() - - if case .error(let error) = result { - UIAlertController.presentAlert(for: error, in: strongSelf) - } - - strongSelf.viewModel.isEditing = false - strongSelf.delegate?.directoryContentViewController(strongSelf, didChangeEditingStatus: strongSelf.viewModel.isEditing) + viewModel.chooseItems { selectedItems in + let indexPaths = viewModel.indexPathsOfSelectedCells + delegate?.directoryContentViewController(self, shouldRemoveItems:selectedItems, removeItemsHandler:{(itemsToRemove)->Void in + var indexPathsToRemove = [IndexPath]() + for item in itemsToRemove + { + if let index = selectedItems.index(where: { $0 == item }) + { + indexPathsToRemove.append(indexPaths[index]) + } + } + self.viewModel.deleteItems(at: indexPathsToRemove) { [weak self] result in + guard let strongSelf = self else { return } + strongSelf.hideLoadingIndicator() + + if case .error(let error) = result { + UIAlertController.presentAlert(for: error, in: strongSelf) + } + + strongSelf.viewModel.isEditing = false + strongSelf.delegate?.directoryContentViewController(strongSelf, didChangeEditingStatus: strongSelf.viewModel.isEditing) + } + }) } } - func handleEditButtonTap() { + @objc func handleEditButtonTap() { viewModel.isEditing = !viewModel.isEditing delegate?.directoryContentViewController(self, didChangeEditingStatus: viewModel.isEditing) } @@ -218,7 +250,7 @@ extension DirectoryContentViewController { } override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { - if kind == UICollectionElementKindSectionHeader { + if kind == UICollectionView.elementKindSectionHeader { let header = collectionView.dequeueReusableHeader(ofClass: CollectionViewHeader.self, for: indexPath) as CollectionViewHeader header.sortModeChangeAction = viewModel.sortModeChangeAction header.sortMode = viewModel.sortMode @@ -226,7 +258,7 @@ extension DirectoryContentViewController { header.layoutIfNeeded() } return header - } else if kind == UICollectionElementKindSectionFooter { + } else if kind == UICollectionView.elementKindSectionFooter { return collectionView.dequeueReusableFooter(ofClass: CollectionViewFooter.self, for: indexPath) as CollectionViewFooter } else { fatalError() diff --git a/FileExplorer/FileExplorer/DirectoryContentViewModel.swift b/FileExplorer/FileExplorer/DirectoryContentViewModel.swift index 627d913..30d4457 100644 --- a/FileExplorer/FileExplorer/DirectoryContentViewModel.swift +++ b/FileExplorer/FileExplorer/DirectoryContentViewModel.swift @@ -76,7 +76,7 @@ final class DirectoryContentViewModel { var isEditActionHidden: Bool { let actionsConfiguration = configuration.actionsConfiguration - return !actionsConfiguration.canChooseDirectories && !actionsConfiguration.canChooseFiles && !actionsConfiguration.canRemoveDirectories && !actionsConfiguration.canRemoveFiles + return !actionsConfiguration.canChooseDirectories && !actionsConfiguration.canChooseFiles && !actionsConfiguration.canRemoveDirectories && !actionsConfiguration.canRemoveFiles || (actionsConfiguration.directSelection) } var isEditActionEnabled: Bool { @@ -148,9 +148,10 @@ final class DirectoryContentViewModel { } let numberOfSelectedItemsIsAllowed = configuration.actionsConfiguration.allowsMultipleSelection ? selectedItems.count > 0 : selectedItems.count == 1 + return !fileService.isDeletionInProgress && selectedItemsAreAllowedToBeSelected && numberOfSelectedItemsIsAllowed } - + var selectActionTitle: String { return NSLocalizedString("Choose", comment: "") } @@ -162,7 +163,7 @@ final class DirectoryContentViewModel { private let configuration: Configuration private let fileSpecifications: FileSpecifications private let fileService: FileService - + init(item: LoadedDirectoryItem, fileSpecifications: FileSpecifications, configuration: Configuration, fileService: FileService = LocalStorageFileService()) { self.url = item.url self.fileSpecifications = fileSpecifications @@ -174,14 +175,26 @@ final class DirectoryContentViewModel { self.allItems = item.resource.filter { filteringConfiguration.fileFilters.count == 0 || filteringConfiguration.fileFilters.matchesItem($0) } self.allItems = self.allItems.filter { filteringConfiguration.ignoredFileFilters.count == 0 || !filteringConfiguration.ignoredFileFilters.matchesItem($0) } self.itemsToDisplay = DirectoryContentViewModel.itemsWithAppliedFilterAndSortCriterias(searchQuery: "", sortMode: sortMode, items: self.allItems) - + + //activate editing mode directly if direct selection with single selection has been set + if configuration.actionsConfiguration.directSelection + { + isEditing = true + } NotificationCenter.default.addObserver(self, selector: #selector(handleItemsDeletedNotification(_:)), name: Notification.Name.ItemsDeleted, object: nil) } func select(at indexPath: IndexPath) { let item = self.item(for: indexPath) if isEditing { - selectedItems.append(item) + if(configuration.actionsConfiguration.allowsMultipleSelection) + { + selectedItems.append(item) + } + else{ + selectedItems.removeAll() + selectedItems.append(item) + } } else { delegate?.directoryViewModel(self, didSelectItem: item) } @@ -201,7 +214,7 @@ final class DirectoryContentViewModel { } func deleteItems(at indexPaths: [IndexPath], completionBlock: @escaping (Result) -> Void) { - let items = indexPaths.flatMap { item(for: $0) } + let items = indexPaths.compactMap { item(for: $0) } fileService.delete(items: items) { result, removedItems, itemsNotRemovedDueToFailure in completionBlock(result) self.delegate?.directoryViewModelDidChange(self) @@ -233,7 +246,7 @@ final class DirectoryContentViewModel { } private func index(for item: Item) -> IndexPath { - for (i, iterItem) in allItems.enumerated() { + for (i, iterItem) in itemsToDisplay.enumerated() { if iterItem == item { return IndexPath(item: i, section: 0) } diff --git a/FileExplorer/FileExplorer/DirectoryItemPresentationCoordinator.swift b/FileExplorer/FileExplorer/DirectoryItemPresentationCoordinator.swift index a8c5346..9a66b40 100644 --- a/FileExplorer/FileExplorer/DirectoryItemPresentationCoordinator.swift +++ b/FileExplorer/FileExplorer/DirectoryItemPresentationCoordinator.swift @@ -29,6 +29,7 @@ protocol DirectoryItemPresentationCoordinatorDelegate: class { func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didSelectItem item: Item) func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didSelectItemDetails item: Item) func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didChooseItems items: [Item]) + func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (([Item])->Void)) func directoryItemPresentationCoordinatorDidFinish(_ coordinator: DirectoryItemPresentationCoordinator) } @@ -76,6 +77,10 @@ final class DirectoryItemPresentationCoordinator { } extension DirectoryItemPresentationCoordinator: DirectoryViewControllerDelegate { + func directoryViewController(_ controller: DirectoryViewController, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (([Item]) -> Void)) { + delegate?.directoryItemPresentationCoordinator(self, shouldRemoveItems: items, removeItemsHandler: removeItemsHandler) + } + func directoryViewController(_ controller: DirectoryViewController, didSelectItem item: Item) { directoryViewController?.isSearchControllerActive = false delegate?.directoryItemPresentationCoordinator(self, didSelectItem: item) diff --git a/FileExplorer/FileExplorer/DirectoryViewController.swift b/FileExplorer/FileExplorer/DirectoryViewController.swift index 84ee28e..02be0f6 100644 --- a/FileExplorer/FileExplorer/DirectoryViewController.swift +++ b/FileExplorer/FileExplorer/DirectoryViewController.swift @@ -58,6 +58,7 @@ protocol DirectoryViewControllerDelegate: class { func directoryViewController(_ controller: DirectoryViewController, didSelectItem item: Item) func directoryViewController(_ controller: DirectoryViewController, didSelectItemDetails item: Item) func directoryViewController(_ controller: DirectoryViewController, didChooseItems items: [Item]) + func directoryViewController(_ controller: DirectoryViewController, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (([Item])->Void)) func directoryViewControllerDidFinish(_ controller: DirectoryViewController) } @@ -104,7 +105,7 @@ final class DirectoryViewController: UIViewController { addContentChildViewController(directoryContentViewController, insets: UIEdgeInsets(top: searchController.searchBar.bounds.height, left: 0.0, bottom: 0.0, right: 0.0)) navigationItem.rightBarButtonItem = directoryContentViewController.navigationItem.rightBarButtonItem navigationItem.title = directoryContentViewController.navigationItem.title - view.sendSubview(toBack: directoryContentViewController.view) + view.sendSubviewToBack(directoryContentViewController.view) setUpLeftBarButtonItem() } @@ -134,7 +135,7 @@ final class DirectoryViewController: UIViewController { // MARK: Actions - func handleFinishButtonTap() { + @objc func handleFinishButtonTap() { delegate?.directoryViewControllerDidFinish(self) } } @@ -147,6 +148,10 @@ extension DirectoryViewController: UISearchBarDelegate { } extension DirectoryViewController: DirectoryContentViewControllerDelegate { + internal func directoryContentViewController(_ controller: DirectoryContentViewController, shouldRemoveItems: [Item], removeItemsHandler: @escaping (([Item]) -> Void)) { + delegate?.directoryViewController(self, shouldRemoveItems: shouldRemoveItems, removeItemsHandler:removeItemsHandler) + } + func directoryContentViewController(_ controller: DirectoryContentViewController, didChangeEditingStatus isEditing: Bool) { searchController.searchBar.isEnabled = !isEditing } diff --git a/FileExplorer/FileExplorer/ErrorViewController.swift b/FileExplorer/FileExplorer/ErrorViewController.swift index d3d66ee..13b6434 100644 --- a/FileExplorer/FileExplorer/ErrorViewController.swift +++ b/FileExplorer/FileExplorer/ErrorViewController.swift @@ -64,7 +64,7 @@ final class ErrorViewController: UIViewController { // MARK: Actions - func handleFinishButtonTap() { + @objc func handleFinishButtonTap() { delegate?.errorViewControllerDidFinish(self) } } diff --git a/FileExplorer/FileExplorer/FileExplorerViewController.swift b/FileExplorer/FileExplorer/FileExplorerViewController.swift index 13b3691..980352c 100644 --- a/FileExplorer/FileExplorer/FileExplorerViewController.swift +++ b/FileExplorer/FileExplorer/FileExplorerViewController.swift @@ -40,6 +40,9 @@ public protocol FileExplorerViewControllerDelegate: class { /// - controller: The controller object managing the file explorer interface. /// - urls: URLs choosen by users. func fileExplorerViewController(_ controller: FileExplorerViewController, didChooseURLs urls: [URL]) + //the handler will return the urls which can be removed + //NOTE: the result URL array can be empty + func fileExplorerViewController(controller: FileExplorerViewController, shouldRemoveURLs urls: [URL], handler: @escaping (([URL]) -> Void)) } /// The FileExplorerViewController class manages customizable for displaying, removing and choosing files and directories stored in local storage of the device in your app. A file explorer view controller manages user interactions and delivers the results of those interactions to a delegate object. @@ -48,6 +51,9 @@ public final class FileExplorerViewController: UIViewController { /// The URL of directory which is initialy presented by file explorer view controller. public var initialDirectoryURL: URL = URL.documentDirectory + /// A Boolean value indicating whether the user is allowed to remove files. + public var canShareFiles: Bool = true + /// A Boolean value indicating whether the user is allowed to remove files. public var canRemoveFiles: Bool = true @@ -62,6 +68,8 @@ public final class FileExplorerViewController: UIViewController { /// A Boolean value indicating whether multiple files and/or directories can be choosen at a time. public var allowsMultipleSelection: Bool = true + /// if directSelection is enabled -> enable editing mode directly + public var directSelection: Bool = false /// Filters that determine which files are displayed by file explorer view controller. /// @@ -113,11 +121,13 @@ public final class FileExplorerViewController: UIViewController { super.viewWillAppear(animated) let fileSpecifications = FileSpecifications(providers: fileSpecificationProviders) - let actionsConfiguration = ActionsConfiguration(canRemoveFiles: canRemoveFiles, + let actionsConfiguration = ActionsConfiguration(canShareFiles: canShareFiles, + canRemoveFiles: canRemoveFiles, canRemoveDirectories: canRemoveDirectories, canChooseFiles: canChooseFiles, canChooseDirectories: canChooseDirectories, - allowsMultipleSelection: allowsMultipleSelection) + allowsMultipleSelection: allowsMultipleSelection, + directSelection: directSelection) let filteringConfiguration = FilteringConfiguration(fileFilters: fileFilters, ignoredFileFilters: ignoredFileFilters) let configuration = Configuration(actionsConfiguration: actionsConfiguration, filteringConfiguration: filteringConfiguration) @@ -145,4 +155,24 @@ extension FileExplorerViewController: ItemPresentationCoordinatorDelegate { let urls = items.map { $0.url } delegate?.fileExplorerViewController(self, didChooseURLs: urls) } + + func itemPresentationCoordinator(_ coordinator: ItemPresentationCoordinator, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (_ removeItems:[Item]) -> Void) + { + let urls = items.map { $0.url } + delegate?.fileExplorerViewController(controller: self, shouldRemoveURLs: urls, handler: { (filesToRemove) -> Void in + var resultArray = [Item] () + for fileUrl in filesToRemove + { + for item in items + { + if item.url == fileUrl + { + resultArray.append(item) + } + } + } + removeItemsHandler(resultArray) + }) + + } } diff --git a/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift b/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift index d4721bc..a88347e 100644 --- a/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift +++ b/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift @@ -32,9 +32,11 @@ final class FileItemPresentationCoordinator { fileprivate weak var navigationController: UINavigationController? fileprivate let fileService: FileService fileprivate let fileSpecifications: FileSpecifications + fileprivate let configuration: Configuration fileprivate let item: Item - init(navigationController: UINavigationController, item: Item, fileSpecifications: FileSpecifications, fileService: FileService = LocalStorageFileService()) { + init(configuration: Configuration, navigationController: UINavigationController, item: Item, fileSpecifications: FileSpecifications, fileService: FileService = LocalStorageFileService()) { + self.configuration = configuration self.navigationController = navigationController self.item = item self.fileSpecifications = fileSpecifications @@ -69,7 +71,7 @@ final class FileItemPresentationCoordinator { private func makePresentingViewController(item: Item, builder: @escaping (LoadedItem) -> UIViewController) -> UIViewController { let viewController = LoadingViewController.make(item: item) { [weak self] loadedItem in let contentViewController = builder(loadedItem) - let actionsViewController = ActionsViewController(contentViewController: contentViewController) + let actionsViewController = ActionsViewController(configuration: self!.configuration, contentViewController: contentViewController) actionsViewController.delegate = self return actionsViewController } @@ -81,6 +83,7 @@ extension FileItemPresentationCoordinator: ActionsViewControllerDelegate { func actionsViewControllerDidRequestShare(_ controller: ActionsViewController) { let activityItem = UIActivityItemProvider(placeholderItem: item.url) let activityViewController = UIActivityViewController(activityItems: [activityItem], applicationActivities: nil) + activityViewController.popoverPresentationController?.sourceView = navigationController?.view navigationController?.present(activityViewController, animated: true, completion: nil) } diff --git a/FileExplorer/FileExplorer/FileService.swift b/FileExplorer/FileExplorer/FileService.swift index 95b9d91..44be591 100644 --- a/FileExplorer/FileExplorer/FileService.swift +++ b/FileExplorer/FileExplorer/FileService.swift @@ -103,7 +103,7 @@ final class LocalStorageFileService: FileService { deletedItems, itemsNotRemovedDueToFailure) } else { - completionBlock(.success(), deletedItems, itemsNotRemovedDueToFailure) + completionBlock(.success(()), deletedItems, itemsNotRemovedDueToFailure) } } diff --git a/FileExplorer/FileExplorer/FileViewController.swift b/FileExplorer/FileExplorer/FileViewController.swift index 1e6d483..aafde43 100644 --- a/FileExplorer/FileExplorer/FileViewController.swift +++ b/FileExplorer/FileExplorer/FileViewController.swift @@ -44,21 +44,21 @@ final class FileViewController: UIViewController { let imageView = ImageView() imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.setContentCompressionResistancePriority(UILayoutPriorityDefaultLow, for: .vertical) - imageView.setContentCompressionResistancePriority(UILayoutPriorityDefaultLow, for: .horizontal) + imageView.setContentCompressionResistancePriority(UILayoutPriority.defaultLow, for: .vertical) + imageView.setContentCompressionResistancePriority(UILayoutPriority.defaultLow, for: .horizontal) let titleView = TitleView() titleView.translatesAutoresizingMaskIntoConstraints = false titleView.title = viewModel.title - titleView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical) - titleView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .horizontal) + titleView.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical) + titleView.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal) let attributesView = AttributesView() attributesView.translatesAutoresizingMaskIntoConstraints = false attributesView.numberOfAttributes = viewModel.numberOfAttributes - attributesView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical) - attributesView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .horizontal) + attributesView.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical) + attributesView.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal) for (index, label) in attributesView.attributeNamesColumn.labels.enumerated() { let attributeViewModel = viewModel.attribute(for: index) label.text = attributeViewModel.attributeName @@ -150,7 +150,7 @@ final class TitleView: UIView { titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor, constant: -1.0).isActive = true titleLabel.widthAnchor.constraint(equalTo: widthAnchor, constant: -20.0).isActive = true - titleLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical) + titleLabel.setContentHuggingPriority(UILayoutPriority.required, for: .vertical) titleLabel.numberOfLines = 1 titleLabel.lineBreakMode = .byTruncatingTail @@ -185,7 +185,7 @@ final class TitleView: UIView { } override var intrinsicContentSize: CGSize { - return CGSize(width: UIViewNoIntrinsicMetric, height: 42.0) + return CGSize(width: UIView.noIntrinsicMetric, height: 42.0) } } diff --git a/FileExplorer/FileExplorer/FileViewModel.swift b/FileExplorer/FileExplorer/FileViewModel.swift index 423f63a..878557e 100644 --- a/FileExplorer/FileExplorer/FileViewModel.swift +++ b/FileExplorer/FileExplorer/FileViewModel.swift @@ -47,7 +47,7 @@ final class FileViewModel { FileViewModel.makeFileSizeItem(fromAttributes: self.item.attributes), FileViewModel.makeCreationDateItem(fromAttributes: self.item.attributes), FileViewModel.makeModificationDateItem(fromAttributes: self.item.attributes) - ].flatMap { $0 } + ].compactMap { $0 } } func thumbnailImage(with size: CGSize) -> UIImage { diff --git a/FileExplorer/FileExplorer/ItemCell.swift b/FileExplorer/FileExplorer/ItemCell.swift index 42ce185..45b78e5 100644 --- a/FileExplorer/FileExplorer/ItemCell.swift +++ b/FileExplorer/FileExplorer/ItemCell.swift @@ -30,8 +30,8 @@ protocol Editable { } enum ColorPallete { - static let gray = UIColor(colorLiteralRed: 200/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1.0) - static let blue = UIColor(colorLiteralRed: 21/255.0, green: 126/255.0, blue: 251/255, alpha: 1.0) + static let gray = UIColor.init(red: 200/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1.0) + static let blue = UIColor.init(red: 21/255.0, green: 126/255.0, blue: 151/255.0, alpha: 1.0) } enum LayoutConstants { @@ -151,26 +151,26 @@ final class ItemCell: UICollectionViewCell, Editable { private func setupAccessoryImageViewConstraints() { accessoryImageView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -15).isActive = true accessoryImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true - accessoryImageView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .horizontal) - accessoryImageView.setContentCompressionResistancePriority(UILayoutPriorityDefaultHigh, for: .vertical) - accessoryImageView.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .horizontal) + accessoryImageView.setContentCompressionResistancePriority(UILayoutPriority.required, for: .horizontal) + accessoryImageView.setContentCompressionResistancePriority(UILayoutPriority.defaultHigh, for: .vertical) + accessoryImageView.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .horizontal) } private func setupTitleLabelContstraints() { titleTextLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 12.0).isActive = true titleTextLabel.trailingAnchor.constraint(equalTo: accessoryImageView.leadingAnchor, constant: -10.0).isActive = true titleTextLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 12.0).isActive = true - titleTextLabel.setContentCompressionResistancePriority(UILayoutPriorityDefaultHigh, for: .horizontal) - titleTextLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .vertical) + titleTextLabel.setContentCompressionResistancePriority(UILayoutPriority.defaultHigh, for: .horizontal) + titleTextLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .vertical) } private func setupSubtitleLabelConstraints() { subtitleTextLabel.leadingAnchor.constraint(equalTo: titleTextLabel.leadingAnchor).isActive = true subtitleTextLabel.trailingAnchor.constraint(equalTo: titleTextLabel.trailingAnchor).isActive = true subtitleTextLabel.topAnchor.constraint(equalTo: titleTextLabel.bottomAnchor, constant: 3.0).isActive = true - subtitleTextLabel.setContentCompressionResistancePriority(UILayoutPriorityDefaultHigh + subtitleTextLabel.setContentCompressionResistancePriority(UILayoutPriority.defaultHigh , for: .horizontal) - subtitleTextLabel.setContentHuggingPriority(UILayoutPriorityDefaultHigh, for: .vertical) + subtitleTextLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .vertical) } private func setupCheckmarkButtonConstraints() { @@ -260,7 +260,7 @@ final class ItemCell: UICollectionViewCell, Editable { // MARK: Actions - func handleAccessoryImageTap() { + @objc func handleAccessoryImageTap() { tapAction() } } diff --git a/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift b/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift index 2750dc2..9c51f35 100644 --- a/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift +++ b/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift @@ -30,6 +30,7 @@ import AVFoundation protocol ItemPresentationCoordinatorDelegate: class { func itemPresentationCoordinatorDidFinish(_ coordinator: ItemPresentationCoordinator) func itemPresentationCoordinator(_ coordinator: ItemPresentationCoordinator, didChooseItems items: [Item]) + func itemPresentationCoordinator(_ coordinator: ItemPresentationCoordinator, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (([Item]) -> Void)) } final class ItemPresentationCoordinator { @@ -51,7 +52,7 @@ final class ItemPresentationCoordinator { switch item.type { case .file: - let coordinator = FileItemPresentationCoordinator(navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) + let coordinator = FileItemPresentationCoordinator(configuration: configuration, navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) coordinator.start(animated) childCoordinators.append(coordinator) case .directory: @@ -69,13 +70,14 @@ final class ItemPresentationCoordinator { } extension ItemPresentationCoordinator: DirectoryItemPresentationCoordinatorDelegate { + func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didSelectItem item: Item) { start(item: item, fileSpecifications: fileSpecifications, configuration: configuration, animated: true) } func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didSelectItemDetails item: Item) { guard let navigationController = navigationController else { fatalError() } - let coordinator = FileItemPresentationCoordinator(navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) + let coordinator = FileItemPresentationCoordinator(configuration: configuration, navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) childCoordinators.append(coordinator) coordinator.startDetailsPreview(true) } @@ -87,4 +89,9 @@ extension ItemPresentationCoordinator: DirectoryItemPresentationCoordinatorDeleg func directoryItemPresentationCoordinatorDidFinish(_ coordinator: DirectoryItemPresentationCoordinator) { delegate?.itemPresentationCoordinatorDidFinish(self) } + internal func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, shouldRemoveItems items: [Item], removeItemsHandler: @escaping (([Item]) -> Void)) { + delegate?.itemPresentationCoordinator(self, shouldRemoveItems: items, removeItemsHandler: {(itemsToRemove) -> Void in + removeItemsHandler(itemsToRemove) + }) + } } diff --git a/FileExplorer/FileExplorer/UICollectionView+Extension.swift b/FileExplorer/FileExplorer/UICollectionView+Extension.swift index fe1b876..e0cbfc9 100644 --- a/FileExplorer/FileExplorer/UICollectionView+Extension.swift +++ b/FileExplorer/FileExplorer/UICollectionView+Extension.swift @@ -42,23 +42,23 @@ extension UICollectionView { } func registerFooter(ofClass viewClass: AnyClass) { - register(viewClass, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: String(describing: viewClass)) + register(viewClass, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: String(describing: viewClass)) } func dequeueReusableFooter(ofClass cellClass: AnyClass, for indexPath: IndexPath) -> T { - return dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: String(describing: cellClass), for: indexPath) as! T + return dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: String(describing: cellClass), for: indexPath) as! T } func registerHeader(ofClass viewClass: AnyClass) { - register(viewClass, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: String(describing: viewClass)) + register(viewClass, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: String(describing: viewClass)) } func dequeueReusableHeader(ofClass cellClass: AnyClass, for indexPath: IndexPath) -> T { - return dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: String(describing: cellClass), for: indexPath) as! T + return dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: String(describing: cellClass), for: indexPath) as! T } func header(for indexPath: IndexPath) -> T? { - return supplementaryView(forElementKind: UICollectionElementKindSectionHeader, at: indexPath) as? T + return supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath) as? T } } diff --git a/FileExplorer/FileExplorer/UITableView+Extension.swift b/FileExplorer/FileExplorer/UITableView+Extension.swift index dbd3e16..d6655ba 100644 --- a/FileExplorer/FileExplorer/UITableView+Extension.swift +++ b/FileExplorer/FileExplorer/UITableView+Extension.swift @@ -38,7 +38,7 @@ extension UITableView { return cell } - func makeCell(with style: UITableViewCellStyle) -> UITableViewCell { + func makeCell(with style: UITableViewCell.CellStyle) -> UITableViewCell { return UITableViewCell(style: style, reuseIdentifier: String(describing: UITableViewCell.self)) } } diff --git a/FileExplorer/FileExplorer/UIViewController+Extension.swift b/FileExplorer/FileExplorer/UIViewController+Extension.swift index 3eb4f1f..b643957 100644 --- a/FileExplorer/FileExplorer/UIViewController+Extension.swift +++ b/FileExplorer/FileExplorer/UIViewController+Extension.swift @@ -39,7 +39,7 @@ extension UIViewController { func showLoadingIndicator() { guard self.activityIndicatorView == nil else { return } - let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge) + let activityIndicatorView = UIActivityIndicatorView(style: .whiteLarge) activityIndicatorView.color = .gray activityIndicatorView.hidesWhenStopped = true activityIndicatorView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY) @@ -96,9 +96,9 @@ extension UIViewController { extension UIViewController { func addContentChildViewController(_ content: UIViewController, insets: UIEdgeInsets = UIEdgeInsets.zero) { view.addSubview(content.view) - addChildViewController(content) - content.view.frame = UIEdgeInsetsInsetRect(view.bounds, insets) + addChild(content) + content.view.frame = view.bounds.inset(by: insets) content.view.autoresizingMask = [.flexibleHeight, .flexibleWidth] - content.didMove(toParentViewController: self) + content.didMove(toParent: self) } } diff --git a/FileExplorer/FileExplorer/URL+Extension.swift b/FileExplorer/FileExplorer/URL+Extension.swift index cf66ab4..aed6d9d 100644 --- a/FileExplorer/FileExplorer/URL+Extension.swift +++ b/FileExplorer/FileExplorer/URL+Extension.swift @@ -43,6 +43,6 @@ extension URL { } func makeStandarizedFirstCharacterOfLastPathComponent() -> Character? { - return makeStandarizedLastPathComponent().localizedUppercase.characters.first + return makeStandarizedLastPathComponent().localizedUppercase.first } } diff --git a/FileExplorer/Pods/Pods.xcodeproj/project.pbxproj b/FileExplorer/Pods/Pods.xcodeproj/project.pbxproj index 7dea3ed..8ae007f 100644 --- a/FileExplorer/Pods/Pods.xcodeproj/project.pbxproj +++ b/FileExplorer/Pods/Pods.xcodeproj/project.pbxproj @@ -369,7 +369,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 1010; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -444,20 +444,32 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", @@ -519,6 +531,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 288824B537CA00FFBE130853E0AFDE17 /* Pods-FileExplorerTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -591,6 +604,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 103C19DFDFB60CB84A61B57E0EDB51AE /* Pods-FileExplorerTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; @@ -698,19 +712,31 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", @@ -724,6 +750,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 10.0; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; SYMROOT = "${SRCROOT}/../build"; VALIDATE_PRODUCT = YES; }; diff --git a/FileExplorer/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-FileExplorerTests.xcscheme b/FileExplorer/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-FileExplorerTests.xcscheme index 9c784f4..b37b2b4 100644 --- a/FileExplorer/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-FileExplorerTests.xcscheme +++ b/FileExplorer/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Pods-FileExplorerTests.xcscheme @@ -1,6 +1,6 @@