UI layouting done
This commit is contained in:
parent
8486978860
commit
4062b0ed9c
@ -8,12 +8,13 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
E2218C9B1EF2D345004298F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2218C9A1EF2D345004298F6 /* AppDelegate.swift */; };
|
E2218C9B1EF2D345004298F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2218C9A1EF2D345004298F6 /* AppDelegate.swift */; };
|
||||||
E2218C9D1EF2D345004298F6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2218C9C1EF2D345004298F6 /* ViewController.swift */; };
|
|
||||||
E2218CA91EF2D37B004298F6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2218CA81EF2D37B004298F6 /* Assets.xcassets */; };
|
E2218CA91EF2D37B004298F6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2218CA81EF2D37B004298F6 /* Assets.xcassets */; };
|
||||||
E2218CDE1EF2D461004298F6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E2218CDC1EF2D461004298F6 /* MainMenu.xib */; };
|
E2218CDE1EF2D461004298F6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E2218CDC1EF2D461004298F6 /* MainMenu.xib */; };
|
||||||
E2218CDF1EF2D461004298F6 /* SettingsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E2218CDD1EF2D461004298F6 /* SettingsWindowController.xib */; };
|
E2218CDF1EF2D461004298F6 /* SettingsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E2218CDD1EF2D461004298F6 /* SettingsWindowController.xib */; };
|
||||||
E2218CE31EF2D54A004298F6 /* buildnum.ver in Resources */ = {isa = PBXBuildFile; fileRef = E2218CE11EF2D54A004298F6 /* buildnum.ver */; };
|
E2218CE31EF2D54A004298F6 /* buildnum.ver in Resources */ = {isa = PBXBuildFile; fileRef = E2218CE11EF2D54A004298F6 /* buildnum.ver */; };
|
||||||
E2218CE41EF2D54A004298F6 /* BumpBuildNumber.py in Resources */ = {isa = PBXBuildFile; fileRef = E2218CE21EF2D54A004298F6 /* BumpBuildNumber.py */; };
|
E2218CE41EF2D54A004298F6 /* BumpBuildNumber.py in Resources */ = {isa = PBXBuildFile; fileRef = E2218CE21EF2D54A004298F6 /* BumpBuildNumber.py */; };
|
||||||
|
E2218D0D1EF2D68F004298F6 /* XMLDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = E2218D0A1EF2D68F004298F6 /* XMLDictionary.m */; };
|
||||||
|
E2218D111EF2D6F1004298F6 /* SettingsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2218D101EF2D6F1004298F6 /* SettingsWindowController.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -29,13 +30,16 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
E2218C981EF2D345004298F6 /* Logger4.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Logger4.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
E2218C981EF2D345004298F6 /* Logger4.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Logger4.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E2218C9A1EF2D345004298F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
E2218C9A1EF2D345004298F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
E2218C9C1EF2D345004298F6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
|
||||||
E2218CA31EF2D345004298F6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
E2218CA31EF2D345004298F6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
E2218CA81EF2D37B004298F6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
E2218CA81EF2D37B004298F6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
E2218CDC1EF2D461004298F6 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
E2218CDC1EF2D461004298F6 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
||||||
E2218CDD1EF2D461004298F6 /* SettingsWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsWindowController.xib; sourceTree = "<group>"; };
|
E2218CDD1EF2D461004298F6 /* SettingsWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsWindowController.xib; sourceTree = "<group>"; };
|
||||||
E2218CE11EF2D54A004298F6 /* buildnum.ver */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildnum.ver; sourceTree = "<group>"; };
|
E2218CE11EF2D54A004298F6 /* buildnum.ver */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildnum.ver; sourceTree = "<group>"; };
|
||||||
E2218CE21EF2D54A004298F6 /* BumpBuildNumber.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = BumpBuildNumber.py; sourceTree = "<group>"; };
|
E2218CE21EF2D54A004298F6 /* BumpBuildNumber.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = BumpBuildNumber.py; sourceTree = "<group>"; };
|
||||||
|
E2218D051EF2D68F004298F6 /* Logger4-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Logger4-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
E2218D081EF2D68F004298F6 /* XMLDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLDictionary.h; sourceTree = "<group>"; };
|
||||||
|
E2218D0A1EF2D68F004298F6 /* XMLDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMLDictionary.m; sourceTree = "<group>"; };
|
||||||
|
E2218D101EF2D6F1004298F6 /* SettingsWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsWindowController.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -69,10 +73,8 @@
|
|||||||
E2218C991EF2D345004298F6 /* Logger4 */ = {
|
E2218C991EF2D345004298F6 /* Logger4 */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E2218CEB1EF2D648004298F6 /* Swift */,
|
||||||
E2218CDA1EF2D43A004298F6 /* Support Files */,
|
E2218CDA1EF2D43A004298F6 /* Support Files */,
|
||||||
E2218C9A1EF2D345004298F6 /* AppDelegate.swift */,
|
|
||||||
E2218C9C1EF2D345004298F6 /* ViewController.swift */,
|
|
||||||
E2218CA31EF2D345004298F6 /* Info.plist */,
|
|
||||||
);
|
);
|
||||||
path = Logger4;
|
path = Logger4;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -81,6 +83,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2218CA81EF2D37B004298F6 /* Assets.xcassets */,
|
E2218CA81EF2D37B004298F6 /* Assets.xcassets */,
|
||||||
|
E2218D041EF2D67B004298F6 /* Obj-C */,
|
||||||
);
|
);
|
||||||
name = "Shared Resources";
|
name = "Shared Resources";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -88,8 +91,9 @@
|
|||||||
E2218CDA1EF2D43A004298F6 /* Support Files */ = {
|
E2218CDA1EF2D43A004298F6 /* Support Files */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E2218CE01EF2D53D004298F6 /* Versioning */,
|
E2218CA31EF2D345004298F6 /* Info.plist */,
|
||||||
E2218CDB1EF2D443004298F6 /* UI */,
|
E2218CDB1EF2D443004298F6 /* UI */,
|
||||||
|
E2218CE01EF2D53D004298F6 /* Versioning */,
|
||||||
);
|
);
|
||||||
name = "Support Files";
|
name = "Support Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -112,12 +116,47 @@
|
|||||||
name = Versioning;
|
name = Versioning;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E2218CEB1EF2D648004298F6 /* Swift */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E2218D121EF2D754004298F6 /* Delegates */,
|
||||||
|
E2218D0F1EF2D6E5004298F6 /* Views */,
|
||||||
|
);
|
||||||
|
name = Swift;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E2218D041EF2D67B004298F6 /* Obj-C */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E2218D081EF2D68F004298F6 /* XMLDictionary.h */,
|
||||||
|
E2218D0A1EF2D68F004298F6 /* XMLDictionary.m */,
|
||||||
|
E2218D051EF2D68F004298F6 /* Logger4-Bridging-Header.h */,
|
||||||
|
);
|
||||||
|
name = "Obj-C";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E2218D0F1EF2D6E5004298F6 /* Views */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E2218D101EF2D6F1004298F6 /* SettingsWindowController.swift */,
|
||||||
|
);
|
||||||
|
name = Views;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E2218D121EF2D754004298F6 /* Delegates */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E2218C9A1EF2D345004298F6 /* AppDelegate.swift */,
|
||||||
|
);
|
||||||
|
name = Delegates;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXLegacyTarget section */
|
/* Begin PBXLegacyTarget section */
|
||||||
E2218CE51EF2D577004298F6 /* Bump Logger4 */ = {
|
E2218CE51EF2D577004298F6 /* Bump Logger4 */ = {
|
||||||
isa = PBXLegacyTarget;
|
isa = PBXLegacyTarget;
|
||||||
buildArgumentsString = "$PROJECT_DIR/Logger4/BumpBuildNumber.py $PROJECT_DIR/Logger4/buildnum.ver $PROJECT_DIR/Logger3/Info.plist";
|
buildArgumentsString = "$PROJECT_DIR/Logger4/BumpBuildNumber.py $PROJECT_DIR/Logger4/buildnum.ver $PROJECT_DIR/Logger4/Info.plist";
|
||||||
buildConfigurationList = E2218CE61EF2D577004298F6 /* Build configuration list for PBXLegacyTarget "Bump Logger4" */;
|
buildConfigurationList = E2218CE61EF2D577004298F6 /* Build configuration list for PBXLegacyTarget "Bump Logger4" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
);
|
);
|
||||||
@ -163,6 +202,7 @@
|
|||||||
E2218C971EF2D345004298F6 = {
|
E2218C971EF2D345004298F6 = {
|
||||||
CreatedOnToolsVersion = 8.3.3;
|
CreatedOnToolsVersion = 8.3.3;
|
||||||
DevelopmentTeam = 795KPDV76S;
|
DevelopmentTeam = 795KPDV76S;
|
||||||
|
LastSwiftMigration = 0830;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
E2218CE51EF2D577004298F6 = {
|
E2218CE51EF2D577004298F6 = {
|
||||||
@ -211,7 +251,8 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
E2218C9D1EF2D345004298F6 /* ViewController.swift in Sources */,
|
E2218D0D1EF2D68F004298F6 /* XMLDictionary.m in Sources */,
|
||||||
|
E2218D111EF2D6F1004298F6 /* SettingsWindowController.swift in Sources */,
|
||||||
E2218C9B1EF2D345004298F6 /* AppDelegate.swift in Sources */,
|
E2218C9B1EF2D345004298F6 /* AppDelegate.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -323,6 +364,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-L4";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-L4";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEVELOPMENT_TEAM = 795KPDV76S;
|
DEVELOPMENT_TEAM = 795KPDV76S;
|
||||||
@ -331,6 +373,8 @@
|
|||||||
PRODUCT_BUNDLE_IDENTIFIER = com.weebly.alikja.Logger4;
|
PRODUCT_BUNDLE_IDENTIFIER = com.weebly.alikja.Logger4;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Logger4-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@ -339,6 +383,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-L4";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-L4";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEVELOPMENT_TEAM = 795KPDV76S;
|
DEVELOPMENT_TEAM = 795KPDV76S;
|
||||||
@ -347,6 +392,7 @@
|
|||||||
PRODUCT_BUNDLE_IDENTIFIER = com.weebly.alikja.Logger4;
|
PRODUCT_BUNDLE_IDENTIFIER = com.weebly.alikja.Logger4;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Logger4-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 3.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|||||||
6
Logger4-Bridging-Header.h
Normal file
6
Logger4-Bridging-Header.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
//
|
||||||
|
// Use this file to import your target's public headers that you would like to
|
||||||
|
// expose to Swift.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "XMLDictionary.h"
|
||||||
@ -11,16 +11,110 @@ import Cocoa
|
|||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
|
// MARK: - Things that have to be kept alive for the application lifetime
|
||||||
|
// Status Item
|
||||||
|
var statusItem: NSStatusItem = NSStatusItem()
|
||||||
|
// URL Session for DOCSIS data and Internet check
|
||||||
|
let urlSession: URLSession = URLSession(configuration: .default)
|
||||||
|
// Preferences
|
||||||
|
let pref: NSWindowController = NSWindowController(windowNibName: "SettingsWindowController")
|
||||||
|
// Timers
|
||||||
|
var timerFreqs: Timer = Timer()
|
||||||
|
var timerFails: Timer = Timer()
|
||||||
|
// Document content list
|
||||||
|
var content: NSMutableDictionary = NSMutableDictionary()
|
||||||
|
|
||||||
|
// MARK: - Application Lifecycle
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||||
// Insert code here to initialize your application
|
// Show Preferneces if defaults are empty
|
||||||
|
UserDefaults.standard.register(defaults: ["upstream" : "", "downstream" : ""])
|
||||||
|
if UserDefaults.standard.string(forKey: "upstream") == nil || UserDefaults.standard.string(forKey: "downstream") == nil {
|
||||||
|
pref.showWindow(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ aNotification: Notification) {
|
// Set status item
|
||||||
// Insert code here to tear down your application
|
statusItem = NSStatusBar.system().statusItem(withLength: -2)
|
||||||
|
statusItem.title = "AL"
|
||||||
|
// Create status item menu
|
||||||
|
let menu: NSMenu = NSMenu.init()
|
||||||
|
menu.autoenablesItems = false
|
||||||
|
let menuAbout: NSMenuItem = NSMenuItem(title: "About Logger", action: #selector(NSApp.orderFrontStandardAboutPanel(_:)), keyEquivalent: "")
|
||||||
|
let menuQuit: NSMenuItem = NSMenuItem.init(title: "Quit", action: #selector(NSApp.terminate(_:)), keyEquivalent: "q")
|
||||||
|
let menuPref: NSMenuItem = NSMenuItem(title: "Preferences", action: #selector(self.preferences(_:)), keyEquivalent: "")
|
||||||
|
menuPref.image = NSImage(named: NSImageNameActionTemplate)
|
||||||
|
// Layout menu
|
||||||
|
menu.addItem(menuAbout)
|
||||||
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
menu.addItem(menuPref)
|
||||||
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
menu.addItem(menuQuit)
|
||||||
|
// Add menu
|
||||||
|
statusItem.menu = menu
|
||||||
|
|
||||||
|
// Check if directory exists, creat or exit
|
||||||
|
let fileManager = FileManager.default
|
||||||
|
var directory: ObjCBool = ObjCBool(false)
|
||||||
|
let exists: Bool = fileManager.fileExists(atPath: ("~/KDLog" as NSString).expandingTildeInPath, isDirectory: &directory)
|
||||||
|
if exists && directory.boolValue {
|
||||||
|
} else if exists {
|
||||||
|
NSLog("FILE WITH NAME KDLog EXISTS, REMOVE IT")
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
try fileManager.createDirectory(atPath: ("~/KDLog" as NSString).expandingTildeInPath, withIntermediateDirectories: false, attributes: nil)
|
||||||
|
}
|
||||||
|
catch let error as NSError {
|
||||||
|
NSLog("ERROR ON DIRECTORY CREATION: \(error.localizedDescription)")
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init timers
|
||||||
|
if UserDefaults.standard.string(forKey: "upstream") != nil || UserDefaults.standard.string(forKey: "downstream") != nil {
|
||||||
|
initTimers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplicationTerminateReply {
|
||||||
|
urlSession.invalidateAndCancel()
|
||||||
|
return .terminateNow
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Logging Functions
|
||||||
|
|
||||||
|
func logFreqs(_: Timer) {
|
||||||
|
// let frequencyOperation: FrequencyOperation = FrequencyOperation()
|
||||||
|
// OperationQueue.main.addOperation(frequencyOperation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logFails(_: Timer) {
|
||||||
|
// let connectionLossOperation: ConnectionLossOperation = ConnectionLossOperation()
|
||||||
|
// OperationQueue.main.addOperation(connectionLossOperation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - General functions
|
||||||
|
|
||||||
|
func preferences(_ sender: NSMenuItem) {
|
||||||
|
timerFreqs.invalidate()
|
||||||
|
timerFails.invalidate()
|
||||||
|
|
||||||
|
pref.showWindow(sender)
|
||||||
|
pref.window?.makeKeyAndOrderFront(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initTimers() {
|
||||||
|
timerFreqs.invalidate()
|
||||||
|
timerFails.invalidate()
|
||||||
|
|
||||||
|
timerFreqs = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(logFreqs), userInfo: nil, repeats: true)
|
||||||
|
timerFails = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(logFails), userInfo: nil, repeats: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func close(_ sender: NSButton){
|
||||||
|
initTimers()
|
||||||
|
sender.superview?.window?.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,9 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>4.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>6</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
|
|||||||
19
Logger4/SettingsWindowController.swift
Normal file
19
Logger4/SettingsWindowController.swift
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// SettingsWindowController.swift
|
||||||
|
// Logger3
|
||||||
|
//
|
||||||
|
// Created by Kilian Hofmann on 15.08.16.
|
||||||
|
// Copyright © 2016 Kilian Hofmann. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class SettingsWindowController: NSWindowController {
|
||||||
|
|
||||||
|
override func windowDidLoad() {
|
||||||
|
super.windowDidLoad()
|
||||||
|
|
||||||
|
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,11 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11185.3" systemVersion="16A286a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12121" systemVersion="16G16b" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11185.3"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12121"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="SettingsWindowController" customModule="Logger3" customModuleProvider="target">
|
<customObject id="-2" userLabel="File's Owner" customClass="SettingsWindowController" customModule="Logger4" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||||
</connections>
|
</connections>
|
||||||
@ -15,14 +16,14 @@
|
|||||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="480" height="148"/>
|
<rect key="contentRect" x="196" y="240" width="480" height="123"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="800"/>
|
||||||
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
|
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="480" height="148"/>
|
<rect key="frame" x="0.0" y="0.0" width="480" height="123"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ANt-3h-Oyk">
|
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ANt-3h-Oyk">
|
||||||
<rect key="frame" x="157" y="106" width="303" height="22"/>
|
<rect key="frame" x="157" y="81" width="303" height="22"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="ZEi-Jt-cuo">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="ZEi-Jt-cuo">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@ -33,8 +34,8 @@
|
|||||||
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.upstream" id="fxN-Gy-Szs"/>
|
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.upstream" id="fxN-Gy-Szs"/>
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ycn-ts-JLP">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ycn-ts-JLP">
|
||||||
<rect key="frame" x="18" y="106" width="116" height="17"/>
|
<rect key="frame" x="18" y="81" width="116" height="17"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Modem Upstream:" id="lAx-c4-sWO">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Modem Upstream:" id="lAx-c4-sWO">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@ -42,8 +43,8 @@
|
|||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d4L-qo-4wS">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d4L-qo-4wS">
|
||||||
<rect key="frame" x="18" y="74" width="133" height="17"/>
|
<rect key="frame" x="18" y="49" width="133" height="17"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Modem Downstream:" id="oeh-xU-Gg6">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Modem Downstream:" id="oeh-xU-Gg6">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@ -51,8 +52,8 @@
|
|||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9gP-wv-Svk">
|
<textField verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9gP-wv-Svk">
|
||||||
<rect key="frame" x="157" y="74" width="303" height="22"/>
|
<rect key="frame" x="157" y="49" width="303" height="22"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="rGM-TE-sjl">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="rGM-TE-sjl">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
@ -63,40 +64,8 @@
|
|||||||
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.downstream" id="9uX-kn-Xc2"/>
|
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.downstream" id="9uX-kn-Xc2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QL3-SH-xov">
|
|
||||||
<rect key="frame" x="18" y="42" width="34" height="17"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Port:" id="olU-sy-AtO">
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="x6I-cX-Bo8">
|
|
||||||
<rect key="frame" x="157" y="42" width="49" height="22"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="crU-qU-FJL">
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
<connections>
|
|
||||||
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.port" id="RKt-4G-WHW"/>
|
|
||||||
</connections>
|
|
||||||
</textField>
|
|
||||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9I9-2a-L2r">
|
|
||||||
<rect key="frame" x="18" y="18" width="122" height="18"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
|
||||||
<buttonCell key="cell" type="check" title="Autostart Server" bezelStyle="regularSquare" imagePosition="left" inset="2" id="r84-bO-IHn">
|
|
||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
</buttonCell>
|
|
||||||
<connections>
|
|
||||||
<binding destination="aHP-ZZ-xCK" name="value" keyPath="values.autostart" id="bbv-6s-vsL"/>
|
|
||||||
</connections>
|
|
||||||
</button>
|
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vGB-sa-cDA">
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vGB-sa-cDA">
|
||||||
<rect key="frame" x="397" y="13" width="57" height="32"/>
|
<rect key="frame" x="409" y="13" width="57" height="32"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="push" title="Ok" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cDR-9m-MtM">
|
<buttonCell key="cell" type="push" title="Ok" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="cDR-9m-MtM">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
@ -106,23 +75,14 @@
|
|||||||
<action selector="close:" target="Lb6-Mc-rfv" id="Asm-ec-kwu"/>
|
<action selector="close:" target="Lb6-Mc-rfv" id="Asm-ec-kwu"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YLU-XV-sDy">
|
|
||||||
<rect key="frame" x="214" y="42" width="144" height="17"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Requires Server restart" id="EYY-im-3b0">
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
</subviews>
|
</subviews>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||||
</connections>
|
</connections>
|
||||||
<point key="canvasLocation" x="139" y="100"/>
|
<point key="canvasLocation" x="139" y="87.5"/>
|
||||||
</window>
|
</window>
|
||||||
<customObject id="Lb6-Mc-rfv" customClass="AppDelegate" customModule="Logger3" customModuleProvider="target"/>
|
<customObject id="Lb6-Mc-rfv" customClass="AppDelegate" customModule="Logger4" customModuleProvider="target"/>
|
||||||
<userDefaultsController representsSharedInstance="YES" id="aHP-ZZ-xCK"/>
|
<userDefaultsController representsSharedInstance="YES" id="aHP-ZZ-xCK"/>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
//
|
|
||||||
// ViewController.swift
|
|
||||||
// Logger4
|
|
||||||
//
|
|
||||||
// Created by Kilian Hofmann on 15.06.17.
|
|
||||||
// Copyright © 2017 Kilian Hofmann. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
class ViewController: NSViewController {
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
|
||||||
}
|
|
||||||
|
|
||||||
override var representedObject: Any? {
|
|
||||||
didSet {
|
|
||||||
// Update the view, if already loaded.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,2 +1,2 @@
|
|||||||
version 4.0
|
version 4.0
|
||||||
build 1
|
build 6
|
||||||
|
|||||||
103
XMLDictionary.h
Executable file
103
XMLDictionary.h
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// XMLDictionary.h
|
||||||
|
//
|
||||||
|
// Version 1.4
|
||||||
|
//
|
||||||
|
// Created by Nick Lockwood on 15/11/2010.
|
||||||
|
// Copyright 2010 Charcoal Design. All rights reserved.
|
||||||
|
//
|
||||||
|
// Get the latest version of XMLDictionary from here:
|
||||||
|
//
|
||||||
|
// https://github.com/nicklockwood/XMLDictionary
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, XMLDictionaryAttributesMode) {
|
||||||
|
XMLDictionaryAttributesModePrefixed = 0, // default
|
||||||
|
XMLDictionaryAttributesModeDictionary,
|
||||||
|
XMLDictionaryAttributesModeUnprefixed,
|
||||||
|
XMLDictionaryAttributesModeDiscard
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, XMLDictionaryNodeNameMode) {
|
||||||
|
XMLDictionaryNodeNameModeRootOnly = 0, // default
|
||||||
|
XMLDictionaryNodeNameModeAlways,
|
||||||
|
XMLDictionaryNodeNameModeNever
|
||||||
|
};
|
||||||
|
|
||||||
|
static NSString *const XMLDictionaryAttributesKey = @"__attributes";
|
||||||
|
static NSString *const XMLDictionaryCommentsKey = @"__comments";
|
||||||
|
static NSString *const XMLDictionaryTextKey = @"__text";
|
||||||
|
static NSString *const XMLDictionaryNodeNameKey = @"__name";
|
||||||
|
static NSString *const XMLDictionaryAttributePrefix = @"_";
|
||||||
|
|
||||||
|
@interface XMLDictionaryParser : NSObject <NSCopying>
|
||||||
|
|
||||||
|
+ (XMLDictionaryParser *)sharedInstance;
|
||||||
|
|
||||||
|
@property(nonatomic, assign) BOOL collapseTextNodes; // defaults to YES
|
||||||
|
@property(nonatomic, assign) BOOL stripEmptyNodes; // defaults to YES
|
||||||
|
@property(nonatomic, assign) BOOL trimWhiteSpace; // defaults to YES
|
||||||
|
@property(nonatomic, assign) BOOL alwaysUseArrays; // defaults to NO
|
||||||
|
@property(nonatomic, assign) BOOL preserveComments; // defaults to NO
|
||||||
|
@property(nonatomic, assign) BOOL wrapRootNode; // defaults to NO
|
||||||
|
|
||||||
|
@property(nonatomic, assign) XMLDictionaryAttributesMode attributesMode;
|
||||||
|
@property(nonatomic, assign) XMLDictionaryNodeNameMode nodeNameMode;
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser;
|
||||||
|
- (NSDictionary *)dictionaryWithData:(NSData *)data;
|
||||||
|
- (NSDictionary *)dictionaryWithString:(NSString *)string;
|
||||||
|
- (NSDictionary *)dictionaryWithFile:(NSString *)path;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSDictionary (XMLDictionary)
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser;
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLData:(NSData *)data;
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLString:(NSString *)string;
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path;
|
||||||
|
|
||||||
|
- (NSDictionary *)attributes;
|
||||||
|
- (NSDictionary *)childNodes;
|
||||||
|
- (NSArray *)comments;
|
||||||
|
- (NSString *)nodeName;
|
||||||
|
- (NSString *)innerText;
|
||||||
|
- (NSString *)innerXML;
|
||||||
|
- (NSString *)XMLString;
|
||||||
|
|
||||||
|
- (NSArray *)arrayValueForKeyPath:(NSString *)keyPath;
|
||||||
|
- (NSString *)stringValueForKeyPath:(NSString *)keyPath;
|
||||||
|
- (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSString (XMLDictionary)
|
||||||
|
|
||||||
|
- (NSString *)XMLEncodedString;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
485
XMLDictionary.m
Executable file
485
XMLDictionary.m
Executable file
@ -0,0 +1,485 @@
|
|||||||
|
//
|
||||||
|
// XMLDictionary.m
|
||||||
|
//
|
||||||
|
// Version 1.4
|
||||||
|
//
|
||||||
|
// Created by Nick Lockwood on 15/11/2010.
|
||||||
|
// Copyright 2010 Charcoal Design. All rights reserved.
|
||||||
|
//
|
||||||
|
// Get the latest version of XMLDictionary from here:
|
||||||
|
//
|
||||||
|
// https://github.com/nicklockwood/XMLDictionary
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "XMLDictionary.h"
|
||||||
|
|
||||||
|
#pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis"
|
||||||
|
#pragma GCC diagnostic ignored "-Wdirect-ivar-access"
|
||||||
|
#pragma GCC diagnostic ignored "-Wformat-non-iso"
|
||||||
|
#pragma GCC diagnostic ignored "-Wgnu"
|
||||||
|
|
||||||
|
#import <Availability.h>
|
||||||
|
#if !__has_feature(objc_arc)
|
||||||
|
#error This class requires automatic reference counting
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface XMLDictionaryParser () <NSXMLParserDelegate>
|
||||||
|
|
||||||
|
@property(nonatomic, strong) NSMutableDictionary *root;
|
||||||
|
@property(nonatomic, strong) NSMutableArray *stack;
|
||||||
|
@property(nonatomic, strong) NSMutableString *text;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation XMLDictionaryParser
|
||||||
|
|
||||||
|
+ (XMLDictionaryParser *)sharedInstance {
|
||||||
|
static dispatch_once_t once;
|
||||||
|
static XMLDictionaryParser *sharedInstance;
|
||||||
|
dispatch_once(&once, ^{
|
||||||
|
|
||||||
|
sharedInstance = [[XMLDictionaryParser alloc] init];
|
||||||
|
});
|
||||||
|
return sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)init {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_collapseTextNodes = YES;
|
||||||
|
_stripEmptyNodes = YES;
|
||||||
|
_trimWhiteSpace = YES;
|
||||||
|
_alwaysUseArrays = NO;
|
||||||
|
_preserveComments = NO;
|
||||||
|
_wrapRootNode = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)copyWithZone:(NSZone *)zone {
|
||||||
|
XMLDictionaryParser *copy = [[[self class] allocWithZone:zone] init];
|
||||||
|
copy.collapseTextNodes = _collapseTextNodes;
|
||||||
|
copy.stripEmptyNodes = _stripEmptyNodes;
|
||||||
|
copy.trimWhiteSpace = _trimWhiteSpace;
|
||||||
|
copy.alwaysUseArrays = _alwaysUseArrays;
|
||||||
|
copy.preserveComments = _preserveComments;
|
||||||
|
copy.attributesMode = _attributesMode;
|
||||||
|
copy.nodeNameMode = _nodeNameMode;
|
||||||
|
copy.wrapRootNode = _wrapRootNode;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryWithParser:(NSXMLParser *)parser {
|
||||||
|
[parser setDelegate:self];
|
||||||
|
[parser parse];
|
||||||
|
id result = _root;
|
||||||
|
_root = nil;
|
||||||
|
_stack = nil;
|
||||||
|
_text = nil;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryWithData:(NSData *)data {
|
||||||
|
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
|
||||||
|
return [self dictionaryWithParser:parser];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryWithString:(NSString *)string {
|
||||||
|
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
return [self dictionaryWithData:data];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryWithFile:(NSString *)path {
|
||||||
|
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||||
|
return [self dictionaryWithData:data];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)XMLStringForNode:(id)node withNodeName:(NSString *)nodeName {
|
||||||
|
if ([node isKindOfClass:[NSArray class]]) {
|
||||||
|
NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:[node count]];
|
||||||
|
for (id individualNode in node) {
|
||||||
|
[nodes addObject:[self XMLStringForNode:individualNode
|
||||||
|
withNodeName:nodeName]];
|
||||||
|
}
|
||||||
|
return [nodes componentsJoinedByString:@"\n"];
|
||||||
|
} else if ([node isKindOfClass:[NSDictionary class]]) {
|
||||||
|
NSDictionary *attributes = [(NSDictionary *)node attributes];
|
||||||
|
NSMutableString *attributeString = [NSMutableString string];
|
||||||
|
for (NSString *key in [attributes allKeys]) {
|
||||||
|
[attributeString
|
||||||
|
appendFormat:@" %@=\"%@\"",
|
||||||
|
[[key description] XMLEncodedString],
|
||||||
|
[[attributes[key] description] XMLEncodedString]];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *innerXML = [node innerXML];
|
||||||
|
if ([innerXML length]) {
|
||||||
|
return
|
||||||
|
[NSString stringWithFormat:@"<%1$@%2$@>%3$@</%1$@>", nodeName,
|
||||||
|
attributeString, innerXML];
|
||||||
|
} else {
|
||||||
|
return [NSString
|
||||||
|
stringWithFormat:@"<%@%@/>", nodeName, attributeString];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
[NSString stringWithFormat:@"<%1$@>%2$@</%1$@>", nodeName,
|
||||||
|
[[node description] XMLEncodedString]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)endText {
|
||||||
|
if (_trimWhiteSpace) {
|
||||||
|
_text = [[_text stringByTrimmingCharactersInSet:
|
||||||
|
[NSCharacterSet whitespaceAndNewlineCharacterSet]]
|
||||||
|
mutableCopy];
|
||||||
|
}
|
||||||
|
if ([_text length]) {
|
||||||
|
NSMutableDictionary *top = [_stack lastObject];
|
||||||
|
id existing = top[XMLDictionaryTextKey];
|
||||||
|
if ([existing isKindOfClass:[NSArray class]]) {
|
||||||
|
[existing addObject:_text];
|
||||||
|
} else if (existing) {
|
||||||
|
top[XMLDictionaryTextKey] = [@[ existing, _text ] mutableCopy];
|
||||||
|
} else {
|
||||||
|
top[XMLDictionaryTextKey] = _text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_text = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addText:(NSString *)text {
|
||||||
|
if (!_text) {
|
||||||
|
_text = [NSMutableString stringWithString:text];
|
||||||
|
} else {
|
||||||
|
[_text appendString:text];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)parser:(__unused NSXMLParser *)parser
|
||||||
|
didStartElement:(NSString *)elementName
|
||||||
|
namespaceURI:(__unused NSString *)namespaceURI
|
||||||
|
qualifiedName:(__unused NSString *)qName
|
||||||
|
attributes:(NSDictionary *)attributeDict {
|
||||||
|
[self endText];
|
||||||
|
|
||||||
|
NSMutableDictionary *node = [NSMutableDictionary dictionary];
|
||||||
|
switch (_nodeNameMode) {
|
||||||
|
case XMLDictionaryNodeNameModeRootOnly: {
|
||||||
|
if (!_root) {
|
||||||
|
node[XMLDictionaryNodeNameKey] = elementName;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMLDictionaryNodeNameModeAlways: {
|
||||||
|
node[XMLDictionaryNodeNameKey] = elementName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMLDictionaryNodeNameModeNever: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([attributeDict count]) {
|
||||||
|
switch (_attributesMode) {
|
||||||
|
case XMLDictionaryAttributesModePrefixed: {
|
||||||
|
for (NSString *key in [attributeDict allKeys]) {
|
||||||
|
node[[XMLDictionaryAttributePrefix
|
||||||
|
stringByAppendingString:key]] = attributeDict[key];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMLDictionaryAttributesModeDictionary: {
|
||||||
|
node[XMLDictionaryAttributesKey] = attributeDict;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMLDictionaryAttributesModeUnprefixed: {
|
||||||
|
[node addEntriesFromDictionary:attributeDict];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMLDictionaryAttributesModeDiscard: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_root) {
|
||||||
|
_root = node;
|
||||||
|
_stack = [NSMutableArray arrayWithObject:node];
|
||||||
|
if (_wrapRootNode) {
|
||||||
|
_root = [NSMutableDictionary dictionaryWithObject:_root
|
||||||
|
forKey:elementName];
|
||||||
|
[_stack insertObject:_root atIndex:0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NSMutableDictionary *top = [_stack lastObject];
|
||||||
|
id existing = top[elementName];
|
||||||
|
if ([existing isKindOfClass:[NSArray class]]) {
|
||||||
|
[existing addObject:node];
|
||||||
|
} else if (existing) {
|
||||||
|
top[elementName] = [@[ existing, node ] mutableCopy];
|
||||||
|
} else if (_alwaysUseArrays) {
|
||||||
|
top[elementName] = [NSMutableArray arrayWithObject:node];
|
||||||
|
} else {
|
||||||
|
top[elementName] = node;
|
||||||
|
}
|
||||||
|
[_stack addObject:node];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)nameForNode:(NSDictionary *)node
|
||||||
|
inDictionary:(NSDictionary *)dict {
|
||||||
|
if (node.nodeName) {
|
||||||
|
return node.nodeName;
|
||||||
|
} else {
|
||||||
|
for (NSString *name in dict) {
|
||||||
|
id object = dict[name];
|
||||||
|
if (object == node) {
|
||||||
|
return name;
|
||||||
|
} else if ([object isKindOfClass:[NSArray class]] &&
|
||||||
|
[object containsObject:node]) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)parser:(__unused NSXMLParser *)parser
|
||||||
|
didEndElement:(__unused NSString *)elementName
|
||||||
|
namespaceURI:(__unused NSString *)namespaceURI
|
||||||
|
qualifiedName:(__unused NSString *)qName {
|
||||||
|
[self endText];
|
||||||
|
|
||||||
|
NSMutableDictionary *top = [_stack lastObject];
|
||||||
|
[_stack removeLastObject];
|
||||||
|
|
||||||
|
if (!top.attributes && !top.childNodes && !top.comments) {
|
||||||
|
NSMutableDictionary *newTop = [_stack lastObject];
|
||||||
|
NSString *nodeName = [self nameForNode:top inDictionary:newTop];
|
||||||
|
if (nodeName) {
|
||||||
|
id parentNode = newTop[nodeName];
|
||||||
|
if (top.innerText && _collapseTextNodes) {
|
||||||
|
if ([parentNode isKindOfClass:[NSArray class]]) {
|
||||||
|
parentNode[[parentNode count] - 1] = top.innerText;
|
||||||
|
} else {
|
||||||
|
newTop[nodeName] = top.innerText;
|
||||||
|
}
|
||||||
|
} else if (!top.innerText && _stripEmptyNodes) {
|
||||||
|
if ([parentNode isKindOfClass:[NSArray class]]) {
|
||||||
|
[parentNode removeLastObject];
|
||||||
|
} else {
|
||||||
|
[newTop removeObjectForKey:nodeName];
|
||||||
|
}
|
||||||
|
} else if (!top.innerText && !_collapseTextNodes &&
|
||||||
|
!_stripEmptyNodes) {
|
||||||
|
top[XMLDictionaryTextKey] = @"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)parser:(__unused NSXMLParser *)parser
|
||||||
|
foundCharacters:(NSString *)string {
|
||||||
|
[self addText:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)parser:(__unused NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock {
|
||||||
|
[self addText:[[NSString alloc] initWithData:CDATABlock
|
||||||
|
encoding:NSUTF8StringEncoding]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)parser:(__unused NSXMLParser *)parser foundComment:(NSString *)comment {
|
||||||
|
if (_preserveComments) {
|
||||||
|
NSMutableDictionary *top = [_stack lastObject];
|
||||||
|
NSMutableArray *comments = top[XMLDictionaryCommentsKey];
|
||||||
|
if (!comments) {
|
||||||
|
comments = [@[ comment ] mutableCopy];
|
||||||
|
top[XMLDictionaryCommentsKey] = comments;
|
||||||
|
} else {
|
||||||
|
[comments addObject:comment];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSDictionary (XMLDictionary)
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLParser:(NSXMLParser *)parser {
|
||||||
|
return [[[XMLDictionaryParser sharedInstance] copy]
|
||||||
|
dictionaryWithParser:parser];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLData:(NSData *)data {
|
||||||
|
return
|
||||||
|
[[[XMLDictionaryParser sharedInstance] copy] dictionaryWithData:data];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLString:(NSString *)string {
|
||||||
|
return [[[XMLDictionaryParser sharedInstance] copy]
|
||||||
|
dictionaryWithString:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)dictionaryWithXMLFile:(NSString *)path {
|
||||||
|
return
|
||||||
|
[[[XMLDictionaryParser sharedInstance] copy] dictionaryWithFile:path];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)attributes {
|
||||||
|
NSDictionary *attributes = self[XMLDictionaryAttributesKey];
|
||||||
|
if (attributes) {
|
||||||
|
return [attributes count] ? attributes : nil;
|
||||||
|
} else {
|
||||||
|
NSMutableDictionary *filteredDict =
|
||||||
|
[NSMutableDictionary dictionaryWithDictionary:self];
|
||||||
|
[filteredDict removeObjectsForKeys:@[
|
||||||
|
XMLDictionaryCommentsKey,
|
||||||
|
XMLDictionaryTextKey,
|
||||||
|
XMLDictionaryNodeNameKey
|
||||||
|
]];
|
||||||
|
for (NSString *key in [filteredDict allKeys]) {
|
||||||
|
[filteredDict removeObjectForKey:key];
|
||||||
|
if ([key hasPrefix:XMLDictionaryAttributePrefix]) {
|
||||||
|
filteredDict[[key
|
||||||
|
substringFromIndex:[XMLDictionaryAttributePrefix length]]] =
|
||||||
|
self[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [filteredDict count] ? filteredDict : nil;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)childNodes {
|
||||||
|
NSMutableDictionary *filteredDict = [self mutableCopy];
|
||||||
|
[filteredDict removeObjectsForKeys:@[
|
||||||
|
XMLDictionaryAttributesKey,
|
||||||
|
XMLDictionaryCommentsKey,
|
||||||
|
XMLDictionaryTextKey,
|
||||||
|
XMLDictionaryNodeNameKey
|
||||||
|
]];
|
||||||
|
for (NSString *key in [filteredDict allKeys]) {
|
||||||
|
if ([key hasPrefix:XMLDictionaryAttributePrefix]) {
|
||||||
|
[filteredDict removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [filteredDict count] ? filteredDict : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)comments {
|
||||||
|
return self[XMLDictionaryCommentsKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)nodeName {
|
||||||
|
return self[XMLDictionaryNodeNameKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)innerText {
|
||||||
|
id text = self[XMLDictionaryTextKey];
|
||||||
|
if ([text isKindOfClass:[NSArray class]]) {
|
||||||
|
return [text componentsJoinedByString:@"\n"];
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)innerXML {
|
||||||
|
NSMutableArray *nodes = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (NSString *comment in [self comments]) {
|
||||||
|
[nodes
|
||||||
|
addObject:[NSString stringWithFormat:@"<!--%@-->",
|
||||||
|
[comment XMLEncodedString]]];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary *childNodes = [self childNodes];
|
||||||
|
for (NSString *key in childNodes) {
|
||||||
|
[nodes addObject:[XMLDictionaryParser XMLStringForNode:childNodes[key]
|
||||||
|
withNodeName:key]];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *text = [self innerText];
|
||||||
|
if (text) {
|
||||||
|
[nodes addObject:[text XMLEncodedString]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [nodes componentsJoinedByString:@"\n"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)XMLString {
|
||||||
|
if ([self count] == 1 && ![self nodeName]) {
|
||||||
|
// ignore outermost dictionary
|
||||||
|
return [self innerXML];
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
[XMLDictionaryParser XMLStringForNode:self
|
||||||
|
withNodeName:[self nodeName] ?: @"root"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)arrayValueForKeyPath:(NSString *)keyPath {
|
||||||
|
id value = [self valueForKeyPath:keyPath];
|
||||||
|
if (value && ![value isKindOfClass:[NSArray class]]) {
|
||||||
|
return @[ value ];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)stringValueForKeyPath:(NSString *)keyPath {
|
||||||
|
id value = [self valueForKeyPath:keyPath];
|
||||||
|
if ([value isKindOfClass:[NSArray class]]) {
|
||||||
|
value = [value count] ? value[0] : nil;
|
||||||
|
}
|
||||||
|
if ([value isKindOfClass:[NSDictionary class]]) {
|
||||||
|
return [(NSDictionary *)value innerText];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictionaryValueForKeyPath:(NSString *)keyPath {
|
||||||
|
id value = [self valueForKeyPath:keyPath];
|
||||||
|
if ([value isKindOfClass:[NSArray class]]) {
|
||||||
|
value = [value count] ? value[0] : nil;
|
||||||
|
}
|
||||||
|
if ([value isKindOfClass:[NSString class]]) {
|
||||||
|
return @{XMLDictionaryTextKey : value};
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSString (XMLDictionary)
|
||||||
|
|
||||||
|
- (NSString *)XMLEncodedString {
|
||||||
|
return
|
||||||
|
[[[[[self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]
|
||||||
|
stringByReplacingOccurrencesOfString:@"<"
|
||||||
|
withString:@"<"]
|
||||||
|
stringByReplacingOccurrencesOfString:@">"
|
||||||
|
withString:@">"]
|
||||||
|
stringByReplacingOccurrencesOfString:@"\""
|
||||||
|
withString:@"""]
|
||||||
|
stringByReplacingOccurrencesOfString:@"\'"
|
||||||
|
withString:@"'"];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Loading…
x
Reference in New Issue
Block a user