├── .cocoadocs.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Cartfile ├── Cartfile.resolved ├── LICENSE ├── README.md ├── Scripts └── release.sh ├── XCDLumberjackNSLogger Demo ├── XCDLumberjackNSLogger Demo.xcodeproj │ └── project.pbxproj └── iOS Demo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── BonjourClientsTableViewController.h │ ├── BonjourClientsTableViewController.m │ ├── Info.plist │ ├── MainViewController.h │ ├── MainViewController.m │ ├── Settings.bundle │ └── Root.plist │ └── main.m ├── XCDLumberjackNSLogger.podspec ├── XCDLumberjackNSLogger.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── XCDLumberjackNSLogger OS X.xcscheme │ ├── XCDLumberjackNSLogger iOS.xcscheme │ └── XCDLumberjackNSLogger tvOS.xcscheme ├── XCDLumberjackNSLogger.xcworkspace └── contents.xcworkspacedata └── XCDLumberjackNSLogger ├── AppledocSettings.plist ├── Info.plist ├── XCDLumberjackNSLogger.h └── XCDLumberjackNSLogger.m /.cocoadocs.yml: -------------------------------------------------------------------------------- 1 | explicit-references: true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | RELEASE_NOTES.md 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Carthage/Checkouts/CocoaLumberjack"] 2 | path = Carthage/Checkouts/CocoaLumberjack 3 | url = https://github.com/CocoaLumberjack/CocoaLumberjack.git 4 | [submodule "Carthage/Checkouts/NSLogger"] 5 | path = Carthage/Checkouts/NSLogger 6 | url = https://github.com/fpillet/NSLogger.git 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### Version 1.1.1 2 | 3 | * Support for CocoaLumberjack 3.0.0 by loosening dependencies’ version requirements (#8) 4 | 5 | #### Version 1.1.0 6 | 7 | * XCDLumberjackNSLogger builds as a framework and is therefore compatible with Carthage (#1) 8 | * tvOS support 9 | * Use filename as tag if no context to tag mapping is found (#5) 10 | * New method to automatically bind a XCDLumberjackNSLogger instance to user defaults 11 | 12 | #### Version 1.0.2 13 | 14 | * XCDLumberjackNSLogger is less strict about CocoaLumberjack and NSLogger required versions 15 | 16 | #### Version 1.0.1 17 | 18 | * Log pretty printed NSData as data 19 | * Use proper thread identifier and queue name 20 | * Added a `debugDescription` implementation 21 | 22 | #### Version 1.0.0 23 | 24 | * Initial version 25 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "CocoaLumberjack/CocoaLumberjack" >= 2.2 2 | github "fpillet/NSLogger" >= 1.7 3 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "CocoaLumberjack/CocoaLumberjack" "3.0.0" 2 | github "fpillet/NSLogger" "v1.7.0" 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Cédric Luthi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | [![Platform](https://img.shields.io/cocoapods/p/XCDLumberjackNSLogger.svg?style=flat)](http://cocoadocs.org/docsets/XCDLumberjackNSLogger/) 4 | [![Pod Version](https://img.shields.io/cocoapods/v/XCDLumberjackNSLogger.svg?style=flat)](http://cocoadocs.org/docsets/XCDLumberjackNSLogger/) 5 | [![License](https://img.shields.io/cocoapods/l/XCDLumberjackNSLogger.svg?style=flat)](LICENSE) 6 | 7 | **XCDLumberjackNSLogger** is a [CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack) logger which sends logs to [NSLogger](https://github.com/fpillet/NSLogger). 8 | 9 | ## Requirements 10 | 11 | - Runs on iOS 8.0 and later 12 | - Runs on OS X 10.10 and later 13 | - Runs on tvOS 9.0 and later 14 | 15 | ## Installation 16 | 17 | XCDLumberjackNSLogger is available through CocoaPods and Carthage. 18 | 19 | CocoaPods: 20 | 21 | ```ruby 22 | pod "XCDLumberjackNSLogger", "~> 1.1" 23 | ``` 24 | 25 | Carthage: 26 | 27 | ```objc 28 | github "0xced/XCDLumberjackNSLogger" ~> 1.1 29 | ``` 30 | 31 | ## Usage 32 | 33 | XCDLumberjackNSLogger is [fully documented](http://cocoadocs.org/docsets/XCDLumberjackNSLogger/). 34 | 35 | #### Binding to User Defaults 36 | 37 | The easiest way to use XCDLumberjackNSLogger is to bind a logger to a user defaults key. 38 | 39 | ```objc 40 | [XCDLumberjackNSLogger bindToBonjourServiceNameUserDefaultsKey:@"NSLoggerBonjourServiceName" configurationHandler:nil]; 41 | ``` 42 | 43 | Anytime you change the user defaults key (`NSLoggerBonjourServiceName` in this example), the logger reconnects to the desktop viewer with the given service name. 44 | 45 | You can change the service name user defaults manually with 46 | 47 | ```objc 48 | [[NSUserDefaults standardUserDefaults] setObject:serviceName forKey:@"NSLoggerBonjourServiceName"]; 49 | ``` 50 | 51 | or with a [Settings bundle][1]: 52 | 53 | ```xml 54 | 55 | AutocapitalizationType 56 | None 57 | AutocorrectionType 58 | No 59 | DefaultValue 60 | 61 | IsSecure 62 | 63 | Key 64 | NSLoggerBonjourServiceName 65 | KeyboardType 66 | Alphabet 67 | Title 68 | NSLogger Service Name 69 | Type 70 | PSTextFieldSpecifier 71 | 72 | ``` 73 | 74 | This is very handy to get logs even in the App Store with zero overhead. Just open the settings of your app (in the iOS Settings app) and change the service name to automatically activate the logger. 75 | 76 | When debugging with Xcode you can set `-NSLoggerBonjourServiceName "Your Service Name"` in *Arguments Passed On Launch* [in your scheme][2] to set the `NSLoggerBonjourServiceName` user default. 77 | 78 | #### Simply send logs to NSLogger 79 | 80 | ```objc 81 | [DDLog addLogger:[XCDLumberjackNSLogger new]]; 82 | ``` 83 | 84 | #### Configuring a bonjour service name 85 | 86 | ```objc 87 | NSString *bonjourServiceName = [[[NSProcessInfo processInfo] environment] objectForKey:@"NSLOGGER_BONJOUR_SERVICE_NAME"]; 88 | [DDLog addLogger:[[XCDLumberjackNSLogger alloc] initWithBonjourServiceName:bonjourServiceName]]; 89 | ``` 90 | 91 | #### Translating contexts to tags 92 | 93 | ```objc 94 | XCDLumberjackNSLogger *logger = [XCDLumberjackNSLogger new]; 95 | logger.tags = @{ @80 : @"CocoaHTTPServer", @((NSInteger)0xced70676) : @"XCDYouTubeKit" }; 96 | [DDLog addLogger:logger]; 97 | ``` 98 | 99 | #### Configuring a viewer host 100 | 101 | ```objc 102 | XCDLumberjackNSLogger *logger = [XCDLumberjackNSLogger new]; 103 | LoggerSetViewerHost(logger.logger, CFSTR("10.0.1.7"), 50000); 104 | [DDLog addLogger:logger]; 105 | ``` 106 | 107 | ## Contact 108 | 109 | Cédric Luthi 110 | 111 | - http://github.com/0xced 112 | - http://twitter.com/0xced 113 | 114 | ## License 115 | 116 | XCDLumberjackNSLogger is available under the MIT license. See the [LICENSE](LICENSE) file for more information. 117 | 118 | [1]: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html 119 | [2]: https://developer.apple.com/library/ios/recipes/xcode_help-scheme_editor/Articles/SchemeRun.html 120 | -------------------------------------------------------------------------------- /Scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | PROJECT_NAME=XCDLumberjackNSLogger 4 | 5 | if [[ $# -ne 1 ]]; then 6 | echo "usage: $0 VERSION" 7 | exit 1 8 | fi 9 | 10 | VERSION=$1 11 | VERSION_PARTS=(${VERSION//./ }) 12 | 13 | grep "#### Version ${VERSION}" RELEASE_NOTES.md > /dev/null || (echo "RELEASE_NOTES.md must contain release notes for version ${VERSION}" && exit 1) 14 | 15 | git flow release start ${VERSION} 16 | 17 | echo "Updating CHANGELOG" 18 | echo -e "$(cat RELEASE_NOTES.md)\n\n$(cat CHANGELOG.md)" > CHANGELOG.md 19 | git add CHANGELOG.md 20 | git commit -m "Update CHANGELOG for version ${VERSION}" 21 | 22 | echo "Updating version" 23 | CURRENT_PROJECT_VERSION=$(xcodebuild -project "${PROJECT_NAME}.xcodeproj" -showBuildSettings | awk '/CURRENT_PROJECT_VERSION/{print $3}') 24 | CURRENT_PROJECT_VERSION=$(expr ${CURRENT_PROJECT_VERSION} + 1) 25 | set -v 26 | sed -i "" "s/DYLIB_CURRENT_VERSION = .*;/DYLIB_CURRENT_VERSION = ${VERSION};/g" "${PROJECT_NAME}.xcodeproj/project.pbxproj" 27 | sed -i "" "s/CURRENT_PROJECT_VERSION = .*;/CURRENT_PROJECT_VERSION = ${CURRENT_PROJECT_VERSION};/g" "${PROJECT_NAME}.xcodeproj/project.pbxproj" 28 | sed -i "" "s/CURRENT_PROJECT_VERSION = .*;/CURRENT_PROJECT_VERSION = ${VERSION};/g" "${PROJECT_NAME} Demo/${PROJECT_NAME} Demo.xcodeproj/project.pbxproj" 29 | sed -i "" "s/^\(.*s.version.*=.*\)\".*\"/\1\"${VERSION}\"/" "${PROJECT_NAME}.podspec" 30 | sed -E -i "" "s/~> [0-9\.]+/~> ${VERSION_PARTS[0]}.${VERSION_PARTS[1]}/g" "README.md" 31 | set +v 32 | git add "${PROJECT_NAME}.xcodeproj" 33 | git add "${PROJECT_NAME} Demo/${PROJECT_NAME} Demo.xcodeproj" 34 | git add "${PROJECT_NAME}.podspec" 35 | git add "README.md" 36 | git commit -m "Update version to ${VERSION}" 37 | 38 | # allow warnings until https://github.com/CocoaPods/CocoaPods/issues/5188 is resolved 39 | pod lib lint --allow-warnings ${PROJECT_NAME}.podspec 40 | 41 | GIT_MERGE_AUTOEDIT=no git flow release finish -s -f RELEASE_NOTES.md ${VERSION} 42 | 43 | echo -e "#### Version X.Y.Z\n\n* " > RELEASE_NOTES.md 44 | 45 | echo "Things remaining to do" 46 | echo " * git push with tags (master and develop)" 47 | echo " * pod trunk push ${PROJECT_NAME}.podspec" 48 | echo " * create a new release on GitHub: https://github.com/0xced/${PROJECT_NAME}/releases/new" 49 | echo " * close milestone on GitHub if applicable: https://github.com/0xced/${PROJECT_NAME}/milestones" 50 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/XCDLumberjackNSLogger Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C2077F5F1CCFA00900E02C9B /* BonjourClientsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C2077F5E1CCFA00900E02C9B /* BonjourClientsTableViewController.m */; }; 11 | C2077F611CCFC78600E02C9B /* XCDLumberjackNSLogger.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = C259B0D81CCE81450059B112 /* XCDLumberjackNSLogger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 12 | C2077F661CCFC81600E02C9B /* CocoaLumberjack.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = C2077F621CCFC7FF00E02C9B /* CocoaLumberjack.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 13 | C2077F671CCFC81600E02C9B /* NSLogger.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = C2077F631CCFC7FF00E02C9B /* NSLogger.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | C245CC6E1CCECB6A00868F12 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = C245CC6D1CCECB6A00868F12 /* Settings.bundle */; }; 15 | C259B0C01CCE80F20059B112 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C259B0BF1CCE80F20059B112 /* main.m */; }; 16 | C259B0C31CCE80F20059B112 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C259B0C21CCE80F20059B112 /* AppDelegate.m */; }; 17 | C259B0C61CCE80F20059B112 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C259B0C51CCE80F20059B112 /* MainViewController.m */; }; 18 | C259B0C91CCE80F20059B112 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C259B0C71CCE80F20059B112 /* Main.storyboard */; }; 19 | C259B0CB1CCE80F20059B112 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C259B0CA1CCE80F20059B112 /* Assets.xcassets */; }; 20 | C259B0CE1CCE80F20059B112 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C259B0CC1CCE80F20059B112 /* LaunchScreen.storyboard */; }; 21 | C259B0D91CCE81450059B112 /* XCDLumberjackNSLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C259B0D81CCE81450059B112 /* XCDLumberjackNSLogger.framework */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | C2077F601CCFC77400E02C9B /* Copy Frameworks */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = ""; 29 | dstSubfolderSpec = 10; 30 | files = ( 31 | C2077F661CCFC81600E02C9B /* CocoaLumberjack.framework in Copy Frameworks */, 32 | C2077F671CCFC81600E02C9B /* NSLogger.framework in Copy Frameworks */, 33 | C2077F611CCFC78600E02C9B /* XCDLumberjackNSLogger.framework in Copy Frameworks */, 34 | ); 35 | name = "Copy Frameworks"; 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | C2077F5D1CCFA00900E02C9B /* BonjourClientsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BonjourClientsTableViewController.h; sourceTree = ""; }; 42 | C2077F5E1CCFA00900E02C9B /* BonjourClientsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BonjourClientsTableViewController.m; sourceTree = ""; }; 43 | C2077F621CCFC7FF00E02C9B /* CocoaLumberjack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CocoaLumberjack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | C2077F631CCFC7FF00E02C9B /* NSLogger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | C245CC6D1CCECB6A00868F12 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 46 | C259B0BB1CCE80F20059B112 /* XCDLumberjackNSLogger Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "XCDLumberjackNSLogger Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | C259B0BF1CCE80F20059B112 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | C259B0C11CCE80F20059B112 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | C259B0C21CCE80F20059B112 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | C259B0C41CCE80F20059B112 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; 51 | C259B0C51CCE80F20059B112 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; 52 | C259B0C81CCE80F20059B112 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | C259B0CA1CCE80F20059B112 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | C259B0CD1CCE80F20059B112 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | C259B0CF1CCE80F20059B112 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | C259B0D81CCE81450059B112 /* XCDLumberjackNSLogger.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = XCDLumberjackNSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | C259B0B81CCE80F20059B112 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | C259B0D91CCE81450059B112 /* XCDLumberjackNSLogger.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | C259B0B21CCE80F20059B112 = { 72 | isa = PBXGroup; 73 | children = ( 74 | C259B0BD1CCE80F20059B112 /* iOS Demo */, 75 | C259B0D71CCE81380059B112 /* Frameworks */, 76 | C259B0BC1CCE80F20059B112 /* Products */, 77 | ); 78 | indentWidth = 4; 79 | sourceTree = ""; 80 | tabWidth = 4; 81 | usesTabs = 1; 82 | }; 83 | C259B0BC1CCE80F20059B112 /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | C259B0BB1CCE80F20059B112 /* XCDLumberjackNSLogger Demo.app */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | C259B0BD1CCE80F20059B112 /* iOS Demo */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | C259B0BF1CCE80F20059B112 /* main.m */, 95 | C259B0C11CCE80F20059B112 /* AppDelegate.h */, 96 | C259B0C21CCE80F20059B112 /* AppDelegate.m */, 97 | C259B0C41CCE80F20059B112 /* MainViewController.h */, 98 | C259B0C51CCE80F20059B112 /* MainViewController.m */, 99 | C2077F5D1CCFA00900E02C9B /* BonjourClientsTableViewController.h */, 100 | C2077F5E1CCFA00900E02C9B /* BonjourClientsTableViewController.m */, 101 | C259B0CA1CCE80F20059B112 /* Assets.xcassets */, 102 | C259B0C71CCE80F20059B112 /* Main.storyboard */, 103 | C259B0CC1CCE80F20059B112 /* LaunchScreen.storyboard */, 104 | C259B0CF1CCE80F20059B112 /* Info.plist */, 105 | C245CC6D1CCECB6A00868F12 /* Settings.bundle */, 106 | ); 107 | path = "iOS Demo"; 108 | sourceTree = ""; 109 | }; 110 | C259B0D71CCE81380059B112 /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | C2077F621CCFC7FF00E02C9B /* CocoaLumberjack.framework */, 114 | C2077F631CCFC7FF00E02C9B /* NSLogger.framework */, 115 | C259B0D81CCE81450059B112 /* XCDLumberjackNSLogger.framework */, 116 | ); 117 | name = Frameworks; 118 | sourceTree = ""; 119 | }; 120 | /* End PBXGroup section */ 121 | 122 | /* Begin PBXNativeTarget section */ 123 | C259B0BA1CCE80F20059B112 /* XCDLumberjackNSLogger Demo */ = { 124 | isa = PBXNativeTarget; 125 | buildConfigurationList = C259B0D21CCE80F20059B112 /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger Demo" */; 126 | buildPhases = ( 127 | C259B0B71CCE80F20059B112 /* Sources */, 128 | C259B0B81CCE80F20059B112 /* Frameworks */, 129 | C259B0B91CCE80F20059B112 /* Resources */, 130 | C2077F601CCFC77400E02C9B /* Copy Frameworks */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = "XCDLumberjackNSLogger Demo"; 137 | productName = "XCDLumberjackNSLogger Demo"; 138 | productReference = C259B0BB1CCE80F20059B112 /* XCDLumberjackNSLogger Demo.app */; 139 | productType = "com.apple.product-type.application"; 140 | }; 141 | /* End PBXNativeTarget section */ 142 | 143 | /* Begin PBXProject section */ 144 | C259B0B31CCE80F20059B112 /* Project object */ = { 145 | isa = PBXProject; 146 | attributes = { 147 | LastUpgradeCheck = 0730; 148 | ORGANIZATIONNAME = "Cédric Luthi"; 149 | TargetAttributes = { 150 | C259B0BA1CCE80F20059B112 = { 151 | CreatedOnToolsVersion = 7.3.1; 152 | }; 153 | }; 154 | }; 155 | buildConfigurationList = C259B0B61CCE80F20059B112 /* Build configuration list for PBXProject "XCDLumberjackNSLogger Demo" */; 156 | compatibilityVersion = "Xcode 3.2"; 157 | developmentRegion = English; 158 | hasScannedForEncodings = 0; 159 | knownRegions = ( 160 | en, 161 | Base, 162 | ); 163 | mainGroup = C259B0B21CCE80F20059B112; 164 | productRefGroup = C259B0BC1CCE80F20059B112 /* Products */; 165 | projectDirPath = ""; 166 | projectRoot = ""; 167 | targets = ( 168 | C259B0BA1CCE80F20059B112 /* XCDLumberjackNSLogger Demo */, 169 | ); 170 | }; 171 | /* End PBXProject section */ 172 | 173 | /* Begin PBXResourcesBuildPhase section */ 174 | C259B0B91CCE80F20059B112 /* Resources */ = { 175 | isa = PBXResourcesBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | C245CC6E1CCECB6A00868F12 /* Settings.bundle in Resources */, 179 | C259B0CE1CCE80F20059B112 /* LaunchScreen.storyboard in Resources */, 180 | C259B0CB1CCE80F20059B112 /* Assets.xcassets in Resources */, 181 | C259B0C91CCE80F20059B112 /* Main.storyboard in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXSourcesBuildPhase section */ 188 | C259B0B71CCE80F20059B112 /* Sources */ = { 189 | isa = PBXSourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | C259B0C61CCE80F20059B112 /* MainViewController.m in Sources */, 193 | C259B0C31CCE80F20059B112 /* AppDelegate.m in Sources */, 194 | C2077F5F1CCFA00900E02C9B /* BonjourClientsTableViewController.m in Sources */, 195 | C259B0C01CCE80F20059B112 /* main.m in Sources */, 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | /* End PBXSourcesBuildPhase section */ 200 | 201 | /* Begin PBXVariantGroup section */ 202 | C259B0C71CCE80F20059B112 /* Main.storyboard */ = { 203 | isa = PBXVariantGroup; 204 | children = ( 205 | C259B0C81CCE80F20059B112 /* Base */, 206 | ); 207 | name = Main.storyboard; 208 | sourceTree = ""; 209 | }; 210 | C259B0CC1CCE80F20059B112 /* LaunchScreen.storyboard */ = { 211 | isa = PBXVariantGroup; 212 | children = ( 213 | C259B0CD1CCE80F20059B112 /* Base */, 214 | ); 215 | name = LaunchScreen.storyboard; 216 | sourceTree = ""; 217 | }; 218 | /* End PBXVariantGroup section */ 219 | 220 | /* Begin XCBuildConfiguration section */ 221 | C259B0D01CCE80F20059B112 /* Debug */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | ALWAYS_SEARCH_USER_PATHS = NO; 225 | CLANG_ANALYZER_NONNULL = YES; 226 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 227 | CLANG_CXX_LIBRARY = "libc++"; 228 | CLANG_ENABLE_MODULES = YES; 229 | CLANG_ENABLE_OBJC_ARC = YES; 230 | CLANG_WARN_BOOL_CONVERSION = YES; 231 | CLANG_WARN_CONSTANT_CONVERSION = YES; 232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 233 | CLANG_WARN_EMPTY_BODY = YES; 234 | CLANG_WARN_ENUM_CONVERSION = YES; 235 | CLANG_WARN_INT_CONVERSION = YES; 236 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 237 | CLANG_WARN_UNREACHABLE_CODE = YES; 238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 239 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 240 | COPY_PHASE_STRIP = NO; 241 | DEBUG_INFORMATION_FORMAT = dwarf; 242 | ENABLE_STRICT_OBJC_MSGSEND = YES; 243 | ENABLE_TESTABILITY = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu99; 245 | GCC_DYNAMIC_NO_PIC = NO; 246 | GCC_NO_COMMON_BLOCKS = YES; 247 | GCC_OPTIMIZATION_LEVEL = 0; 248 | GCC_PREPROCESSOR_DEFINITIONS = ( 249 | "DEBUG=1", 250 | "LOG_LEVEL_DEF=DDLogLevelAll", 251 | "$(inherited)", 252 | ); 253 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 254 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 255 | GCC_WARN_UNDECLARED_SELECTOR = YES; 256 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 257 | GCC_WARN_UNUSED_FUNCTION = YES; 258 | GCC_WARN_UNUSED_VARIABLE = YES; 259 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 260 | MTL_ENABLE_DEBUG_INFO = YES; 261 | ONLY_ACTIVE_ARCH = YES; 262 | SDKROOT = iphoneos; 263 | TARGETED_DEVICE_FAMILY = "1,2"; 264 | }; 265 | name = Debug; 266 | }; 267 | C259B0D11CCE80F20059B112 /* Release */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_NONNULL = YES; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_EMPTY_BODY = YES; 280 | CLANG_WARN_ENUM_CONVERSION = YES; 281 | CLANG_WARN_INT_CONVERSION = YES; 282 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 283 | CLANG_WARN_UNREACHABLE_CODE = YES; 284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 285 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 286 | COPY_PHASE_STRIP = NO; 287 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 288 | ENABLE_NS_ASSERTIONS = NO; 289 | ENABLE_STRICT_OBJC_MSGSEND = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu99; 291 | GCC_NO_COMMON_BLOCKS = YES; 292 | GCC_PREPROCESSOR_DEFINITIONS = ( 293 | "LOG_LEVEL_DEF=DDLogLevelAll", 294 | "$(inherited)", 295 | ); 296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 298 | GCC_WARN_UNDECLARED_SELECTOR = YES; 299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 300 | GCC_WARN_UNUSED_FUNCTION = YES; 301 | GCC_WARN_UNUSED_VARIABLE = YES; 302 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 303 | MTL_ENABLE_DEBUG_INFO = NO; 304 | SDKROOT = iphoneos; 305 | TARGETED_DEVICE_FAMILY = "1,2"; 306 | VALIDATE_PRODUCT = YES; 307 | }; 308 | name = Release; 309 | }; 310 | C259B0D31CCE80F20059B112 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 314 | INFOPLIST_FILE = "iOS Demo/Info.plist"; 315 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 316 | PRODUCT_BUNDLE_IDENTIFIER = "ch.pitaya.XCDLumberjackNSLogger-Demo"; 317 | PRODUCT_NAME = "$(TARGET_NAME)"; 318 | }; 319 | name = Debug; 320 | }; 321 | C259B0D41CCE80F20059B112 /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 325 | INFOPLIST_FILE = "iOS Demo/Info.plist"; 326 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 327 | PRODUCT_BUNDLE_IDENTIFIER = "ch.pitaya.XCDLumberjackNSLogger-Demo"; 328 | PRODUCT_NAME = "$(TARGET_NAME)"; 329 | }; 330 | name = Release; 331 | }; 332 | /* End XCBuildConfiguration section */ 333 | 334 | /* Begin XCConfigurationList section */ 335 | C259B0B61CCE80F20059B112 /* Build configuration list for PBXProject "XCDLumberjackNSLogger Demo" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | C259B0D01CCE80F20059B112 /* Debug */, 339 | C259B0D11CCE80F20059B112 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | C259B0D21CCE80F20059B112 /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger Demo" */ = { 345 | isa = XCConfigurationList; 346 | buildConfigurations = ( 347 | C259B0D31CCE80F20059B112 /* Debug */, 348 | C259B0D41CCE80F20059B112 /* Release */, 349 | ); 350 | defaultConfigurationIsVisible = 0; 351 | defaultConfigurationName = Release; 352 | }; 353 | /* End XCConfigurationList section */ 354 | }; 355 | rootObject = C259B0B31CCE80F20059B112 /* Project object */; 356 | } 357 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 25/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface AppDelegate : UIResponder 9 | @end 10 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 25/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import "AppDelegate.h" 7 | 8 | #import 9 | 10 | @implementation AppDelegate 11 | 12 | @synthesize window = _window; 13 | 14 | - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | [XCDLumberjackNSLogger bindToBonjourServiceNameUserDefaultsKey:@"NSLoggerBonjourServiceName" configurationHandler:nil]; 17 | 18 | DDTTYLogger *ttyLogger = [DDTTYLogger sharedInstance]; 19 | ttyLogger.colorsEnabled = YES; 20 | [DDLog addLogger:ttyLogger withLevel:DDLogLevelWarning]; 21 | 22 | return YES; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 147 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/BonjourClientsTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 26/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface BonjourClientsTableViewController : UITableViewController 9 | @end 10 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/BonjourClientsTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 26/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import "BonjourClientsTableViewController.h" 7 | 8 | #import 9 | #import 10 | 11 | static NSArray * NetServiceAddresses(NSNetService *service) 12 | { 13 | NSMutableArray *addresses = [NSMutableArray new]; 14 | for (NSData *addressData in service.addresses) 15 | { 16 | NSString *addressDescription; 17 | if (addressData.length == sizeof(struct sockaddr_in6)) 18 | { 19 | char ip[INET6_ADDRSTRLEN] = {0}; 20 | inet_ntop(AF_INET6, addressData.bytes + offsetof(struct sockaddr_in6, sin6_addr), ip, sizeof(ip)); 21 | addressDescription = [NSString stringWithFormat:@"[%@]:%@", @(ip), @(service.port)]; 22 | } 23 | else if (addressData.length == sizeof(struct sockaddr_in)) 24 | { 25 | char ip[INET_ADDRSTRLEN] = {0}; 26 | inet_ntop(AF_INET, addressData.bytes + offsetof(struct sockaddr_in, sin_addr), ip, sizeof(ip)); 27 | addressDescription = [NSString stringWithFormat:@"%@:%@", @(ip), @(service.port)]; 28 | } 29 | else 30 | { 31 | addressDescription = addressData.description; 32 | } 33 | [addresses addObject:addressDescription]; 34 | } 35 | return addresses; 36 | } 37 | 38 | @interface BonjourClientsTableViewController () 39 | @property (nonatomic, strong) NSNetServiceBrowser *netServiceBrowser; 40 | @property (nonatomic, strong) NSMutableArray *services; 41 | @end 42 | 43 | @implementation BonjourClientsTableViewController 44 | 45 | - (NSMutableArray *) services 46 | { 47 | if (!_services) 48 | _services = [NSMutableArray new]; 49 | return _services; 50 | } 51 | 52 | - (void) viewDidLoad 53 | { 54 | [super viewDidLoad]; 55 | 56 | self.netServiceBrowser = [NSNetServiceBrowser new]; 57 | self.netServiceBrowser.includesPeerToPeer = YES; 58 | self.netServiceBrowser.delegate = self; 59 | [self.netServiceBrowser searchForServicesOfType:@"_nslogger-ssl._tcp." inDomain:@""]; 60 | } 61 | 62 | - (IBAction) cancel:(id)sender 63 | { 64 | [self dismissViewControllerAnimated:YES completion:nil]; 65 | } 66 | 67 | - (IBAction) disconnect:(id)sender 68 | { 69 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"NSLoggerBonjourServiceName"]; 70 | 71 | [self dismissViewControllerAnimated:YES completion:nil]; 72 | } 73 | 74 | #pragma mark - NSNetServiceBrowserDelegate 75 | 76 | static NSString * NSNetServicesErrorDescription(NSNetServicesError error) 77 | { 78 | switch (error) 79 | { 80 | case NSNetServicesUnknownError: return @"An unknown error occured during resolution or publication."; 81 | case NSNetServicesCollisionError: return @"An NSNetService with the same domain, type and name was already present when the publication request was made."; 82 | case NSNetServicesNotFoundError: return @"The NSNetService was not found when a resolution request was made."; 83 | case NSNetServicesActivityInProgress: return @"A publication or resolution request was sent to an NSNetService instance which was already published or a search request was made of an NSNetServiceBrowser instance which was already searching."; 84 | case NSNetServicesBadArgumentError: return @"An required argument was not provided when initializing the NSNetService instance."; 85 | case NSNetServicesCancelledError: return @"The operation being performed by the NSNetService or NSNetServiceBrowser instance was cancelled."; 86 | case NSNetServicesInvalidError: return @"An invalid argument was provided when initializing the NSNetService instance or starting a search with an NSNetServiceBrowser instance."; 87 | case NSNetServicesTimeoutError: return @"Resolution of an NSNetService instance failed because the timeout was reached."; 88 | } 89 | return [NSString stringWithFormat:@"NSNetServicesError %@", @(error)]; 90 | } 91 | 92 | - (void) netServiceBrowser:(NSNetServiceBrowser *)browser didNotSearch:(NSDictionary *)errorDict 93 | { 94 | NSString *message = NSNetServicesErrorDescription(errorDict[NSNetServicesErrorCode].integerValue); 95 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Bonjour Error" message:message preferredStyle:UIAlertControllerStyleAlert]; 96 | [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 97 | [self dismissViewControllerAnimated:YES completion:nil]; 98 | }]]; 99 | [self presentViewController:alertController animated:YES completion:nil]; 100 | } 101 | 102 | - (void) netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing 103 | { 104 | [service setDelegate:self]; 105 | [service resolveWithTimeout:10]; 106 | 107 | [self.services addObject:service]; 108 | [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.services.count - 1 inSection:0] ] withRowAnimation:UITableViewRowAnimationAutomatic]; 109 | } 110 | 111 | - (void) netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)moreComing 112 | { 113 | NSUInteger serviceIndex = [self.services indexOfObject:service]; 114 | if (serviceIndex != NSNotFound) 115 | { 116 | [self.services removeObjectAtIndex:serviceIndex]; 117 | [self.tableView deleteRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:serviceIndex inSection:0] ] withRowAnimation:UITableViewRowAnimationAutomatic]; 118 | } 119 | } 120 | 121 | #pragma mark - UITableView 122 | 123 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 124 | { 125 | return self.services.count; 126 | } 127 | 128 | - (NSIndexPath *) tableView:(UITableView *)tableView willSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath 129 | { 130 | BOOL isSelectedServiceName = [self.services[indexPath.row].name isEqualToString:[[NSUserDefaults standardUserDefaults] stringForKey:@"NSLoggerBonjourServiceName"]]; 131 | return isSelectedServiceName ? nil : indexPath; 132 | } 133 | 134 | - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 135 | { 136 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BonjourClientCell" forIndexPath:indexPath]; 137 | NSNetService *service = self.services[indexPath.row]; 138 | BOOL isSelectedServiceName = [service.name isEqualToString:[[NSUserDefaults standardUserDefaults] stringForKey:@"NSLoggerBonjourServiceName"]]; 139 | cell.textLabel.text = service.name; 140 | cell.detailTextLabel.text = [NetServiceAddresses(service) componentsJoinedByString:@" ◇ "]; 141 | cell.accessoryType = isSelectedServiceName ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 142 | cell.selectionStyle = isSelectedServiceName ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleGray; 143 | return cell; 144 | } 145 | 146 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 147 | { 148 | [[NSUserDefaults standardUserDefaults] setObject:self.services[indexPath.row].name forKey:@"NSLoggerBonjourServiceName"]; 149 | 150 | [self dismissViewControllerAnimated:YES completion:nil]; 151 | } 152 | 153 | #pragma mark - NSNetServiceDelegate 154 | 155 | - (void) reloadService:(NSNetService *)service 156 | { 157 | NSUInteger serviceIndex = [self.services indexOfObject:service]; 158 | if (serviceIndex != NSNotFound) 159 | { 160 | [self.tableView reloadRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:serviceIndex inSection:0] ] withRowAnimation:UITableViewRowAnimationAutomatic]; 161 | } 162 | } 163 | 164 | - (void) netServiceDidResolveAddress:(NSNetService *)service 165 | { 166 | [self reloadService:service]; 167 | } 168 | 169 | - (void) netService:(NSNetService *)service didNotResolve:(NSDictionary *)errorDict; 170 | { 171 | NSLog(@"netService:%@ didNotResolve:%@", service, errorDict); 172 | [self reloadService:service]; 173 | } 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 25/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import 7 | 8 | @interface MainViewController : UITableViewController 9 | @end 10 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/MainViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 25/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import "MainViewController.h" 7 | 8 | #import 9 | #import 10 | #import 11 | 12 | @implementation MainViewController 13 | 14 | - (void) viewWillAppear:(BOOL)animated 15 | { 16 | [super viewWillAppear:animated]; 17 | 18 | self.navigationItem.prompt = [[NSUserDefaults standardUserDefaults] stringForKey:@"NSLoggerBonjourServiceName"]; 19 | } 20 | 21 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 22 | { 23 | unsigned long length; 24 | uint8_t *bytes = getsectiondata(&_mh_execute_header, "__TEXT", "__text", &length); 25 | switch (indexPath.row) 26 | { 27 | case 0: DDLogError(@"Error log sample"); break; 28 | case 1: DDLogWarn(@"Warning log sample"); break; 29 | case 2: DDLogInfo(@"Info log sample"); break; 30 | case 3: DDLogDebug(@"Debug log sample"); break; 31 | case 4: DDLogVerbose(@"%@", [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO].description); break; 32 | default: break; 33 | } 34 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | Title 9 | NSLogger 10 | Type 11 | PSGroupSpecifier 12 | 13 | 14 | AutocapitalizationType 15 | None 16 | AutocorrectionType 17 | No 18 | DefaultValue 19 | 20 | IsSecure 21 | 22 | Key 23 | NSLoggerBonjourServiceName 24 | KeyboardType 25 | Alphabet 26 | Title 27 | Bonjour Service Name 28 | Type 29 | PSTextFieldSpecifier 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger Demo/iOS Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Cédric Luthi on 25/04/16. 3 | // Copyright © 2016 Cédric Luthi. All rights reserved. 4 | // 5 | 6 | #import 7 | #import "AppDelegate.h" 8 | 9 | int main(int argc, char * argv[]) 10 | { 11 | @autoreleasepool 12 | { 13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "XCDLumberjackNSLogger" 3 | s.version = "1.1.1" 4 | s.summary = "A CocoaLumberjack logger which sends logs to NSLogger" 5 | s.homepage = "https://github.com/0xced/XCDLumberjackNSLogger" 6 | s.license = { :type => "MIT", :file => "LICENSE" } 7 | s.author = { "Cédric Luthi" => "cedric.luthi@gmail.com" } 8 | s.social_media_url = "http://twitter.com/0xced" 9 | s.ios.deployment_target = "8.0" 10 | s.osx.deployment_target = "10.10" 11 | s.tvos.deployment_target = "9.0" 12 | s.source = { :git => "https://github.com/0xced/XCDLumberjackNSLogger.git", :tag => s.version.to_s } 13 | s.source_files = "XCDLumberjackNSLogger/XCDLumberjackNSLogger.{h,m}" 14 | s.requires_arc = true 15 | 16 | s.dependency "CocoaLumberjack", ">= 2.0" 17 | s.dependency "NSLogger", ">= 1.7" 18 | end 19 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C230B1BE1CCAC70600CD5302 /* XCDLumberjackNSLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C2EECA1C2AD98300C5725E /* XCDLumberjackNSLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | C235320B1CCE4E1100ED8F7D /* XCDLumberjackNSLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C2EECA1C2AD98300C5725E /* XCDLumberjackNSLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | C235320C1CCE4E1200ED8F7D /* XCDLumberjackNSLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C2EECA1C2AD98300C5725E /* XCDLumberjackNSLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | C235320D1CCE4E4300ED8F7D /* XCDLumberjackNSLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C2EED21C2ADA7800C5725E /* XCDLumberjackNSLogger.m */; }; 14 | C235320E1CCE4E4400ED8F7D /* XCDLumberjackNSLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C2EED21C2ADA7800C5725E /* XCDLumberjackNSLogger.m */; }; 15 | C235320F1CCE4EDD00ED8F7D /* NSLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C230B1BC1CCAC57D00CD5302 /* NSLogger.framework */; }; 16 | C23532101CCE4EE800ED8F7D /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2C2EED41C2AE09300C5725E /* CocoaLumberjack.framework */; }; 17 | C23532111CCE4EEA00ED8F7D /* NSLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C230B1BC1CCAC57D00CD5302 /* NSLogger.framework */; }; 18 | C23532121CCE4EED00ED8F7D /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2C2EED41C2AE09300C5725E /* CocoaLumberjack.framework */; }; 19 | C23532131CCE4EEF00ED8F7D /* NSLogger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C230B1BC1CCAC57D00CD5302 /* NSLogger.framework */; }; 20 | C2C2EED31C2ADA7800C5725E /* XCDLumberjackNSLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C2EED21C2ADA7800C5725E /* XCDLumberjackNSLogger.m */; }; 21 | C2C2EED51C2AE09300C5725E /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2C2EED41C2AE09300C5725E /* CocoaLumberjack.framework */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | C230B1BC1CCAC57D00CD5302 /* NSLogger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | C23531F61CCE46FD00ED8F7D /* XCDLumberjackNSLogger.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCDLumberjackNSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | C23532031CCE4A6300ED8F7D /* XCDLumberjackNSLogger.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCDLumberjackNSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | C2C2EEC71C2AD98300C5725E /* XCDLumberjackNSLogger.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = XCDLumberjackNSLogger.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | C2C2EECA1C2AD98300C5725E /* XCDLumberjackNSLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCDLumberjackNSLogger.h; sourceTree = ""; }; 30 | C2C2EECC1C2AD98300C5725E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | C2C2EED21C2ADA7800C5725E /* XCDLumberjackNSLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCDLumberjackNSLogger.m; sourceTree = ""; }; 32 | C2C2EED41C2AE09300C5725E /* CocoaLumberjack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CocoaLumberjack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | C23531F21CCE46FD00ED8F7D /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | C23532101CCE4EE800ED8F7D /* CocoaLumberjack.framework in Frameworks */, 41 | C23532111CCE4EEA00ED8F7D /* NSLogger.framework in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | C23531FF1CCE4A6300ED8F7D /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | C23532121CCE4EED00ED8F7D /* CocoaLumberjack.framework in Frameworks */, 50 | C23532131CCE4EEF00ED8F7D /* NSLogger.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | C2C2EEC31C2AD98300C5725E /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | C2C2EED51C2AE09300C5725E /* CocoaLumberjack.framework in Frameworks */, 59 | C235320F1CCE4EDD00ED8F7D /* NSLogger.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | C2C2EEBD1C2AD98300C5725E = { 67 | isa = PBXGroup; 68 | children = ( 69 | C2C2EEC91C2AD98300C5725E /* XCDLumberjackNSLogger */, 70 | C2C2EED61C2AE0FF00C5725E /* Frameworks */, 71 | C2C2EEC81C2AD98300C5725E /* Products */, 72 | ); 73 | indentWidth = 4; 74 | sourceTree = ""; 75 | tabWidth = 4; 76 | usesTabs = 1; 77 | }; 78 | C2C2EEC81C2AD98300C5725E /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | C2C2EEC71C2AD98300C5725E /* XCDLumberjackNSLogger.framework */, 82 | C23531F61CCE46FD00ED8F7D /* XCDLumberjackNSLogger.framework */, 83 | C23532031CCE4A6300ED8F7D /* XCDLumberjackNSLogger.framework */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | C2C2EEC91C2AD98300C5725E /* XCDLumberjackNSLogger */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | C2C2EECC1C2AD98300C5725E /* Info.plist */, 92 | C2C2EECA1C2AD98300C5725E /* XCDLumberjackNSLogger.h */, 93 | C2C2EED21C2ADA7800C5725E /* XCDLumberjackNSLogger.m */, 94 | ); 95 | path = XCDLumberjackNSLogger; 96 | sourceTree = ""; 97 | }; 98 | C2C2EED61C2AE0FF00C5725E /* Frameworks */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | C2C2EED41C2AE09300C5725E /* CocoaLumberjack.framework */, 102 | C230B1BC1CCAC57D00CD5302 /* NSLogger.framework */, 103 | ); 104 | name = Frameworks; 105 | sourceTree = ""; 106 | }; 107 | /* End PBXGroup section */ 108 | 109 | /* Begin PBXHeadersBuildPhase section */ 110 | C23531F31CCE46FD00ED8F7D /* Headers */ = { 111 | isa = PBXHeadersBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | C235320B1CCE4E1100ED8F7D /* XCDLumberjackNSLogger.h in Headers */, 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | C23532001CCE4A6300ED8F7D /* Headers */ = { 119 | isa = PBXHeadersBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | C235320C1CCE4E1200ED8F7D /* XCDLumberjackNSLogger.h in Headers */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | C2C2EEC41C2AD98300C5725E /* Headers */ = { 127 | isa = PBXHeadersBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | C230B1BE1CCAC70600CD5302 /* XCDLumberjackNSLogger.h in Headers */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXHeadersBuildPhase section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | C23531F51CCE46FD00ED8F7D /* XCDLumberjackNSLogger OS X */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = C23531FB1CCE46FD00ED8F7D /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger OS X" */; 140 | buildPhases = ( 141 | C23531F31CCE46FD00ED8F7D /* Headers */, 142 | C23531F11CCE46FD00ED8F7D /* Sources */, 143 | C23531F21CCE46FD00ED8F7D /* Frameworks */, 144 | ); 145 | buildRules = ( 146 | ); 147 | dependencies = ( 148 | ); 149 | name = "XCDLumberjackNSLogger OS X"; 150 | productName = XCDLumberjackNSLogger; 151 | productReference = C23531F61CCE46FD00ED8F7D /* XCDLumberjackNSLogger.framework */; 152 | productType = "com.apple.product-type.framework"; 153 | }; 154 | C23532021CCE4A6300ED8F7D /* XCDLumberjackNSLogger tvOS */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = C23532081CCE4A6300ED8F7D /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger tvOS" */; 157 | buildPhases = ( 158 | C23532001CCE4A6300ED8F7D /* Headers */, 159 | C23531FE1CCE4A6300ED8F7D /* Sources */, 160 | C23531FF1CCE4A6300ED8F7D /* Frameworks */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | ); 166 | name = "XCDLumberjackNSLogger tvOS"; 167 | productName = "XCDLumberjackNSLogger tvOS"; 168 | productReference = C23532031CCE4A6300ED8F7D /* XCDLumberjackNSLogger.framework */; 169 | productType = "com.apple.product-type.framework"; 170 | }; 171 | C2C2EEC61C2AD98300C5725E /* XCDLumberjackNSLogger iOS */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = C2C2EECF1C2AD98300C5725E /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger iOS" */; 174 | buildPhases = ( 175 | C2C2EEC41C2AD98300C5725E /* Headers */, 176 | C2C2EEC21C2AD98300C5725E /* Sources */, 177 | C2C2EEC31C2AD98300C5725E /* Frameworks */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | ); 183 | name = "XCDLumberjackNSLogger iOS"; 184 | productName = XCDLumberjackNSLogger; 185 | productReference = C2C2EEC71C2AD98300C5725E /* XCDLumberjackNSLogger.framework */; 186 | productType = "com.apple.product-type.framework"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | C2C2EEBE1C2AD98300C5725E /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastUpgradeCheck = 0720; 195 | ORGANIZATIONNAME = Pitaya; 196 | TargetAttributes = { 197 | C23531F51CCE46FD00ED8F7D = { 198 | CreatedOnToolsVersion = 7.3.1; 199 | }; 200 | C23532021CCE4A6300ED8F7D = { 201 | CreatedOnToolsVersion = 7.3.1; 202 | }; 203 | C2C2EEC61C2AD98300C5725E = { 204 | CreatedOnToolsVersion = 7.2; 205 | }; 206 | }; 207 | }; 208 | buildConfigurationList = C2C2EEC11C2AD98300C5725E /* Build configuration list for PBXProject "XCDLumberjackNSLogger" */; 209 | compatibilityVersion = "Xcode 3.2"; 210 | developmentRegion = English; 211 | hasScannedForEncodings = 0; 212 | knownRegions = ( 213 | en, 214 | ); 215 | mainGroup = C2C2EEBD1C2AD98300C5725E; 216 | productRefGroup = C2C2EEC81C2AD98300C5725E /* Products */; 217 | projectDirPath = ""; 218 | projectRoot = ""; 219 | targets = ( 220 | C2C2EEC61C2AD98300C5725E /* XCDLumberjackNSLogger iOS */, 221 | C23531F51CCE46FD00ED8F7D /* XCDLumberjackNSLogger OS X */, 222 | C23532021CCE4A6300ED8F7D /* XCDLumberjackNSLogger tvOS */, 223 | ); 224 | }; 225 | /* End PBXProject section */ 226 | 227 | /* Begin PBXSourcesBuildPhase section */ 228 | C23531F11CCE46FD00ED8F7D /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | C235320D1CCE4E4300ED8F7D /* XCDLumberjackNSLogger.m in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | C23531FE1CCE4A6300ED8F7D /* Sources */ = { 237 | isa = PBXSourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | C235320E1CCE4E4400ED8F7D /* XCDLumberjackNSLogger.m in Sources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | C2C2EEC21C2AD98300C5725E /* Sources */ = { 245 | isa = PBXSourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | C2C2EED31C2ADA7800C5725E /* XCDLumberjackNSLogger.m in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXSourcesBuildPhase section */ 253 | 254 | /* Begin XCBuildConfiguration section */ 255 | C23531FC1CCE46FD00ED8F7D /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | CODE_SIGN_IDENTITY = "Mac Developer"; 259 | COMBINE_HIDPI_IMAGES = YES; 260 | SDKROOT = macosx; 261 | }; 262 | name = Debug; 263 | }; 264 | C23531FD1CCE46FD00ED8F7D /* Release */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | CODE_SIGN_IDENTITY = "Mac Developer"; 268 | COMBINE_HIDPI_IMAGES = YES; 269 | SDKROOT = macosx; 270 | }; 271 | name = Release; 272 | }; 273 | C23532091CCE4A6300ED8F7D /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | SDKROOT = appletvos; 277 | TARGETED_DEVICE_FAMILY = 3; 278 | }; 279 | name = Debug; 280 | }; 281 | C235320A1CCE4A6300ED8F7D /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | SDKROOT = appletvos; 285 | TARGETED_DEVICE_FAMILY = 3; 286 | }; 287 | name = Release; 288 | }; 289 | C2C2EECD1C2AD98300C5725E /* Debug */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ALWAYS_SEARCH_USER_PATHS = NO; 293 | CLANG_ANALYZER_NONNULL = YES; 294 | CLANG_ENABLE_MODULES = YES; 295 | CLANG_ENABLE_OBJC_ARC = YES; 296 | CLANG_WARN_BOOL_CONVERSION = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 299 | CLANG_WARN_EMPTY_BODY = YES; 300 | CLANG_WARN_ENUM_CONVERSION = YES; 301 | CLANG_WARN_INT_CONVERSION = YES; 302 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 303 | CLANG_WARN_UNREACHABLE_CODE = YES; 304 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 305 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 306 | COPY_PHASE_STRIP = NO; 307 | CURRENT_PROJECT_VERSION = 5; 308 | DEBUG_INFORMATION_FORMAT = dwarf; 309 | DEFINES_MODULE = YES; 310 | DYLIB_COMPATIBILITY_VERSION = 1.0.0; 311 | DYLIB_CURRENT_VERSION = 1.1.1; 312 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 313 | ENABLE_STRICT_OBJC_MSGSEND = YES; 314 | ENABLE_TESTABILITY = YES; 315 | GCC_NO_COMMON_BLOCKS = YES; 316 | GCC_OPTIMIZATION_LEVEL = 0; 317 | GCC_PREPROCESSOR_DEFINITIONS = ( 318 | "DEBUG=1", 319 | "$(inherited)", 320 | ); 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | INFOPLIST_FILE = XCDLumberjackNSLogger/Info.plist; 328 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 329 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks @loader_path/Frameworks"; 330 | MACOSX_DEPLOYMENT_TARGET = 10.10; 331 | ONLY_ACTIVE_ARCH = YES; 332 | PRODUCT_BUNDLE_IDENTIFIER = ch.pitaya.XCDLumberjackNSLogger; 333 | PRODUCT_NAME = "$(PROJECT_NAME)"; 334 | SKIP_INSTALL = YES; 335 | TVOS_DEPLOYMENT_TARGET = 9.0; 336 | VERSIONING_SYSTEM = "Semantic Versioning"; 337 | }; 338 | name = Debug; 339 | }; 340 | C2C2EECE1C2AD98300C5725E /* Release */ = { 341 | isa = XCBuildConfiguration; 342 | buildSettings = { 343 | ALWAYS_SEARCH_USER_PATHS = NO; 344 | CLANG_ANALYZER_NONNULL = YES; 345 | CLANG_ENABLE_MODULES = YES; 346 | CLANG_ENABLE_OBJC_ARC = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_CONSTANT_CONVERSION = YES; 349 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 350 | CLANG_WARN_EMPTY_BODY = YES; 351 | CLANG_WARN_ENUM_CONVERSION = YES; 352 | CLANG_WARN_INT_CONVERSION = YES; 353 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | CURRENT_PROJECT_VERSION = 5; 359 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 360 | DEFINES_MODULE = YES; 361 | DYLIB_COMPATIBILITY_VERSION = 1.0.0; 362 | DYLIB_CURRENT_VERSION = 1.1.1; 363 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 364 | ENABLE_NS_ASSERTIONS = NO; 365 | ENABLE_STRICT_OBJC_MSGSEND = YES; 366 | GCC_NO_COMMON_BLOCKS = YES; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | INFOPLIST_FILE = XCDLumberjackNSLogger/Info.plist; 374 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 375 | LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks @loader_path/Frameworks"; 376 | MACOSX_DEPLOYMENT_TARGET = 10.10; 377 | PRODUCT_BUNDLE_IDENTIFIER = ch.pitaya.XCDLumberjackNSLogger; 378 | PRODUCT_NAME = "$(PROJECT_NAME)"; 379 | SKIP_INSTALL = YES; 380 | TVOS_DEPLOYMENT_TARGET = 9.0; 381 | VALIDATE_PRODUCT = YES; 382 | VERSIONING_SYSTEM = "Semantic Versioning"; 383 | }; 384 | name = Release; 385 | }; 386 | C2C2EED01C2AD98300C5725E /* Debug */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | SDKROOT = iphoneos; 390 | TARGETED_DEVICE_FAMILY = "1,2"; 391 | }; 392 | name = Debug; 393 | }; 394 | C2C2EED11C2AD98300C5725E /* Release */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | SDKROOT = iphoneos; 398 | TARGETED_DEVICE_FAMILY = "1,2"; 399 | }; 400 | name = Release; 401 | }; 402 | /* End XCBuildConfiguration section */ 403 | 404 | /* Begin XCConfigurationList section */ 405 | C23531FB1CCE46FD00ED8F7D /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger OS X" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | C23531FC1CCE46FD00ED8F7D /* Debug */, 409 | C23531FD1CCE46FD00ED8F7D /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | C23532081CCE4A6300ED8F7D /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger tvOS" */ = { 415 | isa = XCConfigurationList; 416 | buildConfigurations = ( 417 | C23532091CCE4A6300ED8F7D /* Debug */, 418 | C235320A1CCE4A6300ED8F7D /* Release */, 419 | ); 420 | defaultConfigurationIsVisible = 0; 421 | defaultConfigurationName = Release; 422 | }; 423 | C2C2EEC11C2AD98300C5725E /* Build configuration list for PBXProject "XCDLumberjackNSLogger" */ = { 424 | isa = XCConfigurationList; 425 | buildConfigurations = ( 426 | C2C2EECD1C2AD98300C5725E /* Debug */, 427 | C2C2EECE1C2AD98300C5725E /* Release */, 428 | ); 429 | defaultConfigurationIsVisible = 0; 430 | defaultConfigurationName = Release; 431 | }; 432 | C2C2EECF1C2AD98300C5725E /* Build configuration list for PBXNativeTarget "XCDLumberjackNSLogger iOS" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | C2C2EED01C2AD98300C5725E /* Debug */, 436 | C2C2EED11C2AD98300C5725E /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | /* End XCConfigurationList section */ 442 | }; 443 | rootObject = C2C2EEBE1C2AD98300C5725E /* Project object */; 444 | } 445 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcodeproj/xcshareddata/xcschemes/XCDLumberjackNSLogger OS X.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcodeproj/xcshareddata/xcschemes/XCDLumberjackNSLogger iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcodeproj/xcshareddata/xcschemes/XCDLumberjackNSLogger tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger/AppledocSettings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | --company-id 6 | ch.pitaya 7 | --create-docset 8 | 9 | --ignore 10 | 11 | *.m 12 | 13 | --index-desc 14 | README.md 15 | --explicit-crossref 16 | 17 | --print-settings 18 | 19 | --project-company 20 | Cédric Luthi 21 | --project-name 22 | XCDLumberjackNSLogger 23 | --repeat-first-par 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(DYLIB_CURRENT_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2015-2016 Cédric Luthi. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger/XCDLumberjackNSLogger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Cédric Luthi. All rights reserved. 3 | // 4 | 5 | #import 6 | #import 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /** 11 | * The `XCDLumberjackNSLogger` class implements a [CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack) logger which sends logs to [NSLogger](https://github.com/fpillet/NSLogger). 12 | * 13 | * `XCDLumberjackNSLogger` does not support log formatters, i.e. setting the `logFormatter` property has no effect. 14 | */ 15 | @interface XCDLumberjackNSLogger : NSObject 16 | 17 | /** 18 | * ------------------------------ 19 | * @name Binding to User Defaults 20 | * ------------------------------ 21 | */ 22 | 23 | /** 24 | * Automatically synchronize a single instance of a XCDLumberjackNSLogger to a bonjour service name stored in the standard user defaults. 25 | * 26 | * @param userDefaultsKey The user defaults key that contains the NSLogger bonjour service name 27 | * @param configurationHandler A block which is called just before the managed logger is added to the CocoaLumberjack loggers. Configure the logger in this handler, you can set its for example. The return value is the level at which the managed logger will be added. Pass `nil` if you do not need any special configuration. 28 | * 29 | * @discussion The managed XCDLumberjackNSLogger instance is removed from the CocoaLumberjack loggers when the user defaults value becomes nil or the empty string. A new XCDLumberjackNSLogger instance is added back when the user defaults value becomes a valid service name. 30 | * 31 | * @warning This method must be called only once. 32 | */ 33 | + (void) bindToBonjourServiceNameUserDefaultsKey:(NSString *)userDefaultsKey configurationHandler:(nullable DDLogLevel (^)(XCDLumberjackNSLogger *logger))configurationHandler; 34 | 35 | /** 36 | * ------------------ 37 | * @name Initializing 38 | * ------------------ 39 | */ 40 | 41 | /** 42 | * Initializes a logger with the specified bonjour service name. 43 | * 44 | * @param bonjourServiceName The bonjour service name of the destination NSLogger desktop viewer. The bonjour service name may be nil. 45 | * 46 | * @discussion Providing a bonjour service name is useful if you are several developers on the same network using NSLogger. If you are the only developer using NSLogger, you can pass nil or simply use the standard `init` method instead. 47 | * 48 | * @return A logger with the specified bonjour service name. 49 | */ 50 | - (instancetype) initWithBonjourServiceName:(NSString * _Nullable)bonjourServiceName NS_DESIGNATED_INITIALIZER; 51 | 52 | /** 53 | * ------------------------------------- 54 | * @name Accessing the underlying logger 55 | * ------------------------------------- 56 | */ 57 | 58 | /** 59 | * The underlying NSLogger struct. 60 | * 61 | * @discussion Use the underlying logger if you need fine-grained control. For example, you may want to call `LoggerSetViewerHost(lubmerjackNSLogger.logger, host, port)` if you are in a Bonjour-hostile network. You may also use this property to tweak the logger options with the `LoggerSetOptions` function. 62 | */ 63 | @property (readonly) Logger *logger; 64 | 65 | /** 66 | * ---------------------------------- 67 | * @name Translating contexts to tags 68 | * ---------------------------------- 69 | */ 70 | 71 | /** 72 | * This property defines a relation between CocoaLumberjack contexts and NSLogger tags. The keys must be `NSNumber` objects representing CocoaLumberjack contexts and the values must be `NSString` objects corresponding to NSLogger tags. 73 | * 74 | * @discussion Framework authors are [encouraged to choose a context](https://github.com/CocoaLumberjack/CocoaLumberjack/blob/8adde11d0b16843cb45b81dc9b60d1430eb9b538/Documentation/CustomContext.md#example-2) to allow application developers to easily manage the log statements coming from their framework. 75 | * Unfortunately, a context is an NSInteger which is not appropriate for displaying in NSLogger. Use this property to translate unintelligible contexts into readable tags. 76 | * 77 | * For example, CocoaHTTPServer [defines a context](https://github.com/robbiehanson/CocoaHTTPServer/blob/52b2a64e9cbdb5f09cc915814a5fb68a45dd3707/Core/HTTPLogging.h#L55) of 80. In order to translate it to a `CocoaHTTPServer` tag, use `lubmerjackNSLogger.tags = @{ @80 : @"CocoaHTTPServer" };` 78 | */ 79 | @property (copy, nullable) NSDictionary *tags; 80 | 81 | @end 82 | 83 | NS_ASSUME_NONNULL_END 84 | -------------------------------------------------------------------------------- /XCDLumberjackNSLogger/XCDLumberjackNSLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Cédric Luthi. All rights reserved. 3 | // 4 | 5 | #import "XCDLumberjackNSLogger.h" 6 | 7 | @implementation XCDLumberjackNSLogger 8 | 9 | + (void) bindToBonjourServiceNameUserDefaultsKey:(NSString *)userDefaultsKey configurationHandler:(DDLogLevel (^)(XCDLumberjackNSLogger *))configurationHandler 10 | { 11 | static BOOL bound = NO; 12 | if (bound) 13 | @throw [NSException exceptionWithName:@"APIMisuseException" reason:[NSString stringWithFormat:@"The method %s must be called only once.", __PRETTY_FUNCTION__] userInfo:nil]; 14 | bound = YES; 15 | 16 | static XCDLumberjackNSLogger *currentLogger; 17 | 18 | void (^updateLogger)(NSNotification *) = ^ void (NSNotification *notification) { 19 | NSString *currentServiceName = currentLogger.logger ? (__bridge NSString *)LoggerGetBonjourServiceName(currentLogger.logger) : nil; 20 | NSString *bonjourServiceName = [notification.object stringForKey:userDefaultsKey]; 21 | if ([currentServiceName isEqualToString:bonjourServiceName]) 22 | return; 23 | 24 | [DDLog removeLogger:currentLogger]; 25 | if (bonjourServiceName.length > 0) 26 | { 27 | currentLogger = [[self alloc] initWithBonjourServiceName:bonjourServiceName]; 28 | DDLogLevel level = configurationHandler ? configurationHandler(currentLogger) : DDLogLevelAll; 29 | [DDLog addLogger:currentLogger withLevel:level]; 30 | } 31 | else 32 | { 33 | currentLogger = nil; 34 | } 35 | }; 36 | 37 | NSOperationQueue *queue = [NSOperationQueue new]; 38 | queue.name = @"XCDLumberjackNSLogger.UserDefaults"; 39 | [[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil queue:queue usingBlock:updateLogger]; 40 | 41 | [queue addOperationWithBlock:^{ 42 | updateLogger([NSNotification notificationWithName:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]]); 43 | }]; 44 | [queue waitUntilAllOperationsAreFinished]; 45 | } 46 | 47 | - (instancetype) init 48 | { 49 | return [self initWithBonjourServiceName:nil]; 50 | } 51 | 52 | - (instancetype) initWithBonjourServiceName:(NSString *)bonjourServiceName 53 | { 54 | if (!(self = [super init])) 55 | return nil; 56 | 57 | _logger = LoggerInit(); 58 | LoggerSetupBonjour(_logger, NULL, (__bridge CFStringRef)bonjourServiceName); 59 | LoggerSetOptions(_logger, LoggerGetOptions(_logger) & ~kLoggerOption_CaptureSystemConsole); 60 | 61 | return self; 62 | } 63 | 64 | - (void) dealloc 65 | { 66 | LoggerStop(self.logger); 67 | } 68 | 69 | #pragma mark - DDLogger 70 | 71 | static NSData * MessageAsData(NSString *message); 72 | 73 | static void SetThreadNameWithMessage(DDLogMessage *logMessage) 74 | { 75 | static NSDictionary *queueLabels; 76 | static dispatch_once_t once; 77 | dispatch_once(&once, ^{ 78 | queueLabels = @{ 79 | @"com.apple.root.user-interactive-qos": @"User Interactive QoS", // QOS_CLASS_USER_INTERACTIVE 80 | @"com.apple.root.user-initiated-qos": @"User Initiated QoS", // QOS_CLASS_USER_INITIATED 81 | @"com.apple.root.default-qos": @"Default QoS", // QOS_CLASS_DEFAULT 82 | @"com.apple.root.utility-qos": @"Utility QoS", // QOS_CLASS_UTILITY 83 | @"com.apple.root.background-qos": @"Background QoS", // QOS_CLASS_BACKGROUND 84 | @"com.apple.main-thread": @"Main Queue" 85 | }; 86 | }); 87 | 88 | // There is no _thread name_ parameter for LogXXXToF functions, but we can abuse NSLogger’s thread name caching mechanism which uses the current thread dictionary 89 | NSString *queueLabel = queueLabels[logMessage.queueLabel] ?: logMessage.queueLabel; 90 | NSThread.currentThread.threadDictionary[@"__$NSLoggerThreadName$__"] = [NSString stringWithFormat:@"%@ [%@]", logMessage.threadID, queueLabel]; 91 | } 92 | 93 | @synthesize logFormatter = _logFormatter; 94 | 95 | - (NSString *) loggerName 96 | { 97 | return @"cocoa.lumberjack.NSLogger"; 98 | } 99 | 100 | - (void) didAddLogger 101 | { 102 | LoggerStart(self.logger); 103 | } 104 | 105 | - (void) flush 106 | { 107 | LoggerFlush(self.logger, NO); 108 | } 109 | 110 | - (void) logMessage:(DDLogMessage *)logMessage 111 | { 112 | int level = log2f(logMessage.flag); 113 | NSString *tag = self.tags[@(logMessage.context)] ?: logMessage.fileName; 114 | NSData *data = MessageAsData(logMessage.message); 115 | SetThreadNameWithMessage(logMessage); 116 | if (data) 117 | LogDataToF(self.logger, logMessage.file.UTF8String, (int)logMessage.line, logMessage.function.UTF8String, tag, level, data); 118 | else 119 | LogMessageRawToF(self.logger, logMessage.file.UTF8String, (int)logMessage.line, logMessage.function.UTF8String, tag, level, logMessage.message); 120 | } 121 | 122 | #pragma mark - NSObject 123 | 124 | - (NSString *) debugDescription 125 | { 126 | NSMutableString *debugDescription = [NSMutableString stringWithString:[super debugDescription]]; 127 | NSString *bonjourServiceName = (__bridge NSString *)LoggerGetBonjourServiceName(self.logger); 128 | NSString *viewerHost = (__bridge NSString *)LoggerGetViewerHostName(self.logger); 129 | uint32_t options = LoggerGetOptions(self.logger); 130 | NSDictionary *tags = self.tags; 131 | 132 | if (bonjourServiceName) 133 | [debugDescription appendFormat:@"\n\tBonjour Service Name: %@", bonjourServiceName]; 134 | if (viewerHost) 135 | [debugDescription appendFormat:@"\n\tViewer Host: %@:%@", viewerHost, @(LoggerGetViewerPort(self.logger))]; 136 | 137 | [debugDescription appendString:@"\n\tOptions:"]; 138 | [debugDescription appendFormat:@"\n\t\tLog To Console: %@", options & kLoggerOption_LogToConsole ? @"YES" : @"NO"]; 139 | [debugDescription appendFormat:@"\n\t\tCapture System Console: %@", options & kLoggerOption_CaptureSystemConsole ? @"YES" : @"NO"]; 140 | [debugDescription appendFormat:@"\n\t\tBuffer Logs Until Connection: %@", options & kLoggerOption_BufferLogsUntilConnection ? @"YES" : @"NO"]; 141 | [debugDescription appendFormat:@"\n\t\tBrowse Bonjour: %@", options & kLoggerOption_BrowseBonjour ? @"YES" : @"NO"]; 142 | [debugDescription appendFormat:@"\n\t\tBrowse Peer-to-Peer: %@", options & kLoggerOption_BrowsePeerToPeer ? @"YES" : @"NO"]; 143 | [debugDescription appendFormat:@"\n\t\tBrowse Only Local Domain: %@", options & kLoggerOption_BrowseOnlyLocalDomain ? @"YES" : @"NO"]; 144 | [debugDescription appendFormat:@"\n\t\tUse SSL: %@", options & kLoggerOption_UseSSL ? @"YES" : @"NO"]; 145 | 146 | if (tags.count > 0) 147 | { 148 | [debugDescription appendString:@"\n\tTags:"]; 149 | for (NSNumber *context in [[tags allKeys] sortedArrayUsingSelector:@selector(compare:)]) 150 | [debugDescription appendFormat:@"\n\t\t%@ -> %@", context, tags[context]]; 151 | } 152 | return [debugDescription copy]; 153 | } 154 | 155 | @end 156 | 157 | static NSData * MessageAsData(NSString *message) 158 | { 159 | if ([message hasPrefix:@"<"] && [message hasSuffix:@">"]) 160 | { 161 | message = [message substringWithRange:NSMakeRange(1, message.length - 2)]; 162 | message = [message stringByReplacingOccurrencesOfString:@" " withString:@""]; 163 | NSCharacterSet *hexadecimalCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"]; 164 | if (message.length % 2 == 0 && [message rangeOfCharacterFromSet:hexadecimalCharacterSet.invertedSet].location == NSNotFound) 165 | { 166 | NSMutableData *data = [NSMutableData new]; 167 | char chars[3] = {'\0','\0','\0'}; 168 | for (NSUInteger i = 0; i < message.length / 2; i++) 169 | { 170 | chars[0] = [message characterAtIndex:i*2]; 171 | chars[1] = [message characterAtIndex:i*2 + 1]; 172 | uint8_t byte = strtol(chars, NULL, 16); 173 | [data appendBytes:&byte length:sizeof(byte)]; 174 | } 175 | return data; 176 | } 177 | } 178 | return nil; 179 | } 180 | --------------------------------------------------------------------------------