├── .gitignore ├── .travis.yml ├── Classes ├── Models │ ├── RZDebugMenuChildPaneItem.h │ ├── RZDebugMenuChildPaneItem.m │ ├── RZDebugMenuGroupItem.h │ ├── RZDebugMenuGroupItem.m │ ├── RZDebugMenuItem.h │ ├── RZDebugMenuItem.m │ ├── RZDebugMenuLoadedChildPaneItem.h │ ├── RZDebugMenuLoadedChildPaneItem.m │ ├── RZDebugMenuMultiValueItem.h │ ├── RZDebugMenuMultiValueItem.m │ ├── RZDebugMenuMultiValueSelectionItem.h │ ├── RZDebugMenuMultiValueSelectionItem.m │ ├── RZDebugMenuSettingItem.h │ ├── RZDebugMenuSettingItem.m │ ├── RZDebugMenuSettings.h │ ├── RZDebugMenuSettings.m │ ├── RZDebugMenuSettings_Private.h │ ├── RZDebugMenuSliderItem.h │ ├── RZDebugMenuSliderItem.m │ ├── RZDebugMenuTextFieldItem.h │ ├── RZDebugMenuTextFieldItem.m │ ├── RZDebugMenuTitleItem.h │ ├── RZDebugMenuTitleItem.m │ ├── RZDebugMenuToggleItem.h │ ├── RZDebugMenuToggleItem.m │ ├── RZDebugMenuVersionItem.h │ └── RZDebugMenuVersionItem.m ├── RZDebugLogMenuDefines.h ├── RZDebugMenu.h ├── RZDebugMenu.m ├── RZDebugMenuFormViewController.h ├── RZDebugMenuFormViewController.m ├── RZDebugMenuIsolatedUserDefaultsStore.h ├── RZDebugMenuIsolatedUserDefaultsStore.m ├── RZDebugMenuSettingsParser.h ├── RZDebugMenuSettingsParser.m ├── RZDebugMenuSettingsStore.h ├── RZDebugMenuSettingsStore.m ├── RZDebugMenuUserDefaultsStore.h ├── RZDebugMenuUserDefaultsStore.m ├── UI │ ├── RZDebugMenuSettingsForm.h │ ├── RZDebugMenuSettingsForm.m │ ├── RZDebugMenuShortTitles.h │ └── RZDebugMenuShortTitles.m ├── UIViewController+RZDebugMenuPresentationAdditions.h └── UIViewController+RZDebugMenuPresentationAdditions.m ├── Demo ├── .gitignore ├── Podfile ├── RZDebugMenuDemo.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── RZDebugMenuDemo.xcscheme └── RZDebugMenuDemo │ ├── Application │ ├── RZAppDelegate.h │ └── RZAppDelegate.m │ ├── Resources │ ├── EvenMoreSettings.plist │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── LaunchImage.launchimage │ │ │ └── Contents.json │ │ └── greg.imageset │ │ │ ├── Contents.json │ │ │ └── greg.jpeg │ ├── Launch Screen.xib │ ├── MoreSettings.plist │ └── Settings.plist │ ├── Supporting Files │ ├── RZDebugMenuDemo-Info.plist │ ├── RZDebugMenuDemo-Prefix.pch │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m │ └── View Controllers │ ├── RZDebugMenuRootViewController.h │ └── RZDebugMenuRootViewController.m ├── LICENSE ├── README.md ├── RZDebugMenu.podspec ├── RZDebugMenu.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ ├── RZDebugMenu.xccheckout │ └── RZDebugMenuDemo.xccheckout ├── RZDebugMenu ├── Podfile ├── Podfile.lock ├── RZDebugMenu-Prefix.pch ├── RZDebugMenu.xcodeproj │ └── project.pbxproj ├── RZDebugMenu.xcworkspace │ └── contents.xcworkspacedata └── RZDebugMenuTests │ └── Info.plist └── Rakefile /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | !RZDebugMenu.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | Pods 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_install: 3 | - export LANG=en_US.UTF-8 4 | - rake clean 5 | - rake install 6 | script: 7 | - rake build 8 | notifications: 9 | email: 10 | recipients: 11 | - michael.gorbach@raizlabs.com 12 | on_success: change 13 | on_failure: always 14 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuChildPaneItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugChildPaneMenuItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuItem.h" 10 | 11 | @interface RZDebugMenuChildPaneItem : RZDebugMenuItem 12 | 13 | - (instancetype)initWithTitle:(NSString *)title plistName:(NSString *)plistName NS_DESIGNATED_INITIALIZER; 14 | 15 | @property (copy, nonatomic, readonly) NSString *plistName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuChildPaneItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugChildPaneMenuItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuChildPaneItem.h" 10 | 11 | @interface RZDebugMenuChildPaneItem () 12 | 13 | @property (copy, nonatomic, readwrite) NSString *plistName; 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuChildPaneItem 18 | 19 | - (instancetype)initWithTitle:(NSString *)title plistName:(NSString *)plistName 20 | { 21 | self = [super initWithTitle:title]; 22 | if ( self ) { 23 | self.plistName = plistName; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | - (instancetype)initWithTitle:(NSString *)title 30 | { 31 | return [self initWithTitle:title plistName:nil]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuGroupItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuGroupItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 7/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuItem.h" 10 | 11 | @interface RZDebugMenuGroupItem : RZDebugMenuItem 12 | 13 | - (instancetype)initWithTitle:(NSString *)title children:(NSArray *)children NS_DESIGNATED_INITIALIZER; 14 | 15 | @property (copy, nonatomic, readonly) NSArray *children; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuGroupItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuGroupItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 7/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuGroupItem.h" 10 | 11 | @interface RZDebugMenuGroupItem () 12 | 13 | @property (copy, nonatomic, readwrite) NSArray *children; 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuGroupItem 18 | 19 | - (instancetype)initWithTitle:(NSString *)title children:(NSArray *)children 20 | { 21 | self = [super initWithTitle:title]; 22 | if ( self ) { 23 | self.children = children; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | - (instancetype)initWithTitle:(NSString *)title 30 | { 31 | return [self initWithTitle:title children:nil]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/10/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | @interface RZDebugMenuItem : NSObject 10 | 11 | @property (copy, nonatomic, readonly) NSString *title; 12 | 13 | - (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/10/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuItem.h" 10 | 11 | @implementation RZDebugMenuItem 12 | 13 | - (instancetype)initWithTitle:(NSString *)title 14 | { 15 | self = [super init]; 16 | if ( self ) { 17 | _title = title; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuLoadedChildPaneItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuLoadedChildPaneItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuChildPaneItem.h" 10 | 11 | @interface RZDebugMenuLoadedChildPaneItem : RZDebugMenuChildPaneItem 12 | 13 | - (instancetype)initWithTitle:(NSString *)title plistName:(NSString *)plistName settingsMenuItems:(NSArray *)settingsMenuItems NS_DESIGNATED_INITIALIZER; 14 | 15 | @property (copy, nonatomic, readonly) NSArray *settingsMenuItems; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuLoadedChildPaneItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuLoadedChildPaneItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuLoadedChildPaneItem.h" 10 | 11 | @interface RZDebugMenuLoadedChildPaneItem () 12 | 13 | @property (copy, nonatomic, readwrite) NSArray *settingsMenuItems; 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuLoadedChildPaneItem 18 | 19 | - (instancetype)initWithTitle:(NSString *)title plistName:(NSString *)plistName settingsMenuItems:(NSArray *)settingsMenuItems 20 | { 21 | self = [super initWithTitle:title plistName:plistName]; 22 | if ( self ) { 23 | self.settingsMenuItems = settingsMenuItems; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | - (instancetype)initWithTitle:(NSString *)title plistName:(NSString *)plistName 30 | { 31 | return [self initWithTitle:title plistName:plistName settingsMenuItems:nil]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuMultiValueItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuMultiValueItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @interface RZDebugMenuMultiValueItem : RZDebugMenuSettingItem 12 | 13 | @property (strong, nonatomic, readonly) NSArray *selectionItems; 14 | 15 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title selectionItems:(NSArray *)selectionItems NS_DESIGNATED_INITIALIZER; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuMultiValueItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuMultiValueItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuMultiValueItem.h" 10 | 11 | @interface RZDebugMenuMultiValueItem () 12 | 13 | @property (strong, nonatomic, readwrite) NSArray *selectionItems; 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuMultiValueItem 18 | 19 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 20 | { 21 | return [self initWithValue:value key:key title:title selectionItems:nil]; 22 | } 23 | 24 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title selectionItems:(NSArray *)selectionItems 25 | { 26 | self = [super initWithValue:value key:key title:title]; 27 | if ( self ) { 28 | _selectionItems = selectionItems; 29 | } 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuMultiValueSelectionItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuMultiValueSelectionItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/10/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuItem.h" 10 | 11 | @interface RZDebugMenuMultiValueSelectionItem : RZDebugMenuItem 12 | 13 | @property (strong, nonatomic, readonly) id value; 14 | 15 | @property (copy, nonatomic, readonly) NSString *longTitle; 16 | @property (copy, nonatomic, readonly) NSString *shortTitle; 17 | 18 | - (instancetype)initWithLongTitle:(NSString *)longTitle shortTitle:(NSString *)shortTitle value:(id)value NS_DESIGNATED_INITIALIZER; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuMultiValueSelectionItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuMultiValueSelectionItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/10/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuMultiValueSelectionItem.h" 10 | 11 | @interface RZDebugMenuMultiValueSelectionItem () 12 | 13 | @property (strong, nonatomic, readwrite) id value; 14 | @property (copy, nonatomic, readwrite) NSString *shortTitle; 15 | 16 | @end 17 | 18 | @implementation RZDebugMenuMultiValueSelectionItem 19 | 20 | - (instancetype)initWithLongTitle:(NSString *)longTitle shortTitle:(NSString *)shortTitle value:(id)value 21 | { 22 | self = [super initWithTitle:longTitle]; 23 | if ( self ) { 24 | self.shortTitle = shortTitle; 25 | self.value = value; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (instancetype)initWithTitle:(NSString *)title 32 | { 33 | return [self initWithLongTitle:title shortTitle:nil value:nil]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSettingItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingItem.h 3 | // Pods 4 | // 5 | // Created by Michael Gorbach on 2/17/15. 6 | // 7 | // 8 | 9 | #import "RZDebugMenuItem.h" 10 | 11 | @interface RZDebugMenuSettingItem : RZDebugMenuItem 12 | 13 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title NS_DESIGNATED_INITIALIZER; 14 | 15 | @property (strong, nonatomic, readonly) NSString *key; 16 | @property (strong, nonatomic) id value; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSettingItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingItem.m 3 | // Pods 4 | // 5 | // Created by Michael Gorbach on 2/17/15. 6 | // 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @implementation RZDebugMenuSettingItem 12 | 13 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 14 | { 15 | self = [super initWithTitle:title]; 16 | if ( self ) { 17 | _key = key; 18 | _value = value; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | - (instancetype)initWithTitle:(NSString *)title 25 | { 26 | return [self initWithValue:nil key:nil title:title]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSettings.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsInterface.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsStore.h" 10 | 11 | extern NSString *const kRZDebugMenuSettingChangedNotification; 12 | 13 | extern NSString *const kRZDebugMenuSettingChangedNotificationSettingKey; 14 | extern NSString *const kRZDebugMenuSettingChangedNotificationSettingPreviousValueKey; 15 | extern NSString *const kRZDebugMenuSettingChangedNotificationSettingNewValueKey; 16 | 17 | @interface RZDebugMenuSettings : NSObject 18 | 19 | + (RZDebugMenuSettings *)sharedSettings; 20 | 21 | // Keyed access methods. 22 | // You can access and settings via [RZDebugMenuSettings sharedSettings][@"my_setting_key"] 23 | 24 | - (id)objectForKeyedSubscript:(id )key; 25 | - (void)setObject:(id)obj forKeyedSubscript:(id )key; 26 | 27 | // These are all just re-declarations of the standard KVO methods. Standard KVO is the best way to interaction with this class. 28 | 29 | - (id)valueForKey:(NSString *)key; 30 | - (void)setValue:(id)value forKey:(NSString *)key; 31 | 32 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context; 33 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context; 34 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath; 35 | 36 | /** 37 | * Reset all debug settings to their default values. 38 | */ 39 | - (void)reset; 40 | 41 | /** 42 | * Set the class of the store used to persist the debug settigs. By default, this will by an isolated user defaults store. 43 | * 44 | * @param DebugSettingsStoreClass A class with instances that conform to the RZDebugMenuSettingsStore protocol. 45 | */ 46 | - (void)setDebugSettingsStoreClass:(Class)DebugSettingsStoreClass; 47 | - (Class)debugSettingsStoreClass; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSettings.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsInterface.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettings.h" 10 | 11 | #import "RZDebugMenu.h" 12 | #import "RZDebugMenuSettingsStore.h" 13 | #import "RZDebugMenuSettings_Private.h" 14 | #import "RZDebugMenuIsolatedUserDefaultsStore.h" 15 | 16 | NSString *const kRZDebugMenuSettingChangedNotificationSettingKey = @"setting"; 17 | NSString *const kRZDebugMenuSettingChangedNotificationSettingPreviousValueKey = @"previousValue"; 18 | NSString *const kRZDebugMenuSettingChangedNotificationSettingNewValueKey = @"newValue"; 19 | 20 | @interface RZDebugMenuSettings () 21 | 22 | @property (copy, nonatomic, readwrite) NSArray *keys; 23 | @property (copy, nonatomic, readwrite) NSDictionary *defaultValues; 24 | 25 | @property (strong, nonatomic, readwrite) Class debugSettingsStoreClass; 26 | 27 | @property (strong, nonatomic, readwrite) id settingsStore; 28 | 29 | @end 30 | 31 | @implementation RZDebugMenuSettings 32 | 33 | @synthesize debugSettingsStoreClass = _debugSettingsStoreClass; 34 | 35 | static RZDebugMenuSettings *s_sharedSettings; 36 | 37 | + (RZDebugMenuSettings *)sharedSettings 38 | { 39 | NSAssert(s_sharedSettings != nil, @"Settings access before initialization!"); 40 | return s_sharedSettings; 41 | } 42 | 43 | + (void)initializeWithKeys:(NSArray *)keys defaultValues:(NSDictionary *)defaultvalues 44 | { 45 | static dispatch_once_t onceToken; 46 | dispatch_once(&onceToken, ^{ 47 | s_sharedSettings = [[RZDebugMenuSettings alloc] initWithKeys:keys defaultValues:defaultvalues]; 48 | }); 49 | } 50 | 51 | - (instancetype)initWithKeys:(NSArray *)keys defaultValues:(NSDictionary *)defaultValues 52 | { 53 | self = [super init]; 54 | if ( self ) { 55 | self.keys = keys; 56 | self.defaultValues = defaultValues; 57 | } 58 | 59 | return self; 60 | } 61 | 62 | - (id )settingsStore 63 | { 64 | if ( _settingsStore == nil ) { 65 | Class DebugSettingsStoreClass = _debugSettingsStoreClass; 66 | 67 | NSAssert(DebugSettingsStoreClass == Nil || [DebugSettingsStoreClass conformsToProtocol:@protocol(RZDebugMenuSettingsStore)], @""); 68 | 69 | if ( DebugSettingsStoreClass == Nil ) { 70 | DebugSettingsStoreClass = [RZDebugMenuIsolatedUserDefaultsStore class]; 71 | } 72 | 73 | _settingsStore = [[DebugSettingsStoreClass alloc] initWithKeys:self.keys defaultValues:self.defaultValues]; 74 | } 75 | 76 | return _settingsStore; 77 | } 78 | 79 | - (void)reset 80 | { 81 | [self.settingsStore reset]; 82 | } 83 | 84 | // Keyed access pass-through. 85 | 86 | - (id)objectForKeyedSubscript:(id )key 87 | { 88 | return [self.settingsStore objectForKeyedSubscript:key]; 89 | } 90 | 91 | - (void)setObject:(id)obj forKeyedSubscript:(id )key 92 | { 93 | [self.settingsStore setObject:obj forKeyedSubscript:key]; 94 | } 95 | 96 | // KVO pass-through. 97 | 98 | - (id)valueForKey:(NSString *)key 99 | { 100 | return [self.settingsStore valueForKey:key]; 101 | } 102 | 103 | - (void)setValue:(id)value forKey:(NSString *)key 104 | { 105 | [self.settingsStore setValue:value forKey:key]; 106 | } 107 | 108 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context 109 | { 110 | [self.settingsStore addObserver:observer forKeyPath:keyPath options:options context:context]; 111 | } 112 | 113 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context 114 | { 115 | [self.settingsStore removeObserver:observer forKeyPath:keyPath context:context]; 116 | } 117 | 118 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 119 | { 120 | [self.settingsStore removeObserver:observer forKeyPath:keyPath]; 121 | } 122 | 123 | // Store Access 124 | 125 | - (void)setDebugSettingsStoreClass:(Class)DebugSettingsStoreClass 126 | { 127 | NSAssert(_settingsStore == nil, @"The settings store class can not be set after initialization of the settings store."); 128 | _debugSettingsStoreClass = DebugSettingsStoreClass; 129 | } 130 | 131 | // Notifications 132 | 133 | - (void)postChangeNotificationSettingsName:(NSString *)settingName previousValue:(id)previousValue newValue:(id)newValue 134 | { 135 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 136 | if ( settingName ) { 137 | userInfo[kRZDebugMenuSettingChangedNotificationSettingKey] = settingName; 138 | } 139 | 140 | if ( previousValue ) { 141 | userInfo[kRZDebugMenuSettingChangedNotificationSettingPreviousValueKey] = previousValue; 142 | } 143 | 144 | if ( newValue ) { 145 | userInfo[kRZDebugMenuSettingChangedNotificationSettingNewValueKey] = newValue; 146 | } 147 | 148 | [[NSNotificationCenter defaultCenter] postNotificationName:kRZDebugMenuSettingChangedNotification object:self userInfo:[userInfo copy]]; 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSettings_Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettings_Private.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/24/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettings.h" 10 | 11 | @interface RZDebugMenuSettings () 12 | 13 | + (void)initializeWithKeys:(NSArray *)keys defaultValues:(NSDictionary *)defaultvalues; 14 | 15 | - (void)postChangeNotificationSettingsName:(NSString *)settingName previousValue:(id)oldValue newValue:(id)newValue; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSliderItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSliderItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/30/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @interface RZDebugMenuSliderItem : RZDebugMenuSettingItem 12 | 13 | @property (strong, nonatomic, readonly) NSNumber *max; 14 | @property (strong, nonatomic, readonly) NSNumber *min; 15 | 16 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title maxValue:(NSNumber *)max minValue:(NSNumber *)min NS_DESIGNATED_INITIALIZER; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuSliderItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSliderItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/30/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSliderItem.h" 10 | 11 | @interface RZDebugMenuSliderItem () 12 | 13 | @property (strong, nonatomic, readwrite) NSNumber *sliderCellDefaultValue; 14 | @property (strong, nonatomic, readwrite) NSNumber *max; 15 | @property (strong, nonatomic, readwrite) NSNumber *min; 16 | 17 | @end 18 | 19 | @implementation RZDebugMenuSliderItem 20 | 21 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title maxValue:(NSNumber *)max minValue:(NSNumber *)min 22 | { 23 | self = [super initWithValue:value key:key title:title]; 24 | if ( self ) { 25 | _sliderCellDefaultValue = self.value; 26 | _max = max ?: @(1); 27 | _min = min ?: @(0); 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 34 | { 35 | return [self initWithValue:value key:key title:title maxValue:nil minValue:nil]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuTextFieldItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuTextFieldItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/30/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @interface RZDebugMenuTextFieldItem : RZDebugMenuSettingItem 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuTextFieldItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuTextFieldItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/30/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuTextFieldItem.h" 10 | 11 | @interface RZDebugMenuTextFieldItem () 12 | 13 | @property (strong, nonatomic, readwrite) NSString *textFieldCellDefaultValue; 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuTextFieldItem 18 | 19 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 20 | { 21 | self = [super initWithValue:value key:key title:title]; 22 | if ( self ) { 23 | _textFieldCellDefaultValue = self.value; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuTitleItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuTitleItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/25/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @interface RZDebugMenuTitleItem : RZDebugMenuSettingItem 12 | 13 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title values:(NSArray *)values titles:(NSArray *)titles NS_DESIGNATED_INITIALIZER; 14 | 15 | @property (copy, nonatomic, readonly) NSArray *values; 16 | @property (copy, nonatomic, readonly) NSArray *titles; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuTitleItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuTitleItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/25/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuTitleItem.h" 10 | 11 | @interface RZDebugMenuTitleItem () 12 | 13 | @property (copy, nonatomic, readwrite) NSArray *values; 14 | @property (copy, nonatomic, readwrite) NSArray *titles; 15 | 16 | @end 17 | 18 | @implementation RZDebugMenuTitleItem 19 | 20 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title values:(NSArray *)values titles:(NSArray *)titles 21 | { 22 | self = [super initWithValue:value key:key title:title]; 23 | if ( self ) { 24 | self.values = values; 25 | self.titles = titles; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 32 | { 33 | return [self initWithValue:value key:key title:title values:nil titles:nil]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuToggleItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuToggleItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingItem.h" 10 | 11 | @interface RZDebugMenuToggleItem : RZDebugMenuSettingItem 12 | 13 | - (instancetype)initWithValue:(id)value 14 | key:(NSString *)key 15 | title:(NSString *)title 16 | trueValue:(id)trueValue 17 | falseValue:(id)falseValue 18 | NS_DESIGNATED_INITIALIZER; 19 | 20 | @property (strong, nonatomic, readonly) id trueValue; 21 | @property (strong, nonatomic, readonly) id falseValue; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuToggleItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuToggleItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuToggleItem.h" 10 | 11 | @interface RZDebugMenuToggleItem () 12 | 13 | @property (strong, nonatomic, readwrite) id trueValue; 14 | @property (strong, nonatomic, readwrite) id falseValue; 15 | 16 | @end 17 | 18 | @implementation RZDebugMenuToggleItem 19 | 20 | - (instancetype)initWithValue:(id)value 21 | key:(NSString *)key 22 | title:(NSString *)title 23 | trueValue:(id)trueValue 24 | falseValue:(id)falseValue 25 | { 26 | self = [super initWithValue:value key:key title:title]; 27 | if ( self ) { 28 | self.trueValue = trueValue; 29 | self.falseValue = falseValue; 30 | } 31 | 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithValue:(id)value key:(NSString *)key title:(NSString *)title 36 | { 37 | return [self initWithValue:value key:key title:title trueValue:nil falseValue:nil]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuVersionItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuVersionItem.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | // NOTE: This class is READONLY and can not be altered via any interfaces 9 | 10 | #import "RZDebugMenuItem.h" 11 | 12 | @interface RZDebugMenuVersionItem : RZDebugMenuItem 13 | 14 | @property (copy, nonatomic, readonly) NSString *versionString; 15 | 16 | /** 17 | * Use this method to automatically guess the version string from Info.plist. 18 | * 19 | * @return Newly initialized instance. 20 | */ 21 | - (instancetype)init; 22 | 23 | /** 24 | * Use this method to manually specify a version string. 25 | * 26 | * @param version Version string. 27 | * 28 | * @return Newly initialized instance. 29 | */ 30 | - (instancetype)initWithVersionString:(NSString *)version NS_DESIGNATED_INITIALIZER; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Classes/Models/RZDebugMenuVersionItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuVersionItem.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/6/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | // NOTE: This class is READONLY and can not be altered via any interfaces 9 | 10 | #import "RZDebugMenuVersionItem.h" 11 | 12 | static NSString *const kRZVersionNotFound = @"Not Found"; 13 | static NSString *const kRZVersionFormat = @"%@ (%@)"; 14 | 15 | static NSString *const kRZCFBundleVersionKey = @"CFBundleVersion"; 16 | static NSString *const kRZCFBundleShortVersionStringKey = @"CFBundleShortVersionString"; 17 | static NSString *const kRZCFBundleNameKey = @"CFBundleName"; 18 | 19 | @interface RZDebugMenuVersionItem () 20 | 21 | @property (copy, nonatomic, readwrite) NSString *versionString; 22 | 23 | @end 24 | 25 | @implementation RZDebugMenuVersionItem 26 | 27 | - (instancetype)initWithVersionString:(NSString *)versionString 28 | { 29 | self = [super initWithTitle:[[self class] applicationName]]; 30 | if ( self ) { 31 | _versionString = versionString; 32 | } 33 | return self; 34 | } 35 | 36 | + (NSString *)applicationName 37 | { 38 | NSString *name = [[NSBundle mainBundle] objectForInfoDictionaryKey:kRZCFBundleNameKey]; 39 | if ( name.length == 0 ) { 40 | name = kRZVersionNotFound; 41 | } 42 | 43 | return name; 44 | } 45 | 46 | + (NSString *)versionString 47 | { 48 | NSString *versionString = kRZVersionNotFound; 49 | 50 | NSString *shortVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:kRZCFBundleShortVersionStringKey]; 51 | if ( shortVersionString.length > 0 ) { 52 | versionString = shortVersionString; 53 | } 54 | 55 | NSString *bundleVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:kRZCFBundleVersionKey]; 56 | if ( bundleVersionString.length > 0 && [shortVersionString isEqualToString:versionString] == NO ) { 57 | if ( shortVersionString.length > 0 ) { 58 | versionString = [NSString stringWithFormat:kRZVersionFormat, shortVersionString, bundleVersionString]; 59 | } 60 | else { 61 | versionString = bundleVersionString; 62 | } 63 | } 64 | 65 | return versionString; 66 | } 67 | 68 | - (instancetype)initWithTitle:(NSString *)title 69 | { 70 | return [self init]; 71 | } 72 | 73 | - (instancetype)init 74 | { 75 | return [self initWithVersionString:[[self class] versionString]]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Classes/RZDebugLogMenuDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugLogMenuDefines.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 7/3/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #ifndef RZDebugMenuDemo_RZDebugLogMenuDefines_h 10 | #define RZDebugMenuDemo_RZDebugLogMenuDefines_h 11 | 12 | #if DEBUG 13 | #define RZDebugMenuLogDebug( s, ... ) NSLog((@"[RZDebugMenu]: DEBUG -- s"), ##__VA_ARGS__) 14 | #else 15 | #define RZDebugMenuLogDebug( s, ... ) 16 | #endif 17 | 18 | #define RZDebugMenuLogError( s, ... ) NSLog((@"[RZDebugMenu]: ERROR -- s"). ##__VA_ARGS__) 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Classes/RZDebugMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenu.h 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/11/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | /** 10 | * Observer notification name constant. Notification with this name sent on a change in the Debug Menu. The userInfo on the Notification sent contains the setting's key:value pair that was changed. 11 | */ 12 | OBJC_EXTERN NSString* const kRZDebugMenuSettingChangedNotification; 13 | 14 | /** 15 | * RZDebug Menu Class 16 | * 17 | * @warning Can not call 'init' on this class, otherwise app will throw exception 18 | */ 19 | @interface RZDebugMenu : NSObject 20 | /** @name RZDebugMenu Interface */ 21 | 22 | /** 23 | * Enables the debug menu with a specified settings plist 24 | * 25 | * @param fileName Name of the plist which defines the debug settings to be used. The plist should conform to the standard Settings Bundle plist format. 26 | */ 27 | + (void)enableMenuWithSettingsPlistName:(NSString *)plistName; 28 | 29 | /** 30 | * Access the shared debug menu. 31 | * 32 | * @return If yopu have called enableMenuWithSettingsPlistName:, this will return the shared debug debug. 33 | */ 34 | + (instancetype)sharedDebugMenu; 35 | 36 | /** 37 | * Configure presentation of the debug menu button with a 3-finger, 3-tap gesture on the specified view. 38 | * 39 | * @param view The view on which to set up the presentation gesture. 40 | */ 41 | - (void)registerDebugMenuPresentationGestureOnView:(UIView *)view; 42 | 43 | /** 44 | * Manually present the debug menu on the root view controller of the presentation's main window, or the deepest presented view controller if a presentation is already active. 45 | */ 46 | - (void)presentDebugMenu; 47 | 48 | /** 49 | * Manually dismiss the debug menu, if it is currently presented. 50 | */ 51 | - (void)dismissDebugMenu; 52 | 53 | /** 54 | * The top-level view controller for the debug menu to present (in case you want to present it manually yourself). 55 | */ 56 | @property (strong, nonatomic, readonly) UIViewController *debugMenuViewControllerToPresent; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/RZDebugMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenu.m 3 | // RZDebugMenu 4 | // 5 | // Created by Clayton Rieck on 6/11/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenu.h" 10 | 11 | #import "RZDebugMenuSettings.h" 12 | #import "RZDebugMenuSettingsForm.h" 13 | #import "RZDebugMenuSettingsParser.h" 14 | #import "RZDebugMenuChildPaneItem.h" 15 | #import "RZDebugMenuLoadedChildPaneItem.h" 16 | #import "RZDebugMenuGroupItem.h" 17 | #import "RZDebugMenuFormViewController.h" 18 | #import "RZDebugMenuSettings_Private.h" 19 | #import "RZDebugMenuVersionItem.h" 20 | #import "RZDebugMenuGroupItem.h" 21 | #import "UIViewController+RZDebugMenuPresentationAdditions.h" 22 | 23 | #import "RZDebugLogMenuDefines.h" 24 | 25 | #import 26 | 27 | static NSString *const kRZVersionTitle = @"Version"; 28 | 29 | NSString* const kRZDebugMenuSettingChangedNotification = @"RZDebugMenuSettingChanged"; 30 | 31 | static NSUInteger kRZNumberOfTapsToShow = 3; 32 | static NSUInteger kRZNumberOfTouchesToShow = 2; 33 | 34 | @interface RZDebugMenu () 35 | 36 | @property (strong, nonatomic, readwrite) UIViewController *debugMenuViewControllerToPresent; 37 | 38 | @property (strong, nonatomic, readwrite) NSArray *settingsMenuItems; 39 | 40 | @end 41 | 42 | @implementation RZDebugMenu 43 | 44 | #pragma mark - Public API 45 | 46 | + (instancetype)sharedDebugMenu 47 | { 48 | static RZDebugMenu *s_sharedInstance = nil; 49 | static dispatch_once_t onceToken; 50 | dispatch_once(&onceToken, ^{ 51 | s_sharedInstance = [[RZDebugMenu alloc] init_internal]; 52 | }); 53 | 54 | return s_sharedInstance; 55 | } 56 | 57 | + (void)enableMenuWithSettingsPlistName:(NSString *)plistName 58 | { 59 | [[self sharedDebugMenu] loadSettingsMenuFromPlistName:plistName]; 60 | } 61 | 62 | # pragma mark - Lifecycle 63 | 64 | - (instancetype)init 65 | { 66 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 67 | reason:@"RZDebugMenu cannot be instantiated. Please use the class method interface." 68 | userInfo:nil]; 69 | } 70 | 71 | - (RZDebugMenu *)init_internal 72 | { 73 | self = [super init]; 74 | if ( self ) { 75 | [self configureDebugMenu]; 76 | } 77 | 78 | return self; 79 | } 80 | 81 | #pragma mark - Configuration 82 | 83 | - (void)configureDebugMenu 84 | { 85 | if ( self.settingsMenuItems.count > 0 ) { 86 | RZDebugMenuSettingsForm *settingsForm = [[RZDebugMenuSettingsForm alloc] initWithSettingsMenuItems:self.settingsMenuItems]; 87 | 88 | RZDebugMenuFormViewController *settingsMenuViewController = [[RZDebugMenuFormViewController alloc] init]; 89 | settingsMenuViewController.delegate = self; 90 | 91 | settingsForm.delegate = settingsMenuViewController; 92 | 93 | settingsMenuViewController.formController.form = settingsForm; 94 | 95 | UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsMenuViewController]; 96 | 97 | self.debugMenuViewControllerToPresent = modalNavigationController; 98 | } 99 | } 100 | 101 | #pragma mark - Settings Menu 102 | 103 | - (void)loadSettingsMenuFromPlistName:(NSString *)plistName 104 | { 105 | NSError *settingsParsingError = nil; 106 | NSArray *keys = nil; 107 | NSDictionary *defaultValues = nil; 108 | 109 | NSArray *settingsMenuItems = [RZDebugMenuSettingsParser settingsMenuItemsFromPlistName:plistName 110 | returningKeys:&keys 111 | defaultValues:&defaultValues 112 | error:&settingsParsingError]; 113 | if ( settingsMenuItems ) { 114 | // We've loaded all our settings. Initialize the store. 115 | [RZDebugMenuSettings initializeWithKeys:keys defaultValues:defaultValues]; 116 | } 117 | else { 118 | NSLog(@"Failed to parse settings from plist %@: %@.", plistName, settingsParsingError); 119 | } 120 | 121 | if ( settingsMenuItems ) { 122 | RZDebugMenuVersionItem *versionItem = [[RZDebugMenuVersionItem alloc] init]; 123 | RZDebugMenuGroupItem *versionGroupItem = [[RZDebugMenuGroupItem alloc] initWithTitle:kRZVersionTitle children:@[versionItem]]; 124 | settingsMenuItems = [settingsMenuItems arrayByAddingObject:versionGroupItem]; 125 | } 126 | 127 | self.settingsMenuItems = settingsMenuItems; 128 | 129 | [self configureDebugMenu]; 130 | } 131 | 132 | # pragma mark - Presentation 133 | 134 | - (void)registerDebugMenuPresentationGestureOnView:(UIView *)view 135 | { 136 | NSAssert(view != nil, @""); 137 | 138 | UITapGestureRecognizer *manyTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(debugMenuActivationGestureRecognizerFired:)]; 139 | manyTapGestureRecognizer.numberOfTapsRequired = kRZNumberOfTapsToShow; 140 | manyTapGestureRecognizer.numberOfTouchesRequired = kRZNumberOfTouchesToShow; 141 | 142 | [view addGestureRecognizer:manyTapGestureRecognizer]; 143 | } 144 | 145 | - (void)presentDebugMenu 146 | { 147 | if ( self.debugMenuViewControllerToPresent.presentingViewController != nil ) { 148 | NSLog(@"Not presenting debug menu. It is already active."); 149 | return; 150 | } 151 | 152 | if ( self.debugMenuViewControllerToPresent == nil ) { 153 | NSLog(@"No debug menu enabled. Not presenting."); 154 | return; 155 | } 156 | 157 | UIViewController *viewControllerToPresentOn = [UIApplication sharedApplication].keyWindow.rootViewController; 158 | viewControllerToPresentOn = viewControllerToPresentOn.rzDebugMenu_deepestViewControllerForPresentation; 159 | 160 | [viewControllerToPresentOn presentViewController:self.debugMenuViewControllerToPresent animated:YES completion:nil]; 161 | } 162 | 163 | - (void)debugMenuActivationGestureRecognizerFired:(id)sender 164 | { 165 | [self presentDebugMenu]; 166 | } 167 | 168 | - (void)dismissDebugMenu 169 | { 170 | if ( self.debugMenuViewControllerToPresent.presentingViewController ) { 171 | [self.debugMenuViewControllerToPresent dismissViewControllerAnimated:YES completion:nil]; 172 | } 173 | } 174 | 175 | # pragma mark - RZDebugMenuFormViewControllerDelegate 176 | 177 | - (void)debugMenuFormViewControllerShouldDimiss:(RZDebugMenuFormViewController *)debugMenuFormViewController 178 | { 179 | [self dismissDebugMenu]; 180 | } 181 | 182 | @end 183 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuFormViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuFormViewController.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "RZDebugMenuSettingsForm.h" 12 | 13 | @class RZDebugMenuFormViewController; 14 | 15 | @protocol RZDebugMenuFormViewControllerDelegate 16 | 17 | - (void)debugMenuFormViewControllerShouldDimiss:(RZDebugMenuFormViewController *)debugMenuFormViewController; 18 | 19 | @end 20 | 21 | @interface RZDebugMenuFormViewController : FXFormViewController 22 | 23 | @property (weak, nonatomic, readwrite) id delegate; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuFormViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuFormViewController.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/19/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuFormViewController.h" 10 | 11 | #import "RZDebugMenuSettingsForm.h" 12 | 13 | static NSString *const kRZNavigationBarTitle = @"Debug Menu"; 14 | 15 | static NSString *const kRZNavigationBarDoneButtonTitle = @"Done"; 16 | 17 | @interface RZDebugMenuFormViewController () 18 | 19 | - (IBAction)doneButtonTapped:(id)sender; 20 | 21 | @end 22 | 23 | @implementation RZDebugMenuFormViewController 24 | 25 | - (void)viewDidLoad 26 | { 27 | [super viewDidLoad]; 28 | 29 | UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:kRZNavigationBarDoneButtonTitle 30 | style:UIBarButtonItemStylePlain 31 | target:self 32 | action:@selector(doneButtonTapped:)]; 33 | self.navigationItem.rightBarButtonItem = doneButton; 34 | } 35 | 36 | - (NSString *)title 37 | { 38 | return kRZNavigationBarTitle; 39 | } 40 | 41 | - (void)doneButtonTapped:(id)sender 42 | { 43 | [self.delegate debugMenuFormViewControllerShouldDimiss:self]; 44 | } 45 | 46 | # pragma mark - RZDebugMenuSettingsFormDelegate 47 | 48 | - (UIViewController *)viewControllerForChildPaneItem:(RZDebugMenuLoadedChildPaneItem *)childPaneItem 49 | { 50 | NSAssert(childPaneItem != nil, @""); 51 | 52 | RZDebugMenuFormViewController *formViewController = [[RZDebugMenuFormViewController alloc] initWithNibName:nil bundle:nil]; 53 | formViewController.delegate = self.delegate; 54 | 55 | return formViewController; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuIsolatedUserDefaultsStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuIsolatedUserDefaultsStore.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/24/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsStore.h" 10 | 11 | @interface RZDebugMenuIsolatedUserDefaultsStore : RZDebugMenuSettingsStore 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuIsolatedUserDefaultsStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuIsolatedUserDefaultsStore.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/24/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuIsolatedUserDefaultsStore.h" 10 | 11 | #import "RZDebugMenuSettings_Private.h" 12 | 13 | static NSString *const kRZIsolatedUserDefaultsDictionaryKey = @"debugSettings"; 14 | 15 | @interface RZDebugMenuIsolatedUserDefaultsStore () 16 | 17 | @end 18 | 19 | @implementation RZDebugMenuIsolatedUserDefaultsStore 20 | 21 | - (void)setValue:(id)value forKey:(NSString *)key 22 | { 23 | id previousValue = [self valueForKey:key]; 24 | 25 | id defaultValue = [self defaultValueForKey:key]; 26 | if ( value && [previousValue isEqual:value] ) { 27 | // Nothing to do here. Don't even send change notifications. 28 | return; 29 | } 30 | 31 | [self willChangeValueForKey:key]; 32 | 33 | NSDictionary *debugSettingsDictionary = [[NSUserDefaults standardUserDefaults] objectForKey:kRZIsolatedUserDefaultsDictionaryKey]; 34 | 35 | NSMutableDictionary *mutableDebugSettingsDictionary = debugSettingsDictionary ? [debugSettingsDictionary mutableCopy] : [NSMutableDictionary dictionary]; 36 | 37 | // For a default value, simply remove the key and it will fall through to our part. 38 | if ( value && [value isEqual:defaultValue] == NO ) { 39 | mutableDebugSettingsDictionary[key] = value; 40 | } 41 | else { 42 | [mutableDebugSettingsDictionary removeObjectForKey:key]; 43 | } 44 | 45 | debugSettingsDictionary = [mutableDebugSettingsDictionary copy]; 46 | 47 | [[NSUserDefaults standardUserDefaults] setObject:debugSettingsDictionary forKey:kRZIsolatedUserDefaultsDictionaryKey]; 48 | 49 | [self didChangeValueForKey:key]; 50 | 51 | [[RZDebugMenuSettings sharedSettings] postChangeNotificationSettingsName:key previousValue:previousValue newValue:value]; 52 | } 53 | 54 | - (id)innerValueForKey:(NSString *)key 55 | { 56 | NSDictionary *debugSettingsDictionary = [[NSUserDefaults standardUserDefaults] objectForKey:kRZIsolatedUserDefaultsDictionaryKey]; 57 | 58 | id objectToReturn = [debugSettingsDictionary objectForKey:key]; 59 | return objectToReturn; 60 | } 61 | 62 | - (id)valueForKey:(NSString *)key 63 | { 64 | id objectToReturn = [self innerValueForKey:key]; 65 | if ( objectToReturn == nil ) { 66 | objectToReturn = [super valueForKey:key]; 67 | } 68 | 69 | return objectToReturn; 70 | } 71 | 72 | - (void)reset 73 | { 74 | NSDictionary *debugSettingsDictionary = [[NSUserDefaults standardUserDefaults] objectForKey:kRZIsolatedUserDefaultsDictionaryKey]; 75 | 76 | __block NSMutableDictionary *previousValues = nil; 77 | 78 | NSArray *keysBeingReset = [[debugSettingsDictionary keyEnumerator] allObjects]; 79 | [keysBeingReset enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) { 80 | 81 | id previousValue = [self innerValueForKey:key]; 82 | if ( previousValue ) { 83 | if ( previousValues == nil ) { 84 | previousValues = [NSMutableDictionary dictionary]; 85 | } 86 | 87 | previousValues[key] = previousValue; 88 | } 89 | 90 | [self willChangeValueForKey:key]; 91 | }]; 92 | 93 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kRZIsolatedUserDefaultsDictionaryKey]; 94 | 95 | [[[keysBeingReset reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) { 96 | [self didChangeValueForKey:key]; 97 | 98 | id defaultValue = [self defaultValueForKey:key]; 99 | id previousValue = previousValues[key]; 100 | 101 | if ( previousValue ) { 102 | [[RZDebugMenuSettings sharedSettings] postChangeNotificationSettingsName:key previousValue:previousValue newValue:defaultValue]; 103 | } 104 | }]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuSettingsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsParser.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/18/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | @interface RZDebugMenuSettingsParser : NSObject 10 | 11 | + (NSArray *)settingsMenuItemsFromSettingsDictionary:(NSDictionary *)settingsDictionary 12 | returningKeys:(NSArray **)outKeys 13 | defaultValues:(NSDictionary **)outDefaultValues 14 | error:(NSError * __autoreleasing *)outError; 15 | 16 | + (NSArray *)settingsMenuItemsFromPlistName:(NSString *)plistName 17 | returningKeys:(NSArray **)outKeys 18 | defaultValues:(NSDictionary **)outDefaultValues 19 | error:(NSError * __autoreleasing *)outError; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuSettingsParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsParser.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/18/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsParser.h" 10 | 11 | #import "RZDebugMenu.h" 12 | #import "RZDebugMenuItem.h" 13 | #import "RZDebugMenuMultiValueItem.h" 14 | #import "RZDebugMenuToggleItem.h" 15 | #import "RZDebugMenuTextFieldItem.h" 16 | #import "RZDebugMenuSliderItem.h" 17 | #import "RZDebugMenuGroupItem.h" 18 | #import "RZDebugMenuChildPaneItem.h" 19 | #import "RZDebugMenuLoadedChildPaneItem.h" 20 | #import "RZDebugMenuMultiValueSelectionItem.h" 21 | #import "RZDebugMenuTitleItem.h" 22 | 23 | static NSString* const kRZSettingsFileExtension = @"plist"; 24 | 25 | static NSString* const kRZPreferenceSpecifiersKey = @"PreferenceSpecifiers"; 26 | static NSString* const kRZMultiValueSpecifier = @"PSMultiValueSpecifier"; 27 | static NSString* const kRZToggleSwitchSpecifier = @"PSToggleSwitchSpecifier"; 28 | static NSString* const kRZTextFieldSpecifier = @"PSTextFieldSpecifier"; 29 | static NSString* const kRZSliderSpecifier = @"PSSliderSpecifier"; 30 | static NSString* const kRZGroupSpecifer = @"PSGroupSpecifier"; 31 | static NSString* const kRZChildPaneSpecifer = @"PSChildPaneSpecifier"; 32 | static NSString* const kRZTitleSpecifier = @"PSTitleValueSpecifier"; 33 | 34 | static NSString* const kRZKeyBundleVersionString = @"CFBundleShortVersionString"; 35 | 36 | static NSString* const kRZKeyItemIdentifier = @"Key"; 37 | static NSString* const kRZKeyTitle = @"Title"; 38 | static NSString* const kRZKeyType = @"Type"; 39 | static NSString* const kRZKeyFile = @"File"; 40 | static NSString* const kRZKeyDefaultValue = @"DefaultValue"; 41 | 42 | static NSString* const kRZKeyEnvironmentsTitles = @"Titles"; 43 | static NSString* const kRZKeyEnvironmentsShortTitles = @"ShortTitles"; 44 | static NSString* const kRZKeyEnvironmentsValues = @"Values"; 45 | 46 | static NSString* const kRZKeyMaximumValue = @"MaximumValue"; 47 | static NSString* const kRZKeyMinimumValue = @"MinimumValue"; 48 | 49 | static NSString* const kRZKeyTrueValue = @"TrueValue"; 50 | static NSString* const kRZKeyFalseValue = @"FalseValue"; 51 | 52 | @implementation RZDebugMenuSettingsParser 53 | 54 | # pragma mark - Plist Dictionary Parsing 55 | 56 | + (NSArray *)multiValueOptionsArrayWithLongTitles:(NSArray *)longTitles shortTitles:(NSArray *)shortTitles values:(NSArray *)optionValues 57 | { 58 | NSMutableArray *selectionItems = [[NSMutableArray alloc] init]; 59 | 60 | for (NSInteger i = 0; i < longTitles.count; i++) { 61 | 62 | NSString *longTitle = [longTitles objectAtIndex:i]; 63 | NSString *shortTitle = shortTitles ? [shortTitles objectAtIndex:i] : nil; 64 | 65 | NSNumber *value = [optionValues objectAtIndex:i]; 66 | RZDebugMenuMultiValueSelectionItem *selectionItemMetaData = [[RZDebugMenuMultiValueSelectionItem alloc] initWithLongTitle:longTitle 67 | shortTitle:shortTitle 68 | value:value]; 69 | [selectionItems addObject:selectionItemMetaData]; 70 | } 71 | 72 | return [selectionItems copy]; 73 | } 74 | 75 | + (NSArray *)settingsMenuItemsFromSettingsDictionary:(NSDictionary *)settingsDictionary 76 | returningKeys:(NSArray * __autoreleasing *)outKeys 77 | defaultValues:(NSDictionary * __autoreleasing *)outDefaultValues 78 | error:(NSError * __autoreleasing *)outError; 79 | { 80 | NSMutableArray *mutableSettingsMenuItemsToReturn = [NSMutableArray array]; 81 | NSError *errorToReturn = nil; 82 | NSMutableDictionary *mutableDefaultValues = nil; 83 | NSMutableArray *mutableKeys = nil; 84 | 85 | NSArray *preferencesSpecifiers = [settingsDictionary objectForKey:kRZPreferenceSpecifiersKey]; 86 | if ( preferencesSpecifiers ) { 87 | NSAssert([preferencesSpecifiers isKindOfClass:[NSArray class]], @""); 88 | if ( preferencesSpecifiers.count > 0 ) { 89 | NSDictionary *currentGroupSpecifier = nil; 90 | NSMutableArray *currentGroupChildren = nil; 91 | 92 | for ( NSDictionary *preferenceSpecifierDictionary in preferencesSpecifiers ) { 93 | NSString *title = [preferenceSpecifierDictionary objectForKey:kRZKeyTitle]; 94 | NSString *itemType = [preferenceSpecifierDictionary objectForKey:kRZKeyType]; 95 | NSString *itemIdentifier = [preferenceSpecifierDictionary objectForKey:kRZKeyItemIdentifier]; 96 | id defaultValue = [preferenceSpecifierDictionary objectForKey:kRZKeyDefaultValue]; 97 | 98 | RZDebugMenuItem *menuItem = nil; 99 | 100 | if ( [itemType isEqualToString:kRZTextFieldSpecifier] ) { 101 | menuItem = [[RZDebugMenuTextFieldItem alloc] initWithValue:defaultValue key:itemIdentifier title:title]; 102 | } 103 | else if ( [itemType isEqualToString:kRZSliderSpecifier] ) { 104 | NSNumber *maximum = [preferenceSpecifierDictionary objectForKey:kRZKeyMaximumValue]; 105 | NSNumber *minimum = [preferenceSpecifierDictionary objectForKey:kRZKeyMinimumValue]; 106 | menuItem = [[RZDebugMenuSliderItem alloc] initWithValue:defaultValue 107 | key:itemIdentifier 108 | title:title 109 | maxValue:maximum 110 | minValue:minimum]; 111 | } 112 | else if ( [itemType isEqualToString:kRZToggleSwitchSpecifier] ) { 113 | id trueValue = [preferenceSpecifierDictionary objectForKey:kRZKeyTrueValue]; 114 | id falseValue = [preferenceSpecifierDictionary objectForKey:kRZKeyFalseValue]; 115 | 116 | menuItem = [[RZDebugMenuToggleItem alloc] initWithValue:defaultValue 117 | key:itemIdentifier 118 | title:title 119 | trueValue:trueValue 120 | falseValue:falseValue]; 121 | } 122 | else if ( [itemType isEqualToString:kRZMultiValueSpecifier] ) { 123 | NSArray *optionLongTitles = [preferenceSpecifierDictionary objectForKey:kRZKeyEnvironmentsTitles]; 124 | NSArray *optionShortTitles = [preferenceSpecifierDictionary objectForKey:kRZKeyEnvironmentsShortTitles]; 125 | NSArray *optionValues = [preferenceSpecifierDictionary objectForKey:kRZKeyEnvironmentsValues]; 126 | 127 | NSArray *selectionItems = [self multiValueOptionsArrayWithLongTitles:optionLongTitles shortTitles:optionShortTitles values:optionValues]; 128 | 129 | menuItem = [[RZDebugMenuMultiValueItem alloc] initWithValue:defaultValue 130 | key:itemIdentifier 131 | title:title 132 | selectionItems:selectionItems]; 133 | } 134 | else if ( [itemType isEqualToString:kRZGroupSpecifer] ) { 135 | if ( currentGroupSpecifier != nil ) { 136 | 137 | NSString *title = [currentGroupSpecifier objectForKey:kRZKeyTitle]; 138 | RZDebugMenuItem *groupItem = [[RZDebugMenuGroupItem alloc] initWithTitle:title children:currentGroupChildren]; 139 | 140 | [mutableSettingsMenuItemsToReturn addObject:groupItem]; 141 | 142 | currentGroupChildren = nil; 143 | } 144 | 145 | currentGroupSpecifier = preferenceSpecifierDictionary; 146 | } 147 | else if ( [itemType isEqualToString:kRZChildPaneSpecifer] ) { 148 | NSString *plistName = [preferenceSpecifierDictionary objectForKey:kRZKeyFile]; 149 | menuItem = [[RZDebugMenuChildPaneItem alloc] initWithTitle:title plistName:plistName]; 150 | } 151 | else if ( [itemType isEqualToString:kRZTitleSpecifier] ) { 152 | NSArray *titles = [preferenceSpecifierDictionary objectForKey:kRZKeyEnvironmentsTitles]; 153 | NSArray *values = [preferenceSpecifierDictionary objectForKey:kRZKeyEnvironmentsValues]; 154 | menuItem = [[RZDebugMenuTitleItem alloc] initWithValue:defaultValue key:itemIdentifier title:title values:values titles:titles]; 155 | } 156 | else { 157 | NSLog(@"Couldn't recognize preference specifier dictionary: %@.", preferenceSpecifierDictionary); 158 | } 159 | 160 | if ( defaultValue != nil && itemIdentifier.length > 0 ) { 161 | if ( mutableDefaultValues == nil ) { 162 | mutableDefaultValues = [NSMutableDictionary dictionary]; 163 | } 164 | 165 | mutableDefaultValues[itemIdentifier] = defaultValue; 166 | } 167 | 168 | if ( itemIdentifier.length > 0 ) { 169 | if ( mutableKeys == nil ) { 170 | mutableKeys = [NSMutableArray array]; 171 | } 172 | 173 | [mutableKeys addObject:itemIdentifier]; 174 | } 175 | 176 | if ( menuItem ) { 177 | if ( currentGroupSpecifier ) { 178 | if ( currentGroupChildren == nil ) { 179 | currentGroupChildren = [NSMutableArray array]; 180 | } 181 | 182 | [currentGroupChildren addObject:menuItem]; 183 | } 184 | else { 185 | [mutableSettingsMenuItemsToReturn addObject:menuItem]; 186 | } 187 | } 188 | } 189 | 190 | if ( currentGroupSpecifier ) { 191 | NSString *title = [currentGroupSpecifier objectForKey:kRZKeyTitle]; 192 | RZDebugMenuItem *groupItem = [[RZDebugMenuGroupItem alloc] initWithTitle:title children:currentGroupChildren]; 193 | 194 | [mutableSettingsMenuItemsToReturn addObject:groupItem]; 195 | } 196 | } 197 | } 198 | 199 | if ( errorToReturn ) { 200 | mutableSettingsMenuItemsToReturn = nil; 201 | mutableDefaultValues = nil; 202 | mutableKeys = nil; 203 | } 204 | 205 | if ( outDefaultValues ) { 206 | *outDefaultValues = [mutableDefaultValues copy]; 207 | } 208 | 209 | if ( outKeys ) { 210 | *outKeys = [mutableKeys copy]; 211 | } 212 | 213 | if ( outError ) { 214 | *outError = errorToReturn; 215 | } 216 | 217 | return [mutableSettingsMenuItemsToReturn copy]; 218 | } 219 | 220 | # pragma mark - Fiel Reading and Outer Parsing 221 | 222 | + (NSArray *)settingsMenuItemsByRecursivelyLoadingChildPanesFromSettingsMenuItems:(NSArray *)settingsMenuItems 223 | returningKeys:(NSArray * __autoreleasing *)outKeys 224 | defaultValues:(NSDictionary * __autoreleasing *)outDefaultValues 225 | error:(NSError * __autoreleasing *)outError 226 | { 227 | NSError *errorToReturn = nil; 228 | NSMutableArray *mutableSettingsMenuItemsToReturn = [settingsMenuItems mutableCopy]; 229 | NSMutableArray *mutableKeys = nil; 230 | NSMutableDictionary *mutableDefaultValues = nil; 231 | 232 | for ( RZDebugMenuItem *menuItem in settingsMenuItems ) { 233 | NSArray *keysToAdd = nil; 234 | NSDictionary *defaultValuesToAdd = nil; 235 | 236 | if ( [menuItem isKindOfClass:[RZDebugMenuChildPaneItem class]] ) { 237 | NSString *plistName = ((RZDebugMenuChildPaneItem *)menuItem).plistName; 238 | 239 | NSError *childPaneParsingError = nil; 240 | NSArray *childPaneSettingsMenuItems = [[self class] settingsMenuItemsFromPlistName:plistName 241 | returningKeys:&keysToAdd 242 | defaultValues:&defaultValuesToAdd 243 | error:&childPaneParsingError]; 244 | if ( childPaneSettingsMenuItems ) { 245 | RZDebugMenuLoadedChildPaneItem *loadedChildPaneItem = [[RZDebugMenuLoadedChildPaneItem alloc] initWithTitle:menuItem.title 246 | plistName:plistName 247 | settingsMenuItems:childPaneSettingsMenuItems]; 248 | NSUInteger index = [mutableSettingsMenuItemsToReturn indexOfObject:menuItem]; 249 | [mutableSettingsMenuItemsToReturn replaceObjectAtIndex:index withObject:loadedChildPaneItem]; 250 | } 251 | else { 252 | errorToReturn = childPaneParsingError; 253 | break; 254 | } 255 | } 256 | else if ( [menuItem isKindOfClass:[RZDebugMenuGroupItem class]] ) { 257 | RZDebugMenuGroupItem *groupItem = (RZDebugMenuGroupItem *)menuItem; 258 | NSArray *childSettingsMenuItems = groupItem.children; 259 | 260 | NSError *recursiveLoadingError = nil; 261 | childSettingsMenuItems = [self settingsMenuItemsByRecursivelyLoadingChildPanesFromSettingsMenuItems:childSettingsMenuItems 262 | returningKeys:&keysToAdd 263 | defaultValues:&defaultValuesToAdd 264 | error:&recursiveLoadingError]; 265 | 266 | if ( childSettingsMenuItems ) { 267 | groupItem = [[RZDebugMenuGroupItem alloc] initWithTitle:groupItem.title children:childSettingsMenuItems]; 268 | NSUInteger index = [mutableSettingsMenuItemsToReturn indexOfObject:menuItem]; 269 | [mutableSettingsMenuItemsToReturn replaceObjectAtIndex:index withObject:groupItem]; 270 | } 271 | else { 272 | errorToReturn = recursiveLoadingError; 273 | break; 274 | } 275 | } 276 | 277 | if ( keysToAdd ) { 278 | if ( mutableKeys == nil ) { 279 | mutableKeys = [NSMutableArray array]; 280 | } 281 | 282 | [mutableKeys addObjectsFromArray:keysToAdd]; 283 | } 284 | 285 | if ( defaultValuesToAdd ) { 286 | if ( mutableDefaultValues == nil ) { 287 | mutableDefaultValues = [NSMutableDictionary dictionary]; 288 | } 289 | 290 | [mutableDefaultValues addEntriesFromDictionary:defaultValuesToAdd]; 291 | } 292 | } 293 | 294 | if ( errorToReturn ) { 295 | mutableSettingsMenuItemsToReturn = nil; 296 | mutableKeys = nil; 297 | mutableDefaultValues = nil; 298 | } 299 | 300 | if ( outKeys ) { 301 | *outKeys = [mutableKeys copy]; 302 | } 303 | 304 | if ( outDefaultValues ) { 305 | *outDefaultValues = [mutableDefaultValues copy]; 306 | } 307 | 308 | if ( outError ) { 309 | *outError = errorToReturn; 310 | } 311 | 312 | return [mutableSettingsMenuItemsToReturn copy]; 313 | } 314 | 315 | + (NSArray *)settingsMenuItemsFromPlistName:(NSString *)plistName 316 | returningKeys:(NSArray * __autoreleasing *)outKeys 317 | defaultValues:(NSDictionary * __autoreleasing *)outDefaultValues 318 | error:(NSError * __autoreleasing *)outError; 319 | { 320 | plistName = [plistName stringByDeletingPathExtension]; 321 | 322 | NSURL *plistURL = [[NSBundle mainBundle] URLForResource:plistName withExtension:kRZSettingsFileExtension]; 323 | if ( !plistURL ) { 324 | NSString *exceptionName = [plistName stringByAppendingString:@".plist doesn't exist"]; 325 | @throw [NSException exceptionWithName:exceptionName 326 | reason:@"Make sure you have a settings plist file in the Resources directory of your application" 327 | userInfo:nil]; 328 | } 329 | 330 | NSArray *settingsMenuItems = nil; 331 | NSError *errorToReturn = nil; 332 | NSArray *keys = nil; 333 | NSDictionary *defaultValues = nil; 334 | 335 | NSError *dataReadingError = nil; 336 | NSData *plistData = [NSData dataWithContentsOfURL:plistURL options:0 error:&dataReadingError]; 337 | if ( plistData ) { 338 | NSError *dataParsingError = nil; 339 | NSDictionary *propertyListDictionary = [NSPropertyListSerialization propertyListWithData:plistData options:0 format:NULL error:&dataParsingError]; 340 | if ( propertyListDictionary ) { 341 | NSAssert([propertyListDictionary isKindOfClass:[NSDictionary class]], @""); 342 | 343 | NSError *settingsMenuItemsParsingError = nil; 344 | settingsMenuItems = [self settingsMenuItemsFromSettingsDictionary:propertyListDictionary 345 | returningKeys:&keys 346 | defaultValues:&defaultValues 347 | error:&settingsMenuItemsParsingError]; 348 | if ( settingsMenuItems ) { 349 | NSError *recursiveLoadingError = nil; 350 | 351 | NSArray *childKeys = nil; 352 | NSDictionary *childDefaultValues = nil; 353 | settingsMenuItems = [self settingsMenuItemsByRecursivelyLoadingChildPanesFromSettingsMenuItems:settingsMenuItems 354 | returningKeys:&childKeys 355 | defaultValues:&childDefaultValues 356 | error:&recursiveLoadingError]; 357 | 358 | if ( childKeys ) { 359 | if ( keys ) { 360 | keys = [keys arrayByAddingObjectsFromArray:childKeys]; 361 | } 362 | else { 363 | keys = childKeys; 364 | } 365 | } 366 | 367 | if ( childDefaultValues ) { 368 | if ( defaultValues ) { 369 | NSMutableDictionary *mutableDefaultValues = [defaultValues mutableCopy]; 370 | [mutableDefaultValues addEntriesFromDictionary:childDefaultValues]; 371 | defaultValues = [mutableDefaultValues copy]; 372 | } 373 | else { 374 | defaultValues = childDefaultValues; 375 | } 376 | } 377 | 378 | if ( settingsMenuItems == nil ) { 379 | errorToReturn = recursiveLoadingError; 380 | } 381 | } 382 | else { 383 | errorToReturn = settingsMenuItemsParsingError; 384 | } 385 | } 386 | else { 387 | errorToReturn = dataParsingError; 388 | } 389 | } 390 | else { 391 | errorToReturn = dataReadingError; 392 | } 393 | 394 | if ( errorToReturn ) { 395 | settingsMenuItems = nil; 396 | keys = nil; 397 | defaultValues = nil; 398 | } 399 | 400 | if ( outKeys ) { 401 | *outKeys = keys; 402 | } 403 | 404 | if ( outDefaultValues ) { 405 | *outDefaultValues = defaultValues; 406 | } 407 | 408 | if ( outError ) { 409 | *outError = errorToReturn; 410 | } 411 | 412 | return settingsMenuItems; 413 | } 414 | 415 | @end 416 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuSettingsStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsStore.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/23/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | @protocol RZDebugMenuSettingsStore 10 | 11 | - (instancetype)initWithKeys:(NSArray *)keys defaultValues:(NSDictionary *)defaultValues; 12 | 13 | /** 14 | * Reset all debug settings to their default values. 15 | */ 16 | - (void)reset; 17 | 18 | /** 19 | * Default settings value for key. 20 | * 21 | * @param key Key to get the default value for. 22 | * 23 | * @return Default settings value for this key. 24 | */ 25 | - (id)defaultValueForKey:(id)key; 26 | 27 | @property (copy, nonatomic, readonly) NSArray *keys; 28 | 29 | // Keyed Access methods. 30 | 31 | - (id)objectForKeyedSubscript:(id )key; 32 | - (void)setObject:(id)obj forKeyedSubscript:(id )key; 33 | 34 | // These are all standard KVO methods. Standard KVO is the best way to interaction with this class. 35 | 36 | - (id)valueForKey:(NSString *)key; 37 | - (void)setValue:(id)value forKey:(NSString *)key; 38 | 39 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context; 40 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context; 41 | - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath; 42 | 43 | @end 44 | 45 | 46 | @interface RZDebugMenuSettingsStore : NSObject 47 | 48 | @end -------------------------------------------------------------------------------- /Classes/RZDebugMenuSettingsStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsStore.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/23/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsStore.h" 10 | 11 | @interface RZDebugMenuSettingsStore () 12 | 13 | @property (copy, nonatomic, readwrite) NSArray *keys; 14 | @property (copy, nonatomic, readwrite) NSDictionary *defaultValues; 15 | 16 | @end 17 | 18 | @implementation RZDebugMenuSettingsStore 19 | 20 | - (instancetype)initWithKeys:(NSArray *)keys defaultValues:(NSDictionary *)defaultValues 21 | { 22 | self = [super init]; 23 | if ( self ) { 24 | self.keys = keys; 25 | self.defaultValues = defaultValues; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (void)reset 32 | { 33 | NSAssert(NO, @"Subclass should implement reset."); 34 | } 35 | 36 | # pragma mark - Keyed Access 37 | 38 | - (void)setObject:(id)obj forKeyedSubscript:(id )key 39 | { 40 | NSAssert([key isKindOfClass:[NSString class]], @""); 41 | 42 | [self setValue:obj forKey:(NSString *)key]; 43 | } 44 | 45 | - (id)objectForKeyedSubscript:(id )key 46 | { 47 | NSAssert([key isKindOfClass:[NSString class]], @""); 48 | 49 | return [self valueForKey:(NSString *)key]; 50 | } 51 | 52 | - (id)defaultValueForKey:(id)key 53 | { 54 | return [self.defaultValues objectForKey:key]; 55 | } 56 | 57 | - (id)valueForKey:(NSString *)key 58 | { 59 | id valueToReturn = nil; 60 | 61 | if ( [self.keys containsObject:key] ) { 62 | valueToReturn = [self.defaultValues objectForKey:key]; 63 | } 64 | else { 65 | valueToReturn = [super valueForKey:key]; 66 | } 67 | 68 | return valueToReturn; 69 | } 70 | 71 | @end -------------------------------------------------------------------------------- /Classes/RZDebugMenuUserDefaultsStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuUserDefaultsStore.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/23/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsStore.h" 10 | 11 | @interface RZDebugMenuUserDefaultsStore : RZDebugMenuSettingsStore 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/RZDebugMenuUserDefaultsStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuUserDefaultsStore.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/23/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuUserDefaultsStore.h" 10 | 11 | #import "RZDebugMenuSettings_Private.h" 12 | 13 | @interface RZDebugMenuUserDefaultsStore () 14 | 15 | @end 16 | 17 | @implementation RZDebugMenuUserDefaultsStore 18 | 19 | - (void)setValue:(id)value forKey:(NSString *)key 20 | { 21 | id previousValue = [self valueForKey:key]; 22 | 23 | id defaultValue = [self defaultValueForKey:key]; 24 | if ( value && [previousValue isEqual:value] ) { 25 | // Nothing to do here. Don't even send change notifications. 26 | return; 27 | } 28 | 29 | [self willChangeValueForKey:key]; 30 | 31 | // For a default value, simply remove the key and it will fall through to our part. 32 | if ( value && [value isEqual:defaultValue] == NO ) { 33 | [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; 34 | } 35 | else { 36 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; 37 | } 38 | 39 | [self didChangeValueForKey:key]; 40 | 41 | [[RZDebugMenuSettings sharedSettings] postChangeNotificationSettingsName:key previousValue:previousValue newValue:value]; 42 | } 43 | 44 | - (id)valueForKey:(NSString *)key 45 | { 46 | id objectToReturn = [[NSUserDefaults standardUserDefaults] objectForKey:key]; 47 | if ( objectToReturn == nil ) { 48 | objectToReturn = [super valueForKey:key]; 49 | } 50 | 51 | return objectToReturn; 52 | } 53 | 54 | - (void)reset 55 | { 56 | for ( NSString *key in self.keys ) { 57 | id previousValue = [[NSUserDefaults standardUserDefaults] objectForKey:key]; 58 | if ( previousValue != nil ) { 59 | [self willChangeValueForKey:key]; 60 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; 61 | [self didChangeValueForKey:key]; 62 | 63 | id defaultValue = [self defaultValueForKey:key]; 64 | [[RZDebugMenuSettings sharedSettings] postChangeNotificationSettingsName:key previousValue:previousValue newValue:defaultValue]; 65 | } 66 | } 67 | } 68 | 69 | - (void)setObject:(id)obj forKeyedSubscript:(id )key 70 | { 71 | NSAssert([key isKindOfClass:[NSString class]], @""); 72 | 73 | [self setValue:obj forKey:(NSString *)key]; 74 | } 75 | 76 | - (id)objectForKeyedSubscript:(id )key 77 | { 78 | NSAssert([key isKindOfClass:[NSString class]], @""); 79 | 80 | return [self valueForKey:(NSString *)key]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Classes/UI/RZDebugMenuSettingsForm.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsForm.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/18/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class RZDebugMenuLoadedChildPaneItem; 12 | 13 | @protocol RZDebugMenuSettingsFormDelegate 14 | 15 | - (UIViewController *)viewControllerForChildPaneItem:(RZDebugMenuLoadedChildPaneItem *)childPaneItem; 16 | 17 | @end 18 | 19 | @interface RZDebugMenuSettingsForm : NSObject 20 | 21 | - (instancetype)initWithSettingsMenuItems:(NSArray *)settingsMenuItems NS_DESIGNATED_INITIALIZER; 22 | 23 | @property (weak, nonatomic, readwrite) id delegate; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Classes/UI/RZDebugMenuSettingsForm.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuSettingsForm.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/18/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettingsForm.h" 10 | 11 | #import "RZDebugMenuItem.h" 12 | #import "RZDebugMenuMultiValueItem.h" 13 | #import "RZDebugMenuToggleItem.h" 14 | #import "RZDebugMenuTextFieldItem.h" 15 | #import "RZDebugMenuSliderItem.h" 16 | #import "RZDebugMenuGroupItem.h" 17 | #import "RZDebugMenuLoadedChildPaneItem.h" 18 | #import "RZDebugMenuSettings.h" 19 | #import "RZDebugMenuFormViewController.h" 20 | #import "RZDebugMenuTitleItem.h" 21 | #import "RZDebugMenuMultiValueSelectionItem.h" 22 | #import "RZDebugMenuVersionItem.h" 23 | 24 | #import "RZDebugMenuShortTitles.h" 25 | 26 | @interface RZDebugMenuSettingsForm () 27 | 28 | @property (strong, nonatomic, readwrite) NSArray *settingsMenuItems; 29 | 30 | @property (strong, nonatomic, readwrite) NSArray *cachedFields; 31 | 32 | @end 33 | 34 | @implementation RZDebugMenuSettingsForm 35 | 36 | - (instancetype)initWithSettingsMenuItems:(NSArray *)settingsMenuItems 37 | { 38 | self = [super init]; 39 | if ( self ) { 40 | self.settingsMenuItems = settingsMenuItems; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | + (NSArray *)settingsMenuItemsByFlatteningGroupsFromSettingsMenuItems:(NSArray *)settingsMenuItems 47 | { 48 | NSMutableArray *mutableSettingsMenuItems = [NSMutableArray array]; 49 | 50 | for ( RZDebugMenuItem *menuItem in settingsMenuItems ) { 51 | [mutableSettingsMenuItems addObject:menuItem]; 52 | 53 | if ( [menuItem isKindOfClass:[RZDebugMenuGroupItem class]] ) { 54 | NSArray *children = ((RZDebugMenuGroupItem *)menuItem).children; 55 | if ( children.count > 0 ) { 56 | [mutableSettingsMenuItems addObjectsFromArray:children]; 57 | } 58 | } 59 | } 60 | 61 | return [mutableSettingsMenuItems copy]; 62 | } 63 | 64 | - (NSArray *)uncachedFields 65 | { 66 | NSMutableArray *mutableFields = nil; 67 | 68 | NSArray *flattenedSettingsMenuItems = [[self class] settingsMenuItemsByFlatteningGroupsFromSettingsMenuItems:self.settingsMenuItems]; 69 | 70 | RZDebugMenuGroupItem *groupToStart = nil; 71 | id defaultValue = nil; 72 | 73 | for ( RZDebugMenuItem *item in flattenedSettingsMenuItems ) { 74 | NSMutableDictionary *mutableFieldDictionary = [NSMutableDictionary dictionary]; 75 | 76 | NSString *title = item.title; 77 | if ( title.length == 0 ) { 78 | title = @""; 79 | } 80 | mutableFieldDictionary[FXFormFieldTitle] = title; 81 | 82 | if ( groupToStart ) { 83 | mutableFieldDictionary[FXFormFieldHeader] = groupToStart.title; 84 | groupToStart = nil; 85 | } 86 | 87 | 88 | NSString *key = nil; 89 | if ( [item isKindOfClass:[RZDebugMenuSettingItem class]] ) { 90 | key = ((RZDebugMenuSettingItem *)item).key; 91 | } 92 | 93 | if ( key ) { 94 | mutableFieldDictionary[FXFormFieldKey] = key; 95 | } 96 | 97 | NSString *formFieldType = nil; 98 | if ( [item isKindOfClass:[RZDebugMenuTextFieldItem class]] ) { 99 | formFieldType = FXFormFieldTypeText; 100 | } 101 | else if ( [item isKindOfClass:[RZDebugMenuToggleItem class]] ) { 102 | formFieldType = FXFormFieldTypeBoolean; 103 | } 104 | else if ( [item isKindOfClass:[RZDebugMenuSliderItem class]] ) { 105 | formFieldType = FXFormFieldTypeFloat; 106 | 107 | mutableFieldDictionary[FXFormFieldCell] = NSStringFromClass([FXFormSliderCell class]); 108 | 109 | NSArray *sliderMinimumKeyComponents = @[ NSStringFromSelector(@selector(slider)), NSStringFromSelector(@selector(minimumValue)) ]; 110 | NSString *sliderMinimumValueKey = [sliderMinimumKeyComponents componentsJoinedByString:@"."]; 111 | mutableFieldDictionary[sliderMinimumValueKey] = ((RZDebugMenuSliderItem *)item).min; 112 | 113 | NSArray *sliderMaximumKeyComponents = @[ NSStringFromSelector(@selector(slider)), NSStringFromSelector(@selector(maximumValue)) ]; 114 | NSString *sliderMaximumValueKey = [sliderMaximumKeyComponents componentsJoinedByString:@"."]; 115 | mutableFieldDictionary[sliderMaximumValueKey] = ((RZDebugMenuSliderItem *)item).max; 116 | } 117 | else if ( [item isKindOfClass:[RZDebugMenuMultiValueItem class]] ) { 118 | NSArray *selectionItems = ((RZDebugMenuMultiValueItem *)item).selectionItems; 119 | NSArray *longTitles = [selectionItems valueForKey:NSStringFromSelector(@selector(title))]; 120 | NSArray *values = [selectionItems valueForKey:NSStringFromSelector(@selector(value))]; 121 | NSArray *shortTitles = [selectionItems valueForKey:NSStringFromSelector(@selector(shortTitle))]; 122 | 123 | BOOL hasShortTitles = [[shortTitles firstObject] isKindOfClass:[NSString class]]; 124 | 125 | mutableFieldDictionary[FXFormFieldOptions] = values; 126 | 127 | NSArray *titlesForTransform = longTitles; 128 | 129 | if ( hasShortTitles ) { 130 | mutableFieldDictionary[FXFormFieldViewController] = [[RZFormLongNameViewController alloc] initWithLongTitles:longTitles]; 131 | titlesForTransform = shortTitles; 132 | } 133 | 134 | mutableFieldDictionary[FXFormFieldValueTransformer] = ^(id input) { 135 | NSString *valueToReturn = @""; 136 | 137 | if ( input != nil ) { 138 | NSUInteger index = [values indexOfObject:input]; 139 | NSAssert(index < NSNotFound && index >= 0, @""); 140 | valueToReturn = titlesForTransform[index]; 141 | } 142 | 143 | return valueToReturn; 144 | }; 145 | 146 | formFieldType = FXFormFieldTypeDefault; 147 | } 148 | else if ( [item isKindOfClass:[RZDebugMenuGroupItem class]] ) { 149 | groupToStart = (RZDebugMenuGroupItem *)item; 150 | } 151 | else if ( [item isKindOfClass:[RZDebugMenuLoadedChildPaneItem class]] ) { 152 | formFieldType = FXFormFieldTypeDefault; 153 | 154 | RZDebugMenuLoadedChildPaneItem *childPaneItem = (RZDebugMenuLoadedChildPaneItem *)item; 155 | NSArray *settingsMenuItems = childPaneItem.settingsMenuItems; 156 | RZDebugMenuSettingsForm *childSettingsForm = [[RZDebugMenuSettingsForm alloc] initWithSettingsMenuItems:settingsMenuItems]; 157 | childSettingsForm.delegate = self.delegate; 158 | 159 | defaultValue = childSettingsForm; 160 | 161 | mutableFieldDictionary[FXFormFieldClass] = [RZDebugMenuSettingsForm class]; 162 | 163 | UIViewController *formViewController = [self.delegate viewControllerForChildPaneItem:childPaneItem]; 164 | NSAssert(formViewController != nil, @""); 165 | 166 | mutableFieldDictionary[FXFormFieldViewController] = formViewController; 167 | } 168 | else if ( [item isKindOfClass:[RZDebugMenuTitleItem class]] ) { 169 | formFieldType = FXFormFieldTypeDefault; 170 | 171 | NSArray *values = ((RZDebugMenuTitleItem *)item).values; 172 | NSArray *titles = ((RZDebugMenuTitleItem *)item).titles; 173 | 174 | mutableFieldDictionary[FXFormFieldValueTransformer] = ^(id input) { 175 | NSString *valueToReturn = @""; 176 | 177 | if ( input != nil ) { 178 | NSUInteger index = [values indexOfObject:input]; 179 | NSAssert(index < NSNotFound && index >= 0, @""); 180 | valueToReturn = titles[index]; 181 | } 182 | 183 | return valueToReturn; 184 | }; 185 | } 186 | else if ( [item isKindOfClass:[RZDebugMenuVersionItem class]] ) { 187 | defaultValue = ((RZDebugMenuVersionItem *)item).versionString; 188 | formFieldType = FXFormFieldTypeDefault; 189 | 190 | mutableFieldDictionary[FXFormFieldCell] = [FXFormTextFieldCell class]; 191 | 192 | NSArray *textKeyComponents = @[ NSStringFromSelector(@selector(textField)), NSStringFromSelector(@selector(text)) ]; 193 | NSString *textKey = [textKeyComponents componentsJoinedByString:@"."]; 194 | [mutableFieldDictionary setObject:defaultValue forKey:textKey]; 195 | 196 | NSArray *textFieldEnabledKeyComponents = @[ NSStringFromSelector(@selector(textField)), @"enabled" ]; 197 | NSString *textFieldEnabledKey = [textFieldEnabledKeyComponents componentsJoinedByString:@"."]; 198 | [mutableFieldDictionary setObject:@(NO) forKey:textFieldEnabledKey]; 199 | } 200 | 201 | if ( [item isKindOfClass:[RZDebugMenuSettingItem class]] ) { 202 | defaultValue = ((RZDebugMenuSettingItem *)item).value; 203 | } 204 | 205 | if ( defaultValue ) { 206 | mutableFieldDictionary[FXFormFieldDefaultValue] = defaultValue; 207 | } 208 | 209 | if ( formFieldType ) { 210 | mutableFieldDictionary[FXFormFieldType] = formFieldType; 211 | 212 | if ( mutableFields == nil ) { 213 | mutableFields = [NSMutableArray array]; 214 | } 215 | 216 | [mutableFields addObject:[mutableFieldDictionary copy]]; 217 | } 218 | } 219 | 220 | return [mutableFields copy]; 221 | } 222 | 223 | - (NSArray *)fields 224 | { 225 | NSArray *cachedFields = self.cachedFields; 226 | 227 | if ( cachedFields == nil ) { 228 | cachedFields = [self uncachedFields]; 229 | self.cachedFields = cachedFields; 230 | } 231 | 232 | return cachedFields; 233 | } 234 | 235 | + (RZDebugMenuSettingItem *)settingsMenuItemForKey:(NSString *)key inMenuItems:(NSArray *)menuItems 236 | { 237 | RZDebugMenuSettingItem *settingsMenuItem = nil; 238 | 239 | for ( RZDebugMenuItem *menuItem in menuItems ) { 240 | if ( [menuItem isKindOfClass:[RZDebugMenuSettingItem class]] ) { 241 | if ( [((RZDebugMenuSettingItem *)menuItem).key isEqualToString:key] ) { 242 | settingsMenuItem = (RZDebugMenuSettingItem *)menuItem; 243 | break; 244 | } 245 | } 246 | else { 247 | if ( [menuItem isKindOfClass:[RZDebugMenuGroupItem class]] ) { 248 | NSArray *childMenuItems = ((RZDebugMenuGroupItem *)menuItem).children; 249 | settingsMenuItem = [[self class] settingsMenuItemForKey:key inMenuItems:childMenuItems]; 250 | } 251 | else if ( [menuItem isKindOfClass:[RZDebugMenuLoadedChildPaneItem class]] ) { 252 | NSArray *childMenuItems = ((RZDebugMenuLoadedChildPaneItem *)menuItem).settingsMenuItems; 253 | settingsMenuItem = [[self class] settingsMenuItemForKey:key inMenuItems:childMenuItems]; 254 | } 255 | 256 | if ( settingsMenuItem ) { 257 | break; 258 | } 259 | } 260 | } 261 | 262 | return settingsMenuItem; 263 | } 264 | 265 | - (RZDebugMenuSettingItem *)settingsMenuItemForKey:(NSString *)key 266 | { 267 | return [[self class] settingsMenuItemForKey:key inMenuItems:self.settingsMenuItems]; 268 | } 269 | 270 | - (id)valueForKey:(NSString *)key 271 | { 272 | id valueToReturn = nil; 273 | 274 | RZDebugMenuSettingItem *settingsItem = [self settingsMenuItemForKey:key]; 275 | if ( settingsItem ) { 276 | valueToReturn = [RZDebugMenuSettings sharedSettings][key]; 277 | 278 | if ( [settingsItem isKindOfClass:[RZDebugMenuToggleItem class]] ) { 279 | id trueValue = ((RZDebugMenuToggleItem *)settingsItem).trueValue; 280 | id __attribute__((unused)) falseValue = ((RZDebugMenuToggleItem *)settingsItem).falseValue; 281 | if ( trueValue ) { 282 | NSAssert(falseValue != nil, @""); 283 | NSAssert([trueValue class] == [falseValue class], @""); 284 | 285 | NSNumber *(^valueTransformer)(id value) = ^(id value) { 286 | NSNumber *valueToReturn = @(NO); 287 | 288 | if ( [value isEqual:trueValue] ) { 289 | valueToReturn = @(YES); 290 | } 291 | 292 | return valueToReturn; 293 | }; 294 | 295 | valueToReturn = valueTransformer(valueToReturn); 296 | } 297 | } 298 | } 299 | else { 300 | valueToReturn = [super valueForKey:key]; 301 | } 302 | 303 | return valueToReturn; 304 | } 305 | 306 | - (void)setValue:(id)value forKey:(NSString *)key 307 | { 308 | RZDebugMenuSettingItem *settingsItem = [self settingsMenuItemForKey:key]; 309 | if ( settingsItem ) { 310 | if ( [settingsItem isKindOfClass:[RZDebugMenuToggleItem class]] ) { 311 | id trueValue = ((RZDebugMenuToggleItem *)settingsItem).trueValue; 312 | id falseValue = ((RZDebugMenuToggleItem *)settingsItem).falseValue; 313 | if ( trueValue ) { 314 | NSAssert(falseValue != nil, @""); 315 | NSAssert([trueValue class] == [falseValue class], @""); 316 | 317 | id (^reverseValueTransformer)(NSNumber *value) = ^(NSNumber *value) { 318 | id valueToReturn = falseValue; 319 | 320 | NSAssert([value isKindOfClass:[NSNumber class]], @""); 321 | 322 | if ( [value boolValue] ) { 323 | valueToReturn = trueValue; 324 | } 325 | 326 | return valueToReturn; 327 | }; 328 | 329 | value = reverseValueTransformer(value); 330 | } 331 | } 332 | 333 | [RZDebugMenuSettings sharedSettings][key] = value; 334 | } 335 | else { 336 | [super setValue:value forKey:key]; 337 | } 338 | } 339 | 340 | @end 341 | -------------------------------------------------------------------------------- /Classes/UI/RZDebugMenuShortTitles.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuShortTitles.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/25/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // This pair of files is some hackery to FXForms to allow us to have different "long" and "short" titles in a multi-value selection item. In order to get to the FXFormField object and overwrite the the description it sends for options, we need to use a simple custom view controller and a proxy FXFormField. 12 | 13 | @interface RZFormLongNameViewController : FXFormViewController 14 | 15 | - (instancetype)initWithLongTitles:(NSArray *)longTitles; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /Classes/UI/RZDebugMenuShortTitles.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuShortTitles.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/25/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuShortTitles.h" 10 | 11 | #import 12 | 13 | @interface RZFormLongNameProxyField : NSObject 14 | 15 | - (instancetype)initWithFormField:(FXFormField *)formField longTitles:(NSArray *)longTitles; 16 | 17 | @end 18 | 19 | @interface RZFormLongNameViewController () 20 | 21 | @property (copy, nonatomic, readwrite) NSArray *longTitles; 22 | 23 | @end 24 | 25 | @implementation RZFormLongNameViewController 26 | 27 | - (instancetype)initWithLongTitles:(NSArray *)longTitles 28 | { 29 | self = [super initWithNibName:nil bundle:nil]; 30 | if ( self ) { 31 | self.longTitles = longTitles; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | - (void)setField:(FXFormField *)field 38 | { 39 | RZFormLongNameProxyField *proxyField = [[RZFormLongNameProxyField alloc] initWithFormField:field longTitles:self.longTitles]; 40 | [super setField:(FXFormField *)proxyField]; 41 | } 42 | 43 | @end 44 | 45 | @interface RZFormLongNameProxyField () 46 | 47 | @property (strong, nonatomic, readwrite) FXFormField *formField; 48 | @property (copy, nonatomic, readwrite) NSArray *longTitles; 49 | 50 | @end 51 | 52 | @implementation RZFormLongNameProxyField 53 | 54 | - (instancetype)initWithFormField:(FXFormField *)formField longTitles:(NSArray *)longTitles 55 | { 56 | self = [super init]; 57 | if ( self ) { 58 | self.formField = formField; 59 | self.longTitles = longTitles; 60 | } 61 | 62 | return self; 63 | } 64 | 65 | - (NSString *)optionDescriptionAtIndex:(NSUInteger)index 66 | { 67 | return self.longTitles[index]; 68 | } 69 | 70 | - (id)forwardingTargetForSelector:(SEL)aSelector 71 | { 72 | return self.formField; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Classes/UIViewController+RZDebugMenuPresentationAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+RZDebugMenuPresentationAdditions.h 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 3/2/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIViewController (RZDebugMenuPresentationAdditions) 12 | 13 | @property (strong, nonatomic, readonly) UIViewController *rzDebugMenu_deepestPresentedViewController; 14 | @property (strong, nonatomic, readonly) UIViewController *rzDebugMenu_deepestViewControllerForPresentation; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/UIViewController+RZDebugMenuPresentationAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+RZDebugMenuPresentationAdditions.m 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 3/2/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+RZDebugMenuPresentationAdditions.h" 10 | 11 | @implementation UIViewController (RZDebugMenuPresentationAddition) 12 | 13 | - (UIViewController *)rzDebugMenu_deepestPresentedViewController 14 | { 15 | UIViewController *deepestPresentedViewController = nil; 16 | 17 | if ( self.presentedViewController ) { 18 | if ( self.presentedViewController.presentedViewController == nil ) { 19 | deepestPresentedViewController = self.presentedViewController; 20 | } 21 | else { 22 | deepestPresentedViewController = self.presentedViewController.rzDebugMenu_deepestPresentedViewController; 23 | } 24 | } 25 | 26 | return deepestPresentedViewController; 27 | } 28 | 29 | - (UIViewController *)rzDebugMenu_deepestViewControllerForPresentation 30 | { 31 | UIViewController *viewControllerToReturn = self; 32 | 33 | if ( self.presentedViewController ) { 34 | viewControllerToReturn = self.rzDebugMenu_deepestPresentedViewController; 35 | } 36 | 37 | return viewControllerToReturn; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Demo/.gitignore: -------------------------------------------------------------------------------- 1 | Podfile.lock 2 | -------------------------------------------------------------------------------- /Demo/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '8.0' 3 | 4 | pod 'RZDebugMenu', :path => '../' 5 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0C22DAC3193CCDA30042938F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C22DAC2193CCDA30042938F /* Foundation.framework */; }; 11 | 0C22DAC5193CCDA30042938F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C22DAC4193CCDA30042938F /* CoreGraphics.framework */; }; 12 | 0C22DAC7193CCDA30042938F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C22DAC6193CCDA30042938F /* UIKit.framework */; }; 13 | 0C22DACD193CCDA30042938F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0C22DACB193CCDA30042938F /* InfoPlist.strings */; }; 14 | 0C22DACF193CCDA30042938F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C22DACE193CCDA30042938F /* main.m */; }; 15 | 0C22DAD3193CCDA30042938F /* RZAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C22DAD2193CCDA30042938F /* RZAppDelegate.m */; }; 16 | 0C22DAD5193CCDA30042938F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0C22DAD4193CCDA30042938F /* Images.xcassets */; }; 17 | 0C972B03193E0CBB00EA84FF /* Settings.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0C972B02193E0CBB00EA84FF /* Settings.plist */; }; 18 | 0C972B0D193E1A9900EA84FF /* RZDebugMenuRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C972B0A193E1A9900EA84FF /* RZDebugMenuRootViewController.m */; }; 19 | 718E8B87771CE7ACCB66B07B /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AA75CF690541A4B5CA70054A /* libPods.a */; }; 20 | D43C8A051A96494B0057AF66 /* MoreSettings.plist in Resources */ = {isa = PBXBuildFile; fileRef = D43C8A041A96494B0057AF66 /* MoreSettings.plist */; }; 21 | D43C8A071A964E370057AF66 /* EvenMoreSettings.plist in Resources */ = {isa = PBXBuildFile; fileRef = D43C8A061A964E370057AF66 /* EvenMoreSettings.plist */; }; 22 | D43D488D1A9B87D9002B3A55 /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D43D488C1A9B87D9002B3A55 /* Launch Screen.xib */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 0C22DABF193CCDA30042938F /* RZDebugMenuDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RZDebugMenuDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 0C22DAC2193CCDA30042938F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | 0C22DAC4193CCDA30042938F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | 0C22DAC6193CCDA30042938F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 30 | 0C22DACA193CCDA30042938F /* RZDebugMenuDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RZDebugMenuDemo-Info.plist"; sourceTree = ""; }; 31 | 0C22DACC193CCDA30042938F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 32 | 0C22DACE193CCDA30042938F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 0C22DAD0193CCDA30042938F /* RZDebugMenuDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RZDebugMenuDemo-Prefix.pch"; sourceTree = ""; }; 34 | 0C22DAD1193CCDA30042938F /* RZAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RZAppDelegate.h; sourceTree = ""; }; 35 | 0C22DAD2193CCDA30042938F /* RZAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RZAppDelegate.m; sourceTree = ""; }; 36 | 0C22DAD4193CCDA30042938F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 37 | 0C22DADB193CCDA30042938F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 38 | 0C972B02193E0CBB00EA84FF /* Settings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Settings.plist; sourceTree = ""; }; 39 | 0C972B09193E1A9900EA84FF /* RZDebugMenuRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuRootViewController.h; sourceTree = ""; }; 40 | 0C972B0A193E1A9900EA84FF /* RZDebugMenuRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuRootViewController.m; sourceTree = ""; }; 41 | 35E576648AB0A16778F404BC /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 42 | AA75CF690541A4B5CA70054A /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | C679C2B5BBB49FF44D0AAC55 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 44 | D43C8A041A96494B0057AF66 /* MoreSettings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = MoreSettings.plist; sourceTree = ""; }; 45 | D43C8A061A964E370057AF66 /* EvenMoreSettings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = EvenMoreSettings.plist; sourceTree = ""; }; 46 | D43D488C1A9B87D9002B3A55 /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = "Launch Screen.xib"; path = "../Resources/Launch Screen.xib"; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 0C22DABC193CCDA30042938F /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 0C22DAC5193CCDA30042938F /* CoreGraphics.framework in Frameworks */, 55 | 0C22DAC7193CCDA30042938F /* UIKit.framework in Frameworks */, 56 | 0C22DAC3193CCDA30042938F /* Foundation.framework in Frameworks */, 57 | 718E8B87771CE7ACCB66B07B /* libPods.a in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 0C22DAB6193CCDA30042938F = { 65 | isa = PBXGroup; 66 | children = ( 67 | 0C22DAC8193CCDA30042938F /* RZDebugMenuDemo */, 68 | 0C22DAC1193CCDA30042938F /* Frameworks */, 69 | 0C22DAC0193CCDA30042938F /* Products */, 70 | 54A43BACB04A60C10640B341 /* Pods */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 0C22DAC0193CCDA30042938F /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 0C22DABF193CCDA30042938F /* RZDebugMenuDemo.app */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | 0C22DAC1193CCDA30042938F /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 0C22DAC2193CCDA30042938F /* Foundation.framework */, 86 | 0C22DAC4193CCDA30042938F /* CoreGraphics.framework */, 87 | 0C22DAC6193CCDA30042938F /* UIKit.framework */, 88 | 0C22DADB193CCDA30042938F /* XCTest.framework */, 89 | AA75CF690541A4B5CA70054A /* libPods.a */, 90 | ); 91 | name = Frameworks; 92 | sourceTree = ""; 93 | }; 94 | 0C22DAC8193CCDA30042938F /* RZDebugMenuDemo */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 0C972B0F193E1AEE00EA84FF /* Application */, 98 | 0C972B0E193E1AB000EA84FF /* Resources */, 99 | 0C972B04193E1A9900EA84FF /* View Controllers */, 100 | 0C22DAF9193D085C0042938F /* Views */, 101 | 0C22DAC9193CCDA30042938F /* Supporting Files */, 102 | ); 103 | path = RZDebugMenuDemo; 104 | sourceTree = ""; 105 | }; 106 | 0C22DAC9193CCDA30042938F /* Supporting Files */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | D43D488C1A9B87D9002B3A55 /* Launch Screen.xib */, 110 | 0C22DACA193CCDA30042938F /* RZDebugMenuDemo-Info.plist */, 111 | 0C22DACB193CCDA30042938F /* InfoPlist.strings */, 112 | 0C22DACE193CCDA30042938F /* main.m */, 113 | 0C22DAD0193CCDA30042938F /* RZDebugMenuDemo-Prefix.pch */, 114 | ); 115 | path = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | 0C22DAF9193D085C0042938F /* Views */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | ); 122 | path = Views; 123 | sourceTree = ""; 124 | }; 125 | 0C972B04193E1A9900EA84FF /* View Controllers */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 0C972B09193E1A9900EA84FF /* RZDebugMenuRootViewController.h */, 129 | 0C972B0A193E1A9900EA84FF /* RZDebugMenuRootViewController.m */, 130 | ); 131 | path = "View Controllers"; 132 | sourceTree = ""; 133 | }; 134 | 0C972B0E193E1AB000EA84FF /* Resources */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 0C22DAD4193CCDA30042938F /* Images.xcassets */, 138 | 0C972B02193E0CBB00EA84FF /* Settings.plist */, 139 | D43C8A041A96494B0057AF66 /* MoreSettings.plist */, 140 | D43C8A061A964E370057AF66 /* EvenMoreSettings.plist */, 141 | ); 142 | path = Resources; 143 | sourceTree = ""; 144 | }; 145 | 0C972B0F193E1AEE00EA84FF /* Application */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 0C22DAD1193CCDA30042938F /* RZAppDelegate.h */, 149 | 0C22DAD2193CCDA30042938F /* RZAppDelegate.m */, 150 | ); 151 | path = Application; 152 | sourceTree = ""; 153 | }; 154 | 54A43BACB04A60C10640B341 /* Pods */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 35E576648AB0A16778F404BC /* Pods.debug.xcconfig */, 158 | C679C2B5BBB49FF44D0AAC55 /* Pods.release.xcconfig */, 159 | ); 160 | name = Pods; 161 | sourceTree = ""; 162 | }; 163 | /* End PBXGroup section */ 164 | 165 | /* Begin PBXNativeTarget section */ 166 | 0C22DABE193CCDA30042938F /* RZDebugMenuDemo */ = { 167 | isa = PBXNativeTarget; 168 | buildConfigurationList = 0C22DAEB193CCDA30042938F /* Build configuration list for PBXNativeTarget "RZDebugMenuDemo" */; 169 | buildPhases = ( 170 | 5565FF07B3A9DE9BABCCA236 /* Check Pods Manifest.lock */, 171 | 0C22DABB193CCDA30042938F /* Sources */, 172 | 0C22DABC193CCDA30042938F /* Frameworks */, 173 | 0C22DABD193CCDA30042938F /* Resources */, 174 | 6AB572FCE4279374589A97EF /* Copy Pods Resources */, 175 | 66422634A1BA7FF2756C7C19 /* Embed Pods Frameworks */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = RZDebugMenuDemo; 182 | productName = RZDebugMenuDemo; 183 | productReference = 0C22DABF193CCDA30042938F /* RZDebugMenuDemo.app */; 184 | productType = "com.apple.product-type.application"; 185 | }; 186 | /* End PBXNativeTarget section */ 187 | 188 | /* Begin PBXProject section */ 189 | 0C22DAB7193CCDA30042938F /* Project object */ = { 190 | isa = PBXProject; 191 | attributes = { 192 | CLASSPREFIX = RZ; 193 | LastUpgradeCheck = 0510; 194 | ORGANIZATIONNAME = Raizlabs; 195 | }; 196 | buildConfigurationList = 0C22DABA193CCDA30042938F /* Build configuration list for PBXProject "RZDebugMenuDemo" */; 197 | compatibilityVersion = "Xcode 3.2"; 198 | developmentRegion = English; 199 | hasScannedForEncodings = 0; 200 | knownRegions = ( 201 | en, 202 | ); 203 | mainGroup = 0C22DAB6193CCDA30042938F; 204 | productRefGroup = 0C22DAC0193CCDA30042938F /* Products */; 205 | projectDirPath = ""; 206 | projectRoot = ""; 207 | targets = ( 208 | 0C22DABE193CCDA30042938F /* RZDebugMenuDemo */, 209 | ); 210 | }; 211 | /* End PBXProject section */ 212 | 213 | /* Begin PBXResourcesBuildPhase section */ 214 | 0C22DABD193CCDA30042938F /* Resources */ = { 215 | isa = PBXResourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | D43C8A051A96494B0057AF66 /* MoreSettings.plist in Resources */, 219 | D43C8A071A964E370057AF66 /* EvenMoreSettings.plist in Resources */, 220 | 0C22DACD193CCDA30042938F /* InfoPlist.strings in Resources */, 221 | 0C22DAD5193CCDA30042938F /* Images.xcassets in Resources */, 222 | 0C972B03193E0CBB00EA84FF /* Settings.plist in Resources */, 223 | D43D488D1A9B87D9002B3A55 /* Launch Screen.xib in Resources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXShellScriptBuildPhase section */ 230 | 5565FF07B3A9DE9BABCCA236 /* Check Pods Manifest.lock */ = { 231 | isa = PBXShellScriptBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | inputPaths = ( 236 | ); 237 | name = "Check Pods Manifest.lock"; 238 | outputPaths = ( 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | shellPath = /bin/sh; 242 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 243 | showEnvVarsInLog = 0; 244 | }; 245 | 66422634A1BA7FF2756C7C19 /* Embed Pods Frameworks */ = { 246 | isa = PBXShellScriptBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | ); 250 | inputPaths = ( 251 | ); 252 | name = "Embed Pods Frameworks"; 253 | outputPaths = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | shellPath = /bin/sh; 257 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 258 | showEnvVarsInLog = 0; 259 | }; 260 | 6AB572FCE4279374589A97EF /* Copy Pods Resources */ = { 261 | isa = PBXShellScriptBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | ); 265 | inputPaths = ( 266 | ); 267 | name = "Copy Pods Resources"; 268 | outputPaths = ( 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | shellPath = /bin/sh; 272 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 273 | showEnvVarsInLog = 0; 274 | }; 275 | /* End PBXShellScriptBuildPhase section */ 276 | 277 | /* Begin PBXSourcesBuildPhase section */ 278 | 0C22DABB193CCDA30042938F /* Sources */ = { 279 | isa = PBXSourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | 0C22DAD3193CCDA30042938F /* RZAppDelegate.m in Sources */, 283 | 0C972B0D193E1A9900EA84FF /* RZDebugMenuRootViewController.m in Sources */, 284 | 0C22DACF193CCDA30042938F /* main.m in Sources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXSourcesBuildPhase section */ 289 | 290 | /* Begin PBXVariantGroup section */ 291 | 0C22DACB193CCDA30042938F /* InfoPlist.strings */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | 0C22DACC193CCDA30042938F /* en */, 295 | ); 296 | name = InfoPlist.strings; 297 | sourceTree = ""; 298 | }; 299 | /* End PBXVariantGroup section */ 300 | 301 | /* Begin XCBuildConfiguration section */ 302 | 0C22DAE9193CCDA30042938F /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 307 | CLANG_CXX_LIBRARY = "libc++"; 308 | CLANG_ENABLE_MODULES = YES; 309 | CLANG_ENABLE_OBJC_ARC = YES; 310 | CLANG_WARN_BOOL_CONVERSION = YES; 311 | CLANG_WARN_CONSTANT_CONVERSION = YES; 312 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 313 | CLANG_WARN_EMPTY_BODY = YES; 314 | CLANG_WARN_ENUM_CONVERSION = YES; 315 | CLANG_WARN_INT_CONVERSION = YES; 316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 317 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 318 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 319 | COPY_PHASE_STRIP = NO; 320 | GCC_C_LANGUAGE_STANDARD = gnu99; 321 | GCC_DYNAMIC_NO_PIC = NO; 322 | GCC_OPTIMIZATION_LEVEL = 0; 323 | GCC_PREPROCESSOR_DEFINITIONS = ( 324 | "DEBUG=1", 325 | "$(inherited)", 326 | ); 327 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 328 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 329 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 330 | GCC_WARN_UNDECLARED_SELECTOR = YES; 331 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 332 | GCC_WARN_UNUSED_FUNCTION = YES; 333 | GCC_WARN_UNUSED_VARIABLE = YES; 334 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 335 | ONLY_ACTIVE_ARCH = YES; 336 | SDKROOT = iphoneos; 337 | TARGETED_DEVICE_FAMILY = "1,2"; 338 | }; 339 | name = Debug; 340 | }; 341 | 0C22DAEA193CCDA30042938F /* Release */ = { 342 | isa = XCBuildConfiguration; 343 | buildSettings = { 344 | ALWAYS_SEARCH_USER_PATHS = NO; 345 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 346 | CLANG_CXX_LIBRARY = "libc++"; 347 | CLANG_ENABLE_MODULES = YES; 348 | CLANG_ENABLE_OBJC_ARC = YES; 349 | CLANG_WARN_BOOL_CONVERSION = YES; 350 | CLANG_WARN_CONSTANT_CONVERSION = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_EMPTY_BODY = YES; 353 | CLANG_WARN_ENUM_CONVERSION = YES; 354 | CLANG_WARN_INT_CONVERSION = YES; 355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 356 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 357 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 358 | COPY_PHASE_STRIP = YES; 359 | ENABLE_NS_ASSERTIONS = NO; 360 | GCC_C_LANGUAGE_STANDARD = gnu99; 361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 363 | GCC_WARN_UNDECLARED_SELECTOR = YES; 364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 365 | GCC_WARN_UNUSED_FUNCTION = YES; 366 | GCC_WARN_UNUSED_VARIABLE = YES; 367 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 368 | SDKROOT = iphoneos; 369 | TARGETED_DEVICE_FAMILY = "1,2"; 370 | VALIDATE_PRODUCT = YES; 371 | }; 372 | name = Release; 373 | }; 374 | 0C22DAEC193CCDA30042938F /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | baseConfigurationReference = 35E576648AB0A16778F404BC /* Pods.debug.xcconfig */; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 380 | GCC_PREFIX_HEADER = "RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Prefix.pch"; 381 | INFOPLIST_FILE = "RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Info.plist"; 382 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | TARGETED_DEVICE_FAMILY = "1,2"; 385 | WRAPPER_EXTENSION = app; 386 | }; 387 | name = Debug; 388 | }; 389 | 0C22DAED193CCDA30042938F /* Release */ = { 390 | isa = XCBuildConfiguration; 391 | baseConfigurationReference = C679C2B5BBB49FF44D0AAC55 /* Pods.release.xcconfig */; 392 | buildSettings = { 393 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 394 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 395 | GCC_PREFIX_HEADER = "RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Prefix.pch"; 396 | INFOPLIST_FILE = "RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Info.plist"; 397 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | TARGETED_DEVICE_FAMILY = "1,2"; 400 | WRAPPER_EXTENSION = app; 401 | }; 402 | name = Release; 403 | }; 404 | /* End XCBuildConfiguration section */ 405 | 406 | /* Begin XCConfigurationList section */ 407 | 0C22DABA193CCDA30042938F /* Build configuration list for PBXProject "RZDebugMenuDemo" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | 0C22DAE9193CCDA30042938F /* Debug */, 411 | 0C22DAEA193CCDA30042938F /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | 0C22DAEB193CCDA30042938F /* Build configuration list for PBXNativeTarget "RZDebugMenuDemo" */ = { 417 | isa = XCConfigurationList; 418 | buildConfigurations = ( 419 | 0C22DAEC193CCDA30042938F /* Debug */, 420 | 0C22DAED193CCDA30042938F /* Release */, 421 | ); 422 | defaultConfigurationIsVisible = 0; 423 | defaultConfigurationName = Release; 424 | }; 425 | /* End XCConfigurationList section */ 426 | }; 427 | rootObject = 0C22DAB7193CCDA30042938F /* Project object */; 428 | } 429 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo.xcodeproj/xcshareddata/xcschemes/RZDebugMenuDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Application/RZAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZAppDelegate.h 3 | // RZDebugMenuDemo 4 | // 5 | // Created by Clayton Rieck on 6/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | @interface RZAppDelegate : UIResponder 10 | 11 | @property (strong, nonatomic) UIWindow *window; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Application/RZAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZAppDelegate.m 3 | // RZDebugMenuDemo 4 | // 5 | // Created by Clayton Rieck on 6/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZAppDelegate.h" 10 | 11 | #import "RZDebugMenuRootViewController.h" 12 | 13 | #import 14 | #import 15 | #import 16 | 17 | static NSString *const kSettingsPlistName = @"Settings.plist"; 18 | 19 | @implementation RZAppDelegate 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | 24 | #if (DEBUG) 25 | // To activate the debug menu, call this method with the name of the settings plist you want to use. It should be included in your application bundle. 26 | [RZDebugMenu enableMenuWithSettingsPlistName:kSettingsPlistName]; 27 | #endif 28 | 29 | RZDebugMenuRootViewController *rootViewController = [[RZDebugMenuRootViewController alloc] init]; 30 | UINavigationController *rootNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; 31 | 32 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 33 | self.window.backgroundColor = [UIColor whiteColor]; 34 | self.window.rootViewController = rootNavigationController; 35 | [self.window makeKeyAndVisible]; 36 | 37 | #if (DEBUG) 38 | // To configure automatic show and hide of the debug menu via a 4-tap gesture, call this method with your app's primary window. 39 | [[RZDebugMenu sharedDebugMenu] registerDebugMenuPresentationGestureOnView:self.window]; 40 | 41 | // If you want your settings to be stored directly in user defaults, overwriting values used by your app via regular defaults APIs, you can uncomment the line below. 42 | // [[RZDebugMenuSettings sharedSettings] setDebugSettingsStoreClass:[RZDebugMenuUserDefaultsStore class]]; 43 | 44 | // For general observation of changes to any debug settings, you can use this notification, which includes specific information on what setting changes, as well as the previous and new values. 45 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingsChanged:) name:kRZDebugMenuSettingChangedNotification object:nil]; 46 | #endif 47 | 48 | return YES; 49 | } 50 | 51 | - (void)settingsChanged:(NSNotification *)note 52 | { 53 | NSLog(@"Settings changed: %@.", note); 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/EvenMoreSettings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | DefaultValue 9 | activated 10 | Key 11 | mapped_switch 12 | TrueValue 13 | activated 14 | FalseValue 15 | deactivated 16 | Title 17 | Mapped Switch 18 | Type 19 | PSToggleSwitchSpecifier 20 | 21 | 22 | New item 23 | 24 | Type 25 | PSTitleValueSpecifier 26 | Titles 27 | 28 | Zero 29 | One 30 | Two 31 | Three 32 | 33 | Values 34 | 35 | 0 36 | 1 37 | 2 38 | 3 39 | 40 | DefaultValue 41 | 1 42 | Key 43 | mapped_read_only_value 44 | Title 45 | Mapped Read Only Title 46 | 47 | 48 | Title 49 | Eveen More Settings 50 | Type 51 | PSGroupSpecifier 52 | 53 | 54 | Type 55 | PSToggleSwitchSpecifier 56 | Title 57 | Enable Great Things 58 | Key 59 | enable_great_things 60 | DefaultValue 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Images.xcassets/greg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "greg.jpeg" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Images.xcassets/greg.imageset/greg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rightpoint/RZDebugMenu/ffe2e196634c0c720c6e8f9baae583d9ebab88bf/Demo/RZDebugMenuDemo/Resources/Images.xcassets/greg.imageset/greg.jpeg -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Launch Screen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/MoreSettings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | Title 9 | Read Only Title 10 | DefaultValue 11 | Simple Read Only Value 12 | Key 13 | simple_read_only_value 14 | Type 15 | PSTitleValueSpecifier 16 | 17 | 18 | Type 19 | PSChildPaneSpecifier 20 | File 21 | EvenMoreSettings 22 | Title 23 | Even More Settings 24 | 25 | 26 | Title 27 | More Settings 28 | Type 29 | PSGroupSpecifier 30 | 31 | 32 | Title 33 | Slider of Cool 34 | DefaultValue 35 | 25 36 | MaximumValue 37 | 100 38 | MinimumValue 39 | 0 40 | Key 41 | slider_cool_preference 42 | Type 43 | PSSliderSpecifier 44 | 45 | 46 | Type 47 | PSToggleSwitchSpecifier 48 | Title 49 | Enable Awesome 50 | Key 51 | enable_awesome 52 | DefaultValue 53 | 54 | 55 | 56 | Type 57 | PSMultiValueSpecifier 58 | ShortTitles 59 | 60 | Zero 61 | One 62 | Two 63 | Three 64 | 65 | Values 66 | 67 | 0 68 | 1 69 | 2 70 | 3 71 | 72 | Titles 73 | 74 | Zero is a great number. 75 | But not as good as One. 76 | Two is even better. 77 | And Three is the best. 78 | 79 | DefaultValue 80 | 2 81 | Title 82 | Short Title Multi Value 83 | Key 84 | short_title_multi_value 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Resources/Settings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | Title 9 | Text Field Value Magnitude 10 | Type 11 | PSGroupSpecifier 12 | 13 | 14 | DefaultValue 15 | 25 16 | MaximumValue 17 | 100 18 | MinimumValue 19 | 0 20 | Key 21 | slider_preference 22 | Type 23 | PSSliderSpecifier 24 | 25 | 26 | Title 27 | View Settings 28 | Type 29 | PSGroupSpecifier 30 | 31 | 32 | AutocapitalizationType 33 | None 34 | AutocorrectionType 35 | No 36 | KeyboardType 37 | Alphabet 38 | DefaultValue 39 | Use a triple, two-finger tap to get to the Debug Menu. 40 | Key 41 | name_preference 42 | Title 43 | Nav Title 44 | Type 45 | PSTextFieldSpecifier 46 | 47 | 48 | Type 49 | PSChildPaneSpecifier 50 | File 51 | MoreSettings 52 | Title 53 | More Settings 54 | 55 | 56 | Type 57 | PSMultiValueSpecifier 58 | Title 59 | Circle 60 | Key 61 | circle_choice 62 | DefaultValue 63 | 2 64 | Titles 65 | 66 | None 67 | Green Circle 68 | Blue Circle 69 | Red Circle 70 | 71 | Values 72 | 73 | 0 74 | 1 75 | 2 76 | 3 77 | 78 | 79 | 80 | Type 81 | PSToggleSwitchSpecifier 82 | Title 83 | Purple Background 84 | Key 85 | reset_toggle 86 | DefaultValue 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.raizlabs.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationPortraitUpsideDown 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Supporting Files/RZDebugMenuDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Supporting Files/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/Supporting Files/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RZDebugMenuDemo 4 | // 5 | // Created by Clayton Rieck on 6/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZAppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) 12 | { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RZAppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/View Controllers/RZDebugMenuRootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuRootViewController.h 3 | // RZDebugMenuDemo 4 | // 5 | // Created by Clayton Rieck on 6/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuSettings.h" 10 | 11 | @interface RZDebugMenuRootViewController : UIViewController 12 | 13 | @property (strong, nonatomic) UIView *circle; 14 | @property (strong, nonatomic) UITextField *testTextField; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Demo/RZDebugMenuDemo/View Controllers/RZDebugMenuRootViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenuRootViewController.m 3 | // RZDebugMenuDemo 4 | // 5 | // Created by Clayton Rieck on 6/2/14. 6 | // Copyright (c) 2014 Raizlabs. All rights reserved. 7 | // 8 | 9 | #import "RZDebugMenuRootViewController.h" 10 | 11 | #import 12 | #import 13 | 14 | @interface RZDebugMenuRootViewController () 15 | 16 | @end 17 | 18 | @implementation RZDebugMenuRootViewController 19 | 20 | - (void)dealloc 21 | { 22 | [[RZDebugMenuSettings sharedSettings] removeObserver:self forKeyPath:@"reset_toggle"]; 23 | [[RZDebugMenuSettings sharedSettings] removeObserver:self forKeyPath:@"slider_preference"]; 24 | [[RZDebugMenuSettings sharedSettings] removeObserver:self forKeyPath:@"name_preference"]; 25 | [[RZDebugMenuSettings sharedSettings] removeObserver:self forKeyPath:@"circle_choice"]; 26 | } 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | self.view.backgroundColor = [UIColor blueColor]; 32 | 33 | self.circle = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)]; 34 | 35 | self.testTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 100, 50)]; 36 | self.testTextField.text = @"0"; 37 | self.testTextField.textColor = [UIColor whiteColor]; 38 | self.testTextField.enabled = NO; 39 | [self.view addSubview:self.testTextField]; 40 | 41 | // For specific observation of particular debug settings, you can use standard KVO (or any other syntactic sugar on top of it). 42 | [[RZDebugMenuSettings sharedSettings] addObserver:self forKeyPath:@"reset_toggle" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; 43 | [[RZDebugMenuSettings sharedSettings] addObserver:self forKeyPath:@"slider_preference" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; 44 | [[RZDebugMenuSettings sharedSettings] addObserver:self forKeyPath:@"name_preference" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; 45 | [[RZDebugMenuSettings sharedSettings] addObserver:self forKeyPath:@"circle_choice" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; 46 | 47 | UIGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerFired:)]; 48 | [self.view addGestureRecognizer:panGestureRecognizer]; 49 | } 50 | 51 | - (void)panGestureRecognizerFired:(id)sender 52 | { 53 | if ( self.presentedViewController == nil ) { 54 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Whoah there ...." message:@"You swiped the backgroud view, didn't you?" preferredStyle:UIAlertControllerStyleAlert]; 55 | [alertController addAction:[UIAlertAction actionWithTitle:@"Yep" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 56 | }]]; 57 | [self presentViewController:alertController animated:YES completion:nil]; 58 | } 59 | } 60 | 61 | - (void)changeBackground:(NSNumber *)toggleValue 62 | { 63 | if ( [toggleValue boolValue] ) { 64 | self.view.backgroundColor = [UIColor purpleColor]; 65 | } 66 | else { 67 | self.view.backgroundColor = [UIColor blueColor]; 68 | } 69 | } 70 | 71 | - (void)changeValue:(NSNumber *)sliderValue 72 | { 73 | self.testTextField.text = [sliderValue stringValue]; 74 | } 75 | 76 | - (void)changeNavTitle:(NSString *)newTitle 77 | { 78 | self.title = newTitle; 79 | } 80 | 81 | - (void)changeMultiValue:(NSNumber *)newValue 82 | { 83 | self.circle.layer.cornerRadius = 50; 84 | 85 | switch ( [newValue intValue] ) { 86 | case 1: { 87 | self.circle.backgroundColor = [UIColor greenColor]; 88 | [self.view addSubview:self.circle]; 89 | break; 90 | } 91 | 92 | case 2: { 93 | self.circle.backgroundColor = [UIColor blueColor]; 94 | [self.view addSubview:self.circle]; 95 | break; 96 | } 97 | 98 | case 3: { 99 | self.circle.backgroundColor = [UIColor redColor]; 100 | [self.view addSubview:self.circle]; 101 | break; 102 | } 103 | 104 | default: 105 | [self.circle removeFromSuperview]; 106 | break; 107 | } 108 | } 109 | 110 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 111 | { 112 | id newValue = [change objectForKey:NSKeyValueChangeNewKey]; 113 | 114 | if ( [keyPath isEqualToString:@"reset_toggle"] ) { 115 | [self changeBackground:newValue]; 116 | } 117 | else if ( [keyPath isEqualToString:@"slider_preference"] ) { 118 | [self changeValue:newValue]; 119 | } 120 | else if ( [keyPath isEqualToString:@"name_preference"] ) { 121 | [self changeNavTitle:newValue]; 122 | } 123 | else if ( [keyPath isEqualToString:@"circle_choice"] ) { 124 | [self changeMultiValue:newValue]; 125 | } 126 | else { 127 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 128 | } 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Raizlabs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RZDebugMenu 2 | =========== 3 | 4 | [![Build Status](https://travis-ci.org/Raizlabs/RZDebugMenu.svg)](https://travis-ci.org/Raizlabs/RZDebugMenu) 5 | 6 | `RZDebugMenu` gives you an easy way to add tweakable, debug-only preferences or settings to your application. This is useful for many settings you often want to change during development, but never in production, such as whether you are using a `staging` or `production` API endpoint. 7 | 8 | `RZDebugMenu` is configured via Settings Bundle plist file, just like the ones you create for adding your (release build) settings to Settings.app. It supports almost all the Settings Bundle schema defined [here] (https://developer.apple.com/library/prerelease/ios/documentation/PreferenceSettings/Conceptual/SettingsApplicationSchemaReference). 9 | 10 | Once you configure it at the start of your application, `RZDebugMenu` shows your menu automatically on a two-finger, three-tap gesture. 11 | 12 | ## Usage 13 | 14 | ### Setup 15 | 16 | `RZDebugMenu` is driven off of a Settings bundle plist file, so the first thing you should is create this Plist and add it to your project. 17 | 18 | To set up RZDebugMenu, add the following code to your Applcation Delegate's `application:didFinishLaunchingWithOptions:` method. 19 | 20 | ```objc 21 | #if (DEBUG) 22 | // To activate the debug menu, call this method with the name of the settings plist you want to use. It should be included in your application bundle. 23 | [RZDebugMenu enableMenuWithSettingsPlistName:@"debug_settings"]; 24 | #endif 25 | ``` 26 | 27 | Once you have your window, to set up the two-finger, three-tap gesture to show the menu, add the following code: 28 | 29 | ```objc 30 | #if (DEBUG) 31 | // To configure automatic show and hide of the debug menu via a 4-tap gesture, call this method with your app's primary window. 32 | [[RZDebugMenu sharedDebugMenu] registerDebugMenuPresentationGestureOnView:self.window]; 33 | #endif 34 | ``` 35 | 36 | ### Accessing Settings 37 | 38 | You can now access your debug settings via `RZDebugMenuSettings`. 39 | 40 | ```objc 41 | [RZDebugMenuSettings sharedSettings][@"my_setting_key"] 42 | ``` 43 | 44 | You can also use standard KVO on `RZDebugMenuSettings` to access settings, and to watch for changes. 45 | 46 | ```objc 47 | NSNumber *namePreference = [[RZDebugMenuSettings sharedSettings] valueForKey:@"name_preference"]; 48 | [[RZDebugMenuSettings sharedSettings] addObserver:self forKeyPath:@"name_preference" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL]; 49 | ``` 50 | 51 | Finally, you can detect changes in settings via an `NSNotification`, if you prefer that over KVO. 52 | 53 | ```objc 54 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingsChanged:) name:kRZDebugMenuSettingChangedNotification object:nil]; 55 | ``` 56 | 57 | This notification will contain keys that describe the setting that has been changed, as well as the previous and new values. 58 | 59 | ### Advanced Usage 60 | 61 | Check the sample application for some patterns of advanced usage. Including: 62 | 63 | - Changing the way settings are stored (whether they are isolated from or connected to your normal `NSUserDefaults.`) 64 | - Manually showing and dismissing the menu. 65 | 66 | ## Try It 67 | 68 | To try `RZDebugMenu`, install [CocoaPods](http://cocoapods.org) and run 69 | ```sh 70 | pod try RZDebugMenu 71 | ``` 72 | 73 | ## Installation 74 | 75 | `RZDebugMenu` is available through [CocoaPods](http://cocoapods.org). To install, simply add the following line to your `Podfile`: 76 | ```ruby 77 | pod RZDebugMenu 78 | ``` 79 | 80 | ## Authors 81 | 82 | Current Maintainer: 83 | 84 | - Michael Gorbach, michael.gorbach@raizlabs.com 85 | 86 | Previous Maintainers: 87 | 88 | - Clayton Reick 89 | - Nicholas Donaldson 90 | -------------------------------------------------------------------------------- /RZDebugMenu.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "RZDebugMenu" 3 | s.version = "0.3.0" 4 | s.summary = "In-app settings bundle using the plist API in XCode" 5 | 6 | s.description = <<-DESC 7 | RZDebugMenu mimics the behavior of a Settings.bundle, but is globally available within your app so you can change whatever setting you'd like at any point. 8 | DESC 9 | 10 | s.homepage = "https://github.com/Raizlabs/RZDebugMenu" 11 | s.license = { :type => "MIT" } 12 | s.author = { "Clayton Rieck" => "cjrieck123@gmail.com", "Nick Donalodson" => "ndonald2@gmail.com", "Michael Gorbach" => "michael.gorbach@raizlabs.com" } 13 | 14 | s.platform = :ios, "8.0" 15 | 16 | s.source = { :git => "https://github.com/Raizlabs/RZDebugMenu.git", :tag => s.version.to_s } 17 | s.source_files = "Classes", "Classes/**/*.{h,m}" 18 | s.exclude_files = "Classes/Exclude" 19 | 20 | s.requires_arc = true 21 | s.dependency 'FXForms', '~>1.2' 22 | end 23 | -------------------------------------------------------------------------------- /RZDebugMenu.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /RZDebugMenu.xcworkspace/xcshareddata/RZDebugMenu.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 0FEA0FA8-9F59-40AF-8E6B-4F07EB0EABFE 9 | IDESourceControlProjectName 10 | RZDebugMenu 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 0A0BA6C406EF48571FE520A89815D17B517349CA 14 | https://github.com/Raizlabs/RZDebugMenu.git 15 | 16 | IDESourceControlProjectPath 17 | RZDebugMenu.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 0A0BA6C406EF48571FE520A89815D17B517349CA 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/Raizlabs/RZDebugMenu.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 0A0BA6C406EF48571FE520A89815D17B517349CA 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 0A0BA6C406EF48571FE520A89815D17B517349CA 36 | IDESourceControlWCCName 37 | RZDebugMenu 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RZDebugMenu.xcworkspace/xcshareddata/RZDebugMenuDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | DCD429D5-E6BB-4E23-A394-6EBB927DBFED 9 | IDESourceControlProjectName 10 | RZDebugMenuDemo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 0A0BA6C406EF48571FE520A89815D17B517349CA 14 | https://github.com/Raizlabs/RZDebugMenu.git 15 | 16 | IDESourceControlProjectPath 17 | Demo/RZDebugMenuDemo.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 0A0BA6C406EF48571FE520A89815D17B517349CA 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/Raizlabs/RZDebugMenu.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 0A0BA6C406EF48571FE520A89815D17B517349CA 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 0A0BA6C406EF48571FE520A89815D17B517349CA 36 | IDESourceControlWCCName 37 | RZDebugMenu 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RZDebugMenu/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '8.0' 3 | 4 | pod 'FXForms', '~>1.2' 5 | -------------------------------------------------------------------------------- /RZDebugMenu/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FXForms (1.2.12) 3 | 4 | DEPENDENCIES: 5 | - FXForms (~> 1.2) 6 | 7 | SPEC CHECKSUMS: 8 | FXForms: b6a78bac9f6b597ce704e34ac7c1ce9ff628b1d5 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /RZDebugMenu/RZDebugMenu-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // RZDebugMenu-Prefix.pch 3 | // RZDebugMenu 4 | // 5 | // Created by Michael Gorbach on 2/17/15. 6 | // Copyright (c) 2015 Raizlabs. All rights reserved. 7 | // 8 | 9 | #ifndef RZDebugMenu_RZDebugMenu_Prefix_pch 10 | #define RZDebugMenu_RZDebugMenu_Prefix_pch 11 | 12 | #ifdef __OBJC__ 13 | #import 14 | #import 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /RZDebugMenu/RZDebugMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 346B7BB88365D4A7B8D60DD7 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45B80888602266897DB3CC72 /* libPods.a */; }; 11 | D42787971AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = D42787961AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.m */; }; 12 | D43C89601A93E11E0057AF66 /* libRZDebugMenu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D43C89551A93E11E0057AF66 /* libRZDebugMenu.a */; }; 13 | D43C89931A93E24B0057AF66 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D43C89921A93E24B0057AF66 /* Foundation.framework */; }; 14 | D43C89951A93E24E0057AF66 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D43C89941A93E24E0057AF66 /* UIKit.framework */; }; 15 | D43C89A71A94FDBA0057AF66 /* RZDebugMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = D43C89A61A94FDBA0057AF66 /* RZDebugMenu.m */; }; 16 | D43C89C41A94FDF10057AF66 /* RZDebugMenuSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = D43C89C11A94FDF10057AF66 /* RZDebugMenuSettings.m */; }; 17 | D43C89FA1A951B500057AF66 /* RZDebugMenuSettingsParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D43C89F91A951B500057AF66 /* RZDebugMenuSettingsParser.m */; }; 18 | D43C89FD1A951B560057AF66 /* RZDebugMenuSettingsForm.m in Sources */ = {isa = PBXBuildFile; fileRef = D43C89FC1A951B560057AF66 /* RZDebugMenuSettingsForm.m */; }; 19 | D43C8A0B1A9679CE0057AF66 /* RZDebugMenuFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D43C8A091A9679CE0057AF66 /* RZDebugMenuFormViewController.m */; }; 20 | D43D48901A9BE239002B3A55 /* RZDebugMenuSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D488F1A9BE239002B3A55 /* RZDebugMenuSettingsStore.m */; }; 21 | D43D48961A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48951A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.m */; }; 22 | D43D48991A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48981A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.m */; }; 23 | D43D48B21A9CE056002B3A55 /* RZDebugMenuChildPaneItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D489B1A9CE056002B3A55 /* RZDebugMenuChildPaneItem.m */; }; 24 | D43D48B31A9CE056002B3A55 /* RZDebugMenuGroupItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D489D1A9CE056002B3A55 /* RZDebugMenuGroupItem.m */; }; 25 | D43D48B41A9CE056002B3A55 /* RZDebugMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D489F1A9CE056002B3A55 /* RZDebugMenuItem.m */; }; 26 | D43D48B51A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48A11A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.m */; }; 27 | D43D48B61A9CE056002B3A55 /* RZDebugMenuMultiValueItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48A31A9CE056002B3A55 /* RZDebugMenuMultiValueItem.m */; }; 28 | D43D48B71A9CE056002B3A55 /* RZDebugMenuSettingItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48A51A9CE056002B3A55 /* RZDebugMenuSettingItem.m */; }; 29 | D43D48B91A9CE056002B3A55 /* RZDebugMenuSliderItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48A91A9CE056002B3A55 /* RZDebugMenuSliderItem.m */; }; 30 | D43D48BA1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48AB1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.m */; }; 31 | D43D48BB1A9CE056002B3A55 /* RZDebugMenuToggleItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48AD1A9CE056002B3A55 /* RZDebugMenuToggleItem.m */; }; 32 | D43D48BC1A9CE056002B3A55 /* RZDebugMenuVersionItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48AF1A9CE056002B3A55 /* RZDebugMenuVersionItem.m */; }; 33 | D43D48C01A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D43D48BF1A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.m */; }; 34 | D4E340641A9E1DAA006902A2 /* RZDebugMenuTitleItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D4E340631A9E1DAA006902A2 /* RZDebugMenuTitleItem.m */; }; 35 | D4E340671A9E3CAC006902A2 /* RZDebugMenuShortTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = D4E340661A9E3CAC006902A2 /* RZDebugMenuShortTitles.m */; }; 36 | /* End PBXBuildFile section */ 37 | 38 | /* Begin PBXContainerItemProxy section */ 39 | D43C89611A93E11E0057AF66 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = D43C890A1A93DF9E0057AF66 /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = D43C89541A93E11E0057AF66; 44 | remoteInfo = RZDebugMenu; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXCopyFilesBuildPhase section */ 49 | D43C89531A93E11E0057AF66 /* CopyFiles */ = { 50 | isa = PBXCopyFilesBuildPhase; 51 | buildActionMask = 2147483647; 52 | dstPath = "include/$(PRODUCT_NAME)"; 53 | dstSubfolderSpec = 16; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXCopyFilesBuildPhase section */ 59 | 60 | /* Begin PBXFileReference section */ 61 | 05DE3EB7F949B26627EF9421 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 62 | 45B80888602266897DB3CC72 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | CA8145EFE142630B3CDF5152 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 64 | D42787951AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIViewController+RZDebugMenuPresentationAdditions.h"; path = "Classes/UIViewController+RZDebugMenuPresentationAdditions.h"; sourceTree = ""; }; 65 | D42787961AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+RZDebugMenuPresentationAdditions.m"; path = "Classes/UIViewController+RZDebugMenuPresentationAdditions.m"; sourceTree = ""; }; 66 | D43C89551A93E11E0057AF66 /* libRZDebugMenu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRZDebugMenu.a; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | D43C895F1A93E11E0057AF66 /* RZDebugMenuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RZDebugMenuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | D43C89651A93E11E0057AF66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | D43C89921A93E24B0057AF66 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 70 | D43C89941A93E24E0057AF66 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 71 | D43C89971A93E2EE0057AF66 /* RZDebugMenu-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RZDebugMenu-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 72 | D43C89A51A94FDBA0057AF66 /* RZDebugMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenu.h; path = Classes/RZDebugMenu.h; sourceTree = ""; }; 73 | D43C89A61A94FDBA0057AF66 /* RZDebugMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenu.m; path = Classes/RZDebugMenu.m; sourceTree = ""; }; 74 | D43C89A81A94FDC40057AF66 /* RZDebugLogMenuDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RZDebugLogMenuDefines.h; path = Classes/RZDebugLogMenuDefines.h; sourceTree = ""; }; 75 | D43C89C01A94FDF10057AF66 /* RZDebugMenuSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuSettings.h; path = ../Classes/Models/RZDebugMenuSettings.h; sourceTree = ""; }; 76 | D43C89C11A94FDF10057AF66 /* RZDebugMenuSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuSettings.m; path = ../Classes/Models/RZDebugMenuSettings.m; sourceTree = ""; }; 77 | D43C89F81A951B500057AF66 /* RZDebugMenuSettingsParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuSettingsParser.h; path = Classes/RZDebugMenuSettingsParser.h; sourceTree = ""; }; 78 | D43C89F91A951B500057AF66 /* RZDebugMenuSettingsParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuSettingsParser.m; path = Classes/RZDebugMenuSettingsParser.m; sourceTree = ""; }; 79 | D43C89FB1A951B560057AF66 /* RZDebugMenuSettingsForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuSettingsForm.h; sourceTree = ""; }; 80 | D43C89FC1A951B560057AF66 /* RZDebugMenuSettingsForm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuSettingsForm.m; sourceTree = ""; }; 81 | D43C8A081A9679CE0057AF66 /* RZDebugMenuFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuFormViewController.h; path = ../RZDebugMenuFormViewController.h; sourceTree = ""; }; 82 | D43C8A091A9679CE0057AF66 /* RZDebugMenuFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuFormViewController.m; path = ../RZDebugMenuFormViewController.m; sourceTree = ""; }; 83 | D43D488E1A9BE239002B3A55 /* RZDebugMenuSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuSettingsStore.h; path = ../Classes/RZDebugMenuSettingsStore.h; sourceTree = ""; }; 84 | D43D488F1A9BE239002B3A55 /* RZDebugMenuSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuSettingsStore.m; path = ../Classes/RZDebugMenuSettingsStore.m; sourceTree = ""; }; 85 | D43D48941A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuUserDefaultsStore.h; path = ../Classes/RZDebugMenuUserDefaultsStore.h; sourceTree = ""; }; 86 | D43D48951A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuUserDefaultsStore.m; path = ../Classes/RZDebugMenuUserDefaultsStore.m; sourceTree = ""; }; 87 | D43D48971A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuIsolatedUserDefaultsStore.h; path = ../Classes/RZDebugMenuIsolatedUserDefaultsStore.h; sourceTree = ""; }; 88 | D43D48981A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RZDebugMenuIsolatedUserDefaultsStore.m; path = ../Classes/RZDebugMenuIsolatedUserDefaultsStore.m; sourceTree = ""; }; 89 | D43D489A1A9CE056002B3A55 /* RZDebugMenuChildPaneItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuChildPaneItem.h; sourceTree = ""; }; 90 | D43D489B1A9CE056002B3A55 /* RZDebugMenuChildPaneItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuChildPaneItem.m; sourceTree = ""; }; 91 | D43D489C1A9CE056002B3A55 /* RZDebugMenuGroupItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuGroupItem.h; sourceTree = ""; }; 92 | D43D489D1A9CE056002B3A55 /* RZDebugMenuGroupItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuGroupItem.m; sourceTree = ""; }; 93 | D43D489E1A9CE056002B3A55 /* RZDebugMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuItem.h; sourceTree = ""; }; 94 | D43D489F1A9CE056002B3A55 /* RZDebugMenuItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuItem.m; sourceTree = ""; }; 95 | D43D48A01A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuLoadedChildPaneItem.h; sourceTree = ""; }; 96 | D43D48A11A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuLoadedChildPaneItem.m; sourceTree = ""; }; 97 | D43D48A21A9CE056002B3A55 /* RZDebugMenuMultiValueItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuMultiValueItem.h; sourceTree = ""; }; 98 | D43D48A31A9CE056002B3A55 /* RZDebugMenuMultiValueItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuMultiValueItem.m; sourceTree = ""; }; 99 | D43D48A41A9CE056002B3A55 /* RZDebugMenuSettingItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuSettingItem.h; sourceTree = ""; }; 100 | D43D48A51A9CE056002B3A55 /* RZDebugMenuSettingItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuSettingItem.m; sourceTree = ""; }; 101 | D43D48A81A9CE056002B3A55 /* RZDebugMenuSliderItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuSliderItem.h; sourceTree = ""; }; 102 | D43D48A91A9CE056002B3A55 /* RZDebugMenuSliderItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuSliderItem.m; sourceTree = ""; }; 103 | D43D48AA1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuTextFieldItem.h; sourceTree = ""; }; 104 | D43D48AB1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuTextFieldItem.m; sourceTree = ""; }; 105 | D43D48AC1A9CE056002B3A55 /* RZDebugMenuToggleItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuToggleItem.h; sourceTree = ""; }; 106 | D43D48AD1A9CE056002B3A55 /* RZDebugMenuToggleItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuToggleItem.m; sourceTree = ""; }; 107 | D43D48AE1A9CE056002B3A55 /* RZDebugMenuVersionItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuVersionItem.h; sourceTree = ""; }; 108 | D43D48AF1A9CE056002B3A55 /* RZDebugMenuVersionItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuVersionItem.m; sourceTree = ""; }; 109 | D43D48BE1A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuMultiValueSelectionItem.h; sourceTree = ""; }; 110 | D43D48BF1A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuMultiValueSelectionItem.m; sourceTree = ""; }; 111 | D43D48C21A9D04AB002B3A55 /* RZDebugMenuSettings_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RZDebugMenuSettings_Private.h; path = ../Classes/Models/RZDebugMenuSettings_Private.h; sourceTree = ""; }; 112 | D4E340621A9E1DAA006902A2 /* RZDebugMenuTitleItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuTitleItem.h; sourceTree = ""; }; 113 | D4E340631A9E1DAA006902A2 /* RZDebugMenuTitleItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuTitleItem.m; sourceTree = ""; }; 114 | D4E340651A9E3CAC006902A2 /* RZDebugMenuShortTitles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RZDebugMenuShortTitles.h; sourceTree = ""; }; 115 | D4E340661A9E3CAC006902A2 /* RZDebugMenuShortTitles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RZDebugMenuShortTitles.m; sourceTree = ""; }; 116 | /* End PBXFileReference section */ 117 | 118 | /* Begin PBXFrameworksBuildPhase section */ 119 | D43C89521A93E11E0057AF66 /* Frameworks */ = { 120 | isa = PBXFrameworksBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | D43C89951A93E24E0057AF66 /* UIKit.framework in Frameworks */, 124 | D43C89931A93E24B0057AF66 /* Foundation.framework in Frameworks */, 125 | 346B7BB88365D4A7B8D60DD7 /* libPods.a in Frameworks */, 126 | ); 127 | runOnlyForDeploymentPostprocessing = 0; 128 | }; 129 | D43C895C1A93E11E0057AF66 /* Frameworks */ = { 130 | isa = PBXFrameworksBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | D43C89601A93E11E0057AF66 /* libRZDebugMenu.a in Frameworks */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXFrameworksBuildPhase section */ 138 | 139 | /* Begin PBXGroup section */ 140 | 740B81F3A977CCDC1CDF9BF5 /* Pods */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 05DE3EB7F949B26627EF9421 /* Pods.debug.xcconfig */, 144 | CA8145EFE142630B3CDF5152 /* Pods.release.xcconfig */, 145 | ); 146 | name = Pods; 147 | sourceTree = ""; 148 | }; 149 | D42787931AA4CE7700088281 /* Utilities */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | D42787951AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.h */, 153 | D42787961AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.m */, 154 | ); 155 | name = Utilities; 156 | sourceTree = ""; 157 | }; 158 | D43C89091A93DF9E0057AF66 = { 159 | isa = PBXGroup; 160 | children = ( 161 | D43C89561A93E11E0057AF66 /* RZDebugMenu */, 162 | D43C89631A93E11E0057AF66 /* RZDebugMenuTests */, 163 | D43C89961A93E26B0057AF66 /* Frameworks */, 164 | D43C89131A93DF9E0057AF66 /* Products */, 165 | 740B81F3A977CCDC1CDF9BF5 /* Pods */, 166 | ); 167 | sourceTree = ""; 168 | }; 169 | D43C89131A93DF9E0057AF66 /* Products */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | D43C89551A93E11E0057AF66 /* libRZDebugMenu.a */, 173 | D43C895F1A93E11E0057AF66 /* RZDebugMenuTests.xctest */, 174 | ); 175 | name = Products; 176 | sourceTree = ""; 177 | }; 178 | D43C893E1A93E0CB0057AF66 /* Models */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | D43D489A1A9CE056002B3A55 /* RZDebugMenuChildPaneItem.h */, 182 | D43D489B1A9CE056002B3A55 /* RZDebugMenuChildPaneItem.m */, 183 | D43D489C1A9CE056002B3A55 /* RZDebugMenuGroupItem.h */, 184 | D43D489D1A9CE056002B3A55 /* RZDebugMenuGroupItem.m */, 185 | D43D489E1A9CE056002B3A55 /* RZDebugMenuItem.h */, 186 | D43D489F1A9CE056002B3A55 /* RZDebugMenuItem.m */, 187 | D43D48A01A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.h */, 188 | D43D48A11A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.m */, 189 | D43D48A21A9CE056002B3A55 /* RZDebugMenuMultiValueItem.h */, 190 | D43D48A31A9CE056002B3A55 /* RZDebugMenuMultiValueItem.m */, 191 | D43D48A41A9CE056002B3A55 /* RZDebugMenuSettingItem.h */, 192 | D43D48A51A9CE056002B3A55 /* RZDebugMenuSettingItem.m */, 193 | D43D48A81A9CE056002B3A55 /* RZDebugMenuSliderItem.h */, 194 | D43D48A91A9CE056002B3A55 /* RZDebugMenuSliderItem.m */, 195 | D43D48AA1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.h */, 196 | D43D48AB1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.m */, 197 | D43D48AC1A9CE056002B3A55 /* RZDebugMenuToggleItem.h */, 198 | D43D48AD1A9CE056002B3A55 /* RZDebugMenuToggleItem.m */, 199 | D43D48AE1A9CE056002B3A55 /* RZDebugMenuVersionItem.h */, 200 | D43D48AF1A9CE056002B3A55 /* RZDebugMenuVersionItem.m */, 201 | D43D48BE1A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.h */, 202 | D43D48BF1A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.m */, 203 | D4E340621A9E1DAA006902A2 /* RZDebugMenuTitleItem.h */, 204 | D4E340631A9E1DAA006902A2 /* RZDebugMenuTitleItem.m */, 205 | ); 206 | name = Models; 207 | path = Classes/Models; 208 | sourceTree = ""; 209 | }; 210 | D43C89561A93E11E0057AF66 /* RZDebugMenu */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | D43C89971A93E2EE0057AF66 /* RZDebugMenu-Prefix.pch */, 214 | D43C89A81A94FDC40057AF66 /* RZDebugLogMenuDefines.h */, 215 | D43C89A51A94FDBA0057AF66 /* RZDebugMenu.h */, 216 | D43C89A61A94FDBA0057AF66 /* RZDebugMenu.m */, 217 | D43C89F01A94FF230057AF66 /* Settings Parsing */, 218 | D43C89731A93E1490057AF66 /* UX */, 219 | D43C896C1A93E1290057AF66 /* Settings */, 220 | D43C893E1A93E0CB0057AF66 /* Models */, 221 | D42787931AA4CE7700088281 /* Utilities */, 222 | ); 223 | name = RZDebugMenu; 224 | path = ..; 225 | sourceTree = ""; 226 | }; 227 | D43C89631A93E11E0057AF66 /* RZDebugMenuTests */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | D43C89641A93E11E0057AF66 /* Supporting Files */, 231 | ); 232 | path = RZDebugMenuTests; 233 | sourceTree = ""; 234 | }; 235 | D43C89641A93E11E0057AF66 /* Supporting Files */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | D43C89651A93E11E0057AF66 /* Info.plist */, 239 | ); 240 | name = "Supporting Files"; 241 | sourceTree = ""; 242 | }; 243 | D43C896C1A93E1290057AF66 /* Settings */ = { 244 | isa = PBXGroup; 245 | children = ( 246 | D43C89C01A94FDF10057AF66 /* RZDebugMenuSettings.h */, 247 | D43C89C11A94FDF10057AF66 /* RZDebugMenuSettings.m */, 248 | D43D48C21A9D04AB002B3A55 /* RZDebugMenuSettings_Private.h */, 249 | D43D48C11A9D018C002B3A55 /* Stores */, 250 | ); 251 | name = Settings; 252 | path = RZDebugMenu; 253 | sourceTree = ""; 254 | }; 255 | D43C89731A93E1490057AF66 /* UX */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | D43C89F41A95182F0057AF66 /* FXForms Subclasses */, 259 | D43C89871A93E16C0057AF66 /* View Controllers */, 260 | ); 261 | name = UX; 262 | path = Classes/UI; 263 | sourceTree = ""; 264 | }; 265 | D43C89871A93E16C0057AF66 /* View Controllers */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | D43C8A081A9679CE0057AF66 /* RZDebugMenuFormViewController.h */, 269 | D43C8A091A9679CE0057AF66 /* RZDebugMenuFormViewController.m */, 270 | ); 271 | name = "View Controllers"; 272 | sourceTree = ""; 273 | }; 274 | D43C89961A93E26B0057AF66 /* Frameworks */ = { 275 | isa = PBXGroup; 276 | children = ( 277 | D43C89941A93E24E0057AF66 /* UIKit.framework */, 278 | D43C89921A93E24B0057AF66 /* Foundation.framework */, 279 | 45B80888602266897DB3CC72 /* libPods.a */, 280 | ); 281 | name = Frameworks; 282 | path = RZDebugMenu; 283 | sourceTree = ""; 284 | }; 285 | D43C89F01A94FF230057AF66 /* Settings Parsing */ = { 286 | isa = PBXGroup; 287 | children = ( 288 | D43C89F81A951B500057AF66 /* RZDebugMenuSettingsParser.h */, 289 | D43C89F91A951B500057AF66 /* RZDebugMenuSettingsParser.m */, 290 | ); 291 | name = "Settings Parsing"; 292 | sourceTree = ""; 293 | }; 294 | D43C89F41A95182F0057AF66 /* FXForms Subclasses */ = { 295 | isa = PBXGroup; 296 | children = ( 297 | D43C89FB1A951B560057AF66 /* RZDebugMenuSettingsForm.h */, 298 | D43C89FC1A951B560057AF66 /* RZDebugMenuSettingsForm.m */, 299 | D4E340651A9E3CAC006902A2 /* RZDebugMenuShortTitles.h */, 300 | D4E340661A9E3CAC006902A2 /* RZDebugMenuShortTitles.m */, 301 | ); 302 | name = "FXForms Subclasses"; 303 | sourceTree = ""; 304 | }; 305 | D43D48C11A9D018C002B3A55 /* Stores */ = { 306 | isa = PBXGroup; 307 | children = ( 308 | D43D488E1A9BE239002B3A55 /* RZDebugMenuSettingsStore.h */, 309 | D43D488F1A9BE239002B3A55 /* RZDebugMenuSettingsStore.m */, 310 | D43D48941A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.h */, 311 | D43D48951A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.m */, 312 | D43D48971A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.h */, 313 | D43D48981A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.m */, 314 | ); 315 | name = Stores; 316 | sourceTree = ""; 317 | }; 318 | /* End PBXGroup section */ 319 | 320 | /* Begin PBXNativeTarget section */ 321 | D43C89541A93E11E0057AF66 /* RZDebugMenu */ = { 322 | isa = PBXNativeTarget; 323 | buildConfigurationList = D43C89661A93E11E0057AF66 /* Build configuration list for PBXNativeTarget "RZDebugMenu" */; 324 | buildPhases = ( 325 | 58CAA3CF29412D7AED04CFB7 /* Check Pods Manifest.lock */, 326 | D43C89511A93E11E0057AF66 /* Sources */, 327 | D43C89521A93E11E0057AF66 /* Frameworks */, 328 | D43C89531A93E11E0057AF66 /* CopyFiles */, 329 | BC1EC1E2C6901C3A26680258 /* Copy Pods Resources */, 330 | ); 331 | buildRules = ( 332 | ); 333 | dependencies = ( 334 | ); 335 | name = RZDebugMenu; 336 | productName = RZDebugMenu; 337 | productReference = D43C89551A93E11E0057AF66 /* libRZDebugMenu.a */; 338 | productType = "com.apple.product-type.library.static"; 339 | }; 340 | D43C895E1A93E11E0057AF66 /* RZDebugMenuTests */ = { 341 | isa = PBXNativeTarget; 342 | buildConfigurationList = D43C89691A93E11E0057AF66 /* Build configuration list for PBXNativeTarget "RZDebugMenuTests" */; 343 | buildPhases = ( 344 | D43C895B1A93E11E0057AF66 /* Sources */, 345 | D43C895C1A93E11E0057AF66 /* Frameworks */, 346 | D43C895D1A93E11E0057AF66 /* Resources */, 347 | ); 348 | buildRules = ( 349 | ); 350 | dependencies = ( 351 | D43C89621A93E11E0057AF66 /* PBXTargetDependency */, 352 | ); 353 | name = RZDebugMenuTests; 354 | productName = RZDebugMenuTests; 355 | productReference = D43C895F1A93E11E0057AF66 /* RZDebugMenuTests.xctest */; 356 | productType = "com.apple.product-type.bundle.unit-test"; 357 | }; 358 | /* End PBXNativeTarget section */ 359 | 360 | /* Begin PBXProject section */ 361 | D43C890A1A93DF9E0057AF66 /* Project object */ = { 362 | isa = PBXProject; 363 | attributes = { 364 | LastUpgradeCheck = 0610; 365 | ORGANIZATIONNAME = Raizlabs; 366 | TargetAttributes = { 367 | D43C89541A93E11E0057AF66 = { 368 | CreatedOnToolsVersion = 6.1.1; 369 | }; 370 | D43C895E1A93E11E0057AF66 = { 371 | CreatedOnToolsVersion = 6.1.1; 372 | }; 373 | }; 374 | }; 375 | buildConfigurationList = D43C890D1A93DF9E0057AF66 /* Build configuration list for PBXProject "RZDebugMenu" */; 376 | compatibilityVersion = "Xcode 3.2"; 377 | developmentRegion = English; 378 | hasScannedForEncodings = 0; 379 | knownRegions = ( 380 | en, 381 | ); 382 | mainGroup = D43C89091A93DF9E0057AF66; 383 | productRefGroup = D43C89131A93DF9E0057AF66 /* Products */; 384 | projectDirPath = ""; 385 | projectRoot = ""; 386 | targets = ( 387 | D43C89541A93E11E0057AF66 /* RZDebugMenu */, 388 | D43C895E1A93E11E0057AF66 /* RZDebugMenuTests */, 389 | ); 390 | }; 391 | /* End PBXProject section */ 392 | 393 | /* Begin PBXResourcesBuildPhase section */ 394 | D43C895D1A93E11E0057AF66 /* Resources */ = { 395 | isa = PBXResourcesBuildPhase; 396 | buildActionMask = 2147483647; 397 | files = ( 398 | ); 399 | runOnlyForDeploymentPostprocessing = 0; 400 | }; 401 | /* End PBXResourcesBuildPhase section */ 402 | 403 | /* Begin PBXShellScriptBuildPhase section */ 404 | 58CAA3CF29412D7AED04CFB7 /* Check Pods Manifest.lock */ = { 405 | isa = PBXShellScriptBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | ); 409 | inputPaths = ( 410 | ); 411 | name = "Check Pods Manifest.lock"; 412 | outputPaths = ( 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | shellPath = /bin/sh; 416 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 417 | showEnvVarsInLog = 0; 418 | }; 419 | BC1EC1E2C6901C3A26680258 /* Copy Pods Resources */ = { 420 | isa = PBXShellScriptBuildPhase; 421 | buildActionMask = 2147483647; 422 | files = ( 423 | ); 424 | inputPaths = ( 425 | ); 426 | name = "Copy Pods Resources"; 427 | outputPaths = ( 428 | ); 429 | runOnlyForDeploymentPostprocessing = 0; 430 | shellPath = /bin/sh; 431 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 432 | showEnvVarsInLog = 0; 433 | }; 434 | /* End PBXShellScriptBuildPhase section */ 435 | 436 | /* Begin PBXSourcesBuildPhase section */ 437 | D43C89511A93E11E0057AF66 /* Sources */ = { 438 | isa = PBXSourcesBuildPhase; 439 | buildActionMask = 2147483647; 440 | files = ( 441 | D43D48B21A9CE056002B3A55 /* RZDebugMenuChildPaneItem.m in Sources */, 442 | D42787971AA4CEBB00088281 /* UIViewController+RZDebugMenuPresentationAdditions.m in Sources */, 443 | D43C89C41A94FDF10057AF66 /* RZDebugMenuSettings.m in Sources */, 444 | D43D48BB1A9CE056002B3A55 /* RZDebugMenuToggleItem.m in Sources */, 445 | D43D48BA1A9CE056002B3A55 /* RZDebugMenuTextFieldItem.m in Sources */, 446 | D43D48B91A9CE056002B3A55 /* RZDebugMenuSliderItem.m in Sources */, 447 | D43D48991A9CDF02002B3A55 /* RZDebugMenuIsolatedUserDefaultsStore.m in Sources */, 448 | D43C8A0B1A9679CE0057AF66 /* RZDebugMenuFormViewController.m in Sources */, 449 | D43D48B31A9CE056002B3A55 /* RZDebugMenuGroupItem.m in Sources */, 450 | D43D48901A9BE239002B3A55 /* RZDebugMenuSettingsStore.m in Sources */, 451 | D4E340641A9E1DAA006902A2 /* RZDebugMenuTitleItem.m in Sources */, 452 | D43C89A71A94FDBA0057AF66 /* RZDebugMenu.m in Sources */, 453 | D43D48B71A9CE056002B3A55 /* RZDebugMenuSettingItem.m in Sources */, 454 | D4E340671A9E3CAC006902A2 /* RZDebugMenuShortTitles.m in Sources */, 455 | D43D48C01A9CE0D6002B3A55 /* RZDebugMenuMultiValueSelectionItem.m in Sources */, 456 | D43D48B51A9CE056002B3A55 /* RZDebugMenuLoadedChildPaneItem.m in Sources */, 457 | D43D48B41A9CE056002B3A55 /* RZDebugMenuItem.m in Sources */, 458 | D43D48B61A9CE056002B3A55 /* RZDebugMenuMultiValueItem.m in Sources */, 459 | D43C89FD1A951B560057AF66 /* RZDebugMenuSettingsForm.m in Sources */, 460 | D43C89FA1A951B500057AF66 /* RZDebugMenuSettingsParser.m in Sources */, 461 | D43D48961A9BE3F4002B3A55 /* RZDebugMenuUserDefaultsStore.m in Sources */, 462 | D43D48BC1A9CE056002B3A55 /* RZDebugMenuVersionItem.m in Sources */, 463 | ); 464 | runOnlyForDeploymentPostprocessing = 0; 465 | }; 466 | D43C895B1A93E11E0057AF66 /* Sources */ = { 467 | isa = PBXSourcesBuildPhase; 468 | buildActionMask = 2147483647; 469 | files = ( 470 | ); 471 | runOnlyForDeploymentPostprocessing = 0; 472 | }; 473 | /* End PBXSourcesBuildPhase section */ 474 | 475 | /* Begin PBXTargetDependency section */ 476 | D43C89621A93E11E0057AF66 /* PBXTargetDependency */ = { 477 | isa = PBXTargetDependency; 478 | target = D43C89541A93E11E0057AF66 /* RZDebugMenu */; 479 | targetProxy = D43C89611A93E11E0057AF66 /* PBXContainerItemProxy */; 480 | }; 481 | /* End PBXTargetDependency section */ 482 | 483 | /* Begin XCBuildConfiguration section */ 484 | D43C89241A93DF9E0057AF66 /* Debug */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ALWAYS_SEARCH_USER_PATHS = NO; 488 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 489 | CLANG_CXX_LIBRARY = "libc++"; 490 | CLANG_ENABLE_MODULES = YES; 491 | CLANG_ENABLE_OBJC_ARC = YES; 492 | CLANG_WARN_BOOL_CONVERSION = YES; 493 | CLANG_WARN_CONSTANT_CONVERSION = YES; 494 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 495 | CLANG_WARN_EMPTY_BODY = YES; 496 | CLANG_WARN_ENUM_CONVERSION = YES; 497 | CLANG_WARN_INT_CONVERSION = YES; 498 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 499 | CLANG_WARN_UNREACHABLE_CODE = YES; 500 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 501 | COPY_PHASE_STRIP = NO; 502 | ENABLE_STRICT_OBJC_MSGSEND = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_DYNAMIC_NO_PIC = NO; 505 | GCC_OPTIMIZATION_LEVEL = 0; 506 | GCC_PREPROCESSOR_DEFINITIONS = ( 507 | "DEBUG=1", 508 | "$(inherited)", 509 | ); 510 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 511 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 512 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 513 | GCC_WARN_UNDECLARED_SELECTOR = YES; 514 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 515 | GCC_WARN_UNUSED_FUNCTION = YES; 516 | GCC_WARN_UNUSED_VARIABLE = YES; 517 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 518 | MTL_ENABLE_DEBUG_INFO = YES; 519 | ONLY_ACTIVE_ARCH = YES; 520 | SDKROOT = iphoneos; 521 | }; 522 | name = Debug; 523 | }; 524 | D43C89251A93DF9E0057AF66 /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | ALWAYS_SEARCH_USER_PATHS = NO; 528 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 529 | CLANG_CXX_LIBRARY = "libc++"; 530 | CLANG_ENABLE_MODULES = YES; 531 | CLANG_ENABLE_OBJC_ARC = YES; 532 | CLANG_WARN_BOOL_CONVERSION = YES; 533 | CLANG_WARN_CONSTANT_CONVERSION = YES; 534 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 535 | CLANG_WARN_EMPTY_BODY = YES; 536 | CLANG_WARN_ENUM_CONVERSION = YES; 537 | CLANG_WARN_INT_CONVERSION = YES; 538 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 539 | CLANG_WARN_UNREACHABLE_CODE = YES; 540 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 541 | COPY_PHASE_STRIP = YES; 542 | ENABLE_NS_ASSERTIONS = NO; 543 | ENABLE_STRICT_OBJC_MSGSEND = YES; 544 | GCC_C_LANGUAGE_STANDARD = gnu99; 545 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 546 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 547 | GCC_WARN_UNDECLARED_SELECTOR = YES; 548 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 549 | GCC_WARN_UNUSED_FUNCTION = YES; 550 | GCC_WARN_UNUSED_VARIABLE = YES; 551 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 552 | MTL_ENABLE_DEBUG_INFO = NO; 553 | SDKROOT = iphoneos; 554 | VALIDATE_PRODUCT = YES; 555 | }; 556 | name = Release; 557 | }; 558 | D43C89671A93E11E0057AF66 /* Debug */ = { 559 | isa = XCBuildConfiguration; 560 | baseConfigurationReference = 05DE3EB7F949B26627EF9421 /* Pods.debug.xcconfig */; 561 | buildSettings = { 562 | GCC_PREFIX_HEADER = "RZDebugMenu-Prefix.pch"; 563 | GCC_PREPROCESSOR_DEFINITIONS = ( 564 | "DEBUG=1", 565 | "$(inherited)", 566 | ); 567 | OTHER_LDFLAGS = "-ObjC"; 568 | PRODUCT_NAME = "$(TARGET_NAME)"; 569 | SKIP_INSTALL = YES; 570 | }; 571 | name = Debug; 572 | }; 573 | D43C89681A93E11E0057AF66 /* Release */ = { 574 | isa = XCBuildConfiguration; 575 | baseConfigurationReference = CA8145EFE142630B3CDF5152 /* Pods.release.xcconfig */; 576 | buildSettings = { 577 | GCC_PREFIX_HEADER = "RZDebugMenu-Prefix.pch"; 578 | OTHER_LDFLAGS = "-ObjC"; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | SKIP_INSTALL = YES; 581 | }; 582 | name = Release; 583 | }; 584 | D43C896A1A93E11E0057AF66 /* Debug */ = { 585 | isa = XCBuildConfiguration; 586 | buildSettings = { 587 | CODE_SIGN_IDENTITY = "iPhone Developer"; 588 | FRAMEWORK_SEARCH_PATHS = ( 589 | "$(SDKROOT)/Developer/Library/Frameworks", 590 | "$(inherited)", 591 | ); 592 | GCC_PREPROCESSOR_DEFINITIONS = ( 593 | "DEBUG=1", 594 | "$(inherited)", 595 | ); 596 | INFOPLIST_FILE = RZDebugMenuTests/Info.plist; 597 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 598 | PRODUCT_NAME = "$(TARGET_NAME)"; 599 | }; 600 | name = Debug; 601 | }; 602 | D43C896B1A93E11E0057AF66 /* Release */ = { 603 | isa = XCBuildConfiguration; 604 | buildSettings = { 605 | CODE_SIGN_IDENTITY = "iPhone Developer"; 606 | FRAMEWORK_SEARCH_PATHS = ( 607 | "$(SDKROOT)/Developer/Library/Frameworks", 608 | "$(inherited)", 609 | ); 610 | INFOPLIST_FILE = RZDebugMenuTests/Info.plist; 611 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 612 | PRODUCT_NAME = "$(TARGET_NAME)"; 613 | }; 614 | name = Release; 615 | }; 616 | /* End XCBuildConfiguration section */ 617 | 618 | /* Begin XCConfigurationList section */ 619 | D43C890D1A93DF9E0057AF66 /* Build configuration list for PBXProject "RZDebugMenu" */ = { 620 | isa = XCConfigurationList; 621 | buildConfigurations = ( 622 | D43C89241A93DF9E0057AF66 /* Debug */, 623 | D43C89251A93DF9E0057AF66 /* Release */, 624 | ); 625 | defaultConfigurationIsVisible = 0; 626 | defaultConfigurationName = Release; 627 | }; 628 | D43C89661A93E11E0057AF66 /* Build configuration list for PBXNativeTarget "RZDebugMenu" */ = { 629 | isa = XCConfigurationList; 630 | buildConfigurations = ( 631 | D43C89671A93E11E0057AF66 /* Debug */, 632 | D43C89681A93E11E0057AF66 /* Release */, 633 | ); 634 | defaultConfigurationIsVisible = 0; 635 | defaultConfigurationName = Release; 636 | }; 637 | D43C89691A93E11E0057AF66 /* Build configuration list for PBXNativeTarget "RZDebugMenuTests" */ = { 638 | isa = XCConfigurationList; 639 | buildConfigurations = ( 640 | D43C896A1A93E11E0057AF66 /* Debug */, 641 | D43C896B1A93E11E0057AF66 /* Release */, 642 | ); 643 | defaultConfigurationIsVisible = 0; 644 | defaultConfigurationName = Release; 645 | }; 646 | /* End XCConfigurationList section */ 647 | }; 648 | rootObject = D43C890A1A93DF9E0057AF66 /* Project object */; 649 | } 650 | -------------------------------------------------------------------------------- /RZDebugMenu/RZDebugMenu.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RZDebugMenu/RZDebugMenuTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.raizlabs.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | PROJ_PATH="Demo/RZDebugMenuDemo.xcodeproj" 2 | WORKSPACE_PATH="Demo/RZDebugMenuDemo.xcworkspace" 3 | BUILD_SCHEME="RZDebugMenuDemo" 4 | 5 | namespace :install do 6 | task :tools do 7 | # don't care if this fails on travis 8 | sh("brew update") rescue nil 9 | sh("brew upgrade xctool") rescue nil 10 | sh("gem install cocoapods --no-rdoc --no-ri --no-document --quiet") rescue nil 11 | end 12 | 13 | task :pods do 14 | sh("cd Demo && pod install") 15 | end 16 | end 17 | 18 | task :install do 19 | Rake::Task['install:tools'].invoke 20 | Rake::Task['install:pods'].invoke 21 | end 22 | 23 | 24 | # 25 | # Build 26 | # 27 | 28 | task :build do 29 | sh("xctool -workspace '#{WORKSPACE_PATH}' -scheme '#{BUILD_SCHEME}' -sdk iphonesimulator clean build") rescue nil 30 | end 31 | 32 | # 33 | # Clean 34 | # 35 | 36 | namespace :clean do 37 | task :pods do 38 | sh("rm -f Demo/Podfile.lock") 39 | sh "rm -rf Demo/Pods" 40 | sh("rm -rf Demo/*.xcworkspace") 41 | end 42 | 43 | task :demo do 44 | sh("xctool -project '#{PROJ_PATH}' -scheme '#{TEST_SCHEME}' -sdk iphonesimulator clean") rescue nil 45 | end 46 | end 47 | 48 | task :clean do 49 | Rake::Task['clean:pods'].invoke 50 | Rake::Task['clean:demo'].invoke 51 | end 52 | 53 | # 54 | # Utils 55 | # 56 | 57 | task :usage do 58 | puts "Usage:" 59 | puts " rake install -- install all dependencies (xctool, cocoapods)" 60 | puts " rake install:pods -- install cocoapods for tests/demo" 61 | puts " rake install:tools -- install build tool dependencies" 62 | puts " rake clean -- clean everything" 63 | puts " rake clean:demo -- clean the demo project build artifacts" 64 | puts " rake clean:pods -- clean up cocoapods artifacts" 65 | puts " rake sync -- synchronize project/directory hierarchy (dev only)" 66 | puts " rake usage -- print this message" 67 | end 68 | 69 | task :sync do 70 | sync_project(PROJ_PATH, '--exclusion /Classes') 71 | end 72 | 73 | # 74 | # Default 75 | # 76 | 77 | task :default => 'usage' 78 | 79 | # 80 | # Private 81 | # 82 | 83 | private 84 | 85 | def sync_project(path, flags) 86 | sh("synx #{flags} '#{path}'") 87 | end 88 | --------------------------------------------------------------------------------