Compare commits

..

103 Commits

Author SHA1 Message Date
Ryan Olson e40054ba1a Merge pull request #142 from shepting/patch-1
Fix typo pruged -> pruned
2016-09-30 16:42:58 -07:00
Ryan Olson 1761734447 Merge pull request #149 from c0diq/xcode8
Add Xcode8 support
2016-09-30 16:41:54 -07:00
Ryan Olson f23ee3cd95 Merge pull request #151 from Blankdlh/master
Fix method swizzling for NSURLSessionDelegate
2016-09-30 16:38:55 -07:00
kunka e455ac0c7d Fix swizzling for URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: and URLSession:dataTask:didReceiveResponse:completionHandler: 2016-09-29 18:10:31 +08:00
Sylvain Rebaud 94f68c6dfe Add Xcode8 support 2016-09-26 15:15:36 -07:00
Steven Hepting a22f022014 Fix typo. 2016-08-15 08:17:07 -07:00
Ryan Olson 22e7edb698 Bring back the memory reader for heap enumeration
Some malloc replacements don't provide a default reader
2016-08-09 08:55:54 -07:00
Ryan Olson 52fcda53c5 Merge pull request #138 from iampgzp/master
Added curl logger for debugging request
2016-08-01 10:15:44 -07:00
Ji Pei be6c5d0e43 Removed curl log in recordRequestWillBeSentWithRequestID to avoid too much logging spew 2016-08-01 12:49:32 -04:00
Ryan Olson 6ed0037f50 Merge pull request #134 from ThePantsThief/master
Search for a specific class
2016-07-29 15:35:49 -07:00
Ryan Olson 81e3a5ff47 Merge pull request #132 from revolter/patch-1
Update FLEXRuntimeUtility.m
2016-07-29 15:27:32 -07:00
Ji Pei 2a6e28c9d0 Added curl logger for debugging request 2016-07-27 16:52:47 -04:00
ThePantsThief 9e928b0b09 Fix incorrect strcmp check 2016-07-22 12:49:17 -05:00
Tanner Bennett d5deaad628 Search for a specific class
Added a way to jump to a specific class from the System Libraries tab,
since it is sometimes difficult to find a class if you don’t know which
bundle it’s in.

