├── AppExplorer-Bridging-Header.h ├── AppExplorer.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── jcardasi.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── jon.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── jcardasi.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── AppExplorer.xcscheme │ │ └── xcschememanagement.plist │ └── jon.xcuserdatad │ └── xcschemes │ ├── AppExplorer.xcscheme │ └── xcschememanagement.plist ├── AppExplorer ├── AppDelegate.swift ├── AppExplorer-Bridging-Header.h ├── AppTableViewCell.swift ├── AppTableViewCell.xib ├── AppsTableViewController.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ └── Icon-App-76x76@2x.png │ ├── Contents.json │ └── iconmonstr-rocket.imageset │ │ ├── Contents.json │ │ └── iconmonstr-rocket-11-240 (3).png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── DirectoryReader.h ├── DirectoryReader.m ├── Info.plist └── TagLabel.swift ├── Embeddable ├── EmbeddableSystemApplicationManager.swift └── Invocator.m ├── LICENSE ├── Private Headers ├── LSApplicationProxy.h ├── LSApplicationWorkspace.h ├── LSBundleProxy.h ├── LSResourceProxy.h └── UIImage-ApplicationIcons.h ├── README.md ├── SystemApplication.swift └── SystemApplicationManager.swift /AppExplorer-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "LSApplicationProxy.h" 6 | #import "LSApplicationWorkspace.h" 7 | #import "UIImage-ApplicationIcons.h" 8 | 9 | #import "DirectoryReader.h" -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3506132A1D36DF15003AAFC2 /* DirectoryReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 350613291D36DF15003AAFC2 /* DirectoryReader.m */; }; 11 | 3510B5131D35448600BAC743 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3510B5121D35448600BAC743 /* MobileCoreServices.framework */; }; 12 | 3525A57D1D3677EB003606B1 /* AppTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3525A57C1D3677EB003606B1 /* AppTableViewCell.xib */; }; 13 | 3525A5831D367AE1003606B1 /* AppsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3525A5821D367AE1003606B1 /* AppsTableViewController.swift */; }; 14 | 3525A5851D368ABC003606B1 /* TagLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3525A5841D368ABC003606B1 /* TagLabel.swift */; }; 15 | 3525A5861D36AAC6003606B1 /* AppTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3525A5801D367833003606B1 /* AppTableViewCell.swift */; }; 16 | 353EC1C11D3FB05A003B1DDF /* SystemApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353EC1BF1D3FB05A003B1DDF /* SystemApplication.swift */; }; 17 | 353EC1C21D3FB05A003B1DDF /* SystemApplicationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353EC1C01D3FB05A003B1DDF /* SystemApplicationManager.swift */; }; 18 | 35557AEC1D3405630033C3C6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35557AEB1D3405630033C3C6 /* AppDelegate.swift */; }; 19 | 35557AF11D3405630033C3C6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35557AEF1D3405630033C3C6 /* Main.storyboard */; }; 20 | 35557AF31D3405630033C3C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35557AF21D3405630033C3C6 /* Assets.xcassets */; }; 21 | 35557AF61D3405630033C3C6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35557AF41D3405630033C3C6 /* LaunchScreen.storyboard */; }; 22 | 35AD7BF01D5A5F2900335114 /* Embeddable in Resources */ = {isa = PBXBuildFile; fileRef = 35AD7BEF1D5A5F2900335114 /* Embeddable */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 350613281D36DF15003AAFC2 /* DirectoryReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryReader.h; sourceTree = ""; }; 27 | 350613291D36DF15003AAFC2 /* DirectoryReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryReader.m; sourceTree = ""; }; 28 | 3506132C1D397BB0003AAFC2 /* LSApplicationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LSApplicationProxy.h; path = "Private Headers/LSApplicationProxy.h"; sourceTree = ""; }; 29 | 3506132D1D397BB0003AAFC2 /* LSApplicationWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LSApplicationWorkspace.h; path = "Private Headers/LSApplicationWorkspace.h"; sourceTree = ""; }; 30 | 3506132E1D397BB0003AAFC2 /* LSBundleProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LSBundleProxy.h; path = "Private Headers/LSBundleProxy.h"; sourceTree = ""; }; 31 | 3506132F1D397BB0003AAFC2 /* LSResourceProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LSResourceProxy.h; path = "Private Headers/LSResourceProxy.h"; sourceTree = ""; }; 32 | 350613301D397BB0003AAFC2 /* UIImage-ApplicationIcons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage-ApplicationIcons.h"; path = "Private Headers/UIImage-ApplicationIcons.h"; sourceTree = ""; }; 33 | 3510B5121D35448600BAC743 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 34 | 3525A57C1D3677EB003606B1 /* AppTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AppTableViewCell.xib; sourceTree = ""; }; 35 | 3525A5801D367833003606B1 /* AppTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppTableViewCell.swift; sourceTree = ""; }; 36 | 3525A5821D367AE1003606B1 /* AppsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppsTableViewController.swift; sourceTree = ""; }; 37 | 3525A5841D368ABC003606B1 /* TagLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TagLabel.swift; sourceTree = ""; }; 38 | 353EC1BF1D3FB05A003B1DDF /* SystemApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemApplication.swift; sourceTree = SOURCE_ROOT; }; 39 | 353EC1C01D3FB05A003B1DDF /* SystemApplicationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemApplicationManager.swift; sourceTree = SOURCE_ROOT; }; 40 | 353EC1C41D3FB269003B1DDF /* AppExplorer-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AppExplorer-Bridging-Header.h"; sourceTree = ""; }; 41 | 35557AE81D3405630033C3C6 /* AppExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 35557AEB1D3405630033C3C6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 43 | 35557AF01D3405630033C3C6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 35557AF21D3405630033C3C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | 35557AF51D3405630033C3C6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46 | 35557AF71D3405630033C3C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 35AD7BEF1D5A5F2900335114 /* Embeddable */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Embeddable; sourceTree = SOURCE_ROOT; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 35557AE51D3405630033C3C6 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 3510B5131D35448600BAC743 /* MobileCoreServices.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | 350613271D36DA6A003AAFC2 /* Controllers */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 3525A5821D367AE1003606B1 /* AppsTableViewController.swift */, 66 | ); 67 | name = Controllers; 68 | sourceTree = ""; 69 | }; 70 | 3525A57E1D3677F0003606B1 /* Views */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 35557AF41D3405630033C3C6 /* LaunchScreen.storyboard */, 74 | 35557AEF1D3405630033C3C6 /* Main.storyboard */, 75 | 3525A57C1D3677EB003606B1 /* AppTableViewCell.xib */, 76 | 3525A5801D367833003606B1 /* AppTableViewCell.swift */, 77 | 3525A5841D368ABC003606B1 /* TagLabel.swift */, 78 | ); 79 | name = Views; 80 | sourceTree = ""; 81 | }; 82 | 3525A57F1D367808003606B1 /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 3510B5121D35448600BAC743 /* MobileCoreServices.framework */, 86 | ); 87 | name = Frameworks; 88 | sourceTree = ""; 89 | }; 90 | 35557ADF1D3405630033C3C6 = { 91 | isa = PBXGroup; 92 | children = ( 93 | 35557AEA1D3405630033C3C6 /* AppExplorer */, 94 | 3525A57F1D367808003606B1 /* Frameworks */, 95 | 35557AE91D3405630033C3C6 /* Products */, 96 | ); 97 | sourceTree = ""; 98 | }; 99 | 35557AE91D3405630033C3C6 /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 35557AE81D3405630033C3C6 /* AppExplorer.app */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | 35557AEA1D3405630033C3C6 /* AppExplorer */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 353EC1BF1D3FB05A003B1DDF /* SystemApplication.swift */, 111 | 353EC1C01D3FB05A003B1DDF /* SystemApplicationManager.swift */, 112 | 35557AEB1D3405630033C3C6 /* AppDelegate.swift */, 113 | 35557B1D1D3407DA0033C3C6 /* Private Headers */, 114 | 350613271D36DA6A003AAFC2 /* Controllers */, 115 | 3525A57E1D3677F0003606B1 /* Views */, 116 | 35AD7BEF1D5A5F2900335114 /* Embeddable */, 117 | 35557AF21D3405630033C3C6 /* Assets.xcassets */, 118 | 35557AF71D3405630033C3C6 /* Info.plist */, 119 | 350613281D36DF15003AAFC2 /* DirectoryReader.h */, 120 | 350613291D36DF15003AAFC2 /* DirectoryReader.m */, 121 | 353EC1C41D3FB269003B1DDF /* AppExplorer-Bridging-Header.h */, 122 | ); 123 | path = AppExplorer; 124 | sourceTree = ""; 125 | }; 126 | 35557B1D1D3407DA0033C3C6 /* Private Headers */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 3506132C1D397BB0003AAFC2 /* LSApplicationProxy.h */, 130 | 3506132D1D397BB0003AAFC2 /* LSApplicationWorkspace.h */, 131 | 3506132E1D397BB0003AAFC2 /* LSBundleProxy.h */, 132 | 3506132F1D397BB0003AAFC2 /* LSResourceProxy.h */, 133 | 350613301D397BB0003AAFC2 /* UIImage-ApplicationIcons.h */, 134 | ); 135 | name = "Private Headers"; 136 | path = ..; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 35557AE71D3405630033C3C6 /* AppExplorer */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 35557B101D3405630033C3C6 /* Build configuration list for PBXNativeTarget "AppExplorer" */; 145 | buildPhases = ( 146 | 35557AE41D3405630033C3C6 /* Sources */, 147 | 35557AE51D3405630033C3C6 /* Frameworks */, 148 | 35557AE61D3405630033C3C6 /* Resources */, 149 | ); 150 | buildRules = ( 151 | ); 152 | dependencies = ( 153 | ); 154 | name = AppExplorer; 155 | productName = AppExplorer; 156 | productReference = 35557AE81D3405630033C3C6 /* AppExplorer.app */; 157 | productType = "com.apple.product-type.application"; 158 | }; 159 | /* End PBXNativeTarget section */ 160 | 161 | /* Begin PBXProject section */ 162 | 35557AE01D3405630033C3C6 /* Project object */ = { 163 | isa = PBXProject; 164 | attributes = { 165 | LastSwiftUpdateCheck = 0730; 166 | LastUpgradeCheck = 0820; 167 | ORGANIZATIONNAME = "Cardasis, Jonathan (J.)"; 168 | TargetAttributes = { 169 | 35557AE71D3405630033C3C6 = { 170 | CreatedOnToolsVersion = 7.3; 171 | DevelopmentTeam = 43DKZUY8C6; 172 | LastSwiftMigration = 0820; 173 | }; 174 | }; 175 | }; 176 | buildConfigurationList = 35557AE31D3405630033C3C6 /* Build configuration list for PBXProject "AppExplorer" */; 177 | compatibilityVersion = "Xcode 3.2"; 178 | developmentRegion = English; 179 | hasScannedForEncodings = 0; 180 | knownRegions = ( 181 | en, 182 | Base, 183 | ); 184 | mainGroup = 35557ADF1D3405630033C3C6; 185 | productRefGroup = 35557AE91D3405630033C3C6 /* Products */; 186 | projectDirPath = ""; 187 | projectRoot = ""; 188 | targets = ( 189 | 35557AE71D3405630033C3C6 /* AppExplorer */, 190 | ); 191 | }; 192 | /* End PBXProject section */ 193 | 194 | /* Begin PBXResourcesBuildPhase section */ 195 | 35557AE61D3405630033C3C6 /* Resources */ = { 196 | isa = PBXResourcesBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | 35557AF61D3405630033C3C6 /* LaunchScreen.storyboard in Resources */, 200 | 35AD7BF01D5A5F2900335114 /* Embeddable in Resources */, 201 | 35557AF31D3405630033C3C6 /* Assets.xcassets in Resources */, 202 | 3525A57D1D3677EB003606B1 /* AppTableViewCell.xib in Resources */, 203 | 35557AF11D3405630033C3C6 /* Main.storyboard in Resources */, 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXResourcesBuildPhase section */ 208 | 209 | /* Begin PBXSourcesBuildPhase section */ 210 | 35557AE41D3405630033C3C6 /* Sources */ = { 211 | isa = PBXSourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | 3525A5861D36AAC6003606B1 /* AppTableViewCell.swift in Sources */, 215 | 35557AEC1D3405630033C3C6 /* AppDelegate.swift in Sources */, 216 | 3506132A1D36DF15003AAFC2 /* DirectoryReader.m in Sources */, 217 | 3525A5831D367AE1003606B1 /* AppsTableViewController.swift in Sources */, 218 | 3525A5851D368ABC003606B1 /* TagLabel.swift in Sources */, 219 | 353EC1C21D3FB05A003B1DDF /* SystemApplicationManager.swift in Sources */, 220 | 353EC1C11D3FB05A003B1DDF /* SystemApplication.swift in Sources */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXSourcesBuildPhase section */ 225 | 226 | /* Begin PBXVariantGroup section */ 227 | 35557AEF1D3405630033C3C6 /* Main.storyboard */ = { 228 | isa = PBXVariantGroup; 229 | children = ( 230 | 35557AF01D3405630033C3C6 /* Base */, 231 | ); 232 | name = Main.storyboard; 233 | sourceTree = ""; 234 | }; 235 | 35557AF41D3405630033C3C6 /* LaunchScreen.storyboard */ = { 236 | isa = PBXVariantGroup; 237 | children = ( 238 | 35557AF51D3405630033C3C6 /* Base */, 239 | ); 240 | name = LaunchScreen.storyboard; 241 | sourceTree = ""; 242 | }; 243 | /* End PBXVariantGroup section */ 244 | 245 | /* Begin XCBuildConfiguration section */ 246 | 35557B0E1D3405630033C3C6 /* Debug */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | CLANG_ANALYZER_NONNULL = YES; 251 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 252 | CLANG_CXX_LIBRARY = "libc++"; 253 | CLANG_ENABLE_MODULES = YES; 254 | CLANG_ENABLE_OBJC_ARC = YES; 255 | CLANG_WARN_BOOL_CONVERSION = YES; 256 | CLANG_WARN_CONSTANT_CONVERSION = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNREACHABLE_CODE = YES; 265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 266 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 267 | COPY_PHASE_STRIP = NO; 268 | DEBUG_INFORMATION_FORMAT = dwarf; 269 | ENABLE_STRICT_OBJC_MSGSEND = YES; 270 | ENABLE_TESTABILITY = YES; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_NO_COMMON_BLOCKS = YES; 274 | GCC_OPTIMIZATION_LEVEL = 0; 275 | GCC_PREPROCESSOR_DEFINITIONS = ( 276 | "DEBUG=1", 277 | "$(inherited)", 278 | ); 279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 281 | GCC_WARN_UNDECLARED_SELECTOR = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 283 | GCC_WARN_UNUSED_FUNCTION = YES; 284 | GCC_WARN_UNUSED_VARIABLE = YES; 285 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 286 | MTL_ENABLE_DEBUG_INFO = YES; 287 | ONLY_ACTIVE_ARCH = YES; 288 | SDKROOT = iphoneos; 289 | SWIFT_OBJC_BRIDGING_HEADER = "AppExplorer-Bridging-Header.h"; 290 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 291 | }; 292 | name = Debug; 293 | }; 294 | 35557B0F1D3405630033C3C6 /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_ANALYZER_NONNULL = YES; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INFINITE_RECURSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 311 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 312 | CLANG_WARN_UNREACHABLE_CODE = YES; 313 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 314 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 315 | COPY_PHASE_STRIP = NO; 316 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 317 | ENABLE_NS_ASSERTIONS = NO; 318 | ENABLE_STRICT_OBJC_MSGSEND = YES; 319 | GCC_C_LANGUAGE_STANDARD = gnu99; 320 | GCC_NO_COMMON_BLOCKS = YES; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 328 | MTL_ENABLE_DEBUG_INFO = NO; 329 | SDKROOT = iphoneos; 330 | SWIFT_OBJC_BRIDGING_HEADER = "AppExplorer-Bridging-Header.h"; 331 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 332 | VALIDATE_PRODUCT = YES; 333 | }; 334 | name = Release; 335 | }; 336 | 35557B111D3405630033C3C6 /* Debug */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 340 | CLANG_ENABLE_MODULES = YES; 341 | CODE_SIGN_IDENTITY = "iPhone Developer"; 342 | ENABLE_BITCODE = NO; 343 | ENABLE_TESTABILITY = NO; 344 | INFOPLIST_FILE = AppExplorer/Info.plist; 345 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 346 | ONLY_ACTIVE_ARCH = YES; 347 | OTHER_LDFLAGS = ""; 348 | PRODUCT_BUNDLE_IDENTIFIER = com.jonathancardasis.AppExplorer; 349 | PRODUCT_NAME = "$(TARGET_NAME)"; 350 | SWIFT_OBJC_BRIDGING_HEADER = "AppExplorer-Bridging-Header.h"; 351 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 352 | SWIFT_VERSION = 3.0; 353 | }; 354 | name = Debug; 355 | }; 356 | 35557B121D3405630033C3C6 /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 360 | CLANG_ENABLE_MODULES = YES; 361 | CODE_SIGN_IDENTITY = "iPhone Developer"; 362 | ENABLE_BITCODE = NO; 363 | ENABLE_TESTABILITY = NO; 364 | INFOPLIST_FILE = AppExplorer/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 366 | OTHER_LDFLAGS = ""; 367 | PRODUCT_BUNDLE_IDENTIFIER = com.jonathancardasis.AppExplorer; 368 | PRODUCT_NAME = "$(TARGET_NAME)"; 369 | SWIFT_OBJC_BRIDGING_HEADER = "AppExplorer-Bridging-Header.h"; 370 | SWIFT_VERSION = 3.0; 371 | }; 372 | name = Release; 373 | }; 374 | /* End XCBuildConfiguration section */ 375 | 376 | /* Begin XCConfigurationList section */ 377 | 35557AE31D3405630033C3C6 /* Build configuration list for PBXProject "AppExplorer" */ = { 378 | isa = XCConfigurationList; 379 | buildConfigurations = ( 380 | 35557B0E1D3405630033C3C6 /* Debug */, 381 | 35557B0F1D3405630033C3C6 /* Release */, 382 | ); 383 | defaultConfigurationIsVisible = 0; 384 | defaultConfigurationName = Release; 385 | }; 386 | 35557B101D3405630033C3C6 /* Build configuration list for PBXNativeTarget "AppExplorer" */ = { 387 | isa = XCConfigurationList; 388 | buildConfigurations = ( 389 | 35557B111D3405630033C3C6 /* Debug */, 390 | 35557B121D3405630033C3C6 /* Release */, 391 | ); 392 | defaultConfigurationIsVisible = 0; 393 | defaultConfigurationName = Release; 394 | }; 395 | /* End XCConfigurationList section */ 396 | }; 397 | rootObject = 35557AE01D3405630033C3C6 /* Project object */; 398 | } 399 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/project.xcworkspace/xcuserdata/jcardasi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer.xcodeproj/project.xcworkspace/xcuserdata/jcardasi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/project.xcworkspace/xcuserdata/jon.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer.xcodeproj/project.xcworkspace/xcuserdata/jon.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/xcuserdata/jcardasi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/xcuserdata/jcardasi.xcuserdatad/xcschemes/AppExplorer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/xcuserdata/jcardasi.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppExplorer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 35557AE71D3405630033C3C6 16 | 17 | primary 18 | 19 | 20 | 35557AFB1D3405630033C3C6 21 | 22 | primary 23 | 24 | 25 | 35557B061D3405630033C3C6 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/xcuserdata/jon.xcuserdatad/xcschemes/AppExplorer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /AppExplorer.xcodeproj/xcuserdata/jon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppExplorer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 35557AE71D3405630033C3C6 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppExplorer/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/11/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | UIApplication.shared.statusBarStyle = .lightContent 18 | 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /AppExplorer/AppExplorer-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "LSApplicationProxy.h" 6 | #import "LSApplicationWorkspace.h" 7 | #import "UIImage-ApplicationIcons.h" 8 | 9 | #import "DirectoryReader.h" -------------------------------------------------------------------------------- /AppExplorer/AppTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppTableViewCell.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AppTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var appIconView: UIImageView! 14 | @IBOutlet weak var title: UILabel! 15 | @IBOutlet weak var typeTag: TagLabel! 16 | @IBOutlet weak var launchButton: UIButton! 17 | weak var application: SystemApplication? 18 | 19 | var separator = CAShapeLayer() 20 | 21 | override func awakeFromNib() { 22 | super.awakeFromNib() 23 | separator.fillColor = UIColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 1).cgColor 24 | self.layer.addSublayer(separator) 25 | } 26 | 27 | 28 | override func layoutSubviews() { 29 | let separatorFrame = UIEdgeInsetsInsetRect(CGRect(x: 0, y: bounds.height - 2.0/UIScreen.main.scale, width: bounds.width, height: 2.0/UIScreen.main.scale), self.separatorInset) 30 | 31 | separator.path = UIBezierPath(rect: separatorFrame).cgPath 32 | } 33 | 34 | override func setSelected(_ selected: Bool, animated: Bool) { 35 | super.setSelected(selected, animated: animated) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /AppExplorer/AppTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | 46 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /AppExplorer/AppsTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppsTableViewController.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AppsTableViewController: UITableViewController { 12 | 13 | 14 | var applications: [SystemApplication] = [] 15 | 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | self.navigationController?.navigationBar.barTintColor = UIColor(red: 0, green: 188/255.0, blue: 212/255.0, alpha: 1) 21 | self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white, NSFontAttributeName : UIFont(name: "Helvetica-Bold", size: 18)!] 22 | 23 | tableView.register(UINib(nibName: "AppTableViewCell", bundle: nil), forCellReuseIdentifier: "AppCell") 24 | tableView.separatorStyle = .none 25 | 26 | 27 | // Uncomment the following line to preserve selection between presentations 28 | // self.clearsSelectionOnViewWillAppear = false 29 | 30 | 31 | 32 | // Get all apps installed on the device 33 | self.applications = SystemApplicationManager.sharedManager.allInstalledApplications() 34 | 35 | tableView.reloadData() 36 | 37 | 38 | 39 | 40 | } 41 | 42 | override func didReceiveMemoryWarning() { 43 | super.didReceiveMemoryWarning() 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | 48 | // MARK: - Table view data source 49 | override func numberOfSections(in tableView: UITableView) -> Int { 50 | return 1 51 | } 52 | 53 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 54 | return applications.count 55 | } 56 | 57 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 58 | return 90 59 | } 60 | 61 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 62 | let cell = tableView.dequeueReusableCell(withIdentifier: "AppCell", for: indexPath) as! AppTableViewCell 63 | 64 | let application = applications[indexPath.row] 65 | cell.application = application //associate the app to the cell 66 | 67 | cell.appIconView.image = application.icon 68 | cell.title.text = application.name ?? "???" //use question marks if appname doesnt exist 69 | 70 | 71 | if application.type == .system { 72 | cell.typeTag.backgroundColor = cell.typeTag.primaryColor 73 | cell.typeTag.text = "System" 74 | } else { 75 | cell.typeTag.backgroundColor = cell.typeTag.secondaryTagColor 76 | cell.typeTag.text = "User" 77 | } 78 | 79 | cell.launchButton.tag = indexPath.row 80 | cell.launchButton.addTarget(self, action: #selector(launchAppButtonPressed), for: .touchUpInside) 81 | 82 | return cell 83 | } 84 | 85 | //MARK: temporary use to print contents of app from /Applications folder 86 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 87 | guard let cell = tableView.cellForRow(at: indexPath) as? AppTableViewCell else{ 88 | return 89 | } 90 | 91 | let constructedURL = "/Applications/\(cell.application!.executableName!).app" 92 | DirectoryReader.printContents(constructedURL) 93 | } 94 | 95 | 96 | //MARK: - Other Functions 97 | func launchAppButtonPressed(_ sender: UIButton){ 98 | let tappedCell = tableView.cellForRow(at: IndexPath(row: sender.tag, section: 0)) as! AppTableViewCell 99 | 100 | if let application = tappedCell.application { 101 | SystemApplicationManager.sharedManager.openApplication(application) 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "Icon-App-29x29@1x.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "Icon-App-29x29@2x.png", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "size" : "29x29", 27 | "idiom" : "iphone", 28 | "filename" : "Icon-App-29x29@3x.png", 29 | "scale" : "3x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "Icon-App-40x40@2x.png", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "size" : "40x40", 39 | "idiom" : "iphone", 40 | "filename" : "Icon-App-40x40@3x.png", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "Icon-App-60x60@2x.png", 47 | "scale" : "2x" 48 | }, 49 | { 50 | "size" : "60x60", 51 | "idiom" : "iphone", 52 | "filename" : "Icon-App-60x60@3x.png", 53 | "scale" : "3x" 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "size" : "20x20", 58 | "scale" : "1x" 59 | }, 60 | { 61 | "idiom" : "ipad", 62 | "size" : "20x20", 63 | "scale" : "2x" 64 | }, 65 | { 66 | "size" : "29x29", 67 | "idiom" : "ipad", 68 | "filename" : "Icon-App-29x29@1x.png", 69 | "scale" : "1x" 70 | }, 71 | { 72 | "size" : "29x29", 73 | "idiom" : "ipad", 74 | "filename" : "Icon-App-29x29@2x.png", 75 | "scale" : "2x" 76 | }, 77 | { 78 | "size" : "40x40", 79 | "idiom" : "ipad", 80 | "filename" : "Icon-App-40x40@1x.png", 81 | "scale" : "1x" 82 | }, 83 | { 84 | "size" : "40x40", 85 | "idiom" : "ipad", 86 | "filename" : "Icon-App-40x40@2x-1.png", 87 | "scale" : "2x" 88 | }, 89 | { 90 | "size" : "76x76", 91 | "idiom" : "ipad", 92 | "filename" : "Icon-App-76x76@1x.png", 93 | "scale" : "1x" 94 | }, 95 | { 96 | "size" : "76x76", 97 | "idiom" : "ipad", 98 | "filename" : "Icon-App-76x76@2x.png", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "idiom" : "ipad", 103 | "size" : "83.5x83.5", 104 | "scale" : "2x" 105 | } 106 | ], 107 | "info" : { 108 | "version" : 1, 109 | "author" : "xcode" 110 | } 111 | } -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/iconmonstr-rocket.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "iconmonstr-rocket-11-240 (3).png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /AppExplorer/Assets.xcassets/iconmonstr-rocket.imageset/iconmonstr-rocket-11-240 (3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joncardasis/AppExplorer/3174d50cf8b4a1bef05d46f55d976458280487d4/AppExplorer/Assets.xcassets/iconmonstr-rocket.imageset/iconmonstr-rocket-11-240 (3).png -------------------------------------------------------------------------------- /AppExplorer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AppExplorer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /AppExplorer/DirectoryReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // DirectoryReader.h 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DirectoryReader : NSObject 12 | 13 | + (void) printContents: (const char*) path; 14 | + (BOOL) is_file: (const char*) path; 15 | + (int64_t) size_of_file: (const char*) path; 16 | + (BOOL) is_dir: (const char*) path; 17 | 18 | 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /AppExplorer/DirectoryReader.m: -------------------------------------------------------------------------------- 1 | // 2 | // DirectoryReader.m 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | #import "DirectoryReader.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | @implementation DirectoryReader 16 | 17 | 18 | + (void) printContents: (const char*) path{ 19 | DIR *d; 20 | struct dirent *dir; 21 | d = opendir(path); 22 | if (d){ 23 | while((dir = readdir(d)) != NULL){ 24 | NSLog(@"%s", dir->d_name); 25 | } 26 | } 27 | } 28 | 29 | + (BOOL) is_file: (const char*) path { 30 | struct stat path_stat; 31 | stat(path, &path_stat); 32 | return S_ISREG(path_stat.st_mode); 33 | } 34 | 35 | + (int64_t) size_of_file: (const char*) path{ 36 | struct stat path_stat; 37 | if (stat(path, &path_stat) != 0) 38 | return false; 39 | return path_stat.st_size; 40 | } 41 | 42 | + (BOOL) is_dir: (const char*) path { 43 | struct stat path_stat; 44 | if (stat(path, &path_stat) != 0) 45 | return false; 46 | return S_ISDIR(path_stat.st_mode); 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /AppExplorer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIViewControllerBasedStatusBarAppearance 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /AppExplorer/TagLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagLabel.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @IBDesignable class TagLabel: UILabel { 12 | 13 | @IBInspectable var primaryColor: UIColor = UIColor.lightGray{ 14 | didSet{ 15 | self.layer.backgroundColor = primaryColor.cgColor 16 | } 17 | } 18 | @IBInspectable var secondaryTagColor: UIColor = UIColor.darkGray 19 | 20 | override init(frame: CGRect) { 21 | super.init(frame: frame) 22 | self.commonInit() 23 | } 24 | 25 | required init?(coder aDecoder: NSCoder) { 26 | super.init(coder: aDecoder) 27 | self.commonInit() 28 | } 29 | 30 | fileprivate func commonInit(){ 31 | self.layer.masksToBounds = true 32 | self.layer.backgroundColor = primaryColor.cgColor 33 | } 34 | 35 | override func layoutSubviews() { 36 | self.layer.cornerRadius = self.bounds.height/2 37 | self.font = UIFont(descriptor: self.font.fontDescriptor, size: self.bounds.height/2) 38 | self.textAlignment = .center 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Embeddable/EmbeddableSystemApplicationManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmbeddableSystemApplicationManager.swift 3 | // AppExplorer 4 | // 5 | // Created by Jonathan Cardasis on 8/8/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | 12 | 13 | //Reverse-Engineered interface for LSApplicationWorkspace 14 | @objc private protocol LSApplicationWorkspace_Interface{ 15 | @objc func defaultWorkspace()-> LSApplicationWorkspace_Interface 16 | @objc func allInstalledApplications() -> [NSObject] 17 | @objc func openApplicationWithBundleID(bundleID: AnyObject!) -> Bool 18 | } 19 | @objc private protocol UIImage_Private_Interface{ 20 | @objc func _applicationIconImageForBundleIdentifier(bundleID: AnyObject!, format: AnyObject!, scale: AnyObject!) 21 | } 22 | 23 | //Reverse-Engineered calls and variables 24 | private struct ReversedCall{ 25 | struct LSApplicationWorkspace { 26 | struct Selector{ 27 | static let workspace = #selector(LSApplicationWorkspace_Interface.defaultWorkspace) 28 | static let getAllInstalledApplications = #selector(LSApplicationWorkspace_Interface.allInstalledApplications) 29 | static let openApplicationWithBundleID = #selector(LSApplicationWorkspace_Interface.openApplicationWithBundleID(_:)) 30 | } 31 | } 32 | 33 | struct LSApplicationProxy { 34 | static let bundleIdentifier = "bundleIdentifier" 35 | static let localizedName = "localizedName" 36 | static let shortVersionString = "shortVersionString" 37 | static let bundleExecutable = "bundleExecutable" 38 | static let applicationType = "applicationType" 39 | static let signerIdentity = "signerIdentity" 40 | static let dataContainerURL = "dataContainerURL" 41 | static let UIBackgroundModes = "UIBackgroundModes" 42 | } 43 | 44 | struct UIImage{ 45 | static let applicationIconImageForBundleIdentifier = #selector(UIImage_Private_Interface._applicationIconImageForBundleIdentifier(_:format:scale:)) 46 | 47 | } 48 | } 49 | 50 | 51 | class EmbeddableSystemApplicationManager: NSObject { 52 | static let sharedManager = EmbeddableSystemApplicationManager() 53 | private var workspace: NSObject? //LSApplicationWorkspace 54 | 55 | private let LSApplicationWorkspace_class: AnyClass! = NSClassFromString("LSApplicationWorkspace") 56 | 57 | override init(){ 58 | //Setup workspace 59 | if let myClass = LSApplicationWorkspace_class as? NSObjectProtocol { 60 | if myClass.respondsToSelector(ReversedCall.LSApplicationWorkspace.Selector.workspace) { 61 | self.workspace = myClass.performSelector(ReversedCall.LSApplicationWorkspace.Selector.workspace).takeRetainedValue() as? NSObject 62 | } 63 | } 64 | } 65 | 66 | 67 | func allInstalledApplications() -> [SystemApplication]{ 68 | guard let workspace = workspace else{ 69 | return [] 70 | } 71 | guard workspace.respondsToSelector(ReversedCall.LSApplicationWorkspace.Selector.getAllInstalledApplications) == true else{ 72 | return [] 73 | } 74 | var applications = [SystemApplication]() 75 | 76 | //Take an Unretained value so ARC doesn't release the workspace's installed apps array 77 | if let installedApplicationProxies = workspace.performSelector(ReversedCall.LSApplicationWorkspace.Selector.getAllInstalledApplications).takeUnretainedValue() as? NSArray{ 78 | 79 | for installedApp in installedApplicationProxies{ 80 | guard let bundleID = installedApp.valueForKey(ReversedCall.LSApplicationProxy.bundleIdentifier) as? String else{ 81 | return applications 82 | } 83 | 84 | let appIcon = self.applicationIconImageForBundleIdentifier(bundleID) 85 | 86 | let app = SystemApplication() 87 | app.map(bundleID: bundleID, 88 | name: installedApp.valueForKey(ReversedCall.LSApplicationProxy.localizedName) as? String, 89 | version: installedApp.valueForKey(ReversedCall.LSApplicationProxy.shortVersionString) as? String, 90 | executableName: installedApp.valueForKey(ReversedCall.LSApplicationProxy.bundleExecutable) as? String, 91 | type: installedApp.valueForKey(ReversedCall.LSApplicationProxy.applicationType) as? String, 92 | signerIdentity: installedApp.valueForKey(ReversedCall.LSApplicationProxy.signerIdentity) as? String, 93 | applicationPath: installedApp.valueForKey(ReversedCall.LSApplicationProxy.dataContainerURL) as? NSURL, 94 | backgroundModes: installedApp.valueForKey(ReversedCall.LSApplicationProxy.UIBackgroundModes) as? [String], 95 | icon: appIcon 96 | ) 97 | applications.append(app) 98 | } 99 | } 100 | return applications 101 | } 102 | 103 | @discardableResult func openApplication(app: SystemApplication) -> Bool { 104 | if let bundleID = app.bundleID{ 105 | return self.openApplication(bundleID: bundleID) 106 | } 107 | return false 108 | } 109 | 110 | @discardableResult func openApplication(bundleID: String) -> Bool { 111 | if let workspace = workspace, workspace.respondsToSelector(ReversedCall.LSApplicationWorkspace.Selector.openApplicationWithBundleID){ 112 | if workspace.performSelector(ReversedCall.LSApplicationWorkspace.Selector.openApplicationWithBundleID, withObject: bundleID) != nil{ 113 | return true //Not entirely accurate, but probably opened 114 | } 115 | } 116 | return false 117 | } 118 | 119 | func applicationIconImageForBundleIdentifier(bundleID: String) -> UIImage?{ 120 | let appIconSelector = ReversedCall.UIImage.applicationIconImageForBundleIdentifier 121 | //Selector format is (bundleID: String, format: Int, scale: Double) - format 2 will return a 62x62 image 122 | 123 | return Invocator.performClassSelector(appIconSelector, target: UIImage.self, args: [bundleID, 2, Double(UIScreen.mainScreen().scale)]) as? UIImage 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Embeddable/Invocator.m: -------------------------------------------------------------------------------- 1 | // Invocator.m 2 | // 3 | // Created by Jonathan Cardasis on 8/8/16. 4 | // Copyright © 2016 Jonathan Cardasis. All rights reserved. 5 | // 6 | // This class uses the ObjC exclusive NSInvocation in order to call selectors on 7 | // a class with ANY of arguments. 8 | // 9 | // 10 | 11 | #import 12 | @import Foundation; 13 | 14 | 15 | @interface Invocator : NSObject 16 | + (nullable id) performClassSelector:(nonnull SEL)selector target:(nonnull id)target args: (nullable NSArray*)args; 17 | @end 18 | 19 | @implementation Invocator 20 | /* 21 | Will perform a selector on a Class for any number of args. 22 | */ 23 | + (nullable id) performClassSelector:(nonnull SEL)selector target:(nonnull id)target args: (nullable NSArray*)args { 24 | NSMethodSignature *methodSignature = [UIImage methodSignatureForSelector:selector]; 25 | NSInvocation *methodInvocation = [NSInvocation invocationWithMethodSignature:methodSignature]; 26 | 27 | [methodInvocation setTarget:[target class]]; 28 | [methodInvocation setSelector: selector]; 29 | 30 | //Assign arguments to invocation 31 | for(int i=0; i < args.count; i++){ 32 | id arg = [args objectAtIndex:i]; 33 | 34 | /* Assign proper format if the object is a double or float */ 35 | /* NOTE THIS FUNCTION DOES NOT FULLY SUPPORT BOOLS and Swift BOOLEANS! */ 36 | if([arg isKindOfClass: [NSNumber class]]){ 37 | CFNumberType argType = CFNumberGetType((CFNumberRef)arg); 38 | 39 | if(argType == kCFNumberDoubleType || argType == kCFNumberFloat64Type){ 40 | double num = [arg doubleValue]; 41 | [methodInvocation setArgument:&num atIndex:i+2]; 42 | } 43 | else if (argType == kCFNumberFloatType || argType == kCFNumberFloat32Type){ 44 | float num = [arg floatValue]; 45 | [methodInvocation setArgument:&num atIndex:i+2]; 46 | } 47 | else{ 48 | [methodInvocation setArgument:&arg atIndex:i+2]; 49 | } 50 | } 51 | 52 | else{ 53 | [methodInvocation setArgument:&arg atIndex:i+2]; 54 | } 55 | } 56 | 57 | //Execute 58 | [methodInvocation invoke]; 59 | id __unsafe_unretained result; 60 | [methodInvocation getReturnValue:&result]; 61 | 62 | return result; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jonathan Cardasis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Private Headers/LSApplicationProxy.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 3 | */ 4 | 5 | #import 6 | #import "LSBundleProxy.h" 7 | 8 | @interface LSApplicationProxy : LSBundleProxy { 9 | NSNumber * _ODRDiskUsage; 10 | NSArray * _UIBackgroundModes; 11 | NSArray * _VPNPlugins; 12 | NSArray * _appTags; 13 | NSString * _applicationDSID; 14 | NSString * _applicationVariant; 15 | NSArray * _audioComponents; 16 | NSString * _companionAppIdentifier; 17 | NSArray * _deviceFamily; 18 | NSUUID * _deviceIdentifierForVendor; 19 | NSArray * _directionsModes; 20 | NSNumber * _downloaderDSID; 21 | NSNumber * _dynamicDiskUsage; 22 | NSArray * _externalAccessoryProtocols; 23 | NSNumber * _familyID; 24 | unsigned long long _flags; 25 | NSDictionary * _groupContainers; 26 | NSArray * _groupIdentifiers; 27 | unsigned long long _installType; 28 | bool _isContainerized; 29 | NSNumber * _itemID; 30 | NSString * _itemName; 31 | NSString * _minimumSystemVersion; 32 | int _modTime; 33 | unsigned long long _originalInstallType; 34 | NSArray * _plugInKitPlugins; 35 | NSArray * _pluginUUIDs; 36 | NSArray * _privateDocumentIconNames; 37 | LSApplicationProxy * _privateDocumentTypeOwner; 38 | NSNumber * _purchaserDSID; 39 | int _regTime; 40 | NSDate * _registeredDate; 41 | NSArray * _requiredDeviceCapabilities; 42 | NSString * _sdkVersion; 43 | NSString * _shortVersionString; 44 | NSString * _sourceAppIdentifier; 45 | NSNumber * _staticDiskUsage; 46 | NSString * _storeCohortMetadata; 47 | NSNumber * _storeFront; 48 | NSString * _teamID; 49 | NSString * _vendorName; 50 | NSNumber * _versionID; 51 | } 52 | 53 | @property (nonatomic, readonly) NSNumber *ODRDiskUsage; 54 | @property (nonatomic, readonly) NSArray *UIBackgroundModes; 55 | @property (nonatomic, readonly) NSArray *VPNPlugins; 56 | @property (nonatomic, readonly) NSArray *appTags; 57 | @property (nonatomic, readonly) NSString *applicationDSID; 58 | @property (nonatomic, readonly) NSString *applicationIdentifier; 59 | @property (nonatomic, readonly) NSString *applicationType; 60 | @property (nonatomic, readonly) NSString *applicationVariant; 61 | @property (nonatomic, readonly) NSArray *audioComponents; 62 | @property (nonatomic, readonly) NSNumber *betaExternalVersionIdentifier; 63 | @property (nonatomic, readonly) NSString *companionApplicationIdentifier; 64 | @property (nonatomic, readonly) NSArray *deviceFamily; 65 | @property (nonatomic, readonly) NSUUID *deviceIdentifierForVendor; 66 | @property (nonatomic, readonly) NSArray *directionsModes; 67 | @property (nonatomic, readonly) NSNumber *downloaderDSID; 68 | @property (nonatomic, readonly) NSNumber *dynamicDiskUsage; 69 | @property (nonatomic, readonly) NSArray *externalAccessoryProtocols; 70 | @property (nonatomic, readonly) NSNumber *externalVersionIdentifier; 71 | @property (nonatomic, readonly) NSNumber *familyID; 72 | @property (nonatomic, readonly) bool fileSharingEnabled; 73 | @property (nonatomic, readonly) NSDictionary *groupContainers; 74 | @property (nonatomic, readonly) NSArray *groupIdentifiers; 75 | @property (nonatomic, readonly) bool hasMIDBasedSINF; 76 | @property (nonatomic, readonly) bool hasSettingsBundle; 77 | @property (nonatomic, readonly) bool iconIsPrerendered; 78 | @property (nonatomic, readonly) NSProgress *installProgress; 79 | @property (nonatomic, readonly) unsigned long long installType; 80 | @property (nonatomic, readonly) bool isAdHocCodeSigned; 81 | @property (nonatomic, readonly) bool isAppUpdate; 82 | @property (nonatomic, readonly) bool isBetaApp; 83 | @property (nonatomic, readonly) bool isContainerized; 84 | @property (nonatomic, readonly) bool isInstalled; 85 | @property (nonatomic, readonly) bool isNewsstandApp; 86 | @property (nonatomic, readonly) bool isPlaceholder; 87 | @property (nonatomic, readonly) bool isPurchasedReDownload; 88 | @property (nonatomic, readonly) bool isRestricted; 89 | @property (nonatomic, readonly) bool isWatchKitApp; 90 | @property (nonatomic, readonly) NSNumber *itemID; 91 | @property (nonatomic, readonly) NSString *itemName; 92 | @property (nonatomic, readonly) NSString *minimumSystemVersion; 93 | @property (nonatomic, readonly) bool missingRequiredSINF; 94 | @property (nonatomic, readonly) unsigned long long originalInstallType; 95 | @property (nonatomic, readonly) NSArray *plugInKitPlugins; 96 | @property (nonatomic, readonly) NSString *preferredArchitecture; 97 | @property (nonatomic, readonly) bool profileValidated; 98 | @property (nonatomic, readonly) NSNumber *purchaserDSID; 99 | @property (nonatomic, readonly) NSDate *registeredDate; 100 | @property (nonatomic, readonly) NSArray *requiredDeviceCapabilities; 101 | @property (nonatomic, readonly) NSString *roleIdentifier; 102 | @property (nonatomic, readonly) NSString *sdkVersion; 103 | @property (nonatomic, readonly) NSString *shortVersionString; 104 | @property (nonatomic, readonly) NSString *sourceAppIdentifier; 105 | @property (nonatomic, readonly) NSNumber *staticDiskUsage; 106 | @property (nonatomic, readonly) NSString *storeCohortMetadata; 107 | @property (nonatomic, readonly) NSNumber *storeFront; 108 | @property (nonatomic, readonly) bool supportsAudiobooks; 109 | @property (nonatomic, readonly) bool supportsExternallyPlayableContent; 110 | @property (nonatomic, readonly) bool supportsOpenInPlace; 111 | @property (nonatomic, readonly) NSString *teamID; 112 | @property (nonatomic, readonly) NSString *vendorName; 113 | 114 | // Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 115 | 116 | + (id)applicationProxyForBundleURL:(id)arg1; 117 | + (id)applicationProxyForIdentifier:(id)arg1; 118 | + (id)applicationProxyForIdentifier:(id)arg1 placeholder:(bool)arg2; 119 | + (id)applicationProxyForIdentifier:(id)arg1 roleIdentifier:(id)arg2; 120 | + (id)applicationProxyForItemID:(id)arg1; 121 | + (id)applicationProxyWithBundleUnitID:(unsigned int)arg1; 122 | + (bool)supportsSecureCoding; 123 | 124 | - (id)ODRDiskUsage; 125 | - (id)UIBackgroundModes; 126 | - (id)VPNPlugins; 127 | - (id)_initWithBundleUnit:(unsigned int)arg1 applicationIdentifier:(id)arg2; 128 | - (id)appStoreReceiptURL; 129 | - (id)appTags; 130 | - (id)applicationDSID; 131 | - (id)applicationIdentifier; 132 | - (id)applicationType; 133 | - (id)applicationVariant; 134 | - (id)audioComponents; 135 | - (id)betaExternalVersionIdentifier; 136 | - (int)bundleModTime; 137 | - (id)companionApplicationIdentifier; 138 | - (void)dealloc; 139 | - (id)description; 140 | - (id)deviceFamily; 141 | - (id)deviceIdentifierForVendor; 142 | - (id)directionsModes; 143 | - (id)downloaderDSID; 144 | - (id)dynamicDiskUsage; 145 | - (void)encodeWithCoder:(id)arg1; 146 | - (id)externalAccessoryProtocols; 147 | - (id)externalVersionIdentifier; 148 | - (id)familyID; 149 | - (bool)fileSharingEnabled; 150 | - (id)groupContainers; 151 | - (id)groupIdentifiers; 152 | - (bool)hasMIDBasedSINF; 153 | - (bool)hasSettingsBundle; 154 | - (unsigned long long)hash; 155 | - (id)iconDataForVariant:(int)arg1; 156 | - (bool)iconIsPrerendered; 157 | - (id)iconStyleDomain; 158 | - (id)initWithCoder:(id)arg1; 159 | - (id)installProgress; 160 | - (id)installProgressSync; 161 | - (unsigned long long)installType; 162 | - (bool)isAdHocCodeSigned; 163 | - (bool)isAppUpdate; 164 | - (bool)isBetaApp; 165 | - (bool)isContainerized; 166 | - (bool)isEqual:(id)arg1; 167 | - (bool)isInstalled; 168 | - (bool)isNewsstandApp; 169 | - (bool)isPlaceholder; 170 | - (bool)isPurchasedReDownload; 171 | - (bool)isRestricted; 172 | - (bool)isWatchKitApp; 173 | - (id)itemID; 174 | - (id)itemName; 175 | - (id)localizedName; 176 | - (id)localizedNameForContext:(id)arg1; 177 | - (id)localizedShortName; 178 | - (id)machOUUIDs; 179 | - (id)minimumSystemVersion; 180 | - (bool)missingRequiredSINF; 181 | - (unsigned long long)originalInstallType; 182 | - (id)plugInKitPlugins; 183 | - (void)populateNotificationData; 184 | - (id)preferredArchitecture; 185 | - (bool)privateDocumentIconAllowOverride; 186 | - (id)privateDocumentIconNames; 187 | - (id)privateDocumentTypeOwner; 188 | - (id)privateIconsDictionary; 189 | - (bool)profileValidated; 190 | - (id)purchaserDSID; 191 | - (id)registeredDate; 192 | - (id)requiredDeviceCapabilities; 193 | - (id)resourcesDirectoryURL; 194 | - (id)roleIdentifier; 195 | - (id)sdkVersion; 196 | - (void)setPrivateDocumentIconAllowOverride:(bool)arg1; 197 | - (void)setPrivateDocumentIconNames:(id)arg1; 198 | - (void)setPrivateDocumentTypeOwner:(id)arg1; 199 | - (id)shortVersionString; 200 | - (id)sourceAppIdentifier; 201 | - (id)staticDiskUsage; 202 | - (id)storeCohortMetadata; 203 | - (id)storeFront; 204 | - (bool)supportsAudiobooks; 205 | - (bool)supportsExternallyPlayableContent; 206 | - (bool)supportsOpenInPlace; 207 | - (id)teamID; 208 | - (id)uniqueIdentifier; 209 | - (id)userActivityStringForAdvertisementData:(id)arg1; 210 | - (id)vendorName; 211 | - (id)versionIdentifier; 212 | 213 | // Image: /System/Library/Frameworks/UIKit.framework/UIKit 214 | 215 | //- (struct CGSize { double x1; double x2; })_defaultStyleSize:(id)arg1; 216 | //- (struct { int x1; struct CGSize { double x_2_1_1; double x_2_1_2; } x2; }*)_iconVariantDefinitions:(id)arg1; 217 | 218 | // Image: /System/Library/PrivateFrameworks/UserNotification.framework/UserNotification 219 | 220 | + (id)un_applicationProxyForBundleIdentifier:(id)arg1; 221 | + (id)un_bundleForBundleIdentifier:(id)arg1; 222 | 223 | - (bool)_un_isResourceValidForPath:(id)arg1 withContainerPath:(id)arg2; 224 | - (id)un_bundle; 225 | - (id)un_infoDictionary; 226 | - (bool)un_isSystemApplication; 227 | - (id)un_pathForSoundName:(id)arg1; 228 | - (bool)un_requiresLocalNotification; 229 | - (bool)un_shouldUseDefaultDataProvider; 230 | - (bool)un_usesLocalNotification; 231 | 232 | @end 233 | -------------------------------------------------------------------------------- /Private Headers/LSApplicationWorkspace.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 3 | */ 4 | 5 | #import 6 | 7 | @interface LSApplicationWorkspace : NSObject 8 | 9 | 10 | // Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 11 | 12 | + (id)defaultWorkspace; 13 | 14 | - (id)URLOverrideForURL:(id)arg1; 15 | - (void)_LSClearSchemaCaches; 16 | - (bool)_LSPrivateRebuildApplicationDatabasesForSystemApps:(bool)arg1 internal:(bool)arg2 user:(bool)arg3; 17 | - (void)_clearCachedAdvertisingIdentifier; 18 | - (void)addObserver:(id)arg1; 19 | - (id)allApplications; 20 | - (id)allInstalledApplications; 21 | - (id)applicationForOpeningResource:(id)arg1; 22 | - (id)applicationForUserActivityDomainName:(id)arg1; 23 | - (id)applicationForUserActivityType:(id)arg1; 24 | - (bool)applicationIsInstalled:(id)arg1; 25 | - (id)applicationsAvailableForHandlingURLScheme:(id)arg1; 26 | - (id)applicationsAvailableForOpeningDocument:(id)arg1; 27 | - (id)applicationsOfType:(unsigned long long)arg1; 28 | - (id)applicationsWithAudioComponents; 29 | - (id)applicationsWithExternalAccessoryProtocols; 30 | - (id)applicationsWithSettingsBundle; 31 | - (id)applicationsWithUIBackgroundModes; 32 | - (id)applicationsWithVPNPlugins; 33 | - (void)clearAdvertisingIdentifier; 34 | - (void)clearCreatedProgressForBundleID:(id)arg1; 35 | - (id)delegateProxy; 36 | - (id)deviceIdentifierForAdvertising; 37 | - (id)deviceIdentifierForVendor; 38 | - (id)directionsApplications; 39 | - (bool)downgradeApplicationToPlaceholder:(id)arg1 withOptions:(id)arg2 error:(id*)arg3; 40 | - (void)enumerateBundlesOfType:(unsigned long long)arg1 usingBlock:(id /* block */)arg2; 41 | - (bool)establishConnection; 42 | - (bool)getClaimedActivityTypes:(id*)arg1 domains:(id*)arg2; 43 | - (unsigned long long)getInstallTypeForOptions:(id)arg1 andApp:(id)arg2; 44 | - (void)getKnowledgeUUID:(id*)arg1 andSequenceNumber:(id*)arg2; 45 | - (bool)installApplication:(id)arg1 withOptions:(id)arg2; 46 | - (bool)installApplication:(id)arg1 withOptions:(id)arg2 error:(id*)arg3; 47 | - (bool)installApplication:(id)arg1 withOptions:(id)arg2 error:(id*)arg3 usingBlock:(id /* block */)arg4; 48 | - (id)installBundle:(id)arg1 withOptions:(id)arg2 usingBlock:(id /* block */)arg3 forApp:(id)arg4 withError:(id*)arg5 outInstallProgress:(id*)arg6; 49 | - (bool)installPhaseFinishedForProgress:(id)arg1; 50 | - (id)installProgressForApplication:(id)arg1 withPhase:(unsigned long long)arg2; 51 | - (id)installProgressForBundleID:(id)arg1 makeSynchronous:(unsigned char)arg2; 52 | - (id)installedPlugins; 53 | - (id)installedVPNPlugins; 54 | - (bool)invalidateIconCache:(id)arg1; 55 | - (bool)isApplicationAvailableToOpenURL:(id)arg1 error:(id*)arg2; 56 | - (bool)openApplicationWithBundleID:(id)arg1; 57 | - (bool)openSensitiveURL:(id)arg1 withOptions:(id)arg2; 58 | - (bool)openSensitiveURL:(id)arg1 withOptions:(id)arg2 error:(id*)arg3; 59 | - (bool)openURL:(id)arg1; 60 | - (bool)openURL:(id)arg1 withOptions:(id)arg2; 61 | - (bool)openURL:(id)arg1 withOptions:(id)arg2 error:(id*)arg3; 62 | - (void)openUserActivity:(id)arg1 withApplicationProxy:(id)arg2 completionHandler:(id /* block */)arg3; 63 | - (id)operationToOpenResource:(id)arg1 usingApplication:(id)arg2 uniqueDocumentIdentifier:(id)arg3 sourceIsManaged:(bool)arg4 userInfo:(id)arg5 delegate:(id)arg6; 64 | - (id)operationToOpenResource:(id)arg1 usingApplication:(id)arg2 uniqueDocumentIdentifier:(id)arg3 userInfo:(id)arg4; 65 | - (id)operationToOpenResource:(id)arg1 usingApplication:(id)arg2 uniqueDocumentIdentifier:(id)arg3 userInfo:(id)arg4 delegate:(id)arg5; 66 | - (id)operationToOpenResource:(id)arg1 usingApplication:(id)arg2 userInfo:(id)arg3; 67 | - (id)placeholderApplications; 68 | - (id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3; 69 | - (id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3 applyFilter:(id /* block */)arg4; 70 | - (id)pluginsWithIdentifiers:(id)arg1 protocols:(id)arg2 version:(id)arg3 withFilter:(id /* block */)arg4; 71 | - (id)privateURLSchemes; 72 | - (id)publicURLSchemes; 73 | - (bool)registerApplication:(id)arg1; 74 | - (bool)registerApplicationDictionary:(id)arg1; 75 | - (bool)registerApplicationDictionary:(id)arg1 withObserverNotification:(int)arg2; 76 | - (bool)registerBundleWithInfo:(id)arg1 options:(id)arg2 type:(unsigned long long)arg3 progress:(id)arg4; 77 | - (bool)registerPlugin:(id)arg1; 78 | - (id)remoteObserver; 79 | - (void)removeInstallProgressForBundleID:(id)arg1; 80 | - (void)removeObserver:(id)arg1; 81 | - (bool)uninstallApplication:(id)arg1 withOptions:(id)arg2; 82 | - (bool)uninstallApplication:(id)arg1 withOptions:(id)arg2 usingBlock:(id /* block */)arg3; 83 | - (bool)unregisterApplication:(id)arg1; 84 | - (bool)unregisterPlugin:(id)arg1; 85 | - (id)unrestrictedApplications; 86 | - (bool)updateSINFWithData:(id)arg1 forApplication:(id)arg2 options:(id)arg3 error:(id*)arg4; 87 | 88 | // Image: /System/Library/Frameworks/SafariServices.framework/SafariServices 89 | 90 | - (void)_sf_openURL:(id)arg1 withOptions:(id)arg2 completionHandler:(id /* block */)arg3; 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Private Headers/LSBundleProxy.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 3 | */ 4 | 5 | #import 6 | #import "LSResourceProxy.h" 7 | 8 | @interface LSBundleProxy : LSResourceProxy { 9 | NSURL * _appStoreReceiptURL; 10 | NSString * _bundleExecutable; 11 | unsigned long long _bundleFlags; 12 | NSString * _bundleType; 13 | NSURL * _bundleURL; 14 | NSString * _bundleVersion; 15 | NSUUID * _cacheGUID; 16 | NSDictionary * _entitlements; 17 | NSDictionary * _environmentVariables; 18 | bool _foundBackingBundle; 19 | NSDictionary * _groupContainerURLs; 20 | NSString * _localizedShortName; 21 | NSArray * _machOUUIDs; 22 | unsigned long long _plistContentFlags; 23 | unsigned long long _sequenceNumber; 24 | NSString * _signerIdentity; 25 | } 26 | 27 | @property (nonatomic, readonly) NSURL *appStoreReceiptURL; 28 | @property (nonatomic, readonly) NSURL *bundleContainerURL; 29 | @property (nonatomic, readonly) NSString *bundleExecutable; 30 | @property (nonatomic, readonly) NSString *bundleIdentifier; 31 | @property (nonatomic, readonly) NSString *bundleType; 32 | @property (nonatomic, readonly) NSURL *bundleURL; 33 | @property (nonatomic, readonly) NSString *bundleVersion; 34 | @property (nonatomic, readonly) NSUUID *cacheGUID; 35 | @property (nonatomic, readonly) NSURL *containerURL; 36 | @property (nonatomic, readonly) NSURL *dataContainerURL; 37 | @property (nonatomic, readonly) NSDictionary *entitlements; 38 | @property (nonatomic, readonly) NSDictionary *environmentVariables; 39 | @property (nonatomic, readonly) bool foundBackingBundle; 40 | @property (nonatomic, readonly) NSDictionary *groupContainerURLs; 41 | @property (nonatomic, readonly) NSString *localizedShortName; 42 | @property (nonatomic, readonly) NSArray *machOUUIDs; 43 | @property (nonatomic, readonly) unsigned long long sequenceNumber; 44 | @property (nonatomic, readonly) NSString *signerIdentity; 45 | 46 | // Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 47 | 48 | + (id)bundleProxyForIdentifier:(id)arg1; 49 | + (id)bundleProxyForURL:(id)arg1; 50 | + (bool)supportsSecureCoding; 51 | 52 | //- (unsigned char)_createContext:(struct LSContext { struct LSDatabase {} *x1; }*)arg1 andGetBundle:(unsigned int*)arg2 withData:(const struct LSBundleData {}**)arg3; 53 | - (id)_initWithBundleUnit:(unsigned int)arg1 bundleType:(unsigned long long)arg2 BundleID:(id)arg3 localizedName:(id)arg4 bundleContainerURL:(id)arg5 dataContainerURL:(id)arg6 resourcesDirectoryURL:(id)arg7 iconsDictionary:(id)arg8 iconFileNames:(id)arg9 version:(id)arg10; 54 | - (id)_plistValueForKey:(id)arg1; 55 | - (id)appStoreReceiptURL; 56 | - (id)bundleContainerURL; 57 | - (id)bundleExecutable; 58 | - (id)bundleIdentifier; 59 | - (id)bundleType; 60 | - (id)bundleURL; 61 | - (id)bundleVersion; 62 | - (id)cacheGUID; 63 | - (id)containerURL; 64 | - (id)dataContainerURL; 65 | - (void)dealloc; 66 | - (void)encodeWithCoder:(id)arg1; 67 | - (id)entitlements; 68 | - (id)environmentVariables; 69 | - (bool)foundBackingBundle; 70 | - (id)groupContainerURLs; 71 | - (unsigned long long)hash; 72 | - (id)initWithCoder:(id)arg1; 73 | - (bool)isEqual:(id)arg1; 74 | - (id)localizedShortName; 75 | - (id)machOUUIDs; 76 | - (unsigned long long)sequenceNumber; 77 | - (void)setLocalizedShortName:(NSString*)arg1; 78 | - (id)signerIdentity; 79 | - (id)uniqueIdentifier; 80 | 81 | // Image: /System/Library/Frameworks/HealthKit.framework/HealthKit 82 | 83 | + (id)_hk_appExtensionContainerBundleProxyWithProperties:(id)arg1; 84 | + (id)hk_appExtensionContainerBundleForConnection:(id)arg1; 85 | + (id)hk_appExtensionContainerBundleForCurrentTask; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /Private Headers/LSResourceProxy.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 3 | */ 4 | 5 | #import 6 | 7 | @class LSApplicationProxy; 8 | 9 | @interface LSResourceProxy : NSObject { 10 | NSString * _boundApplicationIdentifier; 11 | NSURL * _boundContainerURL; 12 | NSURL * _boundDataContainerURL; 13 | NSString * _boundIconCacheKey; 14 | NSArray * _boundIconFileNames; 15 | bool _boundIconIsBadge; 16 | bool _boundIconIsPrerendered; 17 | NSDictionary * _boundIconsDictionary; 18 | NSURL * _boundResourcesDirURL; 19 | NSString * _localizedName; 20 | LSApplicationProxy * _typeOwner; 21 | } 22 | 23 | @property (nonatomic, readonly) bool boundIconIsBadge; 24 | @property (nonatomic, readonly) NSDictionary *iconsDictionary; 25 | @property (nonatomic, readonly) NSString *localizedName; 26 | 27 | // Image: /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices 28 | 29 | + (id)allowedClasses; 30 | + (bool)supportsSecureCoding; 31 | 32 | - (id)_initWithLocalizedName:(id)arg1; 33 | - (id)_initWithLocalizedName:(id)arg1 boundApplicationIdentifier:(id)arg2 boundContainerURL:(id)arg3 dataContainerURL:(id)arg4 boundResourcesDirectoryURL:(id)arg5 boundIconsDictionary:(id)arg6 boundIconCacheKey:(id)arg7 boundIconFileNames:(id)arg8 typeOwner:(id)arg9 boundIconIsPrerendered:(bool)arg10 boundIconIsBadge:(bool)arg11; 34 | - (id)boundApplicationIdentifier; 35 | - (id)boundContainerURL; 36 | - (id)boundDataContainerURL; 37 | - (id)boundIconCacheKey; 38 | - (id)boundIconFileNames; 39 | - (bool)boundIconIsBadge; 40 | - (bool)boundIconIsPrerendered; 41 | - (id)boundIconsDictionary; 42 | - (id)boundResourcesDirectoryURL; 43 | - (id)copyWithZone:(NSZone*)arg1; 44 | - (void)dealloc; 45 | - (void)encodeWithCoder:(id)arg1; 46 | - (id)iconDataForStyle:(id)arg1 width:(long long)arg2 height:(long long)arg3 options:(unsigned long long)arg4; 47 | - (id)iconDataForVariant:(int)arg1; 48 | - (id)iconStyleDomain; 49 | - (id)iconsDictionary; 50 | - (id)initWithCoder:(id)arg1; 51 | - (id)localizedName; 52 | - (void)setBoundApplicationIdentifier:(id)arg1; 53 | - (void)setBoundContainerURL:(id)arg1; 54 | - (void)setBoundDataContainerURL:(id)arg1; 55 | - (void)setBoundIconCacheKey:(id)arg1; 56 | - (void)setBoundIconFileNames:(id)arg1; 57 | - (void)setBoundIconIsBadge:(bool)arg1; 58 | - (void)setBoundIconIsPrerendered:(bool)arg1; 59 | - (void)setBoundIconsDictionary:(id)arg1; 60 | - (void)setBoundResourcesDirectoryURL:(id)arg1; 61 | - (void)setLocalizedName:(NSString*)arg1; 62 | - (void)setTypeOwner:(id)arg1; 63 | - (id)typeOwner; 64 | - (id)uniqueIdentifier; 65 | 66 | // Image: /System/Library/Frameworks/UIKit.framework/UIKit 67 | 68 | //+ (struct CGSize { double x1; double x2; })_applicationIconCanvasSize; 69 | //+ (long long)_compareApplicationIconCanvasSize:(struct CGSize { double x1; double x2; })arg1 withSize:(struct CGSize { double x1; double x2; })arg2; 70 | // 71 | //- (struct CGSize { double x1; double x2; })_defaultStyleSize:(id)arg1; 72 | //- (struct { int x1; struct CGSize { double x_2_1_1; double x_2_1_2; } x2; }*)_iconDefinitionForSize:(struct CGSize { double x1; double x2; })arg1 style:(id)arg2; 73 | //- (id)_iconForStyle:(id)arg1; 74 | //- (id)_iconForStyle:(id)arg1 size:(struct CGSize { double x1; double x2; })arg2; 75 | //- (struct { int x1; struct CGSize { double x_2_1_1; double x_2_1_2; } x2; }*)_iconVariantDefinitions:(id)arg1; 76 | //- (struct CGSize { double x1; double x2; })_largestImageSize:(id)arg1; 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Private Headers/UIImage-ApplicationIcons.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/Frameworks/UIKit.framework/UIKit 3 | 4 | These methods were extracted from the implementation. 5 | */ 6 | 7 | #import 8 | 9 | @interface UIImage (ApplicationIcons) 10 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 format:(int)arg2; 11 | + (id)_applicationIconImageForBundleIdentifier:(id)arg1 format:(int)arg2 scale:(double)arg3; //chnage 12 | 13 | + (id)_iconForResourceProxy:(id)arg1 format:(int)arg2; 14 | + (id)_iconForResourceProxy:(id)arg1 variant:(int)arg2 variantsScale:(double)arg3; 15 | + (int)_iconVariantForUIApplicationIconFormat:(int)arg1 scale:(double*)arg2; 16 | 17 | @end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # AppExplorer 4 | 5 | AppExplorer demos the use of some of Apple's private frameworks. The application is capable of retrieving all of the devices installed apps as well as their icons and can launch any of the applications. 6 | 7 | 8 | 9 | ## Theory 10 | Each application on iOS is a type of `LSApplicationProxy`. This class contains a number of defining properties associated with each applicaton. `LSApplicationWorkspace` manages these application proxies, controlling the launch of the application, installation, and deletion. 11 | 12 | By using these class headers (as well as the classes they inherit from) I was able to reverse-engineer some private calls and launch applications based on their bundle identifier. These bundle identifiers could, in turn, be found by the application workspace. 13 | 14 | In order to recieve the applications' icon images I used the original `UIImage.h` class header from UIKit. I created an UIImage extention for the important private methods from the original UIImage header which I want to call. The one I was primarily interested in was `_applicationIconImageForBundleIdentifier:(id)arg1 format:(id)arg2;`. 15 | 16 | ## Implementation 17 | I created two classes `SystemApplicationManager` and `SystemApplication` which aim to allow for easier use of interfacing with the underlying classes stated above. Adopting the principals of Swift, I wanted to make sure any data being passed was safely handled, since the private classes these are based on could change at any time. 18 | 19 | 20 | ## Do it yourself! 21 | ### Standard Install 22 | *This method is shown in the demo project.* 23 | 24 | 1. Link the framework `MobileCoreServices.framework`. 25 | 2. Copy the `Private Headers` folder to your project. 26 | 3. Copy the `SystemApplicationManager.swift` and `SystemApplication.swift` classes to your project. 27 | 4. Get Swifty with it! 28 | ```Swift 29 | let installedApps = SystemApplicationManager.sharedManager.allInstalledApplications() 30 | ``` 31 | Thats about it. Now you can get a number of properties from each of the SystemApplication objects in the array. 32 | 33 | ### Non-Framework Install 34 | *This method doesn't require any external frameworks or private headers to be imported.* 35 | 36 | 1. Copy the `EmbeddableSystemApplicationManager.swift` and `Invocator.m` classes from the Embeddable folder as well as the `SystemApplication.swift` class to your project. 37 | 2. Add `#import "Invocator.m"` to your bridging header. 38 | 3. Secretly get data from installed applications! 39 | ```Swift 40 | let installedApps = EmbeddableSystemApplicationManager.sharedManager.allInstalledApplications() 41 | ``` 42 | You can test this by replacing occurances of SystemApplicationManager with EmbeddableSystemApplicationManager and unlinking the framework in the demo project. 43 | 44 | 45 | \* Note that EmbeddableSystemApplicationManager and SystemApplicationManager share the exact same functionality. 46 | -------------------------------------------------------------------------------- /SystemApplication.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemApplication.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum SystemApplicationType{ 12 | case system 13 | case user 14 | } 15 | 16 | class SystemApplication: NSObject { 17 | var bundleID: String? 18 | var name: String? //Springboard display name 19 | var version: String? 20 | var executableName: String? //Name of internal payload executable 21 | var type: SystemApplicationType? 22 | var signerIdentity: String? 23 | var applicationPath: URL? 24 | var backgroundModes: [String]? 25 | var icon: UIImage? 26 | 27 | override init(){ 28 | super.init() 29 | } 30 | 31 | init(bundleID: String){ 32 | super.init() 33 | self.bundleID = bundleID 34 | } 35 | 36 | 37 | /* 38 | Mapping function. 39 | Pass nil for any parameter not given 40 | */ 41 | func map(bundleID: String?, 42 | name: String?, 43 | version: String?, 44 | executableName: String?, 45 | type: String?, 46 | signerIdentity: String?, 47 | applicationPath: URL?, 48 | backgroundModes: [String]?, 49 | icon: UIImage? 50 | ){ 51 | 52 | self.bundleID = bundleID 53 | self.name = name 54 | self.version = version 55 | self.executableName = executableName 56 | if type == "System"{ 57 | self.type = .system 58 | } 59 | else{ 60 | self.type = .user 61 | } 62 | self.signerIdentity = signerIdentity 63 | self.applicationPath = applicationPath 64 | self.backgroundModes = backgroundModes 65 | self.icon = icon 66 | } 67 | 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /SystemApplicationManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ApplicationManager.swift 3 | // AppExplorer 4 | // 5 | // Created by Cardasis, Jonathan (J.) on 7/13/16. 6 | // Copyright © 2016 Cardasis, Jonathan (J.). All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class SystemApplicationManager: NSObject { 12 | static let sharedManager = SystemApplicationManager() 13 | fileprivate var workspace: LSApplicationWorkspace? 14 | 15 | 16 | override init() { 17 | workspace = LSApplicationWorkspace.defaultWorkspace() as? LSApplicationWorkspace 18 | } 19 | 20 | func allInstalledApplications() -> [SystemApplication]{ 21 | guard let workspace = workspace else { //protect 22 | return [] 23 | } 24 | var applications = [SystemApplication]() 25 | let installedApplicationProxies = workspace.allInstalledApplications() as! [LSApplicationProxy] 26 | 27 | for applicationProxy in installedApplicationProxies { 28 | 29 | let bundleIdentifier = applicationProxy.bundleIdentifier 30 | let appIcon = self.applicationIconImageForBundleIdentifier(bundleIdentifier!) 31 | 32 | /* Create and map a system application object to LSApplicationProxys variables */ 33 | let app = SystemApplication() 34 | app.map(bundleID: bundleIdentifier, 35 | name: applicationProxy.localizedName, 36 | version: applicationProxy.shortVersionString, 37 | executableName: applicationProxy.bundleExecutable, 38 | type: applicationProxy.applicationType, 39 | signerIdentity: applicationProxy.signerIdentity, 40 | applicationPath: applicationProxy.dataContainerURL, 41 | backgroundModes: applicationProxy.uiBackgroundModes as? [String], 42 | icon: appIcon 43 | ) 44 | 45 | applications.append(app) 46 | } 47 | 48 | return applications 49 | } 50 | 51 | 52 | @discardableResult func openApplication(_ app: SystemApplication) -> Bool { 53 | if let workspace = workspace { 54 | return workspace.openApplication(withBundleID: app.bundleID) 55 | } 56 | return false 57 | } 58 | 59 | @discardableResult func openApplication(bundleID: String) -> Bool { 60 | if let workspace = workspace { 61 | return workspace.openApplication(withBundleID: bundleID) 62 | } 63 | return false 64 | } 65 | 66 | func applicationIconImageForBundleIdentifier(_ bundleID: String) -> UIImage?{ 67 | //Format of 2 will return a 62x62 image 68 | return UIImage._applicationIconImage(forBundleIdentifier: bundleID, format: 2 69 | , scale: Double(UIScreen.main.scale)) as? UIImage 70 | } 71 | 72 | } 73 | --------------------------------------------------------------------------------