No Description

Kevin Bradley e691d2c1cb synced KBDatePicker with its separately hosted counterpart, made the date interaction a bit cleaner 8 months ago
.github 5a760fb1ac Update issue templates 8 months ago
Classes e691d2c1cb synced KBDatePicker with its separately hosted counterpart, made the date interaction a bit cleaner 8 months ago
Example 212afb019b added usage hints view to make learning the tvOS version a little easier 8 months ago
FLEX.xcodeproj 18637b70ab Merge branch 'master' of https://github.com/FLEXTool/FLEX 8 months ago
FLEXTests 3b5e095f74 Add some tests, fix some tests 8 months ago
Graphics 8f85b22866 Recent icon change 1 year ago
WebKit.framework 885ef194b5 added webkit framework and a few more build changes 8 months ago
flexinjected 7e7c268314 updated README, might actually be PR ready 8 months ago
layout 6bad4b1e90 last changes before rebasing 8 months ago
tvOSAccessoryImages ee25453031 cropped images of the TVTableViewCellAccessoryTypes 8 months ago
.clang-format ed9b721cd5 Add .clang-format file to the project 6 years ago
.gitignore 74a9fd805f update gitignore 8 months ago
.travis.yml 675f03fc71 Make Travis use xcodebuild (and xcpretty) instead of (deprecated) xctool 3 years ago
CONTRIBUTING.md 928f60b56f Add contributing stub 5 years ago
FLEX-tvOS-Info.plist 2afb5e4caa 4.3.0 release commit 8 months ago
FLEX.podspec e89fec4b2d Bump version 9 months ago
LICENSE 3cf9f72dcb Update license year range to 2016 5 years ago
README.md 6bad4b1e90 last changes before rebasing 8 months ago
postScript.sh 2afb5e4caa 4.3.0 release commit 8 months ago
tvOSBuild.sh d1efef8344 last script change for now 8 months ago
tvos_flexing.gif 9332b161c9 new gif and other README changes 8 months ago
view_selection.MP4 4ad4df9ba9 add this video while my speeds are good 9 months ago

README.md

FLEX

CocoaPods CocoaPods [CocoaPods]() Build Status Carthage compatible

FLEX (Flipboard Explorer) is a set of in-app debugging and exploration tools for iOS & tvOS 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.

Demo

Give Yourself Debugging Superpowers

  • Inspect and modify views in the hierarchy.
  • See the properties and ivars on any object.
  • Dynamically modify many properties and ivars.
  • Dynamically call instance and class methods.
  • Observe detailed network request history with timing, headers, and full responses.
  • Add your own simulator keyboard shortcuts.
  • View system log messages (e.g. from NSLog).
  • Access any live object via a scan of the heap.
  • View the file system within your app's sandbox.
  • Browse SQLite/Realm databases in the file system.
  • Trigger 3D touch in the simulator using the control, shift, and command keys.
  • Explore all classes in your app and linked systems frameworks (public and private).
  • Quickly access useful objects such as [UIApplication sharedApplication], the app delegate, the root view controller on the key window, and more.
  • Dynamically view and modify NSUserDefaults values.

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.

Usage

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:

Short version:

// Objective-C
[[FLEXManager sharedManager] showExplorer];
// Swift
FLEXManager.shared.showExplorer()

More complete version:

#if DEBUG
#import "FLEXManager.h"
#endif

...

- (void)handleSixFingerQuadrupleTap:(UITapGestureRecognizer *)tapRecognizer
{
#if DEBUG
    if (tapRecognizer.state == UIGestureRecognizerStateRecognized) {
        // This could also live in a handler for a keyboard shortcut, debug menu item, etc.
        [[FLEXManager sharedManager] showExplorer];
    }
#endif
}

Feature Examples

Modify Views

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.

Modify Views

Network History

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.

Network History

All Objects on the Heap

FLEX queries malloc for all the live allocated memory blocks and searches for ones that look like objects. You can see everything from here.

Heap/Live Objects Explorer

Explore-at-address

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"

Address Explorer

Simulator Keyboard Shortcuts

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]

Simulator Keyboard Shortcuts

File Browser

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.

File Browser

SQLite Browser

SQLite database files (with either .db or .sqlite extensions), or Realm 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.

