├── .gitignore ├── CCLogSystem.podspec ├── CCLogSystem.xcworkspace └── contents.xcworkspacedata ├── CCLogSystem ├── CCLogSystem.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── CCLogSystem │ ├── CCFileOutputRedirectionController.h │ ├── CCLocationMake.h │ ├── CCLocationMake.m │ ├── CCLog.h │ ├── CCLog.m │ ├── CCLogController+Utility.h │ ├── CCLogController+Utility.m │ ├── CCLogController.h │ ├── CCLogController.m │ ├── CCLogReviewViewController.h │ ├── CCLogReviewViewController.m │ ├── CCLogStringImp.h │ ├── CCLogStringImp.m │ ├── CCLogSystem.h │ ├── CCLogSystem.m │ ├── CCLogViewController.h │ ├── CCLogViewController.m │ ├── CCSimpleFileOutputRedirectionController.h │ ├── CCSimpleFileOutputRedirectionController.m │ ├── CCTeeController.h │ ├── CCTeeController.m │ ├── NSObject+CCReverseComparison.h │ └── NSObject+CCReverseComparison.m └── CCLogSystemTests │ └── Info.plist ├── CCLogSystemDemo ├── CCLogSystemDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── CCLogSystemDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── CCLogSystemDemoTests │ ├── CCLogSystemDemoTests.m │ └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | .DS_Store 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | *.xccheckout 15 | *.moved-aside 16 | DerivedData 17 | *.hmap 18 | *.ipa 19 | *.xcuserstate 20 | 21 | # CocoaPods 22 | # 23 | # We recommend against adding the Pods directory to your .gitignore. However 24 | # you should judge for yourself, the pros and cons are mentioned at: 25 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 26 | # 27 | # Pods/ 28 | -------------------------------------------------------------------------------- /CCLogSystem.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "CCLogSystem" 3 | s.version = "1.0.1" 4 | s.summary = "A Log system for iOS." 5 | s.description = <<-DESC 6 | This library provide an iOS Log System. We can use it to replace NSLog. 7 | And It also can record the log to the local files. 8 | We can directly review these logs in our app, and email to ourselves. 9 | DESC 10 | s.homepage = "https://github.com/yechunjun/CCLogSystem" 11 | s.license = "MIT" 12 | s.author = { "Chun Ye" => "chunforios@gmail.com" } 13 | s.social_media_url = "http://chun.tips" 14 | s.platform = :ios, "6.0" 15 | s.source = { :git => "https://github.com/yechunjun/CCLogSystem.git", :tag => "1.0.1" } 16 | s.source_files = "CCLogSystem/CCLogSystem/*.{h,m}" 17 | s.frameworks = "Foundation", "UIKit" 18 | s.requires_arc = true 19 | end 20 | -------------------------------------------------------------------------------- /CCLogSystem.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 10 | 11 | 14 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 343C428E1A0236A700035411 /* CCLogSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 343C428D1A0236A700035411 /* CCLogSystem.m */; }; 11 | 3467CA531A035F9100DA6C84 /* CCLogViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA3E1A035F9100DA6C84 /* CCLogViewController.m */; }; 12 | 3467CA541A035F9100DA6C84 /* CCLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA3F1A035F9100DA6C84 /* CCLog.m */; }; 13 | 3467CA551A035F9100DA6C84 /* CCLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA401A035F9100DA6C84 /* CCLogController.m */; }; 14 | 3467CA561A035F9100DA6C84 /* CCLogController+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA421A035F9100DA6C84 /* CCLogController+Utility.m */; }; 15 | 3467CA571A035F9100DA6C84 /* CCLogReviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA471A035F9100DA6C84 /* CCLogReviewViewController.m */; }; 16 | 3467CA581A035F9100DA6C84 /* CCLogStringImp.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA4A1A035F9100DA6C84 /* CCLogStringImp.m */; }; 17 | 3467CA591A035F9100DA6C84 /* CCLocationMake.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA4B1A035F9100DA6C84 /* CCLocationMake.m */; }; 18 | 3467CA5A1A035F9100DA6C84 /* CCTeeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA4D1A035F9100DA6C84 /* CCTeeController.m */; }; 19 | 3467CA5B1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA4E1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.m */; }; 20 | 3467CA5C1A035F9100DA6C84 /* NSObject+CCReverseComparison.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CA511A035F9100DA6C84 /* NSObject+CCReverseComparison.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | 348FAFCD1A02325000AA05C2 /* CopyFiles */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = "include/$(PRODUCT_NAME)"; 28 | dstSubfolderSpec = 16; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXCopyFilesBuildPhase section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 343C428C1A0236A700035411 /* CCLogSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogSystem.h; sourceTree = ""; }; 37 | 343C428D1A0236A700035411 /* CCLogSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogSystem.m; sourceTree = ""; }; 38 | 3467CA3E1A035F9100DA6C84 /* CCLogViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogViewController.m; sourceTree = ""; }; 39 | 3467CA3F1A035F9100DA6C84 /* CCLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLog.m; sourceTree = ""; }; 40 | 3467CA401A035F9100DA6C84 /* CCLogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogController.m; sourceTree = ""; }; 41 | 3467CA411A035F9100DA6C84 /* CCLogController+Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CCLogController+Utility.h"; sourceTree = ""; }; 42 | 3467CA421A035F9100DA6C84 /* CCLogController+Utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CCLogController+Utility.m"; sourceTree = ""; }; 43 | 3467CA431A035F9100DA6C84 /* CCLogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogController.h; sourceTree = ""; }; 44 | 3467CA441A035F9100DA6C84 /* CCFileOutputRedirectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFileOutputRedirectionController.h; sourceTree = ""; }; 45 | 3467CA451A035F9100DA6C84 /* CCLogReviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogReviewViewController.h; sourceTree = ""; }; 46 | 3467CA461A035F9100DA6C84 /* CCLogStringImp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogStringImp.h; sourceTree = ""; }; 47 | 3467CA471A035F9100DA6C84 /* CCLogReviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogReviewViewController.m; sourceTree = ""; }; 48 | 3467CA481A035F9100DA6C84 /* CCLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLog.h; sourceTree = ""; }; 49 | 3467CA491A035F9100DA6C84 /* CCLocationMake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLocationMake.h; sourceTree = ""; }; 50 | 3467CA4A1A035F9100DA6C84 /* CCLogStringImp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogStringImp.m; sourceTree = ""; }; 51 | 3467CA4B1A035F9100DA6C84 /* CCLocationMake.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLocationMake.m; sourceTree = ""; }; 52 | 3467CA4C1A035F9100DA6C84 /* CCLogViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogViewController.h; sourceTree = ""; }; 53 | 3467CA4D1A035F9100DA6C84 /* CCTeeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTeeController.m; sourceTree = ""; }; 54 | 3467CA4E1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSimpleFileOutputRedirectionController.m; sourceTree = ""; }; 55 | 3467CA4F1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSimpleFileOutputRedirectionController.h; sourceTree = ""; }; 56 | 3467CA501A035F9100DA6C84 /* CCTeeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTeeController.h; sourceTree = ""; }; 57 | 3467CA511A035F9100DA6C84 /* NSObject+CCReverseComparison.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+CCReverseComparison.m"; sourceTree = ""; }; 58 | 3467CA521A035F9100DA6C84 /* NSObject+CCReverseComparison.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+CCReverseComparison.h"; sourceTree = ""; }; 59 | 348FAFCF1A02325000AA05C2 /* libCCLogSystem.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCCLogSystem.a; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 348FAFCC1A02325000AA05C2 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 3467CA5D1A035F9C00DA6C84 /* CCLog */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 3467CA431A035F9100DA6C84 /* CCLogController.h */, 77 | 3467CA401A035F9100DA6C84 /* CCLogController.m */, 78 | 3467CA411A035F9100DA6C84 /* CCLogController+Utility.h */, 79 | 3467CA421A035F9100DA6C84 /* CCLogController+Utility.m */, 80 | 3467CA481A035F9100DA6C84 /* CCLog.h */, 81 | 3467CA3F1A035F9100DA6C84 /* CCLog.m */, 82 | ); 83 | name = CCLog; 84 | sourceTree = ""; 85 | }; 86 | 3467CA5E1A035FB100DA6C84 /* DeveloperUI */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 3467CA451A035F9100DA6C84 /* CCLogReviewViewController.h */, 90 | 3467CA471A035F9100DA6C84 /* CCLogReviewViewController.m */, 91 | 3467CA4C1A035F9100DA6C84 /* CCLogViewController.h */, 92 | 3467CA3E1A035F9100DA6C84 /* CCLogViewController.m */, 93 | ); 94 | name = DeveloperUI; 95 | sourceTree = ""; 96 | }; 97 | 3467CA5F1A035FE100DA6C84 /* Base */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 3467CA491A035F9100DA6C84 /* CCLocationMake.h */, 101 | 3467CA4B1A035F9100DA6C84 /* CCLocationMake.m */, 102 | 3467CA461A035F9100DA6C84 /* CCLogStringImp.h */, 103 | 3467CA4A1A035F9100DA6C84 /* CCLogStringImp.m */, 104 | 3467CA521A035F9100DA6C84 /* NSObject+CCReverseComparison.h */, 105 | 3467CA511A035F9100DA6C84 /* NSObject+CCReverseComparison.m */, 106 | ); 107 | name = Base; 108 | sourceTree = ""; 109 | }; 110 | 3467CA601A03600500DA6C84 /* FileOutput */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 3467CA441A035F9100DA6C84 /* CCFileOutputRedirectionController.h */, 114 | 3467CA501A035F9100DA6C84 /* CCTeeController.h */, 115 | 3467CA4D1A035F9100DA6C84 /* CCTeeController.m */, 116 | 3467CA4F1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.h */, 117 | 3467CA4E1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.m */, 118 | ); 119 | name = FileOutput; 120 | sourceTree = ""; 121 | }; 122 | 348FAFC61A02325000AA05C2 = { 123 | isa = PBXGroup; 124 | children = ( 125 | 348FAFD11A02325000AA05C2 /* CCLogSystem */, 126 | 348FAFD01A02325000AA05C2 /* Products */, 127 | ); 128 | sourceTree = ""; 129 | }; 130 | 348FAFD01A02325000AA05C2 /* Products */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 348FAFCF1A02325000AA05C2 /* libCCLogSystem.a */, 134 | ); 135 | name = Products; 136 | sourceTree = ""; 137 | }; 138 | 348FAFD11A02325000AA05C2 /* CCLogSystem */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 3467CA601A03600500DA6C84 /* FileOutput */, 142 | 3467CA5F1A035FE100DA6C84 /* Base */, 143 | 3467CA5E1A035FB100DA6C84 /* DeveloperUI */, 144 | 3467CA5D1A035F9C00DA6C84 /* CCLog */, 145 | 343C428C1A0236A700035411 /* CCLogSystem.h */, 146 | 343C428D1A0236A700035411 /* CCLogSystem.m */, 147 | ); 148 | path = CCLogSystem; 149 | sourceTree = ""; 150 | }; 151 | /* End PBXGroup section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | 348FAFCE1A02325000AA05C2 /* CCLogSystem */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 348FAFE31A02325000AA05C2 /* Build configuration list for PBXNativeTarget "CCLogSystem" */; 157 | buildPhases = ( 158 | 348FAFCB1A02325000AA05C2 /* Sources */, 159 | 348FAFCC1A02325000AA05C2 /* Frameworks */, 160 | 348FAFCD1A02325000AA05C2 /* CopyFiles */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | ); 166 | name = CCLogSystem; 167 | productName = CCLogSystem; 168 | productReference = 348FAFCF1A02325000AA05C2 /* libCCLogSystem.a */; 169 | productType = "com.apple.product-type.library.static"; 170 | }; 171 | /* End PBXNativeTarget section */ 172 | 173 | /* Begin PBXProject section */ 174 | 348FAFC71A02325000AA05C2 /* Project object */ = { 175 | isa = PBXProject; 176 | attributes = { 177 | LastUpgradeCheck = 0610; 178 | ORGANIZATIONNAME = "Chun Tips"; 179 | TargetAttributes = { 180 | 348FAFCE1A02325000AA05C2 = { 181 | CreatedOnToolsVersion = 6.1; 182 | }; 183 | }; 184 | }; 185 | buildConfigurationList = 348FAFCA1A02325000AA05C2 /* Build configuration list for PBXProject "CCLogSystem" */; 186 | compatibilityVersion = "Xcode 3.2"; 187 | developmentRegion = English; 188 | hasScannedForEncodings = 0; 189 | knownRegions = ( 190 | en, 191 | ); 192 | mainGroup = 348FAFC61A02325000AA05C2; 193 | productRefGroup = 348FAFD01A02325000AA05C2 /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 348FAFCE1A02325000AA05C2 /* CCLogSystem */, 198 | ); 199 | }; 200 | /* End PBXProject section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 348FAFCB1A02325000AA05C2 /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 3467CA591A035F9100DA6C84 /* CCLocationMake.m in Sources */, 208 | 3467CA5C1A035F9100DA6C84 /* NSObject+CCReverseComparison.m in Sources */, 209 | 3467CA551A035F9100DA6C84 /* CCLogController.m in Sources */, 210 | 3467CA541A035F9100DA6C84 /* CCLog.m in Sources */, 211 | 3467CA581A035F9100DA6C84 /* CCLogStringImp.m in Sources */, 212 | 3467CA561A035F9100DA6C84 /* CCLogController+Utility.m in Sources */, 213 | 3467CA5B1A035F9100DA6C84 /* CCSimpleFileOutputRedirectionController.m in Sources */, 214 | 343C428E1A0236A700035411 /* CCLogSystem.m in Sources */, 215 | 3467CA531A035F9100DA6C84 /* CCLogViewController.m in Sources */, 216 | 3467CA571A035F9100DA6C84 /* CCLogReviewViewController.m in Sources */, 217 | 3467CA5A1A035F9100DA6C84 /* CCTeeController.m in Sources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXSourcesBuildPhase section */ 222 | 223 | /* Begin XCBuildConfiguration section */ 224 | 348FAFE11A02325000AA05C2 /* Debug */ = { 225 | isa = XCBuildConfiguration; 226 | buildSettings = { 227 | ALWAYS_SEARCH_USER_PATHS = NO; 228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 229 | CLANG_CXX_LIBRARY = "libc++"; 230 | CLANG_ENABLE_MODULES = YES; 231 | CLANG_ENABLE_OBJC_ARC = YES; 232 | CLANG_WARN_BOOL_CONVERSION = YES; 233 | CLANG_WARN_CONSTANT_CONVERSION = YES; 234 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 235 | CLANG_WARN_EMPTY_BODY = YES; 236 | CLANG_WARN_ENUM_CONVERSION = YES; 237 | CLANG_WARN_INT_CONVERSION = YES; 238 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 239 | CLANG_WARN_UNREACHABLE_CODE = YES; 240 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 241 | COPY_PHASE_STRIP = NO; 242 | ENABLE_STRICT_OBJC_MSGSEND = YES; 243 | GCC_C_LANGUAGE_STANDARD = gnu99; 244 | GCC_DYNAMIC_NO_PIC = NO; 245 | GCC_OPTIMIZATION_LEVEL = 0; 246 | GCC_PREPROCESSOR_DEFINITIONS = ( 247 | "DEBUG=1", 248 | "$(inherited)", 249 | ); 250 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 251 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 252 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 253 | GCC_WARN_UNDECLARED_SELECTOR = YES; 254 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 255 | GCC_WARN_UNUSED_FUNCTION = YES; 256 | GCC_WARN_UNUSED_VARIABLE = YES; 257 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 258 | MTL_ENABLE_DEBUG_INFO = YES; 259 | ONLY_ACTIVE_ARCH = YES; 260 | SDKROOT = iphoneos; 261 | }; 262 | name = Debug; 263 | }; 264 | 348FAFE21A02325000AA05C2 /* Release */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | ALWAYS_SEARCH_USER_PATHS = NO; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | COPY_PHASE_STRIP = YES; 282 | ENABLE_NS_ASSERTIONS = NO; 283 | ENABLE_STRICT_OBJC_MSGSEND = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 292 | MTL_ENABLE_DEBUG_INFO = NO; 293 | SDKROOT = iphoneos; 294 | VALIDATE_PRODUCT = YES; 295 | }; 296 | name = Release; 297 | }; 298 | 348FAFE41A02325000AA05C2 /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | OTHER_LDFLAGS = "-ObjC"; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | SKIP_INSTALL = YES; 304 | }; 305 | name = Debug; 306 | }; 307 | 348FAFE51A02325000AA05C2 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | OTHER_LDFLAGS = "-ObjC"; 311 | PRODUCT_NAME = "$(TARGET_NAME)"; 312 | SKIP_INSTALL = YES; 313 | }; 314 | name = Release; 315 | }; 316 | /* End XCBuildConfiguration section */ 317 | 318 | /* Begin XCConfigurationList section */ 319 | 348FAFCA1A02325000AA05C2 /* Build configuration list for PBXProject "CCLogSystem" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 348FAFE11A02325000AA05C2 /* Debug */, 323 | 348FAFE21A02325000AA05C2 /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | 348FAFE31A02325000AA05C2 /* Build configuration list for PBXNativeTarget "CCLogSystem" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | 348FAFE41A02325000AA05C2 /* Debug */, 332 | 348FAFE51A02325000AA05C2 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | /* End XCConfigurationList section */ 338 | }; 339 | rootObject = 348FAFC71A02325000AA05C2 /* Project object */; 340 | } 341 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCFileOutputRedirectionController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | 15 | @protocol CCFileOutputRedirectionController 16 | 17 | @property (nonatomic, strong) NSFileHandle *inputFileHandle; 18 | @property (nonatomic, strong) NSFileHandle *outputFileHandle; 19 | 20 | - (void)startRecordLog; 21 | 22 | - (void)stopRecordLog; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLocationMake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLog.h" 14 | 15 | typedef NS_ENUM(NSInteger, CCLocationStyle) { 16 | CCLocationStyleShort, // Only point FUNCTION name 17 | CCLocationStyleLong, // Point FILE FUNCTION LINE and Thread 18 | }; 19 | 20 | CC_EXTERN CCLocation CCLocationNowhere; 21 | 22 | CC_EXTERN NSString *CCStringFromLocation(CCLocation location); 23 | 24 | CC_EXTERN NSString *CCStringFromLocationWithStyle(CCLocation location, CCLocationStyle locationStyle); 25 | 26 | CC_EXTERN NSString *CCLogPrefixFromLocation (CCLocation location); 27 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLocationMake.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLocationMake.h" 14 | 15 | #pragma mark - Private 16 | 17 | static NSString *CCStringFromSourceFilePath(const char *file) 18 | { 19 | NSString *path = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:file length:strlen(file)]; 20 | NSString *string = [path lastPathComponent]; 21 | return string; 22 | } 23 | 24 | static NSString *CCStringWithSourceLocationFromLocation(CCLocation location) 25 | { 26 | NSString *string; 27 | if (!memcmp(&location, &CCLocationNowhere, sizeof(location))) { 28 | string = @""; 29 | } else { 30 | string = [NSString stringWithFormat:@"%@ at %d (%s)", CCStringFromSourceFilePath(location.file), location.line, location.func]; 31 | } 32 | return string; 33 | } 34 | 35 | #pragma mark - Public 36 | 37 | NSString *CCLogPrefixFromLocation (CCLocation location) 38 | { 39 | NSString *sourceLocationDescription = CCStringWithSourceLocationFromLocation(location); 40 | NSArray *stringArray = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%@", [NSThread currentThread].description], (sourceLocationDescription.length > 0 ? [NSString stringWithFormat:@"%@:", sourceLocationDescription] : [NSNull null]), nil]; 41 | NSString *string = [stringArray componentsJoinedByString:@" "]; 42 | return string; 43 | } 44 | 45 | NSString *CCStringFromLocationWithStyle(CCLocation location, CCLocationStyle locationStyle) 46 | { 47 | NSString *string; 48 | switch (locationStyle) { 49 | case CCLocationStyleLong: 50 | { 51 | NSString *sourceLocationDescription = CCStringWithSourceLocationFromLocation(location); 52 | NSArray *stringArray = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%@", [NSThread currentThread].description], (sourceLocationDescription.length > 0 ? [NSString stringWithFormat:@"%@", sourceLocationDescription] : [NSNull null]), nil]; 53 | string = [stringArray componentsJoinedByString:@" "]; 54 | } 55 | break; 56 | case CCLocationStyleShort: 57 | string = [NSString stringWithFormat:@"%s", location.func]; 58 | break; 59 | default: 60 | abort(); 61 | break; 62 | } 63 | return string; 64 | } 65 | 66 | NSString *CCStringFromLocation(CCLocation location) 67 | { 68 | return CCStringFromLocationWithStyle(location, CCLocationStyleLong); 69 | } 70 | 71 | CCLocation CCLocationNowhere = { 72 | CC_INITIALIZED_FIELD(file, ""), 73 | CC_INITIALIZED_FIELD(line, 0), 74 | CC_INITIALIZED_FIELD(func, "") 75 | }; 76 | 77 | 78 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | 15 | // Define 16 | #ifdef __cplusplus 17 | #define CC_EXTERN extern "C" __attribute__((visibility ("default"))) 18 | #else 19 | #define CC_EXTERN extern __attribute__((visibility ("default"))) 20 | #endif 21 | 22 | #ifdef __cplusplus 23 | # if !defined __clang__ 24 | # define CC_INITIALIZED_FIELD(name, ...) \ 25 | name: __VA_ARGS__ 26 | # else 27 | # define CC_INITIALIZED_FIELD(name, ...) \ 28 | .name = __VA_ARGS__ 29 | # endif 30 | #else 31 | # define CC_INITIALIZED_FIELD(name, ...) \ 32 | .name = __VA_ARGS__ 33 | #endif 34 | 35 | // Location 36 | typedef struct { 37 | char const *file; 38 | int line; 39 | char const *func; 40 | } CCLocation; 41 | 42 | static inline CCLocation CCLocationMake (char const *file, int line, char const *func) 43 | { 44 | CCLocation location; 45 | location.file = file; 46 | location.line = line; 47 | location.func = func; 48 | 49 | return location; 50 | } 51 | 52 | #define CC_LOCATION() \ 53 | CCLocationMake (__FILE__, __LINE__, __func__) 54 | 55 | // Log 56 | CC_EXTERN void CCLog (CCLocation location, NSString *format, ...); 57 | 58 | CC_EXTERN void switchToCCLog (void); 59 | 60 | CC_EXTERN void switchToNSLog (void); 61 | 62 | // Description 63 | CC_EXTERN NSString *CCDescriptionWithObjCTypeAndArgs (char const *objCType, ...); 64 | 65 | #define CC_STRING_FOR_LOG_VALUE(...) \ 66 | [NSString stringWithFormat:@"%s: %@", \ 67 | #__VA_ARGS__, \ 68 | CC_DESCRIPTION_FOR_VALUE(__VA_ARGS__)] 69 | 70 | #define CC_DESCRIPTION_FOR_VALUE(...) \ 71 | ({ \ 72 | CCDescriptionWithObjCTypeAndArgs ( \ 73 | @encode (__typeof__ (__VA_ARGS__)), \ 74 | (__VA_ARGS__)); \ 75 | }) 76 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLog.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLog.h" 14 | #import "CCLogStringImp.h" 15 | #import 16 | 17 | #pragma mark - Log 18 | 19 | enum CCLogImpKind { 20 | CCLogImpKindStdErr, 21 | CCLogImpKindNSLog 22 | }; 23 | 24 | enum CCLogImpKind CCLogImpKind = CCLogImpKindStdErr; 25 | 26 | static void CCLogString (CCLocation location, NSString *string) 27 | { 28 | if (CCLogImpKindStdErr == CCLogImpKind) { 29 | CCLogStringToStderr(location, string); 30 | } else { 31 | CCLogStringToNSLog(location, string); 32 | } 33 | } 34 | 35 | void switchToCCLog (void) 36 | { 37 | CCLogImpKind = CCLogImpKindStdErr; 38 | } 39 | 40 | void switchToNSLog (void) 41 | { 42 | CCLogImpKind = CCLogImpKindNSLog; 43 | } 44 | 45 | void CCLog (CCLocation location, NSString *format, ...) 46 | { 47 | NSString *string; 48 | { 49 | va_list argList; 50 | va_start(argList, format); 51 | string = [[NSString alloc] initWithFormat:format arguments:argList]; 52 | va_end(argList); 53 | } 54 | CCLogString(location, string); 55 | } 56 | 57 | #pragma mark - Description 58 | 59 | typedef NSString *(*CCDescriptionHandler) (char const *objcType, va_list argList); 60 | 61 | static inline NSString *CCObjectDescription (id object) 62 | { 63 | NSString *description = [object description]; 64 | return description; 65 | } 66 | 67 | static NSString *CCBaseDescriptionHandler (char const *objCType, va_list ap) 68 | { 69 | NSString *description; 70 | 71 | NSString *objCTypeString = [[NSString alloc] initWithUTF8String:objCType]; 72 | 73 | if ([@"c" isEqualToString: objCTypeString]) { 74 | int x = va_arg(ap, int); 75 | if (isprint (x)) { 76 | description = [NSString stringWithFormat:@"'%c'", x]; 77 | } else { 78 | description = [NSString stringWithFormat:@"%d", (int)x]; 79 | } 80 | } else if ([@"i" isEqualToString:objCTypeString]) { 81 | int i = va_arg(ap, int); 82 | description = [NSString stringWithFormat:@"%d", i]; 83 | } else if ([@"s" isEqualToString:objCTypeString]) { 84 | int s = va_arg(ap, int); 85 | description = [NSString stringWithFormat:@"%d", s]; 86 | }else if ([@"l" isEqualToString:objCTypeString]) { 87 | long l = va_arg(ap, long); 88 | description = [NSString stringWithFormat:@"%ld", l]; 89 | } else if ([@"q" isEqualToString:objCTypeString]) { 90 | long long q = va_arg(ap, long long); 91 | description = [NSString stringWithFormat:@"%lld", q]; 92 | } else if ([@"C" isEqualToString:objCTypeString]) { 93 | int C = va_arg(ap, int); 94 | description = [NSString stringWithFormat:@"%d", C]; 95 | } else if ([@"I" isEqualToString:objCTypeString]) { 96 | unsigned int I = va_arg(ap, unsigned int); 97 | description = [NSString stringWithFormat:@"%u", I]; 98 | } else if ([@"S" isEqualToString:objCTypeString]) { 99 | int S = va_arg(ap, int); 100 | description = [NSString stringWithFormat:@"%d", S]; 101 | } else if ([@"L" isEqualToString:objCTypeString]) { 102 | unsigned long L = va_arg(ap, unsigned long); 103 | description = [NSString stringWithFormat:@"%lu", L]; 104 | } else if ([@"Q" isEqualToString:objCTypeString]) { 105 | unsigned long long Q = va_arg(ap, unsigned long long); 106 | description = [NSString stringWithFormat:@"%llu", Q]; 107 | } else if ([@"f" isEqualToString:objCTypeString]) { 108 | double f = va_arg(ap, double); 109 | description = [NSString stringWithFormat:@"%f", f]; 110 | } else if ([@"d" isEqualToString:objCTypeString]) { 111 | double d = va_arg(ap, double); 112 | description = [NSString stringWithFormat:@"%g", d]; 113 | } else if ([@"*" isEqualToString:objCTypeString]) { 114 | char * point = va_arg(ap, char *); 115 | description = [NSString stringWithFormat:@"%s", point]; 116 | } else if ([@"r*" isEqualToString:objCTypeString]) { 117 | char const * constPoint = va_arg(ap, char const *); 118 | description = [NSString stringWithFormat:@"%s", constPoint]; 119 | } else if ([@"^v" isEqualToString:objCTypeString]) { 120 | void * _void = va_arg(ap, void *); 121 | description = [NSString stringWithFormat:@"%p", _void]; 122 | } else if ([@"r^v" isEqualToString:objCTypeString]) { 123 | void const * _constVoid = va_arg(ap, void const *); 124 | description = [NSString stringWithFormat:@"%p", _constVoid]; 125 | } else if ([[NSString stringWithUTF8String:"@"] isEqualToString:objCTypeString]) { 126 | id x = va_arg(ap, id); 127 | description = CCObjectDescription(x); 128 | } else if ([[NSString stringWithUTF8String:"@?"] isEqualToString:objCTypeString]) { 129 | id x = va_arg(ap, id); 130 | description = CCObjectDescription(x); 131 | } else if ([[NSString stringWithUTF8String:":"] isEqualToString:objCTypeString]) { 132 | SEL sel = va_arg(ap, SEL); 133 | description = NSStringFromSelector(sel); 134 | } else if ([[NSString stringWithUTF8String:"#"] isEqualToString:objCTypeString]) { 135 | id class = va_arg(ap, id); 136 | description = NSStringFromClass(class); 137 | } else if ([[NSString stringWithUTF8String:@encode (NSRange)] isEqualToString:objCTypeString]) { 138 | NSRange range = va_arg(ap, NSRange); 139 | description = NSStringFromRange(range); 140 | } else if ([objCTypeString hasPrefix: @"^{"]) { 141 | void *p = va_arg(ap, void *); 142 | description = [NSString stringWithFormat:@"<%@>(%p)", objCTypeString, p]; 143 | } else { 144 | if ([objCTypeString hasPrefix:@"{CGRect"]) { 145 | CGRect rect = va_arg(ap, CGRect); 146 | description = NSStringFromCGRect(rect); 147 | } else if ([objCTypeString hasPrefix:@"{CGVector"]) { 148 | CGVector vector = va_arg(ap, CGVector); 149 | description = NSStringFromCGVector(vector); 150 | } else if ([objCTypeString hasPrefix:@"{CGSize"]) { 151 | CGSize size = va_arg(ap, CGSize); 152 | description = NSStringFromCGSize(size); 153 | } else if ([objCTypeString hasPrefix:@"{CGAffineTransform"]) { 154 | CGAffineTransform transform = va_arg(ap, CGAffineTransform); 155 | description = NSStringFromCGAffineTransform(transform); 156 | } else if ([objCTypeString hasPrefix:@"{UIEdgeInsets"]) { 157 | UIEdgeInsets insets = va_arg(ap, UIEdgeInsets); 158 | description = NSStringFromUIEdgeInsets(insets); 159 | } else if ([objCTypeString hasPrefix:@"{UIOffset"]) { 160 | UIOffset offset = va_arg(ap, UIOffset); 161 | description = NSStringFromUIOffset(offset); 162 | } else { 163 | description = [NSString stringWithFormat:@"<%@>(?)", objCTypeString]; 164 | } 165 | } 166 | return description; 167 | } 168 | 169 | static CCDescriptionHandler CCCurrentDescriptionHandler; 170 | 171 | CCDescriptionHandler CCGetCurrentDescriptionHandler (void) 172 | { 173 | CCDescriptionHandler currentDescriptionHandler; 174 | if (!CCCurrentDescriptionHandler) { 175 | CCCurrentDescriptionHandler = CCBaseDescriptionHandler; 176 | } 177 | currentDescriptionHandler = CCCurrentDescriptionHandler; 178 | return currentDescriptionHandler; 179 | } 180 | 181 | void CCSetCurrentDescriptionHandler (CCDescriptionHandler handler) 182 | { 183 | CCCurrentDescriptionHandler = handler; 184 | } 185 | 186 | NSString *CCDescriptionWithObjCTypeAndArgs (char const *objCType, ...) 187 | { 188 | NSString *description; 189 | 190 | va_list ap; 191 | va_start(ap, objCType); 192 | 193 | description = CCGetCurrentDescriptionHandler() (objCType, ap); 194 | 195 | va_end(ap); 196 | 197 | return description; 198 | } -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogController+Utility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogController.h" 14 | 15 | @interface CCLogController (Utility) 16 | 17 | - (NSString *)pathForbasename:(NSString *)basename; 18 | 19 | + (NSDateFormatter *)dateFormatter; 20 | 21 | + (NSString *)basenamePrefix; 22 | 23 | + (NSString *)pathExtension; 24 | 25 | + (BOOL)forceConsoleLog; 26 | 27 | + (NSString *)basenameForDate:(NSDate *)date; 28 | 29 | + (NSString *)basenameForBasename:(NSString *)origBasename date2:(NSDate *)date2 date2Type:(NSString *)date2Type; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogController+Utility.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogController+Utility.h" 14 | 15 | @implementation CCLogController (Utility) 16 | 17 | - (NSString *)pathForbasename:(NSString *)basename 18 | { 19 | NSString *fileName = [basename stringByAppendingPathExtension:[CCLogController pathExtension]]; 20 | return [self.logsDirectory stringByAppendingPathComponent:fileName]; 21 | } 22 | 23 | + (NSString *)basenameForDate:(NSDate *)date 24 | { 25 | NSDateFormatter *dateFormatter = [CCLogController dateFormatter]; 26 | NSString *dateString = [dateFormatter stringFromDate:date]; 27 | NSString *basenamePrefix = [CCLogController basenamePrefix]; 28 | NSString *basename = [basenamePrefix stringByAppendingString:dateString]; 29 | return basename; 30 | } 31 | 32 | + (NSString *)basenameForBasename:(NSString *)origBasename date2:(NSDate *)date2 date2Type:(NSString *)date2Type 33 | { 34 | NSDateFormatter *dateFormatter = [CCLogController dateFormatter]; 35 | NSString *date2String = [dateFormatter stringFromDate:date2]; 36 | NSString *separator = [CCLogController separator]; 37 | NSString *basename = [@[origBasename, date2String, date2Type] componentsJoinedByString:separator]; 38 | return basename; 39 | } 40 | 41 | + (BOOL)forceConsoleLog 42 | { 43 | return [[[NSProcessInfo processInfo].environment objectForKey:@"NSUnbufferedIO"] boolValue]; 44 | } 45 | 46 | + (NSDateFormatter *)dateFormatter 47 | { 48 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 49 | dateFormatter.locale = [NSLocale currentLocale]; 50 | dateFormatter.dateFormat = @"yyyy-MM-dd-HHmmss"; 51 | return dateFormatter; 52 | } 53 | 54 | + (NSString *)basenamePrefix 55 | { 56 | NSString *processName = [NSProcessInfo processInfo].processName; 57 | NSString *basenamePrefix = [NSString stringWithFormat:@"%@_", processName]; 58 | return basenamePrefix; 59 | } 60 | 61 | + (NSString *)pathExtension 62 | { 63 | return @"log"; 64 | } 65 | 66 | + (NSString *)separator; 67 | { 68 | return @"_"; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | #import "CCFileOutputRedirectionController.h" 15 | #import "CCLogSystem.h" 16 | 17 | @interface CCLogController : NSObject 18 | 19 | @property (nonatomic, weak) id fileOutputRedirectionController; 20 | 21 | @property (nonatomic, copy, readonly) NSString *logsDirectory; 22 | 23 | @property (nonatomic, copy, readonly) NSArray *availableLogs; 24 | 25 | - (void)startCapturingLogsWithRedirectionController: (id )fileOutputRedirectionController logType:(CCLogType)logType; 26 | 27 | - (void)stopCapturingLogs; 28 | 29 | - (void)removeOldLogsExceedingTotalSize: (unsigned long long)maximumTotalSize savingAtLeast: (NSUInteger)minimumCount; 30 | 31 | @end -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogController.h" 14 | #import "CCLogController+Utility.h" 15 | #import 16 | 17 | #import 18 | #import 19 | #import 20 | 21 | #import "CCLog.h" 22 | #import "NSObject+CCReverseComparison.h" 23 | 24 | static NSPointerArray *_logContollerContainer; 25 | 26 | @interface CCLogController () 27 | 28 | @property (nonatomic, copy) NSString *logsDirectory; 29 | 30 | @property (nonatomic, copy) NSArray *availableLogs; 31 | 32 | @property (nonatomic, copy) NSString *outputBasename; 33 | 34 | // Crash 35 | @property (nonatomic) int stdOutDup; 36 | 37 | @property (nonatomic) BOOL stdOutToStdErrRedirectEnabledImp; 38 | 39 | @end 40 | 41 | @implementation CCLogController 42 | 43 | #pragma mark - Init 44 | 45 | + (void)load 46 | { 47 | _logContollerContainer = [[NSPointerArray alloc] initWithOptions:NSPointerFunctionsWeakMemory]; 48 | } 49 | 50 | - (id)init 51 | { 52 | self = [super init]; 53 | if (self) { 54 | NSString *fullNamespace = @"tips.chun.CCLogSystem"; 55 | 56 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 57 | self.logsDirectory = [paths[0] stringByAppendingPathComponent:fullNamespace]; 58 | } 59 | 60 | [_logContollerContainer addPointer:(__bridge void *)(self)]; 61 | 62 | return self; 63 | } 64 | 65 | #pragma mark - Set && Get 66 | 67 | - (NSArray *)availableLogs 68 | { 69 | NSArray *availableLogs; 70 | 71 | NSFileManager *fileManager = [NSFileManager defaultManager]; 72 | 73 | NSError *error; 74 | 75 | NSArray *contents = [fileManager contentsOfDirectoryAtPath:self.logsDirectory error:&error]; 76 | if (!contents) { 77 | availableLogs = nil; 78 | } else { 79 | NSString *dotAndPathExtension = [[@"a" stringByAppendingString:[CCLogController pathExtension]] substringFromIndex:1]; 80 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self endswith %@) and (self beginswith %@)", dotAndPathExtension, [CCLogController basenamePrefix]]; 81 | NSArray *filteredContents = [contents filteredArrayUsingPredicate:predicate]; 82 | NSMutableArray *filteredPaths = [NSMutableArray array]; 83 | 84 | for (NSString *filename in filteredContents) { 85 | NSString *path = [self.logsDirectory stringByAppendingPathComponent:filename]; 86 | [filteredPaths addObject:path]; 87 | } 88 | 89 | availableLogs = [filteredPaths sortedArrayUsingSelector:@selector(reverseCompare:)]; 90 | } 91 | 92 | return availableLogs; 93 | } 94 | 95 | #pragma mark - Public 96 | 97 | - (void)startCapturingLogsWithRedirectionController: (id )fileOutputRedirectionController logType:(CCLogType)logType 98 | { 99 | if (logType == CCLogTypeCCLOG) { 100 | switchToCCLog(); 101 | } else { 102 | switchToNSLog(); 103 | } 104 | 105 | NSFileManager *fileManager = [NSFileManager defaultManager]; 106 | NSString *outputBasename = [CCLogController basenameForDate:[NSDate date]]; 107 | NSString *outputFilePath = [self pathForbasename:outputBasename]; 108 | 109 | if (![fileManager fileExistsAtPath:self.logsDirectory]) { 110 | NSError *error; 111 | [fileManager createDirectoryAtPath:self.logsDirectory withIntermediateDirectories:YES attributes:nil error:&error]; 112 | } 113 | 114 | BOOL fileAlreadyExists = [fileManager fileExistsAtPath:outputFilePath]; 115 | 116 | if (!fileAlreadyExists) { 117 | NSData *data = [NSData data]; 118 | [fileManager createFileAtPath:outputFilePath contents:data attributes:nil]; 119 | } 120 | 121 | CC_LOG_VALUE(outputFilePath); 122 | 123 | NSFileHandle *outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:outputFilePath]; 124 | [outputFileHandle seekToEndOfFile]; 125 | 126 | NSFileHandle *inputFileHandle = [NSFileHandle fileHandleWithStandardError]; 127 | 128 | fileOutputRedirectionController.outputFileHandle = outputFileHandle; 129 | fileOutputRedirectionController.inputFileHandle = inputFileHandle; 130 | self.fileOutputRedirectionController = fileOutputRedirectionController; 131 | 132 | self.outputBasename = [[outputFilePath lastPathComponent] stringByDeletingPathExtension]; 133 | 134 | [self startCapturingCrashLog]; 135 | } 136 | 137 | - (void)stopCapturingLogs 138 | { 139 | [self flush]; 140 | self.fileOutputRedirectionController = nil; 141 | } 142 | 143 | - (void)removeOldLogsExceedingTotalSize: (unsigned long long)maximumTotalSize savingAtLeast: (NSUInteger)minimumCount 144 | { 145 | NSArray *availableLogs = [self availableLogs]; 146 | 147 | if (availableLogs && availableLogs.count > 0) { 148 | NSFileManager *fileManager = [NSFileManager defaultManager]; 149 | 150 | unsigned long long totalSize = 0ULL; 151 | 152 | NSUInteger index; 153 | 154 | for (index = 0; index < availableLogs.count; index ++) { 155 | NSString *path = [availableLogs objectAtIndex:index]; 156 | NSError *error; 157 | NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:&error]; 158 | if (attributes) { 159 | unsigned long long fileSize = [[attributes valueForKey:@"NSFileSize"] longLongValue]; 160 | unsigned long long updatedTotalSize = fileSize + totalSize; 161 | if (updatedTotalSize > maximumTotalSize) { 162 | if (index < minimumCount) { 163 | index = MIN(minimumCount, availableLogs.count); 164 | } 165 | break; 166 | } else { 167 | totalSize = updatedTotalSize; 168 | } 169 | } 170 | } 171 | 172 | NSArray *logsForRemoval = [availableLogs subarrayWithRange:NSMakeRange(index, availableLogs.count - index)]; 173 | 174 | for (NSString *pathForRemoval in logsForRemoval) { 175 | NSError *error; 176 | [fileManager removeItemAtPath:pathForRemoval error:&error]; 177 | } 178 | } 179 | } 180 | 181 | #pragma mark - Private && Log 182 | 183 | - (void)flush 184 | { 185 | fflush (stderr); 186 | fflush (stdout); 187 | 188 | [self.fileOutputRedirectionController stopRecordLog]; 189 | } 190 | 191 | - (void)relocateLogToType:(NSString *)type 192 | { 193 | NSFileManager *fileManager = [NSFileManager defaultManager]; 194 | NSString *basename = [CCLogController basenameForBasename:self.outputBasename date2:[NSDate date] date2Type:type]; 195 | NSString *outputFilePath = [self pathForbasename:self.outputBasename]; 196 | NSString *updatedPath = [self pathForbasename:basename]; 197 | 198 | [fileManager linkItemAtPath:outputFilePath toPath:updatedPath error:NULL]; 199 | 200 | [fileManager removeItemAtPath:outputFilePath error:NULL]; 201 | 202 | self.outputBasename = basename; 203 | } 204 | 205 | #pragma mark - Private && Crash 206 | 207 | static NSUncaughtExceptionHandler *originUncaughtExceptionHandler; 208 | 209 | - (void)formulateCrashLog 210 | { 211 | [self relocateLogToType:@"crashed"]; 212 | 213 | [self setStdOutToStdErrRedirectEnabled:NO]; 214 | 215 | [self stopCapturingLogs]; 216 | 217 | asl_add_log_file (NULL, STDERR_FILENO); 218 | } 219 | 220 | static void logAwareUncaughtExceptionHandler (NSException *exception) 221 | { 222 | CC_LOG_VALUE(exception.name); 223 | CC_LOG_VALUE(exception); 224 | CC_LOG_VALUE(exception.userInfo); 225 | CC_LOG_VALUE(exception.callStackSymbols); 226 | 227 | if (originUncaughtExceptionHandler) { 228 | originUncaughtExceptionHandler(exception); 229 | } 230 | 231 | [_logContollerContainer.allObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 232 | [obj formulateCrashLog]; 233 | }]; 234 | } 235 | 236 | - (void)startCapturingCrashLog 237 | { 238 | [self setStdOutToStdErrRedirectEnabled:YES]; 239 | 240 | originUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); 241 | 242 | NSSetUncaughtExceptionHandler(logAwareUncaughtExceptionHandler); 243 | } 244 | 245 | - (void)stopCapturingCrashLog 246 | { 247 | NSSetUncaughtExceptionHandler (originUncaughtExceptionHandler); 248 | 249 | [self setStdOutToStdErrRedirectEnabled:NO]; 250 | 251 | [self stopCapturingLogs]; 252 | } 253 | 254 | - (void)setStdOutToStdErrRedirectEnabled:(BOOL)redirectEnabled 255 | { 256 | if (redirectEnabled) { 257 | int stdOutDup = dup(STDOUT_FILENO); 258 | dup2(STDERR_FILENO, STDOUT_FILENO); 259 | self.stdOutDup = stdOutDup; 260 | } else { 261 | dup2(self.stdOutDup, STDOUT_FILENO); 262 | close(self.stdOutDup); 263 | } 264 | 265 | self.stdOutToStdErrRedirectEnabledImp = redirectEnabled; 266 | } 267 | 268 | - (BOOL)stdOutToStdErrRedirectEnabled 269 | { 270 | return self.stdOutToStdErrRedirectEnabledImp; 271 | } 272 | 273 | @end 274 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogReviewViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | 15 | @interface CCLogReviewViewController : UIViewController 16 | 17 | - (id)initWithLogPathURL:(NSURL *)logPathURL; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogReviewViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogReviewViewController.h" 14 | #import "CCLogSystem.h" 15 | 16 | @import MessageUI; 17 | 18 | @interface CCLogReviewViewController () 19 | 20 | @property (nonatomic, strong) NSURL *currentLogPathURL; 21 | 22 | @property (nonatomic, strong) UIWebView *webView; 23 | 24 | @end 25 | 26 | @implementation CCLogReviewViewController 27 | 28 | - (id)initWithLogPathURL:(NSURL *)logPathURL; 29 | { 30 | self = [super init]; 31 | if (self) { 32 | self.currentLogPathURL = logPathURL; 33 | 34 | self.title = [self.currentLogPathURL lastPathComponent]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)viewDidLoad 40 | { 41 | [super viewDidLoad]; 42 | 43 | self.webView = [[UIWebView alloc] initWithFrame:CGRectZero]; 44 | self.webView.backgroundColor = [UIColor whiteColor]; 45 | self.webView.translatesAutoresizingMaskIntoConstraints = NO; 46 | self.webView.delegate = self; 47 | [self.view addSubview:self.webView]; 48 | 49 | NSDictionary *views = NSDictionaryOfVariableBindings(_webView); 50 | NSMutableArray *constraits = [NSMutableArray array]; 51 | [constraits addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_webView]|" options:0 metrics:nil views:views]]; 52 | [constraits addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_webView]|" options:0 metrics:nil views:views]]; 53 | [self.view addConstraints:constraits]; 54 | 55 | [self loadLogData]; 56 | 57 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Email" style:UIBarButtonItemStylePlain target:self action:@selector(handleEmailBarButtonItem)]; 58 | } 59 | 60 | #pragma mark - Private 61 | 62 | - (void)handleEmailBarButtonItem 63 | { 64 | if ([MFMailComposeViewController canSendMail]) { 65 | MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init]; 66 | NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 67 | NSString *appVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"]; 68 | NSString *appBuild = [infoDictionary objectForKey:@"CFBundleVersion"]; 69 | NSString *processName = [NSProcessInfo processInfo].processName; 70 | [mailController setSubject:[NSString stringWithFormat:@"%@ Log Report ", processName, appVersion, appBuild]]; 71 | [mailController setMailComposeDelegate:self]; 72 | 73 | NSData *logData = [[NSData alloc] initWithContentsOfURL:self.currentLogPathURL]; 74 | [mailController addAttachmentData:logData mimeType:@"com.apple.log" fileName:self.currentLogPathURL.lastPathComponent]; 75 | 76 | [self presentViewController:mailController animated:YES completion:NULL]; 77 | } else { 78 | [[[UIAlertView alloc] initWithTitle:@"" message:@"Configure your email account in iOS Settings." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; 79 | } 80 | } 81 | 82 | - (void)loadLogData 83 | { 84 | [self.webView loadRequest:[NSURLRequest requestWithURL:self.currentLogPathURL]]; 85 | } 86 | 87 | #pragma mark - MFMailComposeViewControllerDelegate 88 | 89 | - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error 90 | { 91 | [controller dismissViewControllerAnimated:YES completion:NULL]; 92 | } 93 | 94 | #pragma mark - UIWebViewDelegate 95 | 96 | - (void)webViewDidFinishLoad:(UIWebView *)webView 97 | { 98 | CGSize webviewContentSize = webView.scrollView.contentSize; 99 | [webView.scrollView scrollRectToVisible:CGRectMake(0, webviewContentSize.height - webView.bounds.size.height, webView.bounds.size.width, webView.bounds.size.height) animated:NO]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogStringImp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLog.h" 14 | 15 | // Use fprintf 16 | CC_EXTERN void CCLogStringToStderr (CCLocation location, NSString *string); 17 | 18 | // Use NSLog 19 | CC_EXTERN void CCLogStringToNSLog (CCLocation location, NSString *string); 20 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogStringImp.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogStringImp.h" 14 | #import "CCLocationMake.h" 15 | 16 | #pragma mark - Private 17 | 18 | static NSDateFormatter *regeneratedLogDateFormatter (void) 19 | { 20 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 21 | dateFormatter.locale = [NSLocale currentLocale]; 22 | dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; 23 | return dateFormatter; 24 | } 25 | 26 | static NSObject *CCNullForZeroLengthString (NSString *string) 27 | { 28 | return [string length] ? string : [NSNull null]; 29 | } 30 | 31 | static NSString *stringWithLogInfo (CCLocation location, NSString *logInfo) 32 | { 33 | NSString *body = [[NSArray arrayWithObjects:@".", CCNullForZeroLengthString(CCLogPrefixFromLocation(location)), logInfo, nil] componentsJoinedByString:@" "]; 34 | 35 | NSString *timestamp = [regeneratedLogDateFormatter() stringFromDate:[NSDate date]]; 36 | 37 | NSString *string = [NSString stringWithFormat:@"%@ %@", timestamp, body]; 38 | 39 | return string; 40 | } 41 | 42 | #pragma mark - Public 43 | 44 | void CCLogStringToNSLog (CCLocation location, NSString *string) 45 | { 46 | NSString *logString = stringWithLogInfo(location, string); 47 | NSLog(@"%@", logString); 48 | } 49 | 50 | void CCLogStringToStderr (CCLocation location, NSString *string) 51 | { 52 | NSString *logString = stringWithLogInfo(location, string); 53 | fprintf (stderr, "%s\n", [logString UTF8String]); 54 | } -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogSystem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | #import "CCLog.h" 15 | 16 | // Support two types for logging, CCLog and NSLog. 17 | // CCLog uses 'fprintf' 18 | typedef NS_ENUM(NSInteger, CCLogType) { 19 | CCLogTypeCCLOG = 0, 20 | CCLogTypeNSLOG, 21 | }; 22 | 23 | // Use this Macro to log 24 | // Like: CC_LOG(@"This is a Log."); 25 | // The default output is "Timestamp + Thread Info + FILE + LINE + FUNCTION + Log content", like: "2014-10-31 10:09:05.361 . {number = 1, name = main} AppDelegate.m at 24 (-[AppDelegate log]): @"Thi is a Log" 26 | #define CC_LOG(...) \ 27 | CCLog (CC_LOCATION(), __VA_ARGS__) 28 | 29 | // Use this Macro to directly log any value 30 | // Like CC_LOG_VALUE(self.window) or CC_LOG_VALUE(self.window.frame) 31 | #define CC_LOG_VALUE(...) \ 32 | CC_LOG(@"%@", CC_STRING_FOR_LOG_VALUE(__VA_ARGS__)) 33 | 34 | @interface CCLogSystem : NSObject 35 | 36 | // Set up default log configure, the default exceedint total log size is 10*1024*1024, ang logType is CCLogTypeCCLOG 37 | // We should call this function at "- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions" 38 | + (void)setupDefaultLogConfigure; 39 | 40 | // We need to set up the log environment when our app launch 41 | // totalLogSize : exceeding total log size, If log size is more than toalLogSize, will do some clean. 42 | // logType: Support CCLogTypeCCLOG and CCLogTypeNSLOG 43 | + (void)setupLogConfigureWithExceedingTotalLogSize:(unsigned long long)toalLogSize logType:(CCLogType)logType; 44 | 45 | // Call this method, If we want to review the logs, and we can email the log in Developer UI. 46 | + (void)activeDeveloperUI; 47 | 48 | // Return the available logs 49 | // If must call after setup log environment 50 | + (NSArray *)availableLogs; 51 | 52 | @end 53 | 54 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogSystem.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogSystem.h" 14 | #import "CCLogController.h" 15 | #import "CCLogController+Utility.h" 16 | #import "CCTeeController.h" 17 | #import "CCSimpleFileOutputRedirectionController.h" 18 | #import "CCLogViewController.h" 19 | #import "CCLogController.h" 20 | 21 | #define DEFAULT_EXCEEDING_TOTAL_LOG_SIZE 10*1024*1024 22 | 23 | @interface CCLogSystem () 24 | 25 | @property (nonatomic, strong) CCLogController *logController; 26 | 27 | @property (nonatomic, strong) NSObject *redirectionController; 28 | 29 | @end 30 | 31 | @implementation CCLogSystem 32 | 33 | + (CCLogSystem *)defaultLogSystem 34 | { 35 | static dispatch_once_t onceToken; 36 | static CCLogSystem *_defaultLogConfigure; 37 | dispatch_once(&onceToken, ^{ 38 | _defaultLogConfigure = [[self alloc] init]; 39 | }); 40 | return _defaultLogConfigure; 41 | } 42 | 43 | - (id)init 44 | { 45 | self = [super init]; 46 | if (self) { 47 | self.logController = [[CCLogController alloc] init]; 48 | } 49 | return self; 50 | } 51 | 52 | + (void)setupDefaultLogConfigure 53 | { 54 | [self setupLogConfigureWithExceedingTotalLogSize:DEFAULT_EXCEEDING_TOTAL_LOG_SIZE logType:CCLogTypeCCLOG]; 55 | } 56 | 57 | + (void)setupLogConfigureWithExceedingTotalLogSize:(unsigned long long)toalLogSize logType:(CCLogType)logType 58 | { 59 | CCLogSystem *logConfigure = [CCLogSystem defaultLogSystem]; 60 | 61 | [logConfigure.logController removeOldLogsExceedingTotalSize:toalLogSize savingAtLeast:10]; 62 | 63 | if (!logConfigure.redirectionController) { 64 | if ([CCLogController forceConsoleLog]) { 65 | logConfigure.redirectionController = [[CCTeeController alloc] init]; 66 | } else { 67 | logConfigure.redirectionController = [[CCSimpleFileOutputRedirectionController alloc] init]; 68 | } 69 | [logConfigure.logController startCapturingLogsWithRedirectionController:logConfigure.redirectionController logType:logType]; 70 | [logConfigure.redirectionController startRecordLog]; 71 | } 72 | } 73 | 74 | + (void)activeDeveloperUI 75 | { 76 | CCLogViewController *logViewController = [[CCLogViewController alloc] init]; 77 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:logViewController]; 78 | 79 | UIApplication *application = [UIApplication sharedApplication]; 80 | [application.windows enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 81 | if ([obj isKeyWindow]) { 82 | UIWindow *keyWindow = obj; 83 | if (keyWindow.rootViewController) { 84 | [keyWindow.rootViewController presentViewController:navigationController animated:YES completion:NULL]; 85 | } 86 | } 87 | }]; 88 | } 89 | 90 | + (NSArray *)availableLogs 91 | { 92 | if ([CCLogSystem defaultLogSystem].logController) { 93 | return [CCLogSystem defaultLogSystem].logController.availableLogs; 94 | } else { 95 | return nil; 96 | } 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | 15 | @interface CCLogViewController : UITableViewController 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCLogViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCLogViewController.h" 14 | #import "CCLogController.h" 15 | #import "CCLogSystem.h" 16 | #import "CCLogReviewViewController.h" 17 | 18 | static NSString *UITableViewCellReuseIdentifier = @"UITableViewCell"; 19 | 20 | @interface CCLogViewController () 21 | 22 | @property (nonatomic, strong) NSMutableArray *logDatas; 23 | 24 | @end 25 | 26 | @implementation CCLogViewController 27 | 28 | #pragma mark - Life 29 | 30 | - (id)initWithStyle:(UITableViewStyle)style 31 | { 32 | self = [super initWithStyle:UITableViewStylePlain]; 33 | if (self) { 34 | self.title = @"Developer UI"; 35 | 36 | self.logDatas = [NSMutableArray array]; 37 | [self.logDatas addObjectsFromArray:[CCLogSystem availableLogs]]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)viewDidLoad 43 | { 44 | [super viewDidLoad]; 45 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(handleCloseBarButtonitem)]; 46 | } 47 | 48 | #pragma mark - Private 49 | 50 | - (NSString *)logPathStringWithIndexPath:(NSIndexPath *)indexPath 51 | { 52 | return [self.logDatas objectAtIndex:indexPath.row]; 53 | } 54 | 55 | - (void)handleCloseBarButtonitem 56 | { 57 | [self dismissViewControllerAnimated:YES completion:NULL]; 58 | } 59 | 60 | #pragma mark - UITableView 61 | 62 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 63 | { 64 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:UITableViewCellReuseIdentifier]; 65 | if (!cell) { 66 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:UITableViewCellReuseIdentifier]; 67 | } 68 | NSString *logPath = [self logPathStringWithIndexPath:indexPath]; 69 | cell.textLabel.text = [logPath lastPathComponent]; 70 | cell.textLabel.numberOfLines = 0; 71 | return cell; 72 | } 73 | 74 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 75 | { 76 | return self.logDatas.count; 77 | } 78 | 79 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 80 | { 81 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 82 | 83 | NSString *logPathString = [self logPathStringWithIndexPath:indexPath]; 84 | NSURL *logPathURL = [NSURL fileURLWithPath:logPathString]; 85 | CCLogReviewViewController *logReviewViewController = [[CCLogReviewViewController alloc] initWithLogPathURL:logPathURL]; 86 | [self.navigationController pushViewController:logReviewViewController animated:YES]; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCSimpleFileOutputRedirectionController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | #import "CCFileOutputRedirectionController.h" 15 | 16 | @interface CCSimpleFileOutputRedirectionController : NSObject 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCSimpleFileOutputRedirectionController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCSimpleFileOutputRedirectionController.h" 14 | 15 | @interface CCSimpleFileOutputRedirectionController () 16 | 17 | @property (nonatomic, strong) NSFileHandle *inputFileHandleDup; 18 | 19 | @end 20 | 21 | @implementation CCSimpleFileOutputRedirectionController 22 | @synthesize inputFileHandle; 23 | @synthesize outputFileHandle; 24 | 25 | - (void)startRecordLog 26 | { 27 | int inputFileDescriptionDup = dup(self.inputFileHandle.fileDescriptor); 28 | dup2(self.outputFileHandle.fileDescriptor, self.inputFileHandle.fileDescriptor); 29 | 30 | self.inputFileHandleDup = [[NSFileHandle alloc] initWithFileDescriptor:inputFileDescriptionDup]; 31 | } 32 | 33 | - (void)stopRecordLog 34 | { 35 | dup2(self.inputFileHandleDup.fileDescriptor, self.inputFileHandle.fileDescriptor); 36 | self.inputFileHandleDup = nil; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCTeeController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | #import "CCFileOutputRedirectionController.h" 15 | 16 | @interface CCTeeController : NSObject 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/CCTeeController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "CCTeeController.h" 14 | #import 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import "CCLogSystem.h" 21 | 22 | @interface CCTeeController () 23 | 24 | @property (nonatomic, strong) NSPipe *dataPipe; 25 | 26 | @property (nonatomic, strong) NSPipe *pipeForSignallingEOF; 27 | 28 | @property (nonatomic, strong) NSOperation *operation; 29 | 30 | @property (nonatomic, strong) NSOperationQueue *operationQueue; 31 | 32 | @property (nonatomic, strong) NSFileHandle *inputFileHandleDup; 33 | 34 | @property (nonatomic) BOOL closingInputFileHandleDup; 35 | 36 | @end 37 | 38 | @implementation CCTeeController 39 | @synthesize inputFileHandle; 40 | @synthesize outputFileHandle; 41 | 42 | - (void)startRecordLog 43 | { 44 | NSPipe *pipe = [NSPipe pipe]; 45 | 46 | int inputFileDescriptionDup = dup(self.inputFileHandle.fileDescriptor); 47 | dup2(pipe.fileHandleForWriting.fileDescriptor, self.inputFileHandle.fileDescriptor); 48 | 49 | self.dataPipe = pipe; 50 | 51 | self.inputFileHandleDup = [[NSFileHandle alloc] initWithFileDescriptor:inputFileDescriptionDup]; 52 | 53 | self.pipeForSignallingEOF = [NSPipe pipe]; 54 | 55 | self.operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread:) object:nil]; 56 | self.operationQueue = [[NSOperationQueue alloc] init]; 57 | [self.operationQueue addOperation:self.operation]; 58 | } 59 | 60 | - (void)stopRecordLog 61 | { 62 | self.closingInputFileHandleDup = YES; 63 | 64 | [self.pipeForSignallingEOF.fileHandleForWriting writeData:[@"" dataUsingEncoding: NSUTF8StringEncoding]]; 65 | 66 | [self.operationQueue waitUntilAllOperationsAreFinished]; 67 | 68 | [self.dataPipe.fileHandleForWriting closeFile]; 69 | 70 | dup2(self.inputFileHandleDup.fileDescriptor, self.inputFileHandle.fileDescriptor); 71 | 72 | self.closingInputFileHandleDup = NO; 73 | 74 | self.inputFileHandleDup = nil; 75 | 76 | self.dataPipe = nil; 77 | self.pipeForSignallingEOF = nil; 78 | } 79 | 80 | #pragma mark - 81 | #pragma mark - Thread 82 | 83 | - (void)thread:(NSDictionary *)arg 84 | { 85 | @autoreleasepool { 86 | BOOL shouldTerminate = NO; 87 | 88 | NSFileHandle *fileHandleForReading = self.dataPipe.fileHandleForReading; 89 | NSFileHandle *fileHandleForSignallingEOF = self.pipeForSignallingEOF.fileHandleForReading; 90 | 91 | int kq = kqueue(); 92 | 93 | NSFileHandle *kqueueFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:kq closeOnDealloc:YES]; 94 | 95 | struct kevent changes[2]; 96 | EV_SET (&changes[0], fileHandleForReading.fileDescriptor, EVFILT_READ, EV_ADD, 0, 0, 0); 97 | EV_SET (&changes[1], fileHandleForSignallingEOF.fileDescriptor, EVFILT_READ, EV_ADD, 0, 0, 0); 98 | 99 | while (!shouldTerminate) { 100 | BOOL hasEOF; 101 | BOOL hasData; 102 | NSUInteger availableDataLength; 103 | BOOL hasPOSIXError; 104 | NSInteger POSIXError; 105 | struct kevent event; 106 | 107 | int numberOfEvents = kevent (kqueueFileHandle.fileDescriptor, changes, sizeof (changes) / sizeof (changes[0]), &event, 1, NULL); 108 | 109 | if (-1 == numberOfEvents) { 110 | availableDataLength = 0; 111 | hasData = NO; 112 | hasEOF = NO; 113 | hasPOSIXError = YES; 114 | POSIXError = errno; 115 | } else if (0 == numberOfEvents) { 116 | availableDataLength = 0; 117 | hasData = NO; 118 | hasEOF = NO; 119 | hasPOSIXError = NO; 120 | POSIXError = 0; 121 | } else if (1 < numberOfEvents) { 122 | abort (); 123 | } else if (EV_ERROR & event.flags) { 124 | availableDataLength = 0; 125 | hasData = NO; 126 | hasEOF = NO; 127 | hasPOSIXError = YES; 128 | POSIXError = event.data; 129 | } else if (event.ident == (uintptr_t)fileHandleForReading.fileDescriptor) { 130 | hasData = 0 != event.data; 131 | availableDataLength = event.data; 132 | hasEOF = 0 != (EV_EOF & event.flags); 133 | hasPOSIXError = NO; 134 | POSIXError = 0; 135 | } else if (event.ident == (uintptr_t)fileHandleForSignallingEOF.fileDescriptor) { 136 | hasData = NO; 137 | availableDataLength = 0; 138 | hasEOF = 0 != event.data; 139 | hasPOSIXError = NO; 140 | POSIXError = 0; 141 | } else { 142 | abort (); 143 | } 144 | 145 | shouldTerminate = hasEOF || hasPOSIXError; 146 | 147 | if (hasPOSIXError) { 148 | CC_LOG_VALUE(POSIXError); 149 | } 150 | 151 | if (hasData) { 152 | NSData *data = [fileHandleForReading readDataOfLength:availableDataLength]; 153 | [self.outputFileHandle writeData:data]; 154 | if (hasEOF) { 155 | [self.inputFileHandle writeData:data]; 156 | } else { 157 | [self.inputFileHandleDup writeData:data]; 158 | } 159 | } 160 | } 161 | } 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/NSObject+CCReverseComparison.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import 14 | 15 | @interface NSObject (CCReverseComparison) 16 | 17 | - (NSComparisonResult)reverseCompare:(id)object; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystem/NSObject+CCReverseComparison.m: -------------------------------------------------------------------------------- 1 | /* 2 | * CCLogSystem - A Log system for iOS.Support print, record and review logs: 3 | * 4 | * https://github.com/yechunjun/CCLogSystem 5 | * 6 | * This code is distributed under the terms and conditions of the MIT license. 7 | * 8 | * Author: 9 | * Chun Ye 10 | * 11 | */ 12 | 13 | #import "NSObject+CCReverseComparison.h" 14 | #import "CCLogSystem.h" 15 | 16 | @interface NSObject (CCComparison) 17 | 18 | - (NSComparisonResult)compare:(id)object; 19 | 20 | @end 21 | 22 | @implementation NSObject (CCReverseComparison) 23 | 24 | - (NSComparisonResult)reverseCompare:(id)object 25 | { 26 | NSComparisonResult directComparisonResult = NSOrderedSame; 27 | if ([self respondsToSelector:@selector(compare:)]) { 28 | directComparisonResult = [self compare: object]; 29 | NSComparisonResult comparisonResult = (NSOrderedAscending == directComparisonResult) 30 | ? (NSComparisonResult) NSOrderedDescending 31 | : ((NSOrderedDescending == directComparisonResult) 32 | ? (NSComparisonResult) NSOrderedAscending 33 | : directComparisonResult); 34 | 35 | return comparisonResult; 36 | } else { 37 | CC_LOG(@"!!! %@ -> This object didn't implement \"comare\" function.", self); 38 | return directComparisonResult; 39 | } 40 | } 41 | 42 | @end 43 | 44 | -------------------------------------------------------------------------------- /CCLogSystem/CCLogSystemTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | chun.tips.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3465FADF1A033593007632EF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3465FADE1A033593007632EF /* main.m */; }; 11 | 3465FAE21A033593007632EF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3465FAE11A033593007632EF /* AppDelegate.m */; }; 12 | 3465FAE51A033593007632EF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3465FAE41A033593007632EF /* ViewController.m */; }; 13 | 3465FAE81A033593007632EF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3465FAE61A033593007632EF /* Main.storyboard */; }; 14 | 3465FAEA1A033593007632EF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3465FAE91A033593007632EF /* Images.xcassets */; }; 15 | 3465FAED1A033593007632EF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3465FAEB1A033593007632EF /* LaunchScreen.xib */; }; 16 | 3465FAF91A033593007632EF /* CCLogSystemDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3465FAF81A033593007632EF /* CCLogSystemDemoTests.m */; }; 17 | 3467CAB81A03658F00DA6C84 /* CCLocationMake.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAA31A03658F00DA6C84 /* CCLocationMake.m */; }; 18 | 3467CAB91A03658F00DA6C84 /* CCLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAA51A03658F00DA6C84 /* CCLog.m */; }; 19 | 3467CABA1A03658F00DA6C84 /* CCLogController+Utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAA71A03658F00DA6C84 /* CCLogController+Utility.m */; }; 20 | 3467CABB1A03658F00DA6C84 /* CCLogController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAA91A03658F00DA6C84 /* CCLogController.m */; }; 21 | 3467CABC1A03658F00DA6C84 /* CCLogReviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAAB1A03658F00DA6C84 /* CCLogReviewViewController.m */; }; 22 | 3467CABD1A03658F00DA6C84 /* CCLogStringImp.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAAD1A03658F00DA6C84 /* CCLogStringImp.m */; }; 23 | 3467CABE1A03658F00DA6C84 /* CCLogSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAAF1A03658F00DA6C84 /* CCLogSystem.m */; }; 24 | 3467CABF1A03658F00DA6C84 /* CCLogViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAB11A03658F00DA6C84 /* CCLogViewController.m */; }; 25 | 3467CAC01A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAB31A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.m */; }; 26 | 3467CAC11A03658F00DA6C84 /* CCTeeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAB51A03658F00DA6C84 /* CCTeeController.m */; }; 27 | 3467CAC21A03658F00DA6C84 /* NSObject+CCReverseComparison.m in Sources */ = {isa = PBXBuildFile; fileRef = 3467CAB71A03658F00DA6C84 /* NSObject+CCReverseComparison.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 3465FAF31A033593007632EF /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 3465FAD11A033593007632EF /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 3465FAD81A033593007632EF; 36 | remoteInfo = CCLogSystemDemo; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 3465FAD91A033593007632EF /* CCLogSystemDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CCLogSystemDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 3465FADD1A033593007632EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 3465FADE1A033593007632EF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | 3465FAE01A033593007632EF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | 3465FAE11A033593007632EF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | 3465FAE31A033593007632EF /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 47 | 3465FAE41A033593007632EF /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 48 | 3465FAE71A033593007632EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 3465FAE91A033593007632EF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 50 | 3465FAEC1A033593007632EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 51 | 3465FAF21A033593007632EF /* CCLogSystemDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CCLogSystemDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 3465FAF71A033593007632EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 3465FAF81A033593007632EF /* CCLogSystemDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CCLogSystemDemoTests.m; sourceTree = ""; }; 54 | 3467CAA11A03658F00DA6C84 /* CCFileOutputRedirectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFileOutputRedirectionController.h; sourceTree = ""; }; 55 | 3467CAA21A03658F00DA6C84 /* CCLocationMake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLocationMake.h; sourceTree = ""; }; 56 | 3467CAA31A03658F00DA6C84 /* CCLocationMake.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLocationMake.m; sourceTree = ""; }; 57 | 3467CAA41A03658F00DA6C84 /* CCLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLog.h; sourceTree = ""; }; 58 | 3467CAA51A03658F00DA6C84 /* CCLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLog.m; sourceTree = ""; }; 59 | 3467CAA61A03658F00DA6C84 /* CCLogController+Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CCLogController+Utility.h"; sourceTree = ""; }; 60 | 3467CAA71A03658F00DA6C84 /* CCLogController+Utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CCLogController+Utility.m"; sourceTree = ""; }; 61 | 3467CAA81A03658F00DA6C84 /* CCLogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogController.h; sourceTree = ""; }; 62 | 3467CAA91A03658F00DA6C84 /* CCLogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogController.m; sourceTree = ""; }; 63 | 3467CAAA1A03658F00DA6C84 /* CCLogReviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogReviewViewController.h; sourceTree = ""; }; 64 | 3467CAAB1A03658F00DA6C84 /* CCLogReviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogReviewViewController.m; sourceTree = ""; }; 65 | 3467CAAC1A03658F00DA6C84 /* CCLogStringImp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogStringImp.h; sourceTree = ""; }; 66 | 3467CAAD1A03658F00DA6C84 /* CCLogStringImp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogStringImp.m; sourceTree = ""; }; 67 | 3467CAAE1A03658F00DA6C84 /* CCLogSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogSystem.h; sourceTree = ""; }; 68 | 3467CAAF1A03658F00DA6C84 /* CCLogSystem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogSystem.m; sourceTree = ""; }; 69 | 3467CAB01A03658F00DA6C84 /* CCLogViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLogViewController.h; sourceTree = ""; }; 70 | 3467CAB11A03658F00DA6C84 /* CCLogViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLogViewController.m; sourceTree = ""; }; 71 | 3467CAB21A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSimpleFileOutputRedirectionController.h; sourceTree = ""; }; 72 | 3467CAB31A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSimpleFileOutputRedirectionController.m; sourceTree = ""; }; 73 | 3467CAB41A03658F00DA6C84 /* CCTeeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTeeController.h; sourceTree = ""; }; 74 | 3467CAB51A03658F00DA6C84 /* CCTeeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTeeController.m; sourceTree = ""; }; 75 | 3467CAB61A03658F00DA6C84 /* NSObject+CCReverseComparison.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+CCReverseComparison.h"; sourceTree = ""; }; 76 | 3467CAB71A03658F00DA6C84 /* NSObject+CCReverseComparison.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+CCReverseComparison.m"; sourceTree = ""; }; 77 | /* End PBXFileReference section */ 78 | 79 | /* Begin PBXFrameworksBuildPhase section */ 80 | 3465FAD61A033593007632EF /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 3465FAEF1A033593007632EF /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | 3465FAD01A033593007632EF = { 98 | isa = PBXGroup; 99 | children = ( 100 | 3465FADB1A033593007632EF /* CCLogSystemDemo */, 101 | 3465FAF51A033593007632EF /* CCLogSystemDemoTests */, 102 | 3465FADA1A033593007632EF /* Products */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | 3465FADA1A033593007632EF /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 3465FAD91A033593007632EF /* CCLogSystemDemo.app */, 110 | 3465FAF21A033593007632EF /* CCLogSystemDemoTests.xctest */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | 3465FADB1A033593007632EF /* CCLogSystemDemo */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 3467CAA01A03658F00DA6C84 /* CCLogSystem */, 119 | 3465FAE01A033593007632EF /* AppDelegate.h */, 120 | 3465FAE11A033593007632EF /* AppDelegate.m */, 121 | 3465FAE31A033593007632EF /* ViewController.h */, 122 | 3465FAE41A033593007632EF /* ViewController.m */, 123 | 3465FAE61A033593007632EF /* Main.storyboard */, 124 | 3465FAE91A033593007632EF /* Images.xcassets */, 125 | 3465FAEB1A033593007632EF /* LaunchScreen.xib */, 126 | 3465FADC1A033593007632EF /* Supporting Files */, 127 | ); 128 | path = CCLogSystemDemo; 129 | sourceTree = ""; 130 | }; 131 | 3465FADC1A033593007632EF /* Supporting Files */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 3465FADD1A033593007632EF /* Info.plist */, 135 | 3465FADE1A033593007632EF /* main.m */, 136 | ); 137 | name = "Supporting Files"; 138 | sourceTree = ""; 139 | }; 140 | 3465FAF51A033593007632EF /* CCLogSystemDemoTests */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 3465FAF81A033593007632EF /* CCLogSystemDemoTests.m */, 144 | 3465FAF61A033593007632EF /* Supporting Files */, 145 | ); 146 | path = CCLogSystemDemoTests; 147 | sourceTree = ""; 148 | }; 149 | 3465FAF61A033593007632EF /* Supporting Files */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 3465FAF71A033593007632EF /* Info.plist */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | 3467CAA01A03658F00DA6C84 /* CCLogSystem */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 3467CAAE1A03658F00DA6C84 /* CCLogSystem.h */, 161 | 3467CAAF1A03658F00DA6C84 /* CCLogSystem.m */, 162 | 3467CAA41A03658F00DA6C84 /* CCLog.h */, 163 | 3467CAA51A03658F00DA6C84 /* CCLog.m */, 164 | 3467CAA81A03658F00DA6C84 /* CCLogController.h */, 165 | 3467CAA91A03658F00DA6C84 /* CCLogController.m */, 166 | 3467CAA61A03658F00DA6C84 /* CCLogController+Utility.h */, 167 | 3467CAA71A03658F00DA6C84 /* CCLogController+Utility.m */, 168 | 3467CAB01A03658F00DA6C84 /* CCLogViewController.h */, 169 | 3467CAB11A03658F00DA6C84 /* CCLogViewController.m */, 170 | 3467CAAA1A03658F00DA6C84 /* CCLogReviewViewController.h */, 171 | 3467CAAB1A03658F00DA6C84 /* CCLogReviewViewController.m */, 172 | 3467CAA11A03658F00DA6C84 /* CCFileOutputRedirectionController.h */, 173 | 3467CAB21A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.h */, 174 | 3467CAB31A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.m */, 175 | 3467CAB41A03658F00DA6C84 /* CCTeeController.h */, 176 | 3467CAB51A03658F00DA6C84 /* CCTeeController.m */, 177 | 3467CAB61A03658F00DA6C84 /* NSObject+CCReverseComparison.h */, 178 | 3467CAB71A03658F00DA6C84 /* NSObject+CCReverseComparison.m */, 179 | 3467CAAC1A03658F00DA6C84 /* CCLogStringImp.h */, 180 | 3467CAAD1A03658F00DA6C84 /* CCLogStringImp.m */, 181 | 3467CAA21A03658F00DA6C84 /* CCLocationMake.h */, 182 | 3467CAA31A03658F00DA6C84 /* CCLocationMake.m */, 183 | ); 184 | name = CCLogSystem; 185 | path = ../../CCLogSystem/CCLogSystem; 186 | sourceTree = ""; 187 | }; 188 | /* End PBXGroup section */ 189 | 190 | /* Begin PBXNativeTarget section */ 191 | 3465FAD81A033593007632EF /* CCLogSystemDemo */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = 3465FAFC1A033593007632EF /* Build configuration list for PBXNativeTarget "CCLogSystemDemo" */; 194 | buildPhases = ( 195 | 3465FAD51A033593007632EF /* Sources */, 196 | 3465FAD61A033593007632EF /* Frameworks */, 197 | 3465FAD71A033593007632EF /* Resources */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | ); 203 | name = CCLogSystemDemo; 204 | productName = CCLogSystemDemo; 205 | productReference = 3465FAD91A033593007632EF /* CCLogSystemDemo.app */; 206 | productType = "com.apple.product-type.application"; 207 | }; 208 | 3465FAF11A033593007632EF /* CCLogSystemDemoTests */ = { 209 | isa = PBXNativeTarget; 210 | buildConfigurationList = 3465FAFF1A033593007632EF /* Build configuration list for PBXNativeTarget "CCLogSystemDemoTests" */; 211 | buildPhases = ( 212 | 3465FAEE1A033593007632EF /* Sources */, 213 | 3465FAEF1A033593007632EF /* Frameworks */, 214 | 3465FAF01A033593007632EF /* Resources */, 215 | ); 216 | buildRules = ( 217 | ); 218 | dependencies = ( 219 | 3465FAF41A033593007632EF /* PBXTargetDependency */, 220 | ); 221 | name = CCLogSystemDemoTests; 222 | productName = CCLogSystemDemoTests; 223 | productReference = 3465FAF21A033593007632EF /* CCLogSystemDemoTests.xctest */; 224 | productType = "com.apple.product-type.bundle.unit-test"; 225 | }; 226 | /* End PBXNativeTarget section */ 227 | 228 | /* Begin PBXProject section */ 229 | 3465FAD11A033593007632EF /* Project object */ = { 230 | isa = PBXProject; 231 | attributes = { 232 | LastUpgradeCheck = 0610; 233 | ORGANIZATIONNAME = "Chun Tips"; 234 | TargetAttributes = { 235 | 3465FAD81A033593007632EF = { 236 | CreatedOnToolsVersion = 6.1; 237 | }; 238 | 3465FAF11A033593007632EF = { 239 | CreatedOnToolsVersion = 6.1; 240 | TestTargetID = 3465FAD81A033593007632EF; 241 | }; 242 | }; 243 | }; 244 | buildConfigurationList = 3465FAD41A033593007632EF /* Build configuration list for PBXProject "CCLogSystemDemo" */; 245 | compatibilityVersion = "Xcode 3.2"; 246 | developmentRegion = English; 247 | hasScannedForEncodings = 0; 248 | knownRegions = ( 249 | en, 250 | Base, 251 | ); 252 | mainGroup = 3465FAD01A033593007632EF; 253 | productRefGroup = 3465FADA1A033593007632EF /* Products */; 254 | projectDirPath = ""; 255 | projectRoot = ""; 256 | targets = ( 257 | 3465FAD81A033593007632EF /* CCLogSystemDemo */, 258 | 3465FAF11A033593007632EF /* CCLogSystemDemoTests */, 259 | ); 260 | }; 261 | /* End PBXProject section */ 262 | 263 | /* Begin PBXResourcesBuildPhase section */ 264 | 3465FAD71A033593007632EF /* Resources */ = { 265 | isa = PBXResourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | 3465FAE81A033593007632EF /* Main.storyboard in Resources */, 269 | 3465FAED1A033593007632EF /* LaunchScreen.xib in Resources */, 270 | 3465FAEA1A033593007632EF /* Images.xcassets in Resources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | 3465FAF01A033593007632EF /* Resources */ = { 275 | isa = PBXResourcesBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXResourcesBuildPhase section */ 282 | 283 | /* Begin PBXSourcesBuildPhase section */ 284 | 3465FAD51A033593007632EF /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 3467CAB81A03658F00DA6C84 /* CCLocationMake.m in Sources */, 289 | 3467CABD1A03658F00DA6C84 /* CCLogStringImp.m in Sources */, 290 | 3467CABA1A03658F00DA6C84 /* CCLogController+Utility.m in Sources */, 291 | 3467CAC21A03658F00DA6C84 /* NSObject+CCReverseComparison.m in Sources */, 292 | 3467CAC11A03658F00DA6C84 /* CCTeeController.m in Sources */, 293 | 3467CABE1A03658F00DA6C84 /* CCLogSystem.m in Sources */, 294 | 3467CAB91A03658F00DA6C84 /* CCLog.m in Sources */, 295 | 3467CAC01A03658F00DA6C84 /* CCSimpleFileOutputRedirectionController.m in Sources */, 296 | 3467CABB1A03658F00DA6C84 /* CCLogController.m in Sources */, 297 | 3465FAE51A033593007632EF /* ViewController.m in Sources */, 298 | 3465FAE21A033593007632EF /* AppDelegate.m in Sources */, 299 | 3465FADF1A033593007632EF /* main.m in Sources */, 300 | 3467CABF1A03658F00DA6C84 /* CCLogViewController.m in Sources */, 301 | 3467CABC1A03658F00DA6C84 /* CCLogReviewViewController.m in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 3465FAEE1A033593007632EF /* Sources */ = { 306 | isa = PBXSourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | 3465FAF91A033593007632EF /* CCLogSystemDemoTests.m in Sources */, 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | /* End PBXSourcesBuildPhase section */ 314 | 315 | /* Begin PBXTargetDependency section */ 316 | 3465FAF41A033593007632EF /* PBXTargetDependency */ = { 317 | isa = PBXTargetDependency; 318 | target = 3465FAD81A033593007632EF /* CCLogSystemDemo */; 319 | targetProxy = 3465FAF31A033593007632EF /* PBXContainerItemProxy */; 320 | }; 321 | /* End PBXTargetDependency section */ 322 | 323 | /* Begin PBXVariantGroup section */ 324 | 3465FAE61A033593007632EF /* Main.storyboard */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | 3465FAE71A033593007632EF /* Base */, 328 | ); 329 | name = Main.storyboard; 330 | sourceTree = ""; 331 | }; 332 | 3465FAEB1A033593007632EF /* LaunchScreen.xib */ = { 333 | isa = PBXVariantGroup; 334 | children = ( 335 | 3465FAEC1A033593007632EF /* Base */, 336 | ); 337 | name = LaunchScreen.xib; 338 | sourceTree = ""; 339 | }; 340 | /* End PBXVariantGroup section */ 341 | 342 | /* Begin XCBuildConfiguration section */ 343 | 3465FAFA1A033593007632EF /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ALWAYS_SEARCH_USER_PATHS = NO; 347 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 348 | CLANG_CXX_LIBRARY = "libc++"; 349 | CLANG_ENABLE_MODULES = YES; 350 | CLANG_ENABLE_OBJC_ARC = YES; 351 | CLANG_WARN_BOOL_CONVERSION = YES; 352 | CLANG_WARN_CONSTANT_CONVERSION = YES; 353 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 354 | CLANG_WARN_EMPTY_BODY = YES; 355 | CLANG_WARN_ENUM_CONVERSION = YES; 356 | CLANG_WARN_INT_CONVERSION = YES; 357 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | ENABLE_STRICT_OBJC_MSGSEND = YES; 363 | GCC_C_LANGUAGE_STANDARD = gnu99; 364 | GCC_DYNAMIC_NO_PIC = NO; 365 | GCC_OPTIMIZATION_LEVEL = 0; 366 | GCC_PREPROCESSOR_DEFINITIONS = ( 367 | "DEBUG=1", 368 | "$(inherited)", 369 | ); 370 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 371 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 372 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 373 | GCC_WARN_UNDECLARED_SELECTOR = YES; 374 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 375 | GCC_WARN_UNUSED_FUNCTION = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 378 | MTL_ENABLE_DEBUG_INFO = YES; 379 | ONLY_ACTIVE_ARCH = YES; 380 | SDKROOT = iphoneos; 381 | TARGETED_DEVICE_FAMILY = "1,2"; 382 | }; 383 | name = Debug; 384 | }; 385 | 3465FAFB1A033593007632EF /* Release */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ALWAYS_SEARCH_USER_PATHS = NO; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BOOL_CONVERSION = YES; 394 | CLANG_WARN_CONSTANT_CONVERSION = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_EMPTY_BODY = YES; 397 | CLANG_WARN_ENUM_CONVERSION = YES; 398 | CLANG_WARN_INT_CONVERSION = YES; 399 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 400 | CLANG_WARN_UNREACHABLE_CODE = YES; 401 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 402 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 403 | COPY_PHASE_STRIP = YES; 404 | ENABLE_NS_ASSERTIONS = NO; 405 | ENABLE_STRICT_OBJC_MSGSEND = YES; 406 | GCC_C_LANGUAGE_STANDARD = gnu99; 407 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 408 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 409 | GCC_WARN_UNDECLARED_SELECTOR = YES; 410 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 411 | GCC_WARN_UNUSED_FUNCTION = YES; 412 | GCC_WARN_UNUSED_VARIABLE = YES; 413 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 414 | MTL_ENABLE_DEBUG_INFO = NO; 415 | SDKROOT = iphoneos; 416 | TARGETED_DEVICE_FAMILY = "1,2"; 417 | VALIDATE_PRODUCT = YES; 418 | }; 419 | name = Release; 420 | }; 421 | 3465FAFD1A033593007632EF /* Debug */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 425 | INFOPLIST_FILE = CCLogSystemDemo/Info.plist; 426 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 427 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | }; 430 | name = Debug; 431 | }; 432 | 3465FAFE1A033593007632EF /* Release */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | INFOPLIST_FILE = CCLogSystemDemo/Info.plist; 437 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 439 | PRODUCT_NAME = "$(TARGET_NAME)"; 440 | }; 441 | name = Release; 442 | }; 443 | 3465FB001A033593007632EF /* Debug */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | BUNDLE_LOADER = "$(TEST_HOST)"; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(SDKROOT)/Developer/Library/Frameworks", 449 | "$(inherited)", 450 | ); 451 | GCC_PREPROCESSOR_DEFINITIONS = ( 452 | "DEBUG=1", 453 | "$(inherited)", 454 | ); 455 | INFOPLIST_FILE = CCLogSystemDemoTests/Info.plist; 456 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCLogSystemDemo.app/CCLogSystemDemo"; 459 | }; 460 | name = Debug; 461 | }; 462 | 3465FB011A033593007632EF /* Release */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | BUNDLE_LOADER = "$(TEST_HOST)"; 466 | FRAMEWORK_SEARCH_PATHS = ( 467 | "$(SDKROOT)/Developer/Library/Frameworks", 468 | "$(inherited)", 469 | ); 470 | INFOPLIST_FILE = CCLogSystemDemoTests/Info.plist; 471 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 472 | PRODUCT_NAME = "$(TARGET_NAME)"; 473 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCLogSystemDemo.app/CCLogSystemDemo"; 474 | }; 475 | name = Release; 476 | }; 477 | /* End XCBuildConfiguration section */ 478 | 479 | /* Begin XCConfigurationList section */ 480 | 3465FAD41A033593007632EF /* Build configuration list for PBXProject "CCLogSystemDemo" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | 3465FAFA1A033593007632EF /* Debug */, 484 | 3465FAFB1A033593007632EF /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | 3465FAFC1A033593007632EF /* Build configuration list for PBXNativeTarget "CCLogSystemDemo" */ = { 490 | isa = XCConfigurationList; 491 | buildConfigurations = ( 492 | 3465FAFD1A033593007632EF /* Debug */, 493 | 3465FAFE1A033593007632EF /* Release */, 494 | ); 495 | defaultConfigurationIsVisible = 0; 496 | defaultConfigurationName = Release; 497 | }; 498 | 3465FAFF1A033593007632EF /* Build configuration list for PBXNativeTarget "CCLogSystemDemoTests" */ = { 499 | isa = XCConfigurationList; 500 | buildConfigurations = ( 501 | 3465FB001A033593007632EF /* Debug */, 502 | 3465FB011A033593007632EF /* Release */, 503 | ); 504 | defaultConfigurationIsVisible = 0; 505 | defaultConfigurationName = Release; 506 | }; 507 | /* End XCConfigurationList section */ 508 | }; 509 | rootObject = 3465FAD11A033593007632EF /* Project object */; 510 | } 511 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CCLogSystemDemo 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CCLogSystemDemo 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "CCLogSystem.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | typedef void (^TestBlock)(); 19 | 20 | - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 21 | { 22 | [CCLogSystem setupDefaultLogConfigure]; 23 | 24 | CC_LOG(@"%@", application); 25 | 26 | CC_LOG_VALUE(application); 27 | 28 | id applicationTemp = application; 29 | CC_LOG_VALUE(applicationTemp); 30 | 31 | CC_LOG_VALUE(self.window); 32 | 33 | CC_LOG_VALUE(self.window.frame); 34 | 35 | CC_LOG_VALUE(self.window.transform); 36 | 37 | Class applicationClass = NSClassFromString(@"UIApplication"); 38 | CC_LOG_VALUE(applicationClass); 39 | 40 | SEL selector = @selector(application:continueUserActivity:restorationHandler:); 41 | CC_LOG_VALUE(selector); 42 | 43 | NSInteger test = 100; 44 | CC_LOG_VALUE(test); 45 | 46 | float test2 = 100.000001; 47 | CC_LOG_VALUE(test2); 48 | 49 | char test3 = 'a'; 50 | CC_LOG_VALUE(test3); 51 | 52 | TestBlock testBlock = ^{ 53 | }; 54 | CC_LOG_VALUE(testBlock); 55 | 56 | NSObject *a = [[NSObject alloc] init]; 57 | CC_LOG_VALUE(a); 58 | return YES; 59 | } 60 | 61 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 62 | { 63 | // Override point for customization after application launch. 64 | return YES; 65 | } 66 | 67 | - (void)applicationWillResignActive:(UIApplication *)application { 68 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 69 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 70 | } 71 | 72 | - (void)applicationDidEnterBackground:(UIApplication *)application { 73 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 74 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 75 | } 76 | 77 | - (void)applicationWillEnterForeground:(UIApplication *)application { 78 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 79 | } 80 | 81 | - (void)applicationDidBecomeActive:(UIApplication *)application { 82 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 83 | } 84 | 85 | - (void)applicationWillTerminate:(UIApplication *)application { 86 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/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 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/Images.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 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | chun.tips.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 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 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CCLogSystemDemo 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CCLogSystemDemo 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "CCLogSystem.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 22 | [button setTitle:@"Open Developer UI" forState:UIControlStateNormal]; 23 | [button addTarget:self action:@selector(openDeveloperUI) forControlEvents:UIControlEventTouchUpInside]; 24 | button.translatesAutoresizingMaskIntoConstraints = NO; 25 | [self.view addSubview:button]; 26 | 27 | NSMutableArray *constraits = [NSMutableArray array]; 28 | [constraits addObject:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]]; 29 | [constraits addObject:[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]]; 30 | [self.view addConstraints:constraits]; 31 | } 32 | 33 | - (void)didReceiveMemoryWarning { 34 | [super didReceiveMemoryWarning]; 35 | // Dispose of any resources that can be recreated. 36 | } 37 | 38 | - (void)openDeveloperUI 39 | { 40 | [CCLogSystem activeDeveloperUI]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CCLogSystemDemo 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemoTests/CCLogSystemDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCLogSystemDemoTests.m 3 | // CCLogSystemDemoTests 4 | // 5 | // Created by Chun Ye on 10/31/14. 6 | // Copyright (c) 2014 Chun Tips. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CCLogSystemDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation CCLogSystemDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CCLogSystemDemo/CCLogSystemDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | chun.tips.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Chun Ye 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ###CCLogSystem 2 | *** 3 | 4 | CCLogSystem provide an iOS Log System. We can use to replace *NSLog* in our project.And it also provide recording logs to the local file and review or email logs in our app. 5 | 6 | 中文版本请戳: [Chun Tips](http://chun.tips/blog/2014/10/31/fen-xiang-ge-ren-xiang-mu-zhong-de-logxi-tong-cclogsystem/) 7 | 8 | ####Main Features 9 | 10 | * Very simplay API to use 11 | * Use *CC_LOG* to print that get more info. The output info is include "TIMESTAMP" + "THREAD" + "FILE" + "LINE" + "FUNCTION" + origin print info. 12 | * Use *CC_LOG_VALUE* to print any value directly. Like: CC_LOG_VALUE(self.window) or CC_LOG_VALUE(self.window.frame) 13 | * Record crash issue 14 | * Record the logs to the local file 15 | * Provide the Developer UI to review and email the logs in the App 16 | 17 | ####Installation 18 | CCLogSytem is available as a [CocoaPod](http://cocoapods.org/?q=CCLogSystem). 19 | 20 | pod 'CCLogSystem' 21 | 22 | You can also simply copy all the source files located inside CCLogSystem/CCLogSystem/* into your iOS project. 23 | 24 | ####Example 25 | 26 | ###### How to setup CCLogSystem 27 | 28 | - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions: (NSDictionary *)launchOptions 29 | { 30 | [CCLogSystem setupDefaultLogConfigure]; 31 | } 32 | 33 | ##### Use CC_LOG macro to print log 34 | 35 | - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 36 | { 37 | [CCLogSystem setupDefaultLogConfigure]; 38 | 39 | CC_LOG(@"%@", application); 40 | // print: 2014-10-31 15:28:41.038 . {number = 1, name = main} AppDelegate.m at 24 (-[AppDelegate application:willFinishLaunchingWithOptions:]): 41 | } 42 | 43 | ##### Use CC_LOG_VALUE macro to print any value 44 | 45 | CC_LOG_VALUE(application); 46 | 47 | id applicationTemp = application; 48 | CC_LOG_VALUE(applicationTemp); 49 | 50 | CC_LOG_VALUE(self.window); 51 | 52 | CC_LOG_VALUE(self.window.frame); 53 | 54 | CC_LOG_VALUE(self.window.transform); 55 | 56 | Class applicationClass = NSClassFromString(@"UIApplication"); 57 | CC_LOG_VALUE(applicationClass); 58 | 59 | SEL selector = @selector(application:continueUserActivity:restorationHandler:); 60 | CC_LOG_VALUE(selector); 61 | 62 | NSInteger test = 100; 63 | CC_LOG_VALUE(test); 64 | 65 | float test2 = 100.000001; 66 | CC_LOG_VALUE(test2); 67 | 68 | char test3 = 'a'; 69 | CC_LOG_VALUE(test3); 70 | 71 | TestBlock testBlock = ^{ 72 | }; 73 | CC_LOG_VALUE(testBlock); 74 | 75 | ##### Review the logs in our app 76 | 77 | [CCLogSystem activeDeveloperUI]; 78 | 79 | 80 | 81 | 82 | 83 | #### Authors and License 84 | 85 | * All source code is licensed under the MIT License. 86 | * Copyright (c) 2014-2015, [@Chun Ye](http://chun.tips) 87 | 88 | 89 | --------------------------------------------------------------------------------