You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
14 KiB

  1. # FLEX
  2. [![CocoaPods](https://img.shields.io/cocoapods/v/FLEX.svg)](https://cocoapods.org/?q=FLEX)
  3. [![CocoaPods](https://img.shields.io/cocoapods/l/FLEX.svg)](https://github.com/Flipboard/FLEX/blob/master/LICENSE)
  4. [![CocoaPods](https://img.shields.io/cocoapods/p/FLEX.svg)]()
  5. [![Twitter: @ryanolsonk](https://img.shields.io/badge/contact-@ryanolsonk-blue.svg?style=flat)](https://twitter.com/ryanolsonk)
  6. [![Build Status](https://travis-ci.org/Flipboard/FLEX.svg?branch=master)](https://travis-ci.org/Flipboard/FLEX)
  7. [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
  8. FLEX (Flipboard Explorer) is a set of in-app debugging and exploration tools for iOS development. When presented, FLEX shows a toolbar that lives in a window above your application. From this toolbar, you can view and modify nearly every piece of state in your running application.
  9. <img alt="Demo" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70185687-e842c800-16af-11ea-8ef9-9e071380a462.gif>
  10. ## Give Yourself Debugging Superpowers
  11. - Inspect and modify views in the hierarchy.
  12. - See the properties and ivars on any object.
  13. - Dynamically modify many properties and ivars.
  14. - Dynamically call instance and class methods.
  15. - Observe detailed network request history with timing, headers, and full responses.
  16. - Add your own simulator keyboard shortcuts.
  17. - View system log messages (e.g. from `NSLog`).
  18. - Access any live object via a scan of the heap.
  19. - View the file system within your app's sandbox.
  20. - Browse SQLite/Realm databases in the file system.
  21. - Trigger 3D touch in the simulator using the control, shift, and command keys.
  22. - Explore all classes in your app and linked systems frameworks (public and private).
  23. - Quickly access useful objects such as `[UIApplication sharedApplication]`, the app delegate, the root view controller on the key window, and more.
  24. - Dynamically view and modify `NSUserDefaults` values.
  25. Unlike many other debugging tools, FLEX runs entirely inside your app, so you don't need to be connected to LLDB/Xcode or a different remote debugging server. It works well in the simulator and on physical devices.
  26. ## Usage
  27. In the iOS simulator, you can use keyboard shortcuts to activate FLEX. `f` will toggle the FLEX toolbar. Hit the `?` key for a full list of shortcuts. You can also show FLEX programmatically:
  28. Short version:
  29. ```objc
  30. // Objective-C
  31. [[FLEXManager sharedManager] showExplorer];
  32. ```
  33. ```swift
  34. // Swift
  35. FLEXManager.shared().showExplorer()
  36. ```
  37. More complete version:
  38. ```objc
  39. #if DEBUG
  40. #import "FLEXManager.h"
  41. #endif
  42. ...
  43. - (void)handleSixFingerQuadrupleTap:(UITapGestureRecognizer *)tapRecognizer
  44. {
  45. #if DEBUG
  46. if (tapRecognizer.state == UIGestureRecognizerStateRecognized) {
  47. // This could also live in a handler for a keyboard shortcut, debug menu item, etc.
  48. [[FLEXManager sharedManager] showExplorer];
  49. }
  50. #endif
  51. }
  52. ```
  53. ## Feature Examples
  54. ### Modify Views
  55. Once a view is selected, you can tap on the info bar below the toolbar to present more details about the view. From there, you can modify properties and call methods.
  56. <img alt="Modify Views" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271816-c5c2b480-176c-11ea-8bf4-2c5a755bc392.gif>
  57. ### Network History
  58. When enabled, network debugging allows you to view all requests made using NSURLConnection or NSURLSession. Settings allow you to adjust what kind of response bodies get cached and the maximum size limit of the response cache. You can choose to have network debugging enabled automatically on app launch. This setting is persisted across launches.
  59. <img alt="Network History" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271876-e5f27380-176c-11ea-98ef-24170205b706.gif>
  60. ### All Objects on the Heap
  61. FLEX queries malloc for all the live allocated memory blocks and searches for ones that look like objects. You can see everything from here.
  62. <img alt="Heap/Live Objects Explorer" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271850-d83cee00-176c-11ea-9750-ee3a479c6769.gif>
  63. ### Explore-at-address
  64. If you get your hands on an arbitrary address, you can try explore the object at that address, and FLEX will open it if it can verify the address points to a valid object. If FLEX isn't sure, it'll warn you and refuse to dereference the pointer. If you know better, however, you can choose to explore it anyway by choosing "Unsafe Explore"
  65. <img alt="Address Explorer" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271798-bb081f80-176c-11ea-806d-9d74ac293641.gif>
  66. ### Simulator Keyboard Shortcuts
  67. Default keyboard shortcuts allow you to activate the FLEX tools, scroll with the arrow keys, and close modals using the escape key. You can also add custom keyboard shortcuts via `-[FLEXManager registerSimulatorShortcutWithKey:modifiers:action:description]`
  68. <img alt="Simulator Keyboard Shortcuts" width=40% height=40% src="https://user-images.githubusercontent.com/8371943/70272984-d3793980-176e-11ea-89a2-66d187d71b4c.png">
  69. ### File Browser
  70. View the file system within your app's bundle or sandbox container. FLEX shows file sizes, image previews, and pretty prints `.json` and `.plist` files. You can rename and delete files and folders. You can "share" any file if you want to inspect them outside of your app.
  71. <img alt="File Browser" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271831-d115e000-176c-11ea-8078-ada291f980f3.gif>
  72. ### SQLite Browser
  73. SQLite database files (with either `.db` or `.sqlite` extensions), or [Realm](https://realm.io) database files can be explored using FLEX. The database browser lets you view all tables, and individual tables can be sorted by tapping column headers.
  74. <img alt="SQLite Browser" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271881-ea1e9100-176c-11ea-9a42-01618311c869.gif>
  75. ### 3D Touch in the Simulator
  76. Using a combination of the command, control, and shift keys, you can simulate different levels of 3D touch pressure in the simulator. Each key contributes 1/3 of maximum possible force. Note that you need to move the touch slightly to get pressure updates.
  77. <img alt="Simulator 3D Touch" width=36% height=36% src=https://cloud.githubusercontent.com/assets/1422245/11786615/5d4ef96c-a23c-11e5-975e-67275341e439.gif>
  78. ### Explore Loaded Libraries
  79. Go digging for all things public and private. To learn more about a class, you can create an instance of it and explore its default state. You can also type in a class name to jump to that class directly if you know which class you're looking for.
  80. <img alt="Loaded Libraries Exploration" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271868-dffc9280-176c-11ea-8704-a0c05b75cc5f.gif>
  81. ### NSUserDefaults Editing
  82. FLEX allows you to edit defaults that are any combination of strings, numbers, arrays, and dictionaries. The input is parsed as `JSON`. If other kinds of objects are set for a defaults key (i.e. `NSDate`), you can view them but not edit them.
  83. <img alt="NSUserDefaults Editing" width=36% height=36% src=https://user-images.githubusercontent.com/8371943/70271889-edb21800-176c-11ea-92b4-71e07d2b6ce7.gif>
  84. ### Learning from Other Apps
  85. The code injection is left as an exercise for the reader. :innocent:
  86. <p float="left">
  87. <img alt="Springboard Lock Screen" width=25% height=25% src= https://engineering.flipboard.com/assets/flex/flex-readme-reverse-1.png>
  88. <img alt="Springboard Home Screen" width=25% height=25% src= https://engineering.flipboard.com/assets/flex/flex-readme-reverse-2.png>
  89. </p>
  90. ## Installation
  91. FLEX requires an app that targets iOS 9 or higher.
  92. ### CocoaPods
  93. FLEX is available on [CocoaPods](https://cocoapods.org/pods/FLEX). Simply add the following line to your podfile:
  94. ```ruby
  95. pod 'FLEX', :configurations => ['Debug']
  96. ```
  97. ### Carthage
  98. Add the following to your Cartfile:
  99. ```
  100. github "flipboard/FLEX"
  101. ```
  102. ### Buck
  103. If you're using Buck, you may want to silence some of the warnings emitted by FLEX. You will need to build FLEX as an `apple_library` and pass the `-Wno-unsupported-availability-guard` flag, as well as the flags to disable any other warnings FLEX may have.
  104. ### Manual
  105. Manually add the files in `Classes/` to your Xcode project, or just drag in the entire `FLEX/` folder. Be sure to exclude FLEX from `Release` builds or your app will be rejected.
  106. ##### Silencing warnings
  107. Add the following flags to to **Other Warnings Flags** in **Build Settings:**
  108. - `-Wno-deprecated-declarations`
  109. - `-Wno-unsupported-availability-guard`
  110. ## Excluding FLEX from Release (App Store) Builds
  111. FLEX makes it easy to explore the internals of your app, so it is not something you should expose to your users. Fortunately, it is easy to exclude FLEX files from Release builds. The strategies differ depending on how you integrated FLEX in your project, and are described below.
  112. Wrap the places in your code where you integrate FLEX with an `#if DEBUG` statement to ensure the tool is only accessible in your `Debug` builds and to avoid errors in your `Release` builds. For more help with integrating FLEX, see the example project.
  113. ### CocoaPods
  114. CocoaPods automatically excludes FLEX from release builds if you only specify the Debug configuration for FLEX in your Podfile:
  115. ```ruby
  116. pod 'FLEX', :configurations => ['Debug']
  117. ```
  118. ### Carthage
  119. 1. Do NOT add `FLEX.framework` to the embedded binaries of your target, as it would otherwise be included in all builds (therefore also in release ones).
  120. 1. Instead, add `$(PROJECT_DIR)/Carthage/Build/iOS` to your target _Framework Search Paths_ (this setting might already be present if you already included other frameworks with Carthage). This makes it possible to import the FLEX framework from your source files. It does not harm if this setting is added for all configurations, but it should at least be added for the debug one.
  121. 1. Add a _Run Script Phase_ to your target (inserting it after the existing `Link Binary with Libraries` phase, for example), and which will embed `FLEX.framework` in debug builds only:
  122. ```shell
  123. if [ "$CONFIGURATION" == "Debug" ]; then
  124. /usr/local/bin/carthage copy-frameworks
  125. fi
  126. ```
  127. Finally, add `$(SRCROOT)/Carthage/Build/iOS/FLEX.framework` as input file of this script phase.
  128. <img width=75% height=75% src=https://user-images.githubusercontent.com/8371943/70274062-0d4b3f80-1771-11ea-94ea-ca7e7b5ca244.jpg>
  129. ### FLEX files added manually to a project
  130. In Xcode, navigate to `Build Settings > Build Options > Excluded Source File Names`. For your `Release` configuration, set it to `FLEX*` like this to exclude all files with the `FLEX` prefix:
  131. <img width=75% height=75% src=https://user-images.githubusercontent.com/8371943/70281926-e21d1c00-1781-11ea-92eb-aee340791da8.png>
  132. ## Additional Notes
  133. - When setting fields of type `id` or values in `NSUserDefaults`, FLEX attempts to parse the input string as `JSON`. This allows you to use a combination of strings, numbers, arrays, and dictionaries. If you want to set a string value, it must be wrapped in quotes. For ivars or properties that are explicitly typed as `NSStrings`, quotes are not required.
  134. - You may want to disable the exception breakpoint while using FLEX. Certain functions that FLEX uses throw exceptions when they get input they can't handle (i.e. `NSGetSizeAndAlignment()`). FLEX catches these to avoid crashing, but your breakpoint will get hit if it is active.
  135. ## Thanks & Credits
  136. FLEX builds on ideas and inspiration from open source tools that came before it. The following resources have been particularly helpful:
  137. - [DCIntrospect](https://github.com/domesticcatsoftware/DCIntrospect): view hierarchy debugging for the iOS simulator.
  138. - [PonyDebugger](https://github.com/square/PonyDebugger): network, core data, and view hierarchy debugging using the Chrome Developer Tools interface.
  139. - [Mike Ash](https://www.mikeash.com/pyblog/): well written, informative blog posts on all things obj-c and more. The links below were very useful for this project:
  140. - [MAObjCRuntime](https://github.com/mikeash/MAObjCRuntime)
  141. - [Let's Build Key Value Coding](https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html)
  142. - [ARM64 and You](https://www.mikeash.com/pyblog/friday-qa-2013-09-27-arm64-and-you.html)
  143. - [RHObjectiveBeagle](https://github.com/heardrwt/RHObjectiveBeagle): a tool for scanning the heap for live objects. It should be noted that the source code of RHObjectiveBeagle was not consulted due to licensing concerns.
  144. - [heap_find.cpp](https://www.opensource.apple.com/source/lldb/lldb-179.1/examples/darwin/heap_find/heap/heap_find.cpp): an example of enumerating malloc blocks for finding objects on the heap.
  145. - [Gist](https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396) from [@samdmarshall](https://github.com/samdmarshall): another example of enumerating malloc blocks.
  146. - [Non-pointer isa](http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html): an explanation of changes to the isa field on iOS for ARM64 and mention of the useful `objc_debug_isa_class_mask` variable.
  147. - [GZIP](https://github.com/nicklockwood/GZIP): A library for compressing/decompressing data on iOS using libz.
  148. - [FMDB](https://github.com/ccgus/fmdb): This is an Objective-C wrapper around SQLite
  149. ## Contributing
  150. Please see our [Contributing Guide](https://github.com/Flipboard/FLEX/blob/master/CONTRIBUTING.md).
  151. ## TODO
  152. - Swift runtime introspection (swift classes, swift objects on the heap, etc.)
  153. - Improved file type detection and display in the file browser
  154. - Add new NSUserDefault key/value pairs on the fly