SQLite Browser

3D Touch in the Simulator

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.

Simulator 3D Touch

Explore Loaded Libraries

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.

Loaded Libraries Exploration

NSUserDefaults Editing

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.

NSUserDefaults Editing

tvOS Notes

Installation notes

Check releases or build and add the framework manually, this will need review and merging in to the main repo & a cocoapod / carthage et al update to get the framework added in any other way for tvOS versions. ./tvOSBuild.sh is added for convenience and will yield a framework in the build/Release-appletvos folder.

General notes / usage

  • When in 'select' mode press the 'menu' button to return to the toolbar
  • When in 'select' mode play/pause will also work to click items and is more reliable than selection with the remote touch pad, tapping rather than clicking the touchpad is also more reliable. Tapping right on a siri remote / clicking right on an older silver remote will work as well
  • Press and hold 'select' to drill down to details in views hierarchy list view controller. Tapping right on a siri remote / clicking right on an older silver remote will work as well
  • When in selection mode double tap on 'play/pause' OR press and hold 'select' or 'play/pause' to bring up an alert with useful options ('view details', 'move view' and 'show views' are available there)

FLEXInjected notes

  • Easily used with a jailbreak: FLEXInjected (avail from default repos now with 'com.nito.flexinjected', bottom of featured section first item in 'Utilities')
  • After toggling via FLEXInjected it will take 10 seconds after launch for the toolbar to appear, if closed - triple tap play/pause to bring it back

Missing features

  • Snapshot view (i dont think this one is going to make it in)

tvOS

tvOS Video Demo

Learning from Other Apps

The code injection is left as an exercise for the reader. :innocent:

Springboard Lock Screen Springboard Home Screen

Installation

FLEX requires an app that targets iOS 9 or higher. To run the Example project, open a Terminal window in the Example/ folder and run pod install, then open the generated workspace.

CocoaPods

FLEX is available on CocoaPods. Simply add the following line to your podfile:

pod 'FLEX', :configurations => ['Debug']

Carthage

Add the following to your Cartfile:

github "flipboard/FLEX"

Buck

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 other warning flags below to disable any other warnings FLEX may have.

Manual

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.

Silencing warnings

Add the following flags to to Other Warnings Flags in Build Settings:

  • -Wno-deprecated-declarations
  • -Wno-strict-prototypes
  • -Wno-unsupported-availability-guard

Excluding FLEX from Release (App Store) Builds

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.

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.

CocoaPods

CocoaPods automatically excludes FLEX from release builds if you only specify the Debug configuration for FLEX in your Podfile:

pod 'FLEX', :configurations => ['Debug']

Carthage

  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).
  2. 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.
  3. 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:

    if [ "$CONFIGURATION" == "Debug" ]; then
      /usr/local/bin/carthage copy-frameworks
    fi
    

    Finally, add $(SRCROOT)/Carthage/Build/iOS/FLEX.framework as input file of this script phase.

FLEX files added manually to a project

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:

Additional Notes

  • 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.
  • 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.

Thanks & Credits

FLEX builds on ideas and inspiration from open source tools that came before it. The following resources have been particularly helpful:

  • MirrorKit: an Objective-C wrapper around the Objective-C runtime.
  • DCIntrospect: view hierarchy debugging for the iOS simulator.
  • PonyDebugger: network, core data, and view hierarchy debugging using the Chrome Developer Tools interface.
  • Mike Ash: well written, informative blog posts on all things obj-c and more. The links below were very useful for this project:
  • 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.
  • heap_find.cpp: an example of enumerating malloc blocks for finding objects on the heap.
  • Gist from @samdmarshall: another example of enumerating malloc blocks.
  • Non-pointer isa: an explanation of changes to the isa field on iOS for ARM64 and mention of the useful objc_debug_isa_class_mask variable.
  • GZIP: A library for compressing/decompressing data on iOS using libz.
  • FMDB: This is an Objective-C wrapper around SQLite.
  • InAppViewDebugger: The inspiration and reference implementation for FLEX 4's 3D view explorer, by @indragiek.

Contributing

Please see our Contributing Guide.

TODO

  • Swift runtime introspection (swift classes, swift objects on the heap, etc.)
  • Add new NSUserDefault key/value pairs on the fly