Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Assets/Demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ To install Xcode Cleaner go to [releases](https://github.com/IrelDev/XcodeCleane
<p align="center">
<img src = "Assets/Demo.gif" /><br>
</p>

## License
XcodeCleaner is available under the MIT license, see the [LICENSE](LICENSE) file for more information.
22 changes: 20 additions & 2 deletions XcodeCleaner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
9D5A202724BC1A7F0066303A /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D5A202624BC1A7F0066303A /* ActivityIndicatorView.swift */; };
9DB4448224BAEFEE00165FB9 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB4448124BAEFEE00165FB9 /* FileType.swift */; };
9DCE1C0B24B582D200E49E6D /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DCE1C0A24B582D200E49E6D /* CoreDataManager.swift */; };
9DD3BA7024B4639400EDA308 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DD3BA6F24B4639400EDA308 /* AppDelegate.swift */; };
9DD3BA7224B4639400EDA308 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DD3BA7124B4639400EDA308 /* ContentView.swift */; };
Expand Down Expand Up @@ -51,6 +53,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
9D5A202624BC1A7F0066303A /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = "<group>"; };
9DB4448124BAEFEE00165FB9 /* FileType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileType.swift; sourceTree = "<group>"; };
9DCE1C0A24B582D200E49E6D /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = "<group>"; };
9DD3BA6C24B4639400EDA308 /* XcodeCleaner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XcodeCleaner.app; sourceTree = BUILT_PRODUCTS_DIR; };
9DD3BA6F24B4639400EDA308 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -108,6 +112,15 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
9DB4448024BAEFCE00165FB9 /* Enums */ = {
isa = PBXGroup;
children = (
9DD3BA8F24B478B600EDA308 /* DirectoryType.swift */,
9DB4448124BAEFEE00165FB9 /* FileType.swift */,
);
path = Enums;
sourceTree = "<group>";
};
9DD3BA6324B4639400EDA308 = {
isa = PBXGroup;
children = (
Expand All @@ -130,14 +143,14 @@
isa = PBXGroup;
children = (
9DD3BA6F24B4639400EDA308 /* AppDelegate.swift */,
9DD3BA8F24B478B600EDA308 /* DirectoryType.swift */,
9DD3BA8D24B478AE00EDA308 /* DirectoryManager.swift */,
9DCE1C0A24B582D200E49E6D /* CoreDataManager.swift */,
9DD3BA9624B478CC00EDA308 /* Views */,
9DD3BA9124B478C100EDA308 /* Models */,
9DD3BA9624B478CC00EDA308 /* Views */,
9DD3BAA924B4795A00EDA308 /* ViewModels */,
9DD3BAB224B4798200EDA308 /* Protocols */,
9DD3BABB24B479B300EDA308 /* Helpers */,
9DB4448024BAEFCE00165FB9 /* Enums */,
9DD3BABE24B479C900EDA308 /* PieChart */,
9DD3BA7624B4639700EDA308 /* Assets.xcassets */,
9DD3BA7B24B4639700EDA308 /* Main.storyboard */,
Expand Down Expand Up @@ -170,6 +183,7 @@
isa = PBXGroup;
children = (
9DD3BA7124B4639400EDA308 /* ContentView.swift */,
9D5A202624BC1A7F0066303A /* ActivityIndicatorView.swift */,
9DD3BA9924B478FD00EDA308 /* BodyViews */,
9DD3BA9A24B4790200EDA308 /* FooterViews */,
);
Expand Down Expand Up @@ -361,6 +375,7 @@
9DD3BAA824B4794C00EDA308 /* ScanProgressView.swift in Sources */,
9DD3BAC524B479ED00EDA308 /* PieChartSubSliceView.swift in Sources */,
9DD3BA8E24B478AE00EDA308 /* DirectoryManager.swift in Sources */,
9DB4448224BAEFEE00165FB9 /* FileType.swift in Sources */,
9DD3BAB024B4796C00EDA308 /* ViewModel.swift in Sources */,
9DD3BA9424B478C900EDA308 /* DirectoryModel.swift in Sources */,
9DD3BAA224B4793900EDA308 /* FooterView.swift in Sources */,
Expand All @@ -381,6 +396,7 @@
9DD3BAD224B47A1E00EDA308 /* PieChartSliceModel.swift in Sources */,
9DD3BAB824B4798E00EDA308 /* PieChartViewModelProtocol.swift in Sources */,
9DD3BAB124B4796C00EDA308 /* DirectoryListViewModel.swift in Sources */,
9D5A202724BC1A7F0066303A /* ActivityIndicatorView.swift in Sources */,
9DD3BAC024B479DF00EDA308 /* PieChartSliceFactory.swift in Sources */,
9DD3BAD324B47A1E00EDA308 /* PieChartObservableItemsModel.swift in Sources */,
9DD3BA7524B4639400EDA308 /* XcodeCleaner.xcdatamodeld in Sources */,
Expand Down Expand Up @@ -534,6 +550,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.ireldev.XcodeCleaner.XcodeCleaner;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -557,6 +574,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.ireldev.XcodeCleaner.XcodeCleaner;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand Down
90 changes: 73 additions & 17 deletions XcodeCleaner/DirectoryManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,18 @@ struct DirectoryManager {
}
func getArchivesPath() -> String {
let xcodePath = getXcodeDefaultPath()
let deviceSupportPath = "Archives/"
return "\(xcodePath + deviceSupportPath)"
let archivesPath = "Archives/"
return "\(xcodePath + archivesPath)"
}
func getIOSDeviceLogsPath() -> String {
let xcodePath = getXcodeDefaultPath()
let iOSDeviceLogsPath = "iOS Device Logs/"
return "\(xcodePath + iOSDeviceLogsPath)"
}
func getDocumentationCachePath() -> String {
let xcodePath = getXcodeDefaultPath()
let documentationCachePath = "DocumentationCache/"
return "\(xcodePath + documentationCachePath)"
}
func getSubDirectoriesForPath(path: String) -> [String] {
let fileManager = FileManager.default
Expand All @@ -57,37 +67,75 @@ struct DirectoryManager {

return subDirectories
}
func getDirectorySize(path: String, completion: @escaping () -> Void = { }) -> Int64 {
func getFileType(path: String) -> FileType? {
let fileManager = FileManager.default
var isDirectory: ObjCBool = false

if fileManager.fileExists(atPath: path, isDirectory: &isDirectory) {
if isDirectory.boolValue {
return .directory
} else {
return .file
}
}
return nil
}
func getSize(path: String, completion: @escaping () -> Void = { }) -> Int64 {
let fileManager = FileManager.default
var directorySize: Int64 = 0

let directories = fileManager.subpaths(atPath: path)
guard directories != nil else {
completion()
return 0
var normalizedPath: String
let fileType = getFileType(path: path)

switch fileType {
case .directory:
normalizedPath = normalizePathForDirectory(path: path)
case .file:
normalizedPath = normalizePathForFile(path: path)
case .none:
return 0
}

for directory in directories! {
if fileType == .file {
do {
let attributes = try fileManager.attributesOfItem(atPath: path + directory)
let attributes = try fileManager.attributesOfItem(atPath: normalizedPath)
directorySize += attributes[FileAttributeKey.size] as! Int64
} catch {
print(error.localizedDescription)
}
} else {
let directories = fileManager.subpaths(atPath: normalizedPath)

for directory in directories! {
do {
let newPath = normalizedPath + directory
let attributes = try fileManager.attributesOfItem(atPath: newPath)
directorySize += attributes[FileAttributeKey.size] as! Int64
} catch {
print(error.localizedDescription)
}
}
}
completion()

return directorySize
}
func normalizeDirectoryPath(directory: String) -> String {
var newDirectoryPath = directory
func normalizePathForDirectory(path: String) -> String {
var newPath = path

if !newPath.hasSuffix("/") {
newPath += "/"
}
return newPath
}
func normalizePathForFile(path: String) -> String {
var newPath = path

if !newDirectoryPath.hasSuffix("/") {
newDirectoryPath += "/"
if newPath.hasSuffix("/") {
newPath.removeLast()
}
return newDirectoryPath
return newPath
}
func normalizeDirectoryPathForDisplay(directory: String, forType type: DirectoryType) -> String {
func normalizePathForDisplay(directory: String, forType type: DirectoryType) -> String {
var result = directory
var prefix: String

Expand All @@ -98,6 +146,10 @@ struct DirectoryManager {
prefix = getDeviceSupportPath()
case .archives:
prefix = getArchivesPath()
case .iOSDeviceLogs:
prefix = getIOSDeviceLogsPath()
case .documentationCache:
prefix = getDocumentationCachePath()
}

if directory.contains(prefix) {
Expand All @@ -117,9 +169,13 @@ struct DirectoryManager {
directoryPath = getDeviceSupportPath()
case .archives:
directoryPath = getArchivesPath()
case .iOSDeviceLogs:
directoryPath = getIOSDeviceLogsPath()
case .documentationCache:
directoryPath = getDocumentationCachePath()
}

let directoryURL = URL(fileURLWithPath: normalizeDirectoryPath(directory: directoryPath))
let directoryURL = URL(fileURLWithPath: normalizePathForDirectory(path: directoryPath))

do {
try fileManager.removeItem(at: directoryURL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ public enum DirectoryType {
case derivedData
case deviceSupport
case archives
case iOSDeviceLogs
case documentationCache
}
14 changes: 14 additions & 0 deletions XcodeCleaner/Enums/FileType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// FileType.swift
// XcodeCleaner
//
// Created by Kirill Pustovalov on 12.07.2020.
// Copyright © 2020 Kirill Pustovalov. All rights reserved.
//

import Foundation

enum FileType {
case file
case directory
}
2 changes: 1 addition & 1 deletion XcodeCleaner/Helpers/BytesToStringFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

struct BytesToStringFormatter {
static func format(size: Int64, allowedUnits: ByteCountFormatter.Units = [.useGB, .useMB]) -> String {
static func format(size: Int64, allowedUnits: ByteCountFormatter.Units = [.useKB, .useMB, .useGB]) -> String {
let byteCountFormatter = ByteCountFormatter()
byteCountFormatter.allowedUnits = allowedUnits

Expand Down
2 changes: 1 addition & 1 deletion XcodeCleaner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
Expand Down
10 changes: 3 additions & 7 deletions XcodeCleaner/PieChart/Views/PieChartSliceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct PieChartSliceView: View {
var rect: CGRect

let slice: PieChartSliceModel
let sliceSeparatorColor: Color

@State var isVisible: Bool = false

Expand All @@ -24,7 +23,6 @@ struct PieChartSliceView: View {

return Group { sliceShape
.fill()
.overlay(sliceShape.stroke(sliceSeparatorColor, lineWidth: 2))
.foregroundColor(slice.color)
.scaleEffect(isVisible ? 1: 0)
.animation(Animation.easeIn)
Expand All @@ -34,7 +32,7 @@ struct PieChartSliceView: View {
if self.slice.subSlices.count > 0 {
GeometryReader { geometryReader in
ForEach(0 ..< self.slice.subSlices.count, id: \.self) { subSliceIndex in
PieChartSubSliceView(rect: geometryReader.frame(in: .local), subSlice: self.slice.subSlices[subSliceIndex], sliceSeparatorColor: self.sliceSeparatorColor)
PieChartSubSliceView(rect: geometryReader.frame(in: .local), subSlice: self.slice.subSlices[subSliceIndex])
.padding(0 - min(geometryReader.size.width, geometryReader.size.height) / 2)
}
}
Expand All @@ -45,11 +43,9 @@ struct PieChartSliceView: View {

struct PieSliceView_Previews: PreviewProvider {
static var previews: some View {
let pieSlice = PieChartSliceModel(value: .zero, color: .orange, startDegree: 50, endDegree: 130)
let sliceSeparatorColor = Color.black

let pieSlice = PieChartSliceModel(value: .zero, color: .orange, startDegree: 50, endDegree: 130)
return GeometryReader { geometryReader in
PieChartSliceView(rect: geometryReader.frame(in: .local), slice: pieSlice, sliceSeparatorColor: sliceSeparatorColor)
PieChartSliceView(rect: geometryReader.frame(in: .local), slice: pieSlice)
}
.frame(width: 150, height: 150)
}
Expand Down
6 changes: 1 addition & 5 deletions XcodeCleaner/PieChart/Views/PieChartSubSliceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ struct PieChartSubSliceView: View {
var rect: CGRect

let subSlice: PieChartSubSliceModel
let sliceSeparatorColor: Color

@State var isVisible: Bool = false

var body: some View {
Expand All @@ -24,7 +22,6 @@ struct PieChartSubSliceView: View {

return Group { sliceShape
.fill()
.overlay(sliceShape.stroke(sliceSeparatorColor, lineWidth: 2))
.foregroundColor(subSlice.color)
.scaleEffect(isVisible ? 1: 0)
.animation(Animation.easeIn)
Expand All @@ -38,10 +35,9 @@ struct PieChartSubSliceView: View {
struct PieChartSubSliceView_Previews: PreviewProvider {
static var previews: some View {
let pieSlice = PieChartSubSliceModel(value: .zero, color: .orange, startDegree: 50, endDegree: 130)
let sliceSeparatorColor = Color.black

return GeometryReader { geometryReader in
PieChartSubSliceView(rect: geometryReader.frame(in: .local), subSlice: pieSlice, sliceSeparatorColor: sliceSeparatorColor)
PieChartSubSliceView(rect: geometryReader.frame(in: .local), subSlice: pieSlice)
}
.frame(width: 150, height: 150)
}
Expand Down
Loading