├── .gitignore ├── LICENSE ├── README.md ├── iOS10LogTool ├── iOS10LogTool.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcuserdata │ │ └── mac.xcuserdatad │ │ └── xcschemes │ │ ├── iOS10LogTool.xcscheme │ │ └── xcschememanagement.plist └── iOS10LogTool │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SQLogTool │ ├── SQFloatWindow.h │ ├── SQFloatWindow.m │ ├── SQLog.h │ ├── SQLog.m │ ├── SQLogToolManager.h │ └── SQLogToolManager.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── screenshots ├── 分享界面.PNG ├── 悬浮窗模式.PNG ├── 效果示例.gif └── 预览界面.PNG /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | 4 | #用户数据文件夹(无用) 5 | xcuserdata/ 6 | 7 | #使用合成脚本生成的build文件夹 8 | build/ 9 | 10 | #使用合成脚本生成的Products文件夹 11 | Products/ 12 | Product/ 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 shixueqian 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS10LogTool 2 | 一个解决iOS10在发布环境下无法查看调试log的小工具 3 | 4 | 简书介绍地址:[【iOS开发】iOS10 Log调试小工具](http://www.jianshu.com/p/23011d141622) 5 | 6 | ### 出发点 7 | 由于iOS10系统,在发布环境下(打成ipa包安装测试或者发布之后从App Store下载安装的包),使用Xcode已经无法查看我们自己打印的log。所以就做了一个小工具,查看log,便于调试。 8 | 楼主的需求是,在安装了APP之后查看log,验证程序是否正常运行。除了在调试的时候用到,在线上包出问题之后,也能通过查看log来定位问题。 9 | 10 | ### 使用 11 | 12 | * 项目github地址:https://github.com/shixueqian/iOS10LogDebugTool 13 | * 将SQLogTool文件夹中的几个文件拖到工程中 14 | * 在didFinishLaunchingWithOptions方法中进行初始化 15 | 代码示例: 16 | 17 | ``` 18 | //需要导入头文件 #import "SQLogToolManager.h" 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 20 | { 21 | [[SQLogToolManager shareManager] logIntial]; 22 | return YES; 23 | } 24 | ``` 25 | 26 | * 在应用的某个界面上设置一个开关,点击这个开关就将log工具设置到悬浮窗模式(楼主设置的是在登录界面上连续点击10次就触发方法) 27 | 代码示例: 28 | 29 | 30 | ``` 31 | - (IBAction)onClickWriteToTextAndShowFloatWindow:(UIButton *)sender 32 | { 33 | [SQLogToolManager shareManager].logLevel = SQLogToolManagerLevelText; 34 | } 35 | ``` 36 | 37 | * 在需要打印Log的地方使用 ``NSLogD()``来替换平常用的``NSLog()`` 38 | 代码示例: 39 | 40 | ``` 41 | - (IBAction)onClickTest:(UIButton *)sender 42 | { 43 | for (int i = 0; i < 10; ++i) 44 | { 45 | NSLogD(@"这里是测试。%@:%d",@"第一个参数",i); 46 | } 47 | } 48 | ``` 49 | 50 | ### 不足之处&需改进的地方 51 | 52 | 这个只是一个小工具,所以只做了几个我认为比较重要的功能。。主要缺陷: 53 | 54 | * 界面长得不是很好看(管他呢) 55 | * 不能显示系统的log。只能显示使用``NSLogD()``方法打印的log。也就是说,苹果的警告log无法通过这个小工具得到。(当前,这也避免了iOS10上那些恶心的无用log) 56 | * 无法显示崩溃log。楼主认为这个功能不是那么重要,就没做了。 57 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0468D76A1E9CB09B00FE3C2D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D7691E9CB09B00FE3C2D /* main.m */; }; 11 | 0468D76D1E9CB09B00FE3C2D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D76C1E9CB09B00FE3C2D /* AppDelegate.m */; }; 12 | 0468D7701E9CB09B00FE3C2D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D76F1E9CB09B00FE3C2D /* ViewController.m */; }; 13 | 0468D7731E9CB09B00FE3C2D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0468D7711E9CB09B00FE3C2D /* Main.storyboard */; }; 14 | 0468D7751E9CB09B00FE3C2D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0468D7741E9CB09B00FE3C2D /* Assets.xcassets */; }; 15 | 0468D7781E9CB09B00FE3C2D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0468D7761E9CB09B00FE3C2D /* LaunchScreen.storyboard */; }; 16 | 0468D7821E9CB22500FE3C2D /* SQFloatWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D7811E9CB22500FE3C2D /* SQFloatWindow.m */; }; 17 | 0468D7851E9CB23700FE3C2D /* SQLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D7841E9CB23700FE3C2D /* SQLog.m */; }; 18 | 0468D7881E9CB25500FE3C2D /* SQLogToolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0468D7871E9CB25500FE3C2D /* SQLogToolManager.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 0468D7651E9CB09B00FE3C2D /* iOS10LogTool.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOS10LogTool.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 0468D7691E9CB09B00FE3C2D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 0468D76B1E9CB09B00FE3C2D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 0468D76C1E9CB09B00FE3C2D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 0468D76E1E9CB09B00FE3C2D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 0468D76F1E9CB09B00FE3C2D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 0468D7721E9CB09B00FE3C2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 0468D7741E9CB09B00FE3C2D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 0468D7771E9CB09B00FE3C2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 0468D7791E9CB09B00FE3C2D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 0468D7801E9CB22500FE3C2D /* SQFloatWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQFloatWindow.h; sourceTree = ""; }; 33 | 0468D7811E9CB22500FE3C2D /* SQFloatWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQFloatWindow.m; sourceTree = ""; }; 34 | 0468D7831E9CB23700FE3C2D /* SQLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLog.h; sourceTree = ""; }; 35 | 0468D7841E9CB23700FE3C2D /* SQLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQLog.m; sourceTree = ""; }; 36 | 0468D7861E9CB25500FE3C2D /* SQLogToolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLogToolManager.h; sourceTree = ""; }; 37 | 0468D7871E9CB25500FE3C2D /* SQLogToolManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQLogToolManager.m; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 0468D7621E9CB09B00FE3C2D /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 0468D75C1E9CB09B00FE3C2D = { 52 | isa = PBXGroup; 53 | children = ( 54 | 0468D7671E9CB09B00FE3C2D /* iOS10LogTool */, 55 | 0468D7661E9CB09B00FE3C2D /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | 0468D7661E9CB09B00FE3C2D /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 0468D7651E9CB09B00FE3C2D /* iOS10LogTool.app */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | 0468D7671E9CB09B00FE3C2D /* iOS10LogTool */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 0468D77F1E9CB1EF00FE3C2D /* SQLogTool */, 71 | 0468D76B1E9CB09B00FE3C2D /* AppDelegate.h */, 72 | 0468D76C1E9CB09B00FE3C2D /* AppDelegate.m */, 73 | 0468D76E1E9CB09B00FE3C2D /* ViewController.h */, 74 | 0468D76F1E9CB09B00FE3C2D /* ViewController.m */, 75 | 0468D7711E9CB09B00FE3C2D /* Main.storyboard */, 76 | 0468D7741E9CB09B00FE3C2D /* Assets.xcassets */, 77 | 0468D7761E9CB09B00FE3C2D /* LaunchScreen.storyboard */, 78 | 0468D7791E9CB09B00FE3C2D /* Info.plist */, 79 | 0468D7681E9CB09B00FE3C2D /* Supporting Files */, 80 | ); 81 | path = iOS10LogTool; 82 | sourceTree = ""; 83 | }; 84 | 0468D7681E9CB09B00FE3C2D /* Supporting Files */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 0468D7691E9CB09B00FE3C2D /* main.m */, 88 | ); 89 | name = "Supporting Files"; 90 | sourceTree = ""; 91 | }; 92 | 0468D77F1E9CB1EF00FE3C2D /* SQLogTool */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 0468D7801E9CB22500FE3C2D /* SQFloatWindow.h */, 96 | 0468D7811E9CB22500FE3C2D /* SQFloatWindow.m */, 97 | 0468D7831E9CB23700FE3C2D /* SQLog.h */, 98 | 0468D7841E9CB23700FE3C2D /* SQLog.m */, 99 | 0468D7861E9CB25500FE3C2D /* SQLogToolManager.h */, 100 | 0468D7871E9CB25500FE3C2D /* SQLogToolManager.m */, 101 | ); 102 | path = SQLogTool; 103 | sourceTree = ""; 104 | }; 105 | /* End PBXGroup section */ 106 | 107 | /* Begin PBXNativeTarget section */ 108 | 0468D7641E9CB09B00FE3C2D /* iOS10LogTool */ = { 109 | isa = PBXNativeTarget; 110 | buildConfigurationList = 0468D77C1E9CB09B00FE3C2D /* Build configuration list for PBXNativeTarget "iOS10LogTool" */; 111 | buildPhases = ( 112 | 0468D7611E9CB09B00FE3C2D /* Sources */, 113 | 0468D7621E9CB09B00FE3C2D /* Frameworks */, 114 | 0468D7631E9CB09B00FE3C2D /* Resources */, 115 | ); 116 | buildRules = ( 117 | ); 118 | dependencies = ( 119 | ); 120 | name = iOS10LogTool; 121 | productName = iOS10LogTool; 122 | productReference = 0468D7651E9CB09B00FE3C2D /* iOS10LogTool.app */; 123 | productType = "com.apple.product-type.application"; 124 | }; 125 | /* End PBXNativeTarget section */ 126 | 127 | /* Begin PBXProject section */ 128 | 0468D75D1E9CB09B00FE3C2D /* Project object */ = { 129 | isa = PBXProject; 130 | attributes = { 131 | LastUpgradeCheck = 0820; 132 | ORGANIZATIONNAME = shixueqian; 133 | TargetAttributes = { 134 | 0468D7641E9CB09B00FE3C2D = { 135 | CreatedOnToolsVersion = 8.2.1; 136 | DevelopmentTeam = M9XE43A3CX; 137 | ProvisioningStyle = Automatic; 138 | }; 139 | }; 140 | }; 141 | buildConfigurationList = 0468D7601E9CB09B00FE3C2D /* Build configuration list for PBXProject "iOS10LogTool" */; 142 | compatibilityVersion = "Xcode 3.2"; 143 | developmentRegion = English; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | Base, 148 | ); 149 | mainGroup = 0468D75C1E9CB09B00FE3C2D; 150 | productRefGroup = 0468D7661E9CB09B00FE3C2D /* Products */; 151 | projectDirPath = ""; 152 | projectRoot = ""; 153 | targets = ( 154 | 0468D7641E9CB09B00FE3C2D /* iOS10LogTool */, 155 | ); 156 | }; 157 | /* End PBXProject section */ 158 | 159 | /* Begin PBXResourcesBuildPhase section */ 160 | 0468D7631E9CB09B00FE3C2D /* Resources */ = { 161 | isa = PBXResourcesBuildPhase; 162 | buildActionMask = 2147483647; 163 | files = ( 164 | 0468D7781E9CB09B00FE3C2D /* LaunchScreen.storyboard in Resources */, 165 | 0468D7751E9CB09B00FE3C2D /* Assets.xcassets in Resources */, 166 | 0468D7731E9CB09B00FE3C2D /* Main.storyboard in Resources */, 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | }; 170 | /* End PBXResourcesBuildPhase section */ 171 | 172 | /* Begin PBXSourcesBuildPhase section */ 173 | 0468D7611E9CB09B00FE3C2D /* Sources */ = { 174 | isa = PBXSourcesBuildPhase; 175 | buildActionMask = 2147483647; 176 | files = ( 177 | 0468D7881E9CB25500FE3C2D /* SQLogToolManager.m in Sources */, 178 | 0468D7821E9CB22500FE3C2D /* SQFloatWindow.m in Sources */, 179 | 0468D7701E9CB09B00FE3C2D /* ViewController.m in Sources */, 180 | 0468D76D1E9CB09B00FE3C2D /* AppDelegate.m in Sources */, 181 | 0468D76A1E9CB09B00FE3C2D /* main.m in Sources */, 182 | 0468D7851E9CB23700FE3C2D /* SQLog.m in Sources */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXSourcesBuildPhase section */ 187 | 188 | /* Begin PBXVariantGroup section */ 189 | 0468D7711E9CB09B00FE3C2D /* Main.storyboard */ = { 190 | isa = PBXVariantGroup; 191 | children = ( 192 | 0468D7721E9CB09B00FE3C2D /* Base */, 193 | ); 194 | name = Main.storyboard; 195 | sourceTree = ""; 196 | }; 197 | 0468D7761E9CB09B00FE3C2D /* LaunchScreen.storyboard */ = { 198 | isa = PBXVariantGroup; 199 | children = ( 200 | 0468D7771E9CB09B00FE3C2D /* Base */, 201 | ); 202 | name = LaunchScreen.storyboard; 203 | sourceTree = ""; 204 | }; 205 | /* End PBXVariantGroup section */ 206 | 207 | /* Begin XCBuildConfiguration section */ 208 | 0468D77A1E9CB09B00FE3C2D /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | CLANG_ANALYZER_NONNULL = YES; 213 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 214 | CLANG_CXX_LIBRARY = "libc++"; 215 | CLANG_ENABLE_MODULES = YES; 216 | CLANG_ENABLE_OBJC_ARC = YES; 217 | CLANG_WARN_BOOL_CONVERSION = YES; 218 | CLANG_WARN_CONSTANT_CONVERSION = YES; 219 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 220 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 221 | CLANG_WARN_EMPTY_BODY = YES; 222 | CLANG_WARN_ENUM_CONVERSION = YES; 223 | CLANG_WARN_INFINITE_RECURSION = YES; 224 | CLANG_WARN_INT_CONVERSION = YES; 225 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 226 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 230 | COPY_PHASE_STRIP = NO; 231 | DEBUG_INFORMATION_FORMAT = dwarf; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | ENABLE_TESTABILITY = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu99; 235 | GCC_DYNAMIC_NO_PIC = NO; 236 | GCC_NO_COMMON_BLOCKS = YES; 237 | GCC_OPTIMIZATION_LEVEL = 0; 238 | GCC_PREPROCESSOR_DEFINITIONS = ( 239 | "DEBUG=1", 240 | "$(inherited)", 241 | ); 242 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 243 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 244 | GCC_WARN_UNDECLARED_SELECTOR = YES; 245 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 246 | GCC_WARN_UNUSED_FUNCTION = YES; 247 | GCC_WARN_UNUSED_VARIABLE = YES; 248 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 249 | MTL_ENABLE_DEBUG_INFO = YES; 250 | ONLY_ACTIVE_ARCH = YES; 251 | SDKROOT = iphoneos; 252 | TARGETED_DEVICE_FAMILY = "1,2"; 253 | }; 254 | name = Debug; 255 | }; 256 | 0468D77B1E9CB09B00FE3C2D /* Release */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_ANALYZER_NONNULL = YES; 261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 262 | CLANG_CXX_LIBRARY = "libc++"; 263 | CLANG_ENABLE_MODULES = YES; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_BOOL_CONVERSION = YES; 266 | CLANG_WARN_CONSTANT_CONVERSION = YES; 267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 268 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 269 | CLANG_WARN_EMPTY_BODY = YES; 270 | CLANG_WARN_ENUM_CONVERSION = YES; 271 | CLANG_WARN_INFINITE_RECURSION = YES; 272 | CLANG_WARN_INT_CONVERSION = YES; 273 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 278 | COPY_PHASE_STRIP = NO; 279 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 280 | ENABLE_NS_ASSERTIONS = NO; 281 | ENABLE_STRICT_OBJC_MSGSEND = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu99; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 291 | MTL_ENABLE_DEBUG_INFO = NO; 292 | SDKROOT = iphoneos; 293 | TARGETED_DEVICE_FAMILY = "1,2"; 294 | VALIDATE_PRODUCT = YES; 295 | }; 296 | name = Release; 297 | }; 298 | 0468D77D1E9CB09B00FE3C2D /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 303 | DEVELOPMENT_TEAM = M9XE43A3CX; 304 | INFOPLIST_FILE = iOS10LogTool/Info.plist; 305 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 306 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 307 | PRODUCT_BUNDLE_IDENTIFIER = com.shixueqian.iOS10LogTool; 308 | PRODUCT_NAME = "$(TARGET_NAME)"; 309 | }; 310 | name = Debug; 311 | }; 312 | 0468D77E1E9CB09B00FE3C2D /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 316 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 317 | DEVELOPMENT_TEAM = M9XE43A3CX; 318 | INFOPLIST_FILE = iOS10LogTool/Info.plist; 319 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 320 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 321 | PRODUCT_BUNDLE_IDENTIFIER = com.shixueqian.iOS10LogTool; 322 | PRODUCT_NAME = "$(TARGET_NAME)"; 323 | }; 324 | name = Release; 325 | }; 326 | /* End XCBuildConfiguration section */ 327 | 328 | /* Begin XCConfigurationList section */ 329 | 0468D7601E9CB09B00FE3C2D /* Build configuration list for PBXProject "iOS10LogTool" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 0468D77A1E9CB09B00FE3C2D /* Debug */, 333 | 0468D77B1E9CB09B00FE3C2D /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | 0468D77C1E9CB09B00FE3C2D /* Build configuration list for PBXNativeTarget "iOS10LogTool" */ = { 339 | isa = XCConfigurationList; 340 | buildConfigurations = ( 341 | 0468D77D1E9CB09B00FE3C2D /* Debug */, 342 | 0468D77E1E9CB09B00FE3C2D /* Release */, 343 | ); 344 | defaultConfigurationIsVisible = 0; 345 | }; 346 | /* End XCConfigurationList section */ 347 | }; 348 | rootObject = 0468D75D1E9CB09B00FE3C2D /* Project object */; 349 | } 350 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/iOS10LogTool.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS10LogTool.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 0468D7641E9CB09B00FE3C2D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import "AppDelegate.h" 12 | //需要导入头文件 13 | #import "SQLogToolManager.h" 14 | 15 | @interface AppDelegate () 16 | 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | 22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 23 | 24 | NSLog(@"%@",NSHomeDirectory()); 25 | //初始化 26 | [[SQLogToolManager shareManager] logIntial]; 27 | 28 | return YES; 29 | } 30 | 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application { 33 | // 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. 34 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 35 | } 36 | 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application { 39 | // 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. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | 44 | - (void)applicationWillEnterForeground:(UIApplication *)application { 45 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 46 | } 47 | 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application { 50 | // 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. 51 | } 52 | 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/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 | 31 | 38 | 45 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQFloatWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // SQFloatWindow.h 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 悬浮窗处理类 10 | 11 | #import 12 | 13 | @interface SQFloatWindow : UIWindow 14 | 15 | /** 16 | 点击事件block 17 | */ 18 | @property (nonatomic,copy) void(^clickBlocks)(NSInteger i); 19 | 20 | /** 21 | 悬浮窗初始化 22 | warning: frame的长宽必须相等 23 | 24 | @param frame frame 25 | @param mainBtnName 主按钮name 26 | @param titles 数组,子按钮的name 27 | @return SQFloatWindow 28 | */ 29 | - (instancetype)initWithFrame:(CGRect)frame mainBtnName:(NSString*)mainBtnName titles:(NSArray *)titles; 30 | 31 | /** 32 | 显示悬浮窗 33 | */ 34 | - (void)showWindow; 35 | 36 | /** 37 | 隐藏悬浮窗 38 | */ 39 | - (void)dissmissWindow; 40 | 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQFloatWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // SQFloatWindow.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | 10 | #import "SQFloatWindow.h" 11 | 12 | #define WIDTH self.frame.size.width 13 | #define HEIGHT self.frame.size.height 14 | #define kScreenWidth [[UIScreen mainScreen] bounds].size.width 15 | #define kScreenHeight [[UIScreen mainScreen] bounds].size.height 16 | 17 | #define animateDuration 0.3 //位置改变动画时间 18 | #define showDuration 0.1 //展开动画时间 19 | #define statusChangeDuration 3.0 //状态改变时间 20 | #define normalAlpha 0.8 //正常状态时背景alpha值 21 | #define sleepAlpha 0.3 //隐藏到边缘时的背景alpha值 22 | #define myBorderWidth 1.0 //外框宽度 23 | #define marginWith 5 //间隔 24 | 25 | @interface SQFloatWindow() 26 | 27 | @property(nonatomic)NSInteger frameWidth; 28 | @property(nonatomic)BOOL isShowTab;//是否展开 29 | @property(nonatomic,strong)UIPanGestureRecognizer *pan;//移动手势 30 | @property(nonatomic,strong)UITapGestureRecognizer *tap;//点击主按钮 31 | @property(nonatomic,strong)UIButton *mainBtn;//主按钮 32 | @property(nonatomic,strong)UIView *contentView; 33 | @property(nonatomic,strong)NSArray *titles;//子按钮标题数组 34 | 35 | 36 | @end 37 | 38 | @implementation SQFloatWindow 39 | 40 | - (instancetype)initWithFrame:(CGRect)frame 41 | { 42 | self = [super initWithFrame:frame]; 43 | if (self) { 44 | // Initialization code 45 | } 46 | return self; 47 | } 48 | 49 | - (instancetype)initWithFrame:(CGRect)frame mainBtnName:(NSString*)mainBtnName titles:(NSArray *)titles{ 50 | if(self = [super initWithFrame:frame]) 51 | { 52 | NSAssert(mainBtnName != nil, @"mainBtnName can't be nil !"); 53 | NSAssert(titles != nil, @"titles can't be nil !"); 54 | 55 | _isShowTab = FALSE; 56 | 57 | //存储keywindow,因为我们自己的悬浮窗window设置显示的会把自己设置为keywindow,但是实际上我们不需要作为keywindow,所以悬浮窗window显示完之后需要把keywindow还回去 58 | UIWindow *preKeyWindow = [UIApplication sharedApplication].keyWindow; 59 | 60 | self.backgroundColor = [UIColor lightGrayColor]; 61 | self.windowLevel = UIWindowLevelAlert + 1;//设置window层级 62 | self.rootViewController = [UIViewController new]; 63 | [self makeKeyAndVisible]; 64 | 65 | //还回keyWindow 66 | if (preKeyWindow) { 67 | [preKeyWindow makeKeyWindow]; 68 | } 69 | 70 | _frameWidth = frame.size.width; 71 | _titles = titles; 72 | 73 | //加边框 74 | [self drawBorderLineWithView:self borderWidth:1 color:[UIColor whiteColor]]; 75 | 76 | //内容view 77 | [self setupContentView]; 78 | 79 | //添加子按钮 80 | [self setupButtons]; 81 | 82 | //主按钮 83 | [self setupMainBtnWithName:mainBtnName]; 84 | 85 | //手势 86 | _pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(locationChange:)]; 87 | _pan.delaysTouchesBegan = NO; 88 | [self addGestureRecognizer:_pan]; 89 | _tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click:)]; 90 | [self addGestureRecognizer:_tap]; 91 | 92 | //设备旋转的时候收回按钮 93 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; 94 | } 95 | return self; 96 | 97 | } 98 | 99 | //主按钮 100 | - (void)setupMainBtnWithName:(NSString *)mainBtnName 101 | { 102 | _mainBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 103 | [_mainBtn setFrame:(CGRect){0, 0,self.frame.size.width, self.frame.size.height}]; 104 | 105 | _mainBtn.alpha = sleepAlpha; 106 | _mainBtn.backgroundColor = [UIColor brownColor]; 107 | [_mainBtn setTitle:mainBtnName forState:UIControlStateNormal]; 108 | _mainBtn.titleLabel.font = [UIFont systemFontOfSize: self.frameWidth/5]; 109 | [_mainBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 110 | 111 | [self drawBorderLineWithView:_mainBtn borderWidth:1 color:[UIColor whiteColor]]; 112 | 113 | [_mainBtn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; 114 | 115 | [self addSubview:_mainBtn]; 116 | } 117 | 118 | //内容view 119 | - (void)setupContentView 120 | { 121 | _contentView = [[UIView alloc] initWithFrame:(CGRect){_frameWidth ,0,_titles.count * (_frameWidth),_frameWidth}]; 122 | _contentView.alpha = 0; 123 | // _contentView.backgroundColor = [UIColor redColor]; 124 | [self addSubview:_contentView]; 125 | } 126 | 127 | //添加子按钮 128 | - (void)setupButtons{ 129 | 130 | for (int i = 0; i < _titles.count; ++i) 131 | { 132 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 133 | [button setFrame: CGRectMake(self.frameWidth * i , marginWith/2, self.frameWidth-marginWith , self.frameWidth-marginWith )]; 134 | 135 | [button setTitle:_titles[i] forState:UIControlStateNormal]; 136 | button.titleLabel.font = [UIFont systemFontOfSize: self.frameWidth/5]; 137 | button.layer.cornerRadius = button.frame.size.width/2; 138 | button.layer.masksToBounds = YES; 139 | button.backgroundColor = [UIColor brownColor]; 140 | 141 | button.tag = i; 142 | 143 | [button addTarget:self action:@selector(itemsClick:) forControlEvents:UIControlEventTouchUpInside]; 144 | 145 | [self.contentView addSubview:button]; 146 | } 147 | 148 | } 149 | 150 | #pragma mark ------- contentview 操作 -------------------- 151 | //按钮在屏幕右边时,左移contentview 152 | - (void)moveContentviewLeft{ 153 | _contentView.frame = (CGRect){marginWith, 0 ,_contentView.frame.size.width,_contentView.frame.size.height}; 154 | } 155 | 156 | //按钮在屏幕左边时,contentview恢复默认 157 | - (void)resetContentview{ 158 | _contentView.frame = (CGRect){self.frameWidth + marginWith,0,_contentView.frame.size.width,_contentView.frame.size.height}; 159 | } 160 | 161 | 162 | //拖拽悬浮窗(pan移动手势响应) 163 | - (void)locationChange:(UIPanGestureRecognizer*)p 164 | { 165 | CGPoint panPoint = [p locationInView:[[UIApplication sharedApplication] keyWindow]]; 166 | if(p.state == UIGestureRecognizerStateBegan) 167 | { 168 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeStatus) object:nil]; 169 | _mainBtn.alpha = normalAlpha; 170 | } 171 | if(p.state == UIGestureRecognizerStateChanged) 172 | { 173 | self.center = CGPointMake(panPoint.x, panPoint.y); 174 | } 175 | else if(p.state == UIGestureRecognizerStateEnded) 176 | { 177 | [self performSelector:@selector(changeStatus) withObject:nil afterDelay:statusChangeDuration]; 178 | 179 | if(panPoint.x <= kScreenWidth/2) 180 | { 181 | if(panPoint.y <= 40+HEIGHT/2 && panPoint.x >= 20+WIDTH/2) 182 | { 183 | [UIView animateWithDuration:animateDuration animations:^{ 184 | self.center = CGPointMake(panPoint.x, HEIGHT/2); 185 | }]; 186 | } 187 | else if(panPoint.y >= kScreenHeight-HEIGHT/2-40 && panPoint.x >= 20+WIDTH/2) 188 | { 189 | [UIView animateWithDuration:animateDuration animations:^{ 190 | self.center = CGPointMake(panPoint.x, kScreenHeight-HEIGHT/2); 191 | }]; 192 | } 193 | else if (panPoint.x < WIDTH/2+20 && panPoint.y > kScreenHeight-HEIGHT/2) 194 | { 195 | [UIView animateWithDuration:animateDuration animations:^{ 196 | self.center = CGPointMake(WIDTH/2, kScreenHeight-HEIGHT/2); 197 | }]; 198 | } 199 | else 200 | { 201 | CGFloat pointy = panPoint.y < HEIGHT/2 ? HEIGHT/2 :panPoint.y; 202 | [UIView animateWithDuration:animateDuration animations:^{ 203 | self.center = CGPointMake(WIDTH/2, pointy); 204 | }]; 205 | } 206 | } 207 | else if(panPoint.x > kScreenWidth/2) 208 | { 209 | if(panPoint.y <= 40+HEIGHT/2 && panPoint.x < kScreenWidth-WIDTH/2-20 ) 210 | { 211 | [UIView animateWithDuration:animateDuration animations:^{ 212 | self.center = CGPointMake(panPoint.x, HEIGHT/2); 213 | }]; 214 | } 215 | else if(panPoint.y >= kScreenHeight-40-HEIGHT/2 && panPoint.x < kScreenWidth-WIDTH/2-20) 216 | { 217 | [UIView animateWithDuration:animateDuration animations:^{ 218 | self.center = CGPointMake(panPoint.x, kScreenHeight-HEIGHT/2); 219 | }]; 220 | } 221 | else if (panPoint.x > kScreenWidth-WIDTH/2-20 && panPoint.y < HEIGHT/2) 222 | { 223 | [UIView animateWithDuration:animateDuration animations:^{ 224 | self.center = CGPointMake(kScreenWidth-WIDTH/2, HEIGHT/2); 225 | }]; 226 | } 227 | else 228 | { 229 | CGFloat pointy = panPoint.y > kScreenHeight-HEIGHT/2 ? kScreenHeight-HEIGHT/2 :panPoint.y; 230 | [UIView animateWithDuration:animateDuration animations:^{ 231 | self.center = CGPointMake(kScreenWidth-WIDTH/2, pointy); 232 | }]; 233 | } 234 | } 235 | } 236 | } 237 | 238 | //展开/收回子按钮(主按钮响应) 239 | - (void)click:(UITapGestureRecognizer*)p 240 | { 241 | 242 | _mainBtn.alpha = normalAlpha; 243 | 244 | //拉出悬浮窗 245 | if (self.center.x == 0) { 246 | self.center = CGPointMake(WIDTH/2, self.center.y); 247 | }else if (self.center.x == kScreenWidth) { 248 | self.center = CGPointMake(kScreenWidth - WIDTH/2, self.center.y); 249 | }else if (self.center.y == 0) { 250 | self.center = CGPointMake(self.center.x, HEIGHT/2); 251 | }else if (self.center.y == kScreenHeight) { 252 | self.center = CGPointMake(self.center.x, kScreenHeight - HEIGHT/2); 253 | } 254 | //展示按钮列表 255 | if (!self.isShowTab) { 256 | self.isShowTab = TRUE; 257 | 258 | [UIView animateWithDuration:showDuration animations:^{ 259 | 260 | _contentView.alpha = 1; 261 | 262 | if (self.frame.origin.x <= kScreenWidth/2) { 263 | [self resetContentview]; 264 | 265 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, WIDTH + _titles.count * (self.frameWidth + marginWith/2) ,self.frameWidth); 266 | }else{ 267 | 268 | [self moveContentviewLeft]; 269 | 270 | self.mainBtn.frame = CGRectMake((_titles.count * (self.frameWidth + marginWith/2)), 0, self.frameWidth, self.frameWidth); 271 | self.frame = CGRectMake(self.frame.origin.x - _titles.count * (self.frameWidth + marginWith/2), self.frame.origin.y, (WIDTH + _titles.count * (self.frameWidth + marginWith/2)) ,self.frameWidth); 272 | } 273 | 274 | }]; 275 | //移除pan手势 276 | if (_pan) { 277 | [self removeGestureRecognizer:_pan]; 278 | } 279 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeStatus) object:nil]; 280 | }else{ 281 | self.isShowTab = FALSE; 282 | 283 | //添加pan手势 284 | if (_pan) { 285 | [self addGestureRecognizer:_pan]; 286 | } 287 | 288 | [UIView animateWithDuration:showDuration animations:^{ 289 | 290 | _contentView.alpha = 0; 291 | 292 | if (self.frame.origin.x + self.mainBtn.frame.origin.x <= kScreenWidth/2) { 293 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frameWidth ,self.frameWidth); 294 | }else{ 295 | self.mainBtn.frame = CGRectMake(0, 0, self.frameWidth, self.frameWidth); 296 | self.frame = CGRectMake(self.frame.origin.x + _titles.count * (self.frameWidth + marginWith/2), self.frame.origin.y, self.frameWidth ,self.frameWidth); 297 | } 298 | }]; 299 | [self performSelector:@selector(changeStatus) withObject:nil afterDelay:statusChangeDuration]; 300 | } 301 | } 302 | 303 | //改变悬浮窗状态 304 | - (void)changeStatus 305 | { 306 | [UIView animateWithDuration:1.0 animations:^{ 307 | _mainBtn.alpha = sleepAlpha; 308 | }]; 309 | [UIView animateWithDuration:0.5 animations:^{ 310 | CGFloat x = self.center.x < 20+WIDTH/2 ? 0 : self.center.x > kScreenWidth - 20 -WIDTH/2 ? kScreenWidth : self.center.x; 311 | CGFloat y = self.center.y < 40 + HEIGHT/2 ? 0 : self.center.y > kScreenHeight - 40 - HEIGHT/2 ? kScreenHeight : self.center.y; 312 | 313 | //禁止停留在4个角 314 | if((x == 0 && y ==0) || (x == kScreenWidth && y == 0) || (x == 0 && y == kScreenHeight) || (x == kScreenWidth && y == kScreenHeight)){ 315 | y = self.center.y; 316 | } 317 | self.center = CGPointMake(x, y); 318 | }]; 319 | } 320 | 321 | //加圆形边框 322 | - (void)drawBorderLineWithView:(UIView *)view borderWidth:(CGFloat)width color:(UIColor *)color{ 323 | view.layer.masksToBounds = YES; 324 | view.layer.cornerRadius = view.frame.size.width/2; 325 | view.layer.borderWidth = width; 326 | if (!color) { 327 | view.layer.borderColor = [UIColor whiteColor].CGColor; 328 | }else{ 329 | view.layer.borderColor = color.CGColor; 330 | } 331 | } 332 | 333 | 334 | #pragma mark ------- button事件 --------- 335 | - (void)itemsClick:(id)sender{ 336 | if (self.isShowTab){ 337 | [self click:nil]; 338 | } 339 | 340 | UIButton *button = (UIButton *)sender; 341 | if (self.clickBlocks) { 342 | self.clickBlocks(button.tag); 343 | } 344 | } 345 | 346 | - (void)dissmissWindow{ 347 | self.hidden = YES; 348 | } 349 | - (void)showWindow{ 350 | self.hidden = NO; 351 | } 352 | 353 | 354 | #pragma mark ------- 设备旋转 ----------- 355 | - (void)orientChange:(NSNotification *)notification{ 356 | 357 | //旋转前要先改变frame,否则坐标有问题(临时办法) 358 | self.frame = CGRectMake(0, kScreenHeight - self.frame.origin.y - self.frame.size.height, self.frame.size.width,self.frame.size.height); 359 | 360 | if (self.isShowTab) { 361 | [self click:nil]; 362 | } 363 | } 364 | 365 | 366 | @end 367 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // SQLog.h 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // Log处理类 10 | 11 | #import 12 | 13 | //目前只用到了SQLogD 14 | //Debug 15 | #define SQLogD(...) [SQLog logD:[NSString stringWithFormat:__VA_ARGS__],@""]; 16 | //Info 17 | #define SQLogI(...) [SQLog logI:[NSString stringWithFormat:__VA_ARGS__],@""]; 18 | //Warning 19 | #define SQLogW(...) [SQLog logW:[NSString stringWithFormat:__VA_ARGS__],@""]; 20 | //Error 21 | #define SQLogE(desStr) [SQLog logE:[NSString stringWithFormat:@"Function:%s Line:%d Des:%@",__func__,__LINE__,desStr],@""]; 22 | 23 | 24 | //日志等级 25 | typedef enum 26 | { 27 | LOGLEVELV = 0, //wend 28 | LOGLEVELD = 1, //Debug 29 | LOGLEVELI = 2, //Info 30 | LOGLEVELW = 3, //Warning 31 | LOGLEVELE = 4, //Error 32 | } SQLogLevel; 33 | 34 | @interface SQLog : NSObject 35 | 36 | 37 | 38 | 39 | /** 40 | * log初始化函数,在系统启动时调用 41 | */ 42 | + (void)logIntial; 43 | 44 | /** 45 | * 设置要记录的log级别(log显示的最低级别,低于这个级别的log不显示) 46 | * 47 | * @param level level 要设置的log级别 48 | */ 49 | + (void)setLogLevel:(SQLogLevel)level; 50 | 51 | 52 | /** 53 | 获取log文件的路径 54 | 55 | @return log文件的路径 56 | */ 57 | + (NSString *)getLogFilePath; 58 | 59 | 60 | /////////////////////////////////////////////////////// 61 | /** 62 | * log记录函数 63 | * 64 | * @param level log所属的等级 65 | * @param format 具体记录log的格式以及内容 66 | */ 67 | + (void)logLevel:(SQLogLevel)level LogInfo:(NSString*)format,... NS_FORMAT_FUNCTION(2,3); 68 | 69 | /** 70 | * LOGLEVELV级Log记录函数 71 | * 72 | * @param format format 具体记录log的格式以及内容 73 | */ 74 | + (void)logV:(NSString*)format,... NS_FORMAT_FUNCTION(1,2); 75 | 76 | /** 77 | * LOGLEVELD级Log记录函数 78 | * 79 | * @param format 具体记录log的格式以及内容 80 | */ 81 | + (void)logD:(NSString*)format,... NS_FORMAT_FUNCTION(1,2); 82 | 83 | /** 84 | * LOGLEVELI级Log记录函数 85 | * 86 | * @param format 具体记录log的格式以及内容 87 | */ 88 | + (void)logI:(NSString*)format,... NS_FORMAT_FUNCTION(1,2); 89 | 90 | /** 91 | * LOGLEVELW级Log记录函数 92 | * 93 | * @param format 具体记录log的格式以及内容 94 | */ 95 | + (void)logW:(NSString*)format,... NS_FORMAT_FUNCTION(1,2); 96 | 97 | /** 98 | * LOGLEVELE级Log记录函数 99 | * 100 | * @param format 具体记录log的格式以及内容 101 | */ 102 | + (void)logE:(NSString*)format,... NS_FORMAT_FUNCTION(1,2); 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // SQLog.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import "SQLog.h" 12 | #import 13 | #include 14 | #include 15 | 16 | //设置默认记录的日志等级为LOGLEVELD。 17 | static SQLogLevel LogLevel = LOGLEVELD; 18 | 19 | //log文件路径 20 | static NSString *logFilePath = nil; 21 | //log目录路径 22 | static NSString *logDir = nil; 23 | 24 | 25 | // 打印队列 26 | static dispatch_once_t logQueueCreatOnce; 27 | static dispatch_queue_t k_operationQueue; 28 | 29 | 30 | @interface SQLog(privatedMethod) 31 | + (void)logvLevel:(SQLogLevel)level Format:(NSString*)format VaList:(va_list)args; 32 | + (NSString*)SQLogFormatPrefix:(SQLogLevel)logLevel; 33 | @end 34 | 35 | 36 | 37 | @implementation SQLog 38 | 39 | #pragma mark - 初始化 40 | 41 | + (void)logIntial 42 | { 43 | if (!logFilePath) 44 | { 45 | NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 46 | NSString *logDirectory = [documentsDirectory stringByAppendingString:@"/log/"]; 47 | 48 | //创建log文件夹 49 | if (![[NSFileManager defaultManager] fileExistsAtPath:logDirectory]) { 50 | [[NSFileManager defaultManager] createDirectoryAtPath:logDirectory 51 | withIntermediateDirectories:YES 52 | attributes:nil 53 | error:nil]; 54 | } 55 | 56 | logDir = logDirectory; 57 | 58 | NSString *fileName = [NSString stringWithFormat:@"SQ_log.txt"]; 59 | NSString *filePath = [logDirectory stringByAppendingPathComponent:fileName]; 60 | 61 | logFilePath = filePath; 62 | #if DEBUG 63 | NSLog(@"LogPath: %@", logFilePath); 64 | #endif 65 | 66 | //创建log文件 67 | if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) 68 | { 69 | NSString *initString = @"log初始化。。。\n"; 70 | [initString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 71 | } 72 | else 73 | { 74 | [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 75 | } 76 | 77 | } 78 | 79 | dispatch_once(&logQueueCreatOnce, ^{ 80 | //创建串行队列 81 | k_operationQueue = dispatch_queue_create("com.shixueqian.app.operationqueue", DISPATCH_QUEUE_SERIAL); 82 | }); 83 | } 84 | 85 | #pragma mark - 获取log文件的路径 86 | 87 | + (NSString *)getLogFilePath 88 | { 89 | return logFilePath; 90 | } 91 | 92 | #pragma mark - 设置要记录的log级别 93 | 94 | + (void)setLogLevel:(SQLogLevel)level 95 | { 96 | LogLevel = level; 97 | } 98 | 99 | #pragma mark - 获取log文件的路径 100 | //根据logLevel返回前缀 101 | + (NSString*)SQLogFormatPrefix:(SQLogLevel)logLevel 102 | { 103 | NSString *logLevelString = @""; 104 | switch (logLevel) 105 | { 106 | case LOGLEVELV: logLevelString = @"VEND"; break; 107 | case LOGLEVELD: logLevelString = @"DEBUG"; break; 108 | case LOGLEVELI: logLevelString = @"INFO"; break; 109 | case LOGLEVELW: logLevelString = @"WARNING";break; 110 | case LOGLEVELE: logLevelString = @"ERROR"; break; 111 | } 112 | 113 | return [NSString stringWithFormat:@"[%@] ", logLevelString]; 114 | } 115 | 116 | #pragma mark - 写入log文件 117 | 118 | + (void)logvLevel:(SQLogLevel)level Format:(NSString *)format VaList:(va_list)args 119 | { 120 | __block NSString *formatTmp = format; 121 | 122 | dispatch_async(k_operationQueue, ^{//异步串行队列 123 | 124 | if (level >= LogLevel)//只有大于当前LogLevel级别的log才会进行操作 125 | { 126 | formatTmp = [[SQLog SQLogFormatPrefix:level] stringByAppendingString:formatTmp]; 127 | //写入log文件的同时,在控制台打印出来 128 | NSLog(@"%@",formatTmp); 129 | 130 | NSString *contentStr = [[NSString alloc] initWithFormat:formatTmp arguments:args]; 131 | NSString *contentN = [contentStr stringByAppendingString:@"\n"]; 132 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 133 | [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 134 | 135 | //设置为北京时间 136 | NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:8];//直接指定时区,这里是东8区 137 | NSInteger seconds = [timeZone secondsFromGMTForDate: [NSDate date]]; 138 | NSDate *beiJingDate = [NSDate dateWithTimeInterval: seconds sinceDate: [NSDate date]]; 139 | 140 | //这里是最终打印出来的字符串,可以根据需要加一些参数进去 141 | NSString *content = [NSString stringWithFormat:@"%@ %@", [dateFormatter stringFromDate:beiJingDate], contentN]; 142 | 143 | //使用NSFileHandle来写入数据 144 | NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:logFilePath]; 145 | [file seekToEndOfFile]; 146 | [file writeData:[content dataUsingEncoding:NSUTF8StringEncoding]]; 147 | [file closeFile]; 148 | 149 | formatTmp = nil; 150 | } 151 | 152 | }); 153 | } 154 | 155 | 156 | + (void)logLevel:(SQLogLevel)level LogInfo:(NSString *)format, ... 157 | { 158 | va_list args; 159 | va_start(args, format); 160 | [SQLog logvLevel:level Format:format VaList:args]; 161 | va_end(args); 162 | } 163 | 164 | + (void)logV:(NSString *)format, ... 165 | { 166 | va_list args; 167 | va_start(args, format); 168 | [SQLog logvLevel:LOGLEVELV Format:format VaList:args]; 169 | va_end(args); 170 | } 171 | 172 | + (void)logD:(NSString *)format, ... 173 | { 174 | va_list args; 175 | va_start(args, format); 176 | [SQLog logvLevel:LOGLEVELD Format:format VaList:args]; 177 | va_end(args); 178 | } 179 | 180 | + (void)logI:(NSString *)format, ... 181 | { 182 | va_list args; 183 | va_start(args, format); 184 | [SQLog logvLevel:LOGLEVELI Format:format VaList:args]; 185 | va_end(args); 186 | } 187 | 188 | + (void)logW:(NSString *)format, ... 189 | { 190 | va_list args; 191 | va_start(args, format); 192 | [SQLog logvLevel:LOGLEVELW Format:format VaList:args]; 193 | va_end(args); 194 | } 195 | 196 | + (void)logE:(NSString *)format, ... 197 | { 198 | va_list args; 199 | va_start(args, format); 200 | [SQLog logvLevel:LOGLEVELE Format:format VaList:args]; 201 | va_end(args); 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQLogToolManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SQLogToolManager.h 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 本工具的管理类,使用的时候就用这个类即可。 10 | 11 | #import 12 | #import "SQLog.h" 13 | 14 | /** 15 | log显示宏定义。 16 | 17 | @param ... 可变参数,跟NSLog一致 18 | */ 19 | #define NSLogD(...) do{\ 20 | switch ([SQLogToolManager shareManager].logLevel) {\ 21 | case SQLogToolManagerLevelNone:{} break;\ 22 | case SQLogToolManagerLevelLog:{\ 23 | NSLog(__VA_ARGS__);} break;\ 24 | case SQLogToolManagerLevelText:{\ 25 | SQLogD(__VA_ARGS__);} break;\ 26 | default: break;}\ 27 | } while (0); 28 | 29 | 30 | typedef enum 31 | { 32 | SQLogToolManagerLevelNone = 0, //不打印log 33 | SQLogToolManagerLevelLog = 1, //只在控制台显示log 34 | SQLogToolManagerLevelText = 2 //在控制台显示log及在本地写入log 35 | } SQLogToolManagerLevel;//log模式 36 | 37 | @interface SQLogToolManager : NSObject 38 | 39 | 40 | /** 41 | 单例 42 | */ 43 | + (instancetype)shareManager; 44 | 45 | /** 46 | 初始化 47 | */ 48 | - (void)logIntial; 49 | 50 | 51 | /** 52 | logLevel,log模式,通过这个属性设置log的模式 53 | */ 54 | @property (nonatomic, assign) SQLogToolManagerLevel logLevel; 55 | 56 | @end 57 | 58 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/SQLogTool/SQLogToolManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SQLogToolManager.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import "SQLogToolManager.h" 12 | #import "SQLog.h" 13 | #import "SQFloatWindow.h" 14 | 15 | 16 | #define SQ_LogLevel_UserDefalut @"SQLogToolManagerLevel" 17 | 18 | @interface SQLogToolManager () 19 | 20 | /** 21 | 悬浮窗 22 | */ 23 | @property (nonatomic, strong) SQFloatWindow *floatWindow; 24 | 25 | /** 26 | documentInteractionController,用来显示或者分享log文件内容 27 | */ 28 | @property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController ; 29 | 30 | @end 31 | 32 | @implementation SQLogToolManager 33 | 34 | //单例 35 | + (instancetype)shareManager 36 | { 37 | static SQLogToolManager *manager = nil; 38 | static dispatch_once_t onceToken; 39 | dispatch_once(&onceToken, ^{ 40 | manager = [[SQLogToolManager alloc] init]; 41 | }); 42 | return manager; 43 | } 44 | 45 | 46 | //初始化log类型 47 | - (void)logIntial 48 | { 49 | NSInteger logLevel = [[NSUserDefaults standardUserDefaults] integerForKey:SQ_LogLevel_UserDefalut]; 50 | 51 | self.logLevel = (SQLogToolManagerLevel)logLevel; 52 | } 53 | 54 | 55 | 56 | #pragma mark - setter 57 | 58 | - (void)setLogLevel:(SQLogToolManagerLevel)logLevel 59 | { 60 | _logLevel = logLevel; 61 | 62 | NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; 63 | switch (logLevel) { 64 | case SQLogToolManagerLevelNone://不打印log 65 | { 66 | //处理userDefault中的level值及floatWindow显示 67 | [userDefault setInteger:SQLogToolManagerLevelNone forKey:SQ_LogLevel_UserDefalut]; 68 | [userDefault synchronize]; 69 | if (_floatWindow) 70 | { 71 | [_floatWindow dissmissWindow]; 72 | _floatWindow = nil; 73 | } 74 | } 75 | break; 76 | case SQLogToolManagerLevelLog://只在控制台显示log 77 | { 78 | [userDefault setInteger:SQLogToolManagerLevelLog forKey:SQ_LogLevel_UserDefalut]; 79 | [userDefault synchronize]; 80 | 81 | if (_floatWindow) 82 | { 83 | [_floatWindow dissmissWindow]; 84 | _floatWindow = nil; 85 | } 86 | } 87 | break; 88 | case SQLogToolManagerLevelText://在控制台显示log及在本地写入log 89 | { 90 | [userDefault setInteger:SQLogToolManagerLevelText forKey:SQ_LogLevel_UserDefalut]; 91 | [userDefault synchronize]; 92 | 93 | [self.floatWindow showWindow]; 94 | } 95 | break; 96 | 97 | default: 98 | break; 99 | } 100 | } 101 | 102 | 103 | #pragma mark - getter 104 | 105 | - (SQFloatWindow *)floatWindow 106 | { 107 | if (_floatWindow == nil) 108 | { 109 | //log初始化 110 | [SQLog logIntial]; 111 | // [SQLog setLogLevel:LOGLEVELD]; 112 | 113 | //floatWindow 初始化 114 | _floatWindow = [[SQFloatWindow alloc] initWithFrame:CGRectMake(0, 200, 50, 50) mainBtnName:@"调试log" titles:@[@"预览",@"Xcode",@"关闭"]]; 115 | 116 | __weak typeof(self) weakSelf = self; 117 | 118 | //点击事件处理 119 | _floatWindow.clickBlocks = ^(NSInteger i){ 120 | 121 | switch (i) 122 | { 123 | case 0: 124 | { 125 | //显示沙盒本地log 126 | [weakSelf displayLocalLog]; 127 | } 128 | break; 129 | case 1: 130 | { 131 | //Xcode显示log 132 | weakSelf.logLevel = SQLogToolManagerLevelLog; 133 | } 134 | break; 135 | case 2: 136 | { 137 | //隐藏log 138 | weakSelf.logLevel = SQLogToolManagerLevelNone; 139 | } 140 | break; 141 | default: 142 | break; 143 | } 144 | 145 | }; 146 | } 147 | return _floatWindow; 148 | } 149 | 150 | //显示沙盒本地log 151 | - (void)displayLocalLog 152 | { 153 | if (![SQLog getLogFilePath]) 154 | { 155 | return; 156 | } 157 | 158 | //由文件路径初始化UIDocumentInteractionController 159 | UIDocumentInteractionController *documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:[SQLog getLogFilePath]]]; 160 | self.documentInteractionController = documentInteractionController ; 161 | documentInteractionController.delegate = self; 162 | 163 | // //显示分享文档界面 164 | // [documentInteractionController presentOptionsMenuFromRect:[UIScreen mainScreen].bounds inView:[UIApplication sharedApplication].keyWindow.rootViewController.view animated:YES]; 165 | 166 | //直接显示预览界面 167 | [documentInteractionController presentPreviewAnimated:YES]; 168 | } 169 | 170 | #pragma mark - UIDocumentInteractionControllerDelegate 171 | 172 | //在哪个控制器显示预览界面 173 | -(UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller 174 | { 175 | return [UIApplication sharedApplication].keyWindow.rootViewController; 176 | } 177 | 178 | @end 179 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import 12 | 13 | @interface ViewController : UIViewController 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. All rights reserved. 7 | // github地址:https://github.com/shixueqian/iOS10LogDebugTool 8 | // 简书介绍地址:http://www.jianshu.com/p/23011d141622 9 | // 10 | 11 | #import "ViewController.h" 12 | //需要导入头文件 13 | #import "SQLogToolManager.h" 14 | 15 | @interface ViewController () 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | } 26 | 27 | - (IBAction)onClickNone:(UIButton *)sender 28 | { 29 | //设置成SQLogToolManagerLevelNone模式 30 | [SQLogToolManager shareManager].logLevel = SQLogToolManagerLevelNone; 31 | 32 | //调用看看效果 33 | for (int i = 0; i < 10; ++i) 34 | { 35 | NSLogD(@"这里是None模式。%@:%d",@"第一个参数",i); 36 | } 37 | } 38 | 39 | - (IBAction)onClickXcodeLog:(UIButton *)sender 40 | { 41 | //设置成SQLogToolManagerLevelLog模式 42 | [SQLogToolManager shareManager].logLevel = SQLogToolManagerLevelLog; 43 | 44 | //调用看看效果 45 | for (int i = 0; i < 10; ++i) 46 | { 47 | NSLogD(@"这里是Xcode Log模式。%@:%d",@"第一个参数",i); 48 | } 49 | } 50 | 51 | - (IBAction)onClickWriteToTextAndShowFloatWindow:(UIButton *)sender 52 | { 53 | //设置成SQLogToolManagerLevelText模式 54 | [SQLogToolManager shareManager].logLevel = SQLogToolManagerLevelText; 55 | 56 | //调用看看效果 57 | for (int i = 0; i < 1; ++i) 58 | { 59 | NSLogD(@"这里是Log写入模式。%@:%d",@"第一个参数",i); 60 | } 61 | } 62 | 63 | 64 | //测试 65 | - (IBAction)onClickTest:(UIButton *)sender 66 | { 67 | //调用看看效果 68 | for (int i = 0; i < 10; ++i) 69 | { 70 | NSLogD(@"这里是测试。%@:%d",@"第一个参数",i); 71 | } 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /iOS10LogTool/iOS10LogTool/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOS10LogTool 4 | // 5 | // Created by 石学谦 on 17/4/11. 6 | // Copyright © 2017年 shixueqian. 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 | -------------------------------------------------------------------------------- /screenshots/分享界面.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixueqian/iOSLogTool/b7f5c1d1f3782dfece41b6cfc704c757b62a3a17/screenshots/分享界面.PNG -------------------------------------------------------------------------------- /screenshots/悬浮窗模式.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixueqian/iOSLogTool/b7f5c1d1f3782dfece41b6cfc704c757b62a3a17/screenshots/悬浮窗模式.PNG -------------------------------------------------------------------------------- /screenshots/效果示例.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixueqian/iOSLogTool/b7f5c1d1f3782dfece41b6cfc704c757b62a3a17/screenshots/效果示例.gif -------------------------------------------------------------------------------- /screenshots/预览界面.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixueqian/iOSLogTool/b7f5c1d1f3782dfece41b6cfc704c757b62a3a17/screenshots/预览界面.PNG --------------------------------------------------------------------------------