Also fixed a few other things that bugged me, like manually getting the
last path component of a string instead of using the lastPathComponent
property…
2016-07-06 15:04:39 -05:00
Iulian Onofrei 232ae8a6fd Update FLEXRuntimeUtility.m
Fix typos
2016-06-21 10:46:57 +03:00
Ryan Olson c766e5d94a Merge pull request #128 from Flipboard/timoliver-realm-path-fix
Replaced deprecated 'path' property in Realm configuration
2016-05-20 06:15:30 -07:00
Tim Oliver 5f27a2304b Replaced 'path' property with 'fileURL' in Realm configuration 2016-05-20 15:21:24 +08:00
Ryan Olson 0cb0f44f18 Update version in .podspec 2016-02-28 22:18:38 -08:00
Ryan Olson d1c1aa0a26 Fix xcodebuild error from incorrect method resolution 2016-02-28 22:15:07 -08:00
Ryan Olson 832957f621 Merge pull request #114 from SoXeon/master
fix crash when object malloc_size no greater than zero
2016-02-28 21:52:30 -08:00
Ryan Olson 24985ac984 Fix crash on calling _keyCode on events from the simulator keyboard 2016-02-28 21:43:39 -08:00
dazi.dp 0b652c2f2a add malloc.h 2016-02-25 22:31:47 +08:00
dazi.dp 98d83bb438 fix crash when object malloc_size no greater than zero 2016-02-25 22:20:22 +08:00
Tim Oliver e13717b056 Merge pull request #112 from TimOliver/timoliver-realm-null-fix
Added handling for nil Realm property values.
2016-02-23 22:12:57 +08:00
Tim Oliver 552e687b9c Added handling for nil Realm property values 2016-02-23 22:08:51 +08:00
Ryan Olson fb29421644 Merge pull request #110 from TimOliver/patch-1
Updated database features in README.
2016-02-22 22:08:27 -08:00
Tim Oliver f5d930bd58 Updated database features in README. 2016-02-22 02:10:15 +08:00
Ryan Olson 26af4ef476 Merge pull request #105 from TimOliver/timoliver-realm-integration
Added Realm Database File Introspection Alongside SQLite
2016-02-21 09:39:55 -08:00
Ryan Olson ac8940da26 Merge pull request #107 from nin9tyfour/master
*Added the ability to determine a UIView's view controller without selection the view controller's view delegate.
2016-02-16 20:24:36 -08:00
Tim Oliver f597152a62 Cleaned up example project. 2016-02-17 11:35:39 +08:00
Tim Oliver 58f94f108c Made protocol required. 2016-02-17 11:34:54 +08:00
Tim Oliver a5e0bbd50e Added better extension-checking logic. 2016-02-17 11:34:36 +08:00
Tim Oliver ac273fbfc9 Added test Realm file and classes to the sample app. 2016-02-17 11:20:17 +08:00
Tim Oliver 548fd03bd5 Made Realm integration a dynamic runtime check. 2016-02-17 11:19:17 +08:00
nin9tyfour b564c25d2a *Added the ability to determine a UIView's view controller without selection the view controller's view delegate. 2016-02-16 15:29:52 +11:00
Ryan Olson bd821dc553 Restrict simulator force touch support to iOS 9+ 2016-02-13 13:44:00 -08:00
Ryan Olson e46a33417b Merge pull request #106 from ReadmeCritic/master
Correct the spelling of CocoaPods in README
2016-02-13 13:36:37 -08:00
ReadmeCritic a3419a841f Correct the spelling of CocoaPods in README 2016-02-11 15:46:43 -08:00
Tim Oliver cafc1ba0bd Reset UICatalog project. 2016-02-09 14:16:54 +08:00
Tim Oliver 0112c097d9 Updated Realm optional macros and cleaned project changes. 2016-02-09 14:10:52 +08:00
Tim Oliver 507d03fd90 Cleaned up project file, and added test Realm file. 2016-02-07 16:47:31 +08:00
Tim Oliver b6453ac360 Made references to Realm build optional. 2016-02-06 15:36:49 +08:00
Tim Oliver b693ceb20e Cleaned up protocol logic. 2016-02-06 14:42:19 +08:00
Ryan Olson 31e81a616d Merge pull request #104 from Flipboard/dzc-add-contributing
Add contributing stub
2016-01-30 15:13:42 -08:00
David Creemer 928f60b56f Add contributing stub 2016-01-28 13:19:10 -08:00
Tim Oliver 12a1900d75 Abstracted database parser logic and added framework for Realm parser. 2016-01-28 12:50:39 +08:00
Ryan Olson c72b6f7e5b Merge pull request #102 from pra85/patch-1
Update license year range to 2016
2016-01-18 11:43:12 -08:00
Prayag Verma 3cf9f72dcb Update license year range to 2016 2016-01-18 14:12:03 +05:30
Ryan Olson 9b1318e975 Project structure cleanup 2016-01-17 20:52:34 -08:00
Ryan Olson d3d0f04c23 Heap scan cleanup 2016-01-17 19:54:38 -08:00
Ryan Olson b606d04944 Fix keyboard shortcuts firing when typing into an alert view 2016-01-11 13:27:15 -08:00
Ryan Olson 7afd50d241 Remove asl hacks needed for iOS 7 2016-01-08 15:01:42 -08:00
Ryan Olson 94f06d5ff8 Fix heap search/enumeration crashes! 2016-01-06 17:43:01 -08:00
Ryan Olson 85424fd15e Support viewing AFNetworking request bodies 2016-01-05 15:10:10 -08:00
Ryan Olson cff391f78c Use NSKeyedArchiver for files with .coded extensions 2015-12-18 19:38:32 -05:00
Ryan Olson 3e420bb747 Bump version in .podspec 2015-12-14 08:56:10 -08:00
Ryan Olson 8aece0a266 Update README 2015-12-14 08:31:42 -08:00
Ryan Olson 81b27b6918 Modify approach to toggling views and menu modals.
This approach seems to eliminate some of the status bar issues we were seeing.
2015-12-13 23:21:43 -08:00
Ryan Olson 727943c4b3 Merge pull request #92 from WangHengHeng/master
- (void)toggle***Tool - It is not necessary to 'dismiss' when 'present'
2015-12-13 23:12:41 -08:00
Ryan Olson 9f2c032157 List FLEX.h in the public headers in the podspec 2015-12-13 23:06:40 -08:00
Ryan Olson d6a5b1af8d Bump podspec iOS version to 8.0 2015-12-13 23:03:09 -08:00
Ryan Olson dda9dd5beb Move to UISearchController in FLEXSystemLogTableViewController 2015-12-13 22:55:57 -08:00
Ryan Olson 888887f09a Move to UISearchController in FLEXNetworkHistoryTableViewController 2015-12-13 22:46:46 -08:00
Ryan Olson b70a1a2f48 Move to UISearchController in FLEXFileBrowserTableViewController 2015-12-13 22:15:45 -08:00
Ryan Olson 54730c368c Use FLEX.framework in example project
Bump example project deployment target to iOS 8 so we can link to the dynamic framework.
2015-12-13 21:09:20 -08:00
Ryan Olson 21672e6f8d Merge pull request #93 from tttpeng/master
Add a sqlite database browser
2015-12-12 19:11:12 -08:00
Taavo 4ffc992872 Fix some problems about database browser 2015-12-06 04:32:26 +08:00
tttpeng 8eea2ec652 Remove useless methods, About sqlite browser 2015-12-02 12:00:40 +08:00
王 原闯 3df01ee7bb dismiss previous present viewController before present a new one 2015-12-02 10:53:55 +08:00
Ryan Olson d0ad6e4319 Merge pull request #94 from untouchable741/master
Support searching for view pointer address in FLEXHierarchyTableViewC…
2015-12-01 08:26:43 -08:00
Tai Vuong 37aec6dacc Support searching for view pointer address in FLEXHierarchyTableViewController 2015-12-01 22:32:24 +07:00
王 原闯 cdc5aae4b7 - (void)toggle***Tool - It is not necessary to 'dismiss' when 'present' 2015-11-30 18:01:19 +08:00
tttpeng fd2b89fd24 Add sqlite database browser 2015-11-30 17:36:41 +08:00
Ryan Olson f1683e54c3 Add support for force touch in the simulator 2015-11-16 11:37:57 -08:00
Ryan Olson c66dd2e7d3 Merge pull request #85 from dlo/master
Use Objective-C 2.0 subscripting
2015-11-09 06:29:55 -08:00
Ryan Olson 5a5b921bbf Merge pull request #89 from revolter/patch-1
Update FLEXManager.m
2015-11-09 06:27:26 -08:00
Iulian Onofrei 30cc65bd9d Update FLEXManager.m
Fix help screen typo
2015-11-09 11:18:29 +02:00
Dan Loewenherz 29a45aa02d use Objective-C 2.0 subscripting for dictionaries 2015-10-31 17:37:45 -05:00
Dan Loewenherz 08b25ea8d3 use Objective-C 2.0 subscripting for arrays 2015-10-31 17:35:47 -05:00
Ryan Olson 7ffcb83563 Bump version in FLEX.podspec 2015-10-28 20:05:54 -07:00
Ryan Olson b0b64c1ba9 Be robust against nil transactions in FLEXNetworkTransactionTableViewCell 2015-10-28 19:37:41 -07:00
Ryan Olson bc5dfa02ec Merge pull request #84 from robinsonrc/master
Add basic support for viewing shared HTTP cookie storage
2015-10-20 16:31:02 -07:00
Rich Robinson c69f5c220a Update UICatalog project to include FLEXCookiesTableViewController 2015-10-20 07:51:54 +01:00
Rich Robinson 7f28d430d0 Add basic support for viewing shared HTTP cookie storage 2015-10-19 20:05:04 +01:00
Ryan 30dc024903 Add missing runtime import to FLEXUtility 2015-10-10 07:24:54 -07:00
Ryan Olson 6403053989 Merge pull request #81 from orthographic-pedant/spell_check/across
Fixed typographical error, changed accross to across in README.
2015-09-30 14:01:24 -06:00
orthographic-pedant ba352c15e8 Fixed typographical error, changed accross to across in README. 2015-09-30 15:58:40 -04:00
Ryan Olson e9e084e6f1 Use new toggleExplorer convenience method in keyboard shortcut 2015-09-24 12:42:23 -06:00
Ryan Olson 26e92c2bd6 Merge pull request #80 from evliu/master
Convenience method to show/hide explorer depending on current isHidden
2015-09-24 12:37:53 -06:00
Everest Liu 41d761f822 Convenience method to show/hide explorer depending on current isHidden 2015-09-24 10:54:50 -07:00
Ryan Olson 832a03bf27 Bump version in FLEX.podspec 2015-09-21 14:10:26 -06:00
Ryan Olson ebf5254629 Guard usage of class only available in simulator builds 2015-09-21 14:03:16 -06:00
Ryan Olson e199b529c8 Add simulator shortcut info to README 2015-09-21 13:54:08 -06:00
Ryan Olson 06edea64ae Add help menu listing keyboard shortcuts 2015-09-21 13:54:08 -06:00
Ryan Olson 6d3afe36d1 Expand default FLEX keyboard shortcuts 2015-09-21 13:54:08 -06:00
Ryan Olson b22d2b57a2 Add support for keyboard shortcuts in the simulator 2015-09-21 13:54:08 -06:00
Ryan Olson b453086936 Pragma gardening 2015-09-19 21:56:51 -06:00
Ryan Olson 103489c566 Fix header documentatin 2015-09-19 21:56:24 -06:00
Ryan Olson 3dd27557ea Move swizzling helpers into FLEXUtility 2015-09-19 14:10:41 -06:00
Ryan Olson a64188dd5e Simplify network debugging settings
Having two switches to enable network debugging was confusing. One switch now enables network debugging and persists across launches of the app.
2015-09-19 13:56:46 -06:00
Ryan Olson 44e428655a Replace deprecated percent encoding string transformation method 2015-09-19 13:30:30 -06:00
Ryan Olson 96d8b425d5 Bump version in FLEX.podspec 2015-09-10 14:25:42 -06:00
Ryan Olson 7df172afac Make cast explicit 2015-09-10 14:25:08 -06:00
87 changed files with 3340 additions and 1701 deletions
+3
View File
@@ -0,0 +1,3 @@
# Contributing to FLEX #
We welcome contributions! Please open a pull request with your changes.
@@ -31,7 +31,7 @@
inputView.targetSize = FLEXArgumentInputViewSizeSmall;
if (fieldIndex < [customTitles count]) {
inputView.title = [customTitles objectAtIndex:fieldIndex];
inputView.title = customTitles[fieldIndex];
} else {
inputView.title = [NSString stringWithFormat:@"%@ field %lu (%@)", structName, (unsigned long)fieldIndex, prettyTypeEncoding];
}
@@ -72,7 +72,7 @@
[FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset) {
void *fieldPointer = unboxedValue + fieldOffset;
FLEXArgumentInputView *inputView = [self.argumentInputViews objectAtIndex:fieldIndex];
FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex];
if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) {
inputView.inputValue = (__bridge id)fieldPointer;
@@ -102,7 +102,7 @@
[FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset) {
void *fieldPointer = unboxedStruct + fieldOffset;
FLEXArgumentInputView *inputView = [self.argumentInputViews objectAtIndex:fieldIndex];
FLEXArgumentInputView *inputView = self.argumentInputViews[fieldIndex];
if (fieldTypeEncoding[0] == @encode(id)[0] || fieldTypeEncoding[0] == @encode(Class)[0]) {
// Object fields
@@ -17,6 +17,17 @@
- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates;
- (BOOL)wantsWindowToBecomeKey;
// Keyboard shortcut helpers
- (void)toggleSelectTool;
- (void)toggleMoveTool;
- (void)toggleViewsTool;
- (void)toggleMenuTool;
- (void)handleDownArrowKeyPressed;
- (void)handleUpArrowKeyPressed;
- (void)handleRightArrowKeyPressed;
- (void)handleLeftArrowKeyPressed;
@end
@protocol FLEXExplorerViewControllerDelegate <NSObject>
@@ -14,6 +14,7 @@
#import "FLEXGlobalsTableViewController.h"
#import "FLEXObjectExplorerViewController.h"
#import "FLEXObjectExplorerFactory.h"
#import "FLEXNetworkHistoryTableViewController.h"
typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
FLEXExplorerModeDefault,
@@ -330,9 +331,9 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
{
NSUInteger indexOfView = [self.viewsAtTapPoint indexOfObject:object];
if (indexOfView != NSNotFound) {
UIView *view = [self.viewsAtTapPoint objectAtIndex:indexOfView];
UIView *view = self.viewsAtTapPoint[indexOfView];
NSValue *key = [NSValue valueWithNonretainedObject:view];
UIView *outline = [self.outlineViewsForVisibleViews objectForKey:key];
UIView *outline = self.outlineViewsForVisibleViews[key];
if (outline) {
outline.frame = [self frameInLocalCoordinatesForView:view];
}
@@ -367,27 +368,18 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
- (void)selectButtonTapped:(FLEXToolbarItem *)sender
{
if (self.currentMode == FLEXExplorerModeSelect) {
self.currentMode = FLEXExplorerModeDefault;
} else {
self.currentMode = FLEXExplorerModeSelect;
}
[self toggleSelectTool];
}
- (void)hierarchyButtonTapped:(FLEXToolbarItem *)sender
{
NSArray *allViews = [self allViewsInHierarchy];
NSDictionary *depthsForViews = [self hierarchyDepthsForViews:allViews];
FLEXHierarchyTableViewController *hierarchyTVC = [[FLEXHierarchyTableViewController alloc] initWithViews:allViews viewsAtTap:self.viewsAtTapPoint selectedView:self.selectedView depths:depthsForViews];
hierarchyTVC.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:hierarchyTVC];
[self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];
[self toggleViewsTool];
}
- (NSArray *)allViewsInHierarchy
{
NSMutableArray *allViews = [NSMutableArray array];
NSArray *windows = [self allWindows];
NSArray *windows = [FLEXUtility allWindows];
for (UIWindow *window in windows) {
if (window != self.view.window) {
[allViews addObject:window];
@@ -397,28 +389,6 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
return allViews;
}
- (NSArray *)allWindows
{
BOOL includeInternalWindows = YES;
BOOL onlyVisibleWindows = NO;
NSArray *allWindowsComponents = @[@"al", @"lWindo", @"wsIncl", @"udingInt", @"ernalWin", @"dows:o", @"nlyVisi", @"bleWin", @"dows:"];
SEL allWindowsSelector = NSSelectorFromString([allWindowsComponents componentsJoinedByString:@""]);
NSMethodSignature *methodSignature = [[UIWindow class] methodSignatureForSelector:allWindowsSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
invocation.target = [UIWindow class];
invocation.selector = allWindowsSelector;
[invocation setArgument:&includeInternalWindows atIndex:2];
[invocation setArgument:&onlyVisibleWindows atIndex:3];
[invocation invoke];
__unsafe_unretained NSArray *windows = nil;
[invocation getReturnValue:&windows];
return windows;
}
- (UIWindow *)statusWindow
{
NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"];
@@ -427,20 +397,12 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
- (void)moveButtonTapped:(FLEXToolbarItem *)sender
{
if (self.currentMode == FLEXExplorerModeMove) {
self.currentMode = FLEXExplorerModeDefault;
} else {
self.currentMode = FLEXExplorerModeMove;
}
[self toggleMoveTool];
}
- (void)globalsButtonTapped:(FLEXToolbarItem *)sender
{
FLEXGlobalsTableViewController *globalsViewController = [[FLEXGlobalsTableViewController alloc] init];
globalsViewController.delegate = self;
[FLEXGlobalsTableViewController setApplicationWindow:[[UIApplication sharedApplication] keyWindow]];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:globalsViewController];
[self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];
[self toggleMenuTool];
}
- (void)closeButtonTapped:(FLEXToolbarItem *)sender
@@ -603,7 +565,7 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
- (NSArray *)viewsAtPoint:(CGPoint)tapPointInWindow skipHiddenViews:(BOOL)skipHidden
{
NSMutableArray *views = [NSMutableArray array];
for (UIWindow *window in [self allWindows]) {
for (UIWindow *window in [FLEXUtility allWindows]) {
// Don't include the explorer's own window or subviews.
if (window != self.view.window && [window pointInside:tapPointInWindow withEvent:nil]) {
[views addObject:window];
@@ -618,7 +580,7 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
// Select in the window that would handle the touch, but don't just use the result of hitTest:withEvent: so we can still select views with interaction disabled.
// Default to the the application's key window if none of the windows want the touch.
UIWindow *windowForSelection = [[UIApplication sharedApplication] keyWindow];
for (UIWindow *window in [[self allWindows] reverseObjectEnumerator]) {
for (UIWindow *window in [[FLEXUtility allWindows] reverseObjectEnumerator]) {
// Ignore the explorer's own window.
if (window != self.view.window) {
if ([window hitTest:tapPointInWindow withEvent:nil]) {
@@ -830,4 +792,117 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
return self.previousKeyWindow != nil;
}
#pragma mark - Keyboard Shortcut Helpers
- (void)toggleSelectTool
{
if (self.currentMode == FLEXExplorerModeSelect) {
self.currentMode = FLEXExplorerModeDefault;
} else {
self.currentMode = FLEXExplorerModeSelect;
}
}
- (void)toggleMoveTool
{
if (self.currentMode == FLEXExplorerModeMove) {
self.currentMode = FLEXExplorerModeDefault;
} else {
self.currentMode = FLEXExplorerModeMove;
}
}
- (void)toggleViewsTool
{
BOOL viewsModalShown = [[self presentedViewController] isKindOfClass:[UINavigationController class]];
viewsModalShown = viewsModalShown && [[[(UINavigationController *)[self presentedViewController] viewControllers] firstObject] isKindOfClass:[FLEXHierarchyTableViewController class]];
if (viewsModalShown) {
[self resignKeyAndDismissViewControllerAnimated:YES completion:nil];
} else {
void (^presentBlock)() = ^{
NSArray *allViews = [self allViewsInHierarchy];
NSDictionary *depthsForViews = [self hierarchyDepthsForViews:allViews];
FLEXHierarchyTableViewController *hierarchyTVC = [[FLEXHierarchyTableViewController alloc] initWithViews:allViews viewsAtTap:self.viewsAtTapPoint selectedView:self.selectedView depths:depthsForViews];
hierarchyTVC.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:hierarchyTVC];
[self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];
};
if (self.presentedViewController) {
[self resignKeyAndDismissViewControllerAnimated:NO completion:presentBlock];
} else {
presentBlock();
}
}
}
- (void)toggleMenuTool
{
BOOL menuModalShown = [[self presentedViewController] isKindOfClass:[UINavigationController class]];
menuModalShown = menuModalShown && [[[(UINavigationController *)[self presentedViewController] viewControllers] firstObject] isKindOfClass:[FLEXGlobalsTableViewController class]];
if (menuModalShown) {
[self resignKeyAndDismissViewControllerAnimated:YES completion:nil];
} else {
void (^presentBlock)() = ^{
FLEXGlobalsTableViewController *globalsViewController = [[FLEXGlobalsTableViewController alloc] init];
globalsViewController.delegate = self;
[FLEXGlobalsTableViewController setApplicationWindow:[[UIApplication sharedApplication] keyWindow]];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:globalsViewController];
[self makeKeyAndPresentViewController:navigationController animated:YES completion:nil];
};
if (self.presentedViewController) {
[self resignKeyAndDismissViewControllerAnimated:NO completion:presentBlock];
} else {
presentBlock();
}
}
}
- (void)handleDownArrowKeyPressed
{
if (self.currentMode == FLEXExplorerModeMove) {
CGRect frame = self.selectedView.frame;
frame.origin.y += 1.0 / [[UIScreen mainScreen] scale];
self.selectedView.frame = frame;
} else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) {
NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView];
if (selectedViewIndex > 0) {
self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex - 1];
}
}
}
- (void)handleUpArrowKeyPressed
{
if (self.currentMode == FLEXExplorerModeMove) {
CGRect frame = self.selectedView.frame;
frame.origin.y -= 1.0 / [[UIScreen mainScreen] scale];
self.selectedView.frame = frame;
} else if (self.currentMode == FLEXExplorerModeSelect && [self.viewsAtTapPoint count] > 0) {
NSInteger selectedViewIndex = [self.viewsAtTapPoint indexOfObject:self.selectedView];
if (selectedViewIndex < [self.viewsAtTapPoint count] - 1) {
self.selectedView = [self.viewsAtTapPoint objectAtIndex:selectedViewIndex + 1];
}
}
}
- (void)handleRightArrowKeyPressed
{
if (self.currentMode == FLEXExplorerModeMove) {
CGRect frame = self.selectedView.frame;
frame.origin.x += 1.0 / [[UIScreen mainScreen] scale];
self.selectedView.frame = frame;
}
}
- (void)handleLeftArrowKeyPressed
{
if (self.currentMode == FLEXExplorerModeMove) {
CGRect frame = self.selectedView.frame;
frame.origin.x -= 1.0 / [[UIScreen mainScreen] scale];
self.selectedView.frame = frame;
}
}
@end
-165
View File
@@ -1,165 +0,0 @@
//
// FLEXManager.m
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2014 Flipboard. All rights reserved.
//
#import "FLEXManager.h"
#import "FLEXExplorerViewController.h"
#import "FLEXWindow.h"
#import "FLEXGlobalsTableViewControllerEntry.h"
#import "FLEXObjectExplorerFactory.h"
#import "FLEXObjectExplorerViewController.h"
#import "FLEXNetworkObserver.h"
#import "FLEXNetworkRecorder.h"
@interface FLEXManager () <FLEXWindowEventDelegate, FLEXExplorerViewControllerDelegate>
@property (nonatomic, strong) FLEXWindow *explorerWindow;
@property (nonatomic, strong) FLEXExplorerViewController *explorerViewController;
@property (nonatomic, readonly, strong) NSMutableArray *userGlobalEntries;
@end
@implementation FLEXManager
+ (instancetype)sharedManager
{
static FLEXManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[[self class] alloc] init];
});
return sharedManager;
}
- (instancetype)init
{
self = [super init];
if (self) {
_userGlobalEntries = [[NSMutableArray alloc] init];
}
return self;
}
- (FLEXWindow *)explorerWindow
{
NSAssert([NSThread isMainThread], @"You must use %@ from the main thread only.", NSStringFromClass([self class]));
if (!_explorerWindow) {
_explorerWindow = [[FLEXWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_explorerWindow.eventDelegate = self;
_explorerWindow.rootViewController = self.explorerViewController;
}
return _explorerWindow;
}
- (FLEXExplorerViewController *)explorerViewController
{
if (!_explorerViewController) {
_explorerViewController = [[FLEXExplorerViewController alloc] init];
_explorerViewController.delegate = self;
}
return _explorerViewController;
}
- (void)showExplorer
{
self.explorerWindow.hidden = NO;
}
- (void)hideExplorer
{
self.explorerWindow.hidden = YES;
}
- (BOOL)isHidden
{
return self.explorerWindow.isHidden;
}
- (BOOL)isNetworkDebuggingEnabled
{
return [FLEXNetworkObserver isEnabled];
}
- (void)setNetworkDebuggingEnabled:(BOOL)networkDebuggingEnabled
{
[FLEXNetworkObserver setEnabled:networkDebuggingEnabled];
}
- (NSUInteger)networkResponseCacheByteLimit
{
return [[FLEXNetworkRecorder defaultRecorder] responseCacheByteLimit];
}
- (void)setNetworkResponseCacheByteLimit:(NSUInteger)networkResponseCacheByteLimit
{
[[FLEXNetworkRecorder defaultRecorder] setResponseCacheByteLimit:networkResponseCacheByteLimit];
}
#pragma mark - FLEXWindowEventDelegate
- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow
{
// Ask the explorer view controller
return [self.explorerViewController shouldReceiveTouchAtWindowPoint:pointInWindow];
}
- (BOOL)canBecomeKeyWindow
{
// Only when the explorer view controller wants it because it needs to accept key input & affect the status bar.
return [self.explorerViewController wantsWindowToBecomeKey];
}
#pragma mark - FLEXExplorerViewControllerDelegate
- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController
{
[self hideExplorer];
}
#pragma mark - Extensions
- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock
{
NSParameterAssert(entryName);
NSParameterAssert(objectFutureBlock);
NSAssert([NSThread isMainThread], @"This method must be called from the main thread.");
entryName = entryName.copy;
FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{
return entryName;
} viewControllerFuture:^UIViewController *{
return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()];
}];
[self.userGlobalEntries addObject:entry];
}
- (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock
{
NSParameterAssert(entryName);
NSParameterAssert(viewControllerFutureBlock);
NSAssert([NSThread isMainThread], @"This method must be called from the main thread.");
entryName = entryName.copy;
FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{
return entryName;
} viewControllerFuture:^UIViewController *{
UIViewController *viewController = viewControllerFutureBlock();
NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName);
return viewController;
}];
[self.userGlobalEntries addObject:entry];
}
@end
-8
View File
@@ -6,12 +6,4 @@
// Copyright (c) 2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for FLEX.
FOUNDATION_EXPORT double FLEXVersionNumber;
//! Project version string for FLEX.
FOUNDATION_EXPORT const unsigned char FLEXVersionString[];
#import <FLEX/FLEXManager.h>
@@ -17,16 +17,36 @@
- (void)showExplorer;
- (void)hideExplorer;
- (void)toggleExplorer;
#pragma mark - Network Debugging
/// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods
/// on classes that conform to the protocols. This allows you to view network activity history from the main FLEX menu.
/// Full responses are kept temporarily in a size limited cache and may be pruged under memory pressure.
/// Full responses are kept temporarily in a size-limited cache and may be pruned under memory pressure.
@property (nonatomic, assign, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled;
/// Defaults to 50 MB if never set. Values set here are presisted across launches of the app.
/// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.
/// The response cache uses an NSCache, so it may purge prior to hitting the limit when the app is under memory pressure.
@property (nonatomic, assign) NSUInteger networkResponseCacheByteLimit;
#pragma mark - Keyboard Shortcuts
/// Simulator keyboard shortcuts are enabled by default.
/// The shortcuts will not fire when there is an active text field, text view, or other responder accepting key input.
/// You can disable keyboard shortcuts if you have existing keyboard shortcuts that conflict with FLEX, or if you like doing things the hard way ;)
/// Keyboard shortcuts are always disabled (and support is compiled out) in non-simulator builds
@property (nonatomic, assign) BOOL simulatorShortcutsEnabled;
/// Adds an action to run when the specified key & modifier combination is pressed
/// @param key A single character string matching a key on the keyboard
/// @param modifiers Modifier keys such as shift, command, or alt/option
/// @param action The block to run on the main thread when the key & modifier combination is recognized.
/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key.
/// @note The action block will be retained for the duration of the application. You may want to use weak references.
/// @note FLEX registers several default keyboard shortcuts. Use the '?' key to see a list of shortcuts.
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description;
#pragma mark - Extensions
/// Adds an entry at the bottom of the list of Global State items. Call this method before this view controller is displayed.
@@ -0,0 +1,26 @@
//
// PTDatabaseManager.h
// Derived from:
//
// FMDatabase.h
// FMDB( https://github.com/ccgus/fmdb )
//
// Created by Peng Tao on 15/11/23.
//
// Licensed to Flying Meat Inc. under one or more contributor license agreements.
// See the LICENSE file distributed with this work for the terms under
// which Flying Meat Inc. licenses this file to you.
#import <Foundation/Foundation.h>
@protocol FLEXDatabaseManager <NSObject>
@required
- (instancetype)initWithPath:(NSString*)path;
- (BOOL)open;
- (NSArray *)queryAllTables;
- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName;
- (NSArray *)queryAllDataWithTableName:(NSString *)tableName;
@end
@@ -0,0 +1,48 @@
//
// PTMultiColumnTableView.h
// PTMultiColumnTableViewDemo
//
// Created by Peng Tao on 15/11/16.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "FLEXTableColumnHeader.h"
@class FLEXMultiColumnTableView;
@protocol FLEXMultiColumnTableViewDelegate <NSObject>
@required
- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapLabelWithText:(NSString *)text;
- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderWithText:(NSString *)text sortType:(FLEXTableColumnHeaderSortType)sortType;
@end
@protocol FLEXMultiColumnTableViewDataSource <NSObject>
@required
- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView;
- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView;
- (NSString *)columnNameInColumn:(NSInteger)column;
- (NSString *)rowNameInRow:(NSInteger)row;
- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row;
- (NSArray *)contentAtRow:(NSInteger)row;
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView widthForContentCellInColumn:(NSInteger)column;
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView heightForContentCellInRow:(NSInteger)row;
- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView;
- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView;
@end
@interface FLEXMultiColumnTableView : UIView
@property (nonatomic, weak) id<FLEXMultiColumnTableViewDataSource>dataSource;
@property (nonatomic, weak) id<FLEXMultiColumnTableViewDelegate>delegate;
- (void)reloadData;
@end
@@ -0,0 +1,341 @@
//
// PTMultiColumnTableView.m
// PTMultiColumnTableViewDemo
//
// Created by Peng Tao on 15/11/16.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import "FLEXMultiColumnTableView.h"
#import "FLEXTableContentCell.h"
#import "FLEXTableLeftCell.h"
@interface FLEXMultiColumnTableView ()
<UITableViewDataSource, UITableViewDelegate,UIScrollViewDelegate, FLEXTableContentCellDelegate>
@property (nonatomic, strong) UIScrollView *contentScrollView;
@property (nonatomic, strong) UIScrollView *headerScrollView;
@property (nonatomic, strong) UITableView *leftTableView;
@property (nonatomic, strong) UITableView *contentTableView;
@property (nonatomic, strong) UIView *leftHeader;
@property (nonatomic, strong) NSDictionary *sortStatusDict;
@property (nonatomic, strong) NSArray *rowData;
@end
static const CGFloat kColumnMargin = 1;
@implementation FLEXMultiColumnTableView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self loadUI];
}
return self;
}
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
[self reloadData];
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
CGFloat topheaderHeight = [self topHeaderHeight];
CGFloat leftHeaderWidth = [self leftHeaderWidth];
CGFloat contentWidth = 0.0;
NSInteger rowsCount = [self numberOfColumns];
for (int i = 0; i < rowsCount; i++) {
contentWidth += [self contentWidthForColumn:i];
}
self.leftTableView.frame = CGRectMake(0, topheaderHeight, leftHeaderWidth, height - topheaderHeight);
self.headerScrollView.frame = CGRectMake(leftHeaderWidth, 0, width - leftHeaderWidth, topheaderHeight);
self.headerScrollView.contentSize = CGSizeMake( self.contentTableView.frame.size.width, self.headerScrollView.frame.size.height);
self.contentTableView.frame = CGRectMake(0, 0, contentWidth + [self numberOfColumns] * [self columnMargin] , height - topheaderHeight);
self.contentScrollView.frame = CGRectMake(leftHeaderWidth, topheaderHeight, width - leftHeaderWidth, height - topheaderHeight);
self.contentScrollView.contentSize = self.contentTableView.frame.size;
self.leftHeader.frame = CGRectMake(0, 0, [self leftHeaderWidth], [self topHeaderHeight]);
}
- (void)loadUI
{
[self loadHeaderScrollView];
[self loadContentScrollView];
[self loadLeftView];
}
- (void)reloadData
{
[self loadLeftViewData];
[self loadContentData];
[self loadHeaderData];
}
#pragma mark - UI
- (void)loadHeaderScrollView
{
UIScrollView *headerScrollView = [[UIScrollView alloc] init];
headerScrollView.delegate = self;
self.headerScrollView = headerScrollView;
self.headerScrollView.backgroundColor = [UIColor colorWithWhite:0.803 alpha:0.850];
[self addSubview:headerScrollView];
}
- (void)loadContentScrollView
{
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.bounces = NO;
scrollView.delegate = self;
UITableView *tableView = [[UITableView alloc] init];
tableView.delegate = self;
tableView.dataSource = self;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self addSubview:scrollView];
[scrollView addSubview:tableView];
self.contentScrollView = scrollView;
self.contentTableView = tableView;
}
- (void)loadLeftView
{
UITableView *leftTableView = [[UITableView alloc] init];
leftTableView.delegate = self;
leftTableView.dataSource = self;
leftTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.leftTableView = leftTableView;
[self addSubview:leftTableView];
UIView *leftHeader = [[UIView alloc] init];
leftHeader.backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.668];
self.leftHeader = leftHeader;
[self addSubview:leftHeader];
}
#pragma mark - Data
- (void)loadHeaderData
{
NSArray *subviews = self.headerScrollView.subviews;
for (UIView *subview in subviews) {
[subview removeFromSuperview];
}
CGFloat x = 0.0;
CGFloat w = 0.0;
for (int i = 0; i < [self numberOfColumns] ; i++) {
w = [self contentWidthForColumn:i] + [self columnMargin];
FLEXTableColumnHeader *cell = [[FLEXTableColumnHeader alloc] initWithFrame:CGRectMake(x, 0, w, [self topHeaderHeight] - 1)];
cell.label.text = [self columnTitleForColumn:i];
[self.headerScrollView addSubview:cell];
FLEXTableColumnHeaderSortType type = [self.sortStatusDict[[self columnTitleForColumn:i]] integerValue];
[cell changeSortStatusWithType:type];
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(contentHeaderTap:)];
[cell addGestureRecognizer:gesture];
cell.userInteractionEnabled = YES;
x = x + w;
}
}
- (void)contentHeaderTap:(UIGestureRecognizer *)gesture
{
FLEXTableColumnHeader *header = (FLEXTableColumnHeader *)gesture.view;
NSString *string = header.label.text;
FLEXTableColumnHeaderSortType currentType = [self.sortStatusDict[string] integerValue];
FLEXTableColumnHeaderSortType newType ;
switch (currentType) {
case FLEXTableColumnHeaderSortTypeNone:
newType = FLEXTableColumnHeaderSortTypeAsc;
break;
case FLEXTableColumnHeaderSortTypeAsc:
newType = FLEXTableColumnHeaderSortTypeDesc;
break;
case FLEXTableColumnHeaderSortTypeDesc:
newType = FLEXTableColumnHeaderSortTypeAsc;
break;
}
self.sortStatusDict = @{header.label.text : @(newType)};
[header changeSortStatusWithType:newType];
[self.delegate multiColumnTableView:self didTapHeaderWithText:string sortType:newType];
}
- (void)loadContentData
{
[self.contentTableView reloadData];
}
- (void)loadLeftViewData
{
[self.leftTableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIColor *backgroundColor = [UIColor whiteColor];
if (indexPath.row % 2 != 0) {
backgroundColor = [UIColor colorWithWhite:0.950 alpha:0.750];
}
if (tableView != self.leftTableView) {
self.rowData = [self.dataSource contentAtRow:indexPath.row];
FLEXTableContentCell *cell = [FLEXTableContentCell cellWithTableView:tableView
columnNumber:[self numberOfColumns]];
cell.contentView.backgroundColor = backgroundColor;
cell.delegate = self;
for (int i = 0 ; i < cell.labels.count; i++) {
UILabel *label = cell.labels[i];
label.textColor = [UIColor blackColor];
NSString *content = [NSString stringWithFormat:@"%@",self.rowData[i]];
if ([content isEqualToString:@"<null>"]) {
label.textColor = [UIColor lightGrayColor];
content = @"NULL";
}
label.text = content;
label.backgroundColor = backgroundColor;
}
return cell;
}
else {
FLEXTableLeftCell *cell = [FLEXTableLeftCell cellWithTableView:tableView];
cell.contentView.backgroundColor = backgroundColor;
cell.titlelabel.text = [self rowTitleForRow:indexPath.row];
return cell;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dataSource numberOfRowsInTableView:self];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self.dataSource multiColumnTableView:self heightForContentCellInRow:indexPath.row];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == self.contentScrollView) {
self.headerScrollView.contentOffset = scrollView.contentOffset;
}
else if (scrollView == self.headerScrollView) {
self.contentScrollView.contentOffset = scrollView.contentOffset;
}
else if (scrollView == self.leftTableView) {
self.contentTableView.contentOffset = scrollView.contentOffset;
}
else if (scrollView == self.contentTableView) {
self.leftTableView.contentOffset = scrollView.contentOffset;
}
}
#pragma mark -
#pragma mark UITableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.leftTableView) {
[self.contentTableView selectRowAtIndexPath:indexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
}
else if (tableView == self.contentTableView) {
[self.leftTableView selectRowAtIndexPath:indexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
}
}
#pragma mark -
#pragma mark DataSource Accessor
- (NSInteger)numberOfrows
{
return [self.dataSource numberOfRowsInTableView:self];
}
- (NSInteger)numberOfColumns
{
return [self.dataSource numberOfColumnsInTableView:self];
}
- (NSString *)columnTitleForColumn:(NSInteger)column
{
return [self.dataSource columnNameInColumn:column];
}
- (NSString *)rowTitleForRow:(NSInteger)row
{
return [self.dataSource rowNameInRow:row];
}
- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row;
{
return [self.dataSource contentAtColumn:column row:row];
}
- (CGFloat)contentWidthForColumn:(NSInteger)column
{
return [self.dataSource multiColumnTableView:self widthForContentCellInColumn:column];
}
- (CGFloat)contentHeightForRow:(NSInteger)row
{
return [self.dataSource multiColumnTableView:self heightForContentCellInRow:row];
}
- (CGFloat)topHeaderHeight
{
return [self.dataSource heightForTopHeaderInTableView:self];
}
- (CGFloat)leftHeaderWidth
{
return [self.dataSource widthForLeftHeaderInTableView:self];
}
- (CGFloat)columnMargin
{
return kColumnMargin;
}
- (void)tableContentCell:(FLEXTableContentCell *)tableView labelDidTapWithText:(NSString *)text
{
[self.delegate multiColumnTableView:self didTapLabelWithText:text];
}
@end
@@ -0,0 +1,14 @@
//
// FLEXRealmDatabaseManager.h
// FLEX
//
// Created by Tim Oliver on 28/01/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "FLEXDatabaseManager.h"
@interface FLEXRealmDatabaseManager : NSObject <FLEXDatabaseManager>
@end
@@ -0,0 +1,114 @@
//
// FLEXRealmDatabaseManager.m
// FLEX
//
// Created by Tim Oliver on 28/01/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#import "FLEXRealmDatabaseManager.h"
#if __has_include(<Realm/Realm.h>)
#import <Realm/Realm.h>
#import <Realm/RLMRealm_Dynamic.h>
#else
#import "FLEXRealmDefines.h"
#endif
@interface FLEXRealmDatabaseManager ()
@property (nonatomic, copy) NSString *path;
@property (nonatomic, strong) id realm;
@end
//#endif
@implementation FLEXRealmDatabaseManager
- (instancetype)initWithPath:(NSString*)aPath
{
Class realmClass = NSClassFromString(@"RLMRealm");
if (realmClass == nil) {
return nil;
}
self = [super init];
if (self) {
_path = aPath;
}
return self;
}
- (BOOL)open
{
Class realmClass = NSClassFromString(@"RLMRealm");
Class configurationClass = NSClassFromString(@"RLMRealmConfiguration");
if (realmClass == nil || configurationClass == nil) {
return NO;
}
NSError *error = nil;
id configuration = [[configurationClass alloc] init];
[(RLMRealmConfiguration *)configuration setFileURL:[NSURL fileURLWithPath:self.path]];
self.realm = [realmClass realmWithConfiguration:configuration error:&error];
return (error == nil);
}
- (NSArray *)queryAllTables
{
NSMutableArray *allTables = [NSMutableArray array];
RLMSchema *schema = [self.realm schema];
for (RLMObjectSchema *objectSchema in schema.objectSchema) {
if (objectSchema.className == nil) {
continue;
}
NSDictionary *dictionary = @{@"name":objectSchema.className};
[allTables addObject:dictionary];
}
return allTables;
}
- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName
{
RLMObjectSchema *objectSchema = [[self.realm schema] schemaForClassName:tableName];
if (objectSchema == nil) {
return nil;
}
NSMutableArray *columnNames = [NSMutableArray array];
for (RLMProperty *property in objectSchema.properties) {
[columnNames addObject:property.name];
}
return columnNames;
}
- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
{
RLMObjectSchema *objectSchema = [[self.realm schema] schemaForClassName:tableName];
RLMResults *results = [self.realm allObjects:tableName];
if (results.count == 0 || objectSchema == nil) {
return nil;
}
NSMutableArray *allDataEntries = [NSMutableArray array];
for (RLMObject *result in results) {
NSMutableDictionary *entry = [NSMutableDictionary dictionary];
for (RLMProperty *property in objectSchema.properties) {
id value = [result valueForKey:property.name];
entry[property.name] = (value) ? (value) : [NSNull null];
}
[allDataEntries addObject:entry];
}
return allDataEntries;
}
@end
@@ -0,0 +1,46 @@
//
// Realm.h
// FLEX
//
// Created by Tim Oliver on 16/02/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#if __has_include(<Realm/Realm.h>)
#else
@class RLMObject, RLMResults, RLMRealm, RLMRealmConfiguration, RLMSchema, RLMObjectSchema, RLMProperty;
@interface RLMRealmConfiguration : NSObject
@property (nonatomic, copy) NSURL *fileURL;
@end
@interface RLMRealm : NSObject
@property (nonatomic, readonly) RLMSchema *schema;
+ (RLMRealm *)realmWithConfiguration:(RLMRealmConfiguration *)configuration error:(NSError **)error;
- (RLMResults *)allObjects:(NSString *)className;
@end
@interface RLMSchema : NSObject
@property (nonatomic, readonly) NSArray *objectSchema;
- (RLMObjectSchema *)schemaForClassName:(NSString *)className;
@end
@interface RLMObjectSchema : NSObject
@property (nonatomic, readonly) NSString *className;
@property (nonatomic, readonly) NSArray *properties;
@end
@interface RLMProperty : NSString
@property (nonatomic, readonly) NSString *name;
@end
@interface RLMResults : NSObject <NSFastEnumeration>
@property (nonatomic, readonly) NSInteger count;
@end
@interface RLMObject : NSObject
@end
#endif
@@ -0,0 +1,19 @@
//
// PTDatabaseManager.h
// Derived from:
//
// FMDatabase.h
// FMDB( https://github.com/ccgus/fmdb )
//
// Created by Peng Tao on 15/11/23.
//
// Licensed to Flying Meat Inc. under one or more contributor license agreements.
// See the LICENSE file distributed with this work for the terms under
// which Flying Meat Inc. licenses this file to you.
#import <Foundation/Foundation.h>
#import "FLEXDatabaseManager.h"
@interface FLEXSQLiteDatabaseManager : NSObject <FLEXDatabaseManager>
@end
@@ -0,0 +1,190 @@
//
// PTDatabaseManager.m
// PTDatabaseReader
//
// Created by Peng Tao on 15/11/23.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import "FLEXSQLiteDatabaseManager.h"
#import <sqlite3.h>
static NSString *const QUERY_TABLENAMES_SQL = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
@implementation FLEXSQLiteDatabaseManager
{
sqlite3* _db;
NSString* _databasePath;
}
- (instancetype)initWithPath:(NSString*)aPath
{
self = [super init];
if (self) {
_databasePath = [aPath copy];
}
return self;
}
- (BOOL)open {
if (_db) {
return YES;
}
int err = sqlite3_open([_databasePath UTF8String], &_db);
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
}
return YES;
}
- (BOOL)close {
if (!_db) {
return YES;
}
int rc;
BOOL retry;
BOOL triedFinalizingOpenStatements = NO;
do {
retry = NO;
rc = sqlite3_close(_db);
if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
if (!triedFinalizingOpenStatements) {
triedFinalizingOpenStatements = YES;
sqlite3_stmt *pStmt;
while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) {
NSLog(@"Closing leaked statement");
sqlite3_finalize(pStmt);
retry = YES;
}
}
}
else if (SQLITE_OK != rc) {
NSLog(@"error closing!: %d", rc);
}
}
while (retry);
_db = nil;
return YES;
}
- (NSArray *)queryAllTables
{
return [self executeQuery:QUERY_TABLENAMES_SQL];
}
- (NSArray *)queryAllColumnsWithTableName:(NSString *)tableName
{
NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')",tableName];
NSArray *resultArray = [self executeQuery:sql];
NSMutableArray *array = [NSMutableArray array];
for (NSDictionary *dict in resultArray) {
[array addObject:dict[@"name"]];
}
return array;
}
- (NSArray *)queryAllDataWithTableName:(NSString *)tableName
{
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM %@",tableName];
return [self executeQuery:sql];
}
#pragma mark -
#pragma mark - Private
- (NSArray *)executeQuery:(NSString *)sql
{
[self open];
NSMutableArray *resultArray = [NSMutableArray array];
sqlite3_stmt *pstmt;
if (sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pstmt, 0) == SQLITE_OK) {
while (sqlite3_step(pstmt) == SQLITE_ROW) {
NSUInteger num_cols = (NSUInteger)sqlite3_data_count(pstmt);
if (num_cols > 0) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
int columnCount = sqlite3_column_count(pstmt);
int columnIdx = 0;
for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(pstmt, columnIdx)];
id objectValue = [self objectForColumnIndex:columnIdx stmt:pstmt];
[dict setObject:objectValue forKey:columnName];
}
[resultArray addObject:dict];
}
}
}
[self close];
return resultArray;
}
- (id)objectForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt*)stmt {
int columnType = sqlite3_column_type(stmt, columnIdx);
id returnValue = nil;
if (columnType == SQLITE_INTEGER) {
returnValue = [NSNumber numberWithLongLong:sqlite3_column_int64(stmt, columnIdx)];
}
else if (columnType == SQLITE_FLOAT) {
returnValue = [NSNumber numberWithDouble:sqlite3_column_double(stmt, columnIdx)];
}
else if (columnType == SQLITE_BLOB) {
returnValue = [self dataForColumnIndex:columnIdx stmt:stmt];
}
else {
//default to a string for everything else
returnValue = [self stringForColumnIndex:columnIdx stmt:stmt];
}
if (returnValue == nil) {
returnValue = [NSNull null];
}
return returnValue;
}
- (NSString *)stringForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt {
if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
const char *c = (const char *)sqlite3_column_text(stmt, columnIdx);
if (!c) {
// null row.
return nil;
}
return [NSString stringWithUTF8String:c];
}
- (NSData *)dataForColumnIndex:(int)columnIdx stmt:(sqlite3_stmt *)stmt{
if (sqlite3_column_type(stmt, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
const char *dataBuffer = sqlite3_column_blob(stmt, columnIdx);
int dataSize = sqlite3_column_bytes(stmt, columnIdx);
if (dataBuffer == NULL) {
return nil;
}
return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];
}
@end
@@ -0,0 +1,24 @@
//
// FLEXTableContentHeaderCell.h
// UICatalog
//
// Created by Peng Tao on 15/11/26.
// Copyright © 2015年 f. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, FLEXTableColumnHeaderSortType) {
FLEXTableColumnHeaderSortTypeNone = 0,
FLEXTableColumnHeaderSortTypeAsc,
FLEXTableColumnHeaderSortTypeDesc,
};
@interface FLEXTableColumnHeader : UIView
@property (nonatomic, strong) UILabel *label;
- (void)changeSortStatusWithType:(FLEXTableColumnHeaderSortType)type;
@end
@@ -0,0 +1,60 @@
//
// FLEXTableContentHeaderCell.m
// UICatalog
//
// Created by Peng Tao on 15/11/26.
// Copyright © 2015年 f. All rights reserved.
//
#import "FLEXTableColumnHeader.h"
@implementation FLEXTableColumnHeader
{
UILabel *_arrowLabel;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, frame.size.width - 25, frame.size.height)];
label.font = [UIFont systemFontOfSize:13.0];
[self addSubview:label];
self.label = label;
_arrowLabel = [[UILabel alloc] initWithFrame:CGRectMake(frame.size.width - 20, 0, 20, frame.size.height)];
_arrowLabel.font = [UIFont systemFontOfSize:13.0];
[self addSubview:_arrowLabel];
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width - 1, 2, 1, frame.size.height - 4)];
line.backgroundColor = [UIColor colorWithWhite:0.803 alpha:0.850];
[self addSubview:line];
}
return self;
}
- (void)changeSortStatusWithType:(FLEXTableColumnHeaderSortType)type
{
switch (type) {
case FLEXTableColumnHeaderSortTypeNone:
_arrowLabel.text = @"";
break;
case FLEXTableColumnHeaderSortTypeAsc:
_arrowLabel.text = @"⬆️";
break;
case FLEXTableColumnHeaderSortTypeDesc:
_arrowLabel.text = @"⬇️";
break;
}
}
@end
@@ -0,0 +1,27 @@
//
// FLEXTableContentCell.h
// UICatalog
//
// Created by Peng Tao on 15/11/24.
// Copyright © 2015年 f. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FLEXTableContentCell;
@protocol FLEXTableContentCellDelegate <NSObject>
@optional
- (void)tableContentCell:(FLEXTableContentCell *)tableView labelDidTapWithText:(NSString *)text;
@end
@interface FLEXTableContentCell : UITableViewCell
@property (nonatomic, strong)NSArray *labels;
@property (nonatomic, weak) id<FLEXTableContentCellDelegate>delegate;
+ (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteger)number;
@end
@@ -0,0 +1,66 @@
//
// FLEXTableContentCell.m
// UICatalog
//
// Created by Peng Tao on 15/11/24.
// Copyright © 2015年 f. All rights reserved.
//
#import "FLEXTableContentCell.h"
#import "FLEXMultiColumnTableView.h"
@interface FLEXTableContentCell ()
@end
@implementation FLEXTableContentCell
+ (instancetype)cellWithTableView:(UITableView *)tableView columnNumber:(NSInteger)number;
{
static NSString *identifier = @"FLEXTableContentCell";
FLEXTableContentCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[FLEXTableContentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
NSMutableArray *labels = [NSMutableArray array];
for (int i = 0; i < number ; i++) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.backgroundColor = [UIColor whiteColor];
label.font = [UIFont systemFontOfSize:13.0];
label.textAlignment = NSTextAlignmentLeft;
label.backgroundColor = [UIColor greenColor];
[labels addObject:label];
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:cell
action:@selector(labelDidTap:)];
[label addGestureRecognizer:gesture];
label.userInteractionEnabled = YES;
[cell.contentView addSubview:label];
cell.contentView.backgroundColor = [UIColor whiteColor];
}
cell.labels = labels;
}
return cell;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat labelWidth = self.contentView.frame.size.width / self.labels.count;
CGFloat labelHeight = self.contentView.frame.size.height;
for (int i = 0; i < self.labels.count; i++) {
UILabel *label = self.labels[i];
label.frame = CGRectMake(labelWidth * i + 5, 0, (labelWidth - 10), labelHeight);
}
}
- (void)labelDidTap:(UIGestureRecognizer *)gesture
{
UILabel *label = (UILabel *)gesture.view;
if ([self.delegate respondsToSelector:@selector(tableContentCell:labelDidTapWithText:)]) {
[self.delegate tableContentCell:self labelDidTapWithText:label.text];
}
}
@end
@@ -0,0 +1,16 @@
//
// PTTableContentViewController.h
// PTDatabaseReader
//
// Created by Peng Tao on 15/11/23.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FLEXTableContentViewController : UIViewController
@property (nonatomic, strong) NSArray *columnsArray;
@property (nonatomic, strong) NSArray *contentsArray;
@end
@@ -0,0 +1,184 @@
//
// PTTableContentViewController.m
// PTDatabaseReader
//
// Created by Peng Tao on 15/11/23.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import "FLEXTableContentViewController.h"
#import "FLEXMultiColumnTableView.h"
#import "FLEXWebViewController.h"
@interface FLEXTableContentViewController ()<FLEXMultiColumnTableViewDataSource, FLEXMultiColumnTableViewDelegate>
@property (nonatomic, strong)FLEXMultiColumnTableView *multiColumView;
@end
@implementation FLEXTableContentViewController
- (instancetype)init
{
self = [super init];
if (self) {
CGRect rectStatus = [UIApplication sharedApplication].statusBarFrame;
CGFloat y = 64;
if (rectStatus.size.height == 0) {
y = 32;
}
_multiColumView = [[FLEXMultiColumnTableView alloc] initWithFrame:
CGRectMake(0, y, self.view.frame.size.width, self.view.frame.size.height - y)];
_multiColumView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_multiColumView.backgroundColor = [UIColor whiteColor];
_multiColumView.dataSource = self;
_multiColumView.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
[self.view addSubview:_multiColumView];
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.multiColumView reloadData];
}
#pragma mark -
#pragma mark MultiColumnTableView DataSource
- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView
{
return self.columnsArray.count;
}
- (NSInteger)numberOfRowsInTableView:(FLEXMultiColumnTableView *)tableView
{
return self.contentsArray.count;
}
- (NSString *)columnNameInColumn:(NSInteger)column
{
return self.columnsArray[column];
}
- (NSString *)rowNameInRow:(NSInteger)row
{
return [NSString stringWithFormat:@"%ld",(long)row];
}
- (NSString *)contentAtColumn:(NSInteger)column row:(NSInteger)row
{
if (self.contentsArray.count > row) {
NSDictionary *dic = self.contentsArray[row];
if (self.contentsArray.count > column) {
return [NSString stringWithFormat:@"%@",[dic objectForKey:self.columnsArray[column]]];
}
}
return @"";
}
- (NSArray *)contentAtRow:(NSInteger)row
{
NSMutableArray *result = [NSMutableArray array];
if (self.contentsArray.count > row) {
NSDictionary *dic = self.contentsArray[row];
for (int i = 0; i < self.columnsArray.count; i ++) {
[result addObject:dic[self.columnsArray[i]]];
}
return result;
}
return nil;
}
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView
heightForContentCellInRow:(NSInteger)row
{
return 40;
}
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView
widthForContentCellInColumn:(NSInteger)column
{
return 120;
}
- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView
{
return 40;
}
- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView
{
NSString *str = [NSString stringWithFormat:@"%lu",(unsigned long)self.contentsArray.count];
NSDictionary *attrs = @{@"NSFontAttributeName":[UIFont systemFontOfSize:17.0]};
CGSize size = [str boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 14)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attrs context:nil].size;
return size.width + 20;
}
#pragma mark -
#pragma mark MultiColumnTableView Delegate
- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapLabelWithText:(NSString *)text
{
FLEXWebViewController * detailViewController = [[FLEXWebViewController alloc] initWithText:text];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (void)multiColumnTableView:(FLEXMultiColumnTableView *)tableView didTapHeaderWithText:(NSString *)text sortType:(FLEXTableColumnHeaderSortType)sortType
{
NSArray *sortContentData = [self.contentsArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([obj1 objectForKey:text] == [NSNull null]) {
return NSOrderedAscending;
}
if ([obj2 objectForKey:text] == [NSNull null]) {
return NSOrderedDescending;
}
NSComparisonResult result = [[obj1 objectForKey:text] compare:[obj2 objectForKey:text]];
return result;
}];
if (sortType == FLEXTableColumnHeaderSortTypeDesc) {
NSEnumerator *contentReverseEvumerator = [sortContentData reverseObjectEnumerator];
sortContentData = [NSArray arrayWithArray:[contentReverseEvumerator allObjects]];
}
self.contentsArray = sortContentData;
[self.multiColumView reloadData];
}
#pragma mark -
#pragma mark About Transition
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
[super willTransitionToTraitCollection:newCollection
withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
_multiColumView.frame = CGRectMake(0, 32, self.view.frame.size.width, self.view.frame.size.height - 32);
}
else {
_multiColumView.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
}
[self.view setNeedsLayout];
} completion:nil];
}
@end
@@ -0,0 +1,17 @@
//
// FLEXTableLeftCell.h
// UICatalog
//
// Created by Peng Tao on 15/11/24.
// Copyright © 2015年 f. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FLEXTableLeftCell : UITableViewCell
@property (nonatomic, strong) UILabel *titlelabel;
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end
@@ -0,0 +1,35 @@
//
// FLEXTableLeftCell.m
// UICatalog
//
// Created by Peng Tao on 15/11/24.
// Copyright © 2015年 f. All rights reserved.
//
#import "FLEXTableLeftCell.h"
@implementation FLEXTableLeftCell
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *identifier = @"FLEXTableLeftCell";
FLEXTableLeftCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[FLEXTableLeftCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
textLabel.textAlignment = NSTextAlignmentCenter;
textLabel.font = [UIFont systemFontOfSize:13.0];
textLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:textLabel];
cell.titlelabel = textLabel;
}
return cell;
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.titlelabel.frame = self.contentView.frame;
}
@end
@@ -0,0 +1,16 @@
//
// PTTableListViewController.h
// PTDatabaseReader
//
// Created by Peng Tao on 15/11/23.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FLEXTableListViewController : UITableViewController
+ (BOOL)supportsExtension:(NSString *)extension;
- (instancetype)initWithPath:(NSString *)path;
@end
@@ -0,0 +1,136 @@
//
// PTTableListViewController.m
// PTDatabaseReader
//
// Created by Peng Tao on 15/11/23.
// Copyright © 2015年 Peng Tao. All rights reserved.
//
#import "FLEXTableListViewController.h"
#import "FLEXDatabaseManager.h"
#import "FLEXSQLiteDatabaseManager.h"
#import "FLEXRealmDatabaseManager.h"
#import "FLEXTableContentViewController.h"
@interface FLEXTableListViewController ()
{
id<FLEXDatabaseManager> _dbm;
NSString *_databasePath;
}
@property (nonatomic, strong) NSArray *tables;
+ (NSArray *)supportedSQLiteExtensions;
+ (NSArray *)supportedRealmExtensions;
@end
@implementation FLEXTableListViewController
- (instancetype)initWithPath:(NSString *)path
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
_databasePath = [path copy];
_dbm = [self databaseManagerForFileAtPath:_databasePath];
[_dbm open];
[self getAllTables];
}
return self;
}
- (id<FLEXDatabaseManager>)databaseManagerForFileAtPath:(NSString *)path
{
NSString *pathExtension = path.pathExtension.lowercaseString;
NSArray *sqliteExtensions = [FLEXTableListViewController supportedSQLiteExtensions];
if ([sqliteExtensions indexOfObject:pathExtension] != NSNotFound) {
return [[FLEXSQLiteDatabaseManager alloc] initWithPath:path];
}
NSArray *realmExtensions = [FLEXTableListViewController supportedRealmExtensions];
if (realmExtensions != nil && [realmExtensions indexOfObject:pathExtension] != NSNotFound) {
return [[FLEXRealmDatabaseManager alloc] initWithPath:path];
}
return nil;
}
- (void)getAllTables
{
NSArray *resultArray = [_dbm queryAllTables];
NSMutableArray *array = [NSMutableArray array];
for (NSDictionary *dict in resultArray) {
[array addObject:dict[@"name"]];
}
self.tables = array;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tables.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FLEXTableListViewControllerCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"FLEXTableListViewControllerCell"];
}
cell.textLabel.text = self.tables[indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FLEXTableContentViewController *contentViewController = [[FLEXTableContentViewController alloc] init];
contentViewController.contentsArray = [_dbm queryAllDataWithTableName:self.tables[indexPath.row]];
contentViewController.columnsArray = [_dbm queryAllColumnsWithTableName:self.tables[indexPath.row]];
contentViewController.title = self.tables[indexPath.row];
[self.navigationController pushViewController:contentViewController animated:YES];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%lu tables", (unsigned long)self.tables.count];
}
+ (BOOL)supportsExtension:(NSString *)extension
{
extension = extension.lowercaseString;
NSArray *sqliteExtensions = [FLEXTableListViewController supportedSQLiteExtensions];
if (sqliteExtensions.count > 0 && [sqliteExtensions indexOfObject:extension] != NSNotFound) {
return YES;
}
NSArray *realmExtensions = [FLEXTableListViewController supportedRealmExtensions];
if (realmExtensions.count > 0 && [realmExtensions indexOfObject:extension] != NSNotFound) {
return YES;
}
return NO;
}
+ (NSArray *)supportedSQLiteExtensions
{
return @[@"db", @"sqlite", @"sqlite3"];
}
+ (NSArray *)supportedRealmExtensions
{
if (NSClassFromString(@"RLMRealm") == nil) {
return nil;
}
return @[@"realm"];
}
@end
@@ -0,0 +1,21 @@
FMDB
Copyright (c) 2008-2014 Flying Meat Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -68,7 +68,7 @@
- (void)updateTitle
{
NSString *shortImageName = [[self.binaryImageName componentsSeparatedByString:@"/"] lastObject];
NSString *shortImageName = self.binaryImageName.lastPathComponent;
self.title = [NSString stringWithFormat:@"%@ Classes (%lu)", shortImageName, (unsigned long)[self.filteredClassNames count]];
}
@@ -131,7 +131,7 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *className = [self.filteredClassNames objectAtIndex:indexPath.row];
NSString *className = self.filteredClassNames[indexPath.row];
Class selectedClass = objc_getClass([className UTF8String]);
FLEXObjectExplorerViewController *objectExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:selectedClass];
[self.navigationController pushViewController:objectExplorer animated:YES];
@@ -0,0 +1,13 @@
//
// FLEXCookiesTableViewController.h
// FLEX
//
// Created by Rich Robinson on 19/10/2015.
// Copyright © 2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FLEXCookiesTableViewController : UITableViewController
@end
@@ -0,0 +1,71 @@
//
// FLEXCookiesTableViewController.m
// FLEX
//
// Created by Rich Robinson on 19/10/2015.
// Copyright © 2015 Flipboard. All rights reserved.
//
#import "FLEXCookiesTableViewController.h"
#import "FLEXObjectExplorerFactory.h"
#import "FLEXUtility.h"
@interface FLEXCookiesTableViewController ()
@property (nonatomic, strong) NSArray *cookies;
@end
@implementation FLEXCookiesTableViewController
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
self.title = @"Cookies";
NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
_cookies =[[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies sortedArrayUsingDescriptors:@[nameSortDescriptor]];
}
return self;
}
- (NSHTTPCookie *)cookieForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.cookies[indexPath.row];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.cookies.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
cell.detailTextLabel.textColor = [UIColor grayColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSHTTPCookie *cookie = [self cookieForRowAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:@"%@ (%@)", cookie.name, cookie.value];
cell.detailTextLabel.text = cookie.domain;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSHTTPCookie *cookie = [self cookieForRowAtIndexPath:indexPath];
UIViewController *cookieViewController = (UIViewController *)[FLEXObjectExplorerFactory explorerViewControllerForObject:cookie];
[self.navigationController pushViewController:cookieViewController animated:YES];
}
@end
@@ -10,7 +10,7 @@
#import "FLEXFileBrowserSearchOperation.h"
@interface FLEXFileBrowserTableViewController : UITableViewController <UISearchDisplayDelegate, FLEXFileBrowserSearchOperationDelegate>
@interface FLEXFileBrowserTableViewController : UITableViewController
- (id)initWithPath:(NSString *)path;
@@ -11,22 +11,19 @@
#import "FLEXUtility.h"
#import "FLEXWebViewController.h"
#import "FLEXImagePreviewViewController.h"
#import "FLEXTableListViewController.h"
@interface FLEXFileBrowserTableViewCell : UITableViewCell
@end
@interface FLEXFileBrowserTableViewController () <FLEXFileBrowserFileOperationControllerDelegate>
@interface FLEXFileBrowserTableViewController () <FLEXFileBrowserFileOperationControllerDelegate, FLEXFileBrowserSearchOperationDelegate, UISearchResultsUpdating, UISearchControllerDelegate>
@property (nonatomic, copy) NSString *path;
@property (nonatomic, copy) NSArray *childPaths;
@property (nonatomic, copy) NSString *searchString;
@property (nonatomic, strong) NSArray *searchPaths;
@property (nonatomic, strong) NSNumber *recursiveSize;
@property (nonatomic, strong) NSNumber *searchPathsSize;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@property (nonatomic, strong) UISearchDisplayController *searchController;
#pragma clang diagnostic pop
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic) NSOperationQueue *operationQueue;
@property (nonatomic, strong) UIDocumentInteractionController *documentController;
@property (nonatomic, strong) id<FLEXFileBrowserFileOperationController> fileOperationController;
@@ -48,16 +45,10 @@
self.title = [path lastPathComponent];
self.operationQueue = [NSOperationQueue new];
//add search controller
UISearchBar *searchBar = [UISearchBar new];
[searchBar sizeToFit];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
#pragma clang diagnostic pop
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.tableView.tableHeaderView = self.searchController.searchBar;
//computing path size
@@ -106,22 +97,20 @@
{
self.searchPaths = searchResult;
self.searchPathsSize = @(size);
[self.searchController.searchResultsTableView reloadData];
[self.tableView reloadData];
}
#pragma mark - UISearchDisplayDelegate
#pragma mark - UISearchResultsUpdating
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
self.searchString = searchString;
[self reloadSearchPaths];
return YES;
[self reloadDisplayedPaths];
}
- (void)searchDisplayController:(UISearchDisplayController *)controller willHideSearchResultsTableView:(UITableView *)tableView
#pragma mark - UISearchControllerDelegate
- (void)willDismissSearchController:(UISearchController *)searchController
{
//confirm to clear all operations
[self.operationQueue cancelAllOperations];
[self reloadChildPaths];
[self.tableView reloadData];
@@ -137,25 +126,14 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView) {
return [self.childPaths count];
} else {
return [self.searchPaths count];
}
return self.searchController.isActive ? [self.searchPaths count] : [self.childPaths count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSNumber *currentSize = nil;
NSArray *currentPaths = nil;
if (tableView == self.tableView) {
currentSize = self.recursiveSize;
currentPaths = self.childPaths;
} else {
currentSize = self.searchPathsSize;
currentPaths = self.searchPaths;
}
BOOL isSearchActive = self.searchController.isActive;
NSNumber *currentSize = isSearchActive ? self.searchPathsSize : self.recursiveSize;
NSArray *currentPaths = isSearchActive ? self.searchPaths : self.childPaths;
NSString *sizeString = nil;
if (!currentSize) {
@@ -169,14 +147,7 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *fullPath = nil;
if (tableView == self.tableView) {
NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
fullPath = [self.path stringByAppendingPathComponent:subpath];
} else {
fullPath = [self.searchPaths objectAtIndex:indexPath.row];
}
NSString *fullPath = [self filePathAtIndexPath:indexPath];
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:NULL];
BOOL isDirectory = [[attributes fileType] isEqual:NSFileTypeDirectory];
NSString *subtitle = nil;
@@ -217,16 +188,9 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *subpath = nil;
NSString *fullPath = nil;
if (tableView == self.tableView) {
subpath = [self.childPaths objectAtIndex:indexPath.row];
fullPath = [self.path stringByAppendingPathComponent:subpath];
} else {
fullPath = [self.searchPaths objectAtIndex:indexPath.row];
subpath = [fullPath lastPathComponent];
}
NSString *fullPath = [self filePathAtIndexPath:indexPath];
NSString *subpath = [fullPath lastPathComponent];
NSString *pathExtension = [subpath pathExtension];
BOOL isDirectory = NO;
BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory];
@@ -234,26 +198,29 @@
UIViewController *drillInViewController = nil;
if (isDirectory) {
drillInViewController = [[[self class] alloc] initWithPath:fullPath];
} else if ([FLEXUtility isImagePathExtension:[fullPath pathExtension]]) {
} else if ([FLEXUtility isImagePathExtension:pathExtension]) {
UIImage *image = [UIImage imageWithContentsOfFile:fullPath];
drillInViewController = [[FLEXImagePreviewViewController alloc] initWithImage:image];
} else {
// Special case keyed archives, json, and plists to get more readable data.
NSString *prettyString = nil;
if ([[subpath pathExtension] isEqual:@"archive"]) {
if ([pathExtension isEqual:@"archive"] || [pathExtension isEqual:@"coded"]) {
prettyString = [[NSKeyedUnarchiver unarchiveObjectWithFile:fullPath] description];
} else if ([[subpath pathExtension] isEqualToString:@"json"]) {
} else if ([pathExtension isEqualToString:@"json"]) {
prettyString = [FLEXUtility prettyJSONStringFromData:[NSData dataWithContentsOfFile:fullPath]];
} else if ([[subpath pathExtension] isEqualToString:@"plist"]) {
} else if ([pathExtension isEqualToString:@"plist"]) {
NSData *fileData = [NSData dataWithContentsOfFile:fullPath];
prettyString = [[NSPropertyListSerialization propertyListWithData:fileData options:0 format:NULL error:NULL] description];
}
if ([prettyString length] > 0) {
drillInViewController = [[FLEXWebViewController alloc] initWithText:prettyString];
} else if ([FLEXWebViewController supportsPathExtension:[subpath pathExtension]]) {
} else if ([FLEXWebViewController supportsPathExtension:pathExtension]) {
drillInViewController = [[FLEXWebViewController alloc] initWithURL:[NSURL fileURLWithPath:fullPath]];
} else {
} else if ([FLEXTableListViewController supportsExtension:subpath.pathExtension]) {
drillInViewController = [[FLEXTableListViewController alloc] initWithPath:fullPath];
}
else {
NSString *fileString = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:NULL];
if ([fileString length] > 0) {
drillInViewController = [[FLEXWebViewController alloc] initWithText:fileString];
@@ -309,16 +276,8 @@
- (void)fileBrowserRename:(UITableViewCell *)sender
{
NSString *fullPath = nil;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
if (indexPath) {
NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
fullPath = [self.path stringByAppendingPathComponent:subpath];
} else {
indexPath = [self.searchController.searchResultsTableView indexPathForCell:sender];
fullPath = [self.searchPaths objectAtIndex:indexPath.row];
}
NSString *fullPath = [self filePathAtIndexPath:indexPath];
self.fileOperationController = [[FLEXFileBrowserFileRenameOperationController alloc] initWithPath:fullPath];
self.fileOperationController.delegate = self;
@@ -327,17 +286,9 @@
- (void)fileBrowserDelete:(UITableViewCell *)sender
{
NSString *fullPath = nil;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
if (indexPath) {
NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
fullPath = [self.path stringByAppendingPathComponent:subpath];
} else {
indexPath = [self.searchController.searchResultsTableView indexPathForCell:sender];
fullPath = [self.searchPaths objectAtIndex:indexPath.row];
}
NSString *fullPath = [self filePathAtIndexPath:indexPath];
self.fileOperationController = [[FLEXFileBrowserFileDeleteOperationController alloc] initWithPath:fullPath];
self.fileOperationController.delegate = self;
[self.fileOperationController show];
@@ -347,16 +298,20 @@
{
if (self.searchController.isActive) {
[self reloadSearchPaths];
[self.searchController.searchResultsTableView reloadData];
} else {
[self reloadChildPaths];
[self.tableView reloadData];
}
[self.tableView reloadData];
}
- (void)reloadChildPaths
{
self.childPaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL];
NSMutableArray *childPaths = [NSMutableArray array];
NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL];
for (NSString *subpath in subpaths) {
[childPaths addObject:[self.path stringByAppendingPathComponent:subpath]];
}
self.childPaths = childPaths;
}
- (void)reloadSearchPaths
@@ -366,11 +321,16 @@
//clear pre search request and start a new one
[self.operationQueue cancelAllOperations];
FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:self.searchString];
FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:self.searchController.searchBar.text];
newOperation.delegate = self;
[self.operationQueue addOperation:newOperation];
}
- (NSString *)filePathAtIndexPath:(NSIndexPath *)indexPath
{
return self.searchController.isActive ? self.searchPaths[indexPath.row] : self.childPaths[indexPath.row];
}
@end
@@ -14,6 +14,7 @@
#import "FLEXObjectExplorerFactory.h"
#import "FLEXLiveObjectsTableViewController.h"
#import "FLEXFileBrowserTableViewController.h"
#import "FLEXCookiesTableViewController.h"
#import "FLEXGlobalsTableViewControllerEntry.h"
#import "FLEXManager+Private.h"
#import "FLEXSystemLogTableViewController.h"
@@ -26,6 +27,7 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {
FLEXGlobalsRowSystemLog,
FLEXGlobalsRowLiveObjects,
FLEXGlobalsRowFileBrowser,
FLEXGlobalsCookies,
FLEXGlobalsRowSystemLibraries,
FLEXGlobalsRowAppClasses,
FLEXGlobalsRowAppDelegate,
@@ -162,6 +164,15 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) {
};
break;
case FLEXGlobalsCookies:
titleFuture = ^NSString *{
return @"🍪 Cookies";
};
viewControllerFuture = ^UIViewController *{
return [[FLEXCookiesTableViewController alloc] init];
};
break;
case FLEXGlobalsRowFileBrowser:
titleFuture = ^NSString *{
return @"📁 File Browser";
@@ -12,6 +12,8 @@
#import "FLEXRuntimeUtility.h"
#import "FLEXUtility.h"
#import "FLEXHeapEnumerator.h"
#import <malloc/malloc.h>
@interface FLEXInstancesTableViewController ()
@@ -31,7 +33,9 @@
// Note: objects of certain classes crash when retain is called. It is up to the user to avoid tapping into instance lists for these classes.
// Ex. OS_dispatch_queue_specific_queue
// In the future, we could provide some kind of warning for classes that are known to be problematic.
[instances addObject:object];
if (malloc_size((__bridge const void *)(object)) > 0) {
[instances addObject:object];
}
}
}];
FLEXInstancesTableViewController *instancesViewController = [[self alloc] init];
@@ -100,10 +104,10 @@
cell.detailTextLabel.textColor = [UIColor grayColor];
}
id instance = [self.instances objectAtIndex:indexPath.row];
id instance = self.instances[indexPath.row];
NSString *title = nil;
if ((NSInteger)[self.fieldNames count] > indexPath.row) {
title = [NSString stringWithFormat:@"%@ %@", NSStringFromClass(object_getClass(instance)), [self.fieldNames objectAtIndex:indexPath.row]];
title = [NSString stringWithFormat:@"%@ %@", NSStringFromClass(object_getClass(instance)), self.fieldNames[indexPath.row]];
} else {
title = [NSString stringWithFormat:@"%@ %p", NSStringFromClass(object_getClass(instance)), instance];
}
@@ -118,7 +122,7 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
id instance = [self.instances objectAtIndex:indexPath.row];
id instance = self.instances[indexPath.row];
FLEXObjectExplorerViewController *drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:instance];
[self.navigationController pushViewController:drillInViewController animated:YES];
}
@@ -9,6 +9,7 @@
#import "FLEXLibrariesTableViewController.h"
#import "FLEXUtility.h"
#import "FLEXClassesTableViewController.h"
#import "FLEXClassExplorerViewController.h"
#import <objc/runtime.h>
@interface FLEXLibrariesTableViewController () <UISearchBarDelegate>
@@ -17,6 +18,7 @@
@property (nonatomic, strong) NSArray *filteredImageNames;
@property (nonatomic, strong) UISearchBar *searchBar;
@property (nonatomic, strong) Class foundClass;
@end
@@ -63,9 +65,9 @@
// Sort alphabetically
self.imageNames = [imageNameStrings sortedArrayWithOptions:0 usingComparator:^NSComparisonResult(NSString *name1, NSString *name2) {
NSString *shortName1 = [self shortNameForImageName:name1];
NSString *shortName2 = [self shortNameForImageName:name2];
return [shortName1 caseInsensitiveCompare:shortName2];
NSString *shortName1 = [self shortNameForImageName:name1];
NSString *shortName2 = [self shortNameForImageName:name2];
return [shortName1 caseInsensitiveCompare:shortName2];
}];
free(imageNames);
@@ -74,13 +76,11 @@
- (NSString *)shortNameForImageName:(NSString *)imageName
{
NSString *shortName = nil;
NSArray *components = [imageName componentsSeparatedByString:@"/"];
NSUInteger componentsCount = [components count];
if (componentsCount >= 2) {
shortName = [NSString stringWithFormat:@"%@/%@", components[componentsCount - 2], components[componentsCount - 1]];
if (components.count >= 2) {
return [NSString stringWithFormat:@"%@/%@", components[components.count - 2], components[components.count - 1]];
}
return shortName;
return imageName.lastPathComponent;
}
- (void)setImageNames:(NSArray *)imageNames
@@ -109,6 +109,8 @@
} else {
self.filteredImageNames = self.imageNames;
}
self.foundClass = NSClassFromString(searchText);
[self.tableView reloadData];
}
@@ -127,22 +129,32 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.filteredImageNames count];
return self.filteredImageNames.count + (self.foundClass ? 1 : 0);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
static NSString *cellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
}
NSString *fullImageName = self.filteredImageNames[indexPath.row];
cell.textLabel.text = [self shortNameForImageName:fullImageName];
NSString *executablePath;
if (self.foundClass) {
if (indexPath.row == 0) {
cell.textLabel.text = [NSString stringWithFormat:@"Class \"%@\"", self.searchBar.text];
return cell;
} else {
executablePath = self.filteredImageNames[indexPath.row-1];
}
} else {
executablePath = self.filteredImageNames[indexPath.row];
}
cell.textLabel.text = [self shortNameForImageName:executablePath];
return cell;
}
@@ -151,9 +163,15 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init];
classesViewController.binaryImageName = self.filteredImageNames[indexPath.row];
[self.navigationController pushViewController:classesViewController animated:YES];
if (indexPath.row == 0 && self.foundClass) {
FLEXClassExplorerViewController *objectExplorer = [FLEXClassExplorerViewController new];
objectExplorer.object = self.foundClass;
[self.navigationController pushViewController:objectExplorer animated:YES];
} else {
FLEXClassesTableViewController *classesViewController = [[FLEXClassesTableViewController alloc] init];
classesViewController.binaryImageName = self.filteredImageNames[self.foundClass ? indexPath.row-1 : indexPath.row];
[self.navigationController pushViewController:classesViewController animated:YES];
}
}
@end
@@ -100,11 +100,11 @@ static const NSInteger kFLEXLiveObjectsSortByCountIndex = 1;
NSUInteger totalCount = 0;
for (NSString *className in self.allClassNames) {
totalCount += [[self.instanceCountsForClassNames objectForKey:className] unsignedIntegerValue];
totalCount += [self.instanceCountsForClassNames[className] unsignedIntegerValue];
}
NSUInteger filteredCount = 0;
for (NSString *className in self.filteredClassNames) {
filteredCount += [[self.instanceCountsForClassNames objectForKey:className] unsignedIntegerValue];
filteredCount += [self.instanceCountsForClassNames[className] unsignedIntegerValue];
}
if (filteredCount == totalCount) {
@@ -154,8 +154,8 @@ static const NSInteger kFLEXLiveObjectsSortByCountIndex = 1;
self.filteredClassNames = [self.filteredClassNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
} else if (self.searchBar.selectedScopeButtonIndex == kFLEXLiveObjectsSortByCountIndex) {
self.filteredClassNames = [self.filteredClassNames sortedArrayUsingComparator:^NSComparisonResult(NSString *className1, NSString *className2) {
NSNumber *count1 = [self.instanceCountsForClassNames objectForKey:className1];
NSNumber *count2 = [self.instanceCountsForClassNames objectForKey:className2];
NSNumber *count1 = self.instanceCountsForClassNames[className1];
NSNumber *count2 = self.instanceCountsForClassNames[className2];
// Reversed for descending counts.
return [count2 compare:count1];
}];
@@ -189,7 +189,7 @@ static const NSInteger kFLEXLiveObjectsSortByCountIndex = 1;
}
NSString *className = self.filteredClassNames[indexPath.row];
NSNumber *count = [self.instanceCountsForClassNames objectForKey:className];
NSNumber *count = self.instanceCountsForClassNames[className];
cell.textLabel.text = [NSString stringWithFormat:@"%@ (%ld)", className, (long)[count integerValue]];
return cell;
@@ -200,7 +200,7 @@ static const NSInteger kFLEXLiveObjectsSortByCountIndex = 1;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *className = [self.filteredClassNames objectAtIndex:indexPath.row];
NSString *className = self.filteredClassNames[indexPath.row];
FLEXInstancesTableViewController *instancesViewController = [FLEXInstancesTableViewController instancesTableViewControllerForClassName:className];
[self.navigationController pushViewController:instancesViewController animated:YES];
}
@@ -12,12 +12,9 @@
#import "FLEXSystemLogTableViewCell.h"
#import <asl.h>
@interface FLEXSystemLogTableViewController () <UISearchDisplayDelegate>
@interface FLEXSystemLogTableViewController () <UISearchResultsUpdating, UISearchControllerDelegate>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@property (nonatomic, strong) UISearchDisplayController *searchController;
#pragma clang diagnostic pop
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, copy) NSArray *logMessages;
@property (nonatomic, copy) NSArray *filteredLogMessages;
@property (nonatomic, strong) NSTimer *logUpdateTimer;
@@ -35,17 +32,10 @@
self.title = @"Loading...";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@" ⬇︎ " style:UIBarButtonItemStylePlain target:self action:@selector(scrollToLastRow)];
UISearchBar *searchBar = [[UISearchBar alloc] init];
[searchBar sizeToFit];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
#pragma clang diagnostic pop
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self.searchController.searchResultsTableView registerClass:[FLEXSystemLogTableViewCell class] forCellReuseIdentifier:kFLEXSystemLogTableViewCellIdentifier];
self.searchController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.tableView.tableHeaderView = self.searchController.searchBar;
[self updateLogMessages];
@@ -108,25 +98,15 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger numberOfRows = 0;
if (tableView == self.tableView) {
numberOfRows = [self.logMessages count];
} else if (tableView == self.searchController.searchResultsTableView) {
numberOfRows = [self.filteredLogMessages count];
}
return numberOfRows;
return self.searchController.isActive ? [self.filteredLogMessages count] : [self.logMessages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FLEXSystemLogTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kFLEXSystemLogTableViewCellIdentifier forIndexPath:indexPath];
if (tableView == self.tableView) {
cell.logMessage = [self.logMessages objectAtIndex:indexPath.row];
cell.highlightedText = nil;
} else if (tableView == self.searchController.searchResultsTableView) {
cell.logMessage = [self.filteredLogMessages objectAtIndex:indexPath.row];
cell.highlightedText = self.searchController.searchBar.text;
}
cell.logMessage = [self logMessageAtIndexPath:indexPath];
cell.highlightedText = self.searchController.searchBar.text;
if (indexPath.row % 2 == 0) {
cell.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
} else {
@@ -138,12 +118,7 @@
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
FLEXSystemLogMessage *logMessage = nil;
if (tableView == self.tableView) {
logMessage = [self.logMessages objectAtIndex:indexPath.row];
} else if (tableView == self.searchController.searchResultsTableView) {
logMessage = [self.filteredLogMessages objectAtIndex:indexPath.row];
}
FLEXSystemLogMessage *logMessage = [self logMessageAtIndexPath:indexPath];
return [FLEXSystemLogTableViewCell preferredHeightForLogMessage:logMessage inWidth:self.tableView.bounds.size.width];
}
@@ -162,46 +137,38 @@
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:)) {
FLEXSystemLogMessage *logMessage = nil;
if (tableView == self.tableView) {
logMessage = [self.logMessages objectAtIndex:indexPath.row];
} else if (tableView == self.searchController.searchResultsTableView) {
logMessage = [self.filteredLogMessages objectAtIndex:indexPath.row];
}
FLEXSystemLogMessage *logMessage = [self logMessageAtIndexPath:indexPath];
NSString *stringToCopy = [FLEXSystemLogTableViewCell displayedTextForLogMessage:logMessage] ?: @"";
[[UIPasteboard generalPasteboard] setString:stringToCopy];
}
}
#pragma mark - Search display delegate
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
- (FLEXSystemLogMessage *)logMessageAtIndexPath:(NSIndexPath *)indexPath
{
return self.searchController.isActive ? self.filteredLogMessages[indexPath.row] : self.logMessages[indexPath.row];
}
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *filteredLogMessages = [self.logMessages filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FLEXSystemLogMessage *logMessage, NSDictionary *bindings) {
NSString *displayedText = [FLEXSystemLogTableViewCell displayedTextForLogMessage:logMessage];
return [displayedText rangeOfString:searchString options:NSCaseInsensitiveSearch].length > 0;
}]];
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.searchDisplayController.searchBar.text isEqual:searchString]) {
if ([searchController.searchBar.text isEqual:searchString]) {
self.filteredLogMessages = filteredLogMessages;
[self.searchDisplayController.searchResultsTableView reloadData];
[self.tableView reloadData];
}
});
});
// Reload done after the data fetches asynchronously
return NO;
}
#pragma mark - Log Message Fetching
// Due to a mistake in asl.h, things get a little messy. We need to mark these symbols as weak since they won't exist on iOS 7 despite the compiler thinking otherwise.
// asl.h in the iOS 8.1 SDK claims that asl_next() and asl_release() were introduced in iOS 7 to replace aslresponse_next() and aslresponse_free(). However, they were actually added in iOS 8.0.
extern aslmsg asl_next(asl_object_t obj) __attribute__((weak_import));
extern void asl_release(asl_object_t obj) __attribute__((weak_import));
+ (NSArray *)allLogMessagesForCurrentProcess
{
asl_object_t query = asl_new(ASL_TYPE_QUERY);
@@ -214,22 +181,10 @@ extern void asl_release(asl_object_t obj) __attribute__((weak_import));
aslmsg aslMessage = NULL;
NSMutableArray *logMessages = [NSMutableArray array];
if (&asl_next != NULL && &asl_release != NULL) {
while ((aslMessage = asl_next(response))) {
[logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]];
}
asl_release(response);
} else {
// Mute incorrect deprecated warnings. We'll need the "deprecated" functions on iOS 7, where their replacements don't yet exist.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
while ((aslMessage = aslresponse_next(response))) {
[logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]];
}
aslresponse_free(response);
#pragma clang diagnostic pop
while ((aslMessage = asl_next(response))) {
[logMessages addObject:[FLEXSystemLogMessage logMessageFromASLMessage:aslMessage]];
}
asl_release(response);
return logMessages;
}
+360
View File
@@ -0,0 +1,360 @@
//
// FLEXManager.m
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2014 Flipboard. All rights reserved.
//
#import "FLEXManager.h"
#import "FLEXExplorerViewController.h"
#import "FLEXWindow.h"
#import "FLEXGlobalsTableViewControllerEntry.h"
#import "FLEXObjectExplorerFactory.h"
#import "FLEXObjectExplorerViewController.h"
#import "FLEXNetworkObserver.h"
#import "FLEXNetworkRecorder.h"
#import "FLEXKeyboardShortcutManager.h"
#import "FLEXFileBrowserTableViewController.h"
#import "FLEXNetworkHistoryTableViewController.h"
#import "FLEXKeyboardHelpViewController.h"
@interface FLEXManager () <FLEXWindowEventDelegate, FLEXExplorerViewControllerDelegate>
@property (nonatomic, strong) FLEXWindow *explorerWindow;
@property (nonatomic, strong) FLEXExplorerViewController *explorerViewController;
@property (nonatomic, readonly, strong) NSMutableArray *userGlobalEntries;
@end
@implementation FLEXManager
+ (instancetype)sharedManager
{
static FLEXManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[[self class] alloc] init];
});
return sharedManager;
}
- (instancetype)init
{
self = [super init];
if (self) {
_userGlobalEntries = [[NSMutableArray alloc] init];
}
return self;
}
- (FLEXWindow *)explorerWindow
{
NSAssert([NSThread isMainThread], @"You must use %@ from the main thread only.", NSStringFromClass([self class]));
if (!_explorerWindow) {
_explorerWindow = [[FLEXWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_explorerWindow.eventDelegate = self;
_explorerWindow.rootViewController = self.explorerViewController;
}
return _explorerWindow;
}
- (FLEXExplorerViewController *)explorerViewController
{
if (!_explorerViewController) {
_explorerViewController = [[FLEXExplorerViewController alloc] init];
_explorerViewController.delegate = self;
}
return _explorerViewController;
}
- (void)showExplorer
{
self.explorerWindow.hidden = NO;
}
- (void)hideExplorer
{
self.explorerWindow.hidden = YES;
}
- (void)toggleExplorer {
if (self.explorerWindow.isHidden) {
[self showExplorer];
} else {
[self hideExplorer];
}
}
- (BOOL)isHidden
{
return self.explorerWindow.isHidden;
}
- (BOOL)isNetworkDebuggingEnabled
{
return [FLEXNetworkObserver isEnabled];
}
- (void)setNetworkDebuggingEnabled:(BOOL)networkDebuggingEnabled
{
[FLEXNetworkObserver setEnabled:networkDebuggingEnabled];
}
- (NSUInteger)networkResponseCacheByteLimit
{
return [[FLEXNetworkRecorder defaultRecorder] responseCacheByteLimit];
}
- (void)setNetworkResponseCacheByteLimit:(NSUInteger)networkResponseCacheByteLimit
{
[[FLEXNetworkRecorder defaultRecorder] setResponseCacheByteLimit:networkResponseCacheByteLimit];
}
#pragma mark - FLEXWindowEventDelegate
- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow
{
// Ask the explorer view controller
return [self.explorerViewController shouldReceiveTouchAtWindowPoint:pointInWindow];
}
- (BOOL)canBecomeKeyWindow
{
// Only when the explorer view controller wants it because it needs to accept key input & affect the status bar.
return [self.explorerViewController wantsWindowToBecomeKey];
}
#pragma mark - FLEXExplorerViewControllerDelegate
- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController
{
[self hideExplorer];
}
#pragma mark - Simulator Shortcuts
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description
{
# if TARGET_OS_SIMULATOR
[[FLEXKeyboardShortcutManager sharedManager] registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description];
#endif
}
- (void)setSimulatorShortcutsEnabled:(BOOL)simulatorShortcutsEnabled
{
# if TARGET_OS_SIMULATOR
[[FLEXKeyboardShortcutManager sharedManager] setEnabled:simulatorShortcutsEnabled];
#endif
}
- (BOOL)simulatorShortcutsEnabled
{
# if TARGET_OS_SIMULATOR
return [[FLEXKeyboardShortcutManager sharedManager] isEnabled];
#else
return NO;
#endif
}
- (void)registerDefaultSimulatorShortcuts
{
[self registerSimulatorShortcutWithKey:@"f" modifiers:0 action:^{
[self toggleExplorer];
} description:@"Toggle FLEX toolbar"];
[self registerSimulatorShortcutWithKey:@"g" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleMenuTool];
} description:@"Toggle FLEX globals menu"];
[self registerSimulatorShortcutWithKey:@"v" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleViewsTool];
} description:@"Toggle view hierarchy menu"];
[self registerSimulatorShortcutWithKey:@"s" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleSelectTool];
} description:@"Toggle select tool"];
[self registerSimulatorShortcutWithKey:@"m" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleMoveTool];
} description:@"Toggle move tool"];
[self registerSimulatorShortcutWithKey:@"n" modifiers:0 action:^{
[self toggleTopViewControllerOfClass:[FLEXNetworkHistoryTableViewController class]];
} description:@"Toggle network history view"];
[self registerSimulatorShortcutWithKey:UIKeyInputDownArrow modifiers:0 action:^{
if ([self isHidden]) {
[self tryScrollDown];
} else {
[self.explorerViewController handleDownArrowKeyPressed];
}
} description:@"Cycle view selection\n\t\tMove view down\n\t\tScroll down"];
[self registerSimulatorShortcutWithKey:UIKeyInputUpArrow modifiers:0 action:^{
if ([self isHidden]) {
[self tryScrollUp];
} else {
[self.explorerViewController handleUpArrowKeyPressed];
}
} description:@"Cycle view selection\n\t\tMove view up\n\t\tScroll up"];
[self registerSimulatorShortcutWithKey:UIKeyInputRightArrow modifiers:0 action:^{
if (![self isHidden]) {
[self.explorerViewController handleRightArrowKeyPressed];
}
} description:@"Move selected view right"];
[self registerSimulatorShortcutWithKey:UIKeyInputLeftArrow modifiers:0 action:^{
if ([self isHidden]) {
[self tryGoBack];
} else {
[self.explorerViewController handleLeftArrowKeyPressed];
}
} description:@"Move selected view left"];
[self registerSimulatorShortcutWithKey:@"?" modifiers:0 action:^{
[self toggleTopViewControllerOfClass:[FLEXKeyboardHelpViewController class]];
} description:@"Toggle (this) help menu"];
[self registerSimulatorShortcutWithKey:UIKeyInputEscape modifiers:0 action:^{
[[[self topViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} description:@"End editing text\n\t\tDismiss top view controller"];
[self registerSimulatorShortcutWithKey:@"o" modifiers:UIKeyModifierCommand|UIKeyModifierShift action:^{
[self toggleTopViewControllerOfClass:[FLEXFileBrowserTableViewController class]];
} description:@"Toggle file browser menu"];
}
+ (void)load
{
dispatch_async(dispatch_get_main_queue(), ^{
[[[self class] sharedManager] registerDefaultSimulatorShortcuts];
});
}
#pragma mark - Extensions
- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock
{
NSParameterAssert(entryName);
NSParameterAssert(objectFutureBlock);
NSAssert([NSThread isMainThread], @"This method must be called from the main thread.");
entryName = entryName.copy;
FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{
return entryName;
} viewControllerFuture:^UIViewController *{
return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()];
}];
[self.userGlobalEntries addObject:entry];
}
- (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock
{
NSParameterAssert(entryName);
NSParameterAssert(viewControllerFutureBlock);
NSAssert([NSThread isMainThread], @"This method must be called from the main thread.");
entryName = entryName.copy;
FLEXGlobalsTableViewControllerEntry *entry = [FLEXGlobalsTableViewControllerEntry entryWithNameFuture:^NSString *{
return entryName;
} viewControllerFuture:^UIViewController *{
UIViewController *viewController = viewControllerFutureBlock();
NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName);
return viewController;
}];
[self.userGlobalEntries addObject:entry];
}
- (void)tryScrollDown
{
UIScrollView *firstScrollView = [self firstScrollView];
CGPoint contentOffset = [firstScrollView contentOffset];
CGFloat distance = floor(firstScrollView.frame.size.height / 2.0);
CGFloat maxContentOffsetY = firstScrollView.contentSize.height + firstScrollView.contentInset.bottom - firstScrollView.frame.size.height;
distance = MIN(maxContentOffsetY - firstScrollView.contentOffset.y, distance);
contentOffset.y += distance;
[firstScrollView setContentOffset:contentOffset animated:YES];
}
- (void)tryScrollUp
{
UIScrollView *firstScrollView = [self firstScrollView];
CGPoint contentOffset = [firstScrollView contentOffset];
CGFloat distance = floor(firstScrollView.frame.size.height / 2.0);
CGFloat minContentOffsetY = -firstScrollView.contentInset.top;
distance = MIN(firstScrollView.contentOffset.y - minContentOffsetY, distance);
contentOffset.y -= distance;
[firstScrollView setContentOffset:contentOffset animated:YES];
}
- (UIScrollView *)firstScrollView
{
NSMutableArray *views = [[[[UIApplication sharedApplication] keyWindow] subviews] mutableCopy];
UIScrollView *scrollView = nil;
while ([views count] > 0) {
UIView *view = [views firstObject];
[views removeObjectAtIndex:0];
if ([view isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)view;
break;
} else {
[views addObjectsFromArray:[view subviews]];
}
}
return scrollView;
}
- (void)tryGoBack
{
UINavigationController *navigationController = nil;
UIViewController *topViewController = [self topViewController];
if ([topViewController isKindOfClass:[UINavigationController class]]) {
navigationController = (UINavigationController *)topViewController;
} else {
navigationController = topViewController.navigationController;
}
[navigationController popViewControllerAnimated:YES];
}
- (UIViewController *)topViewController
{
UIViewController *topViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
while ([topViewController presentedViewController]) {
topViewController = [topViewController presentedViewController];
}
return topViewController;
}
- (void)toggleTopViewControllerOfClass:(Class)class
{
UIViewController *topViewController = [self topViewController];
if ([topViewController isKindOfClass:[UINavigationController class]] && [[[(UINavigationController *)topViewController viewControllers] firstObject] isKindOfClass:[class class]]) {
[[topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} else {
id viewController = [[class alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[topViewController presentViewController:navigationController animated:YES completion:nil];
}
}
- (void)showExplorerIfNeeded
{
if ([self isHidden]) {
[self showExplorer];
}
}
@end
+19
View File
@@ -0,0 +1,19 @@
//
// FLEXCurlLogger.h
//
//
// Created by Ji Pei on 07/27/16
//
#import <Foundation/Foundation.h>
@interface FLEXNetworkCurlLogger : NSObject
/**
* Generates a cURL command equivalent to the given request.
*
* @param request The request to be translated
*/
+ (NSString *)curlCommandString:(NSURLRequest *)request;
@end
+42
View File
@@ -0,0 +1,42 @@
//
// FLEXCurlLogger.m
//
//
// Created by Ji Pei on 07/27/16
//
#import "FLEXNetworkCurlLogger.h"
@implementation FLEXNetworkCurlLogger
+ (NSString *)curlCommandString:(NSURLRequest *)request {
__block NSMutableString *curlCommandString = [NSMutableString stringWithFormat:@"curl -v -X %@ ", request.HTTPMethod];
[curlCommandString appendFormat:@"\'%@\' ", request.URL.absoluteString];
[request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *val, BOOL *stop) {
[curlCommandString appendFormat:@"-H \'%@: %@\' ", key, val];
}];
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL];
if (cookies) {
[curlCommandString appendFormat:@"-H \'Cookie:"];
for (NSHTTPCookie *cookie in cookies) {
[curlCommandString appendFormat:@" %@=%@;", cookie.name, cookie.value];
}
[curlCommandString appendFormat:@"\' "];
}
if (request.HTTPBody) {
if ([request.allHTTPHeaderFields[@"Content-Length"] intValue] < 1024) {
[curlCommandString appendFormat:@"-d \'%@\'",
[[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]];
} else {
[curlCommandString appendFormat:@"[TOO MUCH DATA TO INCLUDE]"];
}
}
return curlCommandString;
}
@end
@@ -14,7 +14,7 @@
#import "FLEXNetworkObserver.h"
#import "FLEXNetworkSettingsTableViewController.h"
@interface FLEXNetworkHistoryTableViewController () <UISearchDisplayDelegate>
@interface FLEXNetworkHistoryTableViewController () <UISearchResultsUpdating, UISearchControllerDelegate>
/// Backing model
@property (nonatomic, copy) NSArray *networkTransactions;
@@ -23,11 +23,9 @@
@property (nonatomic, assign) long long filteredBytesReceived;
@property (nonatomic, assign) BOOL rowInsertInProgress;
@property (nonatomic, assign) BOOL isPresentingSearch;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@property (nonatomic, strong) UISearchDisplayController *searchController;
#pragma clang diagnostic pop
@property (nonatomic, strong) UISearchController *searchController;
@end
@@ -60,18 +58,10 @@
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.rowHeight = [FLEXNetworkTransactionTableViewCell preferredCellHeight];
UISearchBar *searchBar = [[UISearchBar alloc] init];
[searchBar sizeToFit];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
#pragma clang diagnostic pop
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self.searchController.searchResultsTableView registerClass:[FLEXNetworkTransactionTableViewCell class] forCellReuseIdentifier:kFLEXNetworkTransactionCellIdentifier];
self.searchController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.searchController.searchResultsTableView.rowHeight = [FLEXNetworkTransactionTableViewCell preferredCellHeight];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.tableView.tableHeaderView = self.searchController.searchBar;
[self updateTransactions];
@@ -112,7 +102,7 @@
bytesReceived += transaction.receivedDataLength;
}
self.bytesReceived = bytesReceived;
[self updateFirstSectionHeaderInTableView:self.tableView];
[self updateFirstSectionHeader];
}
- (void)setFilteredNetworkTransactions:(NSArray *)filteredNetworkTransactions
@@ -130,31 +120,31 @@
filteredBytesReceived += transaction.receivedDataLength;
}
self.filteredBytesReceived = filteredBytesReceived;
[self updateFirstSectionHeaderInTableView:self.searchController.searchResultsTableView];
[self updateFirstSectionHeader];
}
- (void)updateFirstSectionHeaderInTableView:(UITableView *)tableView
- (void)updateFirstSectionHeader
{
UIView *view = [tableView headerViewForSection:0];
UIView *view = [self.tableView headerViewForSection:0];
if ([view isKindOfClass:[UITableViewHeaderFooterView class]]) {
UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view;
headerView.textLabel.text = [self headerTextForTableView:tableView];
headerView.textLabel.text = [self headerText];
[headerView setNeedsLayout];
}
}
- (NSString *)headerTextForTableView:(UITableView *)tableView
- (NSString *)headerText
{
NSString *headerText = nil;
if ([FLEXNetworkObserver isEnabled]) {
long long bytesReceived = 0;
NSInteger totalRequests = 0;
if (tableView == self.tableView) {
bytesReceived = self.bytesReceived;
totalRequests = [self.networkTransactions count];
} else if (tableView == self.searchController.searchResultsTableView) {
if (self.searchController.isActive) {
bytesReceived = self.filteredBytesReceived;
totalRequests = [self.filteredNetworkTransactions count];
} else {
bytesReceived = self.bytesReceived;
totalRequests = [self.networkTransactions count];
}
NSString *byteCountText = [NSByteCountFormatter stringFromByteCount:bytesReceived countStyle:NSByteCountFormatterCountStyleBinary];
NSString *requestsText = totalRequests == 1 ? @"Request" : @"Requests";
@@ -179,13 +169,19 @@
if (self.rowInsertInProgress) {
return;
}
if (self.searchController.isActive) {
[self updateTransactions];
[self updateSearchResults];
return;
}
NSInteger existingRowCount = [self.networkTransactions count];
[self updateTransactions];
NSInteger newRowCount = [self.networkTransactions count];
NSInteger addedRowCount = newRowCount - existingRowCount;
if (addedRowCount != 0) {
if (addedRowCount != 0 && !self.isPresentingSearch) {
// Insert animation if we're at the top.
if (self.tableView.contentOffset.y <= 0.0 && addedRowCount > 0) {
[CATransaction begin];
@@ -210,10 +206,6 @@
CGFloat contentHeightChange = self.tableView.contentSize.height - existingContentSize.height;
self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y + contentHeightChange);
}
if (self.searchController.isActive) {
[self updateSearchResultsWithSearchString:self.searchController.searchBar.text];
}
}
}
@@ -222,38 +214,31 @@
[self updateBytesReceived];
[self updateFilteredBytesReceived];
FLEXNetworkTransaction *transaction = [notification.userInfo objectForKey:kFLEXNetworkRecorderUserInfoTransactionKey];
NSArray *tableViews = @[self.tableView];
if (self.searchController.searchResultsTableView) {
tableViews = [tableViews arrayByAddingObject:self.searchController.searchResultsTableView];
}
FLEXNetworkTransaction *transaction = notification.userInfo[kFLEXNetworkRecorderUserInfoTransactionKey];
// Update both the main table view and search table view if needed.
for (UITableView *tableView in tableViews) {
for (FLEXNetworkTransactionTableViewCell *cell in [tableView visibleCells]) {
if ([cell.transaction isEqual:transaction]) {
// Using -[UITableView reloadRowsAtIndexPaths:withRowAnimation:] is overkill here and kicks off a lot of
// work that can make the table view somewhat unresponseive when lots of updates are streaming in.
// We just need to tell the cell that it needs to re-layout.
[cell setNeedsLayout];
break;
}
for (FLEXNetworkTransactionTableViewCell *cell in [self.tableView visibleCells]) {
if ([cell.transaction isEqual:transaction]) {
// Using -[UITableView reloadRowsAtIndexPaths:withRowAnimation:] is overkill here and kicks off a lot of
// work that can make the table view somewhat unresponseive when lots of updates are streaming in.
// We just need to tell the cell that it needs to re-layout.
[cell setNeedsLayout];
break;
}
[self updateFirstSectionHeaderInTableView:tableView];
}
[self updateFirstSectionHeader];
}
- (void)handleTransactionsClearedNotification:(NSNotification *)notification
{
[self updateTransactions];
[self.tableView reloadData];
[self.searchController.searchResultsTableView reloadData];
}
- (void)handleNetworkObserverEnabledStateChangedNotification:(NSNotification *)notification
{
// Update the header, which displays a warning when network debugging is disabled
[self updateFirstSectionHeaderInTableView:self.tableView];
[self updateFirstSectionHeader];
}
#pragma mark - Table view data source
@@ -265,18 +250,12 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger numberOfRows = 0;
if (tableView == self.tableView) {
numberOfRows = [self.networkTransactions count];
} else if (tableView == self.searchController.searchResultsTableView) {
numberOfRows = [self.filteredNetworkTransactions count];
}
return numberOfRows;
return self.searchController.isActive ? [self.filteredNetworkTransactions count] : [self.networkTransactions count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self headerTextForTableView:tableView];
return [self headerText];
}
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
@@ -335,27 +314,19 @@
- (FLEXNetworkTransaction *)transactionAtIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView
{
FLEXNetworkTransaction *transaction = nil;
if (tableView == self.tableView) {
transaction = [self.networkTransactions objectAtIndex:indexPath.row];
} else if (tableView == self.searchController.searchResultsTableView) {
transaction = [self.filteredNetworkTransactions objectAtIndex:indexPath.row];
}
return transaction;
return self.searchController.isActive ? self.filteredNetworkTransactions[indexPath.row] : self.networkTransactions[indexPath.row];
}
#pragma mark - Search display delegate
#pragma mark - UISearchResultsUpdating
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
[self updateSearchResultsWithSearchString:searchString];
// Reload done after the data is filtered asynchronously
return NO;
[self updateSearchResults];
}
- (void)updateSearchResultsWithSearchString:(NSString *)searchString
- (void)updateSearchResults
{
NSString *searchString = self.searchController.searchBar.text;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *filteredNetworkTransactions = [self.networkTransactions filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FLEXNetworkTransaction *transaction, NSDictionary *bindings) {
return [[transaction.request.URL absoluteString] rangeOfString:searchString options:NSCaseInsensitiveSearch].length > 0;
@@ -363,10 +334,27 @@
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.searchController.searchBar.text isEqual:searchString]) {
self.filteredNetworkTransactions = filteredNetworkTransactions;
[self.searchController.searchResultsTableView reloadData];
[self.tableView reloadData];
}
});
});
}
#pragma mark - UISearchControllerDelegate
- (void)willPresentSearchController:(UISearchController *)searchController
{
self.isPresentingSearch = YES;
}
- (void)didPresentSearchController:(UISearchController *)searchController
{
self.isPresentingSearch = NO;
}
- (void)willDismissSearchController:(UISearchController *)searchController
{
[self.tableView reloadData];
}
@end
+6 -5
View File
@@ -7,6 +7,7 @@
//
#import "FLEXNetworkRecorder.h"
#import "FLEXNetworkCurlLogger.h"
#import "FLEXNetworkTransaction.h"
#import "FLEXUtility.h"
#import "FLEXResources.h"
@@ -129,7 +130,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
NSDate *responseDate = [NSDate date];
dispatch_async(self.queue, ^{
FLEXNetworkTransaction *transaction = [self.networkTransactionsForRequestIdentifiers objectForKey:requestID];
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
if (!transaction) {
return;
}
@@ -144,7 +145,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength
{
dispatch_async(self.queue, ^{
FLEXNetworkTransaction *transaction = [self.networkTransactionsForRequestIdentifiers objectForKey:requestID];
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
if (!transaction) {
return;
}
@@ -159,7 +160,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
NSDate *finishedDate = [NSDate date];
dispatch_async(self.queue, ^{
FLEXNetworkTransaction *transaction = [self.networkTransactionsForRequestIdentifiers objectForKey:requestID];
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
if (!transaction) {
return;
}
@@ -215,7 +216,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error
{
dispatch_async(self.queue, ^{
FLEXNetworkTransaction *transaction = [self.networkTransactionsForRequestIdentifiers objectForKey:requestID];
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
if (!transaction) {
return;
}
@@ -230,7 +231,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID
{
dispatch_async(self.queue, ^{
FLEXNetworkTransaction *transaction = [self.networkTransactionsForRequestIdentifiers objectForKey:requestID];
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
if (!transaction) {
return;
}
@@ -39,9 +39,6 @@
UITableViewCell *networkDebuggingCell = [self switchCellWithTitle:@"Network Debugging" toggleAction:@selector(networkDebuggingToggled:) isOn:[FLEXNetworkObserver isEnabled]];
[mutableCells addObject:networkDebuggingCell];
UITableViewCell *enableOnLaunchCell = [self switchCellWithTitle:@"Enable on Launch" toggleAction:@selector(enableOnLaunchToggled:) isOn:[FLEXNetworkObserver shouldEnableOnLaunch]];
[mutableCells addObject:enableOnLaunchCell];
UITableViewCell *cacheMediaResponsesCell = [self switchCellWithTitle:@"Cache Media Responses" toggleAction:@selector(cacheMediaResponsesToggled:) isOn:NO];
[mutableCells addObject:cacheMediaResponsesCell];
@@ -64,11 +61,6 @@
[FLEXNetworkObserver setEnabled:sender.isOn];
}
- (void)enableOnLaunchToggled:(UISwitch *)sender
{
[FLEXNetworkObserver setShouldEnableOnLaunch:sender.isOn];
}
- (void)cacheMediaResponsesToggled:(UISwitch *)sender
{
[[FLEXNetworkRecorder defaultRecorder] setShouldCacheMediaResponses:sender.isOn];
@@ -100,7 +92,7 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self.cells objectAtIndex:indexPath.row];
return self.cells[indexPath.row];
}
#pragma mark - UIActionSheetDelegate
+3
View File
@@ -36,6 +36,9 @@ typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) {
/// Only applicable for image downloads. A small thumbnail to preview the full response.
@property (nonatomic, strong) UIImage *responseThumbnail;
/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.
@property (nonatomic, strong, readonly) NSData *cachedRequestBody;
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state;
@end
+28
View File
@@ -8,6 +8,12 @@
#import "FLEXNetworkTransaction.h"
@interface FLEXNetworkTransaction ()
@property (nonatomic, strong, readwrite) NSData *cachedRequestBody;
@end
@implementation FLEXNetworkTransaction
- (NSString *)description
@@ -22,6 +28,28 @@
return description;
}
- (NSData *)cachedRequestBody {
if (!_cachedRequestBody) {
if (self.request.HTTPBody != nil) {
_cachedRequestBody = self.request.HTTPBody;
} else if ([self.request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
NSInputStream *bodyStream = [self.request.HTTPBodyStream copy];
const NSUInteger bufferSize = 1024;
uint8_t buffer[bufferSize];
NSMutableData *data = [NSMutableData data];
[bodyStream open];
NSInteger readBytes = 0;
do {
readBytes = [bodyStream read:buffer maxLength:bufferSize];
[data appendBytes:buffer length:readBytes];
} while (readBytes > 0);
[bodyStream close];
_cachedRequestBody = data;
}
}
return _cachedRequestBody;
}
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state
{
NSString *readableString = nil;
@@ -7,6 +7,7 @@
//
#import "FLEXNetworkTransactionDetailTableViewController.h"
#import "FLEXNetworkCurlLogger.h"
#import "FLEXNetworkRecorder.h"
#import "FLEXNetworkTransaction.h"
#import "FLEXWebViewController.h"
@@ -53,7 +54,7 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTransactionUpdatedNotification:) name:kFLEXNetworkRecorderTransactionUpdatedNotification object:nil];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonPressed:)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy curl" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonPressed:)];
}
return self;
}
@@ -120,26 +121,7 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
- (void)copyButtonPressed:(id)sender
{
NSMutableString *requestDetailString = [NSMutableString string];
for (FLEXNetworkDetailSection *section in self.sections) {
if ([section.rows count] > 0) {
if ([section.title length] > 0) {
[requestDetailString appendString:section.title];
[requestDetailString appendString:@"\n\n"];
}
for (FLEXNetworkDetailRow *row in section.rows) {
NSString *rowDescription = [[[self class] attributedTextForRow:row] string];
if ([rowDescription length] > 0) {
[requestDetailString appendString:rowDescription];
[requestDetailString appendString:@"\n"];
}
}
[requestDetailString appendString:@"\n\n"];
}
}
[[UIPasteboard generalPasteboard] setString:requestDetailString];
[[UIPasteboard generalPasteboard] setString:[FLEXNetworkCurlLogger curlCommandString:_transaction.request]];
}
#pragma mark - Table view data source
@@ -151,13 +133,13 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
FLEXNetworkDetailSection *sectionModel = [self.sections objectAtIndex:section];
FLEXNetworkDetailSection *sectionModel = self.sections[section];
return [sectionModel.rows count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
FLEXNetworkDetailSection *sectionModel = [self.sections objectAtIndex:section];
FLEXNetworkDetailSection *sectionModel = self.sections[section];
return sectionModel.title;
}
@@ -200,8 +182,8 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
- (FLEXNetworkDetailRow *)rowModelAtIndexPath:(NSIndexPath *)indexPath
{
FLEXNetworkDetailSection *sectionModel = [self.sections objectAtIndex:indexPath.section];
return [sectionModel.rows objectAtIndex:indexPath.row];
FLEXNetworkDetailSection *sectionModel = self.sections[indexPath.section];
return sectionModel.rows[indexPath.row];
}
#pragma mark - Cell Copying
@@ -264,10 +246,10 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
requestMethodRow.detailText = transaction.request.HTTPMethod;
[rows addObject:requestMethodRow];
if ([transaction.request.HTTPBody length] > 0) {
if ([transaction.cachedRequestBody length] > 0) {
FLEXNetworkDetailRow *postBodySizeRow = [[FLEXNetworkDetailRow alloc] init];
postBodySizeRow.title = @"Request Body Size";
postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:[transaction.request.HTTPBody length] countStyle:NSByteCountFormatterCountStyleBinary];
postBodySizeRow.detailText = [NSByteCountFormatter stringFromByteCount:[transaction.cachedRequestBody length] countStyle:NSByteCountFormatterCountStyleBinary];
[rows addObject:postBodySizeRow];
FLEXNetworkDetailRow *postBodyRow = [[FLEXNetworkDetailRow alloc] init];
@@ -396,7 +378,7 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
{
FLEXNetworkDetailSection *postBodySection = [[FLEXNetworkDetailSection alloc] init];
postBodySection.title = @"Request Body Parameters";
if ([transaction.request.HTTPBody length] > 0) {
if ([transaction.cachedRequestBody length] > 0) {
NSString *contentType = [transaction.request valueForHTTPHeaderField:@"Content-Type"];
if ([contentType hasPrefix:@"application/x-www-form-urlencoded"]) {
NSString *bodyString = [[NSString alloc] initWithData:[self postBodyDataForTransaction:transaction] encoding:NSUTF8StringEncoding];
@@ -432,7 +414,7 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
NSMutableArray *rows = [NSMutableArray arrayWithCapacity:[dictionary count]];
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
for (NSString *key in sortedKeys) {
NSString *value = [dictionary objectForKey:key];
NSString *value = dictionary[key];
FLEXNetworkDetailRow *row = [[FLEXNetworkDetailRow alloc] init];
row.title = key;
row.detailText = [value description];
@@ -470,7 +452,7 @@ typedef UIViewController *(^FLEXNetworkDetailRowSelectionFuture)(void);
+ (NSData *)postBodyDataForTransaction:(FLEXNetworkTransaction *)transaction
{
NSData *bodyData = transaction.request.HTTPBody;
NSData *bodyData = transaction.cachedRequestBody;
if ([bodyData length] > 0) {
NSString *contentEncoding = [transaction.request valueForHTTPHeaderField:@"Content-Encoding"];
if ([contentEncoding rangeOfString:@"deflate" options:NSCaseInsensitiveSearch].length > 0 || [contentEncoding rangeOfString:@"gzip" options:NSCaseInsensitiveSearch].length > 0) {
@@ -127,11 +127,13 @@ NSString *const kFLEXNetworkTransactionCellIdentifier = @"kFLEXNetworkTransactio
NSMutableArray *detailComponents = [NSMutableArray array];
NSString *timestamp = [[self class] timestampStringFromRequestDate:self.transaction.startTime];
[detailComponents addObject:timestamp];
if ([timestamp length] > 0) {
[detailComponents addObject:timestamp];
}
// Omit method for GET (assumed as default)
NSString *httpMethod = self.transaction.request.HTTPMethod;
if (httpMethod) {
if ([httpMethod length] > 0) {
[detailComponents addObject:httpMethod];
}
@@ -22,12 +22,8 @@ extern NSString *const kFLEXNetworkObserverEnabledStateChangedNotification;
/// Swizzling occurs when the observer is enabled for the first time.
/// This reduces the impact of FLEX if network debugging is not desired.
/// NOTE: this setting persists between launches of the app.
+ (void)setEnabled:(BOOL)enabled;
+ (BOOL)isEnabled;
/// The enable on launch setting is persisted accross launches of the app.
/// If YES, the observer will automatically enable itself early in the application lifecycle.
+ (void)setShouldEnableOnLaunch:(BOOL)shouldEnableOnLaunch;
+ (BOOL)shouldEnableOnLaunch;
@end
@@ -14,13 +14,14 @@
#import "FLEXNetworkObserver.h"
#import "FLEXNetworkRecorder.h"
#import "FLEXUtility.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import <dispatch/queue.h>
NSString *const kFLEXNetworkObserverEnabledStateChangedNotification = @"kFLEXNetworkObserverEnabledStateChangedNotification";
static NSString *const kFLEXNetworkObserverEnableOnLaunchDefaultsKey = @"com.flex.FLEXNetworkObserver.enableOnLaunch";
static NSString *const kFLEXNetworkObserverEnabledDefaultsKey = @"com.flex.FLEXNetworkObserver.enableOnLaunch";
typedef void (^NSURLSessionAsyncCompletion)(id fileURLOrData, NSURLResponse *response, NSError *error);
@@ -67,7 +68,6 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
@interface FLEXNetworkObserver ()
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;
@property (nonatomic, strong) NSMutableDictionary *requestStatesForRequestIDs;
@property (nonatomic, strong) dispatch_queue_t queue;
@@ -79,43 +79,32 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
+ (void)setEnabled:(BOOL)enabled
{
BOOL previouslyEnabled = [self isEnabled];
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kFLEXNetworkObserverEnabledDefaultsKey];
if (enabled) {
// Inject if needed. This injection is protected with a dispatch_once, so we're ok calling it multiple times.
// By doing the injection lazily, we keep the impact of the tool lower when this feature isn't enabled.
[self injectIntoAllNSURLConnectionDelegateClasses];
}
[[self sharedObserver] setEnabled:enabled];
}
+ (BOOL)isEnabled
{
return [[self sharedObserver] isEnabled];
}
- (void)setEnabled:(BOOL)enabled
{
if (_enabled != enabled) {
_enabled = enabled;
if (previouslyEnabled != enabled) {
[[NSNotificationCenter defaultCenter] postNotificationName:kFLEXNetworkObserverEnabledStateChangedNotification object:self];
}
}
+ (void)setShouldEnableOnLaunch:(BOOL)shouldEnableOnLaunch
+ (BOOL)isEnabled
{
[[NSUserDefaults standardUserDefaults] setBool:shouldEnableOnLaunch forKey:kFLEXNetworkObserverEnableOnLaunchDefaultsKey];
}
+ (BOOL)shouldEnableOnLaunch
{
return [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkObserverEnableOnLaunchDefaultsKey] boolValue];
return [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkObserverEnabledDefaultsKey] boolValue];
}
+ (void)load
{
// We don't want to do the swizzling from +load because not all the classes may be loaded at this point.
dispatch_async(dispatch_get_main_queue(), ^{
if ([self shouldEnableOnLaunch]) {
[self setEnabled:YES];
if ([self isEnabled]) {
[self injectIntoAllNSURLConnectionDelegateClasses];
}
});
}
@@ -139,11 +128,6 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
#pragma mark Delegate Injection Convenience Methods
+ (SEL)swizzledSelectorForSelector:(SEL)selector
{
return NSSelectorFromString([NSString stringWithFormat:@"_flex_swizzle_%x_%@", arc4random(), NSStringFromSelector(selector)]);
}
/// All swizzled delegate methods should make use of this guard.
/// This will prevent duplicated sniffing when the original implementation calls up to a superclass implementation which we've also swizzled.
/// The superclass implementation (and implementations in classes above that) will be executed without inteference if called from the original implementation.
@@ -170,66 +154,6 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
objc_setAssociatedObject(object, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls
{
if ([cls instancesRespondToSelector:selector]) {
unsigned int numMethods = 0;
Method *methods = class_copyMethodList(cls, &numMethods);
BOOL implementsSelector = NO;
for (int index = 0; index < numMethods; index++) {
SEL methodSelector = method_getName(methods[index]);
if (selector == methodSelector) {
implementsSelector = YES;
break;
}
}
free(methods);
if (!implementsSelector) {
return YES;
}
}
return NO;
}
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector
{
// This method is only intended for swizzling methods that are know to exist on the class.
// Bail if that isn't the case.
Method originalMethod = class_getInstanceMethod(class, originalSelector);
if (!originalMethod) {
return;
}
IMP implementation = imp_implementationWithBlock(block);
class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod));
Method newMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, newMethod);
}
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock
{
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
return;
}
IMP implementation = imp_implementationWithBlock((id)([cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock));
Method oldMethod = class_getInstanceMethod(cls, selector);
if (oldMethod) {
class_addMethod(cls, swizzledSelector, implementation, methodDescription.types);
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
method_exchangeImplementations(oldMethod, newMethod);
} else {
class_addMethod(cls, selector, implementation, methodDescription.types);
}
}
#pragma mark - Delegate Injection
+ (void)injectIntoAllNSURLConnectionDelegateClasses
@@ -333,7 +257,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
dispatch_once(&onceToken, ^{
Class class = [NSURLConnection class];
SEL selector = @selector(cancel);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Method originalCancel = class_getInstanceMethod(class, selector);
void (^swizzleBlock)(NSURLConnection *) = ^(NSURLConnection *slf) {
@@ -364,7 +288,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
class = NSClassFromString([@[@"__", @"NSC", @"FURLS", @"ession", @"Task"] componentsJoinedByString:@""]);
}
SEL selector = @selector(resume);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Method originalResume = class_getInstanceMethod(class, selector);
@@ -386,7 +310,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
dispatch_once(&onceToken, ^{
Class class = objc_getMetaClass(class_getName([NSURLConnection class]));
SEL selector = @selector(sendAsynchronousRequest:queue:completionHandler:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
typedef void (^NSURLConnectionAsyncCompletion)(NSURLResponse* response, NSData* data, NSError* connectionError);
@@ -416,7 +340,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}
};
[self replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncSwizzleBlock swizzledSelector:swizzledSelector];
[FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncSwizzleBlock swizzledSelector:swizzledSelector];
});
}
@@ -426,7 +350,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
dispatch_once(&onceToken, ^{
Class class = objc_getMetaClass(class_getName([NSURLConnection class]));
SEL selector = @selector(sendSynchronousRequest:returningResponse:error:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
NSData *(^syncSwizzleBlock)(Class, NSURLRequest *, NSURLResponse **, NSError **) = ^NSData *(Class slf, NSURLRequest *request, NSURLResponse **response, NSError **error) {
NSData *data = nil;
@@ -458,7 +382,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
return data;
};
[self replaceImplementationOfKnownSelector:selector onClass:class withBlock:syncSwizzleBlock swizzledSelector:swizzledSelector];
[FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:syncSwizzleBlock swizzledSelector:swizzledSelector];
});
}
@@ -481,9 +405,9 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) {
SEL selector = selectors[selectorIndex];
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
if ([self instanceRespondsButDoesNotImplementSelector:selector class:class]) {
if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) {
// iOS 7 does not implement these methods on NSURLSession. We actually want to
// swizzle __NSCFURLSession, which we can get from the class of the shared session
class = [[NSURLSession sharedSession] class];
@@ -506,7 +430,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
return task;
};
[self replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncDataOrDownloadSwizzleBlock swizzledSelector:swizzledSelector];
[FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncDataOrDownloadSwizzleBlock swizzledSelector:swizzledSelector];
}
});
}
@@ -528,9 +452,9 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
for (int selectorIndex = 0; selectorIndex < numSelectors; selectorIndex++) {
SEL selector = selectors[selectorIndex];
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
if ([self instanceRespondsButDoesNotImplementSelector:selector class:class]) {
if ([FLEXUtility instanceRespondsButDoesNotImplementSelector:selector class:class]) {
// iOS 7 does not implement these methods on NSURLSession. We actually want to
// swizzle __NSCFURLSession, which we can get from the class of the shared session
class = [[NSURLSession sharedSession] class];
@@ -550,7 +474,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
return task;
};
[self replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncUploadTaskSwizzleBlock swizzledSelector:swizzledSelector];
[FLEXUtility replaceImplementationOfKnownSelector:selector onClass:class withBlock:asyncUploadTaskSwizzleBlock swizzledSelector:swizzledSelector];
}
});
}
@@ -589,7 +513,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
+ (void)injectWillSendRequestIntoDelegateClass:(Class)cls
{
SEL selector = @selector(connection:willSendRequest:redirectResponse:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLConnectionDataDelegate);
if (!protocol) {
@@ -615,13 +539,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
return returnValue;
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDidReceiveResponseIntoDelegateClass:(Class)cls
{
SEL selector = @selector(connection:didReceiveResponse:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLConnectionDataDelegate);
if (!protocol) {
@@ -644,13 +568,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDidReceiveDataIntoDelegateClass:(Class)cls
{
SEL selector = @selector(connection:didReceiveData:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLConnectionDataDelegate);
if (!protocol) {
@@ -673,13 +597,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDidFinishLoadingIntoDelegateClass:(Class)cls
{
SEL selector = @selector(connectionDidFinishLoading:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLConnectionDataDelegate);
if (!protocol) {
@@ -702,13 +626,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDidFailWithErrorIntoDelegateClass:(Class)cls
{
SEL selector = @selector(connection:didFailWithError:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLConnectionDelegate);
struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);
@@ -727,13 +651,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectTaskWillPerformHTTPRedirectionIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionTaskDelegate);
@@ -743,24 +667,25 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
NSURLSessionWillPerformHTTPRedirectionBlock undefinedBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSHTTPURLResponse *response, NSURLRequest *newRequest, void(^completionHandler)(NSURLRequest *)) {
[[FLEXNetworkObserver sharedObserver] URLSession:session task:task willPerformHTTPRedirection:response newRequest:newRequest completionHandler:completionHandler delegate:slf];
completionHandler(newRequest);
};
NSURLSessionWillPerformHTTPRedirectionBlock implementationBlock = ^(id <NSURLSessionTaskDelegate> slf, NSURLSession *session, NSURLSessionTask *task, NSHTTPURLResponse *response, NSURLRequest *newRequest, void(^completionHandler)(NSURLRequest *)) {
[self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{
undefinedBlock(slf, session, task, response, newRequest, completionHandler);
[[FLEXNetworkObserver sharedObserver] URLSession:session task:task willPerformHTTPRedirection:response newRequest:newRequest completionHandler:completionHandler delegate:slf];
} originalImplementationBlock:^{
((id(*)(id, SEL, id, id, id, id, void(^)()))objc_msgSend)(slf, swizzledSelector, session, task, response, newRequest, completionHandler);
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectTaskDidReceiveDataIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:dataTask:didReceiveData:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionDataDelegate);
@@ -780,14 +705,14 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDataTaskDidBecomeDownloadTaskIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:dataTask:didBecomeDownloadTask:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionDataDelegate);
@@ -807,13 +732,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectTaskDidReceiveResponseIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:dataTask:didReceiveResponse:completionHandler:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionDataDelegate);
@@ -823,24 +748,25 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
NSURLSessionDidReceiveResponseBlock undefinedBlock = ^(id <NSURLSessionDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response, void(^completionHandler)(NSURLSessionResponseDisposition disposition)) {
[[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler delegate:slf];
completionHandler(NSURLSessionResponseAllow);
};
NSURLSessionDidReceiveResponseBlock implementationBlock = ^(id <NSURLSessionDelegate> slf, NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response, void(^completionHandler)(NSURLSessionResponseDisposition disposition)) {
[self sniffWithoutDuplicationForObject:session selector:selector sniffingBlock:^{
undefinedBlock(slf, session, dataTask, response, completionHandler);
[[FLEXNetworkObserver sharedObserver] URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler delegate:slf];
} originalImplementationBlock:^{
((void(*)(id, SEL, id, id, id, void(^)()))objc_msgSend)(slf, swizzledSelector, session, dataTask, response, completionHandler);
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectTaskDidCompleteWithErrorIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:task:didCompleteWithError:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionTaskDelegate);
struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);
@@ -859,14 +785,14 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
// Used for overriding AFNetworking behavior
+ (void)injectRespondsToSelectorIntoDelegateClass:(Class)cls
{
SEL selector = @selector(respondsToSelector:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
//Protocol *protocol = @protocol(NSURLSessionTaskDelegate);
Method method = class_getInstanceMethod(cls, selector);
@@ -883,14 +809,14 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
return ((BOOL(*)(id, SEL, SEL))objc_msgSend)(slf, swizzledSelector, sel);
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDownloadTaskDidFinishDownloadingIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:downloadTask:didFinishDownloadingToURL:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionDownloadDelegate);
struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);
@@ -910,13 +836,13 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
+ (void)injectDownloadTaskDidWriteDataIntoDelegateClass:(Class)cls
{
SEL selector = @selector(URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:);
SEL swizzledSelector = [self swizzledSelectorForSelector:selector];
SEL swizzledSelector = [FLEXUtility swizzledSelectorForSelector:selector];
Protocol *protocol = @protocol(NSURLSessionDownloadDelegate);
struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);
@@ -935,7 +861,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id <NSU
}];
};
[self replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
[FLEXUtility replaceImplementationOfSelector:selector withSelector:swizzledSelector forClass:cls withMethodDescription:methodDescription implementationBlock:implementationBlock undefinedBlock:undefinedBlock];
}
@@ -972,14 +898,14 @@ static char const * const kFLEXRequestIDKey = "kFLEXRequestIDKey";
- (void)performBlock:(dispatch_block_t)block
{
if (self.isEnabled) {
if ([[self class] isEnabled]) {
dispatch_async(_queue, block);
}
}
- (FLEXInternalRequestState *)requestStateForRequestID:(NSString *)requestID
{
FLEXInternalRequestState *requestState = [self.requestStatesForRequestIDs objectForKey:requestID];
FLEXInternalRequestState *requestState = self.requestStatesForRequestIDs[requestID];
if (!requestState) {
requestState = [[FLEXInternalRequestState alloc] init];
[self.requestStatesForRequestIDs setObject:requestState forKey:requestID];
@@ -1156,7 +1082,7 @@ static char const * const kFLEXRequestIDKey = "kFLEXRequestIDKey";
FLEXInternalRequestState *requestState = [self requestStateForRequestID:requestID];
if (!requestState.dataAccumulator) {
NSUInteger unsignedBytesExpectedToWrite = totalBytesExpectedToWrite > 0 ? totalBytesExpectedToWrite : 0;
NSUInteger unsignedBytesExpectedToWrite = totalBytesExpectedToWrite > 0 ? (NSUInteger)totalBytesExpectedToWrite : 0;
requestState.dataAccumulator = [[NSMutableData alloc] initWithCapacity:unsignedBytesExpectedToWrite];
[[FLEXNetworkRecorder defaultRecorder] recordResponseReceivedWithRequestID:requestID response:downloadTask.response];
@@ -72,7 +72,7 @@
- (id)detailObjectForRowCookie:(id)rowCookie
{
NSUInteger index = [rowCookie unsignedIntegerValue];
return [self.array objectAtIndex:index];
return self.array[index];
}
@end
@@ -43,7 +43,7 @@
- (NSString *)customSectionSubtitleForRowCookie:(id)rowCookie
{
return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[self.dictionary objectForKey:rowCookie]];
return [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:self.dictionary[rowCookie]];
}
- (BOOL)customSectionCanDrillIntoRowWithCookie:(id)rowCookie
@@ -53,7 +53,7 @@
- (UIViewController *)customSectionDrillInViewControllerForRowCookie:(id)rowCookie
{
return [FLEXObjectExplorerFactory explorerViewControllerForObject:[self.dictionary objectForKey:rowCookie]];
return [FLEXObjectExplorerFactory explorerViewControllerForObject:self.dictionary[rowCookie]];
}
- (BOOL)shouldShowDescription
@@ -50,7 +50,7 @@
for (NSString *objectTypeString in explorerSubclassesForObjectTypeStrings) {
Class objectClass = NSClassFromString(objectTypeString);
if ([object isKindOfClass:objectClass]) {
explorerClass = [explorerSubclassesForObjectTypeStrings objectForKey:objectTypeString];
explorerClass = explorerSubclassesForObjectTypeStrings[objectTypeString];
break;
}
}
@@ -273,7 +273,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
- (NSString *)titleForPropertyAtIndex:(NSInteger)index
{
FLEXPropertyBox *propertyBox = [self.filteredProperties objectAtIndex:index];
FLEXPropertyBox *propertyBox = self.filteredProperties[index];
return [FLEXRuntimeUtility prettyNameForProperty:propertyBox.property];
}
@@ -281,7 +281,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
{
id value = nil;
if ([self canHaveInstanceState]) {
FLEXPropertyBox *propertyBox = [self.filteredProperties objectAtIndex:index];
FLEXPropertyBox *propertyBox = self.filteredProperties[index];
value = [FLEXRuntimeUtility valueForProperty:propertyBox.property onObject:self.object];
}
return value;
@@ -352,7 +352,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
- (NSString *)titleForIvarAtIndex:(NSInteger)index
{
FLEXIvarBox *ivarBox = [self.filteredIvars objectAtIndex:index];
FLEXIvarBox *ivarBox = self.filteredIvars[index];
return [FLEXRuntimeUtility prettyNameForIvar:ivarBox.ivar];
}
@@ -360,7 +360,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
{
id value = nil;
if ([self canHaveInstanceState]) {
FLEXIvarBox *ivarBox = [self.filteredIvars objectAtIndex:index];
FLEXIvarBox *ivarBox = self.filteredIvars[index];
value = [FLEXRuntimeUtility valueForIvar:ivarBox.ivar onObject:self.object];
}
return value;
@@ -451,13 +451,13 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
- (NSString *)titleForMethodAtIndex:(NSInteger)index
{
FLEXMethodBox *methodBox = [self.filteredMethods objectAtIndex:index];
FLEXMethodBox *methodBox = self.filteredMethods[index];
return [FLEXRuntimeUtility prettyNameForMethod:methodBox.method isClassMethod:NO];
}
- (NSString *)titleForClassMethodAtIndex:(NSInteger)index
{
FLEXMethodBox *classMethodBox = [self.filteredClassMethods objectAtIndex:index];
FLEXMethodBox *classMethodBox = self.filteredClassMethods[index];
return [FLEXRuntimeUtility prettyNameForMethod:classMethodBox.method isClassMethod:YES];
}
@@ -612,7 +612,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
break;
case FLEXObjectExplorerSectionSuperclasses:
title = NSStringFromClass([self.filteredSuperclasses objectAtIndex:row]);
title = NSStringFromClass(self.filteredSuperclasses[row]);
break;
case FLEXObjectExplorerSectionReferencingInstances:
@@ -669,7 +669,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
case FLEXObjectExplorerSectionProperties: {
if ([self canHaveInstanceState]) {
FLEXPropertyBox *propertyBox = [self.filteredProperties objectAtIndex:row];
FLEXPropertyBox *propertyBox = self.filteredProperties[row];
objc_property_t property = propertyBox.property;
id currentValue = [self valueForPropertyAtIndex:row];
BOOL canEdit = [FLEXPropertyEditorViewController canEditProperty:property currentValue:currentValue];
@@ -680,7 +680,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
case FLEXObjectExplorerSectionIvars: {
if ([self canHaveInstanceState]) {
FLEXIvarBox *ivarBox = [self.filteredIvars objectAtIndex:row];
FLEXIvarBox *ivarBox = self.filteredIvars[row];
Ivar ivar = ivarBox.ivar;
id currentValue = [self valueForIvarAtIndex:row];
BOOL canEdit = [FLEXIvarEditorViewController canEditIvar:ivar currentValue:currentValue];
@@ -790,7 +790,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
break;
case FLEXObjectExplorerSectionProperties: {
FLEXPropertyBox *propertyBox = [self.filteredProperties objectAtIndex:row];
FLEXPropertyBox *propertyBox = self.filteredProperties[row];
objc_property_t property = propertyBox.property;
id currentValue = [self valueForPropertyAtIndex:row];
if ([FLEXPropertyEditorViewController canEditProperty:property currentValue:currentValue]) {
@@ -801,7 +801,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
} break;
case FLEXObjectExplorerSectionIvars: {
FLEXIvarBox *ivarBox = [self.filteredIvars objectAtIndex:row];
FLEXIvarBox *ivarBox = self.filteredIvars[row];
Ivar ivar = ivarBox.ivar;
id currentValue = [self valueForIvarAtIndex:row];
if ([FLEXIvarEditorViewController canEditIvar:ivar currentValue:currentValue]) {
@@ -812,19 +812,19 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
} break;
case FLEXObjectExplorerSectionMethods: {
FLEXMethodBox *methodBox = [self.filteredMethods objectAtIndex:row];
FLEXMethodBox *methodBox = self.filteredMethods[row];
Method method = methodBox.method;
viewController = [[FLEXMethodCallingViewController alloc] initWithTarget:self.object method:method];
} break;
case FLEXObjectExplorerSectionClassMethods: {
FLEXMethodBox *methodBox = [self.filteredClassMethods objectAtIndex:row];
FLEXMethodBox *methodBox = self.filteredClassMethods[row];
Method method = methodBox.method;
viewController = [[FLEXMethodCallingViewController alloc] initWithTarget:[self.object class] method:method];
} break;
case FLEXObjectExplorerSectionSuperclasses: {
Class superclass = [self.filteredSuperclasses objectAtIndex:row];
Class superclass = self.filteredSuperclasses[row];
viewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:superclass];
} break;
@@ -972,7 +972,7 @@ static const NSInteger kFLEXObjectExplorerScopeIncludeInheritanceIndex = 1;
if ([self.filterText length] > 0) {
filteredIndexSet = [filteredIndexSet indexesPassingTest:^BOOL(NSUInteger index, BOOL *stop) {
BOOL matches = NO;
NSString *rowTitle = [self customSectionTitleForRowCookie:[self.cachedCustomSectionRowCookies objectAtIndex:index]];
NSString *rowTitle = [self customSectionTitleForRowCookie:self.cachedCustomSectionRowCookies[index]];
if ([rowTitle rangeOfString:self.filterText options:NSCaseInsensitiveSearch].location != NSNotFound) {
matches = YES;
}
@@ -15,7 +15,8 @@
typedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {
FLEXViewExplorerRowViewController,
FLEXViewExplorerRowPreview
FLEXViewExplorerRowPreview,
FLEXViewExplorerRowViewControllerForAncestor
};
@interface FLEXViewExplorerViewController ()
@@ -46,6 +47,8 @@ typedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {
if ([FLEXUtility viewControllerForView:self.viewToExplore]) {
[rowCookies addObject:@(FLEXViewExplorerRowViewController)];
}else{
[rowCookies addObject:@(FLEXViewExplorerRowViewControllerForAncestor)];
}
[rowCookies addObject:@(FLEXViewExplorerRowPreview)];
@@ -79,6 +82,10 @@ typedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {
case FLEXViewExplorerRowPreview:
title = @"Preview Image";
break;
case FLEXViewExplorerRowViewControllerForAncestor:
title = @"View Controller For Ancestor";
break;
}
} else if ([rowCookie isKindOfClass:[NSString class]]) {
objc_property_t property = [self viewPropertyForName:rowCookie];
@@ -105,6 +112,10 @@ typedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {
case FLEXViewExplorerRowPreview:
break;
case FLEXViewExplorerRowViewControllerForAncestor:
subtitle = [FLEXRuntimeUtility descriptionForIvarOrPropertyValue:[FLEXUtility viewControllerForAncestralView:self.viewToExplore]];
break;
}
} else if ([rowCookie isKindOfClass:[NSString class]]) {
objc_property_t property = [self viewPropertyForName:rowCookie];
@@ -141,6 +152,10 @@ typedef NS_ENUM(NSUInteger, FLEXViewExplorerRow) {
case FLEXViewExplorerRowPreview:
drillInViewController = [[self class] imagePreviewViewControllerForView:self.viewToExplore];
break;
case FLEXViewExplorerRowViewControllerForAncestor:
drillInViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:[FLEXUtility viewControllerForAncestralView:self.viewToExplore]];
break;
}
} else if ([rowCookie isKindOfClass:[NSString class]]) {
objc_property_t property = [self viewPropertyForName:rowCookie];
+12 -10
View File
@@ -20,12 +20,6 @@ typedef struct {
@implementation FLEXHeapEnumerator
static kern_return_t memory_reader(task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory)
{
*local_memory = (void *)remote_address;
return KERN_SUCCESS;
}
static void range_callback(task_t task, void *context, unsigned type, vm_range_t *ranges, unsigned rangeCount)
{
flex_object_enumeration_block_t block = (__bridge flex_object_enumeration_block_t)context;
@@ -51,6 +45,12 @@ static void range_callback(task_t task, void *context, unsigned type, vm_range_t
}
}
static kern_return_t reader(__unused task_t remote_task, vm_address_t remote_address, __unused vm_size_t size, void **local_memory)
{
*local_memory = (void *)remote_address;
return KERN_SUCCESS;
}
+ (void)enumerateLiveObjectsUsingBlock:(flex_object_enumeration_block_t)block
{
if (!block) {
@@ -60,17 +60,19 @@ static void range_callback(task_t task, void *context, unsigned type, vm_range_t
// Refresh the class list on every call in case classes are added to the runtime.
[self updateRegisteredClasses];
// For another exmple of enumerating through malloc ranges (which helped my understanding of the api) see:
// Inspired by:
// http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final/examples/darwin/heap_find/heap/heap_find.cpp
// Also https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396
// https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396
vm_address_t *zones = NULL;
unsigned int zoneCount = 0;
kern_return_t result = malloc_get_all_zones(mach_task_self(), &memory_reader, &zones, &zoneCount);
kern_return_t result = malloc_get_all_zones(TASK_NULL, reader, &zones, &zoneCount);
if (result == KERN_SUCCESS) {
for (unsigned int i = 0; i < zoneCount; i++) {
malloc_zone_t *zone = (malloc_zone_t *)zones[i];
if (zone->introspect && zone->introspect->enumerator) {
zone->introspect->enumerator(mach_task_self(), (__bridge void *)(block), MALLOC_PTR_IN_USE_RANGE_TYPE, zones[i], &memory_reader, &range_callback);
zone->introspect->enumerator(TASK_NULL, (__bridge void *)block, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, reader, &range_callback);
}
}
}
@@ -0,0 +1,13 @@
//
// FLEXKeyboardHelpViewController.h
// UICatalog
//
// Created by Ryan Olson on 9/19/15.
// Copyright © 2015 f. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FLEXKeyboardHelpViewController : UIViewController
@end
@@ -0,0 +1,44 @@
//
// FLEXKeyboardHelpViewController.m
// UICatalog
//
// Created by Ryan Olson on 9/19/15.
// Copyright © 2015 f. All rights reserved.
//
#import "FLEXKeyboardHelpViewController.h"
#import "FLEXKeyboardShortcutManager.h"
@interface FLEXKeyboardHelpViewController ()
@property (nonatomic, strong) UITextView *textView;
@end
@implementation FLEXKeyboardHelpViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.textView];
#if TARGET_OS_SIMULATOR
self.textView.text = [[FLEXKeyboardShortcutManager sharedManager] keyboardShortcutsDescription];
#endif
self.textView.backgroundColor = [UIColor blackColor];
self.textView.textColor = [UIColor whiteColor];
self.textView.font = [UIFont boldSystemFontOfSize:14.0];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.title = @"Simulator Shortcuts";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)];
}
- (void)donePressed:(id)sender
{
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
@end
@@ -0,0 +1,24 @@
//
// FLEXKeyboardShortcutManager.h
// FLEX
//
// Created by Ryan Olson on 9/19/15.
// Copyright © 2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
#if TARGET_OS_SIMULATOR
@interface FLEXKeyboardShortcutManager : NSObject
+ (instancetype)sharedManager;
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description;
- (NSString *)keyboardShortcutsDescription;
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;
@end
#endif
@@ -0,0 +1,306 @@
//
// FLEXKeyboardShortcutManager.m
// FLEX
//
// Created by Ryan Olson on 9/19/15.
// Copyright © 2015 Flipboard. All rights reserved.
//
#import "FLEXKeyboardShortcutManager.h"
#import "FLEXUtility.h"
#import <objc/runtime.h>
#import <objc/message.h>
#if TARGET_OS_SIMULATOR
@interface UIEvent (UIPhysicalKeyboardEvent)
@property (nonatomic, strong) NSString *_modifiedInput;
@property (nonatomic, strong) NSString *_unmodifiedInput;
@property (nonatomic, assign) UIKeyModifierFlags _modifierFlags;
@property (nonatomic, assign) BOOL _isKeyDown;
@property (nonatomic, assign) long _keyCode;
@end
@interface FLEXKeyInput : NSObject <NSCopying>
@property (nonatomic, copy, readonly) NSString *key;
@property (nonatomic, assign, readonly) UIKeyModifierFlags flags;
@property (nonatomic, copy, readonly) NSString *helpDescription;
@end
@implementation FLEXKeyInput
- (BOOL)isEqual:(id)object
{
BOOL isEqual = NO;
if ([object isKindOfClass:[FLEXKeyInput class]]) {
FLEXKeyInput *keyCommand = (FLEXKeyInput *)object;
BOOL equalKeys = self.key == keyCommand.key || [self.key isEqual:keyCommand.key];
BOOL equalFlags = self.flags == keyCommand.flags;
isEqual = equalKeys && equalFlags;
}
return isEqual;
}
- (NSUInteger)hash
{
return [self.key hash] ^ self.flags;
}
- (id)copyWithZone:(NSZone *)zone
{
return [[self class] keyInputForKey:self.key flags:self.flags helpDescription:self.helpDescription];
}
- (NSString *)description
{
NSDictionary *keyMappings = @{ UIKeyInputUpArrow : @"",
UIKeyInputDownArrow : @"",
UIKeyInputLeftArrow : @"",
UIKeyInputRightArrow : @"",
UIKeyInputEscape : @"",
@" " : @""};
NSString *prettyKey = nil;
if (self.key && keyMappings[self.key]) {
prettyKey = keyMappings[self.key];
} else {
prettyKey = [self.key uppercaseString];
}
NSString *prettyFlags = @"";
if (self.flags & UIKeyModifierControl) {
prettyFlags = [prettyFlags stringByAppendingString:@""];
}
if (self.flags & UIKeyModifierAlternate) {
prettyFlags = [prettyFlags stringByAppendingString:@""];
}
if (self.flags & UIKeyModifierShift) {
prettyFlags = [prettyFlags stringByAppendingString:@""];
}
if (self.flags & UIKeyModifierCommand) {
prettyFlags = [prettyFlags stringByAppendingString:@""];
}
// Fudging to get easy columns with tabs
if ([prettyFlags length] < 2) {
prettyKey = [prettyKey stringByAppendingString:@"\t"];
}
return [NSString stringWithFormat:@"%@%@\t%@", prettyFlags, prettyKey, self.helpDescription];
}
+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags
{
return [self keyInputForKey:key flags:flags helpDescription:nil];
}
+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags helpDescription:(NSString *)helpDescription
{
FLEXKeyInput *keyInput = [[self alloc] init];
if (keyInput) {
keyInput->_key = key;
keyInput->_flags = flags;
keyInput->_helpDescription = helpDescription;
}
return keyInput;
}
@end
@interface FLEXKeyboardShortcutManager ()
@property (nonatomic, strong) NSMutableDictionary *actionsForKeyInputs;
@property (nonatomic, assign, getter=isPressingShift) BOOL pressingShift;
@property (nonatomic, assign, getter=isPressingCommand) BOOL pressingCommand;
@property (nonatomic, assign, getter=isPressingControl) BOOL pressingControl;
@end
@implementation FLEXKeyboardShortcutManager
+ (instancetype)sharedManager
{
static FLEXKeyboardShortcutManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[[self class] alloc] init];
});
return sharedManager;
}
+ (void)load
{
SEL originalKeyEventSelector = NSSelectorFromString(@"handleKeyUIEvent:");
SEL swizzledKeyEventSelector = [FLEXUtility swizzledSelectorForSelector:originalKeyEventSelector];
void (^handleKeyUIEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {
[[[self class] sharedManager] handleKeyboardEvent:event];
((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledKeyEventSelector, event);
};
[FLEXUtility replaceImplementationOfKnownSelector:originalKeyEventSelector onClass:[UIApplication class] withBlock:handleKeyUIEventSwizzleBlock swizzledSelector:swizzledKeyEventSelector];
if ([[UITouch class] instancesRespondToSelector:@selector(maximumPossibleForce)]) {
SEL originalSendEventSelector = NSSelectorFromString(@"sendEvent:");
SEL swizzledSendEventSelector = [FLEXUtility swizzledSelectorForSelector:originalSendEventSelector];
void (^sendEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {
if (event.type == UIEventTypeTouches) {
FLEXKeyboardShortcutManager *keyboardManager = [FLEXKeyboardShortcutManager sharedManager];
NSInteger pressureLevel = 0;
if (keyboardManager.isPressingShift) {
pressureLevel++;
}
if (keyboardManager.isPressingCommand) {
pressureLevel++;
}
if (keyboardManager.isPressingControl) {
pressureLevel++;
}
if (pressureLevel > 0) {
for (UITouch *touch in [event allTouches]) {
double adjustedPressureLevel = pressureLevel * 20 * touch.maximumPossibleForce;
[touch setValue:@(adjustedPressureLevel) forKey:@"_pressure"];
}
}
}
((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledSendEventSelector, event);
};
[FLEXUtility replaceImplementationOfKnownSelector:originalSendEventSelector onClass:[UIApplication class] withBlock:sendEventSwizzleBlock swizzledSelector:swizzledSendEventSelector];
SEL originalSupportsTouchPressureSelector = NSSelectorFromString(@"_supportsForceTouch");
SEL swizzledSupportsTouchPressureSelector = [FLEXUtility swizzledSelectorForSelector:originalSupportsTouchPressureSelector];
BOOL (^supportsTouchPressureSwizzleBlock)(UIDevice *) = ^BOOL(UIDevice *slf) {
return YES;
};
[FLEXUtility replaceImplementationOfKnownSelector:originalSupportsTouchPressureSelector onClass:[UIDevice class] withBlock:supportsTouchPressureSwizzleBlock swizzledSelector:swizzledSupportsTouchPressureSelector];
}
}
- (instancetype)init
{
self = [super init];
if (self) {
_actionsForKeyInputs = [NSMutableDictionary dictionary];
_enabled = YES;
}
return self;
}
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description
{
FLEXKeyInput *keyInput = [FLEXKeyInput keyInputForKey:key flags:modifiers helpDescription:description];
[self.actionsForKeyInputs setObject:action forKey:keyInput];
}
static const long kFLEXControlKeyCode = 0xe0;
static const long kFLEXShiftKeyCode = 0xe1;
static const long kFLEXCommandKeyCode = 0xe3;
- (void)handleKeyboardEvent:(UIEvent *)event
{
if (!self.enabled) {
return;
}
NSString *modifiedInput = nil;
NSString *unmodifiedInput = nil;
UIKeyModifierFlags flags = 0;
BOOL isKeyDown = NO;
if ([event respondsToSelector:@selector(_modifiedInput)]) {
modifiedInput = [event _modifiedInput];
}
if ([event respondsToSelector:@selector(_unmodifiedInput)]) {
unmodifiedInput = [event _unmodifiedInput];
}
if ([event respondsToSelector:@selector(_modifierFlags)]) {
flags = [event _modifierFlags];
}
if ([event respondsToSelector:@selector(_isKeyDown)]) {
isKeyDown = [event _isKeyDown];
}
BOOL interactionEnabled = ![[UIApplication sharedApplication] isIgnoringInteractionEvents];
BOOL hasFirstResponder = NO;
if (isKeyDown && [modifiedInput length] > 0 && interactionEnabled) {
UIResponder *firstResponder = nil;
for (UIWindow *window in [FLEXUtility allWindows]) {
firstResponder = [window valueForKey:@"firstResponder"];
if (firstResponder) {
hasFirstResponder = YES;
break;
}
}
// Ignore key commands (except escape) when there's an active responder
if (firstResponder) {
if ([unmodifiedInput isEqual:UIKeyInputEscape]) {
[firstResponder resignFirstResponder];
}
} else {
FLEXKeyInput *exactMatch = [FLEXKeyInput keyInputForKey:unmodifiedInput flags:flags];
dispatch_block_t actionBlock = self.actionsForKeyInputs[exactMatch];
if (!actionBlock) {
FLEXKeyInput *shiftMatch = [FLEXKeyInput keyInputForKey:modifiedInput flags:flags&(!UIKeyModifierShift)];
actionBlock = self.actionsForKeyInputs[shiftMatch];
}
if (!actionBlock) {
FLEXKeyInput *capitalMatch = [FLEXKeyInput keyInputForKey:[unmodifiedInput uppercaseString] flags:flags];
actionBlock = self.actionsForKeyInputs[capitalMatch];
}
if (actionBlock) {
actionBlock();
}
}
}
// Calling _keyCode on events from the simulator keyboard will crash.
// It is only safe to call _keyCode when there's not an active responder.
if (!hasFirstResponder && [event respondsToSelector:@selector(_keyCode)]) {
long keyCode = [event _keyCode];
if (keyCode == kFLEXControlKeyCode) {
self.pressingControl = isKeyDown;
} else if (keyCode == kFLEXCommandKeyCode) {
self.pressingCommand = isKeyDown;
} else if (keyCode == kFLEXShiftKeyCode) {
self.pressingShift = isKeyDown;
}
}
}
- (NSString *)keyboardShortcutsDescription
{
NSMutableString *description = [NSMutableString string];
NSArray *keyInputs = [[self.actionsForKeyInputs allKeys] sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *_Nonnull input1, FLEXKeyInput *_Nonnull input2) {
return [input1.key caseInsensitiveCompare:input2.key];
}];
for (FLEXKeyInput *keyInput in keyInputs) {
[description appendFormat:@"%@\n", keyInput];
}
return [description copy];
}
@end
#endif
+14 -14
View File
@@ -49,7 +49,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
+ (NSString *)typeEncodingForProperty:(objc_property_t)property
{
NSDictionary *attributesDictionary = [self attributesDictionaryForProperty:property];
return [attributesDictionary objectForKey:kFLEXUtilityAttributeTypeEncoding];
return attributesDictionary[kFLEXUtilityAttributeTypeEncoding];
}
+ (BOOL)isReadonlyProperty:(objc_property_t)property
@@ -77,33 +77,33 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
NSMutableArray *attributesStrings = [NSMutableArray array];
// Atomicity
if ([attributesDictionary objectForKey:kFLEXUtilityAttributeNonAtomic]) {
if (attributesDictionary[kFLEXUtilityAttributeNonAtomic]) {
[attributesStrings addObject:@"nonatomic"];
} else {
[attributesStrings addObject:@"atomic"];
}
// Storage
if ([attributesDictionary objectForKey:kFLEXUtilityAttributeRetain]) {
if (attributesDictionary[kFLEXUtilityAttributeRetain]) {
[attributesStrings addObject:@"strong"];
} else if ([attributesDictionary objectForKey:kFLEXUtilityAttributeCopy]) {
} else if (attributesDictionary[kFLEXUtilityAttributeCopy]) {
[attributesStrings addObject:@"copy"];
} else if ([attributesDictionary objectForKey:kFLEXUtilityAttributeWeak]) {
} else if (attributesDictionary[kFLEXUtilityAttributeWeak]) {
[attributesStrings addObject:@"weak"];
} else {
[attributesStrings addObject:@"assign"];
}
// Mutability
if ([attributesDictionary objectForKey:kFLEXUtilityAttributeReadOnly]) {
if (attributesDictionary[kFLEXUtilityAttributeReadOnly]) {
[attributesStrings addObject:@"readonly"];
} else {
[attributesStrings addObject:@"readwrite"];
}
// Custom getter/setter
NSString *customGetter = [attributesDictionary objectForKey:kFLEXUtilityAttributeCustomGetter];
NSString *customSetter = [attributesDictionary objectForKey:kFLEXUtilityAttributeCustomSetter];
NSString *customGetter = attributesDictionary[kFLEXUtilityAttributeCustomGetter];
NSString *customSetter = attributesDictionary[kFLEXUtilityAttributeCustomSetter];
if (customGetter) {
[attributesStrings addObject:[NSString stringWithFormat:@"getter=%@", customGetter]];
}
@@ -179,7 +179,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
for (NSString *attributeName in [attributePairs allKeys]) {
objc_property_attribute_t attribute;
attribute.name = [attributeName UTF8String];
attribute.value = [[attributePairs objectForKey:attributeName] UTF8String];
attribute.value = [attributePairs[attributeName] UTF8String];
attributes[attributeIndex++] = attribute;
}
@@ -209,7 +209,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
#ifdef __arm64__
// See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html
const char *name = ivar_getName(ivar);
if (type[0] == @encode(Class)[0] && strcmp(name, "isa") != 0) {
if (type[0] == @encode(Class)[0] && strcmp(name, "isa") == 0) {
value = object_getClass(object);
} else
#endif
@@ -316,7 +316,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
NSUInteger numberOfArguments = [methodSignature numberOfArguments];
for (NSUInteger argumentIndex = kFLEXNumberOfImplicitArgs; argumentIndex < numberOfArguments; argumentIndex++) {
NSUInteger argumentsArrayIndex = argumentIndex - kFLEXNumberOfImplicitArgs;
id argumentObject = [arguments count] > argumentsArrayIndex ? [arguments objectAtIndex:argumentsArrayIndex] : nil;
id argumentObject = [arguments count] > argumentsArrayIndex ? arguments[argumentsArrayIndex] : nil;
// NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil.
if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) {
@@ -436,9 +436,9 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
NSString *editableDescription = nil;
if (object) {
// This is a hack to use JSON serialzation for our editable objects.
// This is a hack to use JSON serialization for our editable objects.
// NSJSONSerialization doesn't allow writing fragments - the top level object must be an array or dictionary.
// We always wrap the object inside an array and then strip the outter square braces off the final string.
// We always wrap the object inside an array and then strip the outer square braces off the final string.
NSArray *wrappedObject = @[object];
if ([NSJSONSerialization isValidJSONObject:wrappedObject]) {
NSString *wrappedDescription = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:wrappedObject options:0 error:NULL] encoding:NSUTF8StringEncoding];
@@ -674,7 +674,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
+ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type
{
// CASE marcro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html
// CASE macro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html
#define CASE(ctype, selectorpart) \
if(strcmp(type, @encode(ctype)) == 0) { \
return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \
+11
View File
@@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#define FLEXFloor(x) (floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])
@@ -17,6 +18,7 @@
+ (NSString *)descriptionForView:(UIView *)view includingFrame:(BOOL)includeFrame;
+ (NSString *)stringForCGRect:(CGRect)rect;
+ (UIViewController *)viewControllerForView:(UIView *)view;
+ (UIViewController *)viewControllerForAncestralView:(UIView *)view;
+ (NSString *)detailDescriptionForView:(UIView *)view;
+ (UIImage *)circularImageWithColor:(UIColor *)color radius:(CGFloat)radius;
+ (UIColor *)scrollViewGrayColor;
@@ -38,4 +40,13 @@
+ (BOOL)isValidJSONData:(NSData *)data;
+ (NSData *)inflatedDataFromCompressedData:(NSData *)compressedData;
+ (NSArray *)allWindows;
// Swizzling utilities
+ (SEL)swizzledSelectorForSelector:(SEL)selector;
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls;
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock;
@end
+105 -5
View File
@@ -10,6 +10,7 @@
#import "FLEXResources.h"
#import <ImageIO/ImageIO.h>
#import <zlib.h>
#import <objc/runtime.h>
@implementation FLEXUtility
@@ -57,6 +58,18 @@
return viewController;
}
+ (UIViewController *)viewControllerForAncestralView:(UIView *)view{
UIViewController *viewController = nil;
SEL viewDelSel = NSSelectorFromString([NSString stringWithFormat:@"%@ewControllerForAncestor", @"_vi"]);
if ([view respondsToSelector:viewDelSel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
viewController = [view performSelector:viewDelSel];
#pragma clang diagnostic pop
}
return viewController;
}
+ (NSString *)detailDescriptionForView:(UIView *)view
{
return [NSString stringWithFormat:@"frame %@", [self stringForCGRect:view.frame]];
@@ -92,12 +105,12 @@
+ (NSString *)applicationImageName
{
return [[NSBundle mainBundle] executablePath];
return [NSBundle mainBundle].executablePath;
}
+ (NSString *)applicationName
{
return [[[FLEXUtility applicationImageName] componentsSeparatedByString:@"/"] lastObject];
return [FLEXUtility applicationImageName].lastPathComponent;
}
+ (NSString *)safeDescriptionForObject:(id)object
@@ -246,11 +259,11 @@
// [a, 1]
NSArray *components = [keyValueString componentsSeparatedByString:@"="];
if ([components count] == 2) {
NSString *key = [[components firstObject] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
id value = [[components lastObject] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *key = [[components firstObject] stringByRemovingPercentEncoding];
id value = [[components lastObject] stringByRemovingPercentEncoding];
// Handle multiple entries under the same key as an array
id existingEntry = [queryDictionary objectForKey:key];
id existingEntry = queryDictionary[key];
if (existingEntry) {
if ([existingEntry isKindOfClass:[NSArray class]]) {
value = [existingEntry arrayByAddingObject:value];
@@ -325,4 +338,91 @@
return inflatedData;
}
+ (NSArray *)allWindows
{
BOOL includeInternalWindows = YES;
BOOL onlyVisibleWindows = NO;
NSArray *allWindowsComponents = @[@"al", @"lWindo", @"wsIncl", @"udingInt", @"ernalWin", @"dows:o", @"nlyVisi", @"bleWin", @"dows:"];
SEL allWindowsSelector = NSSelectorFromString([allWindowsComponents componentsJoinedByString:@""]);
NSMethodSignature *methodSignature = [[UIWindow class] methodSignatureForSelector:allWindowsSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
invocation.target = [UIWindow class];
invocation.selector = allWindowsSelector;
[invocation setArgument:&includeInternalWindows atIndex:2];
[invocation setArgument:&onlyVisibleWindows atIndex:3];
[invocation invoke];
__unsafe_unretained NSArray *windows = nil;
[invocation getReturnValue:&windows];
return windows;
}
+ (SEL)swizzledSelectorForSelector:(SEL)selector
{
return NSSelectorFromString([NSString stringWithFormat:@"_flex_swizzle_%x_%@", arc4random(), NSStringFromSelector(selector)]);
}
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls
{
if ([cls instancesRespondToSelector:selector]) {
unsigned int numMethods = 0;
Method *methods = class_copyMethodList(cls, &numMethods);
BOOL implementsSelector = NO;
for (int index = 0; index < numMethods; index++) {
SEL methodSelector = method_getName(methods[index]);
if (selector == methodSelector) {
implementsSelector = YES;
break;
}
}
free(methods);
if (!implementsSelector) {
return YES;
}
}
return NO;
}
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector
{
// This method is only intended for swizzling methods that are know to exist on the class.
// Bail if that isn't the case.
Method originalMethod = class_getInstanceMethod(class, originalSelector);
if (!originalMethod) {
return;
}
IMP implementation = imp_implementationWithBlock(block);
class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod));
Method newMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, newMethod);
}
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock
{
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
return;
}
IMP implementation = imp_implementationWithBlock((id)([cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock));
Method oldMethod = class_getInstanceMethod(cls, selector);
if (oldMethod) {
class_addMethod(cls, swizzledSelector, implementation, methodDescription.types);
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
method_exchangeImplementations(oldMethod, newMethod);
} else {
class_addMethod(cls, selector, implementation, methodDescription.types);
}
}
@end
@@ -106,7 +106,10 @@ static const NSInteger kFLEXHierarchyScopeFullHierarchyIndex = 1;
if ([self.searchBar.text length] > 0) {
self.displayedViews = [candidateViews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIView *candidateView, NSDictionary *bindings) {
NSString *title = [FLEXUtility descriptionForView:candidateView includingFrame:NO];
return [title rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch].location != NSNotFound;
NSString *candidateViewPointerAddress = [NSString stringWithFormat:@"%p", candidateView];
BOOL matchedViewPointerAddress = [candidateViewPointerAddress rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch].location != NSNotFound;
BOOL matchedViewTitle = [title rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch].location != NSNotFound;
return matchedViewPointerAddress || matchedViewTitle;
}]];
} else {
self.displayedViews = candidateViews;
@@ -162,7 +165,7 @@ static const NSInteger kFLEXHierarchyScopeFullHierarchyIndex = 1;
cell = [[FLEXHierarchyTableViewCell alloc] initWithReuseIdentifier:CellIdentifier];
}
UIView *view = [self.displayedViews objectAtIndex:indexPath.row];
UIView *view = self.displayedViews[indexPath.row];
NSNumber *depth = [self.depthsForViews objectForKey:[NSValue valueWithNonretainedObject:view]];
UIColor *viewColor = [FLEXUtility consistentRandomColorForObject:view];
cell.textLabel.text = [FLEXUtility descriptionForView:view includingFrame:NO];
@@ -182,13 +185,13 @@ static const NSInteger kFLEXHierarchyScopeFullHierarchyIndex = 1;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedView = [self.displayedViews objectAtIndex:indexPath.row];
self.selectedView = self.displayedViews[indexPath.row];
[self.delegate hierarchyViewController:self didFinishWithSelectedView:self.selectedView];
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
UIView *drillInView = [self.displayedViews objectAtIndex:indexPath.row];
UIView *drillInView = self.displayedViews[indexPath.row];
FLEXObjectExplorerViewController *viewExplorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:drillInView];
[self.navigationController pushViewController:viewExplorer animated:YES];
}
+58 -499
View File
@@ -7,8 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
0149BFE2198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0149BFE1198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m */; };
01985ABC1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 01985ABB1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.m */; };
22679D581C74188D002248FC /* Dog.m in Sources */ = {isa = PBXBuildFile; fileRef = 22679D571C74188D002248FC /* Dog.m */; };
22679D5C1C7418B6002248FC /* Owner.m in Sources */ = {isa = PBXBuildFile; fileRef = 22679D5B1C7418B6002248FC /* Owner.m */; };
22679D5D1C741A7A002248FC /* dogs.realm in Resources */ = {isa = PBXBuildFile; fileRef = 22679D551C741764002248FC /* dogs.realm */; };
3EC6487318FF8A5000024205 /* ReadMe.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3EC6487218FF8A5000024205 /* ReadMe.txt */; };
5356823E18F3656900BAAD62 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5356823D18F3656900BAAD62 /* Foundation.framework */; };
5356824018F3656900BAAD62 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5356823F18F3656900BAAD62 /* CoreGraphics.framework */; };
@@ -43,77 +44,31 @@
535682BE18F3670300BAAD62 /* AAPLWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 535682A418F3670300BAAD62 /* AAPLWebViewController.m */; };
535682BF18F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m in Sources */ = {isa = PBXBuildFile; fileRef = 535682A618F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m */; };
53874F9918F36B1800510922 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53874F9718F36B1800510922 /* Localizable.strings */; };
650855EB1A9007D5006109A1 /* FLEXArgumentInputDateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 650855EA1A9007D5006109A1 /* FLEXArgumentInputDateView.m */; };
65F8DC6C1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */; };
9421B88D1A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B8801A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.m */; };
9421B88E1A8BBCB200BA3E46 /* FLEXNetworkRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B8821A8BBCB200BA3E46 /* FLEXNetworkRecorder.m */; };
9421B88F1A8BBCB200BA3E46 /* FLEXNetworkTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B8841A8BBCB200BA3E46 /* FLEXNetworkTransaction.m */; };
9421B8901A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B8861A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.m */; };
9421B8911A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B8881A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.m */; };
9421B8921A8BBCB200BA3E46 /* FLEXNetworkObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 9421B88B1A8BBCB200BA3E46 /* FLEXNetworkObserver.m */; };
9421B8931A8BBCB200BA3E46 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 9421B88C1A8BBCB200BA3E46 /* LICENSE */; };
779B1EF51C0C4F25001F5E49 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 779B1EF41C0C4F25001F5E49 /* libsqlite3.dylib */; };
9420A1AD1C1E84EE00B587DF /* FLEX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9420A1AC1C1E84EE00B587DF /* FLEX.framework */; };
943203FE1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 943203FD1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m */; };
944F7489197B458C009AB039 /* FLEXArrayExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7426197B458C009AB039 /* FLEXArrayExplorerViewController.m */; };
944F748A197B458C009AB039 /* FLEXClassExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7428197B458C009AB039 /* FLEXClassExplorerViewController.m */; };
944F748B197B458C009AB039 /* FLEXDefaultsExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F742A197B458C009AB039 /* FLEXDefaultsExplorerViewController.m */; };
944F748D197B458C009AB039 /* FLEXDictionaryExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F742E197B458C009AB039 /* FLEXDictionaryExplorerViewController.m */; };
944F748E197B458C009AB039 /* FLEXImageExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7430197B458C009AB039 /* FLEXImageExplorerViewController.m */; };
944F748F197B458C009AB039 /* FLEXObjectExplorerFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7432197B458C009AB039 /* FLEXObjectExplorerFactory.m */; };
944F7490197B458C009AB039 /* FLEXObjectExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7434197B458C009AB039 /* FLEXObjectExplorerViewController.m */; };
944F7491197B458C009AB039 /* FLEXSetExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7436197B458C009AB039 /* FLEXSetExplorerViewController.m */; };
944F7492197B458C009AB039 /* FLEXViewControllerExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7438197B458C009AB039 /* FLEXViewControllerExplorerViewController.m */; };
944F7493197B458C009AB039 /* FLEXViewExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F743A197B458C009AB039 /* FLEXViewExplorerViewController.m */; };
944F7494197B458C009AB039 /* FLEXHeapEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F743D197B458C009AB039 /* FLEXHeapEnumerator.m */; };
944F7495197B458C009AB039 /* FLEXResources.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F743F197B458C009AB039 /* FLEXResources.m */; };
944F7496197B458C009AB039 /* FLEXRuntimeUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7441197B458C009AB039 /* FLEXRuntimeUtility.m */; };
944F7497197B458C009AB039 /* FLEXUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7443197B458C009AB039 /* FLEXUtility.m */; };
944F7498197B458C009AB039 /* FLEXArgumentInputColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7447197B458C009AB039 /* FLEXArgumentInputColorView.m */; };
944F7499197B458C009AB039 /* FLEXArgumentInputFontView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7449197B458C009AB039 /* FLEXArgumentInputFontView.m */; };
944F749A197B458C009AB039 /* FLEXArgumentInputJSONObjectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F744B197B458C009AB039 /* FLEXArgumentInputJSONObjectView.m */; };
944F749B197B458C009AB039 /* FLEXArgumentInputNotSupportedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F744D197B458C009AB039 /* FLEXArgumentInputNotSupportedView.m */; };
944F749C197B458C009AB039 /* FLEXArgumentInputNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F744F197B458C009AB039 /* FLEXArgumentInputNumberView.m */; };
944F749D197B458C009AB039 /* FLEXArgumentInputStringView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7451197B458C009AB039 /* FLEXArgumentInputStringView.m */; };
944F749E197B458C009AB039 /* FLEXArgumentInputStructView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7453197B458C009AB039 /* FLEXArgumentInputStructView.m */; };
944F749F197B458C009AB039 /* FLEXArgumentInputSwitchView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7455197B458C009AB039 /* FLEXArgumentInputSwitchView.m */; };
944F74A0197B458C009AB039 /* FLEXArgumentInputTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7457197B458C009AB039 /* FLEXArgumentInputTextView.m */; };
944F74A1197B458C009AB039 /* FLEXArgumentInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7459197B458C009AB039 /* FLEXArgumentInputView.m */; };
944F74A2197B458C009AB039 /* FLEXArgumentInputViewFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F745B197B458C009AB039 /* FLEXArgumentInputViewFactory.m */; };
944F74A3197B458C009AB039 /* FLEXDefaultEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F745D197B458C009AB039 /* FLEXDefaultEditorViewController.m */; };
944F74A4197B458C009AB039 /* FLEXFieldEditorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F745F197B458C009AB039 /* FLEXFieldEditorView.m */; };
944F74A5197B458C009AB039 /* FLEXFieldEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7461197B458C009AB039 /* FLEXFieldEditorViewController.m */; };
944F74A6197B458C009AB039 /* FLEXIvarEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7463197B458C009AB039 /* FLEXIvarEditorViewController.m */; };
944F74A7197B458C009AB039 /* FLEXMethodCallingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7465197B458C009AB039 /* FLEXMethodCallingViewController.m */; };
944F74A8197B458C009AB039 /* FLEXPropertyEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7467197B458C009AB039 /* FLEXPropertyEditorViewController.m */; };
944F74A9197B458C009AB039 /* FLEXExplorerToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F746A197B458C009AB039 /* FLEXExplorerToolbar.m */; };
944F74AA197B458C009AB039 /* FLEXExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F746C197B458C009AB039 /* FLEXExplorerViewController.m */; };
944F74AB197B458C009AB039 /* FLEXManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F746E197B458C009AB039 /* FLEXManager.m */; };
944F74AC197B458C009AB039 /* FLEXToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7470197B458C009AB039 /* FLEXToolbarItem.m */; };
944F74AD197B458C009AB039 /* FLEXWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7472197B458C009AB039 /* FLEXWindow.m */; };
944F74AE197B458C009AB039 /* FLEXClassesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7475197B458C009AB039 /* FLEXClassesTableViewController.m */; };
944F74AF197B458C009AB039 /* FLEXFileBrowserTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7477197B458C009AB039 /* FLEXFileBrowserTableViewController.m */; };
944F74B0197B458C009AB039 /* FLEXGlobalsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7479197B458C009AB039 /* FLEXGlobalsTableViewController.m */; };
944F74B1197B458C009AB039 /* FLEXInstancesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F747B197B458C009AB039 /* FLEXInstancesTableViewController.m */; };
944F74B2197B458C009AB039 /* FLEXLibrariesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F747D197B458C009AB039 /* FLEXLibrariesTableViewController.m */; };
944F74B3197B458C009AB039 /* FLEXLiveObjectsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F747F197B458C009AB039 /* FLEXLiveObjectsTableViewController.m */; };
944F74B4197B458C009AB039 /* FLEXWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7481197B458C009AB039 /* FLEXWebViewController.m */; };
944F74B5197B458C009AB039 /* FLEXHierarchyTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7484197B458C009AB039 /* FLEXHierarchyTableViewCell.m */; };
944F74B6197B458C009AB039 /* FLEXHierarchyTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7486197B458C009AB039 /* FLEXHierarchyTableViewController.m */; };
944F74B7197B458C009AB039 /* FLEXImagePreviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7488197B458C009AB039 /* FLEXImagePreviewViewController.m */; };
946C6EC91A7598D3006545C2 /* FLEXSystemLogTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 946C6EC81A7598D3006545C2 /* FLEXSystemLogTableViewCell.m */; };
946C6ECC1A759928006545C2 /* FLEXSystemLogTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 946C6ECA1A759928006545C2 /* FLEXSystemLogTableViewController.m */; };
946C6ECF1A7599C4006545C2 /* FLEXSystemLogMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 946C6ECE1A7599C4006545C2 /* FLEXSystemLogMessage.m */; };
94C681F31A3E941800E1936D /* FLEXLayerExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94C681F21A3E941800E1936D /* FLEXLayerExplorerViewController.m */; };
94CB48391A8EC6000054A905 /* FLEXMultilineTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 94CB48381A8EC6000054A905 /* FLEXMultilineTableViewCell.m */; };
94CB4D431A97183E0054A905 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 94CB4D421A97183E0054A905 /* libz.dylib */; };
94CB4D4F1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94CB4D4E1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.m */; };
D03647D919847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = D03647D819847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
22679D691C742141002248FC /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0149BFE0198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserSearchOperation.h; sourceTree = "<group>"; };
0149BFE1198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserSearchOperation.m; sourceTree = "<group>"; };
01985ABA1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputFontsPickerView.h; sourceTree = "<group>"; };
01985ABB1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputFontsPickerView.m; sourceTree = "<group>"; };
22679D551C741764002248FC /* dogs.realm */ = {isa = PBXFileReference; lastKnownFileType = file; path = dogs.realm; sourceTree = "<group>"; };
22679D561C74188D002248FC /* Dog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dog.h; sourceTree = "<group>"; };
22679D571C74188D002248FC /* Dog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Dog.m; sourceTree = "<group>"; };
22679D5A1C7418B6002248FC /* Owner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Owner.h; sourceTree = "<group>"; };
22679D5B1C7418B6002248FC /* Owner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Owner.m; sourceTree = "<group>"; };
3EC6487218FF8A5000024205 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadMe.txt; sourceTree = SOURCE_ROOT; };
5356823A18F3656900BAAD62 /* UICatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UICatalog.app; sourceTree = BUILT_PRODUCTS_DIR; };
5356823D18F3656900BAAD62 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -176,133 +131,11 @@
535682A518F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+AAPLApplicationSpecific.h"; sourceTree = "<group>"; };
535682A618F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+AAPLApplicationSpecific.m"; sourceTree = "<group>"; };
53874F9818F36B1800510922 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
650855E91A9007D5006109A1 /* FLEXArgumentInputDateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputDateView.h; sourceTree = "<group>"; };
650855EA1A9007D5006109A1 /* FLEXArgumentInputDateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputDateView.m; sourceTree = "<group>"; };
65F8DC6A1A8F11020076F87B /* FLEXFileBrowserFileOperationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserFileOperationController.h; sourceTree = "<group>"; };
65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserFileOperationController.m; sourceTree = "<group>"; };
9421B87F1A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkHistoryTableViewController.h; sourceTree = "<group>"; };
9421B8801A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkHistoryTableViewController.m; sourceTree = "<group>"; };
9421B8811A8BBCB200BA3E46 /* FLEXNetworkRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkRecorder.h; sourceTree = "<group>"; };
9421B8821A8BBCB200BA3E46 /* FLEXNetworkRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkRecorder.m; sourceTree = "<group>"; };
9421B8831A8BBCB200BA3E46 /* FLEXNetworkTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransaction.h; sourceTree = "<group>"; };
9421B8841A8BBCB200BA3E46 /* FLEXNetworkTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransaction.m; sourceTree = "<group>"; };
9421B8851A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransactionDetailTableViewController.h; sourceTree = "<group>"; };
9421B8861A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransactionDetailTableViewController.m; sourceTree = "<group>"; };
9421B8871A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkTransactionTableViewCell.h; sourceTree = "<group>"; };
9421B8881A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkTransactionTableViewCell.m; sourceTree = "<group>"; };
9421B88A1A8BBCB200BA3E46 /* FLEXNetworkObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkObserver.h; sourceTree = "<group>"; };
9421B88B1A8BBCB200BA3E46 /* FLEXNetworkObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkObserver.m; sourceTree = "<group>"; };
9421B88C1A8BBCB200BA3E46 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
779B1EF41C0C4F25001F5E49 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = ../../../../../../usr/lib/libsqlite3.dylib; sourceTree = "<group>"; };
9420A1AC1C1E84EE00B587DF /* FLEX.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FLEX.framework; path = "../../../Library/Developer/Xcode/DerivedData/FLEX-gixtctkeshzdbwbdapvulcvleeiu/Build/Products/Debug-iphoneos/FLEX.framework"; sourceTree = "<group>"; };
943203FC1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AAPLCatalogTableTableViewController.h; sourceTree = "<group>"; };
943203FD1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AAPLCatalogTableTableViewController.m; sourceTree = "<group>"; };
944F7425197B458C009AB039 /* FLEXArrayExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArrayExplorerViewController.h; sourceTree = "<group>"; };
944F7426197B458C009AB039 /* FLEXArrayExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArrayExplorerViewController.m; sourceTree = "<group>"; };
944F7427197B458C009AB039 /* FLEXClassExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassExplorerViewController.h; sourceTree = "<group>"; };
944F7428197B458C009AB039 /* FLEXClassExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassExplorerViewController.m; sourceTree = "<group>"; };
944F7429197B458C009AB039 /* FLEXDefaultsExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDefaultsExplorerViewController.h; sourceTree = "<group>"; };
944F742A197B458C009AB039 /* FLEXDefaultsExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDefaultsExplorerViewController.m; sourceTree = "<group>"; };
944F742D197B458C009AB039 /* FLEXDictionaryExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDictionaryExplorerViewController.h; sourceTree = "<group>"; };
944F742E197B458C009AB039 /* FLEXDictionaryExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDictionaryExplorerViewController.m; sourceTree = "<group>"; };
944F742F197B458C009AB039 /* FLEXImageExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXImageExplorerViewController.h; sourceTree = "<group>"; };
944F7430197B458C009AB039 /* FLEXImageExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXImageExplorerViewController.m; sourceTree = "<group>"; };
944F7431197B458C009AB039 /* FLEXObjectExplorerFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXObjectExplorerFactory.h; sourceTree = "<group>"; };
944F7432197B458C009AB039 /* FLEXObjectExplorerFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectExplorerFactory.m; sourceTree = "<group>"; };
944F7433197B458C009AB039 /* FLEXObjectExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXObjectExplorerViewController.h; sourceTree = "<group>"; };
944F7434197B458C009AB039 /* FLEXObjectExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXObjectExplorerViewController.m; sourceTree = "<group>"; };
944F7435197B458C009AB039 /* FLEXSetExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSetExplorerViewController.h; sourceTree = "<group>"; };
944F7436197B458C009AB039 /* FLEXSetExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSetExplorerViewController.m; sourceTree = "<group>"; };
944F7437197B458C009AB039 /* FLEXViewControllerExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXViewControllerExplorerViewController.h; sourceTree = "<group>"; };
944F7438197B458C009AB039 /* FLEXViewControllerExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewControllerExplorerViewController.m; sourceTree = "<group>"; };
944F7439197B458C009AB039 /* FLEXViewExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXViewExplorerViewController.h; sourceTree = "<group>"; };
944F743A197B458C009AB039 /* FLEXViewExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewExplorerViewController.m; sourceTree = "<group>"; };
944F743C197B458C009AB039 /* FLEXHeapEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHeapEnumerator.h; sourceTree = "<group>"; };
944F743D197B458C009AB039 /* FLEXHeapEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHeapEnumerator.m; sourceTree = "<group>"; };
944F743E197B458C009AB039 /* FLEXResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXResources.h; sourceTree = "<group>"; };
944F743F197B458C009AB039 /* FLEXResources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXResources.m; sourceTree = "<group>"; };
944F7440197B458C009AB039 /* FLEXRuntimeUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRuntimeUtility.h; sourceTree = "<group>"; };
944F7441197B458C009AB039 /* FLEXRuntimeUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRuntimeUtility.m; sourceTree = "<group>"; };
944F7442197B458C009AB039 /* FLEXUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXUtility.h; sourceTree = "<group>"; };
944F7443197B458C009AB039 /* FLEXUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXUtility.m; sourceTree = "<group>"; };
944F7446197B458C009AB039 /* FLEXArgumentInputColorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputColorView.h; sourceTree = "<group>"; };
944F7447197B458C009AB039 /* FLEXArgumentInputColorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputColorView.m; sourceTree = "<group>"; };
944F7448197B458C009AB039 /* FLEXArgumentInputFontView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputFontView.h; sourceTree = "<group>"; };
944F7449197B458C009AB039 /* FLEXArgumentInputFontView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputFontView.m; sourceTree = "<group>"; };
944F744A197B458C009AB039 /* FLEXArgumentInputJSONObjectView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputJSONObjectView.h; sourceTree = "<group>"; };
944F744B197B458C009AB039 /* FLEXArgumentInputJSONObjectView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputJSONObjectView.m; sourceTree = "<group>"; };
944F744C197B458C009AB039 /* FLEXArgumentInputNotSupportedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputNotSupportedView.h; sourceTree = "<group>"; };
944F744D197B458C009AB039 /* FLEXArgumentInputNotSupportedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputNotSupportedView.m; sourceTree = "<group>"; };
944F744E197B458C009AB039 /* FLEXArgumentInputNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputNumberView.h; sourceTree = "<group>"; };
944F744F197B458C009AB039 /* FLEXArgumentInputNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputNumberView.m; sourceTree = "<group>"; };
944F7450197B458C009AB039 /* FLEXArgumentInputStringView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputStringView.h; sourceTree = "<group>"; };
944F7451197B458C009AB039 /* FLEXArgumentInputStringView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputStringView.m; sourceTree = "<group>"; };
944F7452197B458C009AB039 /* FLEXArgumentInputStructView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputStructView.h; sourceTree = "<group>"; };
944F7453197B458C009AB039 /* FLEXArgumentInputStructView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputStructView.m; sourceTree = "<group>"; };
944F7454197B458C009AB039 /* FLEXArgumentInputSwitchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputSwitchView.h; sourceTree = "<group>"; };
944F7455197B458C009AB039 /* FLEXArgumentInputSwitchView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputSwitchView.m; sourceTree = "<group>"; };
944F7456197B458C009AB039 /* FLEXArgumentInputTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputTextView.h; sourceTree = "<group>"; };
944F7457197B458C009AB039 /* FLEXArgumentInputTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputTextView.m; sourceTree = "<group>"; };
944F7458197B458C009AB039 /* FLEXArgumentInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputView.h; sourceTree = "<group>"; };
944F7459197B458C009AB039 /* FLEXArgumentInputView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputView.m; sourceTree = "<group>"; };
944F745A197B458C009AB039 /* FLEXArgumentInputViewFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputViewFactory.h; sourceTree = "<group>"; };
944F745B197B458C009AB039 /* FLEXArgumentInputViewFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputViewFactory.m; sourceTree = "<group>"; };
944F745C197B458C009AB039 /* FLEXDefaultEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDefaultEditorViewController.h; sourceTree = "<group>"; };
944F745D197B458C009AB039 /* FLEXDefaultEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXDefaultEditorViewController.m; sourceTree = "<group>"; };
944F745E197B458C009AB039 /* FLEXFieldEditorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFieldEditorView.h; sourceTree = "<group>"; };
944F745F197B458C009AB039 /* FLEXFieldEditorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFieldEditorView.m; sourceTree = "<group>"; };
944F7460197B458C009AB039 /* FLEXFieldEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFieldEditorViewController.h; sourceTree = "<group>"; };
944F7461197B458C009AB039 /* FLEXFieldEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFieldEditorViewController.m; sourceTree = "<group>"; };
944F7462197B458C009AB039 /* FLEXIvarEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXIvarEditorViewController.h; sourceTree = "<group>"; };
944F7463197B458C009AB039 /* FLEXIvarEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXIvarEditorViewController.m; sourceTree = "<group>"; };
944F7464197B458C009AB039 /* FLEXMethodCallingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMethodCallingViewController.h; sourceTree = "<group>"; };
944F7465197B458C009AB039 /* FLEXMethodCallingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMethodCallingViewController.m; sourceTree = "<group>"; };
944F7466197B458C009AB039 /* FLEXPropertyEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXPropertyEditorViewController.h; sourceTree = "<group>"; };
944F7467197B458C009AB039 /* FLEXPropertyEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXPropertyEditorViewController.m; sourceTree = "<group>"; };
944F7469197B458C009AB039 /* FLEXExplorerToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerToolbar.h; sourceTree = "<group>"; };
944F746A197B458C009AB039 /* FLEXExplorerToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerToolbar.m; sourceTree = "<group>"; };
944F746B197B458C009AB039 /* FLEXExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerViewController.h; sourceTree = "<group>"; };
944F746C197B458C009AB039 /* FLEXExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerViewController.m; sourceTree = "<group>"; };
944F746D197B458C009AB039 /* FLEXManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXManager.h; sourceTree = "<group>"; };
944F746E197B458C009AB039 /* FLEXManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXManager.m; sourceTree = "<group>"; };
944F746F197B458C009AB039 /* FLEXToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXToolbarItem.h; sourceTree = "<group>"; };
944F7470197B458C009AB039 /* FLEXToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXToolbarItem.m; sourceTree = "<group>"; };
944F7471197B458C009AB039 /* FLEXWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXWindow.h; sourceTree = "<group>"; };
944F7472197B458C009AB039 /* FLEXWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXWindow.m; sourceTree = "<group>"; };
944F7474197B458C009AB039 /* FLEXClassesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassesTableViewController.h; sourceTree = "<group>"; };
944F7475197B458C009AB039 /* FLEXClassesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassesTableViewController.m; sourceTree = "<group>"; };
944F7476197B458C009AB039 /* FLEXFileBrowserTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserTableViewController.h; sourceTree = "<group>"; };
944F7477197B458C009AB039 /* FLEXFileBrowserTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserTableViewController.m; sourceTree = "<group>"; };
944F7478197B458C009AB039 /* FLEXGlobalsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXGlobalsTableViewController.h; sourceTree = "<group>"; };
944F7479197B458C009AB039 /* FLEXGlobalsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXGlobalsTableViewController.m; sourceTree = "<group>"; };
944F747A197B458C009AB039 /* FLEXInstancesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXInstancesTableViewController.h; sourceTree = "<group>"; };
944F747B197B458C009AB039 /* FLEXInstancesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXInstancesTableViewController.m; sourceTree = "<group>"; };
944F747C197B458C009AB039 /* FLEXLibrariesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLibrariesTableViewController.h; sourceTree = "<group>"; };
944F747D197B458C009AB039 /* FLEXLibrariesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLibrariesTableViewController.m; sourceTree = "<group>"; };
944F747E197B458C009AB039 /* FLEXLiveObjectsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLiveObjectsTableViewController.h; sourceTree = "<group>"; };
944F747F197B458C009AB039 /* FLEXLiveObjectsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLiveObjectsTableViewController.m; sourceTree = "<group>"; };
944F7480197B458C009AB039 /* FLEXWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXWebViewController.h; sourceTree = "<group>"; };
944F7481197B458C009AB039 /* FLEXWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXWebViewController.m; sourceTree = "<group>"; };
944F7483197B458C009AB039 /* FLEXHierarchyTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHierarchyTableViewCell.h; sourceTree = "<group>"; };
944F7484197B458C009AB039 /* FLEXHierarchyTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHierarchyTableViewCell.m; sourceTree = "<group>"; };
944F7485197B458C009AB039 /* FLEXHierarchyTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXHierarchyTableViewController.h; sourceTree = "<group>"; };
944F7486197B458C009AB039 /* FLEXHierarchyTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXHierarchyTableViewController.m; sourceTree = "<group>"; };
944F7487197B458C009AB039 /* FLEXImagePreviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXImagePreviewViewController.h; sourceTree = "<group>"; };
944F7488197B458C009AB039 /* FLEXImagePreviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXImagePreviewViewController.m; sourceTree = "<group>"; };
946C6EC71A7598D3006545C2 /* FLEXSystemLogTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogTableViewCell.h; sourceTree = "<group>"; };
946C6EC81A7598D3006545C2 /* FLEXSystemLogTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogTableViewCell.m; sourceTree = "<group>"; };
946C6ECA1A759928006545C2 /* FLEXSystemLogTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogTableViewController.m; sourceTree = "<group>"; };
946C6ECB1A759928006545C2 /* FLEXSystemLogTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogTableViewController.h; sourceTree = "<group>"; };
946C6ECD1A7599C4006545C2 /* FLEXSystemLogMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSystemLogMessage.h; sourceTree = "<group>"; };
946C6ECE1A7599C4006545C2 /* FLEXSystemLogMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSystemLogMessage.m; sourceTree = "<group>"; };
94C681F11A3E941800E1936D /* FLEXLayerExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXLayerExplorerViewController.h; sourceTree = "<group>"; };
94C681F21A3E941800E1936D /* FLEXLayerExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXLayerExplorerViewController.m; sourceTree = "<group>"; };
94CB48371A8EC6000054A905 /* FLEXMultilineTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMultilineTableViewCell.h; sourceTree = "<group>"; };
94CB48381A8EC6000054A905 /* FLEXMultilineTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMultilineTableViewCell.m; sourceTree = "<group>"; };
94CB4D421A97183E0054A905 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
94CB4D4D1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkSettingsTableViewController.h; sourceTree = "<group>"; };
94CB4D4E1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkSettingsTableViewController.m; sourceTree = "<group>"; };
D03647D51984720F007D2A1B /* FLEXManager+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FLEXManager+Private.h"; sourceTree = "<group>"; };
D03647D719847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXGlobalsTableViewControllerEntry.h; sourceTree = "<group>"; };
D03647D819847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXGlobalsTableViewControllerEntry.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -310,6 +143,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9420A1AD1C1E84EE00B587DF /* FLEX.framework in Frameworks */,
779B1EF51C0C4F25001F5E49 /* libsqlite3.dylib in Frameworks */,
94CB4D431A97183E0054A905 /* libz.dylib in Frameworks */,
5356824018F3656900BAAD62 /* CoreGraphics.framework in Frameworks */,
5356824218F3656900BAAD62 /* UIKit.framework in Frameworks */,
@@ -320,12 +155,23 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
22679D591C741891002248FC /* Realm */ = {
isa = PBXGroup;
children = (
22679D551C741764002248FC /* dogs.realm */,
22679D561C74188D002248FC /* Dog.h */,
22679D571C74188D002248FC /* Dog.m */,
22679D5A1C7418B6002248FC /* Owner.h */,
22679D5B1C7418B6002248FC /* Owner.m */,
);
name = Realm;
sourceTree = "<group>";
};
5356823118F3656900BAAD62 = {
isa = PBXGroup;
children = (
3EC6487218FF8A5000024205 /* ReadMe.txt */,
5356824318F3656900BAAD62 /* UICatalog */,
943203FF1978F4B700E24DB3 /* 3rd Party */,
5356823C18F3656900BAAD62 /* Frameworks */,
5356823B18F3656900BAAD62 /* Products */,
);
@@ -342,6 +188,8 @@
5356823C18F3656900BAAD62 /* Frameworks */ = {
isa = PBXGroup;
children = (
9420A1AC1C1E84EE00B587DF /* FLEX.framework */,
779B1EF41C0C4F25001F5E49 /* libsqlite3.dylib */,
94CB4D421A97183E0054A905 /* libz.dylib */,
5356823D18F3656900BAAD62 /* Foundation.framework */,
5356823F18F3656900BAAD62 /* CoreGraphics.framework */,
@@ -436,6 +284,7 @@
53874F9A18F36B6900510922 /* Application */ = {
isa = PBXGroup;
children = (
22679D591C741891002248FC /* Realm */,
5356824918F3656900BAAD62 /* main.m */,
5356827B18F3670300BAAD62 /* AAPLAppDelegate.h */,
5356827C18F3670300BAAD62 /* AAPLAppDelegate.m */,
@@ -447,223 +296,6 @@
name = Application;
sourceTree = "<group>";
};
9421B87E1A8BBCB200BA3E46 /* Network */ = {
isa = PBXGroup;
children = (
9421B87F1A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.h */,
9421B8801A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.m */,
94CB4D4D1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.h */,
94CB4D4E1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.m */,
9421B8811A8BBCB200BA3E46 /* FLEXNetworkRecorder.h */,
9421B8821A8BBCB200BA3E46 /* FLEXNetworkRecorder.m */,
9421B8831A8BBCB200BA3E46 /* FLEXNetworkTransaction.h */,
9421B8841A8BBCB200BA3E46 /* FLEXNetworkTransaction.m */,
9421B8851A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.h */,
9421B8861A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.m */,
9421B8871A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.h */,
9421B8881A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.m */,
9421B8891A8BBCB200BA3E46 /* PonyDebugger */,
);
name = Network;
path = ../Classes/Network;
sourceTree = "<group>";
};
9421B8891A8BBCB200BA3E46 /* PonyDebugger */ = {
isa = PBXGroup;
children = (
9421B88A1A8BBCB200BA3E46 /* FLEXNetworkObserver.h */,
9421B88B1A8BBCB200BA3E46 /* FLEXNetworkObserver.m */,
9421B88C1A8BBCB200BA3E46 /* LICENSE */,
);
path = PonyDebugger;
sourceTree = "<group>";
};
943203FF1978F4B700E24DB3 /* 3rd Party */ = {
isa = PBXGroup;
children = (
943204001978F4C100E24DB3 /* FLEX */,
);
name = "3rd Party";
sourceTree = "<group>";
};
943204001978F4C100E24DB3 /* FLEX */ = {
isa = PBXGroup;
children = (
9421B87E1A8BBCB200BA3E46 /* Network */,
944F7424197B458C009AB039 /* Object Explorers */,
944F743B197B458C009AB039 /* Utility */,
944F7444197B458C009AB039 /* Editing */,
944F7468197B458C009AB039 /* Explorer Toolbar */,
944F7473197B458C009AB039 /* Global State Explorers */,
944F7482197B458C009AB039 /* View Hierarchy */,
);
name = FLEX;
sourceTree = "<group>";
};
944F7424197B458C009AB039 /* Object Explorers */ = {
isa = PBXGroup;
children = (
944F7425197B458C009AB039 /* FLEXArrayExplorerViewController.h */,
944F7426197B458C009AB039 /* FLEXArrayExplorerViewController.m */,
944F7427197B458C009AB039 /* FLEXClassExplorerViewController.h */,
944F7428197B458C009AB039 /* FLEXClassExplorerViewController.m */,
944F7429197B458C009AB039 /* FLEXDefaultsExplorerViewController.h */,
944F742A197B458C009AB039 /* FLEXDefaultsExplorerViewController.m */,
944F742D197B458C009AB039 /* FLEXDictionaryExplorerViewController.h */,
944F742E197B458C009AB039 /* FLEXDictionaryExplorerViewController.m */,
944F742F197B458C009AB039 /* FLEXImageExplorerViewController.h */,
944F7430197B458C009AB039 /* FLEXImageExplorerViewController.m */,
944F7431197B458C009AB039 /* FLEXObjectExplorerFactory.h */,
944F7432197B458C009AB039 /* FLEXObjectExplorerFactory.m */,
944F7433197B458C009AB039 /* FLEXObjectExplorerViewController.h */,
944F7434197B458C009AB039 /* FLEXObjectExplorerViewController.m */,
944F7435197B458C009AB039 /* FLEXSetExplorerViewController.h */,
944F7436197B458C009AB039 /* FLEXSetExplorerViewController.m */,
944F7437197B458C009AB039 /* FLEXViewControllerExplorerViewController.h */,
944F7438197B458C009AB039 /* FLEXViewControllerExplorerViewController.m */,
944F7439197B458C009AB039 /* FLEXViewExplorerViewController.h */,
944F743A197B458C009AB039 /* FLEXViewExplorerViewController.m */,
94C681F11A3E941800E1936D /* FLEXLayerExplorerViewController.h */,
94C681F21A3E941800E1936D /* FLEXLayerExplorerViewController.m */,
D03647D619847235007D2A1B /* Private */,
);
name = "Object Explorers";
path = ../Classes/ObjectExplorers;
sourceTree = "<group>";
};
944F743B197B458C009AB039 /* Utility */ = {
isa = PBXGroup;
children = (
944F743C197B458C009AB039 /* FLEXHeapEnumerator.h */,
944F743D197B458C009AB039 /* FLEXHeapEnumerator.m */,
944F743E197B458C009AB039 /* FLEXResources.h */,
944F743F197B458C009AB039 /* FLEXResources.m */,
944F7440197B458C009AB039 /* FLEXRuntimeUtility.h */,
944F7441197B458C009AB039 /* FLEXRuntimeUtility.m */,
944F7442197B458C009AB039 /* FLEXUtility.h */,
944F7443197B458C009AB039 /* FLEXUtility.m */,
94CB48371A8EC6000054A905 /* FLEXMultilineTableViewCell.h */,
94CB48381A8EC6000054A905 /* FLEXMultilineTableViewCell.m */,
);
name = Utility;
path = ../Classes/Utility;
sourceTree = "<group>";
};
944F7444197B458C009AB039 /* Editing */ = {
isa = PBXGroup;
children = (
944F7445197B458C009AB039 /* Argument Input Views */,
944F745C197B458C009AB039 /* FLEXDefaultEditorViewController.h */,
944F745D197B458C009AB039 /* FLEXDefaultEditorViewController.m */,
944F745E197B458C009AB039 /* FLEXFieldEditorView.h */,
944F745F197B458C009AB039 /* FLEXFieldEditorView.m */,
944F7460197B458C009AB039 /* FLEXFieldEditorViewController.h */,
944F7461197B458C009AB039 /* FLEXFieldEditorViewController.m */,
944F7462197B458C009AB039 /* FLEXIvarEditorViewController.h */,
944F7463197B458C009AB039 /* FLEXIvarEditorViewController.m */,
944F7464197B458C009AB039 /* FLEXMethodCallingViewController.h */,
944F7465197B458C009AB039 /* FLEXMethodCallingViewController.m */,
944F7466197B458C009AB039 /* FLEXPropertyEditorViewController.h */,
944F7467197B458C009AB039 /* FLEXPropertyEditorViewController.m */,
);
name = Editing;
path = ../Classes/Editing;
sourceTree = "<group>";
};
944F7445197B458C009AB039 /* Argument Input Views */ = {
isa = PBXGroup;
children = (
944F7446197B458C009AB039 /* FLEXArgumentInputColorView.h */,
944F7447197B458C009AB039 /* FLEXArgumentInputColorView.m */,
650855E91A9007D5006109A1 /* FLEXArgumentInputDateView.h */,
650855EA1A9007D5006109A1 /* FLEXArgumentInputDateView.m */,
944F7448197B458C009AB039 /* FLEXArgumentInputFontView.h */,
944F7449197B458C009AB039 /* FLEXArgumentInputFontView.m */,
944F744A197B458C009AB039 /* FLEXArgumentInputJSONObjectView.h */,
944F744B197B458C009AB039 /* FLEXArgumentInputJSONObjectView.m */,
944F744C197B458C009AB039 /* FLEXArgumentInputNotSupportedView.h */,
944F744D197B458C009AB039 /* FLEXArgumentInputNotSupportedView.m */,
944F744E197B458C009AB039 /* FLEXArgumentInputNumberView.h */,
944F744F197B458C009AB039 /* FLEXArgumentInputNumberView.m */,
944F7450197B458C009AB039 /* FLEXArgumentInputStringView.h */,
944F7451197B458C009AB039 /* FLEXArgumentInputStringView.m */,
01985ABA1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.h */,
01985ABB1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.m */,
944F7452197B458C009AB039 /* FLEXArgumentInputStructView.h */,
944F7453197B458C009AB039 /* FLEXArgumentInputStructView.m */,
944F7454197B458C009AB039 /* FLEXArgumentInputSwitchView.h */,
944F7455197B458C009AB039 /* FLEXArgumentInputSwitchView.m */,
944F7456197B458C009AB039 /* FLEXArgumentInputTextView.h */,
944F7457197B458C009AB039 /* FLEXArgumentInputTextView.m */,
944F7458197B458C009AB039 /* FLEXArgumentInputView.h */,
944F7459197B458C009AB039 /* FLEXArgumentInputView.m */,
944F745A197B458C009AB039 /* FLEXArgumentInputViewFactory.h */,
944F745B197B458C009AB039 /* FLEXArgumentInputViewFactory.m */,
);
name = "Argument Input Views";
path = ArgumentInputViews;
sourceTree = "<group>";
};
944F7468197B458C009AB039 /* Explorer Toolbar */ = {
isa = PBXGroup;
children = (
944F7469197B458C009AB039 /* FLEXExplorerToolbar.h */,
944F746A197B458C009AB039 /* FLEXExplorerToolbar.m */,
944F746B197B458C009AB039 /* FLEXExplorerViewController.h */,
944F746C197B458C009AB039 /* FLEXExplorerViewController.m */,
944F746D197B458C009AB039 /* FLEXManager.h */,
944F746E197B458C009AB039 /* FLEXManager.m */,
D03647D51984720F007D2A1B /* FLEXManager+Private.h */,
944F746F197B458C009AB039 /* FLEXToolbarItem.h */,
944F7470197B458C009AB039 /* FLEXToolbarItem.m */,
944F7471197B458C009AB039 /* FLEXWindow.h */,
944F7472197B458C009AB039 /* FLEXWindow.m */,
);
name = "Explorer Toolbar";
path = ../Classes/ExplorerToolbar;
sourceTree = "<group>";
};
944F7473197B458C009AB039 /* Global State Explorers */ = {
isa = PBXGroup;
children = (
946C6EC61A75986C006545C2 /* System Log */,
944F7474197B458C009AB039 /* FLEXClassesTableViewController.h */,
944F7475197B458C009AB039 /* FLEXClassesTableViewController.m */,
944F7476197B458C009AB039 /* FLEXFileBrowserTableViewController.h */,
944F7477197B458C009AB039 /* FLEXFileBrowserTableViewController.m */,
65F8DC6A1A8F11020076F87B /* FLEXFileBrowserFileOperationController.h */,
65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */,
0149BFE0198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.h */,
0149BFE1198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m */,
944F7478197B458C009AB039 /* FLEXGlobalsTableViewController.h */,
944F7479197B458C009AB039 /* FLEXGlobalsTableViewController.m */,
944F747A197B458C009AB039 /* FLEXInstancesTableViewController.h */,
944F747B197B458C009AB039 /* FLEXInstancesTableViewController.m */,
944F747C197B458C009AB039 /* FLEXLibrariesTableViewController.h */,
944F747D197B458C009AB039 /* FLEXLibrariesTableViewController.m */,
944F747E197B458C009AB039 /* FLEXLiveObjectsTableViewController.h */,
944F747F197B458C009AB039 /* FLEXLiveObjectsTableViewController.m */,
944F7480197B458C009AB039 /* FLEXWebViewController.h */,
944F7481197B458C009AB039 /* FLEXWebViewController.m */,
);
name = "Global State Explorers";
path = ../Classes/GlobalStateExplorers;
sourceTree = "<group>";
};
944F7482197B458C009AB039 /* View Hierarchy */ = {
isa = PBXGroup;
children = (
944F7483197B458C009AB039 /* FLEXHierarchyTableViewCell.h */,
944F7484197B458C009AB039 /* FLEXHierarchyTableViewCell.m */,
944F7485197B458C009AB039 /* FLEXHierarchyTableViewController.h */,
944F7486197B458C009AB039 /* FLEXHierarchyTableViewController.m */,
944F7487197B458C009AB039 /* FLEXImagePreviewViewController.h */,
944F7488197B458C009AB039 /* FLEXImagePreviewViewController.m */,
);
name = "View Hierarchy";
path = ../Classes/ViewHierarchy;
sourceTree = "<group>";
};
944F74B8197B46D2009AB039 /* FLEX Integration */ = {
isa = PBXGroup;
children = (
@@ -673,29 +305,6 @@
name = "FLEX Integration";
sourceTree = "<group>";
};
946C6EC61A75986C006545C2 /* System Log */ = {
isa = PBXGroup;
children = (
946C6ECB1A759928006545C2 /* FLEXSystemLogTableViewController.h */,
946C6ECA1A759928006545C2 /* FLEXSystemLogTableViewController.m */,
946C6ECD1A7599C4006545C2 /* FLEXSystemLogMessage.h */,
946C6ECE1A7599C4006545C2 /* FLEXSystemLogMessage.m */,
946C6EC71A7598D3006545C2 /* FLEXSystemLogTableViewCell.h */,
946C6EC81A7598D3006545C2 /* FLEXSystemLogTableViewCell.m */,
);
name = "System Log";
path = SystemLog;
sourceTree = "<group>";
};
D03647D619847235007D2A1B /* Private */ = {
isa = PBXGroup;
children = (
D03647D719847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.h */,
D03647D819847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.m */,
);
name = Private;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -706,6 +315,7 @@
5356823618F3656900BAAD62 /* Sources */,
5356823718F3656900BAAD62 /* Frameworks */,
5356823818F3656900BAAD62 /* Resources */,
22679D691C742141002248FC /* Embed Frameworks */,
);
buildRules = (
);
@@ -748,7 +358,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9421B8931A8BBCB200BA3E46 /* LICENSE in Resources */,
22679D5D1C741A7A002248FC /* dogs.realm in Resources */,
5356825418F3656900BAAD62 /* Main_iPad.storyboard in Resources */,
53874F9918F36B1800510922 /* Localizable.strings in Resources */,
5356825918F3656900BAAD62 /* Images.xcassets in Resources */,
@@ -764,95 +374,34 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
944F749B197B458C009AB039 /* FLEXArgumentInputNotSupportedView.m in Sources */,
22679D5C1C7418B6002248FC /* Owner.m in Sources */,
535682AE18F3670300BAAD62 /* AAPLDatePickerController.m in Sources */,
946C6ECC1A759928006545C2 /* FLEXSystemLogTableViewController.m in Sources */,
946C6ECF1A7599C4006545C2 /* FLEXSystemLogMessage.m in Sources */,
535682AB18F3670300BAAD62 /* AAPLButtonViewController.m in Sources */,
944F74A2197B458C009AB039 /* FLEXArgumentInputViewFactory.m in Sources */,
944F74A1197B458C009AB039 /* FLEXArgumentInputView.m in Sources */,
535682B618F3670300BAAD62 /* AAPLSegmentedControlViewController.m in Sources */,
944F74AE197B458C009AB039 /* FLEXClassesTableViewController.m in Sources */,
944F74B1197B458C009AB039 /* FLEXInstancesTableViewController.m in Sources */,
944F7497197B458C009AB039 /* FLEXUtility.m in Sources */,
535682B018F3670300BAAD62 /* AAPLDefaultToolbarViewController.m in Sources */,
94CB48391A8EC6000054A905 /* FLEXMultilineTableViewCell.m in Sources */,
535682BD18F3670300BAAD62 /* AAPLTintedToolbarViewController.m in Sources */,
943203FE1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m in Sources */,
9421B8921A8BBCB200BA3E46 /* FLEXNetworkObserver.m in Sources */,
9421B88F1A8BBCB200BA3E46 /* FLEXNetworkTransaction.m in Sources */,
944F748A197B458C009AB039 /* FLEXClassExplorerViewController.m in Sources */,
535682B318F3670300BAAD62 /* AAPLPageControlViewController.m in Sources */,
535682BA18F3670300BAAD62 /* AAPLSwitchViewController.m in Sources */,
535682AF18F3670300BAAD62 /* AAPLDefaultSearchBarViewController.m in Sources */,
944F74B5197B458C009AB039 /* FLEXHierarchyTableViewCell.m in Sources */,
944F74AD197B458C009AB039 /* FLEXWindow.m in Sources */,
944F749D197B458C009AB039 /* FLEXArgumentInputStringView.m in Sources */,
944F74A9197B458C009AB039 /* FLEXExplorerToolbar.m in Sources */,
944F74A8197B458C009AB039 /* FLEXPropertyEditorViewController.m in Sources */,
944F74B0197B458C009AB039 /* FLEXGlobalsTableViewController.m in Sources */,
944F748B197B458C009AB039 /* FLEXDefaultsExplorerViewController.m in Sources */,
944F749E197B458C009AB039 /* FLEXArgumentInputStructView.m in Sources */,
94CB4D4F1A9829F80054A905 /* FLEXNetworkSettingsTableViewController.m in Sources */,
944F74B3197B458C009AB039 /* FLEXLiveObjectsTableViewController.m in Sources */,
944F748E197B458C009AB039 /* FLEXImageExplorerViewController.m in Sources */,
944F74B6197B458C009AB039 /* FLEXHierarchyTableViewController.m in Sources */,
65F8DC6C1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m in Sources */,
535682BC18F3670300BAAD62 /* AAPLTextViewController.m in Sources */,
9421B8901A8BBCB200BA3E46 /* FLEXNetworkTransactionDetailTableViewController.m in Sources */,
944F74B4197B458C009AB039 /* FLEXWebViewController.m in Sources */,
944F74A5197B458C009AB039 /* FLEXFieldEditorViewController.m in Sources */,
944F7489197B458C009AB039 /* FLEXArrayExplorerViewController.m in Sources */,
535682B418F3670300BAAD62 /* AAPLPickerViewController.m in Sources */,
946C6EC91A7598D3006545C2 /* FLEXSystemLogTableViewCell.m in Sources */,
535682BE18F3670300BAAD62 /* AAPLWebViewController.m in Sources */,
944F7490197B458C009AB039 /* FLEXObjectExplorerViewController.m in Sources */,
944F7499197B458C009AB039 /* FLEXArgumentInputFontView.m in Sources */,
944F7496197B458C009AB039 /* FLEXRuntimeUtility.m in Sources */,
944F7491197B458C009AB039 /* FLEXSetExplorerViewController.m in Sources */,
944F74AF197B458C009AB039 /* FLEXFileBrowserTableViewController.m in Sources */,
535682BB18F3670300BAAD62 /* AAPLTextFieldViewController.m in Sources */,
944F749F197B458C009AB039 /* FLEXArgumentInputSwitchView.m in Sources */,
944F74A3197B458C009AB039 /* FLEXDefaultEditorViewController.m in Sources */,
944F74AB197B458C009AB039 /* FLEXManager.m in Sources */,
94C681F31A3E941800E1936D /* FLEXLayerExplorerViewController.m in Sources */,
944F74B2197B458C009AB039 /* FLEXLibrariesTableViewController.m in Sources */,
535682BF18F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m in Sources */,
535682B718F3670300BAAD62 /* AAPLSliderViewController.m in Sources */,
9421B88E1A8BBCB200BA3E46 /* FLEXNetworkRecorder.m in Sources */,
944F74AC197B458C009AB039 /* FLEXToolbarItem.m in Sources */,
944F74B7197B458C009AB039 /* FLEXImagePreviewViewController.m in Sources */,
650855EB1A9007D5006109A1 /* FLEXArgumentInputDateView.m in Sources */,
944F7498197B458C009AB039 /* FLEXArgumentInputColorView.m in Sources */,
944F74A0197B458C009AB039 /* FLEXArgumentInputTextView.m in Sources */,
944F749C197B458C009AB039 /* FLEXArgumentInputNumberView.m in Sources */,
944F749A197B458C009AB039 /* FLEXArgumentInputJSONObjectView.m in Sources */,
944F7494197B458C009AB039 /* FLEXHeapEnumerator.m in Sources */,
535682B918F3670300BAAD62 /* AAPLStepperViewController.m in Sources */,
535682AA18F3670300BAAD62 /* AAPLAppDelegate.m in Sources */,
9421B88D1A8BBCB200BA3E46 /* FLEXNetworkHistoryTableViewController.m in Sources */,
9421B8911A8BBCB200BA3E46 /* FLEXNetworkTransactionTableViewCell.m in Sources */,
535682B518F3670300BAAD62 /* AAPLProgressViewController.m in Sources */,
22679D581C74188D002248FC /* Dog.m in Sources */,
535682AD18F3670300BAAD62 /* AAPLCustomToolbarViewController.m in Sources */,
944F748F197B458C009AB039 /* FLEXObjectExplorerFactory.m in Sources */,
944F748D197B458C009AB039 /* FLEXDictionaryExplorerViewController.m in Sources */,
535682A818F3670300BAAD62 /* AAPLActivityIndicatorViewController.m in Sources */,
944F74A4197B458C009AB039 /* FLEXFieldEditorView.m in Sources */,
944F74A7197B458C009AB039 /* FLEXMethodCallingViewController.m in Sources */,
535682B818F3670300BAAD62 /* AAPLSplitViewControllerDelegate.m in Sources */,
D03647D919847248007D2A1B /* FLEXGlobalsTableViewControllerEntry.m in Sources */,
535682AC18F3670300BAAD62 /* AAPLCustomSearchBarViewController.m in Sources */,
535682A718F3670300BAAD62 /* AAPLActionSheetViewController.m in Sources */,
01985ABC1984DE9500A65332 /* FLEXArgumentInputFontsPickerView.m in Sources */,
944F74AA197B458C009AB039 /* FLEXExplorerViewController.m in Sources */,
944F7492197B458C009AB039 /* FLEXViewControllerExplorerViewController.m in Sources */,
5356824A18F3656900BAAD62 /* main.m in Sources */,
535682B118F3670300BAAD62 /* AAPLImageViewController.m in Sources */,
944F7493197B458C009AB039 /* FLEXViewExplorerViewController.m in Sources */,
944F7495197B458C009AB039 /* FLEXResources.m in Sources */,
535682A918F3670300BAAD62 /* AAPLAlertViewController.m in Sources */,
944F74A6197B458C009AB039 /* FLEXIvarEditorViewController.m in Sources */,
0149BFE2198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m in Sources */,
535682B218F3670300BAAD62 /* AAPLMasterViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -920,7 +469,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -953,7 +502,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -966,9 +515,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
EXCLUDED_SOURCE_FILE_NAMES = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "UICatalog/UICatalog-Prefix.pch";
INFOPLIST_FILE = "UICatalog/UICatalog-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.UICatalog";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
@@ -981,9 +535,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
EXCLUDED_SOURCE_FILE_NAMES = "FLEX*";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "UICatalog/UICatalog-Prefix.pch";
INFOPLIST_FILE = "UICatalog/UICatalog-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.UICatalog";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
+29 -1
View File
@@ -48,7 +48,11 @@
#import "AAPLAppDelegate.h"
#if DEBUG
#import "FLEXManager.h"
#import <FLEX/FLEX.h>
#if __has_include(<Realm/Realm.h>)
#import "Dog.h"
#import "Owner.h"
#endif
#endif
@interface AAPLAppDelegate () <NSURLConnectionDataDelegate, NSURLSessionDataDelegate>
@@ -66,6 +70,11 @@
[[FLEXManager sharedManager] setNetworkDebuggingEnabled:YES];
[self sendExampleNetworkRequests];
self.repeatingLogExampleTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(sendExampleLogMessage) userInfo:nil repeats:YES];
#if __has_include(<Realm/Realm.h>)
[self setUpRealm];
#endif
#endif
return YES;
}
@@ -173,4 +182,23 @@
[self.connections removeObject:connection];
}
#if __has_include(<Realm/Realm.h>)
- (void)setUpRealm
{
NSString *destinationPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
destinationPath = [destinationPath stringByAppendingPathComponent:@"dogs.realm"];
if ([[NSFileManager defaultManager] fileExistsAtPath:destinationPath isDirectory:nil]) {
return;
}
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"dogs" ofType:@"realm"];
if (resourcePath == nil) {
return;
}
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:resourcePath toPath:destinationPath error:&error];
}
#endif
@end
@@ -8,7 +8,7 @@
#if DEBUG
// FLEX should only be compiled and used in debug builds.
#import "FLEXManager.h"
#import <FLEX/FLEX.h>
#endif
@implementation AAPLCatalogTableTableViewController
+1 -1
View File
@@ -49,7 +49,7 @@
#if DEBUG
// FLEX should only be compiled and used in debug builds.
#import "FLEXManager.h"
#import <FLEX/FLEX.h>
#endif
@implementation AAPLMasterViewController
+2 -2
View File
@@ -107,8 +107,8 @@
NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// Convert the keyboard frame from screen to view coordinates.
CGRect keyboardScreenEndFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardScreenBeginFrame = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect keyboardScreenEndFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardScreenBeginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect keyboardViewEndFrame = [self.view convertRect:keyboardScreenEndFrame fromView:self.view.window];
CGRect keyboardViewBeginFrame = [self.view convertRect:keyboardScreenBeginFrame fromView:self.view.window];
+22
View File
@@ -0,0 +1,22 @@
//
// Dog.h
// UICatalog
//
// Created by Tim Oliver on 17/02/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#if __has_include(<Realm/Realm.h>)
#import <Realm/Realm.h>
#import "Owner.h"
@interface Dog : RLMObject
@property NSString *name;
@property CGFloat height;
@property NSDate *birthdate;
@property BOOL vaccinated;
@property Owner *owner;
@end
#endif
+16
View File
@@ -0,0 +1,16 @@
//
// Dog.m
// UICatalog
//
// Created by Tim Oliver on 17/02/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#import "Dog.h"
#if __has_include(<Realm/Realm.h>)
@implementation Dog
@end
#endif
+17
View File
@@ -0,0 +1,17 @@
//
// Owner.h
// UICatalog
//
// Created by Tim Oliver on 17/02/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#if __has_include(<Realm/Realm.h>)
#import <Realm/Realm.h>
@interface Owner : RLMObject
@property NSString *name;
@end
#endif
+16
View File
@@ -0,0 +1,16 @@
//
// Owner.m
// UICatalog
//
// Created by Tim Oliver on 17/02/2016.
// Copyright © 2016 Realm. All rights reserved.
//
#import "Owner.h"
#if __has_include(<Realm/Realm.h>)
@implementation Owner
@end
#endif
Binary file not shown.
+5 -5
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = "FLEX"
spec.version = "2.0.5"
spec.version = "2.3.0"
spec.summary = "A set of in-app debugging and exploration tools for iOS"
spec.description = <<-DESC
- Inspect and modify views in the hierarchy.
@@ -29,11 +29,11 @@ Pod::Spec.new do |spec|
spec.license = { :type => "BSD", :file => "LICENSE" }
spec.author = { "Ryan Olson" => "ryanolsonk@gmail.com" }
spec.social_media_url = "https://twitter.com/ryanolsonk"
spec.platform = :ios, "7.0"
spec.platform = :ios, "8.0"
spec.source = { :git => "https://github.com/Flipboard/FLEX.git", :tag => "#{spec.version}" }
spec.source_files = "Classes/**/*.{h,m}"
spec.frameworks = "CoreGraphics"
spec.libraries = "z"
spec.frameworks = [ "Foundation", "UIKit", "CoreGraphics" ]
spec.libraries = [ "z", "sqlite3" ]
spec.requires_arc = true
spec.public_header_files = "Classes/**/FLEXManager.h"
spec.public_header_files = [ "Classes/**/FLEXManager.h", "Classes/FLEX.h" ]
end
+200 -47
View File
@@ -7,6 +7,14 @@
objects = {
/* Begin PBXBuildFile section */
04F1CA191C137CF1000A52B0 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 04F1CA181C137CF1000A52B0 /* LICENSE */; };
222C88221C7339DC007CA15F /* FLEXRealmDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222C88211C7339DC007CA15F /* FLEXRealmDefines.h */; };
224D49A81C673AB5000EAB86 /* FLEXRealmDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 224D49A41C673AB5000EAB86 /* FLEXRealmDatabaseManager.h */; };
224D49A91C673AB5000EAB86 /* FLEXRealmDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 224D49A51C673AB5000EAB86 /* FLEXRealmDatabaseManager.m */; };
224D49AA1C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 224D49A61C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.h */; };
224D49AB1C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 224D49A71C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.m */; };
2EF6B04D1D494BE50006BDA5 /* FLEXNetworkCurlLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EF6B04B1D494BE50006BDA5 /* FLEXNetworkCurlLogger.m */; };
2EF6B04E1D494BE50006BDA5 /* FLEXNetworkCurlLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EF6B04C1D494BE50006BDA5 /* FLEXNetworkCurlLogger.h */; };
3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94241B5B20570088C3F2 /* FLEX.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A4C94C51B5B21410088C3F2 /* FLEXArrayExplorerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C943C1B5B21410088C3F2 /* FLEXArrayExplorerViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C94C61B5B21410088C3F2 /* FLEXArrayExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C943D1B5B21410088C3F2 /* FLEXArrayExplorerViewController.m */; };
@@ -86,17 +94,6 @@
3A4C95101B5B21410088C3F2 /* FLEXMethodCallingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C948B1B5B21410088C3F2 /* FLEXMethodCallingViewController.m */; };
3A4C95111B5B21410088C3F2 /* FLEXPropertyEditorViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C948C1B5B21410088C3F2 /* FLEXPropertyEditorViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C95121B5B21410088C3F2 /* FLEXPropertyEditorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C948D1B5B21410088C3F2 /* FLEXPropertyEditorViewController.m */; };
3A4C95131B5B21410088C3F2 /* FLEXExplorerToolbar.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C948F1B5B21410088C3F2 /* FLEXExplorerToolbar.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C95141B5B21410088C3F2 /* FLEXExplorerToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94901B5B21410088C3F2 /* FLEXExplorerToolbar.m */; };
3A4C95151B5B21410088C3F2 /* FLEXExplorerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94911B5B21410088C3F2 /* FLEXExplorerViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C95161B5B21410088C3F2 /* FLEXExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94921B5B21410088C3F2 /* FLEXExplorerViewController.m */; };
3A4C95171B5B21410088C3F2 /* FLEXManager+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94931B5B21410088C3F2 /* FLEXManager+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C95181B5B21410088C3F2 /* FLEXManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94941B5B21410088C3F2 /* FLEXManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A4C95191B5B21410088C3F2 /* FLEXManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94951B5B21410088C3F2 /* FLEXManager.m */; };
3A4C951A1B5B21410088C3F2 /* FLEXToolbarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94961B5B21410088C3F2 /* FLEXToolbarItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C951B1B5B21410088C3F2 /* FLEXToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94971B5B21410088C3F2 /* FLEXToolbarItem.m */; };
3A4C951C1B5B21410088C3F2 /* FLEXWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94981B5B21410088C3F2 /* FLEXWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C951D1B5B21410088C3F2 /* FLEXWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94991B5B21410088C3F2 /* FLEXWindow.m */; };
3A4C951E1B5B21410088C3F2 /* FLEXClassesTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C949B1B5B21410088C3F2 /* FLEXClassesTableViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C951F1B5B21410088C3F2 /* FLEXClassesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C949C1B5B21410088C3F2 /* FLEXClassesTableViewController.m */; };
3A4C95201B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -136,9 +133,48 @@
3A4C95421B5B21410088C3F2 /* FLEXNetworkObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94C21B5B21410088C3F2 /* FLEXNetworkObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
3A4C95431B5B21410088C3F2 /* FLEXNetworkObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94C31B5B21410088C3F2 /* FLEXNetworkObserver.m */; };
3A4C95471B5B217D0088C3F2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4C95461B5B217D0088C3F2 /* libz.dylib */; };
679F64861BD53B7B00A8C94C /* FLEXCookiesTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */; };
679F64871BD53B7B00A8C94C /* FLEXCookiesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */; };
779B1ECE1C0C4D7C001F5E49 /* FLEXDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC01C0C4D7C001F5E49 /* FLEXDatabaseManager.h */; };
779B1ED01C0C4D7C001F5E49 /* FLEXMultiColumnTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC21C0C4D7C001F5E49 /* FLEXMultiColumnTableView.h */; };
779B1ED11C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1EC31C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m */; };
779B1ED21C0C4D7C001F5E49 /* FLEXTableColumnHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC41C0C4D7C001F5E49 /* FLEXTableColumnHeader.h */; };
779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1EC51C0C4D7C001F5E49 /* FLEXTableColumnHeader.m */; };
779B1ED41C0C4D7C001F5E49 /* FLEXTableContentCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC61C0C4D7C001F5E49 /* FLEXTableContentCell.h */; };
779B1ED51C0C4D7C001F5E49 /* FLEXTableContentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1EC71C0C4D7C001F5E49 /* FLEXTableContentCell.m */; };
779B1ED61C0C4D7C001F5E49 /* FLEXTableContentViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1EC81C0C4D7C001F5E49 /* FLEXTableContentViewController.h */; };
779B1ED71C0C4D7C001F5E49 /* FLEXTableContentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1EC91C0C4D7C001F5E49 /* FLEXTableContentViewController.m */; };
779B1ED81C0C4D7C001F5E49 /* FLEXTableLeftCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1ECA1C0C4D7C001F5E49 /* FLEXTableLeftCell.h */; };
779B1ED91C0C4D7C001F5E49 /* FLEXTableLeftCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1ECB1C0C4D7C001F5E49 /* FLEXTableLeftCell.m */; };
779B1EDA1C0C4D7C001F5E49 /* FLEXTableListViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 779B1ECC1C0C4D7C001F5E49 /* FLEXTableListViewController.h */; };
779B1EDB1C0C4D7C001F5E49 /* FLEXTableListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 779B1ECD1C0C4D7C001F5E49 /* FLEXTableListViewController.m */; };
779B1EDD1C0C4EAD001F5E49 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 779B1EDC1C0C4EAD001F5E49 /* libsqlite3.dylib */; };
942DCD871BAE0CA300DB5DC2 /* FLEXKeyboardShortcutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 942DCD831BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.m */; };
94A515141C4CA1C00063292F /* FLEXManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A515131C4CA1C00063292F /* FLEXManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
94A515171C4CA1D70063292F /* FLEXManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A515151C4CA1D70063292F /* FLEXManager.m */; };
94A515181C4CA1D70063292F /* FLEXManager+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A515161C4CA1D70063292F /* FLEXManager+Private.h */; };
94A5151D1C4CA1F10063292F /* FLEXExplorerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A515191C4CA1F10063292F /* FLEXExplorerViewController.h */; };
94A5151E1C4CA1F10063292F /* FLEXExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A5151A1C4CA1F10063292F /* FLEXExplorerViewController.m */; };
94A5151F1C4CA1F10063292F /* FLEXWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A5151B1C4CA1F10063292F /* FLEXWindow.h */; };
94A515201C4CA1F10063292F /* FLEXWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A5151C1C4CA1F10063292F /* FLEXWindow.m */; };
94A515251C4CA2080063292F /* FLEXExplorerToolbar.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A515211C4CA2080063292F /* FLEXExplorerToolbar.h */; };
94A515261C4CA2080063292F /* FLEXExplorerToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A515221C4CA2080063292F /* FLEXExplorerToolbar.m */; };
94A515271C4CA2080063292F /* FLEXToolbarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 94A515231C4CA2080063292F /* FLEXToolbarItem.h */; };
94A515281C4CA2080063292F /* FLEXToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 94A515241C4CA2080063292F /* FLEXToolbarItem.m */; };
94AAF0381BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */; };
94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
04F1CA181C137CF1000A52B0 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
222C88211C7339DC007CA15F /* FLEXRealmDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDefines.h; sourceTree = "<group>"; };
224D49A41C673AB5000EAB86 /* FLEXRealmDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDatabaseManager.h; sourceTree = "<group>"; };
224D49A51C673AB5000EAB86 /* FLEXRealmDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRealmDatabaseManager.m; sourceTree = "<group>"; };
224D49A61C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXSQLiteDatabaseManager.h; sourceTree = "<group>"; };
224D49A71C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXSQLiteDatabaseManager.m; sourceTree = "<group>"; };
2EF6B04B1D494BE50006BDA5 /* FLEXNetworkCurlLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkCurlLogger.m; sourceTree = "<group>"; };
2EF6B04C1D494BE50006BDA5 /* FLEXNetworkCurlLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXNetworkCurlLogger.h; sourceTree = "<group>"; };
3A4C941F1B5B20570088C3F2 /* FLEX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FLEX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3A4C94231B5B20570088C3F2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3A4C94241B5B20570088C3F2 /* FLEX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEX.h; sourceTree = "<group>"; };
@@ -220,17 +256,6 @@
3A4C948B1B5B21410088C3F2 /* FLEXMethodCallingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMethodCallingViewController.m; sourceTree = "<group>"; };
3A4C948C1B5B21410088C3F2 /* FLEXPropertyEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXPropertyEditorViewController.h; sourceTree = "<group>"; };
3A4C948D1B5B21410088C3F2 /* FLEXPropertyEditorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXPropertyEditorViewController.m; sourceTree = "<group>"; };
3A4C948F1B5B21410088C3F2 /* FLEXExplorerToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerToolbar.h; sourceTree = "<group>"; };
3A4C94901B5B21410088C3F2 /* FLEXExplorerToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerToolbar.m; sourceTree = "<group>"; };
3A4C94911B5B21410088C3F2 /* FLEXExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXExplorerViewController.h; sourceTree = "<group>"; };
3A4C94921B5B21410088C3F2 /* FLEXExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXExplorerViewController.m; sourceTree = "<group>"; };
3A4C94931B5B21410088C3F2 /* FLEXManager+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FLEXManager+Private.h"; sourceTree = "<group>"; };
3A4C94941B5B21410088C3F2 /* FLEXManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXManager.h; sourceTree = "<group>"; };
3A4C94951B5B21410088C3F2 /* FLEXManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXManager.m; sourceTree = "<group>"; };
3A4C94961B5B21410088C3F2 /* FLEXToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXToolbarItem.h; sourceTree = "<group>"; };
3A4C94971B5B21410088C3F2 /* FLEXToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXToolbarItem.m; sourceTree = "<group>"; };
3A4C94981B5B21410088C3F2 /* FLEXWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXWindow.h; sourceTree = "<group>"; };
3A4C94991B5B21410088C3F2 /* FLEXWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXWindow.m; sourceTree = "<group>"; };
3A4C949B1B5B21410088C3F2 /* FLEXClassesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXClassesTableViewController.h; sourceTree = "<group>"; };
3A4C949C1B5B21410088C3F2 /* FLEXClassesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXClassesTableViewController.m; sourceTree = "<group>"; };
3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserFileOperationController.h; sourceTree = "<group>"; };
@@ -271,6 +296,37 @@
3A4C94C31B5B21410088C3F2 /* FLEXNetworkObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXNetworkObserver.m; sourceTree = "<group>"; };
3A4C94C41B5B21410088C3F2 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
3A4C95461B5B217D0088C3F2 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXCookiesTableViewController.h; sourceTree = "<group>"; };
679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXCookiesTableViewController.m; sourceTree = "<group>"; };
779B1EC01C0C4D7C001F5E49 /* FLEXDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXDatabaseManager.h; sourceTree = "<group>"; };
779B1EC21C0C4D7C001F5E49 /* FLEXMultiColumnTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMultiColumnTableView.h; sourceTree = "<group>"; };
779B1EC31C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMultiColumnTableView.m; sourceTree = "<group>"; };
779B1EC41C0C4D7C001F5E49 /* FLEXTableColumnHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableColumnHeader.h; sourceTree = "<group>"; };
779B1EC51C0C4D7C001F5E49 /* FLEXTableColumnHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableColumnHeader.m; sourceTree = "<group>"; };
779B1EC61C0C4D7C001F5E49 /* FLEXTableContentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableContentCell.h; sourceTree = "<group>"; };
779B1EC71C0C4D7C001F5E49 /* FLEXTableContentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableContentCell.m; sourceTree = "<group>"; };
779B1EC81C0C4D7C001F5E49 /* FLEXTableContentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableContentViewController.h; sourceTree = "<group>"; };
779B1EC91C0C4D7C001F5E49 /* FLEXTableContentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableContentViewController.m; sourceTree = "<group>"; };
779B1ECA1C0C4D7C001F5E49 /* FLEXTableLeftCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableLeftCell.h; sourceTree = "<group>"; };
779B1ECB1C0C4D7C001F5E49 /* FLEXTableLeftCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableLeftCell.m; sourceTree = "<group>"; };
779B1ECC1C0C4D7C001F5E49 /* FLEXTableListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableListViewController.h; sourceTree = "<group>"; };
779B1ECD1C0C4D7C001F5E49 /* FLEXTableListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableListViewController.m; sourceTree = "<group>"; };
779B1EDC1C0C4EAD001F5E49 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = ../../../../../usr/lib/libsqlite3.dylib; sourceTree = "<group>"; };
942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardShortcutManager.h; sourceTree = "<group>"; };
942DCD831BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardShortcutManager.m; sourceTree = "<group>"; };
94A515131C4CA1C00063292F /* FLEXManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXManager.h; sourceTree = "<group>"; };
94A515151C4CA1D70063292F /* FLEXManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXManager.m; path = Manager/FLEXManager.m; sourceTree = "<group>"; };
94A515161C4CA1D70063292F /* FLEXManager+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "FLEXManager+Private.h"; path = "Manager/FLEXManager+Private.h"; sourceTree = "<group>"; };
94A515191C4CA1F10063292F /* FLEXExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLEXExplorerViewController.h; path = ExplorerInterface/FLEXExplorerViewController.h; sourceTree = "<group>"; };
94A5151A1C4CA1F10063292F /* FLEXExplorerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXExplorerViewController.m; path = ExplorerInterface/FLEXExplorerViewController.m; sourceTree = "<group>"; };
94A5151B1C4CA1F10063292F /* FLEXWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLEXWindow.h; path = ExplorerInterface/FLEXWindow.h; sourceTree = "<group>"; };
94A5151C1C4CA1F10063292F /* FLEXWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXWindow.m; path = ExplorerInterface/FLEXWindow.m; sourceTree = "<group>"; };
94A515211C4CA2080063292F /* FLEXExplorerToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLEXExplorerToolbar.h; path = Classes/Toolbar/FLEXExplorerToolbar.h; sourceTree = SOURCE_ROOT; };
94A515221C4CA2080063292F /* FLEXExplorerToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXExplorerToolbar.m; path = Classes/Toolbar/FLEXExplorerToolbar.m; sourceTree = SOURCE_ROOT; };
94A515231C4CA2080063292F /* FLEXToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLEXToolbarItem.h; path = Classes/Toolbar/FLEXToolbarItem.h; sourceTree = SOURCE_ROOT; };
94A515241C4CA2080063292F /* FLEXToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXToolbarItem.m; path = Classes/Toolbar/FLEXToolbarItem.m; sourceTree = SOURCE_ROOT; };
94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardHelpViewController.h; sourceTree = "<group>"; };
94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardHelpViewController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -278,6 +334,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
779B1EDD1C0C4EAD001F5E49 /* libsqlite3.dylib in Frameworks */,
3A4C95471B5B217D0088C3F2 /* libz.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -306,8 +363,11 @@
isa = PBXGroup;
children = (
3A4C94241B5B20570088C3F2 /* FLEX.h */,
94A515131C4CA1C00063292F /* FLEXManager.h */,
94A515111C4C9C1B0063292F /* Manager */,
94A515121C4C9E7B0063292F /* ExplorerInterface */,
3A4C94661B5B21410088C3F2 /* Editing */,
3A4C948E1B5B21410088C3F2 /* ExplorerToolbar */,
3A4C948E1B5B21410088C3F2 /* Toolbar */,
3A4C949A1B5B21410088C3F2 /* GlobalStateExplorers */,
3A4C94B41B5B21410088C3F2 /* Network */,
3A4C943B1B5B21410088C3F2 /* ObjectExplorers */,
@@ -371,6 +431,10 @@
3A4C945C1B5B21410088C3F2 /* FLEXRuntimeUtility.m */,
3A4C945D1B5B21410088C3F2 /* FLEXUtility.h */,
3A4C945E1B5B21410088C3F2 /* FLEXUtility.m */,
942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */,
942DCD831BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.m */,
94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */,
94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */,
);
path = Utility;
sourceTree = "<group>";
@@ -441,27 +505,22 @@
path = ArgumentInputViews;
sourceTree = "<group>";
};
3A4C948E1B5B21410088C3F2 /* ExplorerToolbar */ = {
3A4C948E1B5B21410088C3F2 /* Toolbar */ = {
isa = PBXGroup;
children = (
3A4C948F1B5B21410088C3F2 /* FLEXExplorerToolbar.h */,
3A4C94901B5B21410088C3F2 /* FLEXExplorerToolbar.m */,
3A4C94911B5B21410088C3F2 /* FLEXExplorerViewController.h */,
3A4C94921B5B21410088C3F2 /* FLEXExplorerViewController.m */,
3A4C94931B5B21410088C3F2 /* FLEXManager+Private.h */,
3A4C94941B5B21410088C3F2 /* FLEXManager.h */,
3A4C94951B5B21410088C3F2 /* FLEXManager.m */,
3A4C94961B5B21410088C3F2 /* FLEXToolbarItem.h */,
3A4C94971B5B21410088C3F2 /* FLEXToolbarItem.m */,
3A4C94981B5B21410088C3F2 /* FLEXWindow.h */,
3A4C94991B5B21410088C3F2 /* FLEXWindow.m */,
94A515211C4CA2080063292F /* FLEXExplorerToolbar.h */,
94A515221C4CA2080063292F /* FLEXExplorerToolbar.m */,
94A515231C4CA2080063292F /* FLEXToolbarItem.h */,
94A515241C4CA2080063292F /* FLEXToolbarItem.m */,
);
name = Toolbar;
path = ExplorerToolbar;
sourceTree = "<group>";
};
3A4C949A1B5B21410088C3F2 /* GlobalStateExplorers */ = {
isa = PBXGroup;
children = (
779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */,
3A4C949B1B5B21410088C3F2 /* FLEXClassesTableViewController.h */,
3A4C949C1B5B21410088C3F2 /* FLEXClassesTableViewController.m */,
3A4C949D1B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h */,
@@ -478,6 +537,8 @@
3A4C94A81B5B21410088C3F2 /* FLEXLibrariesTableViewController.m */,
3A4C94A91B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.h */,
3A4C94AA1B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.m */,
679F64841BD53B7B00A8C94C /* FLEXCookiesTableViewController.h */,
679F64851BD53B7B00A8C94C /* FLEXCookiesTableViewController.m */,
3A4C94AB1B5B21410088C3F2 /* FLEXWebViewController.h */,
3A4C94AC1B5B21410088C3F2 /* FLEXWebViewController.m */,
3A4C94AD1B5B21410088C3F2 /* SystemLog */,
@@ -513,6 +574,8 @@
3A4C94BE1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.m */,
3A4C94BF1B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.h */,
3A4C94C01B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.m */,
2EF6B04C1D494BE50006BDA5 /* FLEXNetworkCurlLogger.h */,
2EF6B04B1D494BE50006BDA5 /* FLEXNetworkCurlLogger.m */,
3A4C94C11B5B21410088C3F2 /* PonyDebugger */,
);
path = Network;
@@ -531,11 +594,58 @@
3A4C95451B5B216C0088C3F2 /* Frameworks */ = {
isa = PBXGroup;
children = (
779B1EDC1C0C4EAD001F5E49 /* libsqlite3.dylib */,
3A4C95461B5B217D0088C3F2 /* libz.dylib */,
);
name = Frameworks;
sourceTree = "<group>";
};
779B1EBF1C0C4D7C001F5E49 /* DatabaseBrowser */ = {
isa = PBXGroup;
children = (
222C88211C7339DC007CA15F /* FLEXRealmDefines.h */,
779B1EC01C0C4D7C001F5E49 /* FLEXDatabaseManager.h */,
224D49A41C673AB5000EAB86 /* FLEXRealmDatabaseManager.h */,
224D49A51C673AB5000EAB86 /* FLEXRealmDatabaseManager.m */,
224D49A61C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.h */,
224D49A71C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.m */,
779B1EC21C0C4D7C001F5E49 /* FLEXMultiColumnTableView.h */,
779B1EC31C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m */,
779B1EC41C0C4D7C001F5E49 /* FLEXTableColumnHeader.h */,
779B1EC51C0C4D7C001F5E49 /* FLEXTableColumnHeader.m */,
779B1EC61C0C4D7C001F5E49 /* FLEXTableContentCell.h */,
779B1EC71C0C4D7C001F5E49 /* FLEXTableContentCell.m */,
779B1EC81C0C4D7C001F5E49 /* FLEXTableContentViewController.h */,
779B1EC91C0C4D7C001F5E49 /* FLEXTableContentViewController.m */,
779B1ECA1C0C4D7C001F5E49 /* FLEXTableLeftCell.h */,
779B1ECB1C0C4D7C001F5E49 /* FLEXTableLeftCell.m */,
779B1ECC1C0C4D7C001F5E49 /* FLEXTableListViewController.h */,
779B1ECD1C0C4D7C001F5E49 /* FLEXTableListViewController.m */,
04F1CA181C137CF1000A52B0 /* LICENSE */,
);
path = DatabaseBrowser;
sourceTree = "<group>";
};
94A515111C4C9C1B0063292F /* Manager */ = {
isa = PBXGroup;
children = (
94A515161C4CA1D70063292F /* FLEXManager+Private.h */,
94A515151C4CA1D70063292F /* FLEXManager.m */,
);
name = Manager;
sourceTree = "<group>";
};
94A515121C4C9E7B0063292F /* ExplorerInterface */ = {
isa = PBXGroup;
children = (
94A515191C4CA1F10063292F /* FLEXExplorerViewController.h */,
94A5151A1C4CA1F10063292F /* FLEXExplorerViewController.m */,
94A5151B1C4CA1F10063292F /* FLEXWindow.h */,
94A5151C1C4CA1F10063292F /* FLEXWindow.m */,
);
name = ExplorerInterface;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -543,18 +653,21 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
779B1EDA1C0C4D7C001F5E49 /* FLEXTableListViewController.h in Headers */,
3A4C94ED1B5B21410088C3F2 /* FLEXArgumentInputColorView.h in Headers */,
3A4C94EB1B5B21410088C3F2 /* FLEXImagePreviewViewController.h in Headers */,
3A4C95381B5B21410088C3F2 /* FLEXNetworkRecorder.h in Headers */,
3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */,
3A4C95051B5B21410088C3F2 /* FLEXArgumentInputViewFactory.h in Headers */,
222C88221C7339DC007CA15F /* FLEXRealmDefines.h in Headers */,
3A4C951E1B5B21410088C3F2 /* FLEXClassesTableViewController.h in Headers */,
779B1ED21C0C4D7C001F5E49 /* FLEXTableColumnHeader.h in Headers */,
3A4C94FD1B5B21410088C3F2 /* FLEXArgumentInputStructView.h in Headers */,
94A515141C4CA1C00063292F /* FLEXManager.h in Headers */,
3A4C95201B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h in Headers */,
3A4C953E1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.h in Headers */,
3A4C95301B5B21410088C3F2 /* FLEXSystemLogMessage.h in Headers */,
3A4C95361B5B21410088C3F2 /* FLEXNetworkHistoryTableViewController.h in Headers */,
3A4C95131B5B21410088C3F2 /* FLEXExplorerToolbar.h in Headers */,
3A4C94DD1B5B21410088C3F2 /* FLEXHeapEnumerator.h in Headers */,
3A4C94DB1B5B21410088C3F2 /* FLEXViewExplorerViewController.h in Headers */,
3A4C95321B5B21410088C3F2 /* FLEXSystemLogTableViewCell.h in Headers */,
@@ -562,52 +675,63 @@
3A4C94DF1B5B21410088C3F2 /* FLEXMultilineTableViewCell.h in Headers */,
3A4C953A1B5B21410088C3F2 /* FLEXNetworkSettingsTableViewController.h in Headers */,
3A4C94D11B5B21410088C3F2 /* FLEXLayerExplorerViewController.h in Headers */,
779B1ED01C0C4D7C001F5E49 /* FLEXMultiColumnTableView.h in Headers */,
3A4C94D31B5B21410088C3F2 /* FLEXObjectExplorerFactory.h in Headers */,
94A515271C4CA2080063292F /* FLEXToolbarItem.h in Headers */,
3A4C94E31B5B21410088C3F2 /* FLEXRuntimeUtility.h in Headers */,
3A4C95341B5B21410088C3F2 /* FLEXSystemLogTableViewController.h in Headers */,
3A4C951C1B5B21410088C3F2 /* FLEXWindow.h in Headers */,
3A4C95091B5B21410088C3F2 /* FLEXFieldEditorView.h in Headers */,
3A4C950D1B5B21410088C3F2 /* FLEXIvarEditorViewController.h in Headers */,
3A4C95281B5B21410088C3F2 /* FLEXInstancesTableViewController.h in Headers */,
3A4C95151B5B21410088C3F2 /* FLEXExplorerViewController.h in Headers */,
3A4C950F1B5B21410088C3F2 /* FLEXMethodCallingViewController.h in Headers */,
3A4C94F51B5B21410088C3F2 /* FLEXArgumentInputJSONObjectView.h in Headers */,
3A4C94F11B5B21410088C3F2 /* FLEXArgumentInputFontsPickerView.h in Headers */,
779B1ED61C0C4D7C001F5E49 /* FLEXTableContentViewController.h in Headers */,
3A4C94C91B5B21410088C3F2 /* FLEXDefaultsExplorerViewController.h in Headers */,
3A4C95221B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h in Headers */,
3A4C94FF1B5B21410088C3F2 /* FLEXArgumentInputSwitchView.h in Headers */,
3A4C95171B5B21410088C3F2 /* FLEXManager+Private.h in Headers */,
3A4C94E71B5B21410088C3F2 /* FLEXHierarchyTableViewCell.h in Headers */,
3A4C951A1B5B21410088C3F2 /* FLEXToolbarItem.h in Headers */,
224D49AA1C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.h in Headers */,
3A4C95031B5B21410088C3F2 /* FLEXArgumentInputView.h in Headers */,
94A5151D1C4CA1F10063292F /* FLEXExplorerViewController.h in Headers */,
3A4C94C51B5B21410088C3F2 /* FLEXArrayExplorerViewController.h in Headers */,
3A4C94CB1B5B21410088C3F2 /* FLEXDictionaryExplorerViewController.h in Headers */,
3A4C95071B5B21410088C3F2 /* FLEXDefaultEditorViewController.h in Headers */,
94A5151F1C4CA1F10063292F /* FLEXWindow.h in Headers */,
779B1ECE1C0C4D7C001F5E49 /* FLEXDatabaseManager.h in Headers */,
3A4C94D51B5B21410088C3F2 /* FLEXObjectExplorerViewController.h in Headers */,
3A4C95011B5B21410088C3F2 /* FLEXArgumentInputTextView.h in Headers */,
3A4C952A1B5B21410088C3F2 /* FLEXLibrariesTableViewController.h in Headers */,
779B1ED41C0C4D7C001F5E49 /* FLEXTableContentCell.h in Headers */,
3A4C952C1B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.h in Headers */,
3A4C94EF1B5B21410088C3F2 /* FLEXArgumentInputDateView.h in Headers */,
3A4C94C71B5B21410088C3F2 /* FLEXClassExplorerViewController.h in Headers */,
3A4C94F71B5B21410088C3F2 /* FLEXArgumentInputNotSupportedView.h in Headers */,
3A4C94E51B5B21410088C3F2 /* FLEXUtility.h in Headers */,
3A4C94CF1B5B21410088C3F2 /* FLEXImageExplorerViewController.h in Headers */,
2EF6B04E1D494BE50006BDA5 /* FLEXNetworkCurlLogger.h in Headers */,
3A4C950B1B5B21410088C3F2 /* FLEXFieldEditorViewController.h in Headers */,
94A515251C4CA2080063292F /* FLEXExplorerToolbar.h in Headers */,
3A4C953C1B5B21410088C3F2 /* FLEXNetworkTransaction.h in Headers */,
3A4C94D71B5B21410088C3F2 /* FLEXSetExplorerViewController.h in Headers */,
3A4C94D91B5B21410088C3F2 /* FLEXViewControllerExplorerViewController.h in Headers */,
3A4C952E1B5B21410088C3F2 /* FLEXWebViewController.h in Headers */,
3A4C95181B5B21410088C3F2 /* FLEXManager.h in Headers */,
3A4C95111B5B21410088C3F2 /* FLEXPropertyEditorViewController.h in Headers */,
3A4C94E91B5B21410088C3F2 /* FLEXHierarchyTableViewController.h in Headers */,
3A4C94F31B5B21410088C3F2 /* FLEXArgumentInputFontView.h in Headers */,
3A4C95261B5B21410088C3F2 /* FLEXGlobalsTableViewController.h in Headers */,
224D49A81C673AB5000EAB86 /* FLEXRealmDatabaseManager.h in Headers */,
3A4C94CD1B5B21410088C3F2 /* FLEXGlobalsTableViewControllerEntry.h in Headers */,
3A4C94FB1B5B21410088C3F2 /* FLEXArgumentInputStringView.h in Headers */,
3A4C95421B5B21410088C3F2 /* FLEXNetworkObserver.h in Headers */,
679F64861BD53B7B00A8C94C /* FLEXCookiesTableViewController.h in Headers */,
3A4C95401B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.h in Headers */,
3A4C95241B5B21410088C3F2 /* FLEXFileBrowserTableViewController.h in Headers */,
94AAF0381BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h in Headers */,
94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */,
94A515181C4CA1D70063292F /* FLEXManager+Private.h in Headers */,
3A4C94E11B5B21410088C3F2 /* FLEXResources.h in Headers */,
779B1ED81C0C4D7C001F5E49 /* FLEXTableLeftCell.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -639,7 +763,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = FLEX;
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = Flipboard;
TargetAttributes = {
3A4C941E1B5B20570088C3F2 = {
@@ -669,6 +793,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
04F1CA191C137CF1000A52B0 /* LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -679,6 +804,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
942DCD871BAE0CA300DB5DC2 /* FLEXKeyboardShortcutManager.m in Sources */,
224D49A91C673AB5000EAB86 /* FLEXRealmDatabaseManager.m in Sources */,
2EF6B04D1D494BE50006BDA5 /* FLEXNetworkCurlLogger.m in Sources */,
94A515201C4CA1F10063292F /* FLEXWindow.m in Sources */,
3A4C95121B5B21410088C3F2 /* FLEXPropertyEditorViewController.m in Sources */,
3A4C95391B5B21410088C3F2 /* FLEXNetworkRecorder.m in Sources */,
3A4C950E1B5B21410088C3F2 /* FLEXIvarEditorViewController.m in Sources */,
@@ -686,31 +815,37 @@
3A4C94F61B5B21410088C3F2 /* FLEXArgumentInputJSONObjectView.m in Sources */,
3A4C94EC1B5B21410088C3F2 /* FLEXImagePreviewViewController.m in Sources */,
3A4C94F21B5B21410088C3F2 /* FLEXArgumentInputFontsPickerView.m in Sources */,
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */,
3A4C951F1B5B21410088C3F2 /* FLEXClassesTableViewController.m in Sources */,
3A4C94C61B5B21410088C3F2 /* FLEXArrayExplorerViewController.m in Sources */,
3A4C95081B5B21410088C3F2 /* FLEXDefaultEditorViewController.m in Sources */,
779B1ED11C0C4D7C001F5E49 /* FLEXMultiColumnTableView.m in Sources */,
3A4C94EE1B5B21410088C3F2 /* FLEXArgumentInputColorView.m in Sources */,
3A4C94F01B5B21410088C3F2 /* FLEXArgumentInputDateView.m in Sources */,
3A4C94CA1B5B21410088C3F2 /* FLEXDefaultsExplorerViewController.m in Sources */,
3A4C94D01B5B21410088C3F2 /* FLEXImageExplorerViewController.m in Sources */,
679F64871BD53B7B00A8C94C /* FLEXCookiesTableViewController.m in Sources */,
3A4C94CE1B5B21410088C3F2 /* FLEXGlobalsTableViewControllerEntry.m in Sources */,
3A4C94FE1B5B21410088C3F2 /* FLEXArgumentInputStructView.m in Sources */,
3A4C94E01B5B21410088C3F2 /* FLEXMultilineTableViewCell.m in Sources */,
3A4C95431B5B21410088C3F2 /* FLEXNetworkObserver.m in Sources */,
3A4C94D21B5B21410088C3F2 /* FLEXLayerExplorerViewController.m in Sources */,
779B1EDB1C0C4D7C001F5E49 /* FLEXTableListViewController.m in Sources */,
3A4C94E41B5B21410088C3F2 /* FLEXRuntimeUtility.m in Sources */,
3A4C94D41B5B21410088C3F2 /* FLEXObjectExplorerFactory.m in Sources */,
94A515171C4CA1D70063292F /* FLEXManager.m in Sources */,
3A4C952F1B5B21410088C3F2 /* FLEXWebViewController.m in Sources */,
3A4C94DC1B5B21410088C3F2 /* FLEXViewExplorerViewController.m in Sources */,
3A4C95041B5B21410088C3F2 /* FLEXArgumentInputView.m in Sources */,
3A4C951B1B5B21410088C3F2 /* FLEXToolbarItem.m in Sources */,
3A4C95411B5B21410088C3F2 /* FLEXNetworkTransactionTableViewCell.m in Sources */,
3A4C94D61B5B21410088C3F2 /* FLEXObjectExplorerViewController.m in Sources */,
3A4C95211B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.m in Sources */,
3A4C94DE1B5B21410088C3F2 /* FLEXHeapEnumerator.m in Sources */,
3A4C95251B5B21410088C3F2 /* FLEXFileBrowserTableViewController.m in Sources */,
3A4C94DA1B5B21410088C3F2 /* FLEXViewControllerExplorerViewController.m in Sources */,
779B1ED51C0C4D7C001F5E49 /* FLEXTableContentCell.m in Sources */,
3A4C94E21B5B21410088C3F2 /* FLEXResources.m in Sources */,
94A515281C4CA2080063292F /* FLEXToolbarItem.m in Sources */,
3A4C94D81B5B21410088C3F2 /* FLEXSetExplorerViewController.m in Sources */,
3A4C95311B5B21410088C3F2 /* FLEXSystemLogMessage.m in Sources */,
3A4C94F41B5B21410088C3F2 /* FLEXArgumentInputFontView.m in Sources */,
@@ -719,28 +854,30 @@
3A4C94F81B5B21410088C3F2 /* FLEXArgumentInputNotSupportedView.m in Sources */,
3A4C95351B5B21410088C3F2 /* FLEXSystemLogTableViewController.m in Sources */,
3A4C95271B5B21410088C3F2 /* FLEXGlobalsTableViewController.m in Sources */,
3A4C95161B5B21410088C3F2 /* FLEXExplorerViewController.m in Sources */,
779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */,
3A4C94EA1B5B21410088C3F2 /* FLEXHierarchyTableViewController.m in Sources */,
3A4C95331B5B21410088C3F2 /* FLEXSystemLogTableViewCell.m in Sources */,
3A4C95191B5B21410088C3F2 /* FLEXManager.m in Sources */,
3A4C95021B5B21410088C3F2 /* FLEXArgumentInputTextView.m in Sources */,
94A515261C4CA2080063292F /* FLEXExplorerToolbar.m in Sources */,
3A4C94FA1B5B21410088C3F2 /* FLEXArgumentInputNumberView.m in Sources */,
779B1ED71C0C4D7C001F5E49 /* FLEXTableContentViewController.m in Sources */,
3A4C95001B5B21410088C3F2 /* FLEXArgumentInputSwitchView.m in Sources */,
3A4C94CC1B5B21410088C3F2 /* FLEXDictionaryExplorerViewController.m in Sources */,
3A4C953F1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.m in Sources */,
224D49AB1C673AB5000EAB86 /* FLEXSQLiteDatabaseManager.m in Sources */,
779B1ED91C0C4D7C001F5E49 /* FLEXTableLeftCell.m in Sources */,
3A4C94E61B5B21410088C3F2 /* FLEXUtility.m in Sources */,
3A4C95231B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.m in Sources */,
3A4C950C1B5B21410088C3F2 /* FLEXFieldEditorViewController.m in Sources */,
3A4C952D1B5B21410088C3F2 /* FLEXLiveObjectsTableViewController.m in Sources */,
3A4C953D1B5B21410088C3F2 /* FLEXNetworkTransaction.m in Sources */,
3A4C95141B5B21410088C3F2 /* FLEXExplorerToolbar.m in Sources */,
3A4C94E81B5B21410088C3F2 /* FLEXHierarchyTableViewCell.m in Sources */,
3A4C94C81B5B21410088C3F2 /* FLEXClassExplorerViewController.m in Sources */,
3A4C950A1B5B21410088C3F2 /* FLEXFieldEditorView.m in Sources */,
3A4C951D1B5B21410088C3F2 /* FLEXWindow.m in Sources */,
3A4C95061B5B21410088C3F2 /* FLEXArgumentInputViewFactory.m in Sources */,
3A4C95291B5B21410088C3F2 /* FLEXInstancesTableViewController.m in Sources */,
3A4C952B1B5B21410088C3F2 /* FLEXLibrariesTableViewController.m in Sources */,
94A5151E1C4CA1F10063292F /* FLEXExplorerViewController.m in Sources */,
3A4C95371B5B21410088C3F2 /* FLEXNetworkHistoryTableViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -761,8 +898,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -789,6 +928,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@@ -809,8 +949,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -829,6 +971,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -840,10 +983,15 @@
3A4C94361B5B20570088C3F2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Classes/Info.plist;
INSTALL_PATH = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -856,10 +1004,15 @@
3A4C94371B5B20570088C3F2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Classes/Info.plist;
INSTALL_PATH = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
-413
View File
@@ -1,413 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4C94241B5B20570088C3F2 /* FLEX.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A4C942B1B5B20570088C3F2 /* FLEX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4C941F1B5B20570088C3F2 /* FLEX.framework */; };
3A4C94321B5B20570088C3F2 /* FLEXTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A4C94311B5B20570088C3F2 /* FLEXTests.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3A4C942C1B5B20570088C3F2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 3A4C94161B5B20570088C3F2 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3A4C941E1B5B20570088C3F2;
remoteInfo = FLEX;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
3A4C941F1B5B20570088C3F2 /* FLEX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FLEX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3A4C94231B5B20570088C3F2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3A4C94241B5B20570088C3F2 /* FLEX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEX.h; sourceTree = "<group>"; };
3A4C942A1B5B20570088C3F2 /* FLEXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FLEXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3A4C94301B5B20570088C3F2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3A4C94311B5B20570088C3F2 /* FLEXTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTests.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3A4C941B1B5B20570088C3F2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
3A4C94271B5B20570088C3F2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3A4C942B1B5B20570088C3F2 /* FLEX.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3A4C94151B5B20570088C3F2 = {
isa = PBXGroup;
children = (
3A4C94211B5B20570088C3F2 /* FLEX */,
3A4C942E1B5B20570088C3F2 /* FLEXTests */,
3A4C94201B5B20570088C3F2 /* Products */,
);
sourceTree = "<group>";
};
3A4C94201B5B20570088C3F2 /* Products */ = {
isa = PBXGroup;
children = (
3A4C941F1B5B20570088C3F2 /* FLEX.framework */,
3A4C942A1B5B20570088C3F2 /* FLEXTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
3A4C94211B5B20570088C3F2 /* FLEX */ = {
isa = PBXGroup;
children = (
3A4C94241B5B20570088C3F2 /* FLEX.h */,
3A4C94221B5B20570088C3F2 /* Supporting Files */,
);
path = FLEX;
sourceTree = "<group>";
};
3A4C94221B5B20570088C3F2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
3A4C94231B5B20570088C3F2 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
3A4C942E1B5B20570088C3F2 /* FLEXTests */ = {
isa = PBXGroup;
children = (
3A4C94311B5B20570088C3F2 /* FLEXTests.m */,
3A4C942F1B5B20570088C3F2 /* Supporting Files */,
);
path = FLEXTests;
sourceTree = "<group>";
};
3A4C942F1B5B20570088C3F2 /* Supporting Files */ = {
isa = PBXGroup;
children = (
3A4C94301B5B20570088C3F2 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
3A4C941C1B5B20570088C3F2 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3A4C941E1B5B20570088C3F2 /* FLEX */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3A4C94351B5B20570088C3F2 /* Build configuration list for PBXNativeTarget "FLEX" */;
buildPhases = (
3A4C941A1B5B20570088C3F2 /* Sources */,
3A4C941B1B5B20570088C3F2 /* Frameworks */,
3A4C941C1B5B20570088C3F2 /* Headers */,
3A4C941D1B5B20570088C3F2 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FLEX;
productName = FLEX;
productReference = 3A4C941F1B5B20570088C3F2 /* FLEX.framework */;
productType = "com.apple.product-type.framework";
};
3A4C94291B5B20570088C3F2 /* FLEXTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3A4C94381B5B20570088C3F2 /* Build configuration list for PBXNativeTarget "FLEXTests" */;
buildPhases = (
3A4C94261B5B20570088C3F2 /* Sources */,
3A4C94271B5B20570088C3F2 /* Frameworks */,
3A4C94281B5B20570088C3F2 /* Resources */,
);
buildRules = (
);
dependencies = (
3A4C942D1B5B20570088C3F2 /* PBXTargetDependency */,
);
name = FLEXTests;
productName = FLEXTests;
productReference = 3A4C942A1B5B20570088C3F2 /* FLEXTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
3A4C94161B5B20570088C3F2 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0640;
ORGANIZATIONNAME = Flipboard;
TargetAttributes = {
3A4C941E1B5B20570088C3F2 = {
CreatedOnToolsVersion = 6.4;
};
3A4C94291B5B20570088C3F2 = {
CreatedOnToolsVersion = 6.4;
};
};
};
buildConfigurationList = 3A4C94191B5B20570088C3F2 /* Build configuration list for PBXProject "FLEX" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 3A4C94151B5B20570088C3F2;
productRefGroup = 3A4C94201B5B20570088C3F2 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
3A4C941E1B5B20570088C3F2 /* FLEX */,
3A4C94291B5B20570088C3F2 /* FLEXTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
3A4C941D1B5B20570088C3F2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
3A4C94281B5B20570088C3F2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3A4C941A1B5B20570088C3F2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
3A4C94261B5B20570088C3F2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3A4C94321B5B20570088C3F2 /* FLEXTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3A4C942D1B5B20570088C3F2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3A4C941E1B5B20570088C3F2 /* FLEX */;
targetProxy = 3A4C942C1B5B20570088C3F2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
3A4C94331B5B20570088C3F2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
3A4C94341B5B20570088C3F2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
3A4C94361B5B20570088C3F2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = FLEX/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
3A4C94371B5B20570088C3F2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = FLEX/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
3A4C94391B5B20570088C3F2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = FLEXTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
3A4C943A1B5B20570088C3F2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = FLEXTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3A4C94191B5B20570088C3F2 /* Build configuration list for PBXProject "FLEX" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3A4C94331B5B20570088C3F2 /* Debug */,
3A4C94341B5B20570088C3F2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3A4C94351B5B20570088C3F2 /* Build configuration list for PBXNativeTarget "FLEX" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3A4C94361B5B20570088C3F2 /* Debug */,
3A4C94371B5B20570088C3F2 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
3A4C94381B5B20570088C3F2 /* Build configuration list for PBXNativeTarget "FLEXTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3A4C94391B5B20570088C3F2 /* Debug */,
3A4C943A1B5B20570088C3F2 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 3A4C94161B5B20570088C3F2 /* Project object */;
}
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:FLEX.xcodeproj">
</FileRef>
</Workspace>
+2 -2
View File
@@ -1,4 +1,4 @@
Copyright (c) 2014, Flipboard
Copyright (c) 2014-2016, Flipboard
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -24,4 +24,4 @@ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+26 -3
View File
@@ -17,9 +17,12 @@ FLEX (Flipboard Explorer) is a set of in-app debugging and exploration tools for
- 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.
@@ -28,6 +31,9 @@ Unlike many other debugging tools, FLEX runs entirely inside your app, so you do
## 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 programatically:
Short version:
```objc
@@ -62,7 +68,7 @@ Once a view is selected, you can tap on the info bar below the toolbar to presen
![View Modification](http://engineering.flipboard.com/assets/flex/advanced-view-editing.gif)
### 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 accross launches.
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](http://engineering.flipboard.com/assets/flex/network-history.gif)
@@ -71,11 +77,26 @@ FLEX queries malloc for all the live allocated memory blocks and searches for on
![Heap Exploration](http://engineering.flipboard.com/assets/flex/heap-browser.gif)
### 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 `-[FLEXMananger registerSimulatorShortcutWithKey:modifiers:action:description]`
![Simulator Shortcuts](https://cloud.githubusercontent.com/assets/1422245/10002927/1106fd32-6067-11e5-8e21-57a357c259b6.png)
### File Browser
View the file system within your app's sandbox. FLEX shows file sizes, image previews, and pretty prints `.json` and `.plist` files. You can copy text and image files to the pasteboard if you want to inspect them outside of your app.
![File Browser](http://engineering.flipboard.com/assets/flex/file-browser.gif)
### SQLite Browser
SQLite database files (with either `.db` or `.sqlite` extensions), or [Realm](http://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.
![Database Browser](https://cloud.githubusercontent.com/assets/1422245/11786700/d0ab95dc-a23c-11e5-80ce-0e1b4dba2b6b.png)
### 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](https://cloud.githubusercontent.com/assets/1422245/11786615/5d4ef96c-a23c-11e5-975e-67275341e439.gif)
### System Library Exploration
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.
@@ -93,7 +114,7 @@ The code injection is left as an exercise for the reader. :innocent:
## Installation
FLEX is available on [Cocoapods](http://cocoapods.org/?q=FLEX). Simply add the following line to your podfile:
FLEX is available on [CocoaPods](http://cocoapods.org/?q=FLEX). Simply add the following line to your podfile:
```ruby
pod 'FLEX', '~> 2.0', :configurations => ['Debug']
@@ -133,11 +154,13 @@ FLEX builds on ideas and inspiration from open source tools that came before it.
- [Gist](https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396) from [@samdmarshall](https://github.com/samdmarshall): another example of enumerating malloc blocks.
- [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.
- [GZIP](https://github.com/nicklockwood/GZIP): A library for compressing/decompressing data on iOS using libz.
- [FMDB](https://github.com/ccgus/fmdb): This is an Objective-C wrapper around SQLite
## Contributing
We welcome pull requests for bug fixes, new features, and improvements to FLEX. Contributors to the main FLEX repository must accept Flipboard's Apache-style [Individual Contributor License Agreement (CLA)](https://docs.google.com/forms/d/1gh9y6_i8xFn6pA15PqFeye19VqasuI9-bGp_e0owy74/viewform) before any changes can be merged.
Please see our [Contributing Guide](https://github.com/Flipboard/FLEX/blob/master/CONTRIBUTING.md).
## TODO