mirror of
https://github.com/somegeekintn/SimDirs.git
synced 2026-04-27 14:57:40 +00:00
compiles again but that's about it
This commit is contained in:
parent
61fe44e6df
commit
b64dc063f6
12 changed files with 120 additions and 115 deletions
|
|
@ -170,6 +170,7 @@
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
|
English,
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
|
|
@ -266,6 +267,7 @@
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
|
@ -301,6 +303,7 @@
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -13,7 +13,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
func applicationDidFinishLaunching(aNotification: NSNotification) {
|
func applicationDidFinishLaunching(aNotification: NSNotification) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool {
|
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--Application-->
|
<!--Application-->
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
var minOSVersion : String?
|
var minOSVersion : String?
|
||||||
var icon : NSImage?
|
var icon : NSImage?
|
||||||
var hasValidPaths : Bool { return self.validatedBundlePath != nil || self.validatedSandboxPath != nil }
|
var hasValidPaths : Bool { return self.validatedBundlePath != nil || self.validatedSandboxPath != nil }
|
||||||
var bundleURL : NSURL? { return self.validatedBundlePath.map { NSURL(fileURLWithPath: $0) } }
|
var bundleURL : URL? { return self.validatedBundlePath.map { URL(fileURLWithPath: $0) } }
|
||||||
var sandboxURL : NSURL? { return self.validatedSandboxPath.map { NSURL(fileURLWithPath: $0) } }
|
var sandboxURL : URL? { return self.validatedSandboxPath.map { URL(fileURLWithPath: $0) } }
|
||||||
private var validatedBundlePath : String?
|
private var validatedBundlePath : String?
|
||||||
private var validatedSandboxPath : String?
|
private var validatedSandboxPath : String?
|
||||||
|
|
||||||
|
|
@ -50,12 +50,12 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
self.loadInfoPlist()
|
self.loadInfoPlist()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFromLastLaunchMapInfo(launchBundleInfo: [String : AnyObject]) {
|
func updateFrom(launchBundleInfo: [String : AnyObject]) {
|
||||||
self.bundlePath = launchBundleInfo["BundleContainer"] as? String
|
self.bundlePath = launchBundleInfo["BundleContainer"] as? String
|
||||||
self.sandboxPath = launchBundleInfo["Container"] as? String
|
self.sandboxPath = launchBundleInfo["Container"] as? String
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFromAppStateInfo(appStateInfo: [String : AnyObject]) {
|
func updateFrom(appStateInfo: [String : AnyObject]) {
|
||||||
guard let compatInfo = appStateInfo["compatibilityInfo"] as? [String : AnyObject] else { return }
|
guard let compatInfo = appStateInfo["compatibilityInfo"] as? [String : AnyObject] else { return }
|
||||||
|
|
||||||
self.bundlePath = compatInfo["bundlePath"] as? String
|
self.bundlePath = compatInfo["bundlePath"] as? String
|
||||||
|
|
@ -64,16 +64,13 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
|
|
||||||
func refinePaths() {
|
func refinePaths() {
|
||||||
guard let bundleURL = self.bundleURL else { return }
|
guard let bundleURL = self.bundleURL else { return }
|
||||||
let fileMgr = NSFileManager.defaultManager()
|
let fileMgr = FileManager.default
|
||||||
|
|
||||||
if let lastPathComponent = bundleURL.lastPathComponent where !lastPathComponent.containsString(".app") {
|
if bundleURL.lastPathComponent.contains("app") == true {
|
||||||
if let dirEnumerator = fileMgr.enumeratorAtURL(bundleURL, includingPropertiesForKeys: nil, options: [ .SkipsSubdirectoryDescendants, .SkipsHiddenFiles ], errorHandler: nil) {
|
if let dirEnumerator = fileMgr.enumerator(at: bundleURL, includingPropertiesForKeys: nil, options: [ .skipsSubdirectoryDescendants, .skipsHiddenFiles ]) {
|
||||||
let dirURLs = dirEnumerator.allObjects.flatMap { $0 as? NSURL }
|
|
||||||
|
for appURL in dirEnumerator.allObjects.compactMap({ $0 as? URL}) {
|
||||||
for appURL in dirURLs {
|
if appURL.lastPathComponent.contains(".app") {
|
||||||
guard let lastPathComponent = appURL.lastPathComponent else { continue }
|
|
||||||
|
|
||||||
if lastPathComponent.containsString(".app") {
|
|
||||||
self.validatedBundlePath = appURL.path
|
self.validatedBundlePath = appURL.path
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -84,9 +81,9 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
|
|
||||||
func loadInfoPlist() {
|
func loadInfoPlist() {
|
||||||
guard let bundleURL = self.bundleURL else { return }
|
guard let bundleURL = self.bundleURL else { return }
|
||||||
let infoPlistURL = bundleURL.URLByAppendingPathComponent("Info.plist")
|
let infoPlistURL = bundleURL.appendingPathComponent("Info.plist")
|
||||||
|
|
||||||
if let plistInfo = NSPropertyListSerialization.propertyListWithURL(infoPlistURL) {
|
if let plistInfo = PropertyListSerialization.propertyListWithURL(infoPlistURL) {
|
||||||
self.bundleName = plistInfo[String(kCFBundleNameKey)] as? String ?? ""
|
self.bundleName = plistInfo[String(kCFBundleNameKey)] as? String ?? ""
|
||||||
self.displayName = plistInfo["CFBundleDisplayName"] as? String ?? ""
|
self.displayName = plistInfo["CFBundleDisplayName"] as? String ?? ""
|
||||||
self.shortVersion = plistInfo["CFBundleShortVersionString"] as? String ?? ""
|
self.shortVersion = plistInfo["CFBundleShortVersionString"] as? String ?? ""
|
||||||
|
|
@ -101,7 +98,7 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
let primaryIconValue = bundleIcons["CFBundlePrimaryIcon"].flatMap { item -> [String : AnyObject]? in
|
let primaryIconValue = bundleIcons["CFBundlePrimaryIcon"].flatMap { item -> [String : AnyObject]? in
|
||||||
switch item {
|
switch item {
|
||||||
case let dict as [String : AnyObject]: return dict
|
case let dict as [String : AnyObject]: return dict
|
||||||
case let str as String: return ["CFBundleIconFiles" : [str]]
|
case let str as String: return ["CFBundleIconFiles" : [str]] as [String : AnyObject]
|
||||||
default: return nil
|
default: return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,12 +106,11 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
if let primaryIcon = primaryIconValue {
|
if let primaryIcon = primaryIconValue {
|
||||||
if let bundleIconFiles = primaryIcon["CFBundleIconFiles"] as? [String] {
|
if let bundleIconFiles = primaryIcon["CFBundleIconFiles"] as? [String] {
|
||||||
for iconName in bundleIconFiles {
|
for iconName in bundleIconFiles {
|
||||||
var iconURL = bundleURL.URLByAppendingPathComponent(iconName)
|
var iconURL = bundleURL.appendingPathComponent(iconName)
|
||||||
let icon2XURL = bundleURL.URLByAppendingPathComponent("\(iconName)@2x.png")
|
let icon2XURL = bundleURL.appendingPathComponent("\(iconName)@2x.png")
|
||||||
let missingExt = iconURL.pathExtension.map({ return $0.isEmpty }) ?? true
|
|
||||||
|
|
||||||
if missingExt {
|
if iconURL.pathExtension.isEmpty {
|
||||||
iconURL = iconURL.URLByAppendingPathExtension("png")
|
iconURL = iconURL.appendingPathComponent("png")
|
||||||
}
|
}
|
||||||
|
|
||||||
// .car files not yet working :/
|
// .car files not yet working :/
|
||||||
|
|
@ -143,13 +139,13 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
if let icon = NSImage(contentsOfURL: iconURL) {
|
if let icon = NSImage(contentsOf: iconURL) {
|
||||||
if self.icon?.size.width ?? 0 < icon.size.width {
|
if self.icon?.size.width ?? 0 < icon.size.width {
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let icon = NSImage(contentsOfURL: icon2XURL) {
|
if let icon = NSImage(contentsOf: icon2XURL) {
|
||||||
if self.icon?.size.width ?? 0 < icon.size.width {
|
if self.icon?.size.width ?? 0 < icon.size.width {
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +168,7 @@ class SimApp: OutlineProvider, PropertyProvider {
|
||||||
var outlineImage : NSImage? { return self.icon }
|
var outlineImage : NSImage? { return self.icon }
|
||||||
var childCount : Int { return 0 }
|
var childCount : Int { return 0 }
|
||||||
|
|
||||||
func childAtIndex(index: Int) -> OutlineProvider? {
|
func childAt(index: Int) -> OutlineProvider? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
let name : String
|
let name : String
|
||||||
let type : String
|
let type : String
|
||||||
let udid : String
|
let udid : String
|
||||||
let baseURL : NSURL
|
let baseURL : URL
|
||||||
var platformName = "Unknown"
|
var platformName = "Unknown"
|
||||||
var platformVersion = ""
|
var platformVersion = ""
|
||||||
var platformBuild = ""
|
var platformBuild = ""
|
||||||
var apps = [SimApp]()
|
var apps = [SimApp]()
|
||||||
|
|
||||||
init(name: String, type: String, udid: String, baseURL: NSURL) {
|
init(name: String, type: String, udid: String, baseURL: URL) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
self.udid = udid
|
self.udid = udid
|
||||||
|
|
@ -39,12 +39,12 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
for app in self.apps {
|
for app in self.apps {
|
||||||
app.completeScan()
|
app.completeScan()
|
||||||
}
|
}
|
||||||
self.apps.sortInPlace { $0.displayName < $1.displayName }
|
self.apps.sort(by: { $0.displayName < $1.displayName })
|
||||||
}
|
}
|
||||||
|
|
||||||
func gatherBuildInfo() {
|
func gatherBuildInfo() {
|
||||||
let buildInfoURL = self.baseURL.URLByAppendingPathComponent("data/Library/MobileInstallation/LastBuildInfo.plist")
|
let buildInfoURL = self.baseURL.appendingPathComponent("data/Library/MobileInstallation/LastBuildInfo.plist")
|
||||||
guard let buildInfo = NSPropertyListSerialization.propertyListWithURL(buildInfoURL) else { return }
|
guard let buildInfo = PropertyListSerialization.propertyListWithURL(buildInfoURL) else { return }
|
||||||
|
|
||||||
self.platformVersion = buildInfo["ProductVersion"] as? String ?? ""
|
self.platformVersion = buildInfo["ProductVersion"] as? String ?? ""
|
||||||
self.platformBuild = buildInfo["ProductBuildVersion"] as? String ?? ""
|
self.platformBuild = buildInfo["ProductBuildVersion"] as? String ?? ""
|
||||||
|
|
@ -52,30 +52,30 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
|
|
||||||
// LastLaunchServicesMap.plist seems to be the most reliable location to gather app info
|
// LastLaunchServicesMap.plist seems to be the most reliable location to gather app info
|
||||||
func gatherAppInfoFromLastLaunchMap() {
|
func gatherAppInfoFromLastLaunchMap() {
|
||||||
let launchMapInfoURL = self.baseURL.URLByAppendingPathComponent("data/Library/MobileInstallation/LastLaunchServicesMap.plist")
|
let launchMapInfoURL = self.baseURL.appendingPathComponent("data/Library/MobileInstallation/LastLaunchServicesMap.plist")
|
||||||
guard let launchInfo = NSPropertyListSerialization.propertyListWithURL(launchMapInfoURL) else { return }
|
guard let launchInfo = PropertyListSerialization.propertyListWithURL(launchMapInfoURL) else { return }
|
||||||
guard let userInfo = launchInfo["User"] as? [String : AnyObject] else { return }
|
guard let userInfo = launchInfo["User"] as? [String : AnyObject] else { return }
|
||||||
|
|
||||||
for (bundleID, bundleInfo) in userInfo {
|
for (bundleID, bundleInfo) in userInfo {
|
||||||
guard let bundleInfo = bundleInfo as? [String : AnyObject] else { continue }
|
guard let bundleInfo = bundleInfo as? [String : AnyObject] else { continue }
|
||||||
let simApp = self.apps.match({ $0.bundleID == bundleID }, orMake: { SimApp(bundleID: bundleID) })
|
let simApp = self.apps.match({ $0.bundleID == bundleID }, orMake: { SimApp(bundleID: bundleID) })
|
||||||
|
|
||||||
simApp.updateFromLastLaunchMapInfo(bundleInfo)
|
simApp.updateFrom(launchBundleInfo: bundleInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// applicationState.plist sometimes has info that LastLaunchServicesMap.plist doesn't
|
// applicationState.plist sometimes has info that LastLaunchServicesMap.plist doesn't
|
||||||
func gatherAppInfoFromAppState() {
|
func gatherAppInfoFromAppState() {
|
||||||
for pathComponent in ["data/Library/FrontBoard/applicationState.plist", "data/Library/BackBoard/applicationState.plist"] {
|
for pathComponent in ["data/Library/FrontBoard/applicationState.plist", "data/Library/BackBoard/applicationState.plist"] {
|
||||||
let appStateInfoURL = self.baseURL.URLByAppendingPathComponent(pathComponent)
|
let appStateInfoURL = self.baseURL.appendingPathComponent(pathComponent)
|
||||||
guard let stateInfo = NSPropertyListSerialization.propertyListWithURL(appStateInfoURL) else { continue }
|
guard let stateInfo = PropertyListSerialization.propertyListWithURL(appStateInfoURL) else { continue }
|
||||||
|
|
||||||
for (bundleID, bundleInfo) in stateInfo {
|
for (bundleID, bundleInfo) in stateInfo {
|
||||||
if !bundleID.containsString("com.apple") {
|
if !bundleID.contains("com.apple") {
|
||||||
guard let bundleInfo = bundleInfo as? [String : AnyObject] else { continue }
|
guard let bundleInfo = bundleInfo as? [String : AnyObject] else { continue }
|
||||||
let simApp = self.apps.match({ $0.bundleID == bundleID }, orMake: { SimApp(bundleID: bundleID) })
|
let simApp = self.apps.match({ $0.bundleID == bundleID }, orMake: { SimApp(bundleID: bundleID) })
|
||||||
|
|
||||||
simApp.updateFromAppStateInfo(bundleInfo)
|
simApp.updateFrom(appStateInfo: bundleInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,26 +84,26 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
// mobile_installation.log.0 is my least favorite, most fragile way to scan for app installations
|
// mobile_installation.log.0 is my least favorite, most fragile way to scan for app installations
|
||||||
// try this after everything else
|
// try this after everything else
|
||||||
func gatherAppInfoFromInstallLogs() {
|
func gatherAppInfoFromInstallLogs() {
|
||||||
let installLogURL = self.baseURL.URLByAppendingPathComponent("data/Library/Logs/MobileInstallation/mobile_installation.log.0")
|
let installLogURL = self.baseURL.appendingPathComponent("data/Library/Logs/MobileInstallation/mobile_installation.log.0")
|
||||||
|
|
||||||
if let installLog = try? String(contentsOfURL: installLogURL) {
|
if let installLog = try? String(contentsOf: installLogURL) {
|
||||||
let lines = installLog.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
|
let lines = installLog.components(separatedBy: .newlines)
|
||||||
|
|
||||||
for line in lines.reverse() {
|
for line in lines.reversed() {
|
||||||
if !line.containsString("com.apple") {
|
if !line.contains("com.apple") {
|
||||||
if line.containsString("makeContainerLiveReplacingContainer") {
|
if line.contains("makeContainerLiveReplacingContainer") {
|
||||||
self.extractBundleLocationFromLogEntry(line)
|
self.extractBundleLocationFrom(logEntry: line)
|
||||||
}
|
}
|
||||||
if line.containsString("_refreshUUIDForContainer") {
|
if line.contains("_refreshUUIDForContainer") {
|
||||||
self.extractSandboxLocationFromLogEntry(line)
|
self.extractSandboxLocationFrom(logEntry: line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractBundleLocationFromLogEntry(line: String) {
|
func extractBundleLocationFrom(logEntry: String) {
|
||||||
let logComponents = line.componentsSeparatedByString(" ")
|
let logComponents = logEntry.split(separator: (" ")).map({ String($0) })
|
||||||
|
|
||||||
if let bundlePath = logComponents.last {
|
if let bundlePath = logComponents.last {
|
||||||
if let bundleID = logComponents[safe: logComponents.count - 3] {
|
if let bundleID = logComponents[safe: logComponents.count - 3] {
|
||||||
|
|
@ -114,8 +114,8 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSandboxLocationFromLogEntry(line: String) {
|
func extractSandboxLocationFrom(logEntry: String) {
|
||||||
let logComponents = line.componentsSeparatedByString(" ")
|
let logComponents = logEntry.split(separator: (" ")).map({ String($0) })
|
||||||
|
|
||||||
if let sandboxPath = logComponents.last {
|
if let sandboxPath = logComponents.last {
|
||||||
if let bundleID = logComponents[safe: logComponents.count - 5] {
|
if let bundleID = logComponents[safe: logComponents.count - 5] {
|
||||||
|
|
@ -132,7 +132,7 @@ class SimDevice: OutlineProvider, PropertyProvider {
|
||||||
var outlineImage : NSImage? { return nil }
|
var outlineImage : NSImage? { return nil }
|
||||||
var childCount : Int { return self.apps.count }
|
var childCount : Int { return self.apps.count }
|
||||||
|
|
||||||
func childAtIndex(index: Int) -> OutlineProvider? {
|
func childAt(index: Int) -> OutlineProvider? {
|
||||||
return self.apps[index]
|
return self.apps[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,18 @@ class SimOSVersion: OutlineProvider {
|
||||||
|
|
||||||
func completeScan(platformName: String) {
|
func completeScan(platformName: String) {
|
||||||
for device in self.devices {
|
for device in self.devices {
|
||||||
device.completeScan(platformName)
|
device.completeScan(platformName: platformName)
|
||||||
}
|
}
|
||||||
self.devices.sortInPlace { $0.name < $1.name }
|
self.devices.sort(by: { $0.name < $1.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateWithDeviceInfo(deviceInfo: [String : AnyObject], baseURL: NSURL) {
|
func updateWith(deviceInfo: [String : AnyObject], baseURL: URL) {
|
||||||
guard let deviceName = deviceInfo["name"] as? String else { return }
|
guard let deviceName = deviceInfo["name"] as? String else { return }
|
||||||
guard let deviceUDID = deviceInfo["UDID"] as? String else { return }
|
guard let deviceUDID = deviceInfo["UDID"] as? String else { return }
|
||||||
guard var deviceType = deviceInfo["deviceType"] as? String else { return }
|
guard var deviceType = deviceInfo["deviceType"] as? String else { return }
|
||||||
|
|
||||||
deviceType = deviceType.stringByReplacingOccurrencesOfString("com.apple.CoreSimulator.SimDeviceType.", withString: "")
|
deviceType = deviceType.replacingOccurrences(of: "com.apple.CoreSimulator.SimDeviceType.", with: "")
|
||||||
deviceType = deviceType.stringByReplacingOccurrencesOfString("-", withString: " ")
|
deviceType = deviceType.replacingOccurrences(of: "-", with: " ")
|
||||||
|
|
||||||
self.devices.append(SimDevice(name: deviceName, type: deviceType, udid: deviceUDID, baseURL: baseURL))
|
self.devices.append(SimDevice(name: deviceName, type: deviceType, udid: deviceUDID, baseURL: baseURL))
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ class SimOSVersion: OutlineProvider {
|
||||||
var outlineImage : NSImage? { return nil }
|
var outlineImage : NSImage? { return nil }
|
||||||
var childCount : Int { return self.devices.count }
|
var childCount : Int { return self.devices.count }
|
||||||
|
|
||||||
func childAtIndex(index: Int) -> OutlineProvider? {
|
func childAt(index: Int) -> OutlineProvider? {
|
||||||
return self.devices[index]
|
return self.devices[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,23 +13,21 @@ class SimPlatform: OutlineProvider {
|
||||||
var osVersions = [SimOSVersion]()
|
var osVersions = [SimOSVersion]()
|
||||||
|
|
||||||
class func scan() -> [SimPlatform] {
|
class func scan() -> [SimPlatform] {
|
||||||
let fileMgr = NSFileManager.defaultManager()
|
let fileMgr = FileManager.default
|
||||||
var platforms = [SimPlatform]()
|
var platforms = [SimPlatform]()
|
||||||
|
|
||||||
if let libraryURL = fileMgr.URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first {
|
if let libraryURL = fileMgr.urls(for: .libraryDirectory, in: .userDomainMask).first {
|
||||||
let deviceURL = libraryURL.URLByAppendingPathComponent("Developer/CoreSimulator/Devices")
|
let deviceURL = libraryURL.appendingPathComponent("Developer/CoreSimulator/Devices")
|
||||||
|
|
||||||
if let dirEnumerator = fileMgr.enumeratorAtURL(deviceURL, includingPropertiesForKeys: nil, options: [ .SkipsSubdirectoryDescendants, .SkipsHiddenFiles ], errorHandler: nil) {
|
if let dirEnumerator = fileMgr.enumerator(at: deviceURL, includingPropertiesForKeys: nil, options: [ .skipsSubdirectoryDescendants, .skipsHiddenFiles ], errorHandler: nil) {
|
||||||
let dirURLs = dirEnumerator.allObjects.flatMap { $0 as? NSURL }
|
for baseURL in dirEnumerator.allObjects.compactMap({ $0 as? URL }) {
|
||||||
|
let deviceURL = baseURL.appendingPathComponent("device.plist")
|
||||||
for baseURL in dirURLs {
|
guard let deviceInfo = PropertyListSerialization.propertyListWithURL(deviceURL) else { continue }
|
||||||
let deviceURL = baseURL.URLByAppendingPathComponent("device.plist")
|
|
||||||
guard let deviceInfo = NSPropertyListSerialization.propertyListWithURL(deviceURL) else { continue }
|
|
||||||
guard let runtime = deviceInfo["runtime"] as? String else { continue }
|
guard let runtime = deviceInfo["runtime"] as? String else { continue }
|
||||||
let runtimeComponents = runtime.stringByReplacingOccurrencesOfString("com.apple.CoreSimulator.SimRuntime.", withString: "").componentsSeparatedByString("-")
|
let runtimeComponents = runtime.replacingOccurrences(of: "com.apple.CoreSimulator.SimRuntime.", with: "").split(separator: "-").map({ String($0) })
|
||||||
|
|
||||||
if let platformName = runtimeComponents.first {
|
if let platformName = runtimeComponents.first {
|
||||||
let platform = platforms.match({ $0.name == platformName }, orMake: { SimPlatform(runtimeComponents: runtimeComponents, deviceInfo: deviceInfo) })
|
let platform = platforms.match({ $0.name == platformName }, orMake: { SimPlatform(runtimeComponents: runtimeComponents, deviceInfo: deviceInfo) })
|
||||||
|
|
||||||
platform.updateWith(runtimeComponents, deviceInfo: deviceInfo, baseURL: baseURL)
|
platform.updateWith(runtimeComponents, deviceInfo: deviceInfo, baseURL: baseURL)
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +39,7 @@ class SimPlatform: OutlineProvider {
|
||||||
platform.completeScan()
|
platform.completeScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
return platforms.sort { $0.name < $1.name }
|
return platforms.sorted { $0.name < $1.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
init(runtimeComponents: [String], deviceInfo: [String : AnyObject]) {
|
init(runtimeComponents: [String], deviceInfo: [String : AnyObject]) {
|
||||||
|
|
@ -50,16 +48,16 @@ class SimPlatform: OutlineProvider {
|
||||||
|
|
||||||
func completeScan() {
|
func completeScan() {
|
||||||
for osVersion in self.osVersions {
|
for osVersion in self.osVersions {
|
||||||
osVersion.completeScan(self.name)
|
osVersion.completeScan(platformName: self.name)
|
||||||
}
|
}
|
||||||
self.osVersions.sortInPlace { $0.name > $1.name }
|
self.osVersions.sort(by: { $0.name > $1.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateWith(runtimeComponents: [String], deviceInfo: [String : AnyObject], baseURL: NSURL) {
|
func updateWith(_ runtimeComponents: [String], deviceInfo: [String : AnyObject], baseURL: URL) {
|
||||||
let versionID = "\(runtimeComponents[safe: 1] ?? "0").\(runtimeComponents[safe: 2] ?? "0")"
|
let versionID = "\(runtimeComponents[safe: 1] ?? "0").\(runtimeComponents[safe: 2] ?? "0")"
|
||||||
let osVersion = self.osVersions.match({ $0.name == versionID }, orMake: { SimOSVersion(name: versionID, deviceInfo: deviceInfo) })
|
let osVersion = self.osVersions.match({ $0.name == versionID }, orMake: { SimOSVersion(name: versionID, deviceInfo: deviceInfo) })
|
||||||
|
|
||||||
osVersion.updateWithDeviceInfo(deviceInfo, baseURL: baseURL)
|
osVersion.updateWith(deviceInfo: deviceInfo, baseURL: baseURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - OutlineProvider -
|
// MARK: - OutlineProvider -
|
||||||
|
|
@ -68,7 +66,7 @@ class SimPlatform: OutlineProvider {
|
||||||
var outlineImage : NSImage? { return nil }
|
var outlineImage : NSImage? { return nil }
|
||||||
var childCount : Int { return self.osVersions.count }
|
var childCount : Int { return self.osVersions.count }
|
||||||
|
|
||||||
func childAtIndex(index: Int) -> OutlineProvider? {
|
func childAt(index: Int) -> OutlineProvider? {
|
||||||
return self.osVersions[index]
|
return self.osVersions[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension Array {
|
extension Array {
|
||||||
mutating func match(predicate: (Element) -> Bool, orMake: () -> Element) -> Element {
|
mutating func match(_ predicate: (Element) -> Bool, orMake: () -> Element) -> Element {
|
||||||
let element : Element
|
let element : Element
|
||||||
|
|
||||||
if let index = self.indexOf(predicate) {
|
if let match = self.first(where: predicate) {
|
||||||
element = self[index]
|
element = match
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
element = orMake()
|
element = orMake()
|
||||||
|
|
@ -25,27 +25,27 @@ extension Array {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CollectionType {
|
extension Collection {
|
||||||
subscript (safe index: Index) -> Generator.Element? {
|
subscript (safe index: Index) -> Iterator.Element? {
|
||||||
return indices.contains(index) ? self[index] : nil
|
return indices.contains(index) ? self[index] : nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
var validPath : Bool { return NSFileManager.defaultManager().fileExistsAtPath(self) }
|
var validPath : Bool { return FileManager.default.fileExists(atPath: self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NSURL {
|
extension NSURL {
|
||||||
var validPath : Bool { return self.path.map { NSFileManager.defaultManager().fileExistsAtPath($0) } ?? false }
|
var validPath : Bool { return self.path.map { FileManager.default.fileExists(atPath: $0) } ?? false }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NSPropertyListSerialization {
|
extension PropertyListSerialization {
|
||||||
class func propertyListWithURL(url: NSURL) -> [String : AnyObject]? {
|
class func propertyListWithURL(_ url: URL) -> [String : AnyObject]? {
|
||||||
guard let plistData = NSData(contentsOfURL: url) else { return nil }
|
guard let plistData = try? Data(contentsOf: url) else { return nil }
|
||||||
let plist : [String : AnyObject]?
|
let plist : [String : AnyObject]?
|
||||||
|
|
||||||
do {
|
do {
|
||||||
plist = try NSPropertyListSerialization.propertyListWithData(plistData, options: .Immutable, format: nil) as? [String : AnyObject]
|
plist = try PropertyListSerialization.propertyList(from: plistData, options: [], format: nil) as? [String : AnyObject]
|
||||||
} catch {
|
} catch {
|
||||||
plist = nil
|
plist = nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import Cocoa
|
||||||
struct SimProperty {
|
struct SimProperty {
|
||||||
enum Value {
|
enum Value {
|
||||||
case Text(text: String)
|
case Text(text: String)
|
||||||
case Location(url: NSURL)
|
case Location(url: URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
let title : String
|
let title : String
|
||||||
|
|
@ -40,7 +40,7 @@ class DetailController: NSViewController, NSTableViewDataSource, NSTableViewDele
|
||||||
@IBOutlet weak var imageView : NSImageView!
|
@IBOutlet weak var imageView : NSImageView!
|
||||||
@IBOutlet weak var propertyTable : NSTableView!
|
@IBOutlet weak var propertyTable : NSTableView!
|
||||||
let emptyProvider = EmptyProvider()
|
let emptyProvider = EmptyProvider()
|
||||||
var selectedItem : AnyObject? { didSet { self.reload() } }
|
var selectedItem : Any? { didSet { self.reload() } }
|
||||||
var selectedProvider : PropertyProvider { return (self.selectedItem as? PropertyProvider) ?? self.emptyProvider }
|
var selectedProvider : PropertyProvider { return (self.selectedItem as? PropertyProvider) ?? self.emptyProvider }
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
|
@ -57,33 +57,33 @@ class DetailController: NSViewController, NSTableViewDataSource, NSTableViewDele
|
||||||
|
|
||||||
// MARK: - NSTableViewDataSource -
|
// MARK: - NSTableViewDataSource -
|
||||||
|
|
||||||
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
|
func numberOfRows(in tableView: NSTableView) -> Int {
|
||||||
return self.selectedProvider.properties.count ?? 0
|
return self.selectedProvider.properties.count
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - NSTableViewDelegate -
|
// MARK: - NSTableViewDelegate -
|
||||||
|
|
||||||
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||||
let selectedProperty = self.selectedProvider.properties[row]
|
let selectedProperty = self.selectedProvider.properties[row]
|
||||||
let columnIdentifier = tableColumn?.identifier ?? ""
|
let columnIdentifier = tableColumn?.identifier ?? NSUserInterfaceItemIdentifier("")
|
||||||
let view : NSView?
|
let view : NSView?
|
||||||
|
|
||||||
switch columnIdentifier {
|
switch columnIdentifier.rawValue {
|
||||||
case "value":
|
case "value":
|
||||||
switch selectedProperty.value {
|
switch selectedProperty.value {
|
||||||
case .Text(let text):
|
case .Text(let text):
|
||||||
view = tableView.makeViewWithIdentifier("PropertyValueCell", owner: self)
|
view = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("PropertyValueCell"), owner: self)
|
||||||
(view as? NSTableCellView)?.textField?.stringValue = text
|
(view as? NSTableCellView)?.textField?.stringValue = text
|
||||||
|
|
||||||
case .Location(let url):
|
case .Location(let url):
|
||||||
view = tableView.makeViewWithIdentifier("PropertyActionCell", owner: self)
|
view = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("PropertyActionCell"), owner: self)
|
||||||
if let actionCell = view as? ActionCell {
|
if let actionCell = view as? ActionCell {
|
||||||
actionCell.action = { NSWorkspace.sharedWorkspace().activateFileViewerSelectingURLs([url]) }
|
actionCell.action = { NSWorkspace.shared.activateFileViewerSelecting([url]) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
view = tableView.makeViewWithIdentifier("PropertyTitleCell", owner: self)
|
view = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("PropertyTitleCell"), owner: self)
|
||||||
(view as? NSTableCellView)?.textField?.stringValue = selectedProperty.title
|
(view as? NSTableCellView)?.textField?.stringValue = selectedProperty.title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class DetailTableView: NSTableView {
|
class DetailTableView: NSTableView {
|
||||||
override func drawGridInClipRect(clipRect: NSRect) {
|
override func drawGrid(inClipRect: NSRect) {
|
||||||
let lastRowRect = self.rectOfRow(self.numberOfRows - 1)
|
let lastRowRect = self.rect(ofRow: self.numberOfRows - 1)
|
||||||
let adjClipRect = NSRect(x: 0.0, y: 0.0, width: lastRowRect.width, height: lastRowRect.maxY)
|
let adjClipRect = NSRect(x: 0.0, y: 0.0, width: lastRowRect.width, height: lastRowRect.maxY)
|
||||||
|
|
||||||
super.drawGridInClipRect(NSIntersectionRect(clipRect, adjClipRect))
|
super.drawGrid(inClipRect: NSIntersectionRect(inClipRect, adjClipRect))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ protocol OutlineProvider: AnyObject {
|
||||||
var outlineImage : NSImage? { get }
|
var outlineImage : NSImage? { get }
|
||||||
var childCount : Int { get }
|
var childCount : Int { get }
|
||||||
|
|
||||||
func childAtIndex(index: Int) -> OutlineProvider?
|
func childAt(index: Int) -> OutlineProvider?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension OutlineProvider {
|
extension OutlineProvider {
|
||||||
|
|
@ -32,21 +32,21 @@ class SourceController: NSViewController, NSOutlineViewDataSource, NSOutlineView
|
||||||
|
|
||||||
// MARK: - NSOutlineViewDataSource -
|
// MARK: - NSOutlineViewDataSource -
|
||||||
|
|
||||||
func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int {
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
||||||
return (item as? OutlineProvider)?.childCount ?? self.platforms.count
|
return (item as? OutlineProvider)?.childCount ?? self.platforms.count
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject {
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
||||||
return (item as? OutlineProvider)?.childAtIndex(index) ?? self.platforms[index]
|
return (item as? OutlineProvider)?.childAt(index: index) ?? self.platforms[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool {
|
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
||||||
return (item as? OutlineProvider)?.expandable ?? (self.platforms.count > 0)
|
return (item as? OutlineProvider)?.expandable ?? (self.platforms.count > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - NSOutlineViewDelegate -
|
// MARK: - NSOutlineViewDelegate -
|
||||||
|
|
||||||
func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> NSView? {
|
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
||||||
var view : NSTableCellView? = nil
|
var view : NSTableCellView? = nil
|
||||||
var title = ""
|
var title = ""
|
||||||
var image : NSImage? = nil
|
var image : NSImage? = nil
|
||||||
|
|
@ -56,7 +56,7 @@ class SourceController: NSViewController, NSOutlineViewDataSource, NSOutlineView
|
||||||
image = outlineProvider.outlineImage
|
image = outlineProvider.outlineImage
|
||||||
}
|
}
|
||||||
|
|
||||||
if let outlineCell = outlineView.makeViewWithIdentifier(image != nil ? "ImageCell" : "TextCell", owner: self) as? NSTableCellView {
|
if let outlineCell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(image != nil ? "ImageCell" : "TextCell"), owner: self) as? NSTableCellView {
|
||||||
outlineCell.textField?.stringValue = title
|
outlineCell.textField?.stringValue = title
|
||||||
outlineCell.imageView?.image = image
|
outlineCell.imageView?.image = image
|
||||||
view = outlineCell
|
view = outlineCell
|
||||||
|
|
@ -65,17 +65,17 @@ class SourceController: NSViewController, NSOutlineViewDataSource, NSOutlineView
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineView(outlineView: NSOutlineView, heightOfRowByItem item: AnyObject) -> CGFloat {
|
func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
|
||||||
return (item as? OutlineProvider)?.outlineImage != nil ? 24.0 : 20.0
|
return (item as? OutlineProvider)?.outlineImage != nil ? 24.0 : 20.0
|
||||||
}
|
}
|
||||||
|
|
||||||
func outlineViewSelectionDidChange(notification: NSNotification) {
|
func outlineViewSelectionDidChange(_ notification: Notification) {
|
||||||
if let thing = (self.parentViewController as? NSSplitViewController)?.splitViewItems[safe: 1]?.viewController as? DetailController {
|
if let thing = (self.parent as? NSSplitViewController)?.splitViewItems[safe: 1]?.viewController as? DetailController {
|
||||||
var selectedItem : AnyObject? = nil
|
var selectedItem : Any? = nil
|
||||||
let row = self.outlineView.selectedRow
|
let row = self.outlineView.selectedRow
|
||||||
|
|
||||||
if row != NSNotFound {
|
if row != NSNotFound {
|
||||||
selectedItem = self.outlineView.itemAtRow(row)
|
selectedItem = self.outlineView.item(atRow: row)
|
||||||
}
|
}
|
||||||
|
|
||||||
thing.selectedItem = selectedItem
|
thing.selectedItem = selectedItem
|
||||||
|
|
@ -84,7 +84,7 @@ class SourceController: NSViewController, NSOutlineViewDataSource, NSOutlineView
|
||||||
|
|
||||||
// MARK: - Interaction -
|
// MARK: - Interaction -
|
||||||
|
|
||||||
@IBAction func rescan(sender: AnyObject?) {
|
@IBAction func rescan(_ sender: AnyObject?) {
|
||||||
self.platforms = SimPlatform.scan()
|
self.platforms = SimPlatform.scan()
|
||||||
self.outlineView.reloadData()
|
self.outlineView